Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
11 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: ProfileUtil.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // Class to handle profile loading and unloading without a token.
  7. //
  8. // History: 2000-06-21 vtan created
  9. // --------------------------------------------------------------------------
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <sddl.h>
  15. #include <lmaccess.h>
  16. #include <lmapibuf.h>
  17. #include <dsgetdc.h>
  18. #include "ProfileUtil.h"
  19. #include "TokenUtil.h"
  20. #define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
  21. #define TBOOL(x) (BOOL)(x)
  22. #define TW32(x) (DWORD)(x)
  23. // --------------------------------------------------------------------------
  24. // CUserProfile::s_szUserHiveFilename
  25. //
  26. // Purpose: Default user hive name.
  27. //
  28. // History: 2000-06-21 vtan created
  29. // --------------------------------------------------------------------------
  30. const TCHAR CUserProfile::s_szUserHiveFilename[] = TEXT("ntuser.dat");
  31. // --------------------------------------------------------------------------
  32. // CUserProfile::CUserProfile
  33. //
  34. // Arguments: pszUsername = User name of profile to load.
  35. // pszDomain = Domain for the user.
  36. //
  37. // Returns: <none>
  38. //
  39. // Purpose: Opens a handle to the given user's hive. If the hive isn't
  40. // loaded then the hive is loaded and a handle opened.
  41. //
  42. // History: 2000-06-21 vtan created
  43. // --------------------------------------------------------------------------
  44. CUserProfile::CUserProfile (const TCHAR *pszUsername, const TCHAR *pszDomain) :
  45. _hKeyProfile(NULL),
  46. _pszSID(NULL),
  47. _fLoaded(false)
  48. {
  49. // Validate parameter.
  50. if (!IsBadStringPtr(pszUsername, static_cast<UINT_PTR>(-1)))
  51. {
  52. PSID pSID;
  53. // Convert the username to a SID.
  54. pSID = UsernameToSID(pszUsername, pszDomain);
  55. if (pSID != NULL)
  56. {
  57. // Convert the SID to a string.
  58. if (ConvertSidToStringSid(pSID, &_pszSID) != FALSE)
  59. {
  60. // Attempt to open the user's hive.
  61. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_USERS,
  62. _pszSID,
  63. 0,
  64. KEY_ALL_ACCESS,
  65. &_hKeyProfile))
  66. {
  67. TCHAR szProfilePath[MAX_PATH];
  68. // If that failed then convert the string to a profile path.
  69. if (SIDStringToProfilePath(_pszSID, szProfilePath))
  70. {
  71. // Prevent buffer overrun.
  72. if ((lstrlen(szProfilePath) + sizeof('\\') + ARRAYSIZE(s_szUserHiveFilename)) < ARRAYSIZE(szProfilePath))
  73. {
  74. CPrivilegeEnable privilege(SE_RESTORE_NAME);
  75. // Enable SE_RESTORE_PRIVILEGE and create the
  76. // path to the user hive. Then load the hive.
  77. lstrcat(szProfilePath, TEXT("\\"));
  78. lstrcat(szProfilePath, s_szUserHiveFilename);
  79. if (ERROR_SUCCESS == RegLoadKey(HKEY_USERS, _pszSID, szProfilePath))
  80. {
  81. // Mark the hive as loaded and open the handle.
  82. _fLoaded = true;
  83. TW32(RegOpenKeyEx(HKEY_USERS,
  84. _pszSID,
  85. 0,
  86. KEY_ALL_ACCESS,
  87. &_hKeyProfile));
  88. }
  89. }
  90. }
  91. }
  92. }
  93. (HLOCAL)LocalFree(pSID);
  94. }
  95. }
  96. }
  97. // --------------------------------------------------------------------------
  98. // CUserProfile::~CUserProfile
  99. //
  100. // Arguments: <none>
  101. //
  102. // Returns: <none>
  103. //
  104. // Purpose: Releases resources used by this object.
  105. //
  106. // History: 2000-06-21 vtan created
  107. // --------------------------------------------------------------------------
  108. CUserProfile::~CUserProfile (void)
  109. {
  110. if (_hKeyProfile != NULL)
  111. {
  112. TBOOL(RegCloseKey(_hKeyProfile));
  113. }
  114. if (_fLoaded)
  115. {
  116. CPrivilegeEnable privilege(SE_RESTORE_NAME);
  117. TW32(RegUnLoadKey(HKEY_USERS, _pszSID));
  118. _fLoaded = false;
  119. }
  120. if (_pszSID != NULL)
  121. {
  122. (HLOCAL)LocalFree(_pszSID);
  123. _pszSID = NULL;
  124. }
  125. }
  126. // --------------------------------------------------------------------------
  127. // CUserProfile::operator HKEY
  128. //
  129. // Arguments: <none>
  130. //
  131. // Returns: HKEY
  132. //
  133. // Purpose: Returns the HKEY to the user's hive.
  134. //
  135. // History: 2000-06-21 vtan created
  136. // --------------------------------------------------------------------------
  137. CUserProfile::operator HKEY (void) const
  138. {
  139. return(_hKeyProfile);
  140. }
  141. // --------------------------------------------------------------------------
  142. // CUserProfile::UsernameToSID
  143. //
  144. // Arguments: pszUsername = User name to convert.
  145. // pszDomain = Domain for the user.
  146. //
  147. // Returns: PSID
  148. //
  149. // Purpose: Uses the security accounts manager to look up the account by
  150. // name and return the SID.
  151. //
  152. // History: 2000-06-21 vtan created
  153. // --------------------------------------------------------------------------
  154. PSID CUserProfile::UsernameToSID (const TCHAR *pszUsername, const TCHAR *pszDomain)
  155. {
  156. DWORD dwSIDSize, dwComputerNameSize, dwReferencedDomainSize;
  157. SID_NAME_USE eSIDUse;
  158. PSID pSID, pSIDResult;
  159. WCHAR *pszDomainControllerName;
  160. DOMAIN_CONTROLLER_INFO *pDCI;
  161. TCHAR szComputerName[CNLEN + sizeof('\0')];
  162. pSIDResult = NULL;
  163. dwComputerNameSize = ARRAYSIZE(szComputerName);
  164. if (GetComputerName(szComputerName, &dwComputerNameSize) == FALSE)
  165. {
  166. szComputerName[0] = TEXT('\0');
  167. }
  168. if ((pszDomain != NULL) &&
  169. (lstrcmpi(szComputerName, pszDomain) != 0) &&
  170. (ERROR_SUCCESS == DsGetDcName(NULL,
  171. pszDomain,
  172. NULL,
  173. NULL,
  174. 0,
  175. &pDCI)))
  176. {
  177. pszDomainControllerName = pDCI->DomainControllerName;
  178. }
  179. else
  180. {
  181. pDCI = NULL;
  182. pszDomainControllerName = NULL;
  183. }
  184. dwSIDSize = dwReferencedDomainSize = 0;
  185. (BOOL)LookupAccountName(pszDomainControllerName,
  186. pszUsername,
  187. NULL,
  188. &dwSIDSize,
  189. NULL,
  190. &dwReferencedDomainSize,
  191. &eSIDUse);
  192. pSID = LocalAlloc(LMEM_FIXED, dwSIDSize);
  193. if (pSID != NULL)
  194. {
  195. TCHAR *pszReferencedDomain;
  196. pszReferencedDomain = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, dwReferencedDomainSize * sizeof(TCHAR)));
  197. if (pszReferencedDomain != NULL)
  198. {
  199. if (LookupAccountName(pszDomainControllerName,
  200. pszUsername,
  201. pSID,
  202. &dwSIDSize,
  203. pszReferencedDomain,
  204. &dwReferencedDomainSize,
  205. &eSIDUse) != FALSE)
  206. {
  207. if (SidTypeUser == eSIDUse)
  208. {
  209. // If the account was successfully looked up and the
  210. // account type is a user then return the result back
  211. // to the caller and ensure that it's not released here.
  212. pSIDResult = pSID;
  213. pSID = NULL;
  214. }
  215. }
  216. (HLOCAL)LocalFree(pszReferencedDomain);
  217. }
  218. if (pSID != NULL)
  219. {
  220. (HLOCAL)LocalFree(pSID);
  221. }
  222. }
  223. if (pDCI != NULL)
  224. {
  225. (NET_API_STATUS)NetApiBufferFree(pDCI);
  226. }
  227. return(pSIDResult);
  228. }
  229. // --------------------------------------------------------------------------
  230. // CUserProfile::SIDStringToProfilePath
  231. //
  232. // Arguments: pszSIDString = SID string to look up.
  233. // pszProfilePath = Returned path to the profile.
  234. //
  235. // Returns: bool
  236. //
  237. // Purpose: Looks up the profile path for the given SID string in the
  238. // location where userenv stores it. This doesn't change
  239. // although no API exists for this information.
  240. //
  241. // History: 2000-06-21 vtan created
  242. // --------------------------------------------------------------------------
  243. bool CUserProfile::SIDStringToProfilePath (const TCHAR *pszSIDString, TCHAR *pszProfilePath)
  244. {
  245. bool fResult;
  246. fResult = false;
  247. if (!IsBadStringPtr(pszSIDString, static_cast<UINT_PTR>(-1)) && !IsBadWritePtr(pszProfilePath, MAX_PATH * sizeof(TCHAR)))
  248. {
  249. HKEY hKeyProfileList;
  250. pszProfilePath[0] = TEXT('\0');
  251. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  252. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"),
  253. 0,
  254. KEY_QUERY_VALUE,
  255. &hKeyProfileList))
  256. {
  257. HKEY hKeySID;
  258. if (ERROR_SUCCESS == RegOpenKeyEx(hKeyProfileList,
  259. pszSIDString,
  260. 0,
  261. KEY_QUERY_VALUE,
  262. &hKeySID))
  263. {
  264. DWORD dwType, dwProfilePathSize;
  265. TCHAR szProfilePath[MAX_PATH];
  266. dwProfilePathSize = ARRAYSIZE(szProfilePath);
  267. if (ERROR_SUCCESS == RegQueryValueEx(hKeySID,
  268. TEXT("ProfileImagePath"),
  269. NULL,
  270. &dwType,
  271. reinterpret_cast<LPBYTE>(szProfilePath),
  272. &dwProfilePathSize))
  273. {
  274. if (REG_EXPAND_SZ == dwType)
  275. {
  276. fResult = true;
  277. if (ExpandEnvironmentStrings(szProfilePath, pszProfilePath, MAX_PATH) == 0)
  278. {
  279. dwType = REG_SZ;
  280. }
  281. }
  282. if (REG_SZ == dwType)
  283. {
  284. fResult = true;
  285. (TCHAR*)lstrcpy(pszProfilePath, szProfilePath);
  286. }
  287. }
  288. TW32(RegCloseKey(hKeySID));
  289. }
  290. TW32(RegCloseKey(hKeyProfileList));
  291. }
  292. }
  293. return(fResult);
  294. }