Leaked source code of windows server 2003
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.

813 lines
22 KiB

  1. //============================================================
  2. //
  3. // UserHive.cpp - Class to load/unload specified user's profile
  4. // hive from registry
  5. //
  6. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  7. //
  8. // 01/03/97 a-jmoon created
  9. //
  10. //============================================================
  11. #include "precomp.h"
  12. #include <assertbreak.h>
  13. #include <cregcls.h>
  14. #include "sid.h"
  15. #include "UserHive.h"
  16. #include <cominit.h>
  17. #include <strsafe.h>
  18. #pragma warning(disable : 4995) // we introduced as including strsafe.h gives error for all unsafe string functions
  19. CThreadBase CUserHive::m_criticalSection;
  20. /*****************************************************************************
  21. *
  22. * FUNCTION : CUserHive::CUserHive
  23. *
  24. * DESCRIPTION : Constructor
  25. *
  26. * INPUTS : none
  27. *
  28. * OUTPUTS : none
  29. *
  30. * RETURNS : nothing
  31. *
  32. * COMMENTS :
  33. *
  34. *****************************************************************************/
  35. CUserHive::CUserHive()
  36. {
  37. OSInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  38. GetVersionEx(&OSInfo) ;
  39. m_pOriginalPriv = NULL;
  40. m_dwSize = NULL;
  41. m_hKey = NULL;
  42. }
  43. /*****************************************************************************
  44. *
  45. * FUNCTION : CUserHive::~CUserHive
  46. *
  47. * DESCRIPTION : Destructor
  48. *
  49. * INPUTS : none
  50. *
  51. * OUTPUTS : none
  52. *
  53. * RETURNS : nothing
  54. *
  55. * COMMENTS :
  56. *
  57. *****************************************************************************/
  58. CUserHive::~CUserHive()
  59. {
  60. #ifdef NTONLY
  61. if (m_pOriginalPriv)
  62. RestorePrivilege();
  63. #endif
  64. // NOTE: The destructor does not unload the key. Nor does doing a load unload
  65. // a previously loaded key;
  66. ASSERT_BREAK(m_hKey == NULL);
  67. if (m_hKey != NULL)
  68. {
  69. RegCloseKey(m_hKey);
  70. }
  71. }
  72. /*****************************************************************************
  73. *
  74. * FUNCTION : CUserHive::AcquirePrivilege
  75. *
  76. * DESCRIPTION : Acquires SeRestorePrivilege for calling thread
  77. *
  78. * INPUTS : none
  79. *
  80. * OUTPUTS : none
  81. *
  82. * RETURNS : nothing
  83. *
  84. * COMMENTS :
  85. *
  86. *****************************************************************************/
  87. #ifdef NTONLY
  88. DWORD CUserHive::AcquirePrivilege()
  89. {
  90. // are you calling in twice? Shouldn't.
  91. // at worst, it would cause a leak, so I'm going with it anyway.
  92. ASSERT_BREAK(m_pOriginalPriv == NULL);
  93. BOOL bRetCode = FALSE;
  94. SmartCloseHandle hToken;
  95. TOKEN_PRIVILEGES TPriv ;
  96. LUID LUID ;
  97. // Validate the platform
  98. //======================
  99. // Try getting the thread token.
  100. if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
  101. TOKEN_QUERY, FALSE, &hToken))
  102. {
  103. GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &m_dwSize);
  104. if (m_dwSize > 0)
  105. {
  106. // This is cleaned in the destructor, so no try/catch required
  107. m_pOriginalPriv = (TOKEN_PRIVILEGES*) new BYTE[m_dwSize];
  108. if (m_pOriginalPriv == NULL)
  109. {
  110. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  111. }
  112. }
  113. if (m_pOriginalPriv && GetTokenInformation(hToken, TokenPrivileges, m_pOriginalPriv, m_dwSize, &m_dwSize))
  114. {
  115. bRetCode = LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &LUID) ;
  116. if(bRetCode)
  117. {
  118. TPriv.PrivilegeCount = 1 ;
  119. TPriv.Privileges[0].Luid = LUID ;
  120. TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
  121. bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL) ;
  122. }
  123. bRetCode = LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &LUID) ;
  124. if(bRetCode)
  125. {
  126. TPriv.PrivilegeCount = 1 ;
  127. TPriv.Privileges[0].Luid = LUID ;
  128. TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
  129. bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL) ;
  130. }
  131. }
  132. }
  133. if(!bRetCode)
  134. {
  135. return GetLastError() ;
  136. }
  137. return ERROR_SUCCESS ;
  138. }
  139. #endif
  140. /*****************************************************************************
  141. *
  142. * FUNCTION : CUserHive::RestorePrivilege
  143. *
  144. * DESCRIPTION : Restores original status of SeRestorePrivilege
  145. *
  146. * INPUTS : none
  147. *
  148. * OUTPUTS : none
  149. *
  150. * RETURNS : nothing
  151. *
  152. * COMMENTS :
  153. *
  154. *****************************************************************************/
  155. #ifdef NTONLY
  156. void CUserHive::RestorePrivilege()
  157. {
  158. ASSERT_BREAK(m_pOriginalPriv != NULL);
  159. if (m_pOriginalPriv != NULL)
  160. {
  161. SmartCloseHandle hToken;
  162. try
  163. {
  164. if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hToken))
  165. {
  166. AdjustTokenPrivileges(hToken, FALSE, m_pOriginalPriv, m_dwSize, NULL, NULL);
  167. }
  168. }
  169. catch ( ... )
  170. {
  171. delete m_pOriginalPriv;
  172. m_pOriginalPriv = NULL;
  173. m_dwSize = 0;
  174. throw;
  175. }
  176. delete m_pOriginalPriv;
  177. m_pOriginalPriv = NULL;
  178. m_dwSize = 0;
  179. }
  180. }
  181. #endif
  182. DWORD CUserHive::Load(LPCWSTR pszUserName, LPWSTR pszKeyName, size_t PATHSIZE)
  183. {
  184. // NOTE: The destructor does not unload the key. Nor does doing a load unload
  185. // a previously loaded key;
  186. ASSERT_BREAK(m_hKey == NULL);
  187. #ifdef NTONLY
  188. return LoadNT(pszUserName, pszKeyName, PATHSIZE);
  189. #endif
  190. #ifdef WIN9XONLY
  191. return Load95(pszUserName, pszKeyName);
  192. #endif
  193. }
  194. /*****************************************************************************
  195. *
  196. * FUNCTION : CUserHive::LoadNT
  197. *
  198. * DESCRIPTION : Locates user's hive & loads into registry if not already
  199. * present
  200. *
  201. * INPUTS : none
  202. *
  203. * OUTPUTS : pszKeyName receives the expanded SID of the user's
  204. * registry key under HKEY_USERS
  205. *
  206. * RETURNS : nothing
  207. *
  208. * COMMENTS : Hive will remain in registry unless unloaded
  209. *
  210. *****************************************************************************/
  211. #ifdef NTONLY
  212. DWORD CUserHive::LoadNT(LPCTSTR pszUserName, LPTSTR pszKeyName, size_t PATHSIZE)
  213. {
  214. DWORD i, dwSIDSize, dwRetCode, dwDomainNameSize, dwSubAuthorities ;
  215. TCHAR szDomainName[_MAX_PATH], szSID[_MAX_PATH], szTemp[_MAX_PATH] ;
  216. PSID pSID = NULL ;
  217. PSID_IDENTIFIER_AUTHORITY pSIA ;
  218. SID_NAME_USE AccountType ;
  219. CHString sTemp ;
  220. CRegistry Reg ;
  221. // Set the necessary privs
  222. //========================
  223. dwRetCode = AcquirePrivilege() ;
  224. if(dwRetCode != ERROR_SUCCESS)
  225. {
  226. return dwRetCode ;
  227. }
  228. // Look up the user's account info
  229. //================================
  230. dwSIDSize = 0L ;
  231. dwDomainNameSize = sizeof(szDomainName) ;
  232. BOOL bLookup = FALSE;
  233. {
  234. bLookup = LookupAccountName(NULL, pszUserName, pSID, &dwSIDSize, szDomainName, &dwDomainNameSize, &AccountType);
  235. ASSERT_BREAK ( bLookup == FALSE );
  236. if ( ERROR_INSUFFICIENT_BUFFER == ::GetLastError () )
  237. {
  238. pSID = (PSID) malloc( dwSIDSize );
  239. if ( NULL != pSID )
  240. {
  241. bLookup = LookupAccountName(NULL, pszUserName, pSID, &dwSIDSize, szDomainName, &dwDomainNameSize, &AccountType);
  242. }
  243. else
  244. {
  245. RestorePrivilege() ;
  246. return ERROR_NOT_ENOUGH_MEMORY ;
  247. }
  248. }
  249. }
  250. if(!bLookup)
  251. {
  252. if ( pSID )
  253. {
  254. free ( pSID ) ;
  255. pSID = NULL ;
  256. }
  257. RestorePrivilege() ;
  258. return ERROR_BAD_USERNAME ;
  259. }
  260. // Translate the SID into text (a la PSS article Q131320)
  261. //=======================================================
  262. pSIA = GetSidIdentifierAuthority(pSID) ;
  263. dwSubAuthorities = *GetSidSubAuthorityCount(pSID) ;
  264. dwSIDSize = _stprintf(szSID, _T("S-%lu-"), (DWORD) SID_REVISION) ;
  265. if((pSIA->Value[0] != 0) || (pSIA->Value[1] != 0) )
  266. {
  267. dwSIDSize += _stprintf(szSID + _tcslen(szSID), _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
  268. (USHORT) pSIA->Value[0],
  269. (USHORT) pSIA->Value[1],
  270. (USHORT) pSIA->Value[2],
  271. (USHORT) pSIA->Value[3],
  272. (USHORT) pSIA->Value[4],
  273. (USHORT) pSIA->Value[5]) ;
  274. }
  275. else
  276. {
  277. dwSIDSize += _stprintf(szSID + _tcslen(szSID), _T("%lu"),
  278. (ULONG)(pSIA->Value[5] ) +
  279. (ULONG)(pSIA->Value[4] << 8) +
  280. (ULONG)(pSIA->Value[3] << 16) +
  281. (ULONG)(pSIA->Value[2] << 24));
  282. }
  283. for(i = 0 ; i < dwSubAuthorities ; i++)
  284. {
  285. dwSIDSize += _stprintf(szSID + dwSIDSize, _T("-%lu"),
  286. *GetSidSubAuthority(pSID, i)) ;
  287. }
  288. free ( pSID ) ;
  289. pSID = NULL ;
  290. // See if the key already exists
  291. //==============================
  292. dwRetCode = Reg.Open(HKEY_USERS, szSID, KEY_READ) ;
  293. // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
  294. // Reg.Close();
  295. if(dwRetCode != ERROR_SUCCESS)
  296. {
  297. // Try to locate user's registry hive
  298. //===================================
  299. _stprintf(szTemp, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s"), szSID) ;
  300. dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
  301. if(dwRetCode == ERROR_SUCCESS)
  302. {
  303. dwRetCode = Reg.GetCurrentKeyValue(_T("ProfileImagePath"), sTemp) ;
  304. Reg.Close() ;
  305. if(dwRetCode == ERROR_SUCCESS)
  306. {
  307. // NT 4 doesn't include the file name in the registry
  308. //===================================================
  309. if(OSInfo.dwMajorVersion >= 4)
  310. {
  311. sTemp += _T("\\NTUSER.DAT") ;
  312. }
  313. ExpandEnvironmentStrings(LPCTSTR(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
  314. // Try it three times, another process may have the file open
  315. bool bTryTryAgain = false;
  316. int nTries = 0;
  317. do
  318. {
  319. // need to serialize access, using "write" because RegLoadKey wants exclusive access
  320. // even though it is a read operation
  321. m_criticalSection.BeginWrite();
  322. try
  323. {
  324. dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, szSID, szTemp) ;
  325. }
  326. catch ( ... )
  327. {
  328. m_criticalSection.EndWrite();
  329. throw;
  330. }
  331. m_criticalSection.EndWrite();
  332. if ((dwRetCode == ERROR_SHARING_VIOLATION)
  333. && (++nTries < 11))
  334. {
  335. Sleep(20 * nTries);
  336. bTryTryAgain = true;
  337. }
  338. else
  339. {
  340. bTryTryAgain = false;
  341. }
  342. } while (bTryTryAgain);
  343. // if we still can't get in, tell somebody.
  344. if (dwRetCode == ERROR_SHARING_VIOLATION)
  345. LogErrorMessage(_T("Sharing violation on NTUSER.DAT (Load)"));
  346. }
  347. }
  348. }
  349. if(dwRetCode == ERROR_SUCCESS)
  350. {
  351. HRESULT hr = StringCchCopy(pszKeyName, PATHSIZE, szSID) ;
  352. ASSERT_BREAK(SUCCEEDED(hr));
  353. LONG lRetVal;
  354. CHString sKey(szSID);
  355. sKey += _T("\\Software");
  356. lRetVal = RegOpenKeyEx(HKEY_USERS, sKey, 0, KEY_QUERY_VALUE, &m_hKey);
  357. ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
  358. }
  359. // Restore original privilege level & end self-impersonation
  360. //==========================================================
  361. RestorePrivilege() ;
  362. return dwRetCode ;
  363. }
  364. #endif
  365. /*****************************************************************************
  366. *
  367. * FUNCTION : CUserHive::Load95
  368. *
  369. * DESCRIPTION : Locates user's hive & loads into registry if not already
  370. * present
  371. *
  372. * INPUTS : none
  373. *
  374. * OUTPUTS : pszKeyName receives the expanded SID of the user's
  375. * registry key under HKEY_USERS
  376. *
  377. * RETURNS : nothing
  378. *
  379. * COMMENTS : Hive will remain in registry unless unloaded
  380. *
  381. *****************************************************************************/
  382. #ifdef WIN9XONLY
  383. DWORD CUserHive::Load95(LPCWSTR pszUserName, LPWSTR pszKeyName)
  384. {
  385. DWORD dwRetCode;
  386. WCHAR wszTemp[_MAX_PATH];
  387. TCHAR szTemp[_MAX_PATH];
  388. CHString sTemp ;
  389. CRegistry Reg ;
  390. wcscpy(pszKeyName, pszUserName);
  391. // See if the key already exists
  392. //==============================
  393. dwRetCode = Reg.Open(HKEY_USERS, pszKeyName, KEY_READ) ;
  394. // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
  395. // Reg.Close() ;
  396. if(dwRetCode == ERROR_SUCCESS)
  397. {
  398. // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
  399. // Reg.Close() ;
  400. }
  401. else
  402. {
  403. // Try to locate user's registry hive
  404. //===================================
  405. swprintf(wszTemp, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ProfileList\\%s", pszUserName) ;
  406. dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, wszTemp, KEY_READ);
  407. if(dwRetCode == ERROR_SUCCESS) {
  408. dwRetCode = Reg.GetCurrentKeyValue(L"ProfileImagePath", sTemp) ;
  409. Reg.Close() ;
  410. if(dwRetCode == ERROR_SUCCESS)
  411. {
  412. sTemp += _T("\\USER.DAT") ;
  413. ExpandEnvironmentStrings(TOBSTRT(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
  414. // Try it three times, another process may have the file open
  415. bool bTryTryAgain = false;
  416. int nTries = 0;
  417. do
  418. {
  419. // need to serialize access, using "write" because RegLoadKey wants exclusive access
  420. // even though it is a read operation
  421. m_criticalSection.BeginWrite();
  422. try
  423. {
  424. dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, TOBSTRT(pszUserName), szTemp) ;
  425. }
  426. catch ( ... )
  427. {
  428. m_criticalSection.EndWrite();
  429. throw;
  430. }
  431. m_criticalSection.EndWrite();
  432. if ((dwRetCode == ERROR_SHARING_VIOLATION)
  433. && (++nTries < 11))
  434. {
  435. LogErrorMessage(L"Sharing violation on USER.DAT (Load)");
  436. Sleep(15 * nTries);
  437. bTryTryAgain = true;
  438. }
  439. else
  440. bTryTryAgain = false;
  441. } while (bTryTryAgain);
  442. }
  443. }
  444. }
  445. if (dwRetCode == ERROR_SUCCESS)
  446. {
  447. LONG lRetVal;
  448. CHString sKey(pszUserName);
  449. sKey += L"\\Software";
  450. lRetVal = RegOpenKeyEx(HKEY_USERS, TOBSTRT(sKey), 0, KEY_QUERY_VALUE, &m_hKey);
  451. ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
  452. }
  453. return dwRetCode ;
  454. }
  455. #endif
  456. /*****************************************************************************
  457. *
  458. * FUNCTION : CUserHive::LoadProfile
  459. *
  460. * DESCRIPTION : Locates user's hive & loads into registry if not already
  461. * present
  462. *
  463. * INPUTS : none
  464. *
  465. * OUTPUTS : none.
  466. *
  467. * RETURNS : nothing
  468. *
  469. * COMMENTS : Hive will remain in registry unless unloaded
  470. * NT Only.
  471. *
  472. *****************************************************************************/
  473. DWORD CUserHive::LoadProfile( LPCWSTR pszSID, CHString& strUserName )
  474. {
  475. // NOTE: The destructor does not unload the key. Nor does doing a load unload
  476. // a previously loaded key;
  477. ASSERT_BREAK(m_hKey == NULL);
  478. DWORD dwRetCode = ERROR_SUCCESS;
  479. WCHAR szTemp[_MAX_PATH] ;
  480. CHString sTemp ;
  481. CRegistry Reg ;
  482. strUserName = L"";
  483. // Set the necessary privs
  484. //========================
  485. #ifdef NTONLY
  486. dwRetCode = AcquirePrivilege() ;
  487. #endif
  488. if(dwRetCode != ERROR_SUCCESS)
  489. {
  490. return dwRetCode ;
  491. }
  492. // See if the key already exists
  493. //==============================
  494. dwRetCode = Reg.Open(HKEY_USERS, pszSID, KEY_READ) ;
  495. // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
  496. // Reg.Close() ;
  497. // If we got the profile, make sure we can get account information regarding
  498. // the SID.
  499. if(dwRetCode == ERROR_SUCCESS)
  500. {
  501. CRegistry Reg2 ;
  502. StringCbPrintf(szTemp, _MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s", pszSID) ;
  503. dwRetCode = Reg2.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
  504. if(dwRetCode == ERROR_SUCCESS)
  505. {
  506. // Load the user account information
  507. dwRetCode = UserAccountFromProfile( Reg2, strUserName );
  508. // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
  509. Reg2.Close() ;
  510. }
  511. }
  512. else
  513. {
  514. // Try to locate user's registry hive
  515. //===================================
  516. StringCbPrintf(szTemp,_MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s", pszSID) ;
  517. dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
  518. if(dwRetCode == ERROR_SUCCESS)
  519. {
  520. UserAccountFromProfile( Reg, strUserName );
  521. dwRetCode = Reg.GetCurrentKeyValue(L"ProfileImagePath", sTemp) ;
  522. Reg.Close() ;
  523. if(dwRetCode == ERROR_SUCCESS)
  524. {
  525. // NT 4 doesn't include the file name in the registry
  526. //===================================================
  527. if(OSInfo.dwMajorVersion >= 4)
  528. {
  529. sTemp += _T("\\NTUSER.DAT") ;
  530. }
  531. TCHAR szTemp[MAX_PATH];
  532. ExpandEnvironmentStrings(TOBSTRT(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
  533. // Try it three times, another process may have the file open
  534. bool bTryTryAgain = false;
  535. int nTries = 0;
  536. do
  537. {
  538. // need to serialize access, using "write" because RegLoadKey wants exclusive access
  539. // even though it is a read operation
  540. m_criticalSection.BeginWrite();
  541. try
  542. {
  543. dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, TOBSTRT(pszSID), szTemp);
  544. }
  545. catch ( ... )
  546. {
  547. m_criticalSection.EndWrite();
  548. throw;
  549. }
  550. m_criticalSection.EndWrite();
  551. if ((dwRetCode == ERROR_SHARING_VIOLATION)
  552. && (++nTries < 11))
  553. {
  554. LogErrorMessage(L"Sharing violation on NTUSER.DAT (LoadProfile)");
  555. Sleep(20 * nTries);
  556. bTryTryAgain = true;
  557. }
  558. else
  559. {
  560. bTryTryAgain = false;
  561. }
  562. } while (bTryTryAgain);
  563. }
  564. }
  565. }
  566. if(dwRetCode == ERROR_SUCCESS)
  567. {
  568. LONG lRetVal;
  569. CHString sKey(pszSID);
  570. sKey += _T("\\Software");
  571. lRetVal = RegOpenKeyEx(HKEY_USERS, TOBSTRT(sKey), 0, KEY_QUERY_VALUE, &m_hKey);
  572. ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
  573. }
  574. // Restore original privilege level & end self-impersonation
  575. //==========================================================
  576. #ifdef NTONLY
  577. RestorePrivilege() ;
  578. #endif
  579. return dwRetCode ;
  580. }
  581. /*****************************************************************************
  582. *
  583. * FUNCTION : CUserHive::UserAccountFromProfile
  584. *
  585. * DESCRIPTION : Pulls the PSID out of the registry object, and creates
  586. * a DOMAIN\UserName value.
  587. *
  588. * INPUTS : none
  589. *
  590. * OUTPUTS : none.
  591. *
  592. * RETURNS : nothing
  593. *
  594. * COMMENTS : Registry Object must be preloaded to the correct profile
  595. * key.
  596. *
  597. *****************************************************************************/
  598. DWORD CUserHive::UserAccountFromProfile( CRegistry& reg, CHString& strUserName )
  599. {
  600. DWORD dwReturn = ERROR_SUCCESS,
  601. dwSidSize = 0;
  602. if ( ( dwReturn = reg.GetCurrentBinaryKeyValue( L"Sid", NULL, &dwSidSize ) ) == ERROR_SUCCESS )
  603. {
  604. PSID psid = new byte [ dwSidSize ];
  605. if ( NULL != psid )
  606. {
  607. try
  608. {
  609. if ( ( dwReturn = reg.GetCurrentBinaryKeyValue( L"Sid", (LPBYTE) psid, &dwSidSize ) ) == ERROR_SUCCESS )
  610. {
  611. CSid sid( psid );
  612. // The sid account type must be valid and the lookup must have been
  613. // successful.
  614. if ( sid.IsOK() && sid.IsAccountTypeValid() )
  615. {
  616. sid.GetDomainAccountName( strUserName );
  617. }
  618. else
  619. {
  620. dwReturn = ERROR_NO_SUCH_USER;
  621. }
  622. }
  623. }
  624. catch ( ... )
  625. {
  626. delete [] psid;
  627. throw ;
  628. }
  629. delete [] psid;
  630. }
  631. else
  632. {
  633. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  634. }
  635. }
  636. return dwReturn;
  637. }
  638. /*****************************************************************************
  639. *
  640. * FUNCTION : CUserHive::Unload
  641. *
  642. * DESCRIPTION : Unloads key from HKEY_USERS if present
  643. *
  644. * INPUTS : none
  645. *
  646. * OUTPUTS : none
  647. *
  648. * RETURNS : Windows error code
  649. *
  650. * COMMENTS :
  651. *
  652. *****************************************************************************/
  653. DWORD CUserHive::Unload(LPCWSTR pszKeyName)
  654. {
  655. DWORD dwRetCode = ERROR_SUCCESS;
  656. if (m_hKey != NULL)
  657. {
  658. RegCloseKey(m_hKey);
  659. m_hKey = NULL;
  660. }
  661. #ifdef NTONLY
  662. dwRetCode = AcquirePrivilege();
  663. #endif
  664. if(dwRetCode == ERROR_SUCCESS)
  665. {
  666. m_criticalSection.BeginWrite();
  667. try
  668. {
  669. dwRetCode = RegUnLoadKey(HKEY_USERS, TOBSTRT(pszKeyName)) ;
  670. }
  671. catch ( ... )
  672. {
  673. m_criticalSection.EndWrite();
  674. throw;
  675. }
  676. m_criticalSection.EndWrite();
  677. #ifdef NTONLY
  678. RestorePrivilege() ;
  679. #endif
  680. }
  681. return dwRetCode ;
  682. }