summaryrefslogtreecommitdiffstats
path: root/toolkit/components/startup/nsUserInfoWin.cpp
blob: b27a2c483b1c8a9cda74e3295724b53284d9e8c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsUserInfo.h"

#include "mozilla/ArrayUtils.h" // ArrayLength
#include "nsString.h"
#include "windows.h"
#include "nsCRT.h"
#include "nsXPIDLString.h"

#define SECURITY_WIN32
#include "lm.h"
#include "security.h"

nsUserInfo::nsUserInfo()
{
}

nsUserInfo::~nsUserInfo()
{
}

NS_IMPL_ISUPPORTS(nsUserInfo, nsIUserInfo)

NS_IMETHODIMP
nsUserInfo::GetUsername(char **aUsername)
{
  NS_ENSURE_ARG_POINTER(aUsername);
  *aUsername = nullptr;

  // ULEN is the max username length as defined in lmcons.h
  wchar_t username[UNLEN +1];
  DWORD size = mozilla::ArrayLength(username);
  if (!GetUserNameW(username, &size))
    return NS_ERROR_FAILURE;

  *aUsername = ToNewUTF8String(nsDependentString(username));
  return (*aUsername) ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsUserInfo::GetFullname(char16_t **aFullname)
{
  NS_ENSURE_ARG_POINTER(aFullname);
  *aFullname = nullptr;

  wchar_t fullName[512];
  DWORD size = mozilla::ArrayLength(fullName);

  if (GetUserNameExW(NameDisplay, fullName, &size)) {
    *aFullname = ToNewUnicode(nsDependentString(fullName));
  } else {
    DWORD getUsernameError = GetLastError();

    // Try to use the net APIs regardless of the error because it may be
    // able to obtain the information.
    wchar_t username[UNLEN + 1];
    size = mozilla::ArrayLength(username);
    if (!GetUserNameW(username, &size)) {
      // ERROR_NONE_MAPPED means the user info is not filled out on this computer
      return getUsernameError == ERROR_NONE_MAPPED ?
             NS_ERROR_NOT_AVAILABLE : NS_ERROR_FAILURE;
    }

    const DWORD level = 2;
    LPBYTE info;
    // If the NetUserGetInfo function has no full name info it will return
    // success with an empty string.
    NET_API_STATUS status = NetUserGetInfo(nullptr, username, level, &info);
    if (status != NERR_Success) {
      // We have an error with NetUserGetInfo but we know the info is not
      // filled in because GetUserNameExW returned ERROR_NONE_MAPPED.
      return getUsernameError == ERROR_NONE_MAPPED ?
             NS_ERROR_NOT_AVAILABLE : NS_ERROR_FAILURE;
    }

    nsDependentString fullName =
      nsDependentString(reinterpret_cast<USER_INFO_2 *>(info)->usri2_full_name);

    // NetUserGetInfo returns an empty string if the full name is not filled out
    if (fullName.Length() == 0) {
      NetApiBufferFree(info);
      return NS_ERROR_NOT_AVAILABLE;
    }

    *aFullname = ToNewUnicode(fullName);
    NetApiBufferFree(info);
  }

  return (*aFullname) ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsUserInfo::GetDomain(char **aDomain)
{
  NS_ENSURE_ARG_POINTER(aDomain);
  *aDomain = nullptr;

  const DWORD level = 100;
  LPBYTE info;
  NET_API_STATUS status = NetWkstaGetInfo(nullptr, level, &info);
  if (status == NERR_Success) {
    *aDomain =
      ToNewUTF8String(nsDependentString(reinterpret_cast<WKSTA_INFO_100 *>(info)->
                                        wki100_langroup));
    NetApiBufferFree(info);
  }

  return (*aDomain) ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsUserInfo::GetEmailAddress(char **aEmailAddress)
{
  NS_ENSURE_ARG_POINTER(aEmailAddress);
  *aEmailAddress = nullptr;

  // RFC3696 says max length of an email address is 254
  wchar_t emailAddress[255];
  DWORD size = mozilla::ArrayLength(emailAddress);

  if (!GetUserNameExW(NameUserPrincipal, emailAddress, &size)) {
    DWORD getUsernameError = GetLastError();
    return getUsernameError == ERROR_NONE_MAPPED ?
           NS_ERROR_NOT_AVAILABLE : NS_ERROR_FAILURE;
  }

  *aEmailAddress = ToNewUTF8String(nsDependentString(emailAddress));
  return (*aEmailAddress) ? NS_OK : NS_ERROR_FAILURE;
}