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.

15230 lines
436 KiB

  1. //*************************************************************
  2. //
  3. // Profile management routines. Implements IUserProfile.
  4. // The organization of this file is as follows:
  5. // Implementation of CUserProfile object
  6. // Implementation of CUserProfile2 object
  7. // LoadUserProfile
  8. // UnloadUserProfile
  9. // All other global functions
  10. // Implementation of various other objects and data structures
  11. //
  12. // Microsoft Confidential
  13. // Copyright (c) Microsoft Corporation 1995
  14. // All rights reserved
  15. //
  16. //*************************************************************
  17. #include "uenv.h"
  18. #include <wincred.h>
  19. #include <credp.h>
  20. #include <wow64reg.h>
  21. #include <tchar.h>
  22. #include <stdio.h>
  23. #include <sddl.h>
  24. #include "profmgr.hxx"
  25. //
  26. // XPSP1 specific
  27. //
  28. #include "xpsp1res.h"
  29. //
  30. // Length of const strings.
  31. //
  32. DWORD USER_KEY_PREFIX_LEN = lstrlen(USER_KEY_PREFIX);
  33. DWORD USER_CLASSES_HIVE_SUFFIX_LEN = lstrlen(USER_CLASSES_HIVE_SUFFIX);
  34. //
  35. // Tells us if we are loaded by winlogon or not.
  36. //
  37. extern "C" DWORD g_dwLoadFlags = 0;
  38. //
  39. // The user profile manager. There's only one instance of this object,
  40. // it resides in console winlogon.
  41. //
  42. CUserProfile cUserProfileManager;
  43. //
  44. // Local function proto-types
  45. //
  46. LPTSTR AllocAndExpandProfilePath(LPPROFILEINFO lpProfileInfo);
  47. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD);
  48. BOOL CheckForSlowLink(LPPROFILE lpProfile, DWORD dwTime, LPTSTR lpPath, BOOL bDlgLogin);
  49. BOOL CheckNetDefaultProfile(LPPROFILE lpProfile);
  50. BOOL APIENTRY ChooseProfileDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
  51. LPARAM lParam);
  52. BOOL CompareProfileInfo(LPPROFILEINFO pProfileInfo1, LPPROFILEINFO pProfileInfo2);
  53. LPPROFILEINFO CopyProfileInfo(LPPROFILEINFO pProfileInfo);
  54. BOOL CreateLocalProfileImage(LPPROFILE lpProfile, LPTSTR lpBaseName);
  55. BOOL CreateLocalProfileKey(LPPROFILE lpProfile, PHKEY phKey, BOOL *bKeyExists);
  56. DWORD DecrementProfileRefCount(LPPROFILE lpProfile);
  57. DWORD DeletePolicyState(LPCWSTR szSid );
  58. void DeleteProfileInfo(LPPROFILEINFO pProfileInfo);
  59. void DumpOpenRegistryHandle(LPTSTR lpkeyName);
  60. BOOL GetExistingLocalProfileImage(LPPROFILE lpProfile);
  61. void ReleaseClientContext_s(PPCONTEXT_HANDLE pphContext);
  62. BOOL GetUserDomainName(LPPROFILE lpProfile, LPTSTR lpDomainName,
  63. LPDWORD lpDomainNameSize);
  64. DWORD GetUserPreferenceValue(HANDLE hToken);
  65. DWORD IncrementProfileRefCount(LPPROFILE lpProfile, BOOL bInitialize);
  66. BOOL IsCacheDeleted();
  67. BOOL IsCentralProfileReachable(LPPROFILE lpProfile, BOOL *bCreateCentralProfile,
  68. BOOL *bMandatory, BOOL* bOwnerOK);
  69. BOOL IssueDefaultProfile(LPPROFILE lpProfile, LPTSTR lpDefaultProfile,
  70. LPTSTR lpLocalProfile, LPTSTR lpSidString,
  71. BOOL bMandatory);
  72. BOOL IsTempProfileAllowed();
  73. LPPROFILE LoadProfileInfo(HANDLE hTokenClient, HANDLE hTokenUser, HKEY hKeyCurrentUser);
  74. BOOL ParseProfilePath(LPPROFILE lpProfile, LPTSTR lpProfilePath, BOOL *bpCSCBypassed, TCHAR *cpDrive);
  75. BOOL PatchNewProfileIfRequired(HANDLE hToken);
  76. BOOL IsGuiSetupInProgress();
  77. BOOL PrepareProfileForUse(LPPROFILE lpProfile, LPVOID pEnv);
  78. BOOL RestoreUserProfile(LPPROFILE lpProfile);
  79. BOOL SaveProfileInfo(LPPROFILE lpProfile);
  80. BOOL SetNtUserIniAttributes(LPTSTR szDir);
  81. BOOL SetProfileTime(LPPROFILE lpProfile);
  82. BOOL TestIfUserProfileLoaded(HANDLE hUserToken, LPPROFILEINFO lpProfileInfo);
  83. DWORD ThreadMain(PMAP pThreadMap);
  84. BOOL UpgradeCentralProfile(LPPROFILE lpProfile, LPTSTR lpOldProfile);
  85. BOOL UpgradeProfile(LPPROFILE lpProfile, LPVOID pEnv);
  86. BOOL IsProfileInUse (LPCTSTR szComputer, LPCTSTR lpSid);
  87. BOOL IsUIRequired(HANDLE hToken);
  88. void CheckRUPShare(LPTSTR lpProfilePath);
  89. INT_PTR APIENTRY LoginSlowLinkDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  90. INT_PTR APIENTRY LogoffSlowLinkDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  91. BOOL RegisterDialogInterface(LPTSTR szRPCEndPoint);
  92. BOOL UnRegisterDialogInterface(void);
  93. BOOL IsPartialRoamingProfile(LPPROFILE lpProfile);
  94. void TouchLocalHive(LPPROFILE lpProfile);
  95. HRESULT CheckRoamingShareOwnership(LPTSTR lpDir, HANDLE hTokenUser);
  96. #define USERNAME_VARIABLE TEXT("USERNAME")
  97. //*************************************************************
  98. //
  99. // LoadUserProfile()
  100. //
  101. // Purpose: Loads the user's profile, if unable to load
  102. // use the cached profile or issue the default profile.
  103. //
  104. // Parameters: hToken - User's token
  105. // lpProfileInfo - Profile Information
  106. //
  107. // Return: TRUE if successful
  108. // FALSE if an error occurs
  109. //
  110. // Comments: This is a wrapper around IUserProfile::LoadUserProfile
  111. // and LoadUserProfileP.
  112. //
  113. // History: Date Author Comment
  114. // 6/6/95 ericflo Created
  115. // 6/14/00 weiruc changed to be a wrapper for
  116. // IUserProfile->LoadUserProfileP.
  117. //
  118. //*************************************************************
  119. BOOL WINAPI LoadUserProfile(HANDLE hToken, LPPROFILEINFO lpProfileInfo)
  120. {
  121. BOOL bResult = FALSE; // Return value
  122. HANDLE hOldToken = NULL;
  123. NTSTATUS status;
  124. BOOLEAN bRestoreWasEnabled;
  125. BOOLEAN bBackupWasEnabled;
  126. BOOL bRestoreEnabled = FALSE;
  127. BOOL bBackupEnabled = FALSE;
  128. TCHAR ProfileDir[MAX_PATH];
  129. DWORD dwProfileDirSize = MAX_PATH;
  130. BOOL bCoInitialized = FALSE;
  131. long lResult;
  132. LPTSTR pSid = NULL;
  133. DWORD dwErr = ERROR_SUCCESS;
  134. PCONTEXT_HANDLE phContext = NULL;
  135. handle_t hIfUserProfile;
  136. BOOL bBindInterface = FALSE;
  137. TCHAR szRPCEndPoint[MAX_PATH];
  138. LPTSTR lpRPCEndPoint = NULL;
  139. //
  140. // Initialize the debug flags.
  141. //
  142. InitDebugSupport( FALSE );
  143. //
  144. // Check Parameters
  145. //
  146. if (!lpProfileInfo) {
  147. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: NULL lpProfileInfo")));
  148. dwErr = ERROR_INVALID_PARAMETER;
  149. goto Exit;
  150. }
  151. if (lpProfileInfo->dwSize != sizeof(PROFILEINFO)) {
  152. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: lpProfileInfo->dwSize != sizeof(PROFILEINFO)")));
  153. dwErr = ERROR_INVALID_PARAMETER;
  154. goto Exit;
  155. }
  156. if (!lpProfileInfo->lpUserName || !(*lpProfileInfo->lpUserName)) {
  157. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: received a NULL pointer for lpUserName.")));
  158. dwErr = ERROR_INVALID_PARAMETER;
  159. goto Exit;
  160. }
  161. //
  162. // Make sure we can impersonate the user
  163. //
  164. if (!ImpersonateUser(hToken, &hOldToken)) {
  165. dwErr = GetLastError();
  166. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to impersonate user with %d."), dwErr));
  167. goto Exit;
  168. }
  169. //
  170. // Revert to ourselves.
  171. //
  172. RevertToUser(&hOldToken);
  173. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Yes, we can impersonate the user. Running as self")));
  174. //
  175. // Verbose output
  176. //
  177. DebugMsg((DM_VERBOSE, TEXT("=========================================================")));
  178. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Entering, hToken = <0x%x>, lpProfileInfo = 0x%x"),
  179. hToken, lpProfileInfo));
  180. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->dwFlags = <0x%x>"),
  181. lpProfileInfo->dwFlags));
  182. if (lpProfileInfo->lpUserName) {
  183. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpUserName = <%s>"),
  184. lpProfileInfo->lpUserName));
  185. } else {
  186. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL user name!")));
  187. }
  188. if (lpProfileInfo->lpProfilePath) {
  189. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpProfilePath = <%s>"),
  190. lpProfileInfo->lpProfilePath));
  191. } else {
  192. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL central profile path")));
  193. }
  194. if (lpProfileInfo->lpDefaultPath) {
  195. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpDefaultPath = <%s>"),
  196. lpProfileInfo->lpDefaultPath));
  197. } else {
  198. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL default profile path")));
  199. }
  200. if (lpProfileInfo->lpServerName) {
  201. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpServerName = <%s>"),
  202. lpProfileInfo->lpServerName));
  203. } else {
  204. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL server name")));
  205. }
  206. if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
  207. if (lpProfileInfo->lpPolicyPath) {
  208. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpPolicyPath = <%s>"),
  209. lpProfileInfo->lpPolicyPath));
  210. } else {
  211. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL policy path")));
  212. }
  213. }
  214. //
  215. // If we are in console winlogon process, call
  216. // IUserProfile::LoadUserProfileP directly. Otherwise get the COM interface
  217. //
  218. if(cUserProfileManager.IsConsoleWinlogon()) {
  219. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: In console winlogon process")));
  220. //
  221. // Call the private load user profile function.
  222. //
  223. if (!cUserProfileManager.LoadUserProfileP(NULL, hToken, lpProfileInfo, NULL)) {
  224. dwErr = GetLastError();
  225. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: LoadUserProfileP failed with error %d"), dwErr));
  226. goto Exit;
  227. }
  228. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: LoadUserProfileP succeeded")));
  229. }
  230. else {
  231. //
  232. // Enable restore and backup privilege (LoadUserClasses requires both).
  233. // Winlogon won't be able to enable the privilege for us.
  234. //
  235. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &bRestoreWasEnabled);
  236. if(!NT_SUCCESS(status)) {
  237. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to enable the restore privilege. error = %08x"), status));
  238. dwErr = RtlNtStatusToDosError(status);
  239. goto Exit;
  240. }
  241. bRestoreEnabled = TRUE;
  242. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &bBackupWasEnabled);
  243. if(!NT_SUCCESS(status)) {
  244. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to enable the backup privilege. error = %08x"), status));
  245. dwErr = RtlNtStatusToDosError(status);
  246. goto Exit;
  247. }
  248. bBackupEnabled = TRUE;
  249. //
  250. // Get the IUserProfile interface.
  251. //
  252. if (!GetInterface(&hIfUserProfile, cszRPCEndPoint)) {
  253. dwErr = GetLastError();
  254. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: GetInterface failed with error %d"), dwErr));
  255. goto Exit;
  256. }
  257. bBindInterface = TRUE;
  258. //
  259. // Call IUserProfile->DropClientToken, this will let us drop off our
  260. // client token and give us back the context.
  261. //
  262. RpcTryExcept {
  263. dwErr = cliDropClientContext(hIfUserProfile, lpProfileInfo, &phContext);
  264. }
  265. RpcExcept(1) {
  266. dwErr = RpcExceptionCode();
  267. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Calling DropClientContext took exception. err = %d"), dwErr));
  268. }
  269. RpcEndExcept
  270. if (dwErr != ERROR_SUCCESS) {
  271. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Calling DropClientContext failed. err = %d"), dwErr));
  272. goto Exit;
  273. }
  274. else {
  275. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Calling DropClientToken (as self) succeeded")));
  276. }
  277. //
  278. // Register the dialog interface
  279. //
  280. if (!(lpProfileInfo->dwFlags & (PI_NOUI | PI_LITELOAD))) {
  281. _snwprintf(szRPCEndPoint, MAX_PATH, L"IProfileDialog_%d", GetCurrentProcessId());
  282. if (!RegisterDialogInterface(szRPCEndPoint)) {
  283. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: RegisterDialogInterface fails.")));
  284. lpRPCEndPoint = NULL;
  285. }
  286. else {
  287. lpRPCEndPoint = szRPCEndPoint;
  288. }
  289. }
  290. //
  291. // Impersonate the user and call IUserProfile->LoadUserProfileI().
  292. //
  293. if(!ImpersonateUser(hToken, &hOldToken)) {
  294. dwErr = GetLastError();
  295. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ImpersonateUser failed. err = %d"), dwErr));
  296. goto Exit;
  297. }
  298. RpcTryExcept {
  299. dwErr = cliLoadUserProfileI(hIfUserProfile, lpProfileInfo, phContext, lpRPCEndPoint);
  300. }
  301. RpcExcept(1) {
  302. dwErr = RpcExceptionCode();
  303. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Calling LoadUserProfileI took exception. err = %d"), dwErr));
  304. }
  305. RpcEndExcept
  306. RevertToUser(&hOldToken);
  307. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Running as self")));
  308. if (dwErr != ERROR_SUCCESS) {
  309. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Calling LoadUserProfileI failed. err = %d"), dwErr));
  310. goto Exit;
  311. }
  312. else {
  313. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Calling LoadUserProfileI (as user) succeeded")));
  314. }
  315. //
  316. // Open the user's hive.
  317. //
  318. pSid = GetSidString(hToken);
  319. if(pSid == NULL) {
  320. dwErr = GetLastError();
  321. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: GetSidString failed, err = %d"), dwErr));
  322. goto Exit;
  323. }
  324. lResult = RegOpenKeyEx(HKEY_USERS, pSid, 0, KEY_ALL_ACCESS,
  325. (PHKEY)&lpProfileInfo->hProfile);
  326. if(lResult != ERROR_SUCCESS) {
  327. dwErr = lResult;
  328. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to open current user <%s> key. Error = %d"), pSid, lResult));
  329. DeleteSidString(pSid);
  330. goto Exit;
  331. }
  332. DeleteSidString(pSid);
  333. } // Is console winlogon?
  334. //
  335. // Set the USERPROFILE environment variable just so that there's no change
  336. // of behavior with the old in process LoadUserProfile API. Callers
  337. // expecting this env to be set is under the risk that while
  338. // SetEnvironmentVariable is per process but LoadUserProfile can be called
  339. // on multiple threads.
  340. //
  341. if(!GetUserProfileDirectory(hToken, ProfileDir, &dwProfileDirSize)) {
  342. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: GetUserProfileDirectory failed with %08x"), GetLastError()));
  343. }
  344. else {
  345. SetEnvironmentVariable (TEXT("USERPROFILE"), ProfileDir);
  346. }
  347. bResult = TRUE;
  348. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Returning success. Final Information follows:")));
  349. DebugMsg((DM_VERBOSE, TEXT("lpProfileInfo->UserName = <%s>"), lpProfileInfo->lpUserName));
  350. DebugMsg((DM_VERBOSE, TEXT("lpProfileInfo->lpProfilePath = <%s>"), lpProfileInfo->lpProfilePath));
  351. DebugMsg((DM_VERBOSE, TEXT("lpProfileInfo->dwFlags = 0x%x"), lpProfileInfo->dwFlags));
  352. Exit:
  353. //
  354. // Restore the previous privileges.
  355. //
  356. if(bRestoreEnabled && !bRestoreWasEnabled) {
  357. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, bRestoreWasEnabled, FALSE, &bRestoreWasEnabled);
  358. if(!NT_SUCCESS(status)) {
  359. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Failed to restore the original restore privilege setting. error = %08x"), status));
  360. }
  361. }
  362. if(bBackupEnabled && !bBackupWasEnabled) {
  363. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, bBackupWasEnabled, FALSE, &bBackupWasEnabled);
  364. if(!NT_SUCCESS(status)) {
  365. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Failed to restore the original backup privilege setting. error = %08x"), status));
  366. }
  367. }
  368. //
  369. // Unregister the Dialog interface
  370. //
  371. if (lpRPCEndPoint && !UnRegisterDialogInterface()) {
  372. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: UnRegisterDialogInterface fails.")));
  373. }
  374. //
  375. // Release the context handle
  376. //
  377. if (phContext) {
  378. RpcTryExcept {
  379. cliReleaseClientContext(hIfUserProfile, &phContext);
  380. }
  381. RpcExcept(1) {
  382. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ReleaseClientContext took exception."), RpcExceptionCode()));
  383. }
  384. RpcEndExcept
  385. }
  386. //
  387. // Release the interface
  388. //
  389. if (bBindInterface) {
  390. if (!ReleaseInterface(&hIfUserProfile)) {
  391. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ReleaseInterface failed.")));
  392. }
  393. }
  394. //
  395. // Release the tokens.
  396. //
  397. if(hOldToken) {
  398. CloseHandle(hOldToken);
  399. }
  400. if(bResult) {
  401. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Returning TRUE. hProfile = <0x%x>"), lpProfileInfo->hProfile));
  402. } else {
  403. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Returning FALSE. Error = %d"), dwErr));
  404. }
  405. //
  406. // Set the last error to win32 error code.
  407. //
  408. SetLastError(dwErr);
  409. //
  410. // Return.
  411. //
  412. return bResult;
  413. }
  414. //*************************************************************
  415. //
  416. // UnloadUserProfile()
  417. //
  418. // Purpose: Unloads the user's profile.
  419. //
  420. // Parameters: hToken - User's token
  421. // hProfile - Profile handle created in LoadUserProfile
  422. //
  423. // Return: TRUE if successful
  424. // FALSE if an error occurs
  425. //
  426. // Comments:
  427. //
  428. // History: Date Author Comment
  429. // 6/7/95 ericflo Created
  430. // 6/15/00 weiruc Modified to wrap
  431. // IUserProfile->UnloadUserProfileP.
  432. //
  433. //*************************************************************
  434. BOOL WINAPI UnloadUserProfile(HANDLE hToken, HANDLE hProfile)
  435. {
  436. HANDLE hOldToken = NULL;
  437. BOOL bResult = FALSE;
  438. NTSTATUS status;
  439. BOOLEAN bWasBackupEnabled, bWasRestoreEnabled;
  440. BOOL bBackupEnabled = FALSE, bRestoreEnabled = FALSE;
  441. BOOL bCoInitialized = FALSE;
  442. DWORD dwErr = ERROR_SUCCESS;
  443. PCONTEXT_HANDLE phContext = NULL;
  444. handle_t hIfUserProfile;
  445. BOOL bBindInterface = FALSE;
  446. TCHAR szRPCEndPoint[MAX_PATH];
  447. LPTSTR lpRPCEndPoint = NULL;
  448. //
  449. // Verbose output
  450. //
  451. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Entering, hProfile = <0x%x>"), hProfile));
  452. //
  453. // Check Parameters
  454. //
  455. if (!hProfile || hProfile == INVALID_HANDLE_VALUE) {
  456. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: received a NULL hProfile.")));
  457. dwErr = ERROR_INVALID_PARAMETER;
  458. goto Exit;
  459. }
  460. if(!hToken || hToken == INVALID_HANDLE_VALUE) {
  461. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: received a NULL hToken.")));
  462. dwErr = ERROR_INVALID_PARAMETER;
  463. goto Exit;
  464. }
  465. //
  466. // Make sure we can impersonate the user
  467. //
  468. if (!ImpersonateUser(hToken, &hOldToken)) {
  469. dwErr = GetLastError();
  470. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to impersonate user with %d."), dwErr));
  471. goto Exit;
  472. }
  473. //
  474. // Revert to ourselves.
  475. //
  476. RevertToUser(&hOldToken);
  477. //
  478. // If we are in console winlogon process, call
  479. // IUserProfile::UnloadUserProfileP directly. Otherwise get the COM interface
  480. //
  481. if(cUserProfileManager.IsConsoleWinlogon()) {
  482. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: In console winlogon process")));
  483. //
  484. // Call the private UnloadUserProfile function.
  485. //
  486. if(!cUserProfileManager.UnloadUserProfileP(NULL, hToken, (HKEY)hProfile, NULL)) {
  487. dwErr = GetLastError();
  488. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: UnloadUserProfileP failed with %d"), dwErr));
  489. goto Exit;
  490. }
  491. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: UnloadUserProfileP succeeded")));
  492. }
  493. else {
  494. //
  495. // Close the hProfile key user passed in.
  496. //
  497. RegCloseKey((HKEY)hProfile);
  498. //
  499. // Enable the restore & backup privilege before calling over to winlogon.
  500. // Winlogon won't be able to enable the privilege for us.
  501. //
  502. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &bWasRestoreEnabled);
  503. if(!NT_SUCCESS(status)) {
  504. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to enable the restore privilege. error = %08x"), status));
  505. dwErr = RtlNtStatusToDosError(status);
  506. goto Exit;
  507. }
  508. bRestoreEnabled = TRUE;
  509. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &bWasBackupEnabled);
  510. if(!NT_SUCCESS(status)) {
  511. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: Failed to enable the backup privilege. error = %08x"), status));
  512. dwErr = RtlNtStatusToDosError(status);
  513. goto Exit;
  514. }
  515. bBackupEnabled = TRUE;
  516. //
  517. // Get the IUserProfile interface.
  518. //
  519. if(!GetInterface(&hIfUserProfile, cszRPCEndPoint)) {
  520. dwErr = GetLastError();
  521. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: GetInterface failed with error %d"), dwErr));
  522. goto Exit;
  523. }
  524. bBindInterface = TRUE;
  525. //
  526. // Call IUserProfile->DropClientToken, this will let us drop off our
  527. // client token and give us back the context.
  528. //
  529. RpcTryExcept {
  530. dwErr = cliDropClientContext(hIfUserProfile, NULL, &phContext);
  531. }
  532. RpcExcept(1) {
  533. dwErr = RpcExceptionCode();
  534. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfile: Calling DropClientToken took exception. error %d"), dwErr));
  535. }
  536. RpcEndExcept
  537. if (dwErr != ERROR_SUCCESS) {
  538. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfile: Calling DropClientContext failed. err = %d"), dwErr));
  539. goto Exit;
  540. }
  541. else {
  542. DebugMsg((DM_VERBOSE, TEXT("UnLoadUserProfile: Calling DropClientToken (as self) succeeded")));
  543. }
  544. //
  545. // Register the dialog interface if req
  546. //
  547. if (IsUIRequired(hToken)) {
  548. _snwprintf(szRPCEndPoint, MAX_PATH, L"IProfileDialog_%d", GetCurrentProcessId());
  549. if (!RegisterDialogInterface(szRPCEndPoint)) {
  550. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: RegisterDialogInterface fails.")));
  551. lpRPCEndPoint = NULL;
  552. }
  553. else {
  554. lpRPCEndPoint = szRPCEndPoint;
  555. }
  556. }
  557. //
  558. // Impersonate the user and call IUserProfile->UnloadUserProfileI().
  559. //
  560. if (!ImpersonateUser(hToken, &hOldToken)) {
  561. dwErr = GetLastError();
  562. DebugMsg((DM_WARNING, TEXT("UnloadUserProfile: ImpersonateUser failed. err = %d"), dwErr));
  563. goto Exit;
  564. }
  565. RpcTryExcept {
  566. dwErr = cliUnloadUserProfileI(hIfUserProfile, phContext, lpRPCEndPoint);
  567. }
  568. RpcExcept(1) {
  569. dwErr = RpcExceptionCode();
  570. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfile: Calling UnLoadUserProfileI took exception. err = %d"), dwErr));
  571. }
  572. RpcEndExcept
  573. //
  574. // Revert back.
  575. //
  576. RevertToUser(&hOldToken);
  577. if (dwErr != ERROR_SUCCESS) {
  578. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfile: Calling UnLoadUserProfileI failed. err = %d"), dwErr));
  579. goto Exit;
  580. }
  581. else {
  582. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Calling UnloadUserProfileI succeeded")));
  583. }
  584. } // Is console winlogon?
  585. bResult = TRUE;
  586. Exit:
  587. //
  588. // Restore the previous privilege.
  589. //
  590. if(bRestoreEnabled && !bWasRestoreEnabled) {
  591. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, bWasRestoreEnabled, FALSE, &bWasRestoreEnabled);
  592. if(!NT_SUCCESS(status)) {
  593. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Failed to restore the original restore privilege setting. error = %08x"), status));
  594. }
  595. }
  596. if(bBackupEnabled && !bWasBackupEnabled) {
  597. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, bWasBackupEnabled, FALSE, &bWasBackupEnabled);
  598. if(!NT_SUCCESS(status)) {
  599. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Failed to restore the original backup privilege setting. error = %08x"), status));
  600. }
  601. }
  602. //
  603. // Unregister the Dialog interface
  604. //
  605. if (lpRPCEndPoint && !UnRegisterDialogInterface()) {
  606. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: UnRegisterDialogInterface fails.")));
  607. }
  608. //
  609. // Release the context handle
  610. //
  611. if (phContext) {
  612. RpcTryExcept {
  613. cliReleaseClientContext(hIfUserProfile, &phContext);
  614. }
  615. RpcExcept(1) {
  616. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfile: ReleaseClientContext took exception."), RpcExceptionCode()));
  617. }
  618. RpcEndExcept
  619. }
  620. //
  621. // Release the interface
  622. //
  623. if (bBindInterface) {
  624. if (!ReleaseInterface(&hIfUserProfile)) {
  625. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ReleaseInterface failed.")));
  626. }
  627. }
  628. //
  629. // Release the tokens.
  630. //
  631. if(hOldToken) {
  632. CloseHandle(hOldToken);
  633. }
  634. //
  635. // Set the last error to win32 error code.
  636. //
  637. SetLastError(dwErr);
  638. //
  639. // Return.
  640. //
  641. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: returning %d"), bResult));
  642. return bResult;
  643. }
  644. //*************************************************************
  645. //
  646. // CUserProfile::Initialize()
  647. //
  648. // Initializes the class. Called by and only by console winlogon.
  649. //
  650. // Return value:
  651. //
  652. // This function does not return a value.
  653. //
  654. // History:
  655. //
  656. // Created weiruc 2/29/2000
  657. //
  658. //*************************************************************
  659. void CUserProfile::Initialize()
  660. {
  661. LONG lResult;
  662. HKEY hkProfileList = NULL;
  663. DWORD i = 0;
  664. TCHAR tszSubKeyName[MAX_PATH];
  665. DWORD dwcSubKeyName = MAX_PATH;
  666. FILETIME ftLWT; // last write time.
  667. HRESULT hres;
  668. BOOL bCSInitialized = FALSE;
  669. RPC_STATUS status;
  670. DebugMsg((DM_VERBOSE, TEXT("Entering CUserProfile::Initialize ...")));
  671. //
  672. // If the caller is not winlogon, do nothing and return.
  673. //
  674. if(g_dwLoadFlags != WINLOGON_LOAD) {
  675. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize called by non-winlogon process, %d"), g_dwLoadFlags));
  676. goto Exit;
  677. }
  678. bConsoleWinlogon = TRUE;
  679. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::Initialize called by winlogon")));
  680. //
  681. // If this function is already called, do nothing but return.
  682. //
  683. if(bInitialized) {
  684. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize already called")));
  685. goto Exit;
  686. }
  687. //
  688. // Initialize the critical section that protects the map.
  689. //
  690. __try {
  691. if(!InitializeCriticalSectionAndSpinCount(&csMap, 0x80000000)) {
  692. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: InitializeCriticalSectionAndSpinCount failed with %08x"), GetLastError()));
  693. goto Exit;
  694. }
  695. bCSInitialized = TRUE;
  696. }
  697. __except(EXCEPTION_EXECUTE_HANDLER) {
  698. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: InitializeCriticalSection failed")));
  699. goto Exit;
  700. }
  701. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::Initialize: critical section initialized")));
  702. //
  703. // Initialize the whrc data
  704. //
  705. pMap = NULL;
  706. cTable.Initialize();
  707. //
  708. // Initialize the sync manager.
  709. //
  710. if(!cSyncMgr.Initialize()) {
  711. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: Initialize sync manager failed")));
  712. goto Exit;
  713. }
  714. //
  715. // Clean up the unloaded hives and undeleted profiles that we didn't handle
  716. // before last shutdown.
  717. //
  718. //
  719. // Open the profile list key.
  720. //
  721. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  722. PROFILE_LIST_PATH,
  723. 0,
  724. KEY_READ,
  725. &hkProfileList);
  726. if(lResult != ERROR_SUCCESS) {
  727. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: Failed to open profile list key with error %d"), lResult));
  728. goto Exit;
  729. }
  730. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::Initialize: registry key %s opened"), PROFILE_LIST_PATH));
  731. //
  732. // Enumerate users.
  733. //
  734. i = 0;
  735. while((lResult = RegEnumKeyEx(hkProfileList,
  736. i,
  737. tszSubKeyName,
  738. &dwcSubKeyName,
  739. NULL,
  740. NULL,
  741. NULL,
  742. &ftLWT)) == ERROR_SUCCESS) {
  743. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::Initialize: Proccessing %s"), tszSubKeyName));
  744. CleanupUserProfile(tszSubKeyName, &hkProfileList);
  745. dwcSubKeyName = MAX_PATH;
  746. i++;
  747. }
  748. if(lResult != ERROR_SUCCESS && lResult != ERROR_NO_MORE_ITEMS) {
  749. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: RegEnumKeyEx returned %08x"), lResult));
  750. }
  751. //
  752. // Specify to use the local rpc protocol sequence
  753. //
  754. status = RpcServerUseProtseqEp(cszRPCProtocol, // ncalrpc prot seq
  755. cdwMaxRpcCalls, // max concurrent calls
  756. cszRPCEndPoint,
  757. NULL); // Security descriptor
  758. if (status != RPC_S_OK) {
  759. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: RpcServerUseProtseqEp fails with error %ld"), status));
  760. goto Exit;
  761. }
  762. //
  763. // Register the IUserProfile interface
  764. //
  765. status = RpcServerRegisterIfEx(IUserProfile_v1_0_s_ifspec, // interface to register
  766. NULL, // MgrTypeUuid
  767. NULL, // MgrEpv; null means use default
  768. RPC_IF_AUTOLISTEN, // auto-listen interface
  769. cdwMaxRpcCalls, // max concurrent calls
  770. NULL); // no callback
  771. if (status != RPC_S_OK) {
  772. DebugMsg((DM_WARNING, TEXT("CUserProfile::Initialize: RpcServerRegisterIfEx fails with error %ld"), status));
  773. goto Exit;
  774. }
  775. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::Initialize: RpcServerRegisterIfEx successful")));
  776. bInitialized = TRUE;
  777. Exit:
  778. if(bInitialized == FALSE && bCSInitialized == TRUE) {
  779. DeleteCriticalSection(&csMap);
  780. }
  781. if(hkProfileList != NULL) {
  782. RegCloseKey(hkProfileList);
  783. }
  784. if(bInitialized == TRUE) {
  785. DebugMsg((DM_VERBOSE, TEXT("Exiting CUserProfile::Initialize, successful")));
  786. }
  787. else {
  788. DebugMsg((DM_VERBOSE, TEXT("Exiting CUserProfile::Initialize, unsuccessful")));
  789. }
  790. }
  791. //*************************************************************
  792. //
  793. // CUserProfile::LoadUserProfileP()
  794. //
  795. // Purpose: Loads the user's profile, if unable to load
  796. // use the cached profile or issue the default profile.
  797. //
  798. // Parameters: hTokenClient - the client who's trying to load the
  799. // user's profile. A NULL value indicate
  800. // that this is a in-proccess call.
  801. // hTokenUser - the user who's profile is being loaded.
  802. // lpProfileInfo - Profile Information
  803. //
  804. // Return: TRUE if successful
  805. // FALSE if an error occurs
  806. //
  807. // Comments:
  808. //
  809. // History: Date Author Comment
  810. // 6/6/95 ericflo Created
  811. // 6/27/00 weiruc Made a private function called
  812. // by the win32 API LoadUserProfile to do
  813. // the actual work.
  814. //
  815. //*************************************************************
  816. BOOL CUserProfile::LoadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, LPPROFILEINFO lpProfileInfo, LPTSTR lpRPCEndPoint)
  817. {
  818. LPPROFILE lpProfile = NULL;
  819. BOOL bResult = FALSE, bNewProfileLoaded = FALSE;
  820. HANDLE hOldToken = NULL;
  821. HANDLE hTmpToken = NULL;
  822. DWORD dwRef, dwErr = ERROR_SUCCESS;
  823. LPTSTR SidString = NULL;
  824. LPVOID pEnv = NULL;
  825. NTSTATUS status;
  826. BOOL bInCS = FALSE;
  827. BOOL bCSCBypassed = FALSE;
  828. TCHAR cDrive;
  829. //
  830. // Initialize the debug flags.
  831. //
  832. InitDebugSupport( FALSE );
  833. DebugMsg((DM_VERBOSE, TEXT("In LoadUserProfileP")));
  834. if(hTokenClient && hTokenClient != INVALID_HANDLE_VALUE) {
  835. //
  836. // Check the client's identity
  837. //
  838. if (!IsUserAnAdminMember(hTokenClient) && !IsUserALocalSystemMember(hTokenClient)) {
  839. dwErr = ERROR_ACCESS_DENIED;
  840. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Unable to load profile for client %08x. Not enough permission. Error %d."), hTokenClient, dwErr));
  841. goto Exit;
  842. }
  843. //
  844. // Run under the client's identity rather than winlogon's.
  845. //
  846. if(!ImpersonateUser(hTokenClient, &hTmpToken)) {
  847. dwErr = GetLastError();
  848. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ImpersonateUser <%08x> failed with %08x"), hTokenClient, dwErr));
  849. goto Exit;
  850. }
  851. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Running as client")));
  852. }
  853. //
  854. // Check Parameters
  855. //
  856. if (!lpProfileInfo) {
  857. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: NULL lpProfileInfo")));
  858. dwErr = ERROR_INVALID_PARAMETER;
  859. goto Exit;
  860. }
  861. if (!lpProfileInfo->lpUserName || !(*lpProfileInfo->lpUserName)) {
  862. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: received a NULL pointer for lpUserName.")));
  863. dwErr = ERROR_INVALID_PARAMETER;
  864. goto Exit;
  865. }
  866. //
  867. // if the profile path or default path is greater than MAX_PATH, ignore them.
  868. //
  869. if ((lpProfileInfo->lpProfilePath) && (lstrlen(lpProfileInfo->lpProfilePath) >= MAX_PATH)) {
  870. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: long profile path name %s. ignoring"), lpProfileInfo->lpProfilePath));
  871. ReportError(hTokenUser, PI_NOUI, 1, EVENT_PROFILE_PATH_TOOLONG, lpProfileInfo->lpProfilePath);
  872. (lpProfileInfo->lpProfilePath)[0] = TEXT('\0');
  873. }
  874. if ((lpProfileInfo->lpDefaultPath) && (lstrlen(lpProfileInfo->lpDefaultPath) >= MAX_PATH)) {
  875. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: long default profile path name %s. ignoring"), lpProfileInfo->lpDefaultPath));
  876. (lpProfileInfo->lpDefaultPath)[0] = TEXT('\0');
  877. }
  878. //
  879. // Verbose output
  880. //
  881. DebugMsg((DM_VERBOSE, TEXT("=========================================================")));
  882. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Entering, hToken = <0x%x>, lpProfileInfo = 0x%x"),
  883. hTokenUser, lpProfileInfo));
  884. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->dwFlags = <0x%x>"),
  885. lpProfileInfo->dwFlags));
  886. if (lpProfileInfo->lpUserName) {
  887. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpUserName = <%s>"),
  888. lpProfileInfo->lpUserName));
  889. } else {
  890. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL user name!")));
  891. }
  892. if (lpProfileInfo->lpProfilePath) {
  893. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpProfilePath = <%s>"),
  894. lpProfileInfo->lpProfilePath));
  895. } else {
  896. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL central profile path")));
  897. }
  898. if (lpProfileInfo->lpDefaultPath) {
  899. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpDefaultPath = <%s>"),
  900. lpProfileInfo->lpDefaultPath));
  901. } else {
  902. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL default profile path")));
  903. }
  904. if (lpProfileInfo->lpServerName) {
  905. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpServerName = <%s>"),
  906. lpProfileInfo->lpServerName));
  907. } else {
  908. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL server name")));
  909. }
  910. if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
  911. if (lpProfileInfo->lpPolicyPath) {
  912. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: lpProfileInfo->lpPolicyPath = <%s>"),
  913. lpProfileInfo->lpPolicyPath));
  914. } else {
  915. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: NULL policy path")));
  916. }
  917. }
  918. //
  919. // Make sure someone isn't loading a profile during
  920. // GUI mode setup (eg: mapi)
  921. //
  922. if (IsGuiSetupInProgress()) {
  923. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: LoadUserProfile can not be called during GUI mode setup.")));
  924. dwErr = ERROR_NOT_READY;
  925. goto Exit;
  926. }
  927. //
  928. // Wait for the profile setup event to be signalled
  929. //
  930. if (g_hProfileSetup) {
  931. if ((WaitForSingleObject (g_hProfileSetup, 600000) != WAIT_OBJECT_0)) {
  932. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to wait on the profile setup event. Error = %d."),
  933. GetLastError()));
  934. dwErr = GetLastError();
  935. goto Exit;
  936. }
  937. }
  938. //
  939. // Get the user's sid in string form
  940. //
  941. SidString = GetSidString(hTokenUser);
  942. if (!SidString) {
  943. dwErr = GetLastError();
  944. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to get sid string for user")));
  945. goto Exit;
  946. }
  947. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: User sid: %s"), SidString));
  948. //
  949. // Enter the critical section.
  950. //
  951. if(!cSyncMgr.EnterLock(SidString, lpRPCEndPoint)) {
  952. dwErr = GetLastError();
  953. DebugMsg((DM_WARNING, TEXT("LoadUserProfile:: Failed to get the user profile lock")));
  954. goto Exit;
  955. }
  956. bInCS = TRUE;
  957. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Wait succeeded. In critical section.")));
  958. //------------------- BEGIN CRITICAL SECTION ------------------------
  959. //
  960. // We are in the critical section at this point, no doddling now...
  961. //
  962. //
  963. // Check if the profile is loaded already.
  964. //
  965. if (TestIfUserProfileLoaded(hTokenUser, lpProfileInfo)) {
  966. DWORD dwFlags = lpProfileInfo->dwFlags;
  967. //
  968. // This profile is already loaded. Grab the info from the registry
  969. // and add the missing chunks.
  970. //
  971. lpProfile = LoadProfileInfo(hTokenClient, hTokenUser, (HKEY)lpProfileInfo->hProfile);
  972. if (!lpProfile) {
  973. RegCloseKey ((HKEY)lpProfileInfo->hProfile);
  974. lpProfileInfo->hProfile = NULL;
  975. dwErr = GetLastError();
  976. goto Exit;
  977. }
  978. //
  979. // LoadProfileInfo will overwrite the dwFlags field with the
  980. // value from the previous profile loading. Restore the flags.
  981. //
  982. lpProfile->dwFlags = dwFlags;
  983. if (lpProfile->dwFlags & PI_LITELOAD) {
  984. lpProfile->dwFlags |= PI_NOUI;
  985. }
  986. //
  987. // LoadProfileInfo doesn't restore username, servername, policypath so
  988. // special case these.
  989. //
  990. lpProfile->lpUserName = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpUserName) + 1) * sizeof(TCHAR));
  991. if (!lpProfile->lpUserName) {
  992. RegCloseKey ((HKEY)lpProfileInfo->hProfile);
  993. dwErr = GetLastError();
  994. goto Exit;
  995. }
  996. lstrcpy (lpProfile->lpUserName, lpProfileInfo->lpUserName);
  997. if (lpProfileInfo->lpServerName) {
  998. lpProfile->lpServerName = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpServerName) + 1) * sizeof(TCHAR));
  999. if (lpProfile->lpServerName) {
  1000. lstrcpy (lpProfile->lpServerName, lpProfileInfo->lpServerName);
  1001. }
  1002. }
  1003. if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
  1004. if (lpProfileInfo->lpPolicyPath) {
  1005. lpProfile->lpPolicyPath = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpPolicyPath) + 1) * sizeof(TCHAR));
  1006. if (lpProfile->lpPolicyPath) {
  1007. lstrcpy (lpProfile->lpPolicyPath, lpProfileInfo->lpPolicyPath);
  1008. }
  1009. }
  1010. }
  1011. //
  1012. // If the profile is already loaded because it was leaked,
  1013. // then the classes root may not be loaded. Insure that it
  1014. // is loaded.
  1015. //
  1016. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  1017. dwErr = LoadUserClasses( lpProfile, SidString, FALSE );
  1018. if (dwErr != ERROR_SUCCESS) {
  1019. LPTSTR szErr = NULL;
  1020. szErr = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1021. if (!szErr) {
  1022. dwErr = GetLastError();
  1023. DebugMsg((DM_WARNING, TEXT("LoadUserProfileP: Out of memory")));
  1024. goto Exit;
  1025. }
  1026. //
  1027. // If the user is an Admin, then let him/her log on with
  1028. // either the .default profile, or an empty profile.
  1029. //
  1030. if (IsUserAnAdminMember(lpProfile->hTokenUser)) {
  1031. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_ADMIN_OVERRIDE, GetErrString(dwErr, szErr));
  1032. dwErr = ERROR_SUCCESS;
  1033. LocalFree(szErr);
  1034. }
  1035. else {
  1036. DebugMsg((DM_WARNING, TEXT("LoadUserProfileP: Could not load the user class hive. Error = %d"), dwErr));
  1037. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_FAILED_LOAD_PROFILE, GetErrString(dwErr, szErr));
  1038. RegCloseKey ((HKEY)lpProfileInfo->hProfile);
  1039. lpProfileInfo->hProfile = NULL;
  1040. LocalFree(szErr);
  1041. goto Exit;
  1042. }
  1043. }
  1044. }
  1045. //
  1046. // Jump to the end of the profile loading code.
  1047. //
  1048. goto ProfileLoaded;
  1049. }
  1050. //
  1051. // If we are here, the profile isn't loaded yet, so we are
  1052. // starting from scratch.
  1053. //
  1054. //
  1055. // Clone the process's environment block. This is passed to CreateProcess
  1056. // by userdiff and system policy because they rely on the USERPROFILE
  1057. // environment variable, but setting USERPROFILE for the whole process
  1058. // is not thread safe.
  1059. //
  1060. status = RtlCreateEnvironment(TRUE, &pEnv);
  1061. if(!NT_SUCCESS(status)) {
  1062. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: RtlCreateEnvironment returned %08x"), status));
  1063. dwErr = status;
  1064. goto Exit;
  1065. }
  1066. //
  1067. // Allocate an internal Profile structure to work with.
  1068. //
  1069. lpProfile = (LPPROFILE) LocalAlloc (LPTR, sizeof(USERPROFILE));
  1070. if (!lpProfile) {
  1071. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to allocate memory")));
  1072. dwErr = GetLastError();
  1073. goto Exit;
  1074. }
  1075. //
  1076. // Save the data passed in.
  1077. //
  1078. lpProfile->dwFlags = lpProfileInfo->dwFlags;
  1079. //
  1080. // No UI in case of Lite_Load
  1081. //
  1082. if (lpProfile->dwFlags & PI_LITELOAD) {
  1083. lpProfile->dwFlags |= PI_NOUI;
  1084. }
  1085. lpProfile->dwUserPreference = GetUserPreferenceValue(hTokenUser);
  1086. lpProfile->hTokenUser = hTokenUser;
  1087. lpProfile->hTokenClient = hTokenClient;
  1088. lpProfile->lpUserName = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpUserName) + 1) * sizeof(TCHAR));
  1089. if (!lpProfile->lpUserName) {
  1090. dwErr = GetLastError();
  1091. goto Exit;
  1092. }
  1093. lstrcpy (lpProfile->lpUserName, lpProfileInfo->lpUserName);
  1094. if (lpProfileInfo->lpDefaultPath) {
  1095. lpProfile->lpDefaultProfile = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpDefaultPath) + 1) * sizeof(TCHAR));
  1096. if (lpProfile->lpDefaultProfile) {
  1097. lstrcpy (lpProfile->lpDefaultProfile, lpProfileInfo->lpDefaultPath);
  1098. }
  1099. }
  1100. if (lpProfileInfo->lpProfilePath) {
  1101. lpProfile->lpProfilePath = AllocAndExpandProfilePath (lpProfileInfo);
  1102. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Expanded profile path is %s"),
  1103. lpProfile->lpProfilePath?lpProfile->lpProfilePath:TEXT("NULL")));
  1104. }
  1105. if (lpProfileInfo->lpServerName) {
  1106. lpProfile->lpServerName = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpServerName) + 1) * sizeof(TCHAR));
  1107. if (lpProfile->lpServerName) {
  1108. lstrcpy (lpProfile->lpServerName, lpProfileInfo->lpServerName);
  1109. }
  1110. }
  1111. if (lpProfileInfo->dwFlags & PI_APPLYPOLICY) {
  1112. if (lpProfileInfo->lpPolicyPath) {
  1113. lpProfile->lpPolicyPath = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpProfileInfo->lpPolicyPath) + 1) * sizeof(TCHAR));
  1114. if (lpProfile->lpPolicyPath) {
  1115. lstrcpy (lpProfile->lpPolicyPath, lpProfileInfo->lpPolicyPath);
  1116. }
  1117. }
  1118. }
  1119. lpProfile->lpLocalProfile = (LPTSTR)LocalAlloc (LPTR, MAX_PATH * sizeof(TCHAR));
  1120. if (!lpProfile->lpLocalProfile) {
  1121. dwErr = GetLastError();
  1122. goto Exit;
  1123. }
  1124. lpProfile->lpRoamingProfile = (LPTSTR)LocalAlloc (LPTR, MAX_PATH * sizeof(TCHAR));
  1125. if (!lpProfile->lpRoamingProfile) {
  1126. dwErr = GetLastError();
  1127. goto Exit;
  1128. }
  1129. //
  1130. // If there is a central profile, check for 3.x or 4.0 format.
  1131. //
  1132. if (lpProfileInfo->lpProfilePath && (*lpProfileInfo->lpProfilePath)) {
  1133. //
  1134. // Call ParseProfilePath to work some magic on it
  1135. //
  1136. if (!ParseProfilePath(lpProfile, lpProfile->lpProfilePath, &bCSCBypassed, &cDrive)) {
  1137. dwErr = GetLastError();
  1138. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ParseProfilePath returned FALSE")));
  1139. goto Exit;
  1140. }
  1141. //
  1142. // The real central profile directory is...
  1143. //
  1144. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: ParseProfilePath returned a directory of <%s>"),
  1145. lpProfile->lpRoamingProfile));
  1146. }
  1147. //
  1148. // Load the user's profile
  1149. //
  1150. if (!RestoreUserProfile(lpProfile)) {
  1151. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: RestoreUserProfile returned FALSE")));
  1152. dwErr = GetLastError();
  1153. goto Exit;
  1154. }
  1155. GetSystemTimeAsFileTime (&lpProfile->ftProfileLoad);
  1156. //
  1157. // Save the profile information in the registry
  1158. //
  1159. SaveProfileInfo (lpProfile);
  1160. //
  1161. // Set the USERPROFILE environment variable into the block.
  1162. // This allows ExpandEnvironmentStrings to be used
  1163. // in the userdiff processing.
  1164. //
  1165. if(pEnv) {
  1166. SetEnvironmentVariableInBlock(&pEnv, TEXT("USERPROFILE"), lpProfile->lpLocalProfile, TRUE);
  1167. }
  1168. //
  1169. // Flush the special folder pidls stored in shell32.dll
  1170. //
  1171. FlushSpecialFolderCache();
  1172. //
  1173. // Set attributes on ntuser.ini
  1174. //
  1175. SetNtUserIniAttributes(lpProfile->lpLocalProfile);
  1176. //
  1177. // Upgrade the profile if appropriate.
  1178. //
  1179. if (!(lpProfileInfo->dwFlags & PI_LITELOAD)) {
  1180. if(pEnv) {
  1181. if (!UpgradeProfile(lpProfile, pEnv)) {
  1182. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: UpgradeProfile returned FALSE")));
  1183. }
  1184. }
  1185. else {
  1186. if (!UpgradeProfile(lpProfile, GetEnvironmentStrings())) {
  1187. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: UpgradeProfile returned FALSE")));
  1188. }
  1189. }
  1190. }
  1191. //
  1192. // Prepare the profile for use on this machine
  1193. //
  1194. PrepareProfileForUse (lpProfile, pEnv);
  1195. bNewProfileLoaded = TRUE;
  1196. ProfileLoaded:
  1197. //
  1198. // Increment the profile Ref count
  1199. //
  1200. dwRef = IncrementProfileRefCount(lpProfile, bNewProfileLoaded);
  1201. if (!bNewProfileLoaded && (dwRef <= 1)) {
  1202. DebugMsg((DM_WARNING, TEXT("Profile was loaded but the Ref Count is %d !!!"), dwRef));
  1203. }
  1204. else {
  1205. DebugMsg((DM_VERBOSE, TEXT("Profile Ref Count is %d"), dwRef));
  1206. }
  1207. //
  1208. // This will leave the critical section so other threads/process can
  1209. // continue.
  1210. //
  1211. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Leaving critical Section.")));
  1212. if(cSyncMgr.LeaveLock(SidString)) {
  1213. bInCS = FALSE;
  1214. }
  1215. else {
  1216. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: User profile lock not released %08x"), GetLastError()));
  1217. }
  1218. //
  1219. // Notify LSA that the profile has loaded
  1220. //
  1221. if (!ImpersonateUser(hTokenUser, &hOldToken)) {
  1222. dwErr = GetLastError();
  1223. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to impersonate user with %d."), dwErr ));
  1224. goto Exit;
  1225. }
  1226. else {
  1227. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Impersonated user: %08x, %08x"), hTokenUser, hOldToken));
  1228. }
  1229. if (!CredProfileLoaded()) {
  1230. dwErr = GetLastError();
  1231. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: Failed to notify LSA that profile loaded %d."), dwErr ));
  1232. RevertToUser(&hOldToken);
  1233. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Reverted to user: %08x"), hOldToken));
  1234. goto Exit;
  1235. }
  1236. RevertToUser(&hOldToken);
  1237. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Reverted to user: %08x"), hOldToken));
  1238. //
  1239. // The critical section is now released so we can do slower things like
  1240. // apply policy...
  1241. //
  1242. //------------------- END MUTEX SECTION ------------------------
  1243. //
  1244. // Apply Policy
  1245. //
  1246. if (lpProfile->dwFlags & PI_APPLYPOLICY) {
  1247. //
  1248. // Group Policy does not run on personal
  1249. //
  1250. OSVERSIONINFOEXW version;
  1251. version.dwOSVersionInfoSize = sizeof(version);
  1252. if ( !GetVersionEx( (LPOSVERSIONINFO) &version ) )
  1253. {
  1254. return ERROR_SUCCESS;
  1255. }
  1256. else
  1257. {
  1258. if ( ( version.wSuiteMask & VER_SUITE_PERSONAL ) != 0 )
  1259. {
  1260. return ERROR_SUCCESS;
  1261. }
  1262. }
  1263. if (!ApplySystemPolicy((SP_FLAG_APPLY_MACHINE_POLICY | SP_FLAG_APPLY_USER_POLICY),
  1264. lpProfile->hTokenUser, lpProfile->hKeyCurrentUser,
  1265. lpProfile->lpUserName, lpProfile->lpPolicyPath,
  1266. lpProfile->lpServerName)) {
  1267. DebugMsg((DM_WARNING, TEXT("LoadUserProfile: ApplySystemPolicy returned FALSE")));
  1268. }
  1269. }
  1270. //
  1271. // Save the outgoing parameters
  1272. //
  1273. lpProfileInfo->hProfile = (HANDLE) lpProfile->hKeyCurrentUser;
  1274. //
  1275. // Success!
  1276. //
  1277. bResult = TRUE;
  1278. Exit:
  1279. if (bCSCBypassed) {
  1280. CancelCSCBypassedConnection(lpProfile->hTokenUser, cDrive);
  1281. }
  1282. if(bInCS) {
  1283. cSyncMgr.LeaveLock(SidString);
  1284. }
  1285. if(SidString) {
  1286. DeleteSidString(SidString);
  1287. }
  1288. //
  1289. // Free the structure
  1290. //
  1291. if (lpProfile) {
  1292. if (lpProfile->lpUserName) {
  1293. LocalFree (lpProfile->lpUserName);
  1294. }
  1295. if (lpProfile->lpDefaultProfile) {
  1296. LocalFree (lpProfile->lpDefaultProfile);
  1297. }
  1298. if (lpProfile->lpProfilePath) {
  1299. LocalFree (lpProfile->lpProfilePath);
  1300. }
  1301. if (lpProfile->lpServerName) {
  1302. LocalFree (lpProfile->lpServerName);
  1303. }
  1304. if (lpProfile->lpPolicyPath) {
  1305. LocalFree (lpProfile->lpPolicyPath);
  1306. }
  1307. if (lpProfile->lpLocalProfile) {
  1308. LocalFree (lpProfile->lpLocalProfile);
  1309. }
  1310. if (lpProfile->lpRoamingProfile) {
  1311. LocalFree (lpProfile->lpRoamingProfile);
  1312. }
  1313. if (lpProfile->lpExclusionList) {
  1314. LocalFree (lpProfile->lpExclusionList);
  1315. }
  1316. //
  1317. // Caller will release these handles.
  1318. //
  1319. lpProfile->hTokenClient = NULL;
  1320. lpProfile->hTokenUser = NULL;
  1321. LocalFree (lpProfile);
  1322. }
  1323. //
  1324. // Free the cloned environment block.
  1325. //
  1326. if (pEnv) {
  1327. RtlDestroyEnvironment(pEnv);
  1328. }
  1329. //
  1330. // Revert to ourselves
  1331. //
  1332. if(hTokenClient && hTokenClient != INVALID_HANDLE_VALUE) {
  1333. RevertToUser(&hTmpToken);
  1334. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Reverted back to user <%08x>"), hTmpToken));
  1335. }
  1336. //
  1337. // Verbose output
  1338. //
  1339. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfile: Leaving with a value of %d."), bResult));
  1340. DebugMsg((DM_VERBOSE, TEXT("=========================================================")));
  1341. SetLastError(dwErr);
  1342. return bResult;
  1343. }
  1344. //*************************************************************
  1345. //
  1346. // CUserProfile::UnloadUserProfileP()
  1347. //
  1348. // Purpose: Unloads the user's profile.
  1349. //
  1350. // Parameters: hTokenClient - The client who's trying to load
  1351. // the user's profile.
  1352. // hTokenUser - User's token
  1353. // hProfile - Profile handle
  1354. //
  1355. // Return: TRUE if successful
  1356. // FALSE if an error occurs
  1357. //
  1358. // Comments:
  1359. //
  1360. // History: Date Author Comment
  1361. // 6/7/95 ericflo Created
  1362. // 6/27/00 weiruc Modified to be a private function
  1363. // called by UnloadUserProfile to do
  1364. // the actual work.
  1365. //
  1366. //*************************************************************
  1367. BOOL CUserProfile::UnloadUserProfileP(HANDLE hTokenClient, HANDLE hTokenUser, HKEY hProfile, LPTSTR lpRPCEndPoint)
  1368. {
  1369. LPPROFILE lpProfile=NULL;
  1370. LPTSTR lpSidString = NULL, lpEnd, SidStringTemp = NULL;
  1371. LONG err, IgnoreError, lResult;
  1372. BOOL bProfileCopied = FALSE, bRetVal = FALSE, bDeleteCache, bRoaming = FALSE;
  1373. HKEY hKey;
  1374. DWORD dwSize, dwType, dwDisp;
  1375. LPTSTR szExcludeList1 = NULL;
  1376. LPTSTR szExcludeList2 = NULL;
  1377. LPTSTR szExcludeList = NULL;
  1378. LPTSTR szBuffer = NULL;
  1379. DWORD dwFlags, dwRef = 0;
  1380. HANDLE hOldToken = NULL;
  1381. HANDLE hTmpToken = NULL;
  1382. DWORD dwErr=0, dwErr1 = ERROR_SUCCESS, dwCSCErr; // dwErr1 is what gets set in SetLastError()
  1383. LPTSTR szErr = NULL;
  1384. LPTSTR szKeyName = NULL;
  1385. DWORD dwCopyTmpHive = 0;
  1386. DWORD dwWatchHiveFlags = 0;
  1387. LPTSTR tszTmpHiveFile = NULL;
  1388. BOOL bUnloadHiveSucceeded = TRUE;
  1389. BOOL bInCS = FALSE;
  1390. BOOL bCSCBypassed = FALSE;
  1391. LPTSTR lpCscBypassedPath = NULL;
  1392. TCHAR cDrive;
  1393. //
  1394. // Verbose output
  1395. //
  1396. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Entering, hProfile = <0x%x>"), hProfile));
  1397. //
  1398. // Run under the client's identity rather than winlogon's.
  1399. //
  1400. if(hTokenClient && hTokenClient != INVALID_HANDLE_VALUE) {
  1401. if(!ImpersonateUser(hTokenClient, &hTmpToken)) {
  1402. dwErr1 = GetLastError();
  1403. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: ImpersonateUser <%08x> failed with %08x"), hTokenClient, dwErr1));
  1404. RegCloseKey((HKEY)hProfile);
  1405. goto Exit;
  1406. }
  1407. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: ImpersonateUser <%08x>, old token is <%08x>"), hTokenClient, hTmpToken));
  1408. }
  1409. //
  1410. // Get the Sid string for the current user
  1411. //
  1412. lpSidString = GetProfileSidString(hTokenUser);
  1413. if (!lpSidString) {
  1414. dwErr1 = GetLastError();
  1415. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to get sid string for user %08x"), dwErr1));
  1416. RegCloseKey((HKEY)hProfile);
  1417. goto Exit;
  1418. }
  1419. //
  1420. // Load profile information
  1421. //
  1422. lpProfile = LoadProfileInfo(hTokenClient, hTokenUser, (HKEY)hProfile);
  1423. if (!lpProfile) {
  1424. dwErr1 = GetLastError();
  1425. RegCloseKey((HKEY)hProfile);
  1426. goto Exit;
  1427. }
  1428. //
  1429. // Get the user's sid in string form
  1430. //
  1431. SidStringTemp = GetSidString(hTokenUser);
  1432. if (!SidStringTemp) {
  1433. dwErr1 = GetLastError();
  1434. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to get sid string for user")));
  1435. RegCloseKey(lpProfile->hKeyCurrentUser);
  1436. goto Exit;
  1437. }
  1438. //
  1439. // Allocate memory for Local variables to avoid stack overflow
  1440. //
  1441. szKeyName = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1442. if (!szKeyName) {
  1443. dwErr1 = GetLastError();
  1444. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1445. goto Exit;
  1446. }
  1447. szErr = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1448. if (!szErr) {
  1449. dwErr1 = GetLastError();
  1450. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1451. goto Exit;
  1452. }
  1453. szBuffer = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1454. if (!szBuffer) {
  1455. dwErr1 = GetLastError();
  1456. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1457. goto Exit;
  1458. }
  1459. // Store the actual roaming profile path before mapping it to drive
  1460. lpProfile->lpProfilePath = lpProfile->lpRoamingProfile;
  1461. //
  1462. // Try to bypass CSC to avoid conflicts in syncing files between roaming share & local profile
  1463. //
  1464. if (IsUNCPath(lpProfile->lpRoamingProfile)) {
  1465. if ((dwCSCErr = AbleToBypassCSC(hTokenUser, lpProfile->lpRoamingProfile, &lpCscBypassedPath, &cDrive)) == ERROR_SUCCESS) {
  1466. bCSCBypassed = TRUE;
  1467. lpProfile->lpRoamingProfile = lpCscBypassedPath;
  1468. DebugMsg((DM_VERBOSE, TEXT("UnLoadUserProfileP: CSC bypassed.")));
  1469. }
  1470. else {
  1471. if (dwCSCErr == WN_BAD_LOCALNAME || dwCSCErr == WN_ALREADY_CONNECTED || dwCSCErr == ERROR_BAD_PROVIDER) {
  1472. DebugMsg((DM_VERBOSE, TEXT("UnLoadUserProfileP: CSC bypassed failed. Profile path %s"), lpProfile->lpRoamingProfile));
  1473. }
  1474. else {
  1475. // Share is not up. So we do not need to do any further check
  1476. lpProfile->lpRoamingProfile = NULL;
  1477. DebugMsg((DM_VERBOSE, TEXT("UnLoadUserProfileP: CSC bypassed failed. Ignoring Roaming profile path")));
  1478. }
  1479. }
  1480. }
  1481. //
  1482. // Check for a list of directories to exclude both user preferences
  1483. // and user policy
  1484. //
  1485. szExcludeList1 = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1486. if (!szExcludeList1) {
  1487. dwErr1 = GetLastError();
  1488. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1489. goto Exit;
  1490. }
  1491. szExcludeList2 = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1492. if (!szExcludeList2) {
  1493. dwErr1 = GetLastError();
  1494. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1495. goto Exit;
  1496. }
  1497. szExcludeList = (LPTSTR)LocalAlloc(LPTR, 2*MAX_PATH*sizeof(TCHAR));
  1498. if (!szExcludeList) {
  1499. dwErr1 = GetLastError();
  1500. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1501. goto Exit;
  1502. }
  1503. szExcludeList1[0] = TEXT('\0');
  1504. if (RegOpenKeyEx (lpProfile->hKeyCurrentUser,
  1505. WINLOGON_KEY,
  1506. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  1507. dwSize = MAX_PATH*sizeof(TCHAR);
  1508. RegQueryValueEx (hKey,
  1509. TEXT("ExcludeProfileDirs"),
  1510. NULL,
  1511. &dwType,
  1512. (LPBYTE) szExcludeList1,
  1513. &dwSize);
  1514. RegCloseKey (hKey);
  1515. }
  1516. szExcludeList2[0] = TEXT('\0');
  1517. if (RegOpenKeyEx (lpProfile->hKeyCurrentUser,
  1518. SYSTEM_POLICIES_KEY,
  1519. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  1520. dwSize = MAX_PATH*sizeof(TCHAR);
  1521. RegQueryValueEx (hKey,
  1522. TEXT("ExcludeProfileDirs"),
  1523. NULL,
  1524. &dwType,
  1525. (LPBYTE) szExcludeList2,
  1526. &dwSize);
  1527. RegCloseKey (hKey);
  1528. }
  1529. //
  1530. // Merge the user preferences and policy together
  1531. //
  1532. szExcludeList[0] = TEXT('\0');
  1533. if (szExcludeList1[0] != TEXT('\0')) {
  1534. CheckSemicolon(szExcludeList1);
  1535. lstrcpy (szExcludeList, szExcludeList1);
  1536. }
  1537. if (szExcludeList2[0] != TEXT('\0')) {
  1538. lstrcat (szExcludeList, szExcludeList2);
  1539. }
  1540. //
  1541. // Check if the cached copy of the profile should be deleted
  1542. //
  1543. bDeleteCache = IsCacheDeleted();
  1544. //
  1545. // Enter the critical section.
  1546. //
  1547. if(!cSyncMgr.EnterLock(SidStringTemp, lpRPCEndPoint)) {
  1548. dwErr1 = GetLastError();
  1549. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP:: Failed to get the user profile lock %08x"), dwErr1));
  1550. goto Exit;
  1551. }
  1552. bInCS = TRUE;
  1553. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Wait succeeded. In critical section.")));
  1554. //
  1555. // Flush out the profile which will also sync the log.
  1556. //
  1557. err = RegFlushKey(lpProfile->hKeyCurrentUser);
  1558. if (err != ERROR_SUCCESS) {
  1559. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to flush the current user key, error = %d"), err));
  1560. }
  1561. //
  1562. // Close the current user key that was opened in LoadUserProfile.
  1563. //
  1564. err = RegCloseKey(lpProfile->hKeyCurrentUser);
  1565. if (err != ERROR_SUCCESS) {
  1566. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to close the current user key, error = %d"), err));
  1567. }
  1568. dwRef = DecrementProfileRefCount(lpProfile);
  1569. if (dwRef != 0) {
  1570. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Didn't unload user profile, Ref Count is %d"), dwRef));
  1571. bRetVal = TRUE;
  1572. goto Exit;
  1573. }
  1574. //
  1575. // Unload the user profile
  1576. //
  1577. err = MyRegUnLoadKey(HKEY_USERS, lpSidString);
  1578. if (!err) {
  1579. if((dwErr1 = GetLastError()) == ERROR_ACCESS_DENIED) {
  1580. //
  1581. // We failed to unload the hive due to leaked reg keys.
  1582. //
  1583. dwWatchHiveFlags |= WHRC_UNLOAD_HIVE;
  1584. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  1585. //
  1586. // Call Special Registry APIs to dump handles
  1587. // only if it is not called through Lite_load
  1588. // there are known problems with liteLoad loading because
  1589. // of which eventlog can get full during stress
  1590. //
  1591. lstrcpy(szKeyName, TEXT("\\Registry\\User\\"));
  1592. lstrcat(szKeyName, lpSidString);
  1593. DumpOpenRegistryHandle(szKeyName);
  1594. }
  1595. }
  1596. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Didn't unload user profile <err = %d>"), GetLastError()));
  1597. //
  1598. // Only in the case of reg leak do we want to call WatchHiveRefCount.
  1599. // So use this flag to tell later code the the hive failed to
  1600. // unload, no matter what the reason.
  1601. //
  1602. bUnloadHiveSucceeded = FALSE;
  1603. } else {
  1604. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Succesfully unloaded profile")));
  1605. }
  1606. //
  1607. // Unload HKCU
  1608. //
  1609. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  1610. err = UnloadClasses(lpSidString);
  1611. if (!err) {
  1612. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Didn't unload user classes.")));
  1613. if((dwErr1 = GetLastError()) == ERROR_ACCESS_DENIED) {
  1614. //
  1615. // Call Special Registry APIs to dump handles
  1616. //
  1617. lstrcpy(szKeyName, TEXT("\\Registry\\User\\"));
  1618. lstrcat(szKeyName, lpSidString);
  1619. lstrcat(szKeyName, TEXT("_Classes"));
  1620. DumpOpenRegistryHandle(szKeyName);
  1621. ReportError(hTokenUser, PI_NOUI | EVENT_WARNING_TYPE, 0, EVENT_FAILED_CLASS_HIVE_UNLOAD);
  1622. dwWatchHiveFlags = dwWatchHiveFlags | WHRC_UNLOAD_CLASSESROOT;
  1623. }
  1624. bRetVal = TRUE;
  1625. } else {
  1626. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Successfully unloaded user classes")));
  1627. }
  1628. }
  1629. //
  1630. // Figure out if we need to do anything special in the event of registry
  1631. // key leak.
  1632. //
  1633. if(dwWatchHiveFlags != 0 || !bUnloadHiveSucceeded) {
  1634. tszTmpHiveFile = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  1635. if (!tszTmpHiveFile) {
  1636. dwErr1 = GetLastError();
  1637. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileP: Out of memory")));
  1638. goto Exit;
  1639. }
  1640. dwErr = HandleRegKeyLeak(lpSidString,
  1641. lpProfile,
  1642. bUnloadHiveSucceeded,
  1643. &dwWatchHiveFlags,
  1644. &dwCopyTmpHive,
  1645. tszTmpHiveFile);
  1646. //
  1647. // If registry leak is handled successfully, the last error code should
  1648. // be ERROR_SUCCESS. Otherwise, it should be whatever MyRegUnLoadKey
  1649. // returned, which is in dwErr1.
  1650. //
  1651. if(dwErr == ERROR_SUCCESS) {
  1652. dwErr1 = dwErr;
  1653. }
  1654. }
  1655. //
  1656. // If this is a mandatory or a guest profile, unload it now,
  1657. // Guest profiles are always deleted so one guest can't see
  1658. // the profile of a previous guest. Only do this if the user's
  1659. // hive had been successfully unloaded.
  1660. //
  1661. if ((lpProfile->dwInternalFlags & PROFILE_MANDATORY) ||
  1662. (lpProfile->dwInternalFlags & PROFILE_READONLY) ||
  1663. (lpProfile->dwInternalFlags & PROFILE_GUEST_USER)) {
  1664. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: flushing HKEY_USERS")));
  1665. IgnoreError = RegFlushKey(HKEY_USERS);
  1666. if (IgnoreError != ERROR_SUCCESS) {
  1667. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to flush HKEY_USERS, error = %d"), IgnoreError));
  1668. }
  1669. // Don't delete the guest account if machine is in workgroup
  1670. INT iRole;
  1671. if (bDeleteCache ||
  1672. ((lpProfile->dwInternalFlags & PROFILE_GUEST_USER) &&
  1673. GetMachineRole(&iRole) && (iRole != 0))) {
  1674. //
  1675. // Delete the profile, including all other user related stuff
  1676. //
  1677. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: deleting profile because it is a guest user or cache needs to be deleted")));
  1678. if (!DeleteProfile (lpSidString, NULL, NULL)) {
  1679. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: DeleteProfileDirectory returned false. Error = %d"), GetLastError()));
  1680. }
  1681. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Successfully deleted profile because it is a guest/mandatory user")));
  1682. }
  1683. if (err) {
  1684. bRetVal = TRUE;
  1685. }
  1686. if (lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) {
  1687. //
  1688. // Just delete the user profile, backup should never exist for mandatory profile
  1689. //
  1690. if (!DeleteProfileEx (lpSidString, lpProfile->lpLocalProfile, 0, HKEY_LOCAL_MACHINE, NULL)) {
  1691. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: DeleteProfileDirectory returned false (2). Error = %d"), GetLastError()));
  1692. }
  1693. }
  1694. goto Exit;
  1695. }
  1696. //
  1697. // Impersonate the user
  1698. //
  1699. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  1700. dwErr1 = GetLastError();
  1701. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to impersonate user")));
  1702. goto Exit;
  1703. }
  1704. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Impersonated user")));
  1705. //
  1706. // Copy local profileimage to remote profilepath
  1707. //
  1708. if ( ((lpProfile->dwInternalFlags & PROFILE_UPDATE_CENTRAL) ||
  1709. (lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL)) &&
  1710. !(lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) ) {
  1711. if ((lpProfile->dwUserPreference != USERINFO_LOCAL) &&
  1712. !(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
  1713. //
  1714. // Copy to the profile path
  1715. //
  1716. if (lpProfile->lpRoamingProfile && *lpProfile->lpRoamingProfile) {
  1717. BOOL bRoamDirectoryExist;
  1718. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Copying profile back to %s"),
  1719. lpProfile->lpRoamingProfile));
  1720. bRoaming = TRUE;
  1721. //
  1722. // Check roaming profile directory exist or not. If not exist, try to create it with proper acl's
  1723. //
  1724. bRoamDirectoryExist = TRUE;
  1725. if (GetFileAttributes(lpProfile->lpRoamingProfile) == -1) {
  1726. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Roaming profile directory does not exist.")));
  1727. //
  1728. // Check whether we need to give access to the admin on the RUP share
  1729. //
  1730. //
  1731. // Check for a roaming profile security preference
  1732. //
  1733. BOOL bAddAdminGroup = FALSE;
  1734. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  1735. &hKey) == ERROR_SUCCESS) {
  1736. dwSize = sizeof(bAddAdminGroup);
  1737. RegQueryValueEx(hKey, ADD_ADMIN_GROUP_TO_RUP, NULL, NULL,
  1738. (LPBYTE) &bAddAdminGroup, &dwSize);
  1739. RegCloseKey(hKey);
  1740. }
  1741. //
  1742. // Check for a roaming profile security policy
  1743. //
  1744. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ,
  1745. &hKey) == ERROR_SUCCESS) {
  1746. dwSize = sizeof(bAddAdminGroup);
  1747. RegQueryValueEx(hKey, ADD_ADMIN_GROUP_TO_RUP, NULL, NULL,
  1748. (LPBYTE) &bAddAdminGroup, &dwSize);
  1749. RegCloseKey(hKey);
  1750. }
  1751. if (!CreateSecureDirectory(lpProfile, lpProfile->lpRoamingProfile, NULL, !bAddAdminGroup) ) {
  1752. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: CreateSecureDirectory failed to create roaming profile directory.")));
  1753. bRoamDirectoryExist = FALSE;
  1754. bProfileCopied = FALSE;
  1755. }
  1756. lpProfile->dwInternalFlags |= PROFILE_NEW_CENTRAL; // Since we created a empty profile now
  1757. }
  1758. if (bRoamDirectoryExist) {
  1759. DWORD dwAttributes, dwStart, dwDelta;
  1760. //
  1761. // We have to call GetFileAttributes twice. The
  1762. // first call sets up the session so we can call it again and
  1763. // get accurate timing information for slow link detection.
  1764. //
  1765. dwAttributes = GetFileAttributes(lpProfile->lpProfilePath);
  1766. if (dwAttributes != -1) {
  1767. //
  1768. // if it is success, find out whether the profile is
  1769. // across a slow link.
  1770. //
  1771. dwStart = GetTickCount();
  1772. dwAttributes = GetFileAttributes(lpProfile->lpProfilePath);
  1773. dwDelta = GetTickCount() - dwStart;
  1774. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Tick Count = %d"), dwDelta));
  1775. CheckForSlowLink (lpProfile, dwDelta, lpProfile->lpProfilePath, FALSE);
  1776. if (lpProfile->dwInternalFlags & PROFILE_SLOW_LINK) {
  1777. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Profile is across a slow link. Do not sync roaming profile")));
  1778. }
  1779. }
  1780. }
  1781. if (!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
  1782. if (bRoamDirectoryExist) {
  1783. //
  1784. // Copy the profile
  1785. //
  1786. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  1787. dwFlags |= (lpProfile->dwFlags & (PI_LITELOAD | PI_HIDEPROFILE)) ? (CPD_SYSTEMFILES | CPD_SYSTEMDIRSONLY) :
  1788. (CPD_SYNCHRONIZE | CPD_NONENCRYPTEDONLY);
  1789. dwFlags |= CPD_USEDELREFTIME |
  1790. CPD_USEEXCLUSIONLIST | CPD_DELDESTEXCLUSIONS;
  1791. bProfileCopied = CopyProfileDirectoryEx (lpProfile->lpLocalProfile,
  1792. lpProfile->lpRoamingProfile,
  1793. dwFlags | dwCopyTmpHive,
  1794. &lpProfile->ftProfileLoad,
  1795. (szExcludeList[0] != TEXT('\0')) ?
  1796. szExcludeList : NULL);
  1797. }
  1798. //
  1799. // Save the exclusion list we used for the profile copy
  1800. //
  1801. if (bProfileCopied) {
  1802. // save it on the roaming profile.
  1803. lstrcpy (szBuffer, lpProfile->lpRoamingProfile);
  1804. lpEnd = CheckSlash (szBuffer);
  1805. lstrcpy (lpEnd, c_szNTUserIni);
  1806. bProfileCopied = WritePrivateProfileString (PROFILE_GENERAL_SECTION,
  1807. PROFILE_EXCLUSION_LIST,
  1808. (szExcludeList[0] != TEXT('\0')) ?
  1809. szExcludeList : NULL,
  1810. szBuffer);
  1811. if (lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL) {
  1812. bProfileCopied = WritePrivateProfileString (PROFILE_LOAD_TYPE,
  1813. PROFILE_LAST_UPLOAD_STATE,
  1814. (lpProfile->dwFlags & PI_LITELOAD) ?
  1815. PARTIAL_PROFILE : COMPLETE_PROFILE,
  1816. szBuffer);
  1817. }
  1818. else if (IsPartialRoamingProfile(lpProfile)) {
  1819. bProfileCopied = WritePrivateProfileString (PROFILE_LOAD_TYPE,
  1820. PROFILE_LAST_UPLOAD_STATE,
  1821. (lpProfile->dwFlags & PI_LITELOAD) ?
  1822. PARTIAL_PROFILE : COMPLETE_PROFILE,
  1823. szBuffer);
  1824. }
  1825. if (!bProfileCopied) {
  1826. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to write to ntuser.ini on profile server with error 0x%x"), GetLastError()));
  1827. dwErr = GetLastError();
  1828. }
  1829. else {
  1830. SetFileAttributes (szBuffer, FILE_ATTRIBUTE_HIDDEN);
  1831. }
  1832. }
  1833. else {
  1834. dwErr = GetLastError();
  1835. if (dwErr == ERROR_FILE_ENCRYPTED) {
  1836. ReportError(hTokenUser, lpProfile->dwFlags, 0, EVENT_PROFILEUPDATE_6002);
  1837. }
  1838. }
  1839. //
  1840. // Check return value
  1841. //
  1842. if (bProfileCopied) {
  1843. //
  1844. // The profile is copied, now we want to make sure the timestamp on
  1845. // both the remote profile and the local copy are the same, so we don't
  1846. // ask the user to update when it's not necessary. In the case we
  1847. // save the hive to a temporary file and
  1848. // upload from the tmp file rather than the actual hive file. Do not
  1849. // synchronize the profile time in this case because the hive file
  1850. // will still be in use and there's no point in setting time on the
  1851. // tmp hive file because it will be deleted after we upload it.
  1852. //
  1853. if(bUnloadHiveSucceeded) {
  1854. SetProfileTime(lpProfile);
  1855. }
  1856. } else {
  1857. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: CopyProfileDirectory returned FALSE for primary profile. Error = %d"), dwErr));
  1858. ReportError(hTokenUser, lpProfile->dwFlags, 1, EVENT_CENTRAL_UPDATE_FAILED, GetErrString(dwErr, szErr));
  1859. }
  1860. }
  1861. }
  1862. else {
  1863. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Network share not available.")));
  1864. ReportError(hTokenUser, lpProfile->dwFlags, 1, EVENT_CENTRAL_UPDATE_FAILED, GetErrString(dwCSCErr, szErr));
  1865. }
  1866. }
  1867. }
  1868. //
  1869. // if it is roaming, write only if copy succeeded otherwise write
  1870. //
  1871. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Writing local ini file")));
  1872. if (!bRoaming || bProfileCopied) {
  1873. //
  1874. // Mark the file with system bit before trying to write to it
  1875. //
  1876. SetNtUserIniAttributes(lpProfile->lpLocalProfile);
  1877. // save it locally
  1878. lstrcpy (szBuffer, (lpProfile->lpLocalProfile));
  1879. lpEnd = CheckSlash (szBuffer);
  1880. lstrcpy (lpEnd, c_szNTUserIni);
  1881. err = WritePrivateProfileString (PROFILE_GENERAL_SECTION,
  1882. PROFILE_EXCLUSION_LIST,
  1883. (szExcludeList[0] != TEXT('\0')) ?
  1884. szExcludeList : NULL,
  1885. szBuffer);
  1886. if (!err) {
  1887. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to write to ntuser.ini on client with error 0x%x"), GetLastError()));
  1888. dwErr = GetLastError();
  1889. }
  1890. }
  1891. if (!RevertToUser(&hOldToken)) {
  1892. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to revert to self")));
  1893. }
  1894. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Reverting to Self")));
  1895. //
  1896. // Save the profile unload time
  1897. //
  1898. if (bProfileCopied && !bDeleteCache && !(lpProfile->dwFlags & PI_LITELOAD) &&
  1899. !(lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED)) {
  1900. GetSystemTimeAsFileTime (&lpProfile->ftProfileUnload);
  1901. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfile: Got the System Time")));
  1902. lstrcpy(szBuffer, PROFILE_LIST_PATH);
  1903. lpEnd = CheckSlash (szBuffer);
  1904. lstrcpy(lpEnd, lpSidString);
  1905. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, 0, 0,
  1906. KEY_WRITE, NULL, &hKey, &dwDisp);
  1907. if (lResult == ERROR_SUCCESS) {
  1908. lResult = RegSetValueEx (hKey,
  1909. PROFILE_UNLOAD_TIME_LOW,
  1910. 0,
  1911. REG_DWORD,
  1912. (LPBYTE) &lpProfile->ftProfileUnload.dwLowDateTime,
  1913. sizeof(DWORD));
  1914. if (lResult != ERROR_SUCCESS) {
  1915. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to save low profile load time with error %d"), lResult));
  1916. }
  1917. lResult = RegSetValueEx (hKey,
  1918. PROFILE_UNLOAD_TIME_HIGH,
  1919. 0,
  1920. REG_DWORD,
  1921. (LPBYTE) &lpProfile->ftProfileUnload.dwHighDateTime,
  1922. sizeof(DWORD));
  1923. if (lResult != ERROR_SUCCESS) {
  1924. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: Failed to save high profile load time with error %d"), lResult));
  1925. }
  1926. RegCloseKey (hKey);
  1927. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Setting the unload Time")));
  1928. }
  1929. }
  1930. if (lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) {
  1931. DWORD dwDeleteFlags=0;
  1932. //
  1933. // Just delete the user profile
  1934. //
  1935. if (lpProfile->dwInternalFlags & PROFILE_BACKUP_EXISTS) {
  1936. dwDeleteFlags |= DP_BACKUPEXISTS;
  1937. }
  1938. if (!DeleteProfileEx (lpSidString, lpProfile->lpLocalProfile, dwDeleteFlags, HKEY_LOCAL_MACHINE, NULL)) {
  1939. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: DeleteProfileDirectory returned false (2). Error = %d"), GetLastError()));
  1940. }
  1941. }
  1942. if (bUnloadHiveSucceeded && bRoaming && bProfileCopied && bDeleteCache) {
  1943. //
  1944. // Delete the profile and all the related stuff
  1945. //
  1946. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Deleting the cached profile")));
  1947. if (!DeleteProfile (lpSidString, NULL, NULL)) {
  1948. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileP: DeleteProfileDirectory returned false (2). Error = %d"), GetLastError()));
  1949. }
  1950. }
  1951. if(!(dwWatchHiveFlags & WHRC_UNLOAD_HIVE)) {
  1952. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: exitting and cleaning up")));
  1953. bRetVal = TRUE;
  1954. }
  1955. else {
  1956. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: exitting without cleaning up due to hive unloading failure")));
  1957. }
  1958. Exit:
  1959. if(hTokenClient) {
  1960. //
  1961. // Revert to ourselves.
  1962. //
  1963. RevertToUser(&hTmpToken);
  1964. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Reverted back to user <%08x>"), hTmpToken));
  1965. }
  1966. //
  1967. // Leave the critical section.
  1968. //
  1969. if(bInCS) {
  1970. cSyncMgr.LeaveLock(SidStringTemp);
  1971. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Leave critical section.")));
  1972. }
  1973. //
  1974. // Delete the tmp hive file.
  1975. //
  1976. if (dwCopyTmpHive & CPD_USETMPHIVEFILE) {
  1977. DeleteFile(tszTmpHiveFile);
  1978. }
  1979. if (bCSCBypassed) {
  1980. CancelCSCBypassedConnection(hTokenUser, cDrive);
  1981. }
  1982. if(SidStringTemp) {
  1983. DeleteSidString(SidStringTemp);
  1984. }
  1985. if (lpSidString) {
  1986. DeleteSidString(lpSidString);
  1987. }
  1988. if (lpProfile) {
  1989. if (lpProfile->lpLocalProfile) {
  1990. LocalFree (lpProfile->lpLocalProfile);
  1991. }
  1992. if (lpProfile->lpRoamingProfile) {
  1993. if (lpProfile->lpProfilePath && (lpProfile->lpProfilePath != lpProfile->lpRoamingProfile)) {
  1994. LocalFree (lpProfile->lpProfilePath);
  1995. }
  1996. LocalFree (lpProfile->lpRoamingProfile);
  1997. lpProfile->lpProfilePath = NULL;
  1998. }
  1999. if (lpProfile->lpProfilePath) {
  2000. LocalFree(lpProfile->lpProfilePath);
  2001. }
  2002. LocalFree (lpProfile);
  2003. }
  2004. if (szExcludeList1) {
  2005. LocalFree(szExcludeList1);
  2006. }
  2007. if (szExcludeList2) {
  2008. LocalFree(szExcludeList2);
  2009. }
  2010. if (szExcludeList) {
  2011. LocalFree(szExcludeList);
  2012. }
  2013. if (tszTmpHiveFile) {
  2014. LocalFree(tszTmpHiveFile);
  2015. }
  2016. if (szKeyName) {
  2017. LocalFree(szKeyName);
  2018. }
  2019. if (szErr) {
  2020. LocalFree(szErr);
  2021. }
  2022. if (szBuffer) {
  2023. LocalFree(szBuffer);
  2024. }
  2025. //
  2026. // Verbose output
  2027. //
  2028. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileP: Leaving with a return value of %d"), bRetVal));
  2029. SetLastError(dwErr1);
  2030. return bRetVal;
  2031. }
  2032. //*************************************************************
  2033. //
  2034. // CUserProfile::EnterUserProfileLockLocal()
  2035. //
  2036. // Purpose:
  2037. //
  2038. // Get the user profile lock (for winlogon only, other processes use
  2039. // EnterUserProfileLockRemote). This is just a wrapper for
  2040. // CSyncManager::EnterLock.
  2041. //
  2042. // Parameters:
  2043. //
  2044. // pSid - User's sid string
  2045. //
  2046. // Return:
  2047. //
  2048. // TRUE/FALSE
  2049. //
  2050. // History: Date Author Comment
  2051. // 5/15/00 weiruc Created
  2052. //
  2053. //*************************************************************
  2054. BOOL CUserProfile::EnterUserProfileLockLocal(LPTSTR pSid)
  2055. {
  2056. return cSyncMgr.EnterLock(pSid, NULL);
  2057. }
  2058. //*************************************************************
  2059. //
  2060. // CUserProfile::LeaveUserProfileLockLocal()
  2061. //
  2062. // Purpose:
  2063. //
  2064. // Release the user profile mutex (winlogon only. Remote processes call
  2065. // LeaveUserProfileLockRemote().
  2066. //
  2067. // Parameters:
  2068. //
  2069. // pSid - User's sid string
  2070. //
  2071. // Return:
  2072. //
  2073. // TRUE/FALSE
  2074. //
  2075. // Comments:
  2076. //
  2077. // History: Date Author Comment
  2078. // 8/11/00 weiruc Created
  2079. //
  2080. //*************************************************************
  2081. BOOL CUserProfile::LeaveUserProfileLockLocal(LPTSTR pSid)
  2082. {
  2083. return cSyncMgr.LeaveLock(pSid);
  2084. }
  2085. //*************************************************************
  2086. //
  2087. // CUserProfile::GetRPCEndPoint()
  2088. //
  2089. // Purpose:
  2090. //
  2091. // Returns the rpc end point associated with client registered
  2092. // interface
  2093. //
  2094. // Parameters:
  2095. //
  2096. // pSid - User's sid string
  2097. //
  2098. // Return:
  2099. //
  2100. // LPTSTR
  2101. //
  2102. // Comments:
  2103. //
  2104. // History: Date Author Comment
  2105. // 10/25/00 santanuc Created
  2106. //
  2107. //*************************************************************
  2108. LPTSTR CUserProfile::GetRPCEndPoint(LPTSTR pSid)
  2109. {
  2110. return cSyncMgr.GetRPCEndPoint(pSid);
  2111. }
  2112. //*************************************************************
  2113. //
  2114. // DropClientContext()
  2115. //
  2116. // Purpose: Allows the caller to drop off it's own token.
  2117. //
  2118. // Parameters: hBindHandle - explicit binding handle
  2119. // lpProfileInfo - Profile Information
  2120. // ppfContext - server context
  2121. //
  2122. //
  2123. // Return: DWORD
  2124. // ERROR_SUCCESS - If everything ok
  2125. //
  2126. // Comments:
  2127. //
  2128. // History: Date Author Comment
  2129. // 10/24/00 santanuc Created
  2130. //
  2131. //*************************************************************
  2132. DWORD DropClientContext(IN handle_t hBindHandle, IN LPPROFILEINFO lpProfileInfo, OUT PPCONTEXT_HANDLE pphContext)
  2133. {
  2134. LPPROFILEINFO pProfileInfoCopy = NULL;
  2135. HANDLE hClientToken = NULL;
  2136. PCLIENTINFO pClientInfo = NULL;
  2137. RPC_STATUS status;
  2138. DWORD dwErr = ERROR_ACCESS_DENIED;
  2139. //
  2140. // Initialize the debug flags.
  2141. //
  2142. InitDebugSupport( FALSE );
  2143. if (!pphContext) {
  2144. dwErr = ERROR_INVALID_PARAMETER;
  2145. DebugMsg((DM_WARNING, TEXT("DropClientContext: NULL context %d"), dwErr));
  2146. goto Exit;
  2147. }
  2148. //
  2149. // Make a copy of the PROFILEINFO structure the user passed in.
  2150. //
  2151. if (lpProfileInfo) {
  2152. if(!(pProfileInfoCopy = CopyProfileInfo(lpProfileInfo))) {
  2153. dwErr = GetLastError();
  2154. DebugMsg((DM_WARNING, TEXT("DropClientContext: CopyProfileInfo failed with %d"), dwErr));
  2155. goto Exit;
  2156. }
  2157. }
  2158. //
  2159. // Impersonate the client to get it's token.
  2160. //
  2161. if((status = RpcImpersonateClient(0)) != RPC_S_OK) {
  2162. DebugMsg((DM_WARNING, TEXT("DropClientContext: RpcImpersonateClient failed with %ld"), status));
  2163. dwErr = status;
  2164. goto Exit;
  2165. }
  2166. //
  2167. // Get the client's token.
  2168. //
  2169. if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hClientToken)) {
  2170. dwErr = GetLastError();
  2171. DebugMsg((DM_WARNING, TEXT("DropClientContext: OpenThreadToken failed with %d"), dwErr));
  2172. RpcRevertToSelf();
  2173. goto Exit;
  2174. }
  2175. RpcRevertToSelf();
  2176. DebugMsg((DM_VERBOSE, TEXT("DropClientContext: Got client token")));
  2177. //
  2178. // Make the user's load profile object.
  2179. //
  2180. pClientInfo = (PCLIENTINFO)MIDL_user_allocate(sizeof(CLIENTINFO));
  2181. if(!pClientInfo) {
  2182. dwErr = ERROR_OUTOFMEMORY;
  2183. DebugMsg((DM_WARNING, TEXT("DropClientContext: new failed")));
  2184. goto Exit;
  2185. }
  2186. pClientInfo->hClientToken = hClientToken;
  2187. pClientInfo->pProfileInfo = pProfileInfoCopy;
  2188. *pphContext = (PCONTEXT_HANDLE)pClientInfo;
  2189. DebugMsg((DM_VERBOSE, TEXT("DropClientContext: load profile object successfully made")));
  2190. hClientToken = NULL;
  2191. pProfileInfoCopy = NULL;
  2192. dwErr = ERROR_SUCCESS;
  2193. Exit:
  2194. if(hClientToken) {
  2195. CloseHandle(hClientToken);
  2196. }
  2197. if(pProfileInfoCopy) {
  2198. DeleteProfileInfo(pProfileInfoCopy);
  2199. }
  2200. DebugMsg((DM_VERBOSE, TEXT("DropClientContext: Returning %d"), dwErr));
  2201. return dwErr;
  2202. }
  2203. //*************************************************************
  2204. //
  2205. // ReleaseClientContext()
  2206. //
  2207. // Purpose: Release the client's context handle
  2208. //
  2209. // Parameters: hBindHandle - explicit binding handle
  2210. // ppfContext - server context
  2211. //
  2212. // Return: void
  2213. //
  2214. // Comments:
  2215. //
  2216. // History: Date Author Comment
  2217. // 10/24/00 santanuc Created
  2218. //
  2219. //*************************************************************
  2220. void ReleaseClientContext(IN handle_t hBindHandle, IN OUT PPCONTEXT_HANDLE pphContext)
  2221. {
  2222. PCLIENTINFO pClientInfo;
  2223. DebugMsg((DM_VERBOSE, TEXT("ReleaseClientContext: Releasing context")));
  2224. ReleaseClientContext_s(pphContext);
  2225. }
  2226. //
  2227. // This function also called from server rundown routine
  2228. //
  2229. void ReleaseClientContext_s(PPCONTEXT_HANDLE pphContext)
  2230. {
  2231. PCLIENTINFO pClientInfo;
  2232. DebugMsg((DM_VERBOSE, TEXT("ReleaseClientContext_s: Releasing context")));
  2233. if (*pphContext) {
  2234. pClientInfo = (PCLIENTINFO)*pphContext;
  2235. CloseHandle(pClientInfo->hClientToken);
  2236. DeleteProfileInfo(pClientInfo->pProfileInfo);
  2237. MIDL_user_free(pClientInfo);
  2238. *pphContext = NULL;
  2239. }
  2240. }
  2241. //*************************************************************
  2242. //
  2243. // EnterUserProfileLockRemote()
  2244. //
  2245. // Get the lock for loading/unloading a user's profile.
  2246. //
  2247. // Return value:
  2248. //
  2249. // HRESULT
  2250. //
  2251. // History:
  2252. //
  2253. // Created weiruc 6/16/2000
  2254. //
  2255. //*************************************************************
  2256. DWORD EnterUserProfileLockRemote(IN handle_t hBindHandle, IN LPTSTR pSid)
  2257. {
  2258. DWORD dwErr = ERROR_ACCESS_DENIED;
  2259. RPC_STATUS status;
  2260. HANDLE hToken = NULL;
  2261. //
  2262. // Impersonate the client to get the user's token.
  2263. //
  2264. if((status = RpcImpersonateClient(0)) != RPC_S_OK) {
  2265. DebugMsg((DM_WARNING, TEXT("CUserProfile::EnterUserProfileLockRemote: CoImpersonateClient failed with %ld"), status));
  2266. dwErr = status;
  2267. goto Exit;
  2268. }
  2269. if(!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ, TRUE, &hToken)) {
  2270. dwErr = GetLastError();
  2271. DebugMsg((DM_WARNING, TEXT("CUserProfile::EnterUserProfileLockRemote: OpenThreadToken failed with %d"), dwErr));
  2272. RpcRevertToSelf();
  2273. goto Exit;
  2274. }
  2275. RpcRevertToSelf();
  2276. //
  2277. // Only admin users are allowed to lock a user's profile from being loaded/unloaded.
  2278. //
  2279. if(!IsUserAnAdminMember(hToken)) {
  2280. dwErr = ERROR_ACCESS_DENIED;
  2281. DebugMsg((DM_WARNING, TEXT("CUserProfile::EnterUserProfileLockRemote: Non-admin user!!!")));
  2282. goto Exit;
  2283. }
  2284. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::EnterUserProfileLockRemote: Locking user %s"), pSid));
  2285. if(!cUserProfileManager.EnterUserProfileLockLocal(pSid)) {
  2286. dwErr = GetLastError();
  2287. DebugMsg((DM_WARNING, TEXT("CUserProfile::EnterUserProfileLockRemote: Failed with %d"), dwErr));
  2288. goto Exit;
  2289. }
  2290. dwErr = ERROR_SUCCESS;
  2291. Exit:
  2292. if(hToken) {
  2293. CloseHandle(hToken);
  2294. }
  2295. return dwErr;
  2296. }
  2297. //*************************************************************
  2298. //
  2299. // LeaveUserProfileLockRemote()
  2300. //
  2301. // Release the lock for loading/unloading a user's profile.
  2302. //
  2303. // Return value:
  2304. //
  2305. // HRESULT
  2306. //
  2307. // History:
  2308. //
  2309. // Created weiruc 6/16/2000
  2310. //
  2311. //*************************************************************
  2312. DWORD LeaveUserProfileLockRemote(IN handle_t hBindHandle, IN LPTSTR pSid)
  2313. {
  2314. HANDLE hToken = NULL;
  2315. DWORD dwErr = ERROR_ACCESS_DENIED;
  2316. RPC_STATUS status;
  2317. //
  2318. // Impersonate the client to get the user's token.
  2319. //
  2320. if((status = RpcImpersonateClient(0)) != RPC_S_OK) {
  2321. DebugMsg((DM_WARNING, TEXT("CUserProfile::LeaveUserProfileLockRemote: CoImpersonateClient failed with %ld"), status));
  2322. dwErr = status;
  2323. goto Exit;
  2324. }
  2325. if(!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ, TRUE, &hToken)) {
  2326. dwErr = GetLastError();
  2327. DebugMsg((DM_WARNING, TEXT("CUserProfile::LeaveUserProfileLockRemote: OpenThreadToken failed with %d"), dwErr));
  2328. RpcRevertToSelf();
  2329. goto Exit;
  2330. }
  2331. RpcRevertToSelf();
  2332. //
  2333. // Only admin users are allowed to lock a user's profile from being loaded/unloaded.
  2334. //
  2335. if(!IsUserAnAdminMember(hToken)) {
  2336. dwErr = ERROR_ACCESS_DENIED;
  2337. DebugMsg((DM_WARNING, TEXT("CUserProfile::LeaveUserProfileLockRemote: Non-admin user!!!")));
  2338. goto Exit;
  2339. }
  2340. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::LeaveUserProfileLockRemote: Unlocking user %s"), pSid));
  2341. if(!cUserProfileManager.LeaveUserProfileLockLocal(pSid)) {
  2342. dwErr = GetLastError();
  2343. DebugMsg((DM_WARNING, TEXT("CUserProfile::LeaveUserProfileLockRemote: Failed with %d"), dwErr));
  2344. goto Exit;
  2345. }
  2346. dwErr = ERROR_SUCCESS;
  2347. Exit:
  2348. if(hToken) {
  2349. CloseHandle(hToken);
  2350. }
  2351. return dwErr;
  2352. }
  2353. //*************************************************************
  2354. //
  2355. // CUserProfile::WorkerThreadMain
  2356. //
  2357. // Main function for the worker thread
  2358. //
  2359. // Parameters:
  2360. //
  2361. // pThreadMap the work queue for this thread
  2362. //
  2363. // Return value:
  2364. //
  2365. // Always returns ERROR_SUCCESS.
  2366. //
  2367. // History:
  2368. //
  2369. // Created weiruc 3/2/2000
  2370. //
  2371. //*************************************************************
  2372. DWORD CUserProfile::WorkerThreadMain(PMAP pThreadMap)
  2373. {
  2374. DWORD index;
  2375. HKEY hkProfileList = NULL;
  2376. long lResult;
  2377. BOOL bCleanUp;
  2378. LPTSTR ptszSid, lpTmp;
  2379. DebugMsg((DM_VERBOSE, TEXT("Entering CUserProfile::WorkerThreadMain")));
  2380. while(TRUE) {
  2381. bCleanUp = FALSE;
  2382. ptszSid = NULL;
  2383. index = WaitForMultipleObjects(pThreadMap->dwItems,
  2384. pThreadMap->rghEvents,
  2385. FALSE,
  2386. INFINITE);
  2387. index = index - WAIT_OBJECT_0;
  2388. EnterCriticalSection(&csMap);
  2389. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: In critical section")));
  2390. if(index > 0 && index < pThreadMap->dwItems) {
  2391. LPTSTR lpUserName;
  2392. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: WaitForMultipleObjects successful")));
  2393. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: hive %s unloaded"), pThreadMap->rgSids[index]));
  2394. lpUserName = GetUserNameFromSid(pThreadMap->rgSids[index]);
  2395. ReportError(NULL, PI_NOUI | EVENT_INFO_TYPE, 1, EVENT_HIVE_UNLOADED, lpUserName);
  2396. if (lpUserName != pThreadMap->rgSids[index]) {
  2397. LocalFree(lpUserName);
  2398. }
  2399. //
  2400. // Save the sid and Delete the work item from the map and the hash
  2401. // table.
  2402. //
  2403. ptszSid = pThreadMap->GetSid(index);
  2404. pThreadMap->Delete(index);
  2405. cTable.HashDelete(ptszSid);
  2406. // Convert Sid_Classes entry to Sid as CleanupUserProfile takes only Sid
  2407. lpTmp = ptszSid;
  2408. if (lpTmp) {
  2409. while (*lpTmp && (*lpTmp != TEXT('_')))
  2410. lpTmp++;
  2411. if (*lpTmp) {
  2412. *lpTmp = TEXT('\0');
  2413. }
  2414. }
  2415. //
  2416. // Set the flag to clean up here because we want to do it after
  2417. // we leave the critical section.
  2418. //
  2419. bCleanUp = TRUE;
  2420. } // if waken up because a hive is unloaded
  2421. //
  2422. // Check to see if the map is empty. If it is, delete the map.
  2423. //
  2424. if(pThreadMap->IsEmpty()) {
  2425. PMAP pTmpMap = pMap;
  2426. //
  2427. // We always have at least 1 item left: the thread event, So now
  2428. // we know we don't have any work item anymore. Delete pThreadMap.
  2429. //
  2430. if(pThreadMap == pMap) {
  2431. // pThreadMap is at the beginning of the list.
  2432. pMap = pThreadMap->pNext;
  2433. }
  2434. else {
  2435. for(pTmpMap = pMap; pTmpMap->pNext != pThreadMap; pTmpMap = pTmpMap->pNext);
  2436. pTmpMap->pNext = pThreadMap->pNext;
  2437. }
  2438. pThreadMap->pNext = NULL;
  2439. pThreadMap->Delete(0);
  2440. delete pThreadMap;
  2441. //
  2442. // Leave the critical section.
  2443. //
  2444. LeaveCriticalSection(&csMap);
  2445. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: Leave critical section")));
  2446. if(bCleanUp) {
  2447. //
  2448. // Clean up user's profile.
  2449. //
  2450. CleanupUserProfile(ptszSid, &hkProfileList);
  2451. LocalFree(ptszSid);
  2452. }
  2453. //
  2454. // Close the profile list key.
  2455. //
  2456. if(hkProfileList) {
  2457. RegCloseKey(hkProfileList);
  2458. hkProfileList = NULL;
  2459. }
  2460. //
  2461. // Exit the thread because we don't have any work items anymore.
  2462. //
  2463. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: No more work items, leave thread")));
  2464. return ERROR_SUCCESS;
  2465. } // if thread map is empty
  2466. //
  2467. // Leave the critical section.
  2468. //
  2469. LeaveCriticalSection(&csMap);
  2470. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: Leave critical section")));
  2471. if(bCleanUp) {
  2472. //
  2473. // Clean up user's profile.
  2474. //
  2475. CleanupUserProfile(ptszSid, &hkProfileList);
  2476. LocalFree(ptszSid);
  2477. }
  2478. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WorkerThreadMain: Back to waiting...")));
  2479. } // while
  2480. //
  2481. // Never executed.
  2482. //
  2483. return ERROR_SUCCESS;
  2484. }
  2485. //*************************************************************
  2486. //
  2487. // CUserProfile::WatchHiveRefCount
  2488. //
  2489. // Implementation of the interface IWatchHiveRefCount.
  2490. //
  2491. // Parameters:
  2492. //
  2493. // pctszSid the user's sid
  2494. // dwWHRCFlags indicate which hives to unload
  2495. //
  2496. // Return value:
  2497. //
  2498. // HRESULT error code.
  2499. //
  2500. // History:
  2501. //
  2502. // Created weiruc 5/4/2000
  2503. //
  2504. //*************************************************************
  2505. STDMETHODIMP CUserProfile::WatchHiveRefCount(LPCTSTR pSid, DWORD dwWHRCFlags)
  2506. {
  2507. LPTSTR pSidCopy = NULL;
  2508. NTSTATUS status;
  2509. OBJECT_ATTRIBUTES oa;
  2510. TCHAR tszHiveName[MAX_PATH], *pTmp;
  2511. UNICODE_STRING sHiveName;
  2512. BOOLEAN bWasEnabled;
  2513. HRESULT hres = S_OK, hres1;
  2514. HANDLE hEvent = INVALID_HANDLE_VALUE;
  2515. DWORD dwSidLen = lstrlen(pSid);
  2516. BOOL bInCriticalSection = FALSE;
  2517. DebugMsg((DM_VERBOSE, TEXT("Entering CUserProfile::WatchHiveRefCount: %s, %d"), pSid, dwWHRCFlags));
  2518. //
  2519. // Are we initialized?
  2520. //
  2521. if(!bInitialized) {
  2522. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount not initialized")));
  2523. return E_FAIL;
  2524. }
  2525. //
  2526. // parameter validation
  2527. //
  2528. if(dwSidLen >= sizeof(tszHiveName) / sizeof(TCHAR) - USER_KEY_PREFIX_LEN - USER_CLASSES_HIVE_SUFFIX_LEN ||
  2529. dwSidLen >= sizeof(tszHiveName) / sizeof(TCHAR) - USER_KEY_PREFIX_LEN ||
  2530. lstrcmpi(DEFAULT_HKU, pSid) == 0) {
  2531. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount: Invalid parameter")));
  2532. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2533. }
  2534. //
  2535. // Setup the hive name to be used by NtUnloadKeyEx.
  2536. //
  2537. lstrcpy(tszHiveName, USER_KEY_PREFIX);
  2538. pTmp = tszHiveName + USER_KEY_PREFIX_LEN;
  2539. lstrcpy(pTmp, pSid);
  2540. *pTmp = (TCHAR)_totupper(*pTmp);
  2541. //
  2542. // Enable the restore privilege. Don't give up even if fails. In the case
  2543. // of impersonation, this call will fail. But we still might still have
  2544. // the privilege needed.
  2545. //
  2546. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &bWasEnabled);
  2547. if(!NT_SUCCESS(status)) {
  2548. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WatchHiveRefCount: Failed to enable the restore privilege. error = %08x"), status));
  2549. }
  2550. //
  2551. // Enter the critical section.
  2552. //
  2553. EnterCriticalSection(&csMap);
  2554. bInCriticalSection = TRUE;
  2555. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WatchHiveRefCount: In critical section")));
  2556. //
  2557. // Register for the hive to be unloaded.
  2558. //
  2559. while (dwWHRCFlags & (WHRC_UNLOAD_HIVE | WHRC_UNLOAD_CLASSESROOT)) {
  2560. if(dwWHRCFlags & WHRC_UNLOAD_HIVE) {
  2561. dwWHRCFlags &= ~WHRC_UNLOAD_HIVE;
  2562. }
  2563. else if (dwWHRCFlags & WHRC_UNLOAD_CLASSESROOT) {
  2564. dwWHRCFlags &= ~WHRC_UNLOAD_CLASSESROOT;
  2565. lstrcat(tszHiveName, USER_CLASSES_HIVE_SUFFIX);
  2566. }
  2567. //
  2568. // First make sure that the item is not already in our work list.
  2569. //
  2570. if(cTable.IsInTable(pTmp)) {
  2571. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WatchHiveRefCount: %s already in work list"), pTmp));
  2572. }
  2573. else {
  2574. if((hEvent = CreateEvent(NULL,
  2575. FALSE,
  2576. FALSE,
  2577. NULL)) == NULL) {
  2578. hres = HRESULT_FROM_WIN32(GetLastError());
  2579. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount: CreateEvent failed. error = %08x"), hres));
  2580. goto Exit;
  2581. }
  2582. //
  2583. // Initialize the object attributes.
  2584. //
  2585. RtlInitUnicodeString(&sHiveName, tszHiveName);
  2586. InitializeObjectAttributes(&oa,
  2587. &sHiveName,
  2588. OBJ_CASE_INSENSITIVE,
  2589. NULL,
  2590. NULL);
  2591. //
  2592. // Unload the hive.
  2593. //
  2594. if(!NT_SUCCESS(status = NtUnloadKeyEx(&oa, hEvent))) {
  2595. hres = HRESULT_FROM_WIN32(status);
  2596. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount: NtUnloadKeyEx failed with %08x"), status));
  2597. CloseHandle(hEvent);
  2598. goto Exit;
  2599. }
  2600. else {
  2601. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::WatchHiveRefCount: NtUnloadKeyEx succeeded for %s"), tszHiveName));
  2602. }
  2603. //
  2604. // Add the work item to clean up the profile when the hive is unloaded.
  2605. //
  2606. hres = AddWorkItem(pTmp, hEvent);
  2607. //
  2608. // Do not return error if we fail to add the work item because
  2609. // cleaning up is a best effort. The important thing is that we
  2610. // unloaded the hive successfully, or at least registered
  2611. // successfully to do so.
  2612. //
  2613. if(hres != S_OK) {
  2614. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount: AddWorkItem failed with %08x"), hres));
  2615. CloseHandle(hEvent);
  2616. hres = S_OK;
  2617. }
  2618. } // Item not already in list
  2619. }
  2620. Exit:
  2621. if(bInCriticalSection) {
  2622. LeaveCriticalSection(&csMap);
  2623. }
  2624. //
  2625. // Restore the privilege to its previous state.
  2626. //
  2627. status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, bWasEnabled, FALSE, &bWasEnabled);
  2628. if(!bWasEnabled && !NT_SUCCESS(status)) {
  2629. DebugMsg((DM_WARNING, TEXT("CUserProfile::WatchHiveRefCount: Failed to restore the privilege. error = %08x"), status));
  2630. }
  2631. return hres;
  2632. }
  2633. //*************************************************************
  2634. //
  2635. // CUserProfile::AddWorkItem
  2636. //
  2637. // Add a new work item.
  2638. //
  2639. // Parameters:
  2640. //
  2641. // pSid the user's sid
  2642. // hEvent the event registry will set when hive is unloaded.
  2643. //
  2644. // Return value:
  2645. //
  2646. // HRESULT error code.
  2647. //
  2648. // History:
  2649. //
  2650. // Created weiruc 3/2/2000
  2651. //
  2652. //*************************************************************
  2653. HRESULT CUserProfile::AddWorkItem(LPCTSTR pSid, HANDLE hEvent)
  2654. {
  2655. PMAP pThreadMap = NULL;
  2656. HRESULT hres = E_FAIL;
  2657. HANDLE hThreadEvent = INVALID_HANDLE_VALUE;
  2658. HANDLE hThread = INVALID_HANDLE_VALUE;
  2659. BOOL bHashDelete = TRUE;
  2660. LPTSTR pSidCopy = NULL;
  2661. DebugMsg((DM_VERBOSE, TEXT("Entering CUserProfile::AddWorkItem: %s"), pSid));
  2662. pSidCopy = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pSid) + 1) * sizeof(TCHAR));
  2663. if(!pSidCopy) {
  2664. hres = HRESULT_FROM_WIN32(GetLastError());
  2665. DebugMsg((DM_WARNING, TEXT("CUserProfile::AddWorkItem: Out of memory")));
  2666. goto Exit;
  2667. }
  2668. lstrcpy(pSidCopy, pSid);
  2669. //
  2670. // Make sure the leading 's' is in uppercase.
  2671. //
  2672. *pSidCopy = (TCHAR)_totupper(*pSidCopy);
  2673. //
  2674. // Verify that this sid is not already in our work list.
  2675. //
  2676. if(!cTable.HashAdd(pSidCopy)) {
  2677. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: sid %s already in work list"), pSidCopy));
  2678. bHashDelete = FALSE;
  2679. goto Exit;
  2680. }
  2681. //
  2682. // Look through the work item thread map list to find a thread that is not
  2683. // fully loaded;
  2684. //
  2685. for(pThreadMap = pMap; pThreadMap != NULL; pThreadMap = pThreadMap->pNext) {
  2686. if(pThreadMap->dwItems < MAXIMUM_WAIT_OBJECTS) {
  2687. break;
  2688. }
  2689. }
  2690. if(!pThreadMap) {
  2691. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: No thread available, create a new one.")));
  2692. //
  2693. // Create the thread event.
  2694. //
  2695. pThreadMap = new MAP();
  2696. if(!pThreadMap) {
  2697. hres = HRESULT_FROM_WIN32(GetLastError());
  2698. DebugMsg((DM_WARNING, TEXT("CUserProfile::AddWorkItem: new operator failed. error = %08x"), hres));
  2699. goto Exit;
  2700. }
  2701. if((hThreadEvent = CreateEvent(NULL,
  2702. FALSE,
  2703. FALSE,
  2704. NULL)) == NULL) {
  2705. hres = HRESULT_FROM_WIN32(GetLastError());
  2706. DebugMsg((DM_WARNING, TEXT("CUserProfile::AddWorkItem: CreateEvent failed for thread event. error = %08x"), hres));
  2707. goto Exit;
  2708. }
  2709. pThreadMap->Insert(hThreadEvent, NULL);
  2710. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: Signal event item inserted")));
  2711. //
  2712. // Create the thread.
  2713. //
  2714. if((hThread = CreateThread(NULL,
  2715. 0,
  2716. (LPTHREAD_START_ROUTINE)ThreadMain,
  2717. pThreadMap,
  2718. 0,
  2719. NULL)) == NULL) {
  2720. hres = HRESULT_FROM_WIN32(GetLastError());
  2721. DebugMsg((DM_WARNING, TEXT("CUserProfile::AddWorkItem: CreateThread failed. error = %08x"), hres));
  2722. //
  2723. // Delete the thread signal event item.
  2724. //
  2725. pThreadMap->Delete(0);
  2726. goto Exit;
  2727. }
  2728. else {
  2729. CloseHandle(hThread);
  2730. }
  2731. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: New thread created")));
  2732. //
  2733. // Successful return. Insert the work item into pThreadMap.
  2734. //
  2735. pThreadMap->Insert(hEvent, pSidCopy);
  2736. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: Work Item inserted")));
  2737. //
  2738. // Insert pThreadMap into the map list.
  2739. //
  2740. pThreadMap->pNext = pMap;
  2741. pMap = pThreadMap;
  2742. }
  2743. else {
  2744. //
  2745. // Found an existing thread. Insert the work item into it's map.
  2746. //
  2747. pThreadMap->Insert(hEvent, pSidCopy);
  2748. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: Work item inserted")));
  2749. }
  2750. //
  2751. // Wake up the thread. If the thread can not be waken up by setting the
  2752. // event here, then it'll be stuck in sleep state until one day this
  2753. // SetEvent call succeeds. Leave the work item in and continue.
  2754. //
  2755. if(!SetEvent(pThreadMap->rghEvents[0])) {
  2756. hres = HRESULT_FROM_WIN32(GetLastError());
  2757. DebugMsg((DM_WARNING, TEXT("SetEvent failed. error = %08x"), hres));
  2758. }
  2759. else {
  2760. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::AddWorkItem: thread woken up")));
  2761. }
  2762. pThreadMap = NULL;
  2763. hres = S_OK;
  2764. bHashDelete = FALSE;
  2765. pSidCopy = NULL;
  2766. Exit:
  2767. if(bHashDelete && pSidCopy) {
  2768. cTable.HashDelete(pSidCopy);
  2769. }
  2770. if(pSidCopy) {
  2771. LocalFree(pSidCopy);
  2772. }
  2773. if(pThreadMap) {
  2774. delete pThreadMap;
  2775. }
  2776. DebugMsg((DM_VERBOSE, TEXT("Exiting CUserProfile::AddWorkItem with %08x"), hres));
  2777. return hres;
  2778. }
  2779. //*************************************************************
  2780. //
  2781. // CUserProfile::CleanupUserProfile
  2782. //
  2783. // Unload the hive and delete the profile directory if necessary.
  2784. //
  2785. // Parameters:
  2786. //
  2787. // ptszSid - User's sid string
  2788. // phkProfileList - in/out parameter. Handle to the profile list key.
  2789. // if NULL, will fill in the handle. And this handle
  2790. // has to be closed by the caller.
  2791. //
  2792. // Comment:
  2793. //
  2794. // Always ignore error and continue because this is a best effort.
  2795. //
  2796. //*************************************************************
  2797. void CUserProfile::CleanupUserProfile(LPTSTR ptszSid, HKEY* phkProfileList)
  2798. {
  2799. DWORD dwInternalFlags = 0;
  2800. DWORD dwRefCount;
  2801. BOOL bInCS = FALSE;
  2802. //
  2803. // Enter the critical section.
  2804. //
  2805. if(!EnterUserProfileLockLocal(ptszSid)) {
  2806. DebugMsg((DM_WARNING, TEXT("CUserProfile::CleanupUserProfile:: Failed to get the user profile lock for %s"), ptszSid));
  2807. goto Exit;
  2808. }
  2809. bInCS = TRUE;
  2810. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::CleanupUserProfile: Enter critical section.")));
  2811. //
  2812. // Get the reference count and the internal flags.
  2813. //
  2814. if(GetRefCountAndFlags(ptszSid, phkProfileList, &dwRefCount, &dwInternalFlags) != ERROR_SUCCESS) {
  2815. DebugMsg((DM_WARNING, TEXT("CUserProfile::CleanupUserProfile: Can not get ref count and flags")));
  2816. goto Exit;
  2817. }
  2818. //
  2819. // If the ref count is 0, clean up the user's profile. If not, give up.
  2820. //
  2821. if(dwRefCount != 0) {
  2822. DebugMsg((DM_WARNING, TEXT("CUserProfile::CleanupUserProfile: Ref Count is not 0")));
  2823. goto Exit;
  2824. }
  2825. //
  2826. // Delete the temporary profile if:
  2827. // guest user profile or
  2828. // temp profile or
  2829. // mandatory profile
  2830. // Profiles that are none of the above will not be cleaned up even if
  2831. // Delete cache bit is set in the registry or the policy says delete
  2832. // cached profiles. This is because even though now we unloaded the
  2833. // hive we don't upload the profile. Deleting the local profile might
  2834. // result in user's data loss.
  2835. //
  2836. // Don't delete the guest account if machine is in workgroup
  2837. INT iRole;
  2838. if(dwInternalFlags & PROFILE_MANDATORY ||
  2839. dwInternalFlags & PROFILE_TEMP_ASSIGNED ||
  2840. ((dwInternalFlags & PROFILE_GUEST_USER) && GetMachineRole(&iRole) && (iRole != 0))) {
  2841. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::CleanupUserProfile: DeleteProfile")));
  2842. if(!DeleteProfile(ptszSid, NULL, NULL)) {
  2843. DebugMsg((DM_WARNING, TEXT("CUserProfile::CleanupUserProfile: DeleteProfile returned FALSE. error = %08x"), GetLastError()));
  2844. }
  2845. }
  2846. Exit:
  2847. if(bInCS) {
  2848. LeaveUserProfileLockLocal(ptszSid);
  2849. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::CleanupUserProfile: Leave critical section")));
  2850. }
  2851. }
  2852. //*************************************************************
  2853. //
  2854. // CUserProfile::GetRefCountAndFlags
  2855. //
  2856. // Get the ref count and internal flags from the registry for a user.
  2857. //
  2858. // Parameters:
  2859. //
  2860. // ptszSid - User's sid string
  2861. // phkPL - in/out parameter. Handle to the profile list key.
  2862. // If NULL, will be filled with an opened key to the
  2863. // profile list. The caller is responsible for
  2864. // closing it.
  2865. // dwRefCount - buffer for the ref count.
  2866. // dwInternalFlags - buffer for the internal flags.
  2867. //
  2868. // History:
  2869. //
  2870. // Created weiruc 5/23/2000
  2871. //
  2872. //*************************************************************
  2873. long CUserProfile::GetRefCountAndFlags(LPCTSTR ptszSid, HKEY* phkPL, DWORD* dwRefCount, DWORD* dwInternalFlags)
  2874. {
  2875. HKEY hkUser = NULL;
  2876. DWORD dwType, dwSize = sizeof(DWORD);
  2877. long lResult = ERROR_SUCCESS;
  2878. *dwRefCount = 0;
  2879. *dwInternalFlags = 0;
  2880. if(!*phkPL) {
  2881. //
  2882. // Open the profile list if it's not already opened.
  2883. //
  2884. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2885. PROFILE_LIST_PATH,
  2886. 0,
  2887. KEY_READ,
  2888. phkPL);
  2889. if(lResult != ERROR_SUCCESS) {
  2890. DebugMsg((DM_WARNING, TEXT("CUserProfile::GetRefCountAndFlags: Failed to open profile list key with error %d"), lResult));
  2891. goto Exit;
  2892. }
  2893. }
  2894. //
  2895. // Open the user's key in the profile list.
  2896. //
  2897. if((lResult = RegOpenKeyEx(*phkPL,
  2898. ptszSid,
  2899. 0,
  2900. KEY_READ,
  2901. &hkUser)) != ERROR_SUCCESS) {
  2902. DebugMsg((DM_WARNING, TEXT("CUserProfile::GetRefCountAndFlags: RegOpenKeyEx failed with error %08x"), lResult));
  2903. goto Exit;
  2904. }
  2905. //
  2906. // Query for the ref count and the internal flags.
  2907. //
  2908. if((lResult = RegQueryValueEx(hkUser,
  2909. PROFILE_REF_COUNT,
  2910. 0,
  2911. &dwType,
  2912. (LPBYTE)dwRefCount,
  2913. &dwSize)) != ERROR_SUCCESS) {
  2914. DebugMsg((DM_WARNING, TEXT("CUserProfile::GetRefCountAndFlags: RegQueryValueEx failed, key = %s, error = %08x"), ptszSid, lResult));
  2915. goto Exit;
  2916. }
  2917. dwSize = sizeof(DWORD);
  2918. if((lResult = RegQueryValueEx(hkUser,
  2919. PROFILE_STATE,
  2920. 0,
  2921. &dwType,
  2922. (LPBYTE)dwInternalFlags,
  2923. &dwSize)) != ERROR_SUCCESS) {
  2924. DebugMsg((DM_WARNING, TEXT("CUserProfile::GetRefCountAndFlags: RegQueryValueEx failed, key = %s, error = %08x"), ptszSid, lResult));
  2925. goto Exit;
  2926. }
  2927. DebugMsg((DM_VERBOSE, TEXT("CUserProfile::GetRefCountAndFlags: Ref count is %d, state is %08x"), *dwRefCount, *dwInternalFlags));
  2928. Exit:
  2929. if(hkUser) {
  2930. RegCloseKey(hkUser);
  2931. }
  2932. return lResult;
  2933. }
  2934. //*************************************************************
  2935. //
  2936. // LoadUserProfileI()
  2937. //
  2938. // Purpose: Just a wrapper around CUserProfile::LoadUserProfileP
  2939. //
  2940. // Parameters: hBindHandle - server explicit binding handle
  2941. // pProfileInfo - Profile Information
  2942. // phContext - server context for client
  2943. // lpRPCEndPoint - RPCEndPoint of the registered IProfileDialog interface
  2944. //
  2945. // Return: DWORD
  2946. // ERROR_SUCCESS - if everything is ok
  2947. //
  2948. // Comments:
  2949. //
  2950. // History: Date Author Comment
  2951. // 10/24/00 santanuc Created
  2952. //
  2953. //*************************************************************
  2954. DWORD LoadUserProfileI(IN handle_t hBindHandle, IN LPPROFILEINFO lpProfileInfo, IN PCONTEXT_HANDLE phContext, IN LPTSTR lpRPCEndPoint)
  2955. {
  2956. HANDLE hUserToken = NULL;
  2957. BOOL bImpersonatingUser = FALSE;
  2958. PCLIENTINFO pClientInfo;
  2959. DWORD dwErr = ERROR_ACCESS_DENIED;
  2960. RPC_STATUS status;
  2961. if (lpRPCEndPoint) {
  2962. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfileI: RPC end point %s"), lpRPCEndPoint));
  2963. }
  2964. //
  2965. // Get the context
  2966. //
  2967. if (!phContext) {
  2968. dwErr = ERROR_INVALID_PARAMETER;
  2969. DebugMsg((DM_WARNING, TEXT("LoadUserProfileI: NULL context")));
  2970. goto Exit;
  2971. }
  2972. pClientInfo = (PCLIENTINFO)phContext;
  2973. //
  2974. // Verify that the PROFILEINFO structure passed in is the same one.
  2975. //
  2976. if(!CompareProfileInfo(lpProfileInfo, pClientInfo->pProfileInfo)) {
  2977. dwErr = ERROR_INVALID_PARAMETER;
  2978. DebugMsg((DM_WARNING, TEXT("LoadUserProfileI: PROFILEINFO structure passed in is different")));
  2979. goto Exit;
  2980. }
  2981. //
  2982. // Impersonate the client to get the user's token.
  2983. //
  2984. if((status = RpcImpersonateClient(0)) != S_OK) {
  2985. DebugMsg((DM_WARNING, TEXT("LoadUserProfileI: CoImpersonateClient failed with %ld"), status));
  2986. dwErr = status;
  2987. goto Exit;
  2988. }
  2989. bImpersonatingUser = TRUE;
  2990. if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hUserToken)) {
  2991. dwErr = GetLastError();
  2992. DebugMsg((DM_WARNING, TEXT("LoadUserProfileI: OpenThreadToken failed with %d"), dwErr));
  2993. goto Exit;
  2994. }
  2995. RpcRevertToSelf();
  2996. bImpersonatingUser = FALSE;
  2997. //
  2998. // Now that we have both the client and the user's token, call
  2999. // LoadUserProfileP to do the work.
  3000. //
  3001. if(!cUserProfileManager.LoadUserProfileP(pClientInfo->hClientToken, hUserToken, pClientInfo->pProfileInfo, lpRPCEndPoint)) {
  3002. dwErr = GetLastError();
  3003. DebugMsg((DM_WARNING, TEXT("LoadUserProfileI: LoadUserProfileP failed with %d"), dwErr));
  3004. goto Exit;
  3005. }
  3006. //
  3007. // Close the registry handle to the user hive opened by LoadUserProfileP.
  3008. //
  3009. RegCloseKey((HKEY)pClientInfo->pProfileInfo->hProfile);
  3010. dwErr = ERROR_SUCCESS;
  3011. Exit:
  3012. if(bImpersonatingUser) {
  3013. RpcRevertToSelf();
  3014. }
  3015. if(hUserToken) {
  3016. CloseHandle(hUserToken);
  3017. }
  3018. DebugMsg((DM_VERBOSE, TEXT("LoadUserProfileI: returning %d"), dwErr));
  3019. return dwErr;
  3020. }
  3021. //*************************************************************
  3022. //
  3023. // UnloadUserProfileI()
  3024. //
  3025. // Purpose: Just a wrapper around CUserProfile::UnloadUserProfileP
  3026. //
  3027. // Parameters: hBindHandle - server explicit binding handle
  3028. // phContext - server context for client
  3029. // lpRPCEndPoint - RPCEndPoint of the registered IProfileDialog interface
  3030. //
  3031. // Return: DWORD
  3032. // ERROR_SUCCESS - if everything is ok
  3033. //
  3034. // Comments:
  3035. //
  3036. // History: Date Author Comment
  3037. // 10/24/00 santanuc Created
  3038. //
  3039. //*************************************************************
  3040. DWORD UnloadUserProfileI(IN handle_t hBindHandle, IN PCONTEXT_HANDLE phContext, IN LPTSTR lpRPCEndPoint)
  3041. {
  3042. HANDLE hUserToken = NULL;
  3043. HKEY hProfile = NULL;
  3044. BOOL bImpersonatingUser = FALSE;
  3045. PCLIENTINFO pClientInfo;
  3046. LPTSTR pSid = NULL;
  3047. long lResult;
  3048. RPC_STATUS status;
  3049. DWORD dwErr = ERROR_ACCESS_DENIED;
  3050. //
  3051. // Get the context
  3052. //
  3053. if (!phContext) {
  3054. dwErr = ERROR_INVALID_PARAMETER;
  3055. DebugMsg((DM_WARNING, TEXT("UnLoadUserProfileI: NULL context")));
  3056. goto Exit;
  3057. }
  3058. pClientInfo = (PCLIENTINFO)phContext;
  3059. //
  3060. // Impersonate the client to get the user's token.
  3061. //
  3062. if((status = RpcImpersonateClient(0)) != RPC_S_OK) {
  3063. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileI: CoImpersonateClient failed with %ld"), status));
  3064. dwErr = status;
  3065. goto Exit;
  3066. }
  3067. bImpersonatingUser = TRUE;
  3068. if(!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ, TRUE, &hUserToken)) {
  3069. dwErr = GetLastError();
  3070. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileI: OpenThreadToken failed with %d"), dwErr));
  3071. goto Exit;
  3072. }
  3073. RpcRevertToSelf();
  3074. bImpersonatingUser = FALSE;
  3075. //
  3076. // Open the user's registry hive root.
  3077. //
  3078. pSid = GetSidString(hUserToken);
  3079. if((lResult = RegOpenKeyEx(HKEY_USERS, pSid, 0, KEY_ALL_ACCESS, &hProfile)) != ERROR_SUCCESS) {
  3080. dwErr = lResult;
  3081. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileI: RegOpenKeyEx failed with %d"), dwErr));
  3082. goto Exit;
  3083. }
  3084. //
  3085. // Now that we have both the client and the user's token, call
  3086. // UnloadUserProfileP to do the work. hProfile gets closed in
  3087. // UnloadUserProfileP so don't close it again.
  3088. //
  3089. if(!cUserProfileManager.UnloadUserProfileP(pClientInfo->hClientToken, hUserToken, hProfile, lpRPCEndPoint)) {
  3090. dwErr = GetLastError();
  3091. DebugMsg((DM_WARNING, TEXT("UnloadUserProfileI: UnloadUserProfileP failed with %d"), dwErr));
  3092. goto Exit;
  3093. }
  3094. dwErr = ERROR_SUCCESS;
  3095. Exit:
  3096. if(bImpersonatingUser) {
  3097. RpcRevertToSelf();
  3098. }
  3099. if(hUserToken) {
  3100. CloseHandle(hUserToken);
  3101. }
  3102. if(pSid) {
  3103. DeleteSidString(pSid);
  3104. }
  3105. DebugMsg((DM_VERBOSE, TEXT("UnloadUserProfileI: returning %d"), dwErr));
  3106. SetLastError(dwErr);
  3107. return dwErr;
  3108. }
  3109. //*************************************************************
  3110. //
  3111. // CompareProfileInfo()
  3112. //
  3113. // Purpose: Compare field by field two PROFILEINFO structures
  3114. // except for the hProfile field.
  3115. //
  3116. // Parameters: pInfo1, pInfo2
  3117. //
  3118. // Return: TRUE - Same
  3119. // FALSE - Not the same
  3120. //
  3121. // History: Date Author Comment
  3122. // 6/29/00 weiruc Created
  3123. //
  3124. //*************************************************************
  3125. BOOL CompareProfileInfo(LPPROFILEINFO pInfo1, LPPROFILEINFO pInfo2)
  3126. {
  3127. BOOL bRet = TRUE;
  3128. if(!pInfo1 || !pInfo2) {
  3129. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: Invalid parameter")));
  3130. return FALSE;
  3131. }
  3132. if(pInfo1->dwSize != pInfo2->dwSize) {
  3133. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: dwSize %d != %d"), pInfo1->dwSize, pInfo2->dwSize));
  3134. return FALSE;
  3135. }
  3136. if(pInfo1->dwFlags != pInfo2->dwFlags) {
  3137. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: dwFlags %d != %d"), pInfo1->dwFlags, pInfo2->dwFlags));
  3138. return FALSE;
  3139. }
  3140. if(lstrcmpi(pInfo1->lpUserName, pInfo2->lpUserName)) {
  3141. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: lpUserName <%s> != <%s>"), pInfo1->lpUserName, pInfo2->lpUserName));
  3142. return FALSE;
  3143. }
  3144. if(lstrcmpi(pInfo1->lpProfilePath, pInfo2->lpProfilePath)) {
  3145. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: lpProfilePath <%s> != <%s>"), pInfo1->lpProfilePath, pInfo2->lpProfilePath));
  3146. return FALSE;
  3147. }
  3148. if(lstrcmpi(pInfo1->lpDefaultPath, pInfo2->lpDefaultPath)) {
  3149. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: lpDefaultPath <%s> != <%s>"), pInfo1->lpDefaultPath, pInfo2->lpDefaultPath));
  3150. return FALSE;
  3151. }
  3152. if(lstrcmpi(pInfo1->lpServerName, pInfo2->lpServerName)) {
  3153. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: lpServerName <%s> != <%s>"), pInfo1->lpServerName, pInfo2->lpServerName));
  3154. return FALSE;
  3155. }
  3156. if(lstrcmpi(pInfo1->lpPolicyPath, pInfo2->lpPolicyPath)) {
  3157. DebugMsg((DM_WARNING, TEXT("CompareProfileInfo: lpPolicyPath <%s> != <%s>"), pInfo1->lpPolicyPath, pInfo2->lpPolicyPath));
  3158. return FALSE;
  3159. }
  3160. return TRUE;
  3161. }
  3162. //*************************************************************
  3163. //
  3164. // CopyProfileInfo()
  3165. //
  3166. // Purpose: Allocate and copy a PROFILEINFO structure.
  3167. //
  3168. // Parameters: pProfileInfo - To be copied
  3169. //
  3170. // Return: The copy
  3171. //
  3172. // History: Date Author Comment
  3173. // 6/29/00 weiruc Created
  3174. //
  3175. //*************************************************************
  3176. LPPROFILEINFO CopyProfileInfo(LPPROFILEINFO pProfileInfo)
  3177. {
  3178. LPPROFILEINFO pInfoCopy = NULL;
  3179. BOOL bSuccess = FALSE;
  3180. //
  3181. // Allocate and initialize memory for the PROFILEINFO copy.
  3182. //
  3183. pInfoCopy = (LPPROFILEINFO)LocalAlloc(LPTR, sizeof(PROFILEINFO));
  3184. if(!pInfoCopy) {
  3185. goto Exit;
  3186. }
  3187. //
  3188. // Copy field by field.
  3189. //
  3190. pInfoCopy->dwSize = pProfileInfo->dwSize;
  3191. pInfoCopy->dwFlags = pProfileInfo->dwFlags;
  3192. if(pProfileInfo->lpUserName) {
  3193. pInfoCopy->lpUserName = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pProfileInfo->lpUserName) + 1) * sizeof(TCHAR));
  3194. if(!pInfoCopy->lpUserName) {
  3195. goto Exit;
  3196. }
  3197. lstrcpy(pInfoCopy->lpUserName, pProfileInfo->lpUserName);
  3198. }
  3199. if(pProfileInfo->lpProfilePath) {
  3200. pInfoCopy->lpProfilePath = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pProfileInfo->lpProfilePath) + 1) * sizeof(TCHAR));
  3201. if(!pInfoCopy->lpProfilePath) {
  3202. goto Exit;
  3203. }
  3204. lstrcpy(pInfoCopy->lpProfilePath, pProfileInfo->lpProfilePath);
  3205. }
  3206. if(pProfileInfo->lpDefaultPath) {
  3207. pInfoCopy->lpDefaultPath = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pProfileInfo->lpDefaultPath) + 1) * sizeof(TCHAR));
  3208. if(!pInfoCopy->lpDefaultPath) {
  3209. goto Exit;
  3210. }
  3211. lstrcpy(pInfoCopy->lpDefaultPath, pProfileInfo->lpDefaultPath);
  3212. }
  3213. if(pProfileInfo->lpServerName) {
  3214. pInfoCopy->lpServerName = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pProfileInfo->lpServerName) + 1) * sizeof(TCHAR));
  3215. if(!pInfoCopy->lpServerName) {
  3216. goto Exit;
  3217. }
  3218. lstrcpy(pInfoCopy->lpServerName, pProfileInfo->lpServerName);
  3219. }
  3220. if(pProfileInfo->lpPolicyPath) {
  3221. pInfoCopy->lpPolicyPath = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pProfileInfo->lpPolicyPath) + 1) * sizeof(TCHAR));
  3222. if(!pInfoCopy->lpPolicyPath) {
  3223. goto Exit;
  3224. }
  3225. lstrcpy(pInfoCopy->lpPolicyPath, pProfileInfo->lpPolicyPath);
  3226. }
  3227. bSuccess = TRUE;
  3228. Exit:
  3229. if(!bSuccess && pInfoCopy) {
  3230. DeleteProfileInfo(pInfoCopy);
  3231. pInfoCopy = NULL;
  3232. }
  3233. return pInfoCopy;
  3234. }
  3235. //*************************************************************
  3236. //
  3237. // DeleteProfileInfo()
  3238. //
  3239. // Purpose: Delete a PROFILEINFO structure
  3240. //
  3241. // Parameters: pInfo
  3242. //
  3243. // Return: void
  3244. //
  3245. // History: Date Author Comment
  3246. // 6/29/00 weiruc Created
  3247. //
  3248. //*************************************************************
  3249. void DeleteProfileInfo(LPPROFILEINFO pInfo)
  3250. {
  3251. if(!pInfo) {
  3252. return;
  3253. }
  3254. if(pInfo->lpUserName) {
  3255. LocalFree(pInfo->lpUserName);
  3256. }
  3257. if(pInfo->lpProfilePath) {
  3258. LocalFree(pInfo->lpProfilePath);
  3259. }
  3260. if(pInfo->lpDefaultPath) {
  3261. LocalFree(pInfo->lpDefaultPath);
  3262. }
  3263. if(pInfo->lpServerName) {
  3264. LocalFree(pInfo->lpServerName);
  3265. }
  3266. if(pInfo->lpPolicyPath) {
  3267. LocalFree(pInfo->lpPolicyPath);
  3268. }
  3269. LocalFree(pInfo);
  3270. }
  3271. //*************************************************************
  3272. //
  3273. // GetInterface()
  3274. //
  3275. // Purpose: Get the rpc binding handle
  3276. //
  3277. // Parameters: phIfHandle - rpc binding handle to initialize
  3278. // lpRPCEndPoint - RPCEndPoint of interface
  3279. //
  3280. // Return: TRUE if successful.
  3281. //
  3282. // History: Date Author Comment
  3283. // 10/24/00 santanuc Created
  3284. //
  3285. //*************************************************************
  3286. BOOL GetInterface(handle_t * phIfHandle, LPTSTR lpRPCEndPoint)
  3287. {
  3288. RPC_STATUS status;
  3289. LPTSTR pszStringBinding = NULL;
  3290. BOOL bStringBinding = FALSE, bRetVal = FALSE;
  3291. // compose string to pass to binding api
  3292. status = RpcStringBindingCompose(NULL,
  3293. cszRPCProtocol,
  3294. NULL,
  3295. lpRPCEndPoint,
  3296. NULL,
  3297. &pszStringBinding);
  3298. if (status != RPC_S_OK) {
  3299. DebugMsg((DM_WARNING, TEXT("GetInterface: RpcStringBindingCompose fails with error %ld"), status));
  3300. goto Exit;
  3301. }
  3302. bStringBinding = TRUE;
  3303. // set the binding handle that will be used to bind to the server.
  3304. status = RpcBindingFromStringBinding(pszStringBinding,
  3305. phIfHandle);
  3306. if (status != RPC_S_OK) {
  3307. DebugMsg((DM_WARNING, TEXT("GetInterface: RpcStringBindingCompose fails with error %ld"), status));
  3308. goto Exit;
  3309. }
  3310. bRetVal = TRUE;
  3311. DebugMsg((DM_VERBOSE, TEXT("GetInterface: Returning rpc binding handle")));
  3312. Exit:
  3313. // free string
  3314. if (bStringBinding)
  3315. RpcStringFree(&pszStringBinding);
  3316. return bRetVal;
  3317. }
  3318. //*************************************************************
  3319. //
  3320. // ReleaseInterface()
  3321. //
  3322. // Purpose: Release the rpc binding handle
  3323. //
  3324. // Parameters: phIfHandle - rpc binding handle to initialize
  3325. //
  3326. // Return: TRUE if successful.
  3327. //
  3328. // History: Date Author Comment
  3329. // 10/24/00 santanuc Created
  3330. //
  3331. //*************************************************************
  3332. BOOL ReleaseInterface(handle_t * phIfHandle)
  3333. {
  3334. RPC_STATUS status;
  3335. // free binding handle
  3336. DebugMsg((DM_VERBOSE, TEXT("ReleaseInterface: Releasing rpc binding handle")));
  3337. status = RpcBindingFree(phIfHandle);
  3338. return (status == RPC_S_OK);
  3339. }
  3340. //*************************************************************
  3341. //
  3342. // Routine Description:
  3343. //
  3344. // This routine determines if we're doing a gui-mode setup.
  3345. //
  3346. // This value is retrieved from the following registry location:
  3347. //
  3348. // \HKLM\System\Setup\
  3349. //
  3350. // SystemSetupInProgress : REG_DWORD : 0x00 (where nonzero
  3351. // means we're doing a gui-setup)
  3352. //
  3353. // Arguments:
  3354. //
  3355. // None.
  3356. //
  3357. // Return Value:
  3358. //
  3359. // TRUE/FALSE
  3360. //
  3361. // Note:
  3362. //
  3363. // This function is courtesy of Andrew Ritz and the Setup API.
  3364. // It's copied over from base\pnp\setupapi\dll.c.
  3365. //
  3366. //***************************************************************
  3367. BOOL IsGuiSetupInProgress()
  3368. {
  3369. HKEY hKey;
  3370. DWORD Err, DataType, DataSize = sizeof(DWORD);
  3371. DWORD Value;
  3372. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3373. TEXT("System\\Setup"),
  3374. 0,
  3375. KEY_READ,
  3376. &hKey)) == ERROR_SUCCESS) {
  3377. //
  3378. // Attempt to read the the "DriverCachePath" value.
  3379. //
  3380. Err = RegQueryValueEx(
  3381. hKey,
  3382. TEXT("SystemSetupInProgress"),
  3383. NULL,
  3384. &DataType,
  3385. (LPBYTE)&Value,
  3386. &DataSize);
  3387. RegCloseKey(hKey);
  3388. }
  3389. if(Err == NO_ERROR) {
  3390. if(Value) {
  3391. return(TRUE);
  3392. }
  3393. }
  3394. return(FALSE);
  3395. }
  3396. //*************************************************************
  3397. //
  3398. // CheckNetDefaultProfile()
  3399. //
  3400. // Purpose: Checks if a network profile exists
  3401. //
  3402. // Parameters: lpProfile - Profile information
  3403. //
  3404. // Return: TRUE if successful
  3405. // FALSE if an error occurs
  3406. //
  3407. // Comments: This routine assumes we are working
  3408. // in the user's context.
  3409. //
  3410. // History: Date Author Comment
  3411. // 9/21/95 ericflo Created
  3412. // 4/10/99 ushaji modified to remove local caching
  3413. //
  3414. //*************************************************************
  3415. BOOL CheckNetDefaultProfile (LPPROFILE lpProfile)
  3416. {
  3417. HANDLE hFile;
  3418. WIN32_FIND_DATA fd;
  3419. TCHAR szBuffer[MAX_PATH];
  3420. TCHAR szLocalDir[MAX_PATH];
  3421. DWORD dwSize, dwFlags, dwErr;
  3422. LPTSTR lpEnd;
  3423. BOOL bRetVal = FALSE;
  3424. LPTSTR lpNetPath = lpProfile->lpDefaultProfile;
  3425. HANDLE hOldToken;
  3426. //
  3427. // Get the error at the beginning of the call.
  3428. //
  3429. dwErr = GetLastError();
  3430. //
  3431. // Verbose output
  3432. //
  3433. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Entering, lpNetPath = <%s>"),
  3434. (lpNetPath ? lpNetPath : TEXT("NULL"))));
  3435. if (!lpNetPath || !(*lpNetPath)) {
  3436. return bRetVal;
  3437. }
  3438. //
  3439. // Impersonate the user....
  3440. //
  3441. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  3442. if (lpProfile->lpDefaultProfile) {
  3443. *lpProfile->lpDefaultProfile = TEXT('\0');
  3444. }
  3445. //
  3446. // Last error is set
  3447. //
  3448. return bRetVal;
  3449. }
  3450. //
  3451. // See if network copy exists
  3452. //
  3453. hFile = FindFirstFile (lpNetPath, &fd);
  3454. if (hFile != INVALID_HANDLE_VALUE) {
  3455. //
  3456. // Close the find handle
  3457. //
  3458. FindClose (hFile);
  3459. //
  3460. // We found something. Is it a directory?
  3461. //
  3462. if ( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  3463. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a file. ignoring Network Defaul profile")));
  3464. dwErr = ERROR_FILE_NOT_FOUND;
  3465. goto Exit;
  3466. }
  3467. //
  3468. // Is there a ntuser.* file in this directory?
  3469. //
  3470. lstrcpy (szBuffer, lpNetPath);
  3471. lpEnd = CheckSlash (szBuffer);
  3472. lstrcpy (lpEnd, c_szNTUserStar);
  3473. hFile = FindFirstFile (szBuffer, &fd);
  3474. if (hFile == INVALID_HANDLE_VALUE) {
  3475. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: FindFirstFile found a directory, but no ntuser files.")));
  3476. dwErr = ERROR_FILE_NOT_FOUND;
  3477. goto Exit;
  3478. }
  3479. FindClose (hFile);
  3480. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Found a valid network profile.")));
  3481. bRetVal = TRUE;
  3482. }
  3483. else {
  3484. dwErr = ERROR_FILE_NOT_FOUND;
  3485. }
  3486. Exit:
  3487. //
  3488. // If we are leaving successfully, then
  3489. // save the local profile directory.
  3490. //
  3491. if (bRetVal) {
  3492. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: setting default profile to <%s>"), lpNetPath));
  3493. } else {
  3494. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: setting default profile to NULL")));
  3495. //
  3496. // resetting it to NULL in case we didn't see the server directory.
  3497. //
  3498. if (lpProfile->lpDefaultProfile) {
  3499. *lpProfile->lpDefaultProfile = TEXT('\0');
  3500. }
  3501. }
  3502. //
  3503. // Tag the internal flags so we don't do this again.
  3504. //
  3505. lpProfile->dwInternalFlags |= DEFAULT_NET_READY;
  3506. //
  3507. // Now set the last error
  3508. //
  3509. //
  3510. // Revert before trying to delete the local default network profile
  3511. //
  3512. RevertToUser(&hOldToken);
  3513. //
  3514. // We will keep this on always so that we can delete any preexisting
  3515. // default network profile, try to delete it and ignore
  3516. // the failure if it happens
  3517. //
  3518. // Expand the local profile directory
  3519. //
  3520. dwSize = ARRAYSIZE(szLocalDir);
  3521. if (!GetProfilesDirectoryEx(szLocalDir, &dwSize, TRUE)) {
  3522. DebugMsg((DM_WARNING, TEXT("CheckNetDefaultProfile: Failed to get default user profile.")));
  3523. SetLastError(dwErr);
  3524. return bRetVal;
  3525. }
  3526. lpEnd = CheckSlash (szLocalDir);
  3527. lstrcpy (lpEnd, DEFAULT_USER_NETWORK);
  3528. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Removing local copy of network default user profile.")));
  3529. Delnode (szLocalDir);
  3530. //
  3531. // Verbose Output
  3532. //
  3533. DebugMsg((DM_VERBOSE, TEXT("CheckNetDefaultProfile: Leaving with a value of %d."), bRetVal));
  3534. SetLastError(dwErr);
  3535. return bRetVal;
  3536. }
  3537. //*************************************************************
  3538. //
  3539. // ParseProfilePath()
  3540. //
  3541. // Purpose: Parses the profile path to determine if
  3542. // it points at a directory or a filename.
  3543. // In addition it determines whether a profile is
  3544. // acoss a slow link and whether the user has access
  3545. // to the profile.
  3546. //
  3547. // Parameters: lpProfile - Profile Information
  3548. // lpProfilePath - Input path
  3549. //
  3550. // Return: TRUE if successful
  3551. // FALSE if an error occurs
  3552. //
  3553. // Comments:
  3554. //
  3555. // History: Date Author Comment
  3556. // 6/6/95 ericflo Created
  3557. //
  3558. //*************************************************************
  3559. BOOL ParseProfilePath(LPPROFILE lpProfile, LPTSTR lpProfilePath, BOOL *bpCSCBypassed, TCHAR *cpDrive)
  3560. {
  3561. DWORD dwAttributes;
  3562. LPTSTR lpEnd;
  3563. BOOL bRetVal = FALSE;
  3564. BOOL bMandatory = FALSE;
  3565. DWORD dwStart, dwDelta, dwErr = ERROR_SUCCESS;
  3566. DWORD dwStrLen;
  3567. HANDLE hOldToken;
  3568. TCHAR szErr[MAX_PATH];
  3569. BOOL bAddAdminGroup = FALSE;
  3570. BOOL bReadOnly = FALSE;
  3571. HKEY hSubKey;
  3572. DWORD dwSize, dwType;
  3573. BOOL bImpersonated = FALSE;
  3574. LPTSTR lpCscBypassedPath = NULL;
  3575. //
  3576. // Verbose output
  3577. //
  3578. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Entering, lpProfilePath = <%s>"),
  3579. lpProfilePath));
  3580. if (lpProfile->dwUserPreference == USERINFO_LOCAL) {
  3581. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: User preference is local. Ignoring roaming profile path")));
  3582. goto DisableAndExit;
  3583. }
  3584. //
  3585. // Check for .man extension
  3586. //
  3587. dwStrLen = lstrlen (lpProfilePath);
  3588. if (dwStrLen >= 4) {
  3589. lpEnd = lpProfilePath + dwStrLen - 4;
  3590. if (!lstrcmpi(lpEnd, c_szMAN)) {
  3591. bMandatory = TRUE;
  3592. lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
  3593. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Mandatory profile (.man extension)")));
  3594. }
  3595. }
  3596. //
  3597. // Check whether we need to give access to the admin on the RUP share
  3598. //
  3599. //
  3600. // Check for a roaming profile security/read only preference
  3601. //
  3602. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  3603. &hSubKey) == ERROR_SUCCESS) {
  3604. dwSize = sizeof(bAddAdminGroup);
  3605. RegQueryValueEx(hSubKey, ADD_ADMIN_GROUP_TO_RUP, NULL, &dwType,
  3606. (LPBYTE) &bAddAdminGroup, &dwSize);
  3607. dwSize = sizeof(bReadOnly);
  3608. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  3609. (LPBYTE) &bReadOnly, &dwSize);
  3610. RegCloseKey(hSubKey);
  3611. }
  3612. //
  3613. // Check for a roaming profile security/read only policy
  3614. //
  3615. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ,
  3616. &hSubKey) == ERROR_SUCCESS) {
  3617. dwSize = sizeof(bAddAdminGroup);
  3618. RegQueryValueEx(hSubKey, ADD_ADMIN_GROUP_TO_RUP, NULL, &dwType,
  3619. (LPBYTE) &bAddAdminGroup, &dwSize);
  3620. dwSize = sizeof(bReadOnly);
  3621. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  3622. (LPBYTE) &bReadOnly, &dwSize);
  3623. RegCloseKey(hSubKey);
  3624. }
  3625. if (bReadOnly) {
  3626. lpProfile->dwInternalFlags |= PROFILE_READONLY;
  3627. }
  3628. //
  3629. // Impersonate the user
  3630. //
  3631. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  3632. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to impersonate user")));
  3633. // last error is already set.
  3634. return FALSE;
  3635. }
  3636. bImpersonated = TRUE;
  3637. // Check whether RUP share is CSCed, if it is give a warning.
  3638. CheckRUPShare(lpProfilePath);
  3639. //
  3640. // Try to bypass CSC to avoid conflicts in syncing files between roaming share & local profile
  3641. //
  3642. if (IsUNCPath(lpProfilePath)) {
  3643. if ((dwErr = AbleToBypassCSC(lpProfile->hTokenUser, lpProfilePath, &lpCscBypassedPath, cpDrive)) == ERROR_SUCCESS) {
  3644. *bpCSCBypassed = TRUE;
  3645. lpProfilePath = lpCscBypassedPath;
  3646. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: CSC bypassed. Profile path %s"), lpProfilePath));
  3647. }
  3648. else {
  3649. if (dwErr == WN_BAD_LOCALNAME || dwErr == WN_ALREADY_CONNECTED || dwErr == ERROR_BAD_PROVIDER) {
  3650. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: CSC bypassed failed. Profile path %s"), lpProfilePath));
  3651. dwErr = ERROR_SUCCESS;
  3652. }
  3653. else {
  3654. // Share is not up. So we do not need to do any further check
  3655. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: CSC bypassed failed. Ignoring Roaming profile path")));
  3656. goto Exit;
  3657. }
  3658. }
  3659. }
  3660. //
  3661. // Start by calling GetFileAttributes so we have file attributes
  3662. // to work with. We have to call GetFileAttributes twice. The
  3663. // first call sets up the session so we can call it again and
  3664. // get accurate timing information for slow link detection.
  3665. //
  3666. dwAttributes = GetFileAttributes(lpProfilePath);
  3667. if (dwAttributes != -1) {
  3668. dwStart = GetTickCount();
  3669. dwAttributes = GetFileAttributes(lpProfilePath);
  3670. dwDelta = GetTickCount() - dwStart;
  3671. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Tick Count = %d"), dwDelta));
  3672. //
  3673. // if it is success, find out whether the profile is
  3674. // across a slow link.
  3675. //
  3676. // Looks like this is possible at least when a
  3677. // share doesn't exist on a server across a slow link.
  3678. // if this is not possible
  3679. // then checkforslowlink will have to be moved down to check
  3680. // after we have found a valid share
  3681. //
  3682. if (!bMandatory && !bReadOnly) {
  3683. CheckForSlowLink (lpProfile, dwDelta, lpProfile->lpProfilePath, TRUE);
  3684. if (lpProfile->dwInternalFlags & PROFILE_SLOW_LINK) {
  3685. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Profile is across a slow link. Ignoring roaming profile path")));
  3686. goto DisableAndExit;
  3687. }
  3688. }
  3689. }
  3690. else {
  3691. dwErr = GetLastError(); // get the error now for later use
  3692. }
  3693. //
  3694. // if we have got a valid handle
  3695. //
  3696. if (dwAttributes != -1) {
  3697. //
  3698. // GetFileAttributes found something.
  3699. // look at the file attributes.
  3700. //
  3701. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: GetFileAttributes found something with attributes <0x%x>"),
  3702. dwAttributes));
  3703. //
  3704. // If we found a directory, we have a proper profile
  3705. // directory. exit.
  3706. //
  3707. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  3708. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a directory")));
  3709. bRetVal = TRUE;
  3710. goto Exit;
  3711. }
  3712. else {
  3713. //
  3714. // We found a file.
  3715. //
  3716. // In 3.51, we used to have a file for the profile.
  3717. //
  3718. // In the migration part of the code, we used to take this file
  3719. // nad migrate to a directory that ends in .pds (for normal profiles)
  3720. // and .pdm for (for mandatory profiles).
  3721. //
  3722. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Found a file")));
  3723. }
  3724. dwErr = ERROR_PATH_NOT_FOUND;
  3725. goto Exit;
  3726. }
  3727. //
  3728. // GetFileAttributes failed. Look at the error to determine why.
  3729. //
  3730. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: GetFileAttributes failed with error %d"),
  3731. dwErr));
  3732. if (bMandatory) {
  3733. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Couldn't access mandatory profile <%s> with error %d"), lpProfilePath, GetLastError()));
  3734. goto Exit;
  3735. }
  3736. if (bReadOnly) {
  3737. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Couldn't access mandatory profile <%s> with error %d"), lpProfilePath, GetLastError()));
  3738. goto Exit;
  3739. }
  3740. //
  3741. // To fix bug #414176, the last error code chk has been added.
  3742. //
  3743. // ERROR_BAD_NET_NAME is the error code that is returned by GetFileAttributes
  3744. // when the profile directory for a user actually points to the root
  3745. // of the share.
  3746. // CreateDirectory should succeed.
  3747. //
  3748. if ( (dwErr == ERROR_FILE_NOT_FOUND) ||
  3749. (dwErr == ERROR_PATH_NOT_FOUND) ||
  3750. (dwErr == ERROR_BAD_NET_NAME) ) {
  3751. //
  3752. // Nothing found with this name.
  3753. //
  3754. // In 3.51, we used to have a file for the profile.
  3755. //
  3756. // In the migration part of the code, we used to take this file
  3757. // nad migrate to a directory that ends in .pds (for normal profiles)
  3758. // and .pdm for (for mandatory profiles).
  3759. //
  3760. if (CreateSecureDirectory(lpProfile, lpProfilePath, NULL, !bAddAdminGroup)) {
  3761. //
  3762. // Successfully created the directory.
  3763. //
  3764. DebugMsg((DM_VERBOSE, TEXT("ParseProfilePath: Succesfully created the sub-directory")));
  3765. bRetVal = TRUE;
  3766. goto Exit;
  3767. } else {
  3768. dwErr = GetLastError();
  3769. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to create user sub-directory. Error = %d"),
  3770. GetLastError()));
  3771. goto Exit;
  3772. }
  3773. }
  3774. goto Exit;
  3775. Exit:
  3776. if (!bRetVal) {
  3777. //
  3778. // We have failed to connect to the profile server for some reason.
  3779. // Now evaluate whether we want to disable profile and log the user in
  3780. // or prevent the user from logging on.
  3781. //
  3782. // In addition give an appropriate popup..
  3783. //
  3784. if (IsUserAnAdminMember(lpProfile->hTokenUser)) {
  3785. if (bMandatory) {
  3786. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_MANDATORY_NOT_AVAILABLE_DISABLE, GetErrString(dwErr, szErr));
  3787. }
  3788. else if (bReadOnly) {
  3789. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_READONLY_NOT_AVAILABLE_DISABLE, GetErrString(dwErr, szErr));
  3790. }
  3791. else {
  3792. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_CENTRAL_NOT_AVAILABLE_DISABLE, GetErrString(dwErr, szErr));
  3793. }
  3794. goto DisableAndExit;
  3795. }
  3796. else {
  3797. if (bMandatory) {
  3798. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_MANDATORY_NOT_AVAILABLE_ERROR, GetErrString(dwErr, szErr));
  3799. }
  3800. else if (bReadOnly) {
  3801. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_READONLY_NOT_AVAILABLE_DISABLE, GetErrString(dwErr, szErr));
  3802. goto DisableAndExit;
  3803. // temporary profile decisions will kick in, in restoreuserprofile later on..
  3804. }
  3805. else {
  3806. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_CENTRAL_NOT_AVAILABLE_DISABLE, GetErrString(dwErr, szErr));
  3807. goto DisableAndExit;
  3808. // temporary profile decisions will kick in, in restoreuserprofile later on..
  3809. }
  3810. }
  3811. }
  3812. else {
  3813. lstrcpy(lpProfile->lpRoamingProfile, lpProfilePath);
  3814. }
  3815. goto CleanupAndExit;
  3816. DisableAndExit:
  3817. lpProfile->lpRoamingProfile[0] = TEXT('\0');
  3818. bRetVal = TRUE;
  3819. CleanupAndExit:
  3820. //
  3821. // Revert to being 'ourself'
  3822. //
  3823. if(bImpersonated) {
  3824. if (!RevertToUser(&hOldToken)) {
  3825. DebugMsg((DM_WARNING, TEXT("ParseProfilePath: Failed to revert to self")));
  3826. }
  3827. }
  3828. if (lpCscBypassedPath) {
  3829. LocalFree(lpCscBypassedPath);
  3830. }
  3831. if (!bRetVal)
  3832. SetLastError(dwErr);
  3833. return bRetVal;
  3834. }
  3835. //*************************************************************
  3836. //
  3837. // GetExclusionList()
  3838. //
  3839. // Purpose: Get's the exclusion list used at logon
  3840. //
  3841. // Parameters: lpProfile - Profile Information
  3842. //
  3843. // Return: TRUE if successful
  3844. // FALSE if an error occurs
  3845. //
  3846. //*************************************************************
  3847. BOOL GetExclusionList (LPPROFILE lpProfile)
  3848. {
  3849. LPTSTR szExcludeListLocal = NULL;
  3850. LPTSTR szExcludeListServer = NULL;
  3851. LPTSTR szNTUserIni = NULL;
  3852. LPTSTR lpEnd;
  3853. HANDLE hOldToken;
  3854. BOOL bRetVal = FALSE;
  3855. //
  3856. // Allocate memory for Local variables to avoid stack overflow
  3857. //
  3858. szExcludeListLocal = (LPTSTR)LocalAlloc(LPTR, 2*MAX_PATH*sizeof(TCHAR));
  3859. if (!szExcludeListLocal) {
  3860. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Out of memory")));
  3861. goto Exit;
  3862. }
  3863. szExcludeListServer = (LPTSTR)LocalAlloc(LPTR, 2*MAX_PATH*sizeof(TCHAR));
  3864. if (!szExcludeListServer) {
  3865. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Out of memory")));
  3866. goto Exit;
  3867. }
  3868. szNTUserIni = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  3869. if (!szNTUserIni) {
  3870. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Out of memory")));
  3871. goto Exit;
  3872. }
  3873. //
  3874. // Impersonate the user
  3875. //
  3876. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  3877. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Failed to impersonate user")));
  3878. // last error is set
  3879. goto Exit;
  3880. }
  3881. //
  3882. // Get the exclusion list from the server
  3883. //
  3884. szExcludeListServer[0] = TEXT('\0');
  3885. lstrcpy (szNTUserIni, lpProfile->lpRoamingProfile);
  3886. lpEnd = CheckSlash (szNTUserIni);
  3887. lstrcpy(lpEnd, c_szNTUserIni);
  3888. GetPrivateProfileString (PROFILE_GENERAL_SECTION,
  3889. PROFILE_EXCLUSION_LIST,
  3890. TEXT(""), szExcludeListServer,
  3891. 2*MAX_PATH,
  3892. szNTUserIni);
  3893. //
  3894. // Get the exclusion list from the cache
  3895. //
  3896. szExcludeListLocal[0] = TEXT('\0');
  3897. lstrcpy (szNTUserIni, lpProfile->lpLocalProfile);
  3898. lpEnd = CheckSlash (szNTUserIni);
  3899. lstrcpy(lpEnd, c_szNTUserIni);
  3900. GetPrivateProfileString (PROFILE_GENERAL_SECTION,
  3901. PROFILE_EXCLUSION_LIST,
  3902. TEXT(""), szExcludeListLocal,
  3903. 2*MAX_PATH,
  3904. szNTUserIni);
  3905. //
  3906. // Go back to system security context
  3907. //
  3908. if (!RevertToUser(&hOldToken)) {
  3909. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Failed to revert to self")));
  3910. }
  3911. //
  3912. // See if the lists are the same
  3913. //
  3914. if (!lstrcmpi (szExcludeListServer, szExcludeListLocal)) {
  3915. if (szExcludeListServer[0] != TEXT('\0')) {
  3916. lpProfile->lpExclusionList = (LPTSTR)LocalAlloc (LPTR, (lstrlen (szExcludeListServer) + 1) * sizeof(TCHAR));
  3917. if (lpProfile->lpExclusionList) {
  3918. lstrcpy (lpProfile->lpExclusionList, szExcludeListServer);
  3919. DebugMsg((DM_VERBOSE, TEXT("GetExclusionList: The exclusion lists on both server and client are the same. The list is: <%s>"),
  3920. szExcludeListServer));
  3921. } else {
  3922. DebugMsg((DM_WARNING, TEXT("GetExclusionList: Failed to allocate memory for exclusion list with error %d"),
  3923. GetLastError()));
  3924. }
  3925. } else {
  3926. DebugMsg((DM_VERBOSE, TEXT("GetExclusionList: The exclusion on both server and client is empty.")));
  3927. }
  3928. } else {
  3929. DebugMsg((DM_VERBOSE, TEXT("GetExclusionList: The exclusion lists between server and client are different. Server is <%s> and client is <%s>"),
  3930. szExcludeListServer, szExcludeListLocal));
  3931. }
  3932. bRetVal = TRUE;
  3933. Exit:
  3934. if (szExcludeListLocal) {
  3935. LocalFree(szExcludeListLocal);
  3936. }
  3937. if (szExcludeListServer) {
  3938. LocalFree(szExcludeListServer);
  3939. }
  3940. if (szNTUserIni) {
  3941. LocalFree(szNTUserIni);
  3942. }
  3943. return bRetVal;
  3944. }
  3945. //*************************************************************
  3946. //
  3947. // RestoreUserProfile()
  3948. //
  3949. // Purpose: Downloads the user's profile if possible,
  3950. // otherwise use either cached profile or
  3951. // default profile.
  3952. //
  3953. // Parameters: lpProfile - Profile information
  3954. //
  3955. // Return: TRUE if successful
  3956. // FALSE if an error occurs
  3957. //
  3958. // Comments:
  3959. //
  3960. // History: Date Author Comment
  3961. // 6/19/95 ericflo Created
  3962. //
  3963. //*************************************************************
  3964. BOOL RestoreUserProfile(LPPROFILE lpProfile)
  3965. {
  3966. BOOL IsCentralReachable = FALSE;
  3967. BOOL IsLocalReachable = FALSE;
  3968. BOOL IsMandatory = FALSE;
  3969. BOOL IsProfilePathNULL = FALSE;
  3970. BOOL bCreateCentralProfile = FALSE;
  3971. BOOL bDefaultUsed = FALSE;
  3972. BOOL bCreateLocalProfile = TRUE;
  3973. LPTSTR lpRoamingProfile = NULL;
  3974. LPTSTR lpLocalProfile;
  3975. BOOL bProfileLoaded = FALSE;
  3976. BOOL bDefaultProfileIssued = FALSE;
  3977. BOOL bNewUser = TRUE;
  3978. LPTSTR SidString;
  3979. LONG error = ERROR_SUCCESS;
  3980. LPTSTR szProfile = NULL;
  3981. LPTSTR szDefaultProfile = NULL;
  3982. LPTSTR lpEnd;
  3983. BOOL bRet;
  3984. DWORD dwSize, dwFlags, dwErr=0, dwErr1;
  3985. HANDLE hOldToken;
  3986. LPTSTR szErr = NULL;
  3987. BOOL bOwnerOK = TRUE;
  3988. //
  3989. // Get the error at the beginning of the call.
  3990. //
  3991. dwErr1 = GetLastError();
  3992. //
  3993. // Verbose output
  3994. //
  3995. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Entering")));
  3996. //
  3997. // Get the Sid string for the current user
  3998. //
  3999. SidString = GetSidString(lpProfile->hTokenUser);
  4000. if (!SidString) {
  4001. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to get sid string for user")));
  4002. return FALSE;
  4003. }
  4004. //
  4005. // Allocate memory for Local variables to avoid stack overflow
  4006. //
  4007. szProfile = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  4008. if (!szProfile) {
  4009. dwErr = GetLastError();
  4010. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Out of memory")));
  4011. goto CleanUp;
  4012. }
  4013. szDefaultProfile = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  4014. if (!szDefaultProfile) {
  4015. dwErr = GetLastError();
  4016. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Out of memory")));
  4017. goto CleanUp;
  4018. }
  4019. szErr = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  4020. if (!szErr) {
  4021. dwErr = GetLastError();
  4022. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Out of memory")));
  4023. goto CleanUp;
  4024. }
  4025. //
  4026. // Test if this user is a guest.
  4027. //
  4028. if (IsUserAGuest(lpProfile->hTokenUser)) {
  4029. lpProfile->dwInternalFlags |= PROFILE_GUEST_USER;
  4030. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: User is a Guest")));
  4031. }
  4032. //
  4033. // Test if this user is an admin.
  4034. //
  4035. if (IsUserAnAdminMember(lpProfile->hTokenUser)) {
  4036. lpProfile->dwInternalFlags |= PROFILE_ADMIN_USER;
  4037. lpProfile->dwInternalFlags &= ~PROFILE_GUEST_USER;
  4038. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: User is a Admin")));
  4039. }
  4040. //
  4041. // Decide if the central profilemage is available.
  4042. //
  4043. IsCentralReachable = IsCentralProfileReachable(lpProfile,
  4044. &bCreateCentralProfile,
  4045. &IsMandatory,
  4046. &bOwnerOK);
  4047. if (IsCentralReachable) {
  4048. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is reachable")));
  4049. if (IsMandatory) {
  4050. lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
  4051. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is mandatory")));
  4052. } else {
  4053. lpProfile->dwInternalFlags |= PROFILE_UPDATE_CENTRAL;
  4054. lpProfile->dwInternalFlags |= bCreateCentralProfile ? PROFILE_NEW_CENTRAL : 0;
  4055. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Central Profile is roaming")));
  4056. if ((lpProfile->dwUserPreference == USERINFO_LOCAL) ||
  4057. (lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) {
  4058. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Ignoring central profile due to User Preference of Local only (or slow link).")));
  4059. IsProfilePathNULL = TRUE;
  4060. IsCentralReachable = FALSE;
  4061. goto CheckLocal;
  4062. }
  4063. }
  4064. } else {
  4065. if (*lpProfile->lpRoamingProfile) {
  4066. error = GetLastError();
  4067. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: IsCentralProfileReachable returned FALSE. error = %d"),
  4068. error));
  4069. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  4070. dwErr = error;
  4071. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_MANDATORY_NOT_AVAILABLE_ERROR, GetErrString(error, szErr));
  4072. goto Exit;
  4073. } else if (lpProfile->dwInternalFlags & PROFILE_READONLY) {
  4074. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_READONLY_NOT_AVAILABLE, GetErrString(error, szErr));
  4075. *lpProfile->lpRoamingProfile = TEXT('\0');
  4076. } else if (!bOwnerOK) {
  4077. ReportError(lpProfile->hTokenUser, EVENT_ERROR_TYPE, 0, EVENT_LOGON_RUP_NOT_SECURE);
  4078. *lpProfile->lpRoamingProfile = TEXT('\0');
  4079. } else {
  4080. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_CENTRAL_NOT_AVAILABLE, GetErrString(error, szErr));
  4081. *lpProfile->lpRoamingProfile = TEXT('\0');
  4082. }
  4083. }
  4084. }
  4085. //
  4086. // do not create a new profile locally if there is a central profile and
  4087. // it is not reachable and if we do not have slow link or user preferences set
  4088. // or read only profile.
  4089. //
  4090. if ((lpProfile->lpProfilePath) && (*lpProfile->lpProfilePath)) {
  4091. if ((!IsCentralReachable) &&
  4092. (lpProfile->dwUserPreference != USERINFO_LOCAL) &&
  4093. (!(lpProfile->dwInternalFlags & PROFILE_SLOW_LINK)) &&
  4094. (!(lpProfile->dwInternalFlags & PROFILE_READONLY)))
  4095. bCreateLocalProfile = FALSE;
  4096. }
  4097. lpRoamingProfile = lpProfile->lpRoamingProfile;
  4098. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Profile path = <%s>"), lpRoamingProfile ? lpRoamingProfile : TEXT("")));
  4099. if (!lpRoamingProfile || !(*lpRoamingProfile)) {
  4100. IsProfilePathNULL = TRUE;
  4101. }
  4102. CheckLocal:
  4103. //
  4104. // Determine if the local copy of the profilemage is available.
  4105. //
  4106. IsLocalReachable = GetExistingLocalProfileImage(lpProfile);
  4107. if (IsLocalReachable) {
  4108. DebugMsg((DM_VERBOSE, TEXT("Local Existing Profile Image is reachable")));
  4109. //
  4110. // If we assign a TEMP profile from previous session due to leak
  4111. // then issue a error message
  4112. //
  4113. if (lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) {
  4114. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_TEMPPROFILEASSIGNED);
  4115. }
  4116. } else {
  4117. bNewUser = FALSE;
  4118. if (bCreateLocalProfile)
  4119. {
  4120. bNewUser = CreateLocalProfileImage(lpProfile, lpProfile->lpUserName);
  4121. if (!bNewUser) {
  4122. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CreateLocalProfileImage failed. Unable to create a new profile!")));
  4123. }
  4124. else {
  4125. DebugMsg((DM_VERBOSE, TEXT("Creating Local Profile")));
  4126. IsLocalReachable = TRUE;
  4127. }
  4128. }
  4129. if (!bNewUser) {
  4130. if (lpProfile->dwFlags & PI_LITELOAD) {
  4131. //
  4132. // in lite load conditions we do not load a profile if it is not going to be cached on the machine.
  4133. //
  4134. dwErr = GetLastError();
  4135. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Profile not loaded because server is unavailable during liteload")));
  4136. goto Exit;
  4137. }
  4138. //
  4139. // if the user is not admin and is not allowed to create temp profile log him out.
  4140. //
  4141. if ((!(lpProfile->dwInternalFlags & PROFILE_ADMIN_USER)) && (!IsTempProfileAllowed())) {
  4142. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: User being logged off because of no temp profile policy")));
  4143. //
  4144. // We have already lost the error returned from parseprofilepath. PATH_NOT_FOUND sounds quite close.
  4145. // returning this.
  4146. //
  4147. dwErr = ERROR_PATH_NOT_FOUND;
  4148. goto Exit;
  4149. }
  4150. if (!CreateLocalProfileImage(lpProfile, TEMP_PROFILE_NAME_BASE)) {
  4151. dwErr = GetLastError();
  4152. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CreateLocalProfileImage with TEMP failed with error %d. Unable to issue temporary profile!"), dwErr));
  4153. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_TEMP_DIR_FAILED, GetErrString(dwErr, szErr));
  4154. goto Exit;
  4155. }
  4156. else {
  4157. lpProfile->dwInternalFlags |= PROFILE_TEMP_ASSIGNED;
  4158. if (!bCreateLocalProfile)
  4159. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_TEMPPROFILEASSIGNED);
  4160. else {
  4161. //
  4162. // We have failed to create a local profile. So issue a proper error message.
  4163. //
  4164. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_TEMPPROFILEASSIGNED2);
  4165. }
  4166. }
  4167. }
  4168. // clear any partly loaded flag if it exists, since this is a new profile.
  4169. lpProfile->dwInternalFlags &= ~PROFILE_PARTLY_LOADED;
  4170. lpProfile->dwInternalFlags |= PROFILE_NEW_LOCAL;
  4171. }
  4172. lpLocalProfile = lpProfile->lpLocalProfile;
  4173. DebugMsg((DM_VERBOSE, TEXT("Local profile name is <%s>"), lpLocalProfile));
  4174. //
  4175. // If we assign a TEMP profile from previous session due to leak
  4176. // then do not reconcile RUP with TEMP profile
  4177. //
  4178. if ((lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) && IsCentralReachable) {
  4179. IsCentralReachable = FALSE;
  4180. }
  4181. //
  4182. // We can do a couple of quick checks here to filter out
  4183. // new users.
  4184. //
  4185. if (( (lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL) &&
  4186. (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL) ) ||
  4187. (!IsCentralReachable &&
  4188. (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL) )) {
  4189. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Working with a new user. Go straight to issuing a default profile.")));
  4190. goto IssueDefault;
  4191. }
  4192. //
  4193. // If both central and local profileimages exist, reconcile them
  4194. // and load.
  4195. //
  4196. if (IsCentralReachable && IsLocalReachable) {
  4197. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Reconciling roaming profile with local profile")));
  4198. GetExclusionList (lpProfile);
  4199. //
  4200. // Impersonate the user
  4201. //
  4202. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  4203. bProfileLoaded = FALSE;
  4204. dwErr = GetLastError();
  4205. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to impersonate user")));
  4206. goto Exit;
  4207. }
  4208. //
  4209. // Copy the profile
  4210. //
  4211. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  4212. //
  4213. // if the roaming profile is empty and the local profile is
  4214. // mandatory, treat the profile as mandatory.
  4215. //
  4216. // Same as Win2k
  4217. //
  4218. if ((lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL) &&
  4219. (lpProfile->dwInternalFlags & PROFILE_LOCALMANDATORY)) {
  4220. lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
  4221. }
  4222. //
  4223. // This can possibly be a transition from mandatory to non mandatory.
  4224. // In that case, since the local profile is mandatory
  4225. // we wouldn't expect any items from here to be synced with the
  4226. // server yet. Go for a full sync with server but the profile will
  4227. // not be marked mandatory from now on.
  4228. //
  4229. if ((lpProfile->dwInternalFlags & PROFILE_MANDATORY) ||
  4230. (lpProfile->dwInternalFlags & PROFILE_READONLY) ||
  4231. (lpProfile->dwInternalFlags & PROFILE_LOCALMANDATORY)) {
  4232. dwFlags |= (CPD_COPYIFDIFFERENT | CPD_SYNCHRONIZE);
  4233. }
  4234. if (lpProfile->dwFlags & (PI_LITELOAD | PI_HIDEPROFILE)) {
  4235. dwFlags |= CPD_SYSTEMFILES | CPD_SYSTEMDIRSONLY;
  4236. }
  4237. else
  4238. dwFlags |= CPD_NONENCRYPTEDONLY;
  4239. //
  4240. // Profile unload time does not exist for mandatory, temp and read only profile.
  4241. // But for read only profile we still want to use exclusion list without any ref time
  4242. //
  4243. if (lpProfile->lpExclusionList && *lpProfile->lpExclusionList) {
  4244. if (lpProfile->dwInternalFlags & PROFILE_READONLY) {
  4245. dwFlags |= CPD_USEEXCLUSIONLIST;
  4246. }
  4247. else if (lpProfile->ftProfileUnload.dwHighDateTime || lpProfile->ftProfileUnload.dwLowDateTime) {
  4248. dwFlags |= (CPD_USEDELREFTIME | CPD_SYNCHRONIZE | CPD_USEEXCLUSIONLIST);
  4249. }
  4250. }
  4251. //
  4252. // If roaming copy is partial (due to LITE upload) then ignore the hive and
  4253. // synchronize logic as it will end up deleting files from destination - a
  4254. // massive data loss.
  4255. //
  4256. if (IsPartialRoamingProfile(lpProfile)) {
  4257. dwFlags &= ~CPD_SYNCHRONIZE;
  4258. dwFlags |= CPD_IGNOREHIVE;
  4259. }
  4260. //
  4261. // Check whether in local machine user profile is switching from local to
  4262. // roaming for first time. If yes and we have a existing hive in RUP share
  4263. // then always overwrite the local hive with hive in RUP share. This is
  4264. // to avoid wrong hive usage due to cached login
  4265. //
  4266. TouchLocalHive(lpProfile);
  4267. bRet = CopyProfileDirectoryEx (lpRoamingProfile,
  4268. lpLocalProfile,
  4269. dwFlags, &lpProfile->ftProfileUnload,
  4270. lpProfile->lpExclusionList);
  4271. //
  4272. // Revert to being 'ourself'
  4273. //
  4274. if (!RevertToUser(&hOldToken)) {
  4275. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to revert to self")));
  4276. }
  4277. if (!bRet) {
  4278. error = GetLastError();
  4279. if (error == ERROR_DISK_FULL) {
  4280. dwErr = error;
  4281. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: CopyProfileDirectory failed because of DISK_FULL, Exitting")));
  4282. goto Exit;
  4283. }
  4284. if (error == ERROR_FILE_ENCRYPTED) {
  4285. dwErr = error;
  4286. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CopyProfileDirectory returned FALSE. Error = %d"), error));
  4287. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_PROFILEUPDATE_6002);
  4288. lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
  4289. // show the popup but exit only in the case if it is a new local profile
  4290. if (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)
  4291. goto IssueDefault;
  4292. }
  4293. else {
  4294. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: CopyProfileDirectory failed. Issuing default profile")));
  4295. lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
  4296. lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
  4297. goto IssueDefault;
  4298. }
  4299. }
  4300. lstrcpy (szProfile, lpLocalProfile);
  4301. lpEnd = CheckSlash(szProfile);
  4302. //
  4303. // If the central profile is unreachable and the local profile
  4304. // is manatory, treat it as mandatory. This is the same as Win2k
  4305. //
  4306. // We are not copying anything from the server
  4307. //
  4308. if (lpProfile->dwInternalFlags & PROFILE_LOCALMANDATORY) {
  4309. lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
  4310. }
  4311. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  4312. lstrcpy (lpEnd, c_szNTUserMan);
  4313. } else {
  4314. lstrcpy (lpEnd, c_szNTUserDat);
  4315. }
  4316. error = MyRegLoadKey(HKEY_USERS, SidString, szProfile);
  4317. bProfileLoaded = (error == ERROR_SUCCESS);
  4318. //
  4319. // If we failed to load the central profile for some
  4320. // reason, don't update it when we log off.
  4321. //
  4322. if (bProfileLoaded) {
  4323. goto Exit;
  4324. } else {
  4325. dwErr = error;
  4326. lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
  4327. lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
  4328. if (error == ERROR_BADDB) {
  4329. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_FAILED_LOAD_1009);
  4330. goto IssueDefault;
  4331. } else if (error == ERROR_NO_SYSTEM_RESOURCES) {
  4332. goto Exit;
  4333. }
  4334. else {
  4335. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_FAILED_LOAD_LOCAL, GetErrString(error, szErr));
  4336. goto IssueDefault;
  4337. }
  4338. }
  4339. }
  4340. //
  4341. // Only a local profile exists so use it.
  4342. //
  4343. if (!IsCentralReachable && IsLocalReachable) {
  4344. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: No central profile. Attempting to load local profile.")));
  4345. lstrcpy (szProfile, lpLocalProfile);
  4346. lpEnd = CheckSlash(szProfile);
  4347. //
  4348. // If the central profile is unreachable and the local profile
  4349. // is manatory, treat it as mandatory. This is the same as Win2k
  4350. //
  4351. // We are not copying anything from the server
  4352. //
  4353. if (lpProfile->dwInternalFlags & PROFILE_LOCALMANDATORY) {
  4354. lpProfile->dwInternalFlags |= PROFILE_MANDATORY;
  4355. }
  4356. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  4357. lstrcpy (lpEnd, c_szNTUserMan);
  4358. } else {
  4359. lstrcpy (lpEnd, c_szNTUserDat);
  4360. }
  4361. error = MyRegLoadKey(HKEY_USERS, SidString, szProfile);
  4362. bProfileLoaded = (error == ERROR_SUCCESS);
  4363. if (!bProfileLoaded) {
  4364. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: MyRegLoadKey returned FALSE.")));
  4365. dwErr = error;
  4366. if (error == ERROR_BADDB) {
  4367. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_FAILED_LOAD_1009);
  4368. lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
  4369. goto IssueDefault;
  4370. } else if (error == ERROR_NO_SYSTEM_RESOURCES) {
  4371. goto Exit;
  4372. } else {
  4373. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_FAILED_LOAD_LOCAL, GetErrString(error, szErr));
  4374. }
  4375. }
  4376. if (!bProfileLoaded && IsProfilePathNULL) {
  4377. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Failed to load local profile and profile path is NULL, going to overwrite local profile")));
  4378. lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
  4379. goto IssueDefault;
  4380. }
  4381. goto Exit;
  4382. }
  4383. //
  4384. // Last combination. Unable to access a local profile cache,
  4385. // but a central profile exists. Use the temporary profile.
  4386. //
  4387. if (IsCentralReachable) {
  4388. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Using temporary cache with central profile")));
  4389. GetExclusionList (lpProfile);
  4390. //
  4391. // Impersonate the user
  4392. //
  4393. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  4394. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to impersonate user")));
  4395. dwErr = GetLastError();
  4396. goto Exit;
  4397. }
  4398. //
  4399. // Local is not reachable. So Localmandatory will not be set..
  4400. //
  4401. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  4402. dwFlags |= CPD_SYNCHRONIZE;
  4403. if ((lpProfile->dwInternalFlags & PROFILE_MANDATORY) ||
  4404. (lpProfile->dwInternalFlags & PROFILE_READONLY)) {
  4405. dwFlags |= CPD_COPYIFDIFFERENT;
  4406. }
  4407. if (lpProfile->dwFlags & (PI_LITELOAD | PI_HIDEPROFILE)) {
  4408. dwFlags |= CPD_SYSTEMFILES | CPD_SYSTEMDIRSONLY;
  4409. }
  4410. else
  4411. dwFlags |= CPD_NONENCRYPTEDONLY;
  4412. //
  4413. // Profile unload time does not exist for mandatory, temp and read only profile.
  4414. // But for read only profile we still want to use exclusion list without any ref time
  4415. //
  4416. if (lpProfile->lpExclusionList && *lpProfile->lpExclusionList) {
  4417. if (lpProfile->dwInternalFlags & PROFILE_READONLY) {
  4418. dwFlags |= CPD_USEEXCLUSIONLIST;
  4419. }
  4420. else if (lpProfile->ftProfileUnload.dwHighDateTime || lpProfile->ftProfileUnload.dwLowDateTime) {
  4421. dwFlags |= (CPD_USEDELREFTIME | CPD_SYNCHRONIZE | CPD_USEEXCLUSIONLIST);
  4422. }
  4423. }
  4424. bRet = CopyProfileDirectoryEx (lpRoamingProfile,
  4425. lpLocalProfile,
  4426. dwFlags, &lpProfile->ftProfileUnload,
  4427. lpProfile->lpExclusionList);
  4428. //
  4429. // Revert to being 'ourself'
  4430. //
  4431. if (!RevertToUser(&hOldToken)) {
  4432. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to revert to self")));
  4433. }
  4434. //
  4435. // Check return value
  4436. //
  4437. if (!bRet) {
  4438. error = GetLastError();
  4439. if (error == ERROR_FILE_ENCRYPTED) {
  4440. dwErr = error;
  4441. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CopyProfileDirectory returned FALSE. Error = %d"), error));
  4442. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_PROFILEUPDATE_6002);
  4443. lpProfile->dwInternalFlags &= ~PROFILE_UPDATE_CENTRAL;
  4444. // show the popup but exit only in the case if it is a new local profile
  4445. if (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)
  4446. goto IssueDefault;
  4447. }
  4448. else {
  4449. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CopyProfileDirectory returned FALSE. Error = %d"), error));
  4450. goto Exit;
  4451. }
  4452. }
  4453. lstrcpy (szProfile, lpLocalProfile);
  4454. lpEnd = CheckSlash(szProfile);
  4455. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  4456. lstrcpy (lpEnd, c_szNTUserMan);
  4457. } else {
  4458. lstrcpy (lpEnd, c_szNTUserDat);
  4459. }
  4460. error = MyRegLoadKey(HKEY_USERS, SidString, szProfile);
  4461. bProfileLoaded = (error == ERROR_SUCCESS);
  4462. if (bProfileLoaded) {
  4463. goto Exit;
  4464. }
  4465. SetLastError(error);
  4466. dwErr = error;
  4467. if (error == ERROR_BADDB) {
  4468. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_FAILED_LOAD_1009);
  4469. // fall through
  4470. } else if (error == ERROR_NO_SYSTEM_RESOURCES) {
  4471. goto Exit;
  4472. }
  4473. //
  4474. // we will delete the contents at this point
  4475. //
  4476. lpProfile->dwInternalFlags |= PROFILE_DELETE_CACHE;
  4477. }
  4478. IssueDefault:
  4479. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Issuing default profile")));
  4480. //
  4481. // If a cache exists, delete it, since we will
  4482. // generate a new one below.
  4483. //
  4484. if (lpProfile->dwInternalFlags & PROFILE_DELETE_CACHE) {
  4485. DWORD dwDeleteFlags=0;
  4486. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Deleting cached profile directory <%s>."), lpLocalProfile));
  4487. lpProfile->dwInternalFlags &= ~PROFILE_DELETE_CACHE;
  4488. if ((!(lpProfile->dwInternalFlags & PROFILE_ADMIN_USER)) && (!IsTempProfileAllowed())) {
  4489. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: User being logged off because of no temp profile policy and is not an admin")));
  4490. //
  4491. // We should have some error from a prev. operation. depending on that.
  4492. //
  4493. goto Exit;
  4494. }
  4495. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  4496. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: User being logged off because the profile is mandatory")));
  4497. //
  4498. // We should have some error from a prev. operation. depending on that.
  4499. //
  4500. goto Exit;
  4501. }
  4502. //
  4503. // backup only if we are not using a temp profile already.
  4504. //
  4505. if (!(lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED))
  4506. dwDeleteFlags |= DP_BACKUP | DP_BACKUPEXISTS;
  4507. if ((dwDeleteFlags & DP_BACKUP) && (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)) {
  4508. dwDeleteFlags = 0;
  4509. }
  4510. if (!DeleteProfileEx (SidString, lpLocalProfile, dwDeleteFlags, HKEY_LOCAL_MACHINE, NULL)) {
  4511. dwErr = GetLastError();
  4512. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: DeleteProfileDirectory returned false. Error = %d"), dwErr));
  4513. goto Exit;
  4514. }
  4515. else {
  4516. if (dwDeleteFlags & DP_BACKUP) {
  4517. lpProfile->dwInternalFlags |= PROFILE_BACKUP_EXISTS;
  4518. ReportError(lpProfile->hTokenUser, PI_NOUI, 0, EVENT_PROFILE_DIR_BACKEDUP);
  4519. }
  4520. }
  4521. if (lpProfile->dwFlags & PI_LITELOAD) {
  4522. //
  4523. // in lite load conditions we do not load a profile if it is not going to be cached on the machine.
  4524. //
  4525. // dwErr should be set before, use the same.
  4526. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Profile not loaded because server is unavailable during liteload")));
  4527. goto Exit;
  4528. }
  4529. //
  4530. // Create a local profile to work with
  4531. //
  4532. if (!CreateLocalProfileImage(lpProfile, TEMP_PROFILE_NAME_BASE)) {
  4533. dwErr = GetLastError();
  4534. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: CreateLocalProfile Image with TEMP failed.")));
  4535. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_TEMP_DIR_FAILED, GetErrString(dwErr, szErr));
  4536. goto Exit;
  4537. }
  4538. else
  4539. {
  4540. lpProfile->dwInternalFlags |= PROFILE_TEMP_ASSIGNED;
  4541. lpProfile->dwInternalFlags |= PROFILE_NEW_LOCAL;
  4542. // clear any partly loaded flag if it exists, since this is a new profile.
  4543. lpProfile->dwInternalFlags &= ~PROFILE_PARTLY_LOADED;
  4544. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_TEMPPROFILEASSIGNED);
  4545. }
  4546. }
  4547. //
  4548. // If a default profile location was specified, try
  4549. // that first.
  4550. //
  4551. if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) )
  4552. {
  4553. CheckNetDefaultProfile (lpProfile);
  4554. }
  4555. if ( lpProfile->lpDefaultProfile && *lpProfile->lpDefaultProfile) {
  4556. if (IssueDefaultProfile (lpProfile, lpProfile->lpDefaultProfile,
  4557. lpLocalProfile, SidString,
  4558. (lpProfile->dwInternalFlags & PROFILE_MANDATORY))) {
  4559. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Successfully setup the specified default.")));
  4560. bProfileLoaded = TRUE;
  4561. goto IssueDefaultExit;
  4562. }
  4563. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: IssueDefaultProfile failed with specified default.")));
  4564. }
  4565. //
  4566. // IssueLocalDefault
  4567. //
  4568. //
  4569. // Issue the local default profile.
  4570. //
  4571. dwSize = MAX_PATH;
  4572. if (!GetDefaultUserProfileDirectory(szDefaultProfile, &dwSize)) {
  4573. dwErr = GetLastError();
  4574. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to get default user profile.")));
  4575. goto Exit;
  4576. }
  4577. if (IssueDefaultProfile (lpProfile, szDefaultProfile,
  4578. lpLocalProfile, SidString,
  4579. (lpProfile->dwInternalFlags & PROFILE_MANDATORY))) {
  4580. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Successfully setup the local default.")));
  4581. bProfileLoaded = TRUE;
  4582. goto IssueDefaultExit;
  4583. }
  4584. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: IssueDefaultProfile failed with local default.")));
  4585. dwErr = GetLastError();
  4586. IssueDefaultExit:
  4587. //
  4588. // If the default profile was successfully issued, then
  4589. // we need to set the security on the hive.
  4590. //
  4591. if (bProfileLoaded) {
  4592. if (!SetupNewHive(lpProfile, SidString, NULL)) {
  4593. dwErr = GetLastError();
  4594. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: SetupNewHive failed")));
  4595. bProfileLoaded = FALSE;
  4596. }
  4597. else {
  4598. bDefaultProfileIssued = TRUE;
  4599. }
  4600. }
  4601. Exit:
  4602. //
  4603. // If the profile was loaded, then save the profile type in the
  4604. // user's hive, and setup the "User Shell Folders" section for
  4605. // Explorer.
  4606. //
  4607. if (bProfileLoaded) {
  4608. //
  4609. // Open the Current User key. This will be closed in
  4610. // UnloadUserProfile.
  4611. //
  4612. error = RegOpenKeyEx(HKEY_USERS, SidString, 0, KEY_ALL_ACCESS,
  4613. &lpProfile->hKeyCurrentUser);
  4614. if (error != ERROR_SUCCESS) {
  4615. bProfileLoaded = FALSE;
  4616. dwErr = error;
  4617. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to open current user key. Error = %d"), error));
  4618. }
  4619. }
  4620. if ((bProfileLoaded) && (!(lpProfile->dwFlags & PI_LITELOAD))) {
  4621. //
  4622. // merge the subtrees to create the HKCR tree
  4623. //
  4624. error = LoadUserClasses( lpProfile, SidString, bDefaultProfileIssued );
  4625. if (error != ERROR_SUCCESS) {
  4626. bProfileLoaded = FALSE;
  4627. dwErr = error;
  4628. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Failed to merge classes root. Error = %d"), error));
  4629. }
  4630. }
  4631. if ((!bProfileLoaded) && (!(lpProfile->dwFlags & PI_LITELOAD))) {
  4632. error = dwErr;
  4633. //
  4634. // If the user is an Admin, then let him/her log on with
  4635. // either the .default profile, or an empty profile.
  4636. //
  4637. if (lpProfile->dwInternalFlags & PROFILE_ADMIN_USER) {
  4638. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_ADMIN_OVERRIDE, GetErrString(error, szErr));
  4639. bProfileLoaded = TRUE;
  4640. } else {
  4641. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: Could not load the user profile. Error = %d"), error));
  4642. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 1, EVENT_FAILED_LOAD_PROFILE, GetErrString(error, szErr));
  4643. if (lpProfile->hKeyCurrentUser) {
  4644. RegCloseKey (lpProfile->hKeyCurrentUser);
  4645. }
  4646. MyRegUnLoadKey(HKEY_USERS, SidString);
  4647. if ((lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)) {
  4648. if (!DeleteProfileEx (SidString, lpLocalProfile, 0, HKEY_LOCAL_MACHINE, NULL)) {
  4649. DebugMsg((DM_WARNING, TEXT("RestoreUserProfile: DeleteProfileDirectory returned false. Error = %d"), GetLastError()));
  4650. }
  4651. }
  4652. }
  4653. }
  4654. CleanUp:
  4655. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: About to Leave. Final Information follows:")));
  4656. DebugMsg((DM_VERBOSE, TEXT("Profile was %s loaded."), bProfileLoaded ? TEXT("successfully") : TEXT("NOT successfully")));
  4657. DebugMsg((DM_VERBOSE, TEXT("lpProfile->lpRoamingProfile = <%s>"), lpProfile->lpRoamingProfile));
  4658. DebugMsg((DM_VERBOSE, TEXT("lpProfile->lpLocalProfile = <%s>"), lpProfile->lpLocalProfile));
  4659. DebugMsg((DM_VERBOSE, TEXT("lpProfile->dwInternalFlags = 0x%x"), lpProfile->dwInternalFlags));
  4660. //
  4661. // Free up the user's sid string
  4662. //
  4663. DeleteSidString(SidString);
  4664. if (szProfile) {
  4665. LocalFree(szProfile);
  4666. }
  4667. if (szDefaultProfile) {
  4668. LocalFree(szDefaultProfile);
  4669. }
  4670. if (szErr) {
  4671. LocalFree(szErr);
  4672. }
  4673. if (bProfileLoaded) {
  4674. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  4675. // clear any partly loaded flag if it exists, since this is a new profile.
  4676. lpProfile->dwInternalFlags &= ~PROFILE_PARTLY_LOADED;
  4677. }
  4678. else {
  4679. if (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)
  4680. lpProfile->dwInternalFlags |= PROFILE_PARTLY_LOADED;
  4681. }
  4682. }
  4683. if (bProfileLoaded)
  4684. SetLastError(dwErr1);
  4685. else {
  4686. //
  4687. // Make sure that at least some error is returned.
  4688. //
  4689. if (!dwErr) {
  4690. dwErr = ERROR_BAD_ENVIRONMENT;
  4691. }
  4692. SetLastError(dwErr);
  4693. }
  4694. DebugMsg((DM_VERBOSE, TEXT("RestoreUserProfile: Leaving.")));
  4695. return bProfileLoaded;
  4696. }
  4697. //***************************************************************************
  4698. //
  4699. // GetProfileSidString
  4700. //
  4701. // Purpose: Allocates and returns a string representing the sid that we should
  4702. // for the profiles
  4703. //
  4704. // Parameters: hToken - user's token
  4705. //
  4706. // Return: SidString is successful
  4707. // NULL if an error occurs
  4708. //
  4709. // Comments:
  4710. // Tries to get the old sid that we used using the profile guid.
  4711. // if it doesn't exist get the sid directly from the token
  4712. //
  4713. // History: Date Author Comment
  4714. // 11/14/95 ushaji created
  4715. //***************************************************************************
  4716. LPTSTR GetProfileSidString(HANDLE hToken)
  4717. {
  4718. LPTSTR lpSidString;
  4719. TCHAR LocalProfileKey[MAX_PATH];
  4720. LONG error;
  4721. HKEY hSubKey;
  4722. //
  4723. // First, get the current user's sid and see if we have
  4724. // profile information for them.
  4725. //
  4726. lpSidString = GetSidString(hToken);
  4727. if (lpSidString) {
  4728. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  4729. lstrcat(LocalProfileKey, TEXT("\\"));
  4730. lstrcat(LocalProfileKey, lpSidString);
  4731. error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0,
  4732. KEY_READ, &hSubKey);
  4733. if (error == ERROR_SUCCESS) {
  4734. RegCloseKey(hSubKey);
  4735. return lpSidString;
  4736. }
  4737. lstrcat(LocalProfileKey, c_szBAK);
  4738. error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0,
  4739. KEY_READ, &hSubKey);
  4740. if (ERROR_SUCCESS == error) {
  4741. RegCloseKey(hSubKey);
  4742. return lpSidString;
  4743. }
  4744. DeleteSidString(lpSidString);
  4745. }
  4746. //
  4747. // Check for an old sid string
  4748. //
  4749. lpSidString = GetOldSidString(hToken, PROFILE_GUID_PATH);
  4750. if (!lpSidString) {
  4751. //
  4752. // Last resort, use the user's current sid
  4753. //
  4754. DebugMsg((DM_VERBOSE, TEXT("GetProfileSid: No Guid -> Sid Mapping available")));
  4755. lpSidString = GetSidString(hToken);
  4756. }
  4757. return lpSidString;
  4758. }
  4759. //*************************************************************
  4760. //
  4761. // TestIfUserProfileLoaded()
  4762. //
  4763. // Purpose: Test to see if this user's profile is loaded.
  4764. //
  4765. // Parameters: hToken - user's token
  4766. // lpProfileInfo - Profile information from app
  4767. //
  4768. // Return: TRUE if successful
  4769. // FALSE if an error occurs
  4770. //
  4771. // Comments:
  4772. //
  4773. // History: Date Author Comment
  4774. // 6/19/95 ericflo Ported
  4775. //
  4776. //*************************************************************
  4777. BOOL TestIfUserProfileLoaded(HANDLE hToken, LPPROFILEINFO lpProfileInfo)
  4778. {
  4779. LPTSTR SidString;
  4780. DWORD error;
  4781. HKEY hSubKey;
  4782. //
  4783. // Get the Sid string for the user
  4784. //
  4785. SidString = GetProfileSidString(hToken);
  4786. if (!SidString) {
  4787. DebugMsg((DM_WARNING, TEXT("TestIfUserProfileLoaded: Failed to get sid string for user")));
  4788. return FALSE;
  4789. }
  4790. error = RegOpenKeyEx(HKEY_USERS, SidString, 0, KEY_ALL_ACCESS, &hSubKey);
  4791. DeleteSidString(SidString);
  4792. if (error == ERROR_SUCCESS) {
  4793. DebugMsg((DM_VERBOSE, TEXT("TestIfUserProfileLoaded: Profile already loaded.")));
  4794. //
  4795. // This key will be closed in before IUserProfile->LoadUserProfile
  4796. // returns. It'll be reopened on the client side.
  4797. //
  4798. lpProfileInfo->hProfile = hSubKey;
  4799. }
  4800. SetLastError(error);
  4801. return(error == ERROR_SUCCESS);
  4802. }
  4803. //*************************************************************
  4804. //
  4805. // SecureUserKey()
  4806. //
  4807. // Purpose: Sets security on a key in the user's hive
  4808. // so only admin's can change it.
  4809. //
  4810. // Parameters: lpProfile - Profile Information
  4811. // lpKey - Key to secure
  4812. // pSid - Sid (used by CreateNewUser)
  4813. //
  4814. // Return: TRUE if successful
  4815. // FALSE if an error occurs
  4816. //
  4817. // Comments:
  4818. //
  4819. // History: Date Author Comment
  4820. // 6/20/95 ericflo Created
  4821. //
  4822. //*************************************************************
  4823. BOOL SecureUserKey(LPPROFILE lpProfile, LPTSTR lpKey, PSID pSid)
  4824. {
  4825. DWORD Error, IgnoreError;
  4826. HKEY RootKey;
  4827. SECURITY_DESCRIPTOR sd;
  4828. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  4829. PACL pAcl = NULL;
  4830. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
  4831. DWORD cbAcl, AceIndex, dwDisp;
  4832. ACE_HEADER * lpAceHeader;
  4833. BOOL bRetVal = FALSE;
  4834. BOOL bFreeSid = TRUE;
  4835. DWORD dwFlags = 0;
  4836. //
  4837. // Verbose Output
  4838. //
  4839. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Entering")));
  4840. //
  4841. // Create the security descriptor
  4842. //
  4843. //
  4844. // Give the user access by their real sid so they still have access
  4845. // when they logoff and logon again
  4846. //
  4847. if (pSid) {
  4848. psidUser = pSid;
  4849. bFreeSid = FALSE;
  4850. dwFlags = PI_NOUI;
  4851. } else {
  4852. psidUser = GetUserSid(lpProfile->hTokenUser);
  4853. dwFlags = lpProfile->dwFlags;
  4854. }
  4855. if (!psidUser) {
  4856. DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to get user sid")));
  4857. return FALSE;
  4858. }
  4859. //
  4860. // Get the system sid
  4861. //
  4862. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  4863. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  4864. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize system sid. Error = %d"), GetLastError()));
  4865. goto Exit;
  4866. }
  4867. //
  4868. // Get the admin sid
  4869. //
  4870. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  4871. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  4872. 0, 0, 0, 0, &psidAdmin)) {
  4873. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize admin sid. Error = %d"), GetLastError()));
  4874. goto Exit;
  4875. }
  4876. //
  4877. // Get the restricted sid
  4878. //
  4879. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
  4880. 0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
  4881. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize restricted sid. Error = %d"), GetLastError()));
  4882. goto Exit;
  4883. }
  4884. //
  4885. // Allocate space for the ACL
  4886. //
  4887. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  4888. (2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidRestricted)) +
  4889. sizeof(ACL) +
  4890. (8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  4891. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  4892. if (!pAcl) {
  4893. goto Exit;
  4894. }
  4895. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  4896. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize acl. Error = %d"), GetLastError()));
  4897. goto Exit;
  4898. }
  4899. //
  4900. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  4901. //
  4902. AceIndex = 0;
  4903. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) {
  4904. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for user. Error = %d"), GetLastError()));
  4905. goto Exit;
  4906. }
  4907. AceIndex++;
  4908. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  4909. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for system. Error = %d"), GetLastError()));
  4910. goto Exit;
  4911. }
  4912. AceIndex++;
  4913. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  4914. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for admin. Error = %d"), GetLastError()));
  4915. goto Exit;
  4916. }
  4917. AceIndex++;
  4918. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
  4919. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for restricted. Error = %d"), GetLastError()));
  4920. goto Exit;
  4921. }
  4922. //
  4923. // Now the inheritable ACEs
  4924. //
  4925. AceIndex++;
  4926. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) {
  4927. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for user. Error = %d"), GetLastError()));
  4928. goto Exit;
  4929. }
  4930. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  4931. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  4932. goto Exit;
  4933. }
  4934. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  4935. AceIndex++;
  4936. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  4937. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for system. Error = %d"), GetLastError()));
  4938. goto Exit;
  4939. }
  4940. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  4941. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  4942. goto Exit;
  4943. }
  4944. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  4945. AceIndex++;
  4946. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  4947. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for admin. Error = %d"), GetLastError()));
  4948. goto Exit;
  4949. }
  4950. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  4951. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  4952. goto Exit;
  4953. }
  4954. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  4955. AceIndex++;
  4956. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
  4957. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to add ace for restricted. Error = %d"), GetLastError()));
  4958. goto Exit;
  4959. }
  4960. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  4961. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  4962. goto Exit;
  4963. }
  4964. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  4965. //
  4966. // Put together the security descriptor
  4967. //
  4968. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  4969. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  4970. goto Exit;
  4971. }
  4972. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  4973. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  4974. goto Exit;
  4975. }
  4976. //
  4977. // Open the root of the user's profile
  4978. //
  4979. Error = RegCreateKeyEx(HKEY_USERS,
  4980. lpKey,
  4981. 0,
  4982. NULL,
  4983. REG_OPTION_NON_VOLATILE,
  4984. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  4985. NULL,
  4986. &RootKey,
  4987. &dwDisp);
  4988. if (Error != ERROR_SUCCESS) {
  4989. DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to open root of user registry, error = %d"), Error));
  4990. } else {
  4991. //
  4992. // Set the security descriptor on the key
  4993. //
  4994. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  4995. if (Error == ERROR_SUCCESS) {
  4996. bRetVal = TRUE;
  4997. } else {
  4998. DebugMsg((DM_WARNING, TEXT("SecureUserKey: Failed to apply security to registry key, error = %d"), Error));
  4999. SetLastError(Error);
  5000. }
  5001. RegCloseKey(RootKey);
  5002. }
  5003. Exit:
  5004. //
  5005. // Free the sids and acl
  5006. //
  5007. if (bFreeSid && psidUser) {
  5008. DeleteUserSid (psidUser);
  5009. }
  5010. if (psidRestricted) {
  5011. FreeSid(psidRestricted);
  5012. }
  5013. if (psidSystem) {
  5014. FreeSid(psidSystem);
  5015. }
  5016. if (psidAdmin) {
  5017. FreeSid(psidAdmin);
  5018. }
  5019. if (pAcl) {
  5020. GlobalFree (pAcl);
  5021. }
  5022. //
  5023. // Verbose Output
  5024. //
  5025. DebugMsg((DM_VERBOSE, TEXT("SecureUserKey: Leaving with a return value of %d"), bRetVal));
  5026. return(bRetVal);
  5027. }
  5028. //*************************************************************
  5029. //
  5030. // ApplySecurityToRegistryTree()
  5031. //
  5032. // Purpose: Applies the passed security descriptor to the passed
  5033. // key and all its descendants. Only the parts of
  5034. // the descriptor inddicated in the security
  5035. // info value are actually applied to each registry key.
  5036. //
  5037. // Parameters: RootKey - Registry key
  5038. // pSD - Security Descriptor
  5039. //
  5040. // Return: ERROR_SUCCESS if successful
  5041. //
  5042. // Comments:
  5043. //
  5044. // History: Date Author Comment
  5045. // 7/19/95 ericflo Created
  5046. //
  5047. //*************************************************************
  5048. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
  5049. {
  5050. DWORD Error, IgnoreError;
  5051. DWORD SubKeyIndex;
  5052. LPTSTR SubKeyName;
  5053. HKEY SubKey;
  5054. DWORD cchSubKeySize = MAX_PATH + 1;
  5055. //
  5056. // First apply security
  5057. //
  5058. RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
  5059. //
  5060. // Open each sub-key and apply security to its sub-tree
  5061. //
  5062. SubKeyIndex = 0;
  5063. SubKeyName = (LPTSTR)GlobalAlloc (GPTR, cchSubKeySize * sizeof(TCHAR));
  5064. if (!SubKeyName) {
  5065. DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryTree: Failed to allocate memory, error = %d"), GetLastError()));
  5066. return GetLastError();
  5067. }
  5068. while (TRUE) {
  5069. //
  5070. // Get the next sub-key name
  5071. //
  5072. Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
  5073. if (Error != ERROR_SUCCESS) {
  5074. if (Error == ERROR_NO_MORE_ITEMS) {
  5075. //
  5076. // Successful end of enumeration
  5077. //
  5078. Error = ERROR_SUCCESS;
  5079. } else {
  5080. DebugMsg((DM_WARNING, TEXT("ApplySecurityToRegistryTree: Registry enumeration failed with error = %d"), Error));
  5081. }
  5082. break;
  5083. }
  5084. //
  5085. // Open the sub-key
  5086. //
  5087. Error = RegOpenKeyEx(RootKey,
  5088. SubKeyName,
  5089. 0,
  5090. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  5091. &SubKey);
  5092. if (Error == ERROR_SUCCESS) {
  5093. //
  5094. // Apply security to the sub-tree
  5095. //
  5096. ApplySecurityToRegistryTree(SubKey, pSD);
  5097. //
  5098. // We're finished with the sub-key
  5099. //
  5100. RegCloseKey(SubKey);
  5101. }
  5102. //
  5103. // Go enumerate the next sub-key
  5104. //
  5105. SubKeyIndex ++;
  5106. }
  5107. GlobalFree (SubKeyName);
  5108. return Error;
  5109. }
  5110. //*************************************************************
  5111. //
  5112. // SetDefaultUserHiveSecurity()
  5113. //
  5114. // Purpose: Initializes a user hive with the
  5115. // appropriate acls
  5116. //
  5117. // Parameters: lpProfile - Profile Information
  5118. // pSid - Sid (used by CreateNewUser)
  5119. // RootKey - registry handle to hive root
  5120. //
  5121. // Return: ERROR_SUCCESS if successful
  5122. // other error code if an error occurs
  5123. //
  5124. // Comments:
  5125. //
  5126. // History: Date Author Comment
  5127. // 7/18/95 ericflo Created as part of
  5128. // SetupNewHive
  5129. // 3/29/98 adamed Moved out of SetupNewHive
  5130. // to this function
  5131. //
  5132. //*************************************************************
  5133. BOOL SetDefaultUserHiveSecurity(LPPROFILE lpProfile, PSID pSid, HKEY RootKey)
  5134. {
  5135. DWORD Error;
  5136. SECURITY_DESCRIPTOR sd;
  5137. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  5138. PACL pAcl = NULL;
  5139. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
  5140. DWORD cbAcl, AceIndex;
  5141. ACE_HEADER * lpAceHeader;
  5142. BOOL bRetVal = FALSE;
  5143. BOOL bFreeSid = TRUE;
  5144. DWORD dwFlags = 0;
  5145. //
  5146. // Verbose Output
  5147. //
  5148. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Entering")));
  5149. //
  5150. // Create the security descriptor that will be applied to each key
  5151. //
  5152. //
  5153. // Give the user access by their real sid so they still have access
  5154. // when they logoff and logon again
  5155. //
  5156. if (pSid) {
  5157. psidUser = pSid;
  5158. bFreeSid = FALSE;
  5159. dwFlags = PI_NOUI;
  5160. } else {
  5161. psidUser = GetUserSid(lpProfile->hTokenUser);
  5162. dwFlags = lpProfile->dwFlags;
  5163. }
  5164. if (!psidUser) {
  5165. DebugMsg((DM_WARNING, TEXT("SetDefaultUserHiveSecurity: Failed to get user sid")));
  5166. return FALSE;
  5167. }
  5168. //
  5169. // Get the system sid
  5170. //
  5171. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  5172. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  5173. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to initialize system sid. Error = %d"),
  5174. GetLastError()));
  5175. goto Exit;
  5176. }
  5177. //
  5178. // Get the admin sid
  5179. //
  5180. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  5181. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  5182. 0, 0, 0, 0, &psidAdmin)) {
  5183. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to initialize admin sid. Error = %d"),
  5184. GetLastError()));
  5185. goto Exit;
  5186. }
  5187. //
  5188. // Get the Restricted sid
  5189. //
  5190. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
  5191. 0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
  5192. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to initialize restricted sid. Error = %d"),
  5193. GetLastError()));
  5194. goto Exit;
  5195. }
  5196. //
  5197. // Allocate space for the ACL
  5198. //
  5199. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  5200. (2 * GetLengthSid (psidAdmin)) + (2*GetLengthSid(psidRestricted)) +
  5201. sizeof(ACL) +
  5202. (8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  5203. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  5204. if (!pAcl) {
  5205. goto Exit;
  5206. }
  5207. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  5208. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to initialize acl. Error = %d"), GetLastError()));
  5209. goto Exit;
  5210. }
  5211. //
  5212. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  5213. //
  5214. AceIndex = 0;
  5215. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
  5216. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d"), GetLastError()));
  5217. goto Exit;
  5218. }
  5219. AceIndex++;
  5220. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  5221. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d"), GetLastError()));
  5222. goto Exit;
  5223. }
  5224. AceIndex++;
  5225. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  5226. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d"), GetLastError()));
  5227. goto Exit;
  5228. }
  5229. AceIndex++;
  5230. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
  5231. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for Restricted. Error = %d"), GetLastError()));
  5232. goto Exit;
  5233. }
  5234. //
  5235. // Now the inheritable ACEs
  5236. //
  5237. AceIndex++;
  5238. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  5239. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d"), GetLastError()));
  5240. goto Exit;
  5241. }
  5242. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  5243. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  5244. goto Exit;
  5245. }
  5246. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  5247. AceIndex++;
  5248. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  5249. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d"), GetLastError()));
  5250. goto Exit;
  5251. }
  5252. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  5253. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  5254. goto Exit;
  5255. }
  5256. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  5257. AceIndex++;
  5258. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  5259. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d"), GetLastError()));
  5260. goto Exit;
  5261. }
  5262. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  5263. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  5264. goto Exit;
  5265. }
  5266. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  5267. AceIndex++;
  5268. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
  5269. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to add ace for restricted. Error = %d"), GetLastError()));
  5270. goto Exit;
  5271. }
  5272. if (!GetAce(pAcl, AceIndex, (LPVOID*)&lpAceHeader)) {
  5273. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError()));
  5274. goto Exit;
  5275. }
  5276. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  5277. //
  5278. // Put together the security descriptor
  5279. //
  5280. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  5281. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  5282. goto Exit;
  5283. }
  5284. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  5285. DebugMsg((DM_VERBOSE, TEXT("SetDefaultUserHiveSecurity: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  5286. goto Exit;
  5287. }
  5288. //
  5289. // Set the security descriptor on the entire tree
  5290. //
  5291. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  5292. if (ERROR_SUCCESS == Error) {
  5293. bRetVal = TRUE;
  5294. }
  5295. else
  5296. SetLastError(Error);
  5297. Exit:
  5298. //
  5299. // Free the sids and acl
  5300. //
  5301. if (bFreeSid && psidUser) {
  5302. DeleteUserSid (psidUser);
  5303. }
  5304. if (psidSystem) {
  5305. FreeSid(psidSystem);
  5306. }
  5307. if (psidAdmin) {
  5308. FreeSid(psidAdmin);
  5309. }
  5310. if (psidRestricted) {
  5311. FreeSid(psidRestricted);
  5312. }
  5313. if (pAcl) {
  5314. GlobalFree (pAcl);
  5315. }
  5316. return bRetVal;
  5317. }
  5318. //*************************************************************
  5319. //
  5320. // SetupNewHive()
  5321. //
  5322. // Purpose: Initializes the new user hive created by copying
  5323. // the default hive.
  5324. //
  5325. // Parameters: lpProfile - Profile Information
  5326. // lpSidString - Sid string
  5327. // pSid - Sid (used by CreateNewUser)
  5328. //
  5329. // Return: TRUE if successful
  5330. // FALSE if an error occurs
  5331. //
  5332. // Comments:
  5333. //
  5334. // History: Date Author Comment
  5335. // 7/18/95 ericflo Created
  5336. //
  5337. //*************************************************************
  5338. BOOL SetupNewHive(LPPROFILE lpProfile, LPTSTR lpSidString, PSID pSid)
  5339. {
  5340. DWORD Error, IgnoreError;
  5341. HKEY RootKey;
  5342. BOOL bRetVal = FALSE;
  5343. DWORD dwFlags = 0;
  5344. TCHAR szErr[MAX_PATH];
  5345. //
  5346. // Verbose Output
  5347. //
  5348. if (!lpProfile && !pSid) {
  5349. DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Invalid parameter")));
  5350. SetLastError(ERROR_INVALID_PARAMETER);
  5351. return FALSE;
  5352. }
  5353. DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Entering")));
  5354. if (pSid) {
  5355. dwFlags = PI_NOUI;
  5356. } else {
  5357. dwFlags = lpProfile->dwFlags;
  5358. }
  5359. //
  5360. // Open the root of the user's profile
  5361. //
  5362. Error = RegOpenKeyEx(HKEY_USERS,
  5363. lpSidString,
  5364. 0,
  5365. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  5366. &RootKey);
  5367. if (Error != ERROR_SUCCESS) {
  5368. DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to open root of user registry, error = %d"), Error));
  5369. } else {
  5370. //
  5371. // First Secure the entire hive -- use security that
  5372. // will be sufficient for most of the hive.
  5373. // After this, we can add special settings to special
  5374. // sections of this hive.
  5375. //
  5376. if (SetDefaultUserHiveSecurity(lpProfile, pSid, RootKey)) {
  5377. TCHAR szSubKey[MAX_PATH];
  5378. LPTSTR lpEnd;
  5379. //
  5380. // Change the security on certain keys in the user's registry
  5381. // so that only Admin's and the OS have write access.
  5382. //
  5383. lstrcpy (szSubKey, lpSidString);
  5384. lpEnd = CheckSlash(szSubKey);
  5385. lstrcpy (lpEnd, WINDOWS_POLICIES_KEY);
  5386. if (!SecureUserKey(lpProfile, szSubKey, pSid)) {
  5387. DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to secure windows policies key")));
  5388. }
  5389. lstrcpy (lpEnd, ROOT_POLICIES_KEY);
  5390. if (!SecureUserKey(lpProfile, szSubKey, pSid)) {
  5391. DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to secure root policies key")));
  5392. }
  5393. bRetVal = TRUE;
  5394. } else {
  5395. Error = GetLastError();
  5396. DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to apply security to user registry tree, error = %d"), Error));
  5397. ReportError(lpProfile->hTokenUser, dwFlags, 1, EVENT_SECURITY_FAILED, GetErrString(Error, szErr));
  5398. }
  5399. RegFlushKey (RootKey);
  5400. IgnoreError = RegCloseKey(RootKey);
  5401. if (IgnoreError != ERROR_SUCCESS) {
  5402. DebugMsg((DM_WARNING, TEXT("SetupNewHive: Failed to close reg key, error = %d"), IgnoreError));
  5403. }
  5404. }
  5405. //
  5406. // Verbose Output
  5407. //
  5408. DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Leaving with a return value of %d"), bRetVal));
  5409. if (!bRetVal)
  5410. SetLastError(Error);
  5411. return(bRetVal);
  5412. }
  5413. //*************************************************************
  5414. //
  5415. // IsCentralProfileReachable()
  5416. //
  5417. // Purpose: Checks to see if the user can access the
  5418. // central profile.
  5419. //
  5420. // Parameters: lpProfile - User's token
  5421. // bCreateCentralProfile - Should the central profile be created
  5422. // bMandatory - Is this a mandatory profile
  5423. //
  5424. // Return: TRUE if successful
  5425. // FALSE if an error occurs
  5426. //
  5427. // Comments:
  5428. //
  5429. // History: Date Author Comment
  5430. // 6/20/95 ericflo Ported
  5431. //
  5432. //*************************************************************
  5433. BOOL IsCentralProfileReachable(LPPROFILE lpProfile, BOOL *bCreateCentralProfile,
  5434. BOOL *bMandatory, BOOL* bOwnerOK)
  5435. {
  5436. HANDLE hFile;
  5437. TCHAR szProfile[MAX_PATH];
  5438. LPTSTR lpProfilePath, lpEnd;
  5439. BOOL bRetVal = FALSE;
  5440. DWORD dwError;
  5441. HANDLE hOldToken;
  5442. HRESULT hr;
  5443. dwError = GetLastError();
  5444. //
  5445. // Verbose Output
  5446. //
  5447. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Entering")));
  5448. //
  5449. // Setup default values
  5450. //
  5451. *bMandatory = FALSE;
  5452. *bCreateCentralProfile = FALSE;
  5453. *bOwnerOK = TRUE;
  5454. //
  5455. // Check parameters
  5456. //
  5457. if (lpProfile->lpRoamingProfile[0] == TEXT('\0')) {
  5458. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Null path. Leaving")));
  5459. return FALSE;
  5460. }
  5461. lpProfilePath = lpProfile->lpRoamingProfile;
  5462. //
  5463. // Make sure we don't overrun our temporary buffer
  5464. //
  5465. if ((lstrlen(lpProfilePath) + 1 + lstrlen(c_szNTUserMan + 1)) > MAX_PATH) {
  5466. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Failed because temporary buffer is too small.")));
  5467. SetLastError(ERROR_BUFFER_OVERFLOW);
  5468. return FALSE;
  5469. }
  5470. //
  5471. // Copy the profile path to a temporary buffer
  5472. // we can munge it.
  5473. //
  5474. lstrcpy (szProfile, lpProfilePath);
  5475. //
  5476. // Impersonate the user
  5477. //
  5478. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  5479. DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Failed to impersonate user")));
  5480. return FALSE;
  5481. }
  5482. //
  5483. // Check ownership of the profile
  5484. //
  5485. hr = CheckRoamingShareOwnership(szProfile, lpProfile->hTokenUser);
  5486. if (FAILED(hr))
  5487. {
  5488. //
  5489. // Only set the bOwnerOK to false when we encountered the invalid owner error,
  5490. // this would allow us to discover other reasons for failure
  5491. //
  5492. if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_OWNER))
  5493. *bOwnerOK = FALSE;
  5494. DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Ownership check failed with %08X"), hr));
  5495. SetLastError(HRESULT_CODE(hr));
  5496. goto Exit;
  5497. }
  5498. //
  5499. // Add the slash if appropriate and then tack on ntuser.man.
  5500. //
  5501. lpEnd = CheckSlash(szProfile);
  5502. lstrcpy(lpEnd, c_szNTUserMan);
  5503. //
  5504. // See if this file exists
  5505. //
  5506. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Testing <%s>"), szProfile));
  5507. hFile = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
  5508. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5509. if (hFile != INVALID_HANDLE_VALUE) {
  5510. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Found a mandatory profile.")));
  5511. CloseHandle(hFile);
  5512. *bMandatory = TRUE;
  5513. bRetVal = TRUE;
  5514. goto Exit;
  5515. }
  5516. dwError = GetLastError();
  5517. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Profile is not reachable, error = %d"),
  5518. dwError));
  5519. //
  5520. // If we received an error other than file not
  5521. // found, bail now because we won't be able to
  5522. // access this location.
  5523. //
  5524. if (dwError != ERROR_FILE_NOT_FOUND) {
  5525. DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Profile path <%s> is not reachable, error = %d"),
  5526. szProfile, dwError));
  5527. goto Exit;
  5528. }
  5529. //
  5530. // Now try ntuser.dat
  5531. //
  5532. lstrcpy(lpEnd, c_szNTUserDat);
  5533. //
  5534. // See if this file exists.
  5535. //
  5536. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Testing <%s>"), szProfile));
  5537. hFile = CreateFile(szProfile, GENERIC_READ, FILE_SHARE_READ, NULL,
  5538. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5539. if (hFile != INVALID_HANDLE_VALUE) {
  5540. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Found a user profile.")));
  5541. CloseHandle(hFile);
  5542. bRetVal = TRUE;
  5543. goto Exit;
  5544. }
  5545. dwError = GetLastError();
  5546. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Profile is not reachable, error = %d"),
  5547. dwError));
  5548. //
  5549. // If file not found than central profile is empty. For read
  5550. // only profile ignore the empty central profile.
  5551. //
  5552. if ((dwError == ERROR_FILE_NOT_FOUND) && !(lpProfile->dwInternalFlags & PROFILE_READONLY)) {
  5553. DebugMsg((DM_VERBOSE, TEXT("IsCentralProfileReachable: Ok to create a user profile.")));
  5554. *bCreateCentralProfile = TRUE;
  5555. bRetVal = TRUE;
  5556. goto Exit;
  5557. }
  5558. DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Profile path <%s> is not reachable(2), error = %d"),
  5559. szProfile, dwError));
  5560. Exit:
  5561. //
  5562. // Go back to system security context
  5563. //
  5564. if (!RevertToUser(&hOldToken)) {
  5565. DebugMsg((DM_WARNING, TEXT("IsCentralProfileReachable: Failed to revert to self")));
  5566. }
  5567. return bRetVal;
  5568. }
  5569. //*************************************************************
  5570. //
  5571. // MyRegLoadKey()
  5572. //
  5573. // Purpose: Loads a hive into the registry
  5574. //
  5575. // Parameters: hKey - Key to load the hive into
  5576. // lpSubKey - Subkey name
  5577. // lpFile - hive filename
  5578. //
  5579. // Return: ERROR_SUCCESS if successful
  5580. // Error number if an error occurs
  5581. //
  5582. // Comments:
  5583. //
  5584. // History: Date Author Comment
  5585. // 6/22/95 ericflo Created
  5586. //
  5587. //*************************************************************
  5588. LONG MyRegLoadKey(HKEY hKey, LPTSTR lpSubKey, LPTSTR lpFile)
  5589. {
  5590. NTSTATUS Status = STATUS_SUCCESS;
  5591. BOOLEAN WasEnabled;
  5592. int error;
  5593. TCHAR szErr[MAX_PATH];
  5594. BOOL bAdjustPriv = FALSE;
  5595. HANDLE hToken = NULL;
  5596. //
  5597. // Check to see if we are impersonating.
  5598. //
  5599. if(!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken) || hToken == NULL) {
  5600. bAdjustPriv = TRUE;
  5601. }
  5602. else {
  5603. CloseHandle(hToken);
  5604. }
  5605. //
  5606. // Enable the restore privilege
  5607. //
  5608. if(bAdjustPriv) {
  5609. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  5610. }
  5611. if (NT_SUCCESS(Status)) {
  5612. error = RegLoadKey(hKey, lpSubKey, lpFile);
  5613. //
  5614. // Restore the privilege to its previous state
  5615. //
  5616. if(bAdjustPriv) {
  5617. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  5618. if (!NT_SUCCESS(Status)) {
  5619. DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to restore RESTORE privilege to previous enabled state")));
  5620. }
  5621. }
  5622. //
  5623. // Check if the hive was loaded
  5624. //
  5625. if (error != ERROR_SUCCESS) {
  5626. ReportError(NULL, PI_NOUI, 2, EVENT_REGLOADKEYFAILED, GetErrString(error, szErr), lpFile);
  5627. DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to load subkey <%s>, error =%d"), lpSubKey, error));
  5628. }
  5629. #if defined(_WIN64)
  5630. else {
  5631. //
  5632. // Notify Wow64 service that it need to watch this hive if it care to do so
  5633. //
  5634. if ( hKey == HKEY_USERS )
  5635. Wow64RegNotifyLoadHiveUserSid ( lpSubKey );
  5636. }
  5637. #endif
  5638. } else {
  5639. error = Status;
  5640. DebugMsg((DM_WARNING, TEXT("MyRegLoadKey: Failed to enable restore privilege to load registry key, err = %08x"), error));
  5641. }
  5642. DebugMsg((DM_VERBOSE, TEXT("MyRegLoadKey: Returning %08x"), error));
  5643. return error;
  5644. }
  5645. //*************************************************************
  5646. //
  5647. // MyRegUnLoadKey()
  5648. //
  5649. // Purpose: Unloads a registry key
  5650. //
  5651. // Parameters: hKey - Registry handle
  5652. // lpSubKey - Subkey to be unloaded
  5653. //
  5654. //
  5655. // Return: TRUE if successful
  5656. // FALSE if an error occurs
  5657. //
  5658. // Comments:
  5659. //
  5660. // History: Date Author Comment
  5661. // 6/19/95 ericflo Ported
  5662. //
  5663. //*************************************************************
  5664. BOOL MyRegUnLoadKey(HKEY hKey, LPTSTR lpSubKey)
  5665. {
  5666. BOOL bResult = TRUE;
  5667. LONG error;
  5668. LONG eTmp;
  5669. NTSTATUS Status = STATUS_SUCCESS;
  5670. BOOLEAN WasEnabled;
  5671. HKEY hSubKey;
  5672. HANDLE hToken = NULL;
  5673. BOOL bAdjustPriv = FALSE;
  5674. #if defined(_WIN64)
  5675. //
  5676. // Notify wow64 service to release any resources
  5677. //
  5678. if ( hKey == HKEY_USERS )
  5679. Wow64RegNotifyUnloadHiveUserSid ( lpSubKey );
  5680. #endif
  5681. //
  5682. // Check to see if we are impersonating.
  5683. //
  5684. if(!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken) || hToken == NULL) {
  5685. bAdjustPriv = TRUE;
  5686. }
  5687. else {
  5688. CloseHandle(hToken);
  5689. }
  5690. //
  5691. // Enable the restore privilege
  5692. //
  5693. if (bAdjustPriv) {
  5694. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  5695. }
  5696. if (NT_SUCCESS(Status)) {
  5697. error = RegUnLoadKey(hKey, lpSubKey);
  5698. //
  5699. // If the key didn't unload, check to see if it exists.
  5700. // If the key doesn't exist, then it was probably cleaned up by
  5701. // WatchHiveRefCount, but it certainly isn't loaded, so this
  5702. // function should succeed.
  5703. //
  5704. if (error != ERROR_SUCCESS) {
  5705. eTmp = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &hSubKey);
  5706. if (eTmp == ERROR_FILE_NOT_FOUND) {
  5707. error = ERROR_SUCCESS;
  5708. }
  5709. else if (eTmp == ERROR_SUCCESS) {
  5710. RegCloseKey( hSubKey );
  5711. }
  5712. }
  5713. if ( error != ERROR_SUCCESS) {
  5714. //
  5715. // RegUnlodKey returns ERROR_WRITE_PROTECT if hive is already scheduled for unloading
  5716. //
  5717. if (error == ERROR_WRITE_PROTECT) {
  5718. DebugMsg((DM_VERBOSE, TEXT("MyRegUnloadKey: user hive is already scheduled for unloading")));
  5719. }
  5720. else {
  5721. DebugMsg((DM_WARNING, TEXT("MyRegUnLoadKey: Failed to unmount hive %08x"), error));
  5722. }
  5723. bResult = FALSE;
  5724. }
  5725. //
  5726. // Restore the privilege to its previous state
  5727. //
  5728. if (bAdjustPriv) {
  5729. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  5730. if (!NT_SUCCESS(Status)) {
  5731. DebugMsg((DM_WARNING, TEXT("MyRegUnLoadKey: Failed to restore RESTORE privilege to previous enabled state")));
  5732. }
  5733. }
  5734. } else {
  5735. DebugMsg((DM_WARNING, TEXT("MyRegUnLoadKey: Failed to enable restore privilege to unload registry key")));
  5736. error = Status;
  5737. bResult = FALSE;
  5738. }
  5739. DebugMsg((DM_VERBOSE, TEXT("MyRegUnLoadKey: Returning %d."), bResult));
  5740. SetLastError(error);
  5741. return bResult;
  5742. }
  5743. //*************************************************************
  5744. //
  5745. // UpgradeLocalProfile()
  5746. //
  5747. // Purpose: Upgrades a local profile from a 3.x profile
  5748. // to a profile directory structure.
  5749. //
  5750. // Parameters: lpProfile - Profile Information
  5751. // lpOldProfile - Previous profile file
  5752. //
  5753. // Return: TRUE if successful
  5754. // FALSE if an error occurs
  5755. //
  5756. // Comments:
  5757. //
  5758. // History: Date Author Comment
  5759. // 7/6/95 ericflo Created
  5760. //
  5761. //*************************************************************
  5762. BOOL UpgradeLocalProfile (LPPROFILE lpProfile, LPTSTR lpOldProfile)
  5763. {
  5764. TCHAR szSrc[MAX_PATH];
  5765. TCHAR szDest[MAX_PATH];
  5766. LPTSTR lpSrcEnd, lpDestEnd;
  5767. BOOL bRetVal = FALSE;
  5768. DWORD dwSize, dwFlags;
  5769. HANDLE hOldToken;
  5770. DWORD dwErr;
  5771. dwErr = GetLastError();
  5772. //
  5773. // Verbose Output
  5774. //
  5775. DebugMsg((DM_VERBOSE, TEXT("UpgradeLocalProfile: Entering")));
  5776. //
  5777. // Setup the temporary buffers
  5778. //
  5779. lstrcpy (szSrc, lpOldProfile);
  5780. lstrcpy (szDest, lpProfile->lpLocalProfile);
  5781. lpDestEnd = CheckSlash (szDest);
  5782. lstrcpy (lpDestEnd, c_szNTUserDat);
  5783. //
  5784. // Copy the hive
  5785. //
  5786. if (!CopyFile(szSrc, szDest, FALSE)) {
  5787. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: CopyFile failed to copy hive with error = %d"),
  5788. GetLastError()));
  5789. return FALSE;
  5790. }
  5791. //
  5792. // Delete the old hive
  5793. //
  5794. DeleteFile (szSrc);
  5795. //
  5796. // Copy log file
  5797. //
  5798. lstrcat (szSrc, c_szLog);
  5799. lstrcat (szDest, c_szLog);
  5800. if (!CopyFile(szSrc, szDest, FALSE)) {
  5801. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: CopyFile failed to copy hive log with error = %d"),
  5802. GetLastError()));
  5803. }
  5804. //
  5805. // Delete the old hive log
  5806. //
  5807. DeleteFile (szSrc);
  5808. //
  5809. // Copy in the new shell folders from the default
  5810. //
  5811. if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) ) {
  5812. CheckNetDefaultProfile (lpProfile);
  5813. }
  5814. if (lpProfile->lpDefaultProfile && *lpProfile->lpDefaultProfile) {
  5815. ExpandEnvironmentStrings(lpProfile->lpDefaultProfile, szSrc, MAX_PATH);
  5816. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  5817. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to impersonate user")));
  5818. goto IssueLocalDefault;
  5819. }
  5820. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  5821. dwFlags |= CPD_IGNOREHIVE | CPD_CREATETITLE;
  5822. dwFlags |= CPD_IGNOREENCRYPTEDFILES | CPD_IGNORELONGFILENAMES;
  5823. if (CopyProfileDirectoryEx (szSrc, lpProfile->lpLocalProfile,
  5824. dwFlags,
  5825. NULL, NULL)) {
  5826. bRetVal = TRUE;
  5827. }
  5828. //
  5829. // Go back to system security context
  5830. //
  5831. if (!RevertToUser(&hOldToken)) {
  5832. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to revert to self")));
  5833. }
  5834. if ((!bRetVal) && (GetLastError() == ERROR_DISK_FULL)) {
  5835. dwErr = GetLastError();
  5836. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to Copy default profile. Disk is FULL")));
  5837. goto Exit;
  5838. }
  5839. }
  5840. IssueLocalDefault:
  5841. if (!bRetVal) {
  5842. dwSize = ARRAYSIZE(szSrc);
  5843. if (!GetDefaultUserProfileDirectory(szSrc, &dwSize)) {
  5844. dwErr = GetLastError();
  5845. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to get default user profile.")));
  5846. goto Exit;
  5847. }
  5848. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  5849. dwErr = GetLastError();
  5850. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to impersonate user")));
  5851. goto Exit;
  5852. }
  5853. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  5854. dwFlags |= CPD_IGNOREHIVE | CPD_CREATETITLE;
  5855. dwFlags |= CPD_IGNOREENCRYPTEDFILES | CPD_IGNORELONGFILENAMES;
  5856. bRetVal = CopyProfileDirectoryEx (szSrc,
  5857. lpProfile->lpLocalProfile,
  5858. dwFlags,
  5859. NULL, NULL);
  5860. //
  5861. // Go back to system security context
  5862. //
  5863. if (!RevertToUser(&hOldToken)) {
  5864. DebugMsg((DM_WARNING, TEXT("UpgradeLocalProfile: Failed to revert to self")));
  5865. }
  5866. }
  5867. if (!bRetVal)
  5868. dwErr = GetLastError();
  5869. Exit:
  5870. SetLastError(dwErr);
  5871. return bRetVal;
  5872. }
  5873. //*************************************************************
  5874. //
  5875. // UpgradeCentralProfile()
  5876. //
  5877. // Purpose: Upgrades a central profile from a 3.x profile
  5878. // to a profile directory structure.
  5879. //
  5880. // Parameters: lpProfile - Profile Information
  5881. // lpOldProfile - Previous profile file
  5882. //
  5883. // Return: TRUE if successful
  5884. // FALSE if an error occurs
  5885. //
  5886. // Comments:
  5887. //
  5888. // History: Date Author Comment
  5889. // 7/6/95 ericflo Created
  5890. //
  5891. //*************************************************************
  5892. BOOL UpgradeCentralProfile (LPPROFILE lpProfile, LPTSTR lpOldProfile)
  5893. {
  5894. TCHAR szSrc[MAX_PATH];
  5895. TCHAR szDest[MAX_PATH];
  5896. LPTSTR lpSrcEnd, lpDestEnd, lpDot;
  5897. BOOL bRetVal = FALSE;
  5898. BOOL bMandatory = FALSE;
  5899. DWORD dwSize, dwFlags;
  5900. HANDLE hOldToken;
  5901. DWORD dwErr;
  5902. dwErr = GetLastError();
  5903. //
  5904. // Verbose Output
  5905. //
  5906. DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Entering")));
  5907. //
  5908. // Impersonate the user
  5909. //
  5910. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  5911. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Failed to impersonate user")));
  5912. return FALSE;
  5913. }
  5914. //
  5915. // Setup the source buffer
  5916. //
  5917. lstrcpy (szSrc, lpOldProfile);
  5918. //
  5919. // Determine the profile type
  5920. //
  5921. lpDot = szSrc + lstrlen(szSrc) - 4;
  5922. if (*lpDot == TEXT('.')) {
  5923. if (!lstrcmpi (lpDot, c_szMAN)) {
  5924. bMandatory = TRUE;
  5925. }
  5926. }
  5927. //
  5928. // Setup the destination buffer
  5929. //
  5930. lstrcpy (szDest, lpProfile->lpRoamingProfile);
  5931. lpDestEnd = CheckSlash (szDest);
  5932. if (bMandatory) {
  5933. lstrcpy (lpDestEnd, c_szNTUserMan);
  5934. } else {
  5935. lstrcpy (lpDestEnd, c_szNTUserDat);
  5936. }
  5937. //
  5938. // Copy the hive
  5939. //
  5940. if (!CopyFile(szSrc, szDest, FALSE)) {
  5941. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: CopyFile failed to copy hive with error = %d"),
  5942. GetLastError()));
  5943. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Source = <%s>"), szSrc));
  5944. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Destination = <%s>"), szDest));
  5945. dwErr = GetLastError();
  5946. goto Exit;
  5947. }
  5948. //
  5949. // Copy log file
  5950. //
  5951. lstrcpy (lpDot, c_szLog);
  5952. lstrcat (szDest, c_szLog);
  5953. if (!CopyFile(szSrc, szDest, FALSE)) {
  5954. DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: CopyFile failed to copy hive log with error = %d"),
  5955. GetLastError()));
  5956. DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Source = <%s>"), szSrc));
  5957. DebugMsg((DM_VERBOSE, TEXT("UpgradeCentralProfile: Destination = <%s>"), szDest));
  5958. }
  5959. //
  5960. // Copy in the new shell folders from the default
  5961. //
  5962. if ( !(lpProfile->dwInternalFlags & DEFAULT_NET_READY) ) {
  5963. CheckNetDefaultProfile (lpProfile);
  5964. }
  5965. if (lpProfile->lpDefaultProfile && *lpProfile->lpDefaultProfile) {
  5966. ExpandEnvironmentStrings(lpProfile->lpDefaultProfile, szSrc, MAX_PATH);
  5967. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  5968. dwFlags |= CPD_IGNOREHIVE | CPD_CREATETITLE;
  5969. dwFlags |= CPD_IGNOREENCRYPTEDFILES | CPD_IGNORELONGFILENAMES;
  5970. if (CopyProfileDirectoryEx (szSrc, lpProfile->lpRoamingProfile,
  5971. dwFlags,
  5972. NULL, NULL)) {
  5973. bRetVal = TRUE;
  5974. }
  5975. }
  5976. if (!bRetVal) {
  5977. dwSize = ARRAYSIZE(szSrc);
  5978. if (!GetDefaultUserProfileDirectory(szSrc, &dwSize)) {
  5979. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Failed to get default user profile.")));
  5980. dwErr = GetLastError();
  5981. goto Exit;
  5982. }
  5983. dwFlags = (lpProfile->dwFlags & PI_NOUI) ? CPD_NOERRORUI : 0;
  5984. dwFlags |= CPD_IGNOREHIVE | CPD_CREATETITLE;
  5985. dwFlags |= CPD_IGNOREENCRYPTEDFILES | CPD_IGNORELONGFILENAMES;
  5986. bRetVal = CopyProfileDirectoryEx (szSrc,
  5987. lpProfile->lpRoamingProfile,
  5988. dwFlags,
  5989. NULL, NULL);
  5990. }
  5991. if (!bRetVal)
  5992. dwErr = GetLastError();
  5993. Exit:
  5994. //
  5995. // Go back to system security context
  5996. //
  5997. if (!RevertToUser(&hOldToken)) {
  5998. DebugMsg((DM_WARNING, TEXT("UpgradeCentralProfile: Failed to revert to self")));
  5999. }
  6000. return bRetVal;
  6001. }
  6002. //*************************************************************
  6003. //
  6004. // CreateSecureDirectory()
  6005. //
  6006. // Purpose: Creates a secure directory that only the user,
  6007. // admin, and system have access to in the normal case
  6008. // and for only the user and system in the restricted case.
  6009. //
  6010. //
  6011. // Parameters: lpProfile - Profile Information
  6012. // lpDirectory - Directory Name
  6013. // pSid - Sid (used by CreateUserProfile)
  6014. // fRestricted - Flag to set restricted access.
  6015. //
  6016. // Return: TRUE if successful
  6017. // FALSE if an error occurs
  6018. //
  6019. // Comments:
  6020. //
  6021. // History: Date Author Comment
  6022. // 7/20/95 ericflo Created
  6023. // 9/30/98 ushaji added fRestricted flag
  6024. // 7/18/00 santanuc modified to avoid deadlock when Documents and Settings directory is encrypted
  6025. //
  6026. //*************************************************************
  6027. BOOL CreateSecureDirectory (LPPROFILE lpProfile, LPTSTR lpDirectory, PSID pSid, BOOL fRestricted)
  6028. {
  6029. SECURITY_DESCRIPTOR sd;
  6030. SECURITY_ATTRIBUTES sa;
  6031. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  6032. PACL pAcl = NULL;
  6033. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
  6034. DWORD cbAcl, aceIndex;
  6035. ACE_HEADER * lpAceHeader;
  6036. BOOL bRetVal = FALSE;
  6037. BOOL bFreeSid = TRUE;
  6038. //
  6039. // Verbose Output
  6040. //
  6041. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Entering with <%s>"), lpDirectory));
  6042. if (!lpProfile && !pSid) {
  6043. //
  6044. // Attempt to create the directory
  6045. //
  6046. if (CreateNestedDirectoryEx(lpDirectory, NULL, FALSE)) {
  6047. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Created the directory <%s>"), lpDirectory));
  6048. bRetVal = TRUE;
  6049. } else {
  6050. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to created the directory <%s>"), lpDirectory));
  6051. }
  6052. goto Exit;
  6053. }
  6054. //
  6055. // Get the SIDs we'll need for the DACL
  6056. //
  6057. if (pSid) {
  6058. psidUser = pSid;
  6059. bFreeSid = FALSE;
  6060. } else {
  6061. if((psidUser = GetUserSid(lpProfile->hTokenUser)) == NULL) {
  6062. DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: GetUserSid returned NULL. error = %08x"), GetLastError()));
  6063. goto Exit;
  6064. }
  6065. }
  6066. //
  6067. // Get the system sid
  6068. //
  6069. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  6070. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  6071. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize system sid. Error = %d"), GetLastError()));
  6072. goto Exit;
  6073. }
  6074. //
  6075. // Get the Admin sid only if Frestricted is off
  6076. //
  6077. if (!fRestricted)
  6078. {
  6079. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  6080. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  6081. 0, 0, 0, 0, &psidAdmin)) {
  6082. DebugMsg((DM_VERBOSE, TEXT("SetupNewHive: Failed to initialize admin sid. Error = %d"), GetLastError()));
  6083. goto Exit;
  6084. }
  6085. }
  6086. //
  6087. // Allocate space for the ACL
  6088. //
  6089. if (!fRestricted)
  6090. {
  6091. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  6092. (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  6093. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  6094. }
  6095. else
  6096. {
  6097. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  6098. sizeof(ACL) +
  6099. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  6100. }
  6101. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  6102. if (!pAcl) {
  6103. goto Exit;
  6104. }
  6105. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  6106. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize acl. Error = %d"), GetLastError()));
  6107. goto Exit;
  6108. }
  6109. //
  6110. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  6111. //
  6112. aceIndex = 0;
  6113. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidUser)) {
  6114. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6115. goto Exit;
  6116. }
  6117. aceIndex++;
  6118. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  6119. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6120. goto Exit;
  6121. }
  6122. if (!fRestricted)
  6123. {
  6124. aceIndex++;
  6125. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  6126. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6127. goto Exit;
  6128. }
  6129. }
  6130. //
  6131. // Now the inheritable ACEs
  6132. //
  6133. aceIndex++;
  6134. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  6135. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6136. goto Exit;
  6137. }
  6138. if (!GetAce(pAcl, aceIndex, (LPVOID*)&lpAceHeader)) {
  6139. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  6140. goto Exit;
  6141. }
  6142. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  6143. aceIndex++;
  6144. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  6145. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6146. goto Exit;
  6147. }
  6148. if (!GetAce(pAcl, aceIndex, (LPVOID*)&lpAceHeader)) {
  6149. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  6150. goto Exit;
  6151. }
  6152. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  6153. if (!fRestricted)
  6154. {
  6155. aceIndex++;
  6156. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  6157. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6158. goto Exit;
  6159. }
  6160. }
  6161. if (!GetAce(pAcl, aceIndex, (LPVOID*)&lpAceHeader)) {
  6162. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
  6163. goto Exit;
  6164. }
  6165. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  6166. //
  6167. // Put together the security descriptor
  6168. //
  6169. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  6170. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  6171. goto Exit;
  6172. }
  6173. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  6174. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  6175. goto Exit;
  6176. }
  6177. //
  6178. // Add the security descriptor to the sa structure
  6179. //
  6180. sa.nLength = sizeof(sa);
  6181. sa.lpSecurityDescriptor = &sd;
  6182. sa.bInheritHandle = FALSE;
  6183. //
  6184. // Attempt to create the directory
  6185. //
  6186. if (CreateNestedDirectoryEx(lpDirectory, &sa, FALSE)) {
  6187. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Created the directory <%s>"), lpDirectory));
  6188. bRetVal = TRUE;
  6189. } else {
  6190. DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to created the directory <%s>"), lpDirectory));
  6191. }
  6192. Exit:
  6193. if (bFreeSid && psidUser) {
  6194. DeleteUserSid (psidUser);
  6195. }
  6196. if (psidSystem) {
  6197. FreeSid(psidSystem);
  6198. }
  6199. if (psidAdmin) {
  6200. FreeSid(psidAdmin);
  6201. }
  6202. if (pAcl) {
  6203. GlobalFree (pAcl);
  6204. }
  6205. return bRetVal;
  6206. }
  6207. //*************************************************************
  6208. //
  6209. // GetUserDomainName()
  6210. //
  6211. // Purpose: Gets the current user's domain name
  6212. //
  6213. // Parameters: lpProfile - Profile Information
  6214. // lpDomainName - Receives the user's domain name
  6215. // lpDomainNameSize - Size of the lpDomainName buffer (truncates the name to this size)
  6216. //
  6217. //
  6218. // Return: TRUE if successful
  6219. // FALSE if an error occurs
  6220. //
  6221. //*************************************************************
  6222. BOOL GetUserDomainName (LPPROFILE lpProfile, LPTSTR lpDomainName, LPDWORD lpDomainNameSize)
  6223. {
  6224. BOOL bResult = FALSE;
  6225. LPTSTR lpTemp, lpDomain = NULL;
  6226. HANDLE hOldToken;
  6227. DWORD dwErr;
  6228. TCHAR szErr[MAX_PATH];
  6229. dwErr = GetLastError();
  6230. //
  6231. // if no lpProfile is passed e.g. in setup.c and so just ignore.
  6232. //
  6233. lpDomainName[0] = TEXT('\0');
  6234. if (!lpProfile) {
  6235. DebugMsg((DM_WARNING, TEXT("GetUserDomainName: lpProfile structure is NULL, returning")));
  6236. return FALSE;
  6237. }
  6238. //
  6239. // Impersonate the user
  6240. //
  6241. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  6242. DebugMsg((DM_WARNING, TEXT("GetUserDomainName: Failed to impersonate user")));
  6243. dwErr = GetLastError();
  6244. goto Exit;
  6245. }
  6246. //
  6247. // Get the username in NT4 format
  6248. //
  6249. lpDomain = MyGetUserNameEx (NameSamCompatible);
  6250. RevertToUser(&hOldToken);
  6251. if (!lpDomain) {
  6252. DebugMsg((DM_WARNING, TEXT("GetUserDomainName: MyGetUserNameEx failed for NT4 style name with %d"),
  6253. GetLastError()));
  6254. dwErr = GetLastError();
  6255. ReportError (NULL, PI_NOUI, 1, EVENT_FAILED_USERNAME, GetErrString(dwErr, szErr));
  6256. goto Exit;
  6257. }
  6258. //
  6259. // Look for the \ between the domain and username and replace
  6260. // it with a NULL
  6261. //
  6262. lpTemp = lpDomain;
  6263. while (*lpTemp && ((*lpTemp) != TEXT('\\')))
  6264. lpTemp++;
  6265. if (*lpTemp != TEXT('\\')) {
  6266. DebugMsg((DM_WARNING, TEXT("GetUserDomainName: Failed to find slash in NT4 style name: <%s>"),
  6267. lpDomain));
  6268. dwErr = ERROR_INVALID_DATA;
  6269. goto Exit;
  6270. }
  6271. *lpTemp = TEXT('\0');
  6272. lstrcpyn (lpDomainName, lpDomain, (*lpDomainNameSize)-1);
  6273. //
  6274. // Success
  6275. //
  6276. DebugMsg((DM_VERBOSE, TEXT("GetUserDomainName: DomainName = <%s>"), lpDomainName));
  6277. bResult = TRUE;
  6278. Exit:
  6279. if (lpDomain) {
  6280. LocalFree (lpDomain);
  6281. }
  6282. SetLastError(dwErr);
  6283. return bResult;
  6284. }
  6285. //*************************************************************
  6286. //
  6287. // ComputeLocalProfileName()
  6288. //
  6289. // Purpose: Constructs the pathname of the local profile
  6290. // for this user. It will attempt to create
  6291. // a directory of the username, and then if
  6292. // unsccessful it will try the username.xxx
  6293. // where xxx is a three digit number
  6294. //
  6295. // Parameters: lpProfile - Profile Information
  6296. // lpUserName - UserName
  6297. // lpProfileImage - Profile directory (unexpanded)
  6298. // cchMaxProfileImage - lpProfileImage buffer size
  6299. // lpExpProfileImage - Expanded directory
  6300. // cchMaxExpProfileImage - lpExpProfileImage buffer size
  6301. // pSid - User's sid
  6302. // bWin9xUpg - Flag to say whether it is win9x upgrade
  6303. //
  6304. // Return: TRUE if successful
  6305. // FALSE if an error occurs
  6306. //
  6307. // Comments: lpProfileImage should be initialized with the
  6308. // root profile path and the trailing backslash.
  6309. // if it is a win9x upgrade give back the user's dir and don't do
  6310. // conflict resolution.
  6311. //
  6312. // History: Date Author Comment
  6313. // 6/20/95 ericflo Created
  6314. //
  6315. //*************************************************************
  6316. BOOL ComputeLocalProfileName (LPPROFILE lpProfile, LPCTSTR lpUserName,
  6317. LPTSTR lpProfileImage, DWORD cchMaxProfileImage,
  6318. LPTSTR lpExpProfileImage, DWORD cchMaxExpProfileImage,
  6319. PSID pSid, BOOL bWin9xUpg)
  6320. {
  6321. int i = 0;
  6322. TCHAR szNumber[5], lpUserDomain[50], szDomainName[50+3];
  6323. LPTSTR lpEnd;
  6324. BOOL bRetVal = FALSE;
  6325. BOOL bResult;
  6326. HANDLE hFile;
  6327. WIN32_FIND_DATA fd;
  6328. DWORD dwDomainNamelen;
  6329. DWORD dwErr;
  6330. //
  6331. // Check buffer size
  6332. //
  6333. dwDomainNamelen = ARRAYSIZE(lpUserDomain);
  6334. if ((DWORD)(lstrlen(lpProfileImage) + lstrlen(lpUserName) + dwDomainNamelen + 2 + 5 + 1) > cchMaxProfileImage) {
  6335. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: buffer too small")));
  6336. SetLastError(ERROR_BUFFER_OVERFLOW);
  6337. return FALSE;
  6338. }
  6339. //
  6340. // Place the username onto the end of the profile image
  6341. //
  6342. lpEnd = CheckSlash (lpProfileImage);
  6343. lstrcpy (lpEnd, lpUserName);
  6344. //
  6345. // Expand the profile path
  6346. //
  6347. ExpandEnvironmentStrings(lpProfileImage, lpExpProfileImage, cchMaxExpProfileImage);
  6348. //
  6349. // Does this directory exist?
  6350. //
  6351. hFile = FindFirstFile (lpExpProfileImage, &fd);
  6352. if (hFile == INVALID_HANDLE_VALUE) {
  6353. //
  6354. // Attempt to create the directory, if it returns an error bail
  6355. // CreateSecureDirectory does not return an error for already_exists
  6356. // so this should be ok.
  6357. //
  6358. bResult = CreateSecureDirectory(lpProfile, lpExpProfileImage, pSid, FALSE);
  6359. if (bResult) {
  6360. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s>"), lpExpProfileImage));
  6361. bRetVal = TRUE;
  6362. }
  6363. else {
  6364. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: trying to create dir <%s> returned %d"), lpExpProfileImage, GetLastError()));
  6365. bRetVal = FALSE;
  6366. }
  6367. goto Exit;
  6368. } else {
  6369. FindClose (hFile);
  6370. if (bWin9xUpg) {
  6371. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s> in win9xupg case"), lpExpProfileImage));
  6372. bRetVal = TRUE;
  6373. goto Exit;
  6374. }
  6375. }
  6376. //
  6377. // get the User Domain Name
  6378. //
  6379. if (!GetUserDomainName(lpProfile, lpUserDomain, &dwDomainNamelen)) {
  6380. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: Couldn't get the User Domain")));
  6381. *lpUserDomain = TEXT('\0');
  6382. }
  6383. lpEnd = lpProfileImage + lstrlen(lpProfileImage);
  6384. //
  6385. // Place the " (DomainName)" onto the end of the username
  6386. //
  6387. if ((*lpUserDomain) != TEXT('\0')) {
  6388. TCHAR szFormat[30];
  6389. LoadString (g_hDllInstance, IDS_PROFILEDOMAINNAME_FORMAT, szFormat,
  6390. ARRAYSIZE(szFormat));
  6391. wsprintf(szDomainName, szFormat, lpUserDomain);
  6392. lstrcpy(lpEnd, szDomainName);
  6393. //
  6394. // Expand the profile path
  6395. //
  6396. ExpandEnvironmentStrings(lpProfileImage, lpExpProfileImage, cchMaxExpProfileImage);
  6397. //
  6398. // Does this directory exist?
  6399. //
  6400. hFile = FindFirstFile (lpExpProfileImage, &fd);
  6401. if (hFile == INVALID_HANDLE_VALUE) {
  6402. //
  6403. // Attempt to create the directory
  6404. //
  6405. bResult = CreateSecureDirectory(lpProfile, lpExpProfileImage, pSid, FALSE);
  6406. if (bResult) {
  6407. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s>"), lpExpProfileImage));
  6408. bRetVal = TRUE;
  6409. }
  6410. else {
  6411. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: trying to create dir <%s> returned %d"), lpExpProfileImage, GetLastError()));
  6412. bRetVal = FALSE;
  6413. }
  6414. goto Exit;
  6415. } else {
  6416. FindClose (hFile);
  6417. }
  6418. }
  6419. //
  6420. // Failed to create the directory for some reason.
  6421. // Now try username (DomanName).000, username (DomanName).001, etc
  6422. //
  6423. lpEnd = lpProfileImage + lstrlen(lpProfileImage);
  6424. for (i=0; i < 1000; i++) {
  6425. //
  6426. // Convert the number to a string and attach it.
  6427. //
  6428. wsprintf (szNumber, TEXT(".%.3d"), i);
  6429. lstrcpy (lpEnd, szNumber);
  6430. //
  6431. // Expand the profile path
  6432. //
  6433. ExpandEnvironmentStrings(lpProfileImage, lpExpProfileImage, cchMaxExpProfileImage);
  6434. //
  6435. // Does this directory exist?
  6436. //
  6437. hFile = FindFirstFile (lpExpProfileImage, &fd);
  6438. if (hFile == INVALID_HANDLE_VALUE) {
  6439. //
  6440. // Attempt to create the directory
  6441. //
  6442. bResult = CreateSecureDirectory(lpProfile, lpExpProfileImage, pSid, FALSE);
  6443. if (bResult) {
  6444. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: generated the profile directory <%s>"), lpExpProfileImage));
  6445. bRetVal = TRUE;
  6446. }
  6447. else {
  6448. DebugMsg((DM_VERBOSE, TEXT("ComputeLocalProfileName: trying to create dir <%s> returned %d"), lpExpProfileImage, GetLastError()));
  6449. bRetVal = FALSE;
  6450. }
  6451. goto Exit;
  6452. } else {
  6453. FindClose (hFile);
  6454. }
  6455. }
  6456. DebugMsg((DM_WARNING, TEXT("ComputeLocalProfileName: Could not generate a profile directory. Error = %d"), GetLastError()));
  6457. Exit:
  6458. if (bRetVal && lpProfile && (lpProfile->dwFlags & PI_HIDEPROFILE)) {
  6459. SetFileAttributes(lpExpProfileImage,
  6460. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
  6461. GetFileAttributes(lpExpProfileImage));
  6462. }
  6463. return bRetVal;
  6464. }
  6465. //*************************************************************
  6466. //
  6467. // SetMachineProfileKeySecurity
  6468. //
  6469. // Purpose: Sets the security on the profile key under HKLM/ProfileList
  6470. //
  6471. // Parameters: lpProfile - Profile information
  6472. // lpKeyName - Name of the registry key
  6473. //
  6474. // Return: TRUE if successful
  6475. // FALSE if an error occurs
  6476. //
  6477. // Comments:
  6478. //
  6479. // History: Date Author Comment
  6480. // 2/22/99 ushaji adapted
  6481. // 2/3/00 weiruc fixed function comment
  6482. // fixed bug 441598
  6483. //
  6484. //*************************************************************
  6485. BOOL SetMachineProfileKeySecurity (LPPROFILE lpProfile, LPTSTR lpKeyName)
  6486. {
  6487. SECURITY_DESCRIPTOR sd;
  6488. SECURITY_ATTRIBUTES sa;
  6489. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  6490. PACL pAcl = NULL;
  6491. PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL;
  6492. PSID psidThisUser = NULL;
  6493. DWORD cbAcl, aceIndex;
  6494. ACE_HEADER * lpAceHeader;
  6495. BOOL bRetVal = FALSE;
  6496. HKEY hKeyProfile=NULL;
  6497. DWORD Error, dwDisp;
  6498. //
  6499. // Get the system sid
  6500. //
  6501. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  6502. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  6503. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to initialize system sid. Error = %d"), GetLastError()));
  6504. goto Exit;
  6505. }
  6506. //
  6507. // Get the Admin sid
  6508. //
  6509. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  6510. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  6511. 0, 0, 0, 0, &psidAdmin)) {
  6512. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to initialize admin sid. Error = %d"), GetLastError()));
  6513. goto Exit;
  6514. }
  6515. //
  6516. // Get the users sid
  6517. //
  6518. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  6519. DOMAIN_ALIAS_RID_USERS,
  6520. 0, 0, 0, 0, 0, 0, &psidUsers)) {
  6521. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to initialize authenticated users sid. Error = %d"), GetLastError()));
  6522. goto Exit;
  6523. }
  6524. //
  6525. // Get this users sid
  6526. //
  6527. if((psidThisUser = GetUserSid(lpProfile->hTokenUser)) == NULL) {
  6528. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to get the user's sid. Error = %d"), GetLastError()));
  6529. goto Exit;
  6530. }
  6531. //
  6532. // Allocate space for the ACL. (No Inheritable Aces)
  6533. //
  6534. cbAcl = (GetLengthSid (psidSystem)) +
  6535. (GetLengthSid (psidAdmin)) +
  6536. (GetLengthSid (psidUsers)) +
  6537. (GetLengthSid (psidThisUser)) +
  6538. sizeof(ACL) +
  6539. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  6540. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  6541. if (!pAcl) {
  6542. goto Exit;
  6543. }
  6544. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  6545. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to initialize acl. Error = %d"), GetLastError()));
  6546. goto Exit;
  6547. }
  6548. //
  6549. // Add Aces. Non-inheritable ACEs first
  6550. //
  6551. aceIndex = 0;
  6552. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  6553. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6554. goto Exit;
  6555. }
  6556. aceIndex++;
  6557. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  6558. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6559. goto Exit;
  6560. }
  6561. aceIndex++;
  6562. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUsers)) {
  6563. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6564. goto Exit;
  6565. }
  6566. aceIndex++;
  6567. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER), psidThisUser)) {
  6568. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
  6569. goto Exit;
  6570. }
  6571. //
  6572. // Put together the security descriptor
  6573. //
  6574. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  6575. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  6576. goto Exit;
  6577. }
  6578. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  6579. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  6580. goto Exit;
  6581. }
  6582. Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  6583. lpKeyName,
  6584. 0,
  6585. NULL,
  6586. REG_OPTION_NON_VOLATILE,
  6587. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  6588. NULL,
  6589. &hKeyProfile,
  6590. &dwDisp);
  6591. if (Error != ERROR_SUCCESS) {
  6592. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Couldn't open registry key to set security. Error = %d"), Error));
  6593. SetLastError(Error);
  6594. goto Exit;
  6595. }
  6596. //
  6597. // Set the security
  6598. //
  6599. Error = RegSetKeySecurity(hKeyProfile, DACL_SECURITY_INFORMATION, &sd);
  6600. if (Error != ERROR_SUCCESS) {
  6601. DebugMsg((DM_WARNING, TEXT("SetMachineProfileKeySecurity: Couldn't set security. Error = %d"), Error));
  6602. SetLastError(Error);
  6603. goto Exit;
  6604. }
  6605. else {
  6606. bRetVal = TRUE;
  6607. }
  6608. Exit:
  6609. if (psidSystem) {
  6610. FreeSid(psidSystem);
  6611. }
  6612. if (psidAdmin) {
  6613. FreeSid(psidAdmin);
  6614. }
  6615. if (psidUsers) {
  6616. FreeSid(psidUsers);
  6617. }
  6618. if (psidThisUser) {
  6619. FreeSid(psidThisUser);
  6620. }
  6621. if (pAcl) {
  6622. GlobalFree (pAcl);
  6623. }
  6624. if (hKeyProfile) {
  6625. RegCloseKey(hKeyProfile);
  6626. }
  6627. return bRetVal;
  6628. }
  6629. //*************************************************************
  6630. //
  6631. // CreateLocalProfileKey()
  6632. //
  6633. // Purpose: Creates a registry key pointing at the user profile
  6634. //
  6635. // Parameters: lpProfile - Profile information
  6636. // phKey - Handle to registry key if successful
  6637. // bKeyExists - TRUE if the registry key already existed
  6638. //
  6639. // Return: TRUE if successful
  6640. // FALSE if an error occurs
  6641. //
  6642. // Comments:
  6643. //
  6644. // History: Date Author Comment
  6645. // 6/20/95 ericflo Ported
  6646. //
  6647. //*************************************************************
  6648. BOOL CreateLocalProfileKey (LPPROFILE lpProfile, PHKEY phKey, BOOL *bKeyExists)
  6649. {
  6650. TCHAR LocalProfileKey[MAX_PATH];
  6651. DWORD Disposition;
  6652. DWORD RegErr = ERROR_SUCCESS + 1;
  6653. BOOL Result;
  6654. LPTSTR SidString;
  6655. DWORD dwErr;
  6656. dwErr = GetLastError();
  6657. SidString = GetSidString(lpProfile->hTokenUser);
  6658. if (SidString != NULL) {
  6659. //
  6660. // Call the RegCreateKey api in the user's context
  6661. //
  6662. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  6663. lstrcat(LocalProfileKey, TEXT("\\"));
  6664. lstrcat(LocalProfileKey, SidString);
  6665. RegErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  6666. KEY_READ | KEY_WRITE, NULL, phKey, &Disposition);
  6667. if (RegErr == ERROR_SUCCESS) {
  6668. *bKeyExists = (BOOL)(Disposition & REG_OPENED_EXISTING_KEY);
  6669. //
  6670. // If the key didn't exist before and profile is not mandatory, set the security on it.
  6671. //
  6672. if ((!(*bKeyExists)) && (!(lpProfile->dwInternalFlags & PROFILE_MANDATORY))) {
  6673. if (!SetMachineProfileKeySecurity(lpProfile, LocalProfileKey)) {
  6674. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileKey: SetMachineProfileKeySecurity Failed. Error = %d"), GetLastError()));
  6675. }
  6676. }
  6677. else {
  6678. DebugMsg((DM_VERBOSE, TEXT("CreateLocalProfileKey: Not setting additional Security")));
  6679. }
  6680. } else {
  6681. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileKey: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, RegErr));
  6682. dwErr = RegErr;
  6683. }
  6684. DeleteSidString(SidString);
  6685. }
  6686. SetLastError(dwErr);
  6687. return(RegErr == ERROR_SUCCESS);
  6688. }
  6689. //*************************************************************
  6690. //
  6691. // GetExistingLocalProfileImage()
  6692. //
  6693. // Purpose: opens the profileimagepath
  6694. //
  6695. // Parameters: lpProfile - Profile information
  6696. //
  6697. // Return: TRUE if the profile image is reachable
  6698. // FALSE if an error occurs
  6699. //
  6700. // Comments:
  6701. //
  6702. // History: Date Author Comment
  6703. // 6/20/95 ericflo Ported
  6704. // 9/26/98 ushaji Modified
  6705. //
  6706. //*************************************************************
  6707. BOOL GetExistingLocalProfileImage(LPPROFILE lpProfile)
  6708. {
  6709. HKEY hKey = NULL;
  6710. BOOL bKeyExists;
  6711. LPTSTR lpProfileImage = NULL;
  6712. LPTSTR lpExpProfileImage = NULL;
  6713. LPTSTR lpOldProfileImage = NULL;
  6714. LPTSTR lpExpandedPath, lpEnd;
  6715. DWORD cbExpProfileImage = sizeof(TCHAR)*MAX_PATH;
  6716. HANDLE hFile;
  6717. WIN32_FIND_DATA fd;
  6718. DWORD cb;
  6719. DWORD err;
  6720. DWORD dwType;
  6721. DWORD dwSize;
  6722. LONG lResult;
  6723. DWORD dwInternalFlags = 0;
  6724. BOOL bRetVal = FALSE;
  6725. LPTSTR SidString;
  6726. HANDLE hOldToken;
  6727. lpProfile->lpLocalProfile[0] = TEXT('\0');
  6728. if (!PatchNewProfileIfRequired(lpProfile->hTokenUser)) {
  6729. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Patch Profile Image failed")));
  6730. return FALSE;
  6731. }
  6732. if (!CreateLocalProfileKey(lpProfile, &hKey, &bKeyExists)) {
  6733. return FALSE; // not reachable and cannot keep a local copy
  6734. }
  6735. //
  6736. // Allocate memory for Local variables to avoid stack overflow
  6737. //
  6738. lpProfileImage = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  6739. if (!lpProfileImage) {
  6740. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Out of memory")));
  6741. goto Exit;
  6742. }
  6743. lpExpProfileImage = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  6744. if (!lpExpProfileImage) {
  6745. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Out of memory")));
  6746. goto Exit;
  6747. }
  6748. lpOldProfileImage = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  6749. if (!lpOldProfileImage) {
  6750. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Out of memory")));
  6751. goto Exit;
  6752. }
  6753. if (bKeyExists) {
  6754. //
  6755. // Check if the local profile image is valid.
  6756. //
  6757. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Found entry in profile list for existing local profile")));
  6758. err = RegQueryValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0, &dwType,
  6759. (LPBYTE)lpExpProfileImage, &cbExpProfileImage);
  6760. if (err == ERROR_SUCCESS && cbExpProfileImage) {
  6761. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Local profile image filename = <%s>"), lpExpProfileImage));
  6762. if (dwType == REG_EXPAND_SZ) {
  6763. //
  6764. // Expand the profile image filename
  6765. //
  6766. cb = sizeof(TCHAR)*MAX_PATH;
  6767. lpExpandedPath = (LPTSTR)LocalAlloc(LPTR, cb);
  6768. if (lpExpandedPath) {
  6769. ExpandEnvironmentStrings(lpExpProfileImage, lpExpandedPath, cb);
  6770. lstrcpy(lpExpProfileImage, lpExpandedPath);
  6771. LocalFree(lpExpandedPath);
  6772. }
  6773. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Expanded local profile image filename = <%s>"), lpExpProfileImage));
  6774. }
  6775. //
  6776. // Query for the internal flags
  6777. //
  6778. dwSize = sizeof(DWORD);
  6779. err = RegQueryValueEx (hKey, PROFILE_STATE, NULL,
  6780. &dwType, (LPBYTE) &dwInternalFlags, &dwSize);
  6781. if (err != ERROR_SUCCESS) {
  6782. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Failed to query internal flags with error %d"), err));
  6783. }
  6784. //
  6785. // if we do not have a fully loaded profile, mark it as new
  6786. // if it was not called with Liteload
  6787. //
  6788. if (dwInternalFlags & PROFILE_PARTLY_LOADED) {
  6789. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: We do not have a fully loaded profile on this machine")));
  6790. //
  6791. // retain the partially loaded flag and remove it at the end of
  6792. // restoreuserprofile..
  6793. //
  6794. lpProfile->dwInternalFlags |= PROFILE_PARTLY_LOADED;
  6795. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  6796. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Treating this profile as new")));
  6797. lpProfile->dwInternalFlags |= PROFILE_NEW_LOCAL;
  6798. }
  6799. }
  6800. //
  6801. // if due to leak we are getting the old TEMP profile then preserve
  6802. // the internal flag. This will allow to revert back to .bak profile
  6803. // correctly when the leak is fixed.
  6804. //
  6805. if (dwInternalFlags & PROFILE_TEMP_ASSIGNED) {
  6806. lpProfile->dwInternalFlags |= dwInternalFlags;
  6807. }
  6808. //
  6809. // Call FindFirst to see if we need to migrate this profile
  6810. //
  6811. hFile = FindFirstFile (lpExpProfileImage, &fd);
  6812. if (hFile == INVALID_HANDLE_VALUE) {
  6813. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Local profile image filename we got from our profile list doesn't exit. Error = %d"), GetLastError()));
  6814. bRetVal = FALSE;
  6815. goto Exit;
  6816. }
  6817. FindClose(hFile);
  6818. //
  6819. // If this is a file, then we need to migrate it to
  6820. // the new directory structure. (from a 3.5 machine)
  6821. //
  6822. if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  6823. lstrcpy (lpOldProfileImage, lpExpProfileImage);
  6824. if (CreateLocalProfileImage(lpProfile, lpProfile->lpUserName)) {
  6825. if (UpgradeLocalProfile (lpProfile, lpOldProfileImage))
  6826. bRetVal = TRUE;
  6827. else {
  6828. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Failed to upgrade 3.5 profiles")));
  6829. bRetVal = FALSE;
  6830. }
  6831. }
  6832. else {
  6833. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Failed to create a new profile to upgrade")));
  6834. bRetVal = FALSE;
  6835. }
  6836. goto Exit;
  6837. }
  6838. //
  6839. // Test if a mandatory profile exists
  6840. //
  6841. lpEnd = CheckSlash (lpExpProfileImage);
  6842. lstrcpy (lpEnd, c_szNTUserMan);
  6843. //
  6844. // Impersonate the user, before trying to access ntuser, ntuser.man
  6845. // fail, if we can not access..
  6846. //
  6847. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  6848. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Failed to impersonate user")));
  6849. bRetVal = FALSE;
  6850. goto Exit;
  6851. }
  6852. if (GetFileAttributes(lpExpProfileImage) != -1) {
  6853. //
  6854. // This is just to tag that the local profile is a mandatory profile
  6855. //
  6856. lpProfile->dwInternalFlags |= PROFILE_LOCALMANDATORY;
  6857. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Found local mandatory profile image file ok <%s>"),
  6858. lpExpProfileImage));
  6859. *(lpEnd - 1) = TEXT('\0');
  6860. lstrcpy(lpProfile->lpLocalProfile, lpExpProfileImage);
  6861. //
  6862. // Since this profile was mandatory, treat it as if it has never
  6863. // synced with the server.
  6864. //
  6865. lpProfile->ftProfileUnload.dwLowDateTime = 0;
  6866. lpProfile->ftProfileUnload.dwHighDateTime = 0;
  6867. RevertToUser(&hOldToken);
  6868. bRetVal = TRUE; // local copy is valid and reachable
  6869. goto Exit;
  6870. } else {
  6871. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: No local mandatory profile. Error = %d"), GetLastError()));
  6872. }
  6873. //
  6874. // Test if a normal profile exists
  6875. //
  6876. lstrcpy (lpEnd, c_szNTUserDat);
  6877. if (GetFileAttributes(lpExpProfileImage) != -1) {
  6878. RevertToUser(&hOldToken);
  6879. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Found local profile image file ok <%s>"),
  6880. lpExpProfileImage));
  6881. *(lpEnd - 1) = TEXT('\0');
  6882. lstrcpy(lpProfile->lpLocalProfile, lpExpProfileImage);
  6883. //
  6884. // Read the time this profile was unloaded
  6885. //
  6886. dwSize = sizeof(lpProfile->ftProfileUnload.dwLowDateTime);
  6887. lResult = RegQueryValueEx (hKey,
  6888. PROFILE_UNLOAD_TIME_LOW,
  6889. NULL,
  6890. &dwType,
  6891. (LPBYTE) &lpProfile->ftProfileUnload.dwLowDateTime,
  6892. &dwSize);
  6893. if (lResult == ERROR_SUCCESS) {
  6894. dwSize = sizeof(lpProfile->ftProfileUnload.dwHighDateTime);
  6895. lResult = RegQueryValueEx (hKey,
  6896. PROFILE_UNLOAD_TIME_HIGH,
  6897. NULL,
  6898. &dwType,
  6899. (LPBYTE) &lpProfile->ftProfileUnload.dwHighDateTime,
  6900. &dwSize);
  6901. if (lResult != ERROR_SUCCESS) {
  6902. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Failed to query high profile unload time with error %d"), lResult));
  6903. lpProfile->ftProfileUnload.dwLowDateTime = 0;
  6904. lpProfile->ftProfileUnload.dwHighDateTime = 0;
  6905. }
  6906. } else {
  6907. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Failed to query low profile unload time with error %d"), lResult));
  6908. lpProfile->ftProfileUnload.dwLowDateTime = 0;
  6909. lpProfile->ftProfileUnload.dwHighDateTime = 0;
  6910. }
  6911. bRetVal = TRUE; // local copy is valid and reachable
  6912. goto Exit;
  6913. } else {
  6914. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Local profile image filename we got from our profile list doesn't exit. <%s> Error = %d"),
  6915. lpExpProfileImage, GetLastError()));
  6916. }
  6917. //
  6918. // Revert to User before continuing
  6919. //
  6920. RevertToUser(&hOldToken);
  6921. }
  6922. }
  6923. Exit:
  6924. if (lpProfileImage) {
  6925. LocalFree(lpProfileImage);
  6926. }
  6927. if (lpExpProfileImage) {
  6928. LocalFree(lpExpProfileImage);
  6929. }
  6930. if (lpOldProfileImage) {
  6931. LocalFree(lpOldProfileImage);
  6932. }
  6933. if (hKey) {
  6934. err = RegCloseKey(hKey);
  6935. if (err != STATUS_SUCCESS) {
  6936. DebugMsg((DM_WARNING, TEXT("GetExistingLocalProfileImage: Failed to close registry key, error = %d"), err));
  6937. }
  6938. }
  6939. return bRetVal;
  6940. }
  6941. //*************************************************************
  6942. //
  6943. // CreateLocalProfileImage()
  6944. //
  6945. // Purpose: creates the profileimagepath
  6946. //
  6947. // Parameters: lpProfile - Profile information
  6948. // lpBaseName - Base Name from which profile dir name
  6949. // will be generated.
  6950. //
  6951. // Return: TRUE if the profile image is creatable
  6952. // FALSE if an error occurs
  6953. //
  6954. // Comments:
  6955. //
  6956. // History: Date Author Comment
  6957. // 6/20/95 ericflo Ported
  6958. // 9/26/98 ushaji Modified
  6959. //
  6960. //*************************************************************
  6961. BOOL CreateLocalProfileImage(LPPROFILE lpProfile, LPTSTR lpBaseName)
  6962. {
  6963. HKEY hKey;
  6964. BOOL bKeyExists;
  6965. TCHAR lpProfileImage[MAX_PATH];
  6966. TCHAR lpExpProfileImage[MAX_PATH];
  6967. DWORD cbExpProfileImage = sizeof(TCHAR)*MAX_PATH;
  6968. DWORD err;
  6969. DWORD dwSize;
  6970. PSID UserSid;
  6971. BOOL bRetVal = FALSE;
  6972. lpProfile->lpLocalProfile[0] = TEXT('\0');
  6973. if (!CreateLocalProfileKey(lpProfile, &hKey, &bKeyExists)) {
  6974. return FALSE; // not reachable and cannot keep a local copy
  6975. }
  6976. //
  6977. // No local copy found, try to create a new one.
  6978. //
  6979. DebugMsg((DM_VERBOSE, TEXT("CreateLocalProfileImage: One way or another we haven't got an existing local profile, try and create one")));
  6980. dwSize = ARRAYSIZE(lpProfileImage);
  6981. if (!GetProfilesDirectoryEx(lpProfileImage, &dwSize, FALSE)) {
  6982. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileImage: Failed to get profile root directory.")));
  6983. goto Exit;
  6984. }
  6985. if (ComputeLocalProfileName(lpProfile, lpBaseName,
  6986. lpProfileImage, MAX_PATH,
  6987. lpExpProfileImage, MAX_PATH, NULL, FALSE)) {
  6988. //
  6989. // Add this image file to our profile list for this user
  6990. //
  6991. err = RegSetValueEx(hKey,
  6992. PROFILE_IMAGE_VALUE_NAME,
  6993. 0,
  6994. REG_EXPAND_SZ,
  6995. (LPBYTE)lpProfileImage,
  6996. sizeof(TCHAR)*(lstrlen(lpProfileImage) + 1));
  6997. if (err == ERROR_SUCCESS) {
  6998. lstrcpy(lpProfile->lpLocalProfile, lpExpProfileImage);
  6999. //
  7000. // Get the sid of the logged on user
  7001. //
  7002. UserSid = GetUserSid(lpProfile->hTokenUser);
  7003. if (UserSid != NULL) {
  7004. //
  7005. // Store the user sid under the Sid key of the local profile
  7006. //
  7007. err = RegSetValueEx(hKey,
  7008. TEXT("Sid"),
  7009. 0,
  7010. REG_BINARY,
  7011. (BYTE*)UserSid,
  7012. RtlLengthSid(UserSid));
  7013. if (err != ERROR_SUCCESS) {
  7014. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileImage: Failed to set 'sid' value of user in profile list, error = %d"), err));
  7015. SetLastError(err);
  7016. }
  7017. //
  7018. // We're finished with the user sid
  7019. //
  7020. DeleteUserSid(UserSid);
  7021. bRetVal = TRUE;
  7022. } else {
  7023. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileImage: Failed to get sid of logged on user, so unable to update profile list")));
  7024. SetLastError(err);
  7025. }
  7026. } else {
  7027. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileImage: Failed to update profile list for user with local profile image filename, error = %d"), err));
  7028. SetLastError(err);
  7029. }
  7030. }
  7031. Exit:
  7032. err = RegCloseKey(hKey);
  7033. if (err != STATUS_SUCCESS) {
  7034. DebugMsg((DM_WARNING, TEXT("CreateLocalProfileImage: Failed to close registry key, error = %d"), err));
  7035. SetLastError(err);
  7036. }
  7037. return bRetVal;
  7038. }
  7039. //*************************************************************
  7040. //
  7041. // IssueDefaultProfile()
  7042. //
  7043. // Purpose: Issues the specified default profile to a user
  7044. //
  7045. // Parameters: lpProfile - Profile Information
  7046. // lpDefaultProfile - Default profile location
  7047. // lpLocalProfile - Local profile location
  7048. // lpSidString - User's sid
  7049. // bMandatory - Issue mandatory profile
  7050. //
  7051. // Return: TRUE if profile was successfully setup
  7052. // FALSE if an error occurs
  7053. //
  7054. // Comments:
  7055. //
  7056. // History: Date Author Comment
  7057. // 6/22/95 ericflo Created
  7058. //
  7059. //*************************************************************
  7060. BOOL IssueDefaultProfile (LPPROFILE lpProfile, LPTSTR lpDefaultProfile,
  7061. LPTSTR lpLocalProfile, LPTSTR lpSidString,
  7062. BOOL bMandatory)
  7063. {
  7064. LPTSTR lpEnd, lpTemp;
  7065. TCHAR szProfile[MAX_PATH];
  7066. TCHAR szTempProfile[MAX_PATH];
  7067. BOOL bProfileLoaded = FALSE;
  7068. WIN32_FIND_DATA fd;
  7069. HANDLE hFile;
  7070. LONG error;
  7071. DWORD dwFlags;
  7072. HANDLE hOldToken;
  7073. //
  7074. // Verbose Output
  7075. //
  7076. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Entering. lpDefaultProfile = <%s> lpLocalProfile = <%s>"),
  7077. lpDefaultProfile, lpLocalProfile));
  7078. //
  7079. // First expand the default profile
  7080. //
  7081. if (!ExpandEnvironmentStrings(lpDefaultProfile, szProfile, MAX_PATH)) {
  7082. DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: ExpandEnvironmentStrings Failed with error %d"), GetLastError()));
  7083. return FALSE;
  7084. }
  7085. //
  7086. // Impersonate the user
  7087. //
  7088. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  7089. DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: Failed to impersonate user")));
  7090. return FALSE;
  7091. }
  7092. //
  7093. // Does the default profile directory exist?
  7094. //
  7095. hFile = FindFirstFile (szProfile, &fd);
  7096. if (hFile == INVALID_HANDLE_VALUE) {
  7097. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Default profile <%s> does not exist."), szProfile));
  7098. RevertToUser(&hOldToken);
  7099. return FALSE;
  7100. }
  7101. FindClose(hFile);
  7102. //
  7103. // Copy profile to user profile
  7104. //
  7105. dwFlags = CPD_CREATETITLE | CPD_IGNORESECURITY |
  7106. CPD_IGNORELONGFILENAMES | CPD_IGNORECOPYERRORS;
  7107. if (lpProfile->dwFlags & (PI_LITELOAD | PI_HIDEPROFILE)) {
  7108. dwFlags |= CPD_SYSTEMFILES | CPD_SYSTEMDIRSONLY;
  7109. }
  7110. else
  7111. dwFlags |= CPD_IGNOREENCRYPTEDFILES;
  7112. //
  7113. // Call it with force copy unless there might be a partial profile locally
  7114. //
  7115. if (!(lpProfile->dwInternalFlags & PROFILE_PARTLY_LOADED)) {
  7116. dwFlags |= CPD_FORCECOPY;
  7117. }
  7118. if (!CopyProfileDirectoryEx (szProfile, lpLocalProfile, dwFlags, NULL, NULL)) {
  7119. DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: CopyProfileDirectory returned FALSE. Error = %d"), GetLastError()));
  7120. RevertToUser(&hOldToken);
  7121. return FALSE;
  7122. }
  7123. //
  7124. // Rename the profile is a mandatory one was requested.
  7125. //
  7126. lstrcpy (szProfile, lpLocalProfile);
  7127. lpEnd = CheckSlash (szProfile);
  7128. if (bMandatory) {
  7129. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Mandatory profile was requested.")));
  7130. lstrcpy (szTempProfile, szProfile);
  7131. lstrcpy (lpEnd, c_szNTUserMan);
  7132. hFile = FindFirstFile (szProfile, &fd);
  7133. if (hFile != INVALID_HANDLE_VALUE) {
  7134. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Mandatory profile already exists.")));
  7135. FindClose(hFile);
  7136. } else {
  7137. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Renaming ntuser.dat to ntuser.man")));
  7138. lpTemp = CheckSlash(szTempProfile);
  7139. lstrcpy (lpTemp, c_szNTUserDat);
  7140. if (!MoveFile(szTempProfile, szProfile)) {
  7141. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: MoveFile returned false. Error = %d"), GetLastError()));
  7142. }
  7143. }
  7144. } else {
  7145. lstrcpy (lpEnd, c_szNTUserDat);
  7146. }
  7147. //
  7148. // Revert to being 'ourself'
  7149. //
  7150. if (!RevertToUser(&hOldToken)) {
  7151. DebugMsg((DM_WARNING, TEXT("IssueDefaultProfile: Failed to revert to self")));
  7152. }
  7153. //
  7154. // Try to load the new profile
  7155. //
  7156. error = MyRegLoadKey(HKEY_USERS, lpSidString, szProfile);
  7157. bProfileLoaded = (error == ERROR_SUCCESS);
  7158. if (!bProfileLoaded) {
  7159. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: MyRegLoadKey failed with error %d"),
  7160. error));
  7161. SetLastError(error);
  7162. if (error == ERROR_BADDB) {
  7163. ReportError(lpProfile->hTokenUser, lpProfile->dwFlags, 0, EVENT_FAILED_LOAD_1009);
  7164. }
  7165. return FALSE;
  7166. }
  7167. DebugMsg((DM_VERBOSE, TEXT("IssueDefaultProfile: Leaving successfully")));
  7168. return TRUE;
  7169. }
  7170. //*************************************************************
  7171. //
  7172. // DeleteProfileEx ()
  7173. //
  7174. // Purpose: Deletes the specified profile from the
  7175. // registry and disk.
  7176. //
  7177. // Parameters: lpSidString - Registry subkey
  7178. // lpProfileDir - Profile directory
  7179. // bBackup - Backup profile before deleting
  7180. // szComputerName - Computer name. This parameter will be NULL
  7181. // for local computer.
  7182. //
  7183. // Return: TRUE if successful
  7184. // FALSE if an error occurs
  7185. //
  7186. // Comments:
  7187. //
  7188. // History: Date Author Comment
  7189. // 6/23/95 ericflo Created
  7190. //
  7191. //*************************************************************
  7192. BOOL DeleteProfileEx (LPCTSTR lpSidString, LPTSTR lpLocalProfile, DWORD dwDeleteFlags, HKEY hKeyLM, LPCTSTR szComputerName)
  7193. {
  7194. LONG lResult;
  7195. TCHAR szTemp[MAX_PATH];
  7196. TCHAR szUserGuid[MAX_PATH], szBuffer[MAX_PATH];
  7197. TCHAR szRegBackup[MAX_PATH];
  7198. HKEY hKey;
  7199. DWORD dwType, dwSize, dwErr;
  7200. BOOL bRetVal=TRUE;
  7201. LPTSTR lpEnd = NULL;
  7202. BOOL bBackup;
  7203. bBackup = dwDeleteFlags & DP_BACKUP;
  7204. dwErr = GetLastError();
  7205. //
  7206. // Cleanup the registry first.
  7207. // delete the guid only if we don't have a bak to keep track of
  7208. //
  7209. if (lpSidString && *lpSidString) {
  7210. //
  7211. // If profile in use then do not delete it
  7212. //
  7213. if (IsProfileInUse(szComputerName, lpSidString)) {
  7214. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Fail to delete profile with sid %s as it is still in use."), lpSidString));
  7215. dwErr = ERROR_INVALID_PARAMETER;
  7216. bRetVal = FALSE;
  7217. goto Exit;
  7218. }
  7219. if (!(dwDeleteFlags & DP_BACKUPEXISTS)) {
  7220. lstrcpy(szTemp, PROFILE_LIST_PATH);
  7221. lstrcat(szTemp, TEXT("\\"));
  7222. lstrcat(szTemp, lpSidString);
  7223. //
  7224. // get the user guid
  7225. //
  7226. lResult = RegOpenKeyEx(hKeyLM, szTemp, 0, KEY_READ, &hKey);
  7227. if (lResult == ERROR_SUCCESS) {
  7228. //
  7229. // Query for the user guid
  7230. //
  7231. dwSize = MAX_PATH * sizeof(TCHAR);
  7232. lResult = RegQueryValueEx (hKey, PROFILE_GUID, NULL, &dwType, (LPBYTE) szUserGuid, &dwSize);
  7233. if (lResult != ERROR_SUCCESS) {
  7234. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Failed to query profile guid with error %d"), lResult));
  7235. }
  7236. else {
  7237. lstrcpy(szTemp, PROFILE_GUID_PATH);
  7238. lstrcat(szTemp, TEXT("\\"));
  7239. lstrcat(szTemp, szUserGuid);
  7240. //
  7241. // Delete the profile guid from the guid list
  7242. //
  7243. lResult = RegDeleteKey(hKeyLM, szTemp);
  7244. if (lResult != ERROR_SUCCESS) {
  7245. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: failed to delete profile guid. Error = %d"), lResult));
  7246. }
  7247. }
  7248. RegCloseKey(hKey);
  7249. }
  7250. }
  7251. lstrcpy(szTemp, PROFILE_LIST_PATH);
  7252. lstrcat(szTemp, TEXT("\\"));
  7253. lstrcat(szTemp, lpSidString);
  7254. if (bBackup) {
  7255. lstrcpy(szRegBackup, szTemp);
  7256. lstrcat(szRegBackup, c_szBAK);
  7257. lResult = RegRenameKey(hKeyLM, szTemp, szRegBackup);
  7258. if (lResult != ERROR_SUCCESS) {
  7259. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Unable to rename registry entry. Error = %d"), lResult));
  7260. dwErr = lResult;
  7261. bRetVal = FALSE;
  7262. }
  7263. }
  7264. else {
  7265. lResult = RegDeleteKey(hKeyLM, szTemp);
  7266. if (lResult != ERROR_SUCCESS) {
  7267. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Unable to delete registry entry. Error = %d"), lResult));
  7268. dwErr = lResult;
  7269. bRetVal = FALSE;
  7270. }
  7271. }
  7272. }
  7273. if (bBackup) {
  7274. lResult = RegOpenKeyEx(hKeyLM, szRegBackup, 0, KEY_ALL_ACCESS, &hKey);
  7275. if (lResult == ERROR_SUCCESS) {
  7276. DWORD dwInternalFlags;
  7277. dwSize = sizeof(DWORD);
  7278. lResult = RegQueryValueEx (hKey, PROFILE_STATE, NULL, &dwType, (LPBYTE)&dwInternalFlags, &dwSize);
  7279. if (lResult == ERROR_SUCCESS) {
  7280. dwInternalFlags |= PROFILE_THIS_IS_BAK;
  7281. lResult = RegSetValueEx (hKey, PROFILE_STATE, 0, REG_DWORD,
  7282. (LPBYTE) &dwInternalFlags, sizeof(dwInternalFlags));
  7283. }
  7284. else {
  7285. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Failed to query profile internalflags with error %d"), lResult));
  7286. }
  7287. RegCloseKey(hKey);
  7288. }
  7289. } else {
  7290. if (!Delnode (lpLocalProfile)) {
  7291. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Delnode failed. Error = %d"), GetLastError()));
  7292. dwErr = GetLastError();
  7293. bRetVal = FALSE;
  7294. }
  7295. }
  7296. if (dwDeleteFlags & DP_DELBACKUP) {
  7297. goto Exit;
  7298. // don't delete any more stuff because the user actually might be logged in.
  7299. }
  7300. //
  7301. // Delete the Group Policy per user stuff..
  7302. //
  7303. lstrcpy(szBuffer, GP_XXX_SID_PREFIX);
  7304. lpEnd = CheckSlash(szBuffer);
  7305. lstrcpy(lpEnd, lpSidString);
  7306. if (!RegDelnode (hKeyLM, szBuffer)) {
  7307. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Failed to delete the group policy key %s"), szBuffer));
  7308. }
  7309. lstrcpy(szBuffer, GP_EXTENSIONS_SID_PREFIX);
  7310. lpEnd = CheckSlash(szBuffer);
  7311. lstrcpy(lpEnd, lpSidString);
  7312. if (!RegDelnode (hKeyLM, szBuffer)) {
  7313. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Failed to delete the group policy extensions key %s"), szBuffer));
  7314. }
  7315. DeletePolicyState( lpSidString );
  7316. Exit:
  7317. SetLastError(dwErr);
  7318. return bRetVal;
  7319. }
  7320. //*************************************************************
  7321. //
  7322. // UpgradeProfile()
  7323. //
  7324. // Purpose: Called after a profile is successfully loaded.
  7325. // Stamps build number into the profile, and if
  7326. // appropriate upgrades the per-user settings
  7327. // that NT setup wants done.
  7328. //
  7329. // Parameters: lpProfile - Profile Information
  7330. // pEnv - Environment block
  7331. //
  7332. // Return: TRUE if successful
  7333. // FALSE if an error occurs
  7334. //
  7335. // Comments:
  7336. //
  7337. // History: Date Author Comment
  7338. // 7/7/95 ericflo Created
  7339. //
  7340. //*************************************************************
  7341. BOOL UpgradeProfile (LPPROFILE lpProfile, LPVOID pEnv)
  7342. {
  7343. HKEY hKey;
  7344. DWORD dwDisp, dwType, dwSize, dwBuildNumber;
  7345. LONG lResult;
  7346. BOOL bUpgrade = FALSE;
  7347. BOOL bDoUserdiff = TRUE;
  7348. //
  7349. // Verbose output
  7350. //
  7351. DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Entering")));
  7352. //
  7353. // Query for the build number
  7354. //
  7355. lResult = RegCreateKeyEx (lpProfile->hKeyCurrentUser, WINLOGON_KEY,
  7356. 0, NULL, REG_OPTION_NON_VOLATILE,
  7357. KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
  7358. if (lResult != ERROR_SUCCESS) {
  7359. DebugMsg((DM_WARNING, TEXT("UpgradeProfile: Failed to open winlogon key. Error = %d"), lResult));
  7360. return FALSE;
  7361. }
  7362. dwSize = sizeof(dwBuildNumber);
  7363. lResult = RegQueryValueEx (hKey, PROFILE_BUILD_NUMBER,
  7364. NULL, &dwType, (LPBYTE)&dwBuildNumber,
  7365. &dwSize);
  7366. if (lResult == ERROR_SUCCESS) {
  7367. //
  7368. // Found the build number. If the profile build is greater,
  7369. // we don't want to process the userdiff hive
  7370. //
  7371. if (dwBuildNumber >= g_dwBuildNumber) {
  7372. DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Build numbers match")));
  7373. bDoUserdiff = FALSE;
  7374. }
  7375. } else {
  7376. dwBuildNumber = 0;
  7377. }
  7378. if (bDoUserdiff) {
  7379. //
  7380. // Set the build number
  7381. //
  7382. lResult = RegSetValueEx (hKey, PROFILE_BUILD_NUMBER, 0, REG_DWORD,
  7383. (LPBYTE) &g_dwBuildNumber, sizeof(g_dwBuildNumber));
  7384. if (lResult != ERROR_SUCCESS) {
  7385. DebugMsg((DM_WARNING, TEXT("UpgradeProfile: Failed to set build number. Error = %d"), lResult));
  7386. }
  7387. }
  7388. //
  7389. // Close the registry key
  7390. //
  7391. RegCloseKey (hKey);
  7392. if (bDoUserdiff) {
  7393. //
  7394. // Apply changes to user's hive that NT setup needs.
  7395. //
  7396. if (!ProcessUserDiff(lpProfile, dwBuildNumber, pEnv)) {
  7397. DebugMsg((DM_WARNING, TEXT("UpgradeProfile: ProcessUserDiff failed")));
  7398. }
  7399. }
  7400. DebugMsg((DM_VERBOSE, TEXT("UpgradeProfile: Leaving Successfully")));
  7401. return TRUE;
  7402. }
  7403. //*************************************************************
  7404. //
  7405. // SetProfileTime()
  7406. //
  7407. // Purpose: Sets the timestamp on the remote profile and
  7408. // local profile to be the same regardless of the
  7409. // file system type being used.
  7410. //
  7411. // Parameters: lpProfile - Profile Information
  7412. //
  7413. // Return: TRUE if successful
  7414. // FALSE if an error occurs
  7415. //
  7416. // Comments:
  7417. //
  7418. // History: Date Author Comment
  7419. // 9/25/95 ericflo Ported
  7420. //
  7421. //*************************************************************
  7422. BOOL SetProfileTime(LPPROFILE lpProfile)
  7423. {
  7424. HANDLE hFileCentral;
  7425. HANDLE hFileLocal;
  7426. FILETIME ft;
  7427. TCHAR szProfile[MAX_PATH];
  7428. LPTSTR lpEnd;
  7429. HANDLE hOldToken;
  7430. //
  7431. // Impersonate the user
  7432. //
  7433. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  7434. DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to impersonate user")));
  7435. return FALSE;
  7436. }
  7437. //
  7438. // Create the central filename
  7439. //
  7440. lstrcpy (szProfile, lpProfile->lpRoamingProfile);
  7441. lpEnd = CheckSlash (szProfile);
  7442. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  7443. lstrcpy (lpEnd, c_szNTUserMan);
  7444. } else {
  7445. lstrcpy (lpEnd, c_szNTUserDat);
  7446. }
  7447. hFileCentral = CreateFile(szProfile,
  7448. GENERIC_READ | GENERIC_WRITE,
  7449. FILE_SHARE_READ, NULL,
  7450. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  7451. if (hFileCentral == INVALID_HANDLE_VALUE) {
  7452. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't open central profile <%s>, error = %d"),
  7453. szProfile, GetLastError()));
  7454. if (!RevertToUser(&hOldToken)) {
  7455. DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
  7456. }
  7457. return FALSE;
  7458. } else {
  7459. if (!GetFileTime(hFileCentral, NULL, NULL, &ft)) {
  7460. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't get time of central profile, error = %d"), GetLastError()));
  7461. }
  7462. }
  7463. //
  7464. // Revert to being 'ourself'
  7465. //
  7466. if (!RevertToUser(&hOldToken)) {
  7467. DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
  7468. }
  7469. //
  7470. // Create the local filename
  7471. //
  7472. lstrcpy (szProfile, lpProfile->lpLocalProfile);
  7473. lpEnd = CheckSlash (szProfile);
  7474. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY) {
  7475. lstrcpy (lpEnd, c_szNTUserMan);
  7476. } else {
  7477. lstrcpy (lpEnd, c_szNTUserDat);
  7478. }
  7479. hFileLocal = CreateFile(szProfile,
  7480. GENERIC_READ | GENERIC_WRITE,
  7481. FILE_SHARE_READ, NULL,
  7482. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  7483. if (hFileLocal == INVALID_HANDLE_VALUE) {
  7484. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't open local profile <%s>, error = %d"),
  7485. szProfile, GetLastError()));
  7486. } else {
  7487. if (!SetFileTime(hFileLocal, NULL, NULL, &ft)) {
  7488. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't set time on local profile, error = %d"), GetLastError()));
  7489. }
  7490. if (!GetFileTime(hFileLocal, NULL, NULL, &ft)) {
  7491. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't get time on local profile, error = %d"), GetLastError()));
  7492. }
  7493. CloseHandle(hFileLocal);
  7494. }
  7495. //
  7496. // Reset time of central profile in case of discrepencies in
  7497. // times of different file systems.
  7498. //
  7499. //
  7500. // Impersonate the user
  7501. //
  7502. if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) {
  7503. DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to impersonate user")));
  7504. CloseHandle(hFileCentral);
  7505. return FALSE;
  7506. }
  7507. //
  7508. // Set the time on the central profile
  7509. //
  7510. if (!SetFileTime(hFileCentral, NULL, NULL, &ft)) {
  7511. DebugMsg((DM_WARNING, TEXT("SetProfileTime: couldn't set time on local profile, error = %d"), GetLastError()));
  7512. }
  7513. CloseHandle(hFileCentral);
  7514. //
  7515. // Revert to being 'ourself'
  7516. //
  7517. if (!RevertToUser(&hOldToken)) {
  7518. DebugMsg((DM_WARNING, TEXT("SetProfileTime: Failed to revert to self")));
  7519. }
  7520. return TRUE;
  7521. }
  7522. //*************************************************************
  7523. //
  7524. // IsCacheDeleted()
  7525. //
  7526. // Purpose: Determines if the locally cached copy of the
  7527. // roaming profile should be deleted.
  7528. //
  7529. // Parameters: void
  7530. //
  7531. // Return: TRUE if local cache should be deleted
  7532. // FALSE if not
  7533. //
  7534. // Comments:
  7535. //
  7536. // History: Date Author Comment
  7537. // 6/28/96 ericflo Created
  7538. //
  7539. //*************************************************************
  7540. BOOL IsCacheDeleted (void)
  7541. {
  7542. BOOL bRetVal = FALSE;
  7543. DWORD dwSize, dwType;
  7544. HKEY hKey;
  7545. //
  7546. // Open the winlogon registry key
  7547. //
  7548. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  7549. WINLOGON_KEY,
  7550. 0,
  7551. KEY_READ,
  7552. &hKey) == ERROR_SUCCESS) {
  7553. //
  7554. // Check for the flag.
  7555. //
  7556. dwSize = sizeof(BOOL);
  7557. RegQueryValueEx (hKey,
  7558. DELETE_ROAMING_CACHE,
  7559. NULL,
  7560. &dwType,
  7561. (LPBYTE) &bRetVal,
  7562. &dwSize);
  7563. RegCloseKey (hKey);
  7564. }
  7565. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  7566. SYSTEM_POLICIES_KEY,
  7567. 0,
  7568. KEY_READ,
  7569. &hKey) == ERROR_SUCCESS) {
  7570. //
  7571. // Check for the flag.
  7572. //
  7573. dwSize = sizeof(BOOL);
  7574. RegQueryValueEx (hKey,
  7575. DELETE_ROAMING_CACHE,
  7576. NULL,
  7577. &dwType,
  7578. (LPBYTE) &bRetVal,
  7579. &dwSize);
  7580. RegCloseKey (hKey);
  7581. }
  7582. return bRetVal;
  7583. }
  7584. //*************************************************************
  7585. //
  7586. // GetProfileType()
  7587. //
  7588. // Purpose: Finds out some characterstics of a loaded profile
  7589. //
  7590. // Parameters: dwFlags - Returns the various profile flags
  7591. //
  7592. // Return: TRUE if successful
  7593. // FALSE if an error occurs
  7594. //
  7595. // Comments: should be called after impersonation.
  7596. //
  7597. // History: Date Author Comment
  7598. // 11/10/98 ushaji Created
  7599. //
  7600. //*************************************************************
  7601. BOOL WINAPI GetProfileType(DWORD *dwFlags)
  7602. {
  7603. LPTSTR SidString;
  7604. DWORD error, dwErr;
  7605. HKEY hSubKey;
  7606. BOOL bRetVal = FALSE;
  7607. LPPROFILE lpProfile = NULL;
  7608. HANDLE hToken;
  7609. if (!dwFlags) {
  7610. SetLastError(ERROR_INVALID_PARAMETER);
  7611. return FALSE;
  7612. }
  7613. *dwFlags = 0;
  7614. dwErr = GetLastError();
  7615. //
  7616. // Get the token for the caller
  7617. //
  7618. if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) {
  7619. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
  7620. DebugMsg((DM_WARNING, TEXT("GetProfileType: Failed to get token with %d"), GetLastError()));
  7621. return FALSE;
  7622. }
  7623. }
  7624. //
  7625. // Get the Sid string for the user
  7626. //
  7627. SidString = GetProfileSidString(hToken);
  7628. if (!SidString) {
  7629. DebugMsg((DM_WARNING, TEXT("GetProfileType: Failed to get sid string for user")));
  7630. dwErr = GetLastError();
  7631. goto Exit;
  7632. }
  7633. error = RegOpenKeyEx(HKEY_USERS, SidString, 0, KEY_READ, &hSubKey);
  7634. if (error == ERROR_SUCCESS) {
  7635. DebugMsg((DM_VERBOSE, TEXT("GetProfileType: Profile already loaded.")));
  7636. RegCloseKey(hSubKey);
  7637. }
  7638. else {
  7639. DebugMsg((DM_WARNING, TEXT("GetProfileType: Profile is not loaded.")));
  7640. dwErr = error;
  7641. goto Exit;
  7642. }
  7643. lpProfile = LoadProfileInfo(NULL, hToken, NULL);
  7644. if (!lpProfile) {
  7645. DebugMsg((DM_WARNING, TEXT("GetProfileType: Couldn't load Profile Information.")));
  7646. dwErr = GetLastError();
  7647. *dwFlags = 0;
  7648. goto Exit;
  7649. }
  7650. if (lpProfile->dwInternalFlags & PROFILE_GUEST_USER)
  7651. *dwFlags |= PT_TEMPORARY;
  7652. if (lpProfile->dwInternalFlags & PROFILE_MANDATORY)
  7653. *dwFlags |= PT_MANDATORY;
  7654. // external API, retaining the mandatory flag
  7655. if (lpProfile->dwInternalFlags & PROFILE_READONLY)
  7656. *dwFlags |= PT_MANDATORY;
  7657. if (((lpProfile->dwUserPreference != USERINFO_LOCAL)) &&
  7658. ((lpProfile->dwInternalFlags & PROFILE_UPDATE_CENTRAL) ||
  7659. (lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL))) {
  7660. *dwFlags |= PT_ROAMING;
  7661. if (IsCacheDeleted()) {
  7662. DebugMsg((DM_VERBOSE, TEXT("GetProfileType: Profile is to be deleted")));
  7663. *dwFlags |= PT_TEMPORARY;
  7664. }
  7665. }
  7666. if (lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED)
  7667. *dwFlags |= PT_TEMPORARY;
  7668. bRetVal = TRUE;
  7669. Exit:
  7670. if (SidString)
  7671. DeleteSidString(SidString);
  7672. SetLastError(dwErr);
  7673. if (lpProfile) {
  7674. if (lpProfile->lpLocalProfile) {
  7675. LocalFree (lpProfile->lpLocalProfile);
  7676. }
  7677. if (lpProfile->lpRoamingProfile) {
  7678. LocalFree (lpProfile->lpRoamingProfile);
  7679. }
  7680. LocalFree (lpProfile);
  7681. }
  7682. CloseHandle (hToken);
  7683. if (bRetVal) {
  7684. DebugMsg((DM_VERBOSE, TEXT("GetProfileType: ProfileFlags is %d"), *dwFlags));
  7685. }
  7686. return bRetVal;
  7687. }
  7688. //*************************************************************
  7689. //
  7690. // DumpOpenRegistryHandle()
  7691. //
  7692. // Purpose: Dumps the existing reg handle into the debugger
  7693. //
  7694. // Parameters: lpKeyName - The key name to the key in the form of
  7695. // \registry\user....
  7696. //
  7697. //
  7698. // Return: Nothing
  7699. //
  7700. // Comments:
  7701. //
  7702. // History: Date Author Comment
  7703. //*************************************************************
  7704. void DumpOpenRegistryHandle(LPTSTR lpkeyName)
  7705. {
  7706. UNICODE_STRING UnicodeKeyName;
  7707. OBJECT_ATTRIBUTES keyAttributes;
  7708. ULONG HandleCount = 0;
  7709. BOOL bBreakOnUnloadFailure=FALSE;
  7710. HKEY hKey;
  7711. DWORD dwSize, dwType;
  7712. //
  7713. // Initialize unicode string for our in params
  7714. //
  7715. RtlInitUnicodeString(&UnicodeKeyName, lpkeyName);
  7716. //
  7717. // Initialize the Obja structure
  7718. //
  7719. InitializeObjectAttributes(
  7720. &keyAttributes,
  7721. &UnicodeKeyName,
  7722. OBJ_CASE_INSENSITIVE,
  7723. NULL,
  7724. NULL
  7725. );
  7726. NtQueryOpenSubKeys(&keyAttributes, &HandleCount);
  7727. DebugMsg((DM_WARNING, TEXT("DumpOpenRegistryHandle: %d user registry Handles leaked from %s"), HandleCount, lpkeyName));
  7728. //
  7729. // for debugging sometimes it is necessary to break at the point of
  7730. // failure
  7731. //
  7732. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  7733. WINLOGON_KEY,
  7734. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  7735. dwSize = sizeof(bBreakOnUnloadFailure);
  7736. RegQueryValueEx (hKey,
  7737. TEXT("BreakOnHiveUnloadFailure"),
  7738. NULL,
  7739. &dwType,
  7740. (LPBYTE) &bBreakOnUnloadFailure,
  7741. &dwSize);
  7742. RegCloseKey (hKey);
  7743. }
  7744. if (bBreakOnUnloadFailure)
  7745. DebugBreak();
  7746. }
  7747. //*************************************************************
  7748. //
  7749. // ExtractProfileFromBackup()
  7750. //
  7751. // Purpose: Extracts the profile from backup if required.
  7752. //
  7753. // Parameters: hToken - User Token
  7754. // SidString -
  7755. // dwBackupFlags - Backup Flags.
  7756. // indicating that profile already exists.
  7757. // Profile created from backup
  7758. // 0 indicates no such profile exists
  7759. //
  7760. //
  7761. // Return: (BOOL) TRUE if successful
  7762. // FALSE if an error occurs
  7763. //
  7764. // Comments:
  7765. //
  7766. // History: Date Author Comment
  7767. // 9/21/99 ushaji Created
  7768. //
  7769. //*************************************************************
  7770. #define EX_ALREADY_EXISTS 1
  7771. #define EX_PROFILE_CREATED 2
  7772. BOOL ExtractProfileFromBackup(HANDLE hToken, LPTSTR SidString, DWORD *dwBackupFlags)
  7773. {
  7774. TCHAR LocalKey[MAX_PATH], *lpEnd, szLocalProfile;
  7775. TCHAR LocalBackupKey[MAX_PATH];
  7776. HKEY hKey=NULL;
  7777. DWORD dwType, dwSize;
  7778. DWORD lResult;
  7779. LPTSTR lpExpandedPath;
  7780. DWORD cbExpProfileImage = sizeof(TCHAR)*MAX_PATH;
  7781. TCHAR lpExpProfileImage[MAX_PATH];
  7782. BOOL bRetVal = TRUE;
  7783. DWORD dwInternalFlags;
  7784. DWORD cb;
  7785. *dwBackupFlags = 0;
  7786. lstrcpy(LocalKey, PROFILE_LIST_PATH);
  7787. lpEnd = CheckSlash (LocalKey);
  7788. lstrcpy(lpEnd, SidString);
  7789. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LocalKey, 0, KEY_ALL_ACCESS, &hKey);
  7790. if (lResult == ERROR_SUCCESS) {
  7791. dwSize = sizeof(DWORD);
  7792. lResult = RegQueryValueEx (hKey, PROFILE_STATE, NULL,
  7793. &dwType, (LPBYTE) &dwInternalFlags, &dwSize);
  7794. if (lResult == ERROR_SUCCESS) {
  7795. //
  7796. // if there is a sid key, check whether this is a temp profile
  7797. //
  7798. if (dwInternalFlags & PROFILE_TEMP_ASSIGNED) {
  7799. DWORD dwDeleteFlags = 0;
  7800. if (dwInternalFlags & PROFILE_BACKUP_EXISTS) {
  7801. dwDeleteFlags |= DP_BACKUPEXISTS;
  7802. }
  7803. //
  7804. // We need the path to pass to DeleteProfile
  7805. //
  7806. lResult = RegQueryValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0, &dwType,
  7807. (LPBYTE)lpExpProfileImage, &cbExpProfileImage);
  7808. if (lResult == ERROR_SUCCESS && cbExpProfileImage) {
  7809. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Local profile image filename = <%s>"), lpExpProfileImage));
  7810. if (dwType == REG_EXPAND_SZ) {
  7811. //
  7812. // Expand the profile image filename
  7813. //
  7814. cb = sizeof(lpExpProfileImage);
  7815. lpExpandedPath = (LPTSTR)LocalAlloc(LPTR, cb);
  7816. if (lpExpandedPath) {
  7817. ExpandEnvironmentStrings(lpExpProfileImage, lpExpandedPath, ARRAYSIZE(lpExpProfileImage));
  7818. lstrcpy(lpExpProfileImage, lpExpandedPath);
  7819. LocalFree(lpExpandedPath);
  7820. }
  7821. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Expanded local profile image filename = <%s>"), lpExpProfileImage));
  7822. }
  7823. if (!DeleteProfileEx (SidString, lpExpProfileImage, dwDeleteFlags, HKEY_LOCAL_MACHINE, NULL)) {
  7824. DebugMsg((DM_WARNING, TEXT("ExtractProfileFromBackup: DeleteProfileDirectory returned false (2). Error = %d"), GetLastError()));
  7825. lResult = GetLastError();
  7826. goto Exit;
  7827. }
  7828. else {
  7829. if (!(dwInternalFlags & PROFILE_BACKUP_EXISTS)) {
  7830. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Temprorary profile but there is no backup")));
  7831. bRetVal = TRUE;
  7832. goto Exit;
  7833. }
  7834. }
  7835. }
  7836. else {
  7837. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Couldn't get the local profile path")));
  7838. bRetVal = FALSE;
  7839. goto Exit;
  7840. }
  7841. }
  7842. else {
  7843. *dwBackupFlags |= EX_ALREADY_EXISTS;
  7844. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: A profile already exists")));
  7845. goto Exit;
  7846. }
  7847. }
  7848. else {
  7849. DebugMsg((DM_VERBOSE, TEXT("GetExistingLocalProfileImage: Failed to query internal flags with error %d"), lResult));
  7850. bRetVal = FALSE;
  7851. goto Exit;
  7852. }
  7853. RegCloseKey(hKey);
  7854. hKey = NULL;
  7855. }
  7856. else {
  7857. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Failed to open key %s with error %d"), LocalKey, lResult));
  7858. }
  7859. //
  7860. // Now try to get the profile from the backup
  7861. //
  7862. lstrcpy(LocalBackupKey, LocalKey);
  7863. lstrcat(LocalBackupKey, c_szBAK);
  7864. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LocalBackupKey, 0, KEY_ALL_ACCESS, &hKey);
  7865. if (lResult == ERROR_SUCCESS) {
  7866. RegCloseKey(hKey);
  7867. hKey = NULL;
  7868. //
  7869. // Check whether the key exists should already be done before this
  7870. //
  7871. lResult = RegRenameKey(HKEY_LOCAL_MACHINE, LocalBackupKey, LocalKey);
  7872. if (lResult == ERROR_SUCCESS) {
  7873. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, LocalKey, 0, KEY_ALL_ACCESS, &hKey);
  7874. if (lResult == ERROR_SUCCESS) {
  7875. DWORD dwInternalFlags;
  7876. dwSize = sizeof(DWORD);
  7877. lResult = RegQueryValueEx (hKey, PROFILE_STATE, NULL, &dwType, (LPBYTE)&dwInternalFlags, &dwSize);
  7878. if (lResult == ERROR_SUCCESS) {
  7879. dwInternalFlags &= ~PROFILE_THIS_IS_BAK;
  7880. lResult = RegSetValueEx (hKey, PROFILE_STATE, 0, REG_DWORD,
  7881. (LPBYTE) &dwInternalFlags, sizeof(dwInternalFlags));
  7882. }
  7883. RegCloseKey(hKey);
  7884. hKey = NULL;
  7885. }
  7886. else {
  7887. DebugMsg((DM_WARNING, TEXT("DeleteProfileEx: Failed to open LocalKey with error %d"), lResult));
  7888. }
  7889. bRetVal = TRUE;
  7890. *dwBackupFlags |= EX_PROFILE_CREATED;
  7891. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Profile created from Backup")));
  7892. goto Exit;
  7893. }
  7894. else {
  7895. DebugMsg((DM_WARNING, TEXT("ExtractProfileFromBackup: Couldn't rename key %s -> %s. Error = %d"), LocalBackupKey, LocalKey, lResult));
  7896. bRetVal = FALSE;
  7897. goto Exit;
  7898. }
  7899. }
  7900. else {
  7901. DebugMsg((DM_VERBOSE, TEXT("ExtractProfileFromBackup: Couldn't open backup profile key. Error = %d"), lResult));
  7902. }
  7903. Exit:
  7904. if (hKey)
  7905. RegCloseKey(hKey);
  7906. if (!bRetVal)
  7907. SetLastError(lResult);
  7908. return bRetVal;
  7909. }
  7910. //*************************************************************
  7911. //
  7912. // PatchNewProfileIfRequired()
  7913. //
  7914. // Purpose: if the old sid and the new sid are not the same, delete the old
  7915. // from the profile list and update the guidlist
  7916. //
  7917. // Parameters: hToken - User Token
  7918. //
  7919. // Return: (BOOL) TRUE if successful
  7920. // FALSE if an error occurs
  7921. //
  7922. // Comments:
  7923. //
  7924. // History: Date Author Comment
  7925. // 11/16/98 ushaji Created
  7926. //
  7927. //*************************************************************
  7928. BOOL PatchNewProfileIfRequired(HANDLE hToken)
  7929. {
  7930. TCHAR LocalOldProfileKey[MAX_PATH], LocalNewProfileKey[MAX_PATH], *lpEnd;
  7931. HKEY hNewKey=NULL;
  7932. BOOL bRetVal = FALSE;
  7933. DWORD dwType, dwDisp, dwSize;
  7934. LONG lResult;
  7935. LPTSTR OldSidString=NULL, SidString=NULL;
  7936. PSID UserSid;
  7937. DWORD dwBackupFlags;
  7938. HMODULE hMsiLib = NULL;
  7939. PFNMSINOTIFYSIDCHANGE pfnMsiNotifySidChange;
  7940. //
  7941. // Get the current sid.
  7942. //
  7943. SidString = GetSidString(hToken);
  7944. if (!SidString) {
  7945. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: No SidString found")));
  7946. return FALSE;
  7947. }
  7948. if (ExtractProfileFromBackup(hToken, SidString, &dwBackupFlags)) {
  7949. if ((dwBackupFlags & EX_ALREADY_EXISTS) || (dwBackupFlags & EX_PROFILE_CREATED)) {
  7950. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: A profile already exists with the current sid, exitting")));
  7951. bRetVal = TRUE;
  7952. goto Exit;
  7953. }
  7954. }
  7955. else {
  7956. //
  7957. // Treat it as if no such profile exists
  7958. //
  7959. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: ExtractProfileFromBackup returned error %d"), GetLastError()));
  7960. }
  7961. //
  7962. // Get the old sid.
  7963. //
  7964. OldSidString = GetOldSidString(hToken, PROFILE_GUID_PATH);
  7965. if (!OldSidString) {
  7966. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: No OldSidString found")));
  7967. bRetVal = TRUE;
  7968. goto Exit;
  7969. }
  7970. //
  7971. // if old sid and new sid are the same quit
  7972. //
  7973. if (lstrcmpi(OldSidString, SidString) == 0) {
  7974. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: Old and the new sid are the same, exitting")));
  7975. bRetVal = TRUE;
  7976. goto Exit;
  7977. }
  7978. if (ExtractProfileFromBackup(hToken, OldSidString, &dwBackupFlags)) {
  7979. if ((dwBackupFlags & EX_ALREADY_EXISTS) || (dwBackupFlags & EX_PROFILE_CREATED)) {
  7980. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: A profile with the old sid found")));
  7981. }
  7982. }
  7983. else {
  7984. //
  7985. // Treat it as if no such profile exists
  7986. //
  7987. DebugMsg((DM_VERBOSE, TEXT("PatchNewProfileIfRequred: ExtractProfileFromBackup returned error %d"), GetLastError()));
  7988. }
  7989. lstrcpy(LocalNewProfileKey, PROFILE_LIST_PATH);
  7990. lpEnd = CheckSlash (LocalNewProfileKey);
  7991. lstrcpy(lpEnd, SidString);
  7992. lstrcpy(LocalOldProfileKey, PROFILE_LIST_PATH);
  7993. lpEnd = CheckSlash (LocalOldProfileKey);
  7994. lstrcpy(lpEnd, OldSidString);
  7995. lResult = RegRenameKey(HKEY_LOCAL_MACHINE, LocalOldProfileKey, LocalNewProfileKey);
  7996. if (lResult != ERROR_SUCCESS) {
  7997. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: Failed to rename profile mapping key with error %d"), lResult));
  7998. goto Exit;
  7999. }
  8000. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalNewProfileKey, 0, 0, 0,
  8001. KEY_WRITE, NULL, &hNewKey, &dwDisp);
  8002. if (lResult != ERROR_SUCCESS) {
  8003. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: Failed to open new profile mapping key with error %d"), lResult));
  8004. goto Exit;
  8005. }
  8006. //
  8007. // Get the sid of the logged on user
  8008. //
  8009. UserSid = GetUserSid(hToken);
  8010. if (UserSid != NULL) {
  8011. //
  8012. // Store the user sid under the Sid key of the local profile
  8013. //
  8014. lResult = RegSetValueEx(hNewKey,
  8015. TEXT("Sid"),
  8016. 0,
  8017. REG_BINARY,
  8018. (BYTE*)UserSid,
  8019. RtlLengthSid(UserSid));
  8020. if (lResult != ERROR_SUCCESS) {
  8021. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: Failed to set 'sid' value of user in profile list, error = %d"), lResult));
  8022. }
  8023. //
  8024. // We're finished with the user sid
  8025. //
  8026. DeleteUserSid(UserSid);
  8027. }
  8028. //
  8029. // Set the guid->sid corresp.
  8030. //
  8031. if (!SetOldSidString(hToken, SidString, PROFILE_GUID_PATH)) {
  8032. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: Couldn't set the old Sid in the GuidList")));
  8033. }
  8034. //
  8035. // Make a call to msi lib to notify sid change of user, so that it can update installation information
  8036. //
  8037. hMsiLib = LoadLibrary(TEXT("msi.dll"));
  8038. if (hMsiLib) {
  8039. pfnMsiNotifySidChange = (PFNMSINOTIFYSIDCHANGE) GetProcAddress(hMsiLib,
  8040. #ifdef UNICODE
  8041. "MsiNotifySidChangeW");
  8042. #else
  8043. "MsiNotifySidChangeA");
  8044. #endif
  8045. if (pfnMsiNotifySidChange) {
  8046. (*pfnMsiNotifySidChange)(OldSidString, SidString);
  8047. }
  8048. else {
  8049. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: GetProcAddress returned failure. error %d"), GetLastError()));
  8050. }
  8051. FreeLibrary(hMsiLib);
  8052. }
  8053. else {
  8054. DebugMsg((DM_WARNING, TEXT("PatchNewProfileIfRequred: LoadLibrary returned failure. error %d"), GetLastError()));
  8055. }
  8056. bRetVal = TRUE;
  8057. Exit:
  8058. if (SidString)
  8059. DeleteSidString(SidString);
  8060. if (OldSidString)
  8061. DeleteSidString(OldSidString);
  8062. if (hNewKey)
  8063. RegCloseKey(hNewKey);
  8064. return bRetVal;
  8065. }
  8066. //*************************************************************
  8067. //
  8068. // IncrementProfileRefCount()
  8069. //
  8070. // Purpose: Increments Profile Ref Count
  8071. //
  8072. // Parameters: lpProfile - Profile Information
  8073. // bInitilize - dwRef should be initialized
  8074. //
  8075. // Return: Ref Count
  8076. //
  8077. // Comments: This functions ref counts independent of ability
  8078. // to load/unload the hive.
  8079. //
  8080. // Caveat:
  8081. // We have changed the machanism here to use ref counting
  8082. // and not depend on unloadability of ntuser.dat. NT4
  8083. // apps might have forgotten to unloaduserprofiles
  8084. // and might still be working because the handle got
  8085. // closed automatically when processes
  8086. // exitted. This will be treated as an App Bug.
  8087. //
  8088. //
  8089. // History: Date Author Comment
  8090. // 1/12/99 ushaji Created
  8091. //
  8092. //*************************************************************
  8093. DWORD IncrementProfileRefCount(LPPROFILE lpProfile, BOOL bInitialize)
  8094. {
  8095. LPTSTR SidString, lpEnd;
  8096. TCHAR LocalProfileKey[MAX_PATH];
  8097. LONG lResult;
  8098. HKEY hKey;
  8099. DWORD dwType, dwSize, dwCount, dwDisp, dwRef=0;
  8100. //
  8101. // Get the Sid string for the user
  8102. //
  8103. SidString = GetSidString(lpProfile->hTokenUser);
  8104. if (!SidString) {
  8105. DebugMsg((DM_WARNING, TEXT("IncrementProfileRefCount: Failed to get sid string for user")));
  8106. return 0;
  8107. }
  8108. //
  8109. // Open the profile mapping
  8110. //
  8111. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  8112. lpEnd = CheckSlash (LocalProfileKey);
  8113. lstrcpy(lpEnd, SidString);
  8114. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  8115. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  8116. if (lResult != ERROR_SUCCESS) {
  8117. DebugMsg((DM_WARNING, TEXT("IncrementProfileRefCount: Failed to open profile mapping key with error %d"), lResult));
  8118. DeleteSidString(SidString);
  8119. return 0;
  8120. }
  8121. //
  8122. // Query for the profile ref count.
  8123. //
  8124. dwSize = sizeof(DWORD);
  8125. if (!bInitialize) {
  8126. lResult = RegQueryValueEx (hKey,
  8127. PROFILE_REF_COUNT,
  8128. 0,
  8129. &dwType,
  8130. (LPBYTE) &dwRef,
  8131. &dwSize);
  8132. if (lResult != ERROR_SUCCESS) {
  8133. DebugMsg((DM_VERBOSE, TEXT("IncrementProfileRefCount: Failed to query profile reference count with error %d"), lResult));
  8134. }
  8135. }
  8136. dwRef++;
  8137. //
  8138. // Set the profile Ref count
  8139. //
  8140. lResult = RegSetValueEx (hKey,
  8141. PROFILE_REF_COUNT,
  8142. 0,
  8143. REG_DWORD,
  8144. (LPBYTE) &dwRef,
  8145. sizeof(DWORD));
  8146. if (lResult != ERROR_SUCCESS) {
  8147. DebugMsg((DM_WARNING, TEXT("IncrementProfileRefCount: Failed to save profile reference count with error %d"), lResult));
  8148. }
  8149. DeleteSidString(SidString);
  8150. RegCloseKey (hKey);
  8151. return dwRef;
  8152. }
  8153. //*************************************************************
  8154. //
  8155. // DecrementProfileRefCount()
  8156. //
  8157. // Purpose: Deccrements Profile Ref Count
  8158. //
  8159. // Parameters: lpProfile - Profile Information
  8160. //
  8161. // Return: Ref Count
  8162. //
  8163. // Comments: This functions ref counts independent of ability
  8164. // to load/unload the hive.
  8165. //
  8166. // History: Date Author Comment
  8167. // 1/12/99 ushaji Created
  8168. //
  8169. //*************************************************************
  8170. DWORD DecrementProfileRefCount(LPPROFILE lpProfile)
  8171. {
  8172. LPTSTR SidString, lpEnd;
  8173. TCHAR LocalProfileKey[MAX_PATH];
  8174. LONG lResult;
  8175. HKEY hKey;
  8176. DWORD dwType, dwSize, dwCount, dwDisp, dwRef=0;
  8177. //
  8178. // Get the Sid string for the user
  8179. //
  8180. SidString = GetSidString(lpProfile->hTokenUser);
  8181. if (!SidString) {
  8182. DebugMsg((DM_WARNING, TEXT("DecrementProfileRefCount: Failed to get sid string for user")));
  8183. return 0;
  8184. }
  8185. //
  8186. // Open the profile mapping
  8187. //
  8188. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  8189. lpEnd = CheckSlash (LocalProfileKey);
  8190. lstrcpy(lpEnd, SidString);
  8191. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  8192. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  8193. if (lResult != ERROR_SUCCESS) {
  8194. DebugMsg((DM_WARNING, TEXT("DecrementProfileRefCount: Failed to open profile mapping key with error %d"), lResult));
  8195. DeleteSidString(SidString);
  8196. return 0;
  8197. }
  8198. //
  8199. // Query for the profile ref count.
  8200. //
  8201. dwSize = sizeof(DWORD);
  8202. lResult = RegQueryValueEx (hKey,
  8203. PROFILE_REF_COUNT,
  8204. 0,
  8205. &dwType,
  8206. (LPBYTE) &dwRef,
  8207. &dwSize);
  8208. if (lResult != ERROR_SUCCESS) {
  8209. DebugMsg((DM_VERBOSE, TEXT("DecrementProfileRefCount: Failed to query profile reference count with error %d"), lResult));
  8210. }
  8211. if (dwRef) {
  8212. dwRef--;
  8213. }
  8214. else {
  8215. DebugMsg((DM_WARNING, TEXT("DecrementRefCount: Ref Count is already zero !!!!!!")));
  8216. }
  8217. //
  8218. // Set the profile Ref count
  8219. //
  8220. lResult = RegSetValueEx (hKey,
  8221. PROFILE_REF_COUNT,
  8222. 0,
  8223. REG_DWORD,
  8224. (LPBYTE) &dwRef,
  8225. sizeof(DWORD));
  8226. if (lResult != ERROR_SUCCESS) {
  8227. DebugMsg((DM_WARNING, TEXT("DecrementProfileRefCount: Failed to save profile reference count with error %d"), lResult));
  8228. }
  8229. DeleteSidString(SidString);
  8230. RegCloseKey (hKey);
  8231. return dwRef;
  8232. }
  8233. //*************************************************************
  8234. //
  8235. // SaveProfileInfo()
  8236. //
  8237. // Purpose: Saves key parts of the lpProfile structure
  8238. // in the registry for UnloadUserProfile to use.
  8239. //
  8240. // Parameters: lpProfile - Profile information
  8241. //
  8242. // Return: (BOOL) TRUE if successful
  8243. // FALSE if an error occurs
  8244. //
  8245. // Comments:
  8246. //
  8247. // History: Date Author Comment
  8248. // 12/4/95 ericflo Created
  8249. //
  8250. //*************************************************************
  8251. BOOL SaveProfileInfo(LPPROFILE lpProfile)
  8252. {
  8253. LPTSTR SidString, lpEnd;
  8254. TCHAR LocalProfileKey[MAX_PATH];
  8255. LONG lResult;
  8256. HKEY hKey;
  8257. DWORD dwType, dwSize, dwCount, dwDisp;
  8258. LPTSTR szUserGuid = NULL;
  8259. //
  8260. // Get the Sid string for the user
  8261. //
  8262. SidString = GetSidString(lpProfile->hTokenUser);
  8263. if (!SidString) {
  8264. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to get sid string for user")));
  8265. return FALSE;
  8266. }
  8267. //
  8268. // Open the profile mapping
  8269. //
  8270. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  8271. lpEnd = CheckSlash (LocalProfileKey);
  8272. lstrcpy(lpEnd, SidString);
  8273. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  8274. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  8275. if (lResult != ERROR_SUCCESS) {
  8276. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to open profile mapping key with error %d"), lResult));
  8277. SetLastError(lResult);
  8278. DeleteSidString(SidString);
  8279. return FALSE;
  8280. }
  8281. //
  8282. // Save the flags
  8283. //
  8284. lResult = RegSetValueEx (hKey,
  8285. PROFILE_FLAGS,
  8286. 0,
  8287. REG_DWORD,
  8288. (LPBYTE) &lpProfile->dwFlags,
  8289. sizeof(DWORD));
  8290. if (lResult != ERROR_SUCCESS) {
  8291. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save flags with error %d"), lResult));
  8292. }
  8293. //
  8294. // Save the internal flags
  8295. //
  8296. lResult = RegSetValueEx (hKey,
  8297. PROFILE_STATE,
  8298. 0,
  8299. REG_DWORD,
  8300. (LPBYTE) &lpProfile->dwInternalFlags,
  8301. sizeof(DWORD));
  8302. if (lResult != ERROR_SUCCESS) {
  8303. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save flags2 with error %d"), lResult));
  8304. }
  8305. //
  8306. // Save the central profile path only if it is non-null.
  8307. // That way it will allow a roaming user/administrator to change roaming profile to local
  8308. // and then go back to roaming again.
  8309. //
  8310. //
  8311. // lpProfilePath contains the actual roaming share name whereas lpRoamingProfile contains path
  8312. // name wrt to mapped drive name. If lpProfilePath is NULL then use lpRoamingProfile which
  8313. // is a NULL string.
  8314. //
  8315. lResult = RegSetValueEx(hKey,
  8316. PROFILE_CENTRAL_PROFILE,
  8317. 0,
  8318. REG_SZ,
  8319. (LPBYTE) (lpProfile->lpProfilePath ?
  8320. lpProfile->lpProfilePath : lpProfile->lpRoamingProfile),
  8321. (lstrlen((lpProfile->lpProfilePath ?
  8322. lpProfile->lpProfilePath : lpProfile->lpRoamingProfile)) + 1) * sizeof(TCHAR));
  8323. if (lResult != ERROR_SUCCESS) {
  8324. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save central profile with error %d"), lResult));
  8325. }
  8326. //
  8327. // local profile path, saved in CreateLocalProfileImage
  8328. //
  8329. //
  8330. // Save the profile load time
  8331. //
  8332. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  8333. lResult = RegSetValueEx (hKey,
  8334. PROFILE_LOAD_TIME_LOW,
  8335. 0,
  8336. REG_DWORD,
  8337. (LPBYTE) &lpProfile->ftProfileLoad.dwLowDateTime,
  8338. sizeof(DWORD));
  8339. if (lResult != ERROR_SUCCESS) {
  8340. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save low profile load time with error %d"), lResult));
  8341. }
  8342. lResult = RegSetValueEx (hKey,
  8343. PROFILE_LOAD_TIME_HIGH,
  8344. 0,
  8345. REG_DWORD,
  8346. (LPBYTE) &lpProfile->ftProfileLoad.dwHighDateTime,
  8347. sizeof(DWORD));
  8348. if (lResult != ERROR_SUCCESS) {
  8349. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save high profile load time with error %d"), lResult));
  8350. }
  8351. }
  8352. //
  8353. // Set the user's GUID if this is a new profile
  8354. //
  8355. if (!(lpProfile->dwInternalFlags & PROFILE_TEMP_ASSIGNED) &&
  8356. (lpProfile->dwInternalFlags & PROFILE_NEW_LOCAL)) {
  8357. szUserGuid = GetUserGuid(lpProfile->hTokenUser);
  8358. if (szUserGuid) {
  8359. lResult = RegSetValueEx (hKey,
  8360. PROFILE_GUID,
  8361. 0,
  8362. REG_SZ,
  8363. (LPBYTE) szUserGuid,
  8364. (lstrlen(szUserGuid)+1)*sizeof(TCHAR));
  8365. if (lResult != ERROR_SUCCESS) {
  8366. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Failed to save user guid with error %d"), lResult));
  8367. }
  8368. LocalFree(szUserGuid);
  8369. }
  8370. //
  8371. // Save the guid->sid corresp. for the next time
  8372. //
  8373. if (!SetOldSidString(lpProfile->hTokenUser, SidString, PROFILE_GUID_PATH)) {
  8374. DebugMsg((DM_WARNING, TEXT("SaveProfileInfo: Couldn't set the old Sid in the GuidList")));
  8375. }
  8376. }
  8377. DeleteSidString(SidString);
  8378. RegCloseKey (hKey);
  8379. return(TRUE);
  8380. }
  8381. //*************************************************************
  8382. //
  8383. // LoadProfileInfo()
  8384. //
  8385. // Purpose: Loads key parts of the lpProfile structure
  8386. // in the registry for UnloadUserProfile to use.
  8387. //
  8388. // Parameters: hTokenClient - Caller's token.
  8389. // hTokenUser - User's token
  8390. // hKeyCurrentUser - User registry key handle
  8391. //
  8392. // Return: LPPROFILE if successful
  8393. // NULL if not
  8394. //
  8395. // Comments: This function doesn't re-initialize all of the
  8396. // fields in the PROFILE structure.
  8397. //
  8398. // History: Date Author Comment
  8399. // 12/5/95 ericflo Created
  8400. //
  8401. //*************************************************************
  8402. LPPROFILE LoadProfileInfo (HANDLE hTokenClient, HANDLE hTokenUser, HKEY hKeyCurrentUser)
  8403. {
  8404. LPPROFILE lpProfile;
  8405. LPTSTR SidString = NULL, lpEnd;
  8406. TCHAR szBuffer[MAX_PATH];
  8407. LONG lResult;
  8408. HKEY hKey = NULL;
  8409. DWORD dwType, dwSize;
  8410. UINT i;
  8411. BOOL bSuccess = FALSE;
  8412. DWORD dwErr = 0;
  8413. dwErr = GetLastError();
  8414. //
  8415. // Allocate an internal Profile structure to work with.
  8416. //
  8417. lpProfile = (LPPROFILE) LocalAlloc (LPTR, sizeof(USERPROFILE));
  8418. if (!lpProfile) {
  8419. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to allocate memory")));
  8420. dwErr = GetLastError();
  8421. goto Exit;
  8422. }
  8423. //
  8424. // Save the data passed in.
  8425. //
  8426. lpProfile->hTokenClient = hTokenClient;
  8427. lpProfile->hTokenUser = hTokenUser;
  8428. lpProfile->hKeyCurrentUser = hKeyCurrentUser;
  8429. //
  8430. // Allocate memory for the various paths
  8431. //
  8432. lpProfile->lpLocalProfile = (LPTSTR)LocalAlloc (LPTR, MAX_PATH * sizeof(TCHAR));
  8433. if (!lpProfile->lpLocalProfile) {
  8434. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to alloc memory for local profile path. Error = %d"),
  8435. GetLastError()));
  8436. dwErr = GetLastError();
  8437. goto Exit;
  8438. }
  8439. lpProfile->lpRoamingProfile = (LPTSTR)LocalAlloc (LPTR, MAX_PATH * sizeof(TCHAR));
  8440. if (!lpProfile->lpRoamingProfile) {
  8441. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to alloc memory for central profile path. Error = %d"),
  8442. GetLastError()));
  8443. dwErr = GetLastError();
  8444. goto Exit;
  8445. }
  8446. //
  8447. // Get the Sid string for the user
  8448. //
  8449. SidString = GetProfileSidString(lpProfile->hTokenUser);
  8450. if (!SidString) {
  8451. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to get sid string for user")));
  8452. dwErr = GetLastError();
  8453. goto Exit;
  8454. }
  8455. //
  8456. // Open the profile mapping
  8457. //
  8458. lstrcpy(szBuffer, PROFILE_LIST_PATH);
  8459. lpEnd = CheckSlash (szBuffer);
  8460. lstrcpy(lpEnd, SidString);
  8461. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0,
  8462. KEY_READ, &hKey);
  8463. if (lResult != ERROR_SUCCESS) {
  8464. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to open profile mapping key with error %d"), lResult));
  8465. dwErr = lResult;
  8466. goto Exit;
  8467. }
  8468. //
  8469. // Query for the flags
  8470. //
  8471. dwSize = sizeof(DWORD);
  8472. lResult = RegQueryValueEx (hKey,
  8473. PROFILE_FLAGS,
  8474. NULL,
  8475. &dwType,
  8476. (LPBYTE) &lpProfile->dwFlags,
  8477. &dwSize);
  8478. if (lResult != ERROR_SUCCESS) {
  8479. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query flags with error %d"), lResult));
  8480. dwErr = lResult;
  8481. goto Exit;
  8482. }
  8483. //
  8484. // Query for the internal flags
  8485. //
  8486. dwSize = sizeof(DWORD);
  8487. lResult = RegQueryValueEx (hKey,
  8488. PROFILE_STATE,
  8489. NULL,
  8490. &dwType,
  8491. (LPBYTE) &lpProfile->dwInternalFlags,
  8492. &dwSize);
  8493. if (lResult != ERROR_SUCCESS) {
  8494. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query internal flags with error %d"), lResult));
  8495. dwErr = lResult;
  8496. goto Exit;
  8497. }
  8498. //
  8499. // Query for the user preference value
  8500. //
  8501. lpProfile->dwUserPreference = USERINFO_UNDEFINED;
  8502. dwSize = sizeof(DWORD);
  8503. RegQueryValueEx (hKey,
  8504. USER_PREFERENCE,
  8505. NULL,
  8506. &dwType,
  8507. (LPBYTE) &lpProfile->dwUserPreference,
  8508. &dwSize);
  8509. //
  8510. // Query for the central profile path
  8511. //
  8512. dwSize = MAX_PATH * sizeof(TCHAR);
  8513. lResult = RegQueryValueEx (hKey,
  8514. PROFILE_CENTRAL_PROFILE,
  8515. NULL,
  8516. &dwType,
  8517. (LPBYTE) lpProfile->lpRoamingProfile,
  8518. &dwSize);
  8519. if (lResult != ERROR_SUCCESS) {
  8520. DebugMsg((DM_VERBOSE, TEXT("LoadProfileInfo: Failed to query central profile with error %d"), lResult));
  8521. lpProfile->lpRoamingProfile[0] = TEXT('\0');
  8522. }
  8523. //
  8524. // Query for the local profile path. The local profile path
  8525. // needs to be expanded so read it into the temporary buffer.
  8526. //
  8527. dwSize = sizeof(szBuffer);
  8528. lResult = RegQueryValueEx (hKey,
  8529. PROFILE_IMAGE_VALUE_NAME,
  8530. NULL,
  8531. &dwType,
  8532. (LPBYTE) szBuffer,
  8533. &dwSize);
  8534. if (lResult != ERROR_SUCCESS) {
  8535. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query local profile with error %d"), lResult));
  8536. dwErr = lResult;
  8537. goto Exit;
  8538. }
  8539. //
  8540. // Expand the local profile
  8541. //
  8542. ExpandEnvironmentStrings(szBuffer, lpProfile->lpLocalProfile, MAX_PATH);
  8543. //
  8544. // Query for the profile load time
  8545. //
  8546. lpProfile->ftProfileLoad.dwLowDateTime = 0;
  8547. lpProfile->ftProfileLoad.dwHighDateTime = 0;
  8548. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  8549. dwSize = sizeof(lpProfile->ftProfileLoad.dwLowDateTime);
  8550. lResult = RegQueryValueEx (hKey,
  8551. PROFILE_LOAD_TIME_LOW,
  8552. NULL,
  8553. &dwType,
  8554. (LPBYTE) &lpProfile->ftProfileLoad.dwLowDateTime,
  8555. &dwSize);
  8556. if (lResult != ERROR_SUCCESS) {
  8557. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query low profile load time with error %d"), lResult));
  8558. dwErr = lResult;
  8559. goto Exit;
  8560. }
  8561. dwSize = sizeof(lpProfile->ftProfileLoad.dwHighDateTime);
  8562. lResult = RegQueryValueEx (hKey,
  8563. PROFILE_LOAD_TIME_HIGH,
  8564. NULL,
  8565. &dwType,
  8566. (LPBYTE) &lpProfile->ftProfileLoad.dwHighDateTime,
  8567. &dwSize);
  8568. if (lResult != ERROR_SUCCESS) {
  8569. DebugMsg((DM_WARNING, TEXT("LoadProfileInfo: Failed to query high profile load time with error %d"), lResult));
  8570. dwErr = lResult;
  8571. goto Exit;
  8572. }
  8573. }
  8574. //
  8575. // Sucess!
  8576. //
  8577. bSuccess = TRUE;
  8578. Exit:
  8579. if (hKey) {
  8580. RegCloseKey (hKey);
  8581. }
  8582. if (SidString) {
  8583. DeleteSidString(SidString);
  8584. }
  8585. //
  8586. // If the profile information was successfully loaded, return
  8587. // lpProfile now. Otherwise, free any memory and return NULL.
  8588. //
  8589. if (bSuccess) {
  8590. SetLastError(dwErr);
  8591. return lpProfile;
  8592. }
  8593. if (lpProfile) {
  8594. if (lpProfile->lpRoamingProfile) {
  8595. LocalFree (lpProfile->lpRoamingProfile);
  8596. }
  8597. if (lpProfile->lpLocalProfile) {
  8598. LocalFree (lpProfile->lpLocalProfile);
  8599. }
  8600. LocalFree (lpProfile);
  8601. }
  8602. SetLastError(dwErr);
  8603. return NULL;
  8604. }
  8605. //*************************************************************
  8606. //
  8607. // CheckForSlowLink()
  8608. //
  8609. // Purpose: Checks if the network connection is slow.
  8610. //
  8611. // Parameters: lpProfile - Profile Information
  8612. // dwTime - Time delta
  8613. // lpPath - UNC path to test
  8614. // bDlgLogin - Type of Dialog
  8615. //
  8616. // Return: TRUE if profile should be downloaded
  8617. // FALSE if not (use local)
  8618. //
  8619. // Comments:
  8620. //
  8621. // History: Date Author Comment
  8622. // 2/21/96 ericflo Created
  8623. //
  8624. //*************************************************************
  8625. BOOL CheckForSlowLink(LPPROFILE lpProfile, DWORD dwTime, LPTSTR lpPath, BOOL bDlgLogin)
  8626. {
  8627. DWORD dwSlowTimeOut, dwSlowDlgTimeOut, dwSlowLinkDetectEnabled, dwSlowLinkUIEnabled;
  8628. ULONG ulTransferRate;
  8629. DWORD dwType, dwSize;
  8630. BOOL bRetVal = TRUE;
  8631. HKEY hKey;
  8632. LONG lResult;
  8633. BOOL bSlow = FALSE;
  8634. BOOL bLegacyCheck = TRUE;
  8635. LPTSTR lpPathTemp, lpTempSrc, lpTempDest;
  8636. LPSTR lpPathTempA;
  8637. struct hostent *hostp;
  8638. ULONG inaddr, ulSpeed;
  8639. DWORD dwResult;
  8640. PWSOCK32_API pWSock32;
  8641. LPTSTR szSidUser;
  8642. handle_t hIfProfileDialog;
  8643. LPTSTR lpRPCEndPoint = NULL;
  8644. DWORD dwErr = ERROR_SUCCESS;
  8645. RPC_ASYNC_STATE AsyncHnd;
  8646. RPC_STATUS status;
  8647. //
  8648. // If the User Preferences states to always use the local
  8649. // profile then we can exit now with true. The profile
  8650. // won't actually be downloaded. In RestoreUserProfile,
  8651. // this will be filtered out, and only the local will be used.
  8652. //
  8653. if (lpProfile->dwUserPreference == USERINFO_LOCAL) {
  8654. return TRUE;
  8655. }
  8656. //
  8657. // Get the slow link detection flag, slow link timeout,
  8658. // dialog box timeout values, and default profile to use.
  8659. //
  8660. dwSlowTimeOut = SLOW_LINK_TIMEOUT;
  8661. dwSlowDlgTimeOut = PROFILE_DLG_TIMEOUT;
  8662. dwSlowLinkDetectEnabled = 1;
  8663. dwSlowLinkUIEnabled = 0;
  8664. ulTransferRate = SLOW_LINK_TRANSFER_RATE;
  8665. bRetVal = FALSE;
  8666. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  8667. WINLOGON_KEY,
  8668. 0,
  8669. KEY_READ,
  8670. &hKey);
  8671. if (lResult == ERROR_SUCCESS) {
  8672. dwSize = sizeof(DWORD);
  8673. RegQueryValueEx (hKey,
  8674. TEXT("SlowLinkDetectEnabled"),
  8675. NULL,
  8676. &dwType,
  8677. (LPBYTE) &dwSlowLinkDetectEnabled,
  8678. &dwSize);
  8679. dwSize = sizeof(DWORD);
  8680. RegQueryValueEx (hKey,
  8681. TEXT("SlowLinkTimeOut"),
  8682. NULL,
  8683. &dwType,
  8684. (LPBYTE) &dwSlowTimeOut,
  8685. &dwSize);
  8686. dwSize = sizeof(DWORD);
  8687. RegQueryValueEx (hKey,
  8688. TEXT("ProfileDlgTimeOut"),
  8689. NULL,
  8690. &dwType,
  8691. (LPBYTE) &dwSlowDlgTimeOut,
  8692. &dwSize);
  8693. dwSize = sizeof(DWORD);
  8694. RegQueryValueEx (hKey,
  8695. TEXT("SlowLinkUIEnabled"),
  8696. NULL,
  8697. &dwType,
  8698. (LPBYTE) &dwSlowLinkUIEnabled,
  8699. &dwSize);
  8700. dwSize = sizeof(BOOL);
  8701. RegQueryValueEx (hKey,
  8702. TEXT("SlowLinkProfileDefault"),
  8703. NULL,
  8704. &dwType,
  8705. (LPBYTE) &bRetVal,
  8706. &dwSize);
  8707. dwSize = sizeof(ULONG);
  8708. RegQueryValueEx (hKey,
  8709. TEXT("UserProfileMinTransferRate"),
  8710. NULL,
  8711. &dwType,
  8712. (LPBYTE) &ulTransferRate,
  8713. &dwSize);
  8714. RegCloseKey (hKey);
  8715. }
  8716. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  8717. SYSTEM_POLICIES_KEY,
  8718. 0,
  8719. KEY_READ,
  8720. &hKey);
  8721. if (lResult == ERROR_SUCCESS) {
  8722. dwSize = sizeof(DWORD);
  8723. RegQueryValueEx (hKey,
  8724. TEXT("SlowLinkDetectEnabled"),
  8725. NULL,
  8726. &dwType,
  8727. (LPBYTE) &dwSlowLinkDetectEnabled,
  8728. &dwSize);
  8729. dwSize = sizeof(DWORD);
  8730. RegQueryValueEx (hKey,
  8731. TEXT("SlowLinkTimeOut"),
  8732. NULL,
  8733. &dwType,
  8734. (LPBYTE) &dwSlowTimeOut,
  8735. &dwSize);
  8736. dwSize = sizeof(DWORD);
  8737. RegQueryValueEx (hKey,
  8738. TEXT("ProfileDlgTimeOut"),
  8739. NULL,
  8740. &dwType,
  8741. (LPBYTE) &dwSlowDlgTimeOut,
  8742. &dwSize);
  8743. dwSize = sizeof(DWORD);
  8744. RegQueryValueEx (hKey,
  8745. TEXT("SlowLinkUIEnabled"),
  8746. NULL,
  8747. &dwType,
  8748. (LPBYTE) &dwSlowLinkUIEnabled,
  8749. &dwSize);
  8750. dwSize = sizeof(BOOL);
  8751. RegQueryValueEx (hKey,
  8752. TEXT("SlowLinkProfileDefault"),
  8753. NULL,
  8754. &dwType,
  8755. (LPBYTE) &bRetVal,
  8756. &dwSize);
  8757. dwSize = sizeof(ULONG);
  8758. RegQueryValueEx (hKey,
  8759. TEXT("UserProfileMinTransferRate"),
  8760. NULL,
  8761. &dwType,
  8762. (LPBYTE) &ulTransferRate,
  8763. &dwSize);
  8764. RegCloseKey (hKey);
  8765. }
  8766. //
  8767. // If slow link detection is disabled, then always download
  8768. // the profile.
  8769. //
  8770. if (!dwSlowLinkDetectEnabled || !ulTransferRate) {
  8771. return TRUE;
  8772. }
  8773. //
  8774. // If slow link timeout is set to 0 then always consider the link as slow link
  8775. //
  8776. if (!dwSlowTimeOut) {
  8777. bSlow = TRUE;
  8778. bLegacyCheck = FALSE;
  8779. }
  8780. //
  8781. // If lpPath is UNC path and we yet not decided that link is slow, then try
  8782. // pinging the server
  8783. //
  8784. if (!bSlow && (*lpPath == TEXT('\\')) && (*(lpPath+1) == TEXT('\\'))) {
  8785. lpPathTemp = (LPTSTR)LocalAlloc (LPTR, (lstrlen(lpPath)+1) * sizeof(TCHAR));
  8786. if (lpPathTemp) {
  8787. lpTempSrc = lpPath+2;
  8788. lpTempDest = lpPathTemp;
  8789. while ((*lpTempSrc != TEXT('\\')) && *lpTempSrc) {
  8790. *lpTempDest = *lpTempSrc;
  8791. lpTempDest++;
  8792. lpTempSrc++;
  8793. }
  8794. *lpTempDest = TEXT('\0');
  8795. lpPathTempA = ProduceAFromW(lpPathTemp);
  8796. if (lpPathTempA) {
  8797. pWSock32 = LoadWSock32();
  8798. if ( pWSock32 ) {
  8799. hostp = pWSock32->pfngethostbyname(lpPathTempA);
  8800. if (hostp) {
  8801. inaddr = *(long *)hostp->h_addr;
  8802. dwResult = PingComputer (inaddr, &ulSpeed);
  8803. if (dwResult == ERROR_SUCCESS) {
  8804. if (ulSpeed) {
  8805. //
  8806. // If the delta time is greater that the timeout time, then this
  8807. // is a slow link.
  8808. //
  8809. if (ulSpeed < ulTransferRate) {
  8810. bSlow = TRUE;
  8811. }
  8812. }
  8813. bLegacyCheck = FALSE;
  8814. }
  8815. }
  8816. }
  8817. FreeProducedString(lpPathTempA);
  8818. }
  8819. LocalFree (lpPathTemp);
  8820. }
  8821. }
  8822. if (bLegacyCheck) {
  8823. //
  8824. // If the delta time is less that the timeout time, then it
  8825. // is ok to download their profile (fast enough net connection).
  8826. //
  8827. if (dwTime < dwSlowTimeOut) {
  8828. return TRUE;
  8829. }
  8830. } else {
  8831. if (!bSlow) {
  8832. return TRUE;
  8833. }
  8834. }
  8835. //
  8836. // Display the slow link dialog
  8837. //
  8838. // If someone sets the dialog box timeout to 0, then we
  8839. // don't want to prompt the user. Just do the default
  8840. //
  8841. if ((dwSlowLinkUIEnabled) && (dwSlowDlgTimeOut > 0) && (!(lpProfile->dwFlags & PI_NOUI))) {
  8842. szSidUser = GetSidString(lpProfile->hTokenUser);
  8843. if (szSidUser) {
  8844. lpRPCEndPoint = cUserProfileManager.GetRPCEndPoint(szSidUser);
  8845. if (lpRPCEndPoint && GetInterface(&hIfProfileDialog, lpRPCEndPoint)) {
  8846. DebugMsg((DM_VERBOSE, TEXT("CheckForSlowLink: RPC End point %s"), lpRPCEndPoint));
  8847. status = RpcAsyncInitializeHandle(&AsyncHnd, sizeof(RPC_ASYNC_STATE));
  8848. if (status != RPC_S_OK) {
  8849. dwErr = status;
  8850. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: RpcAsyncInitializeHandle failed. err = %d"), dwErr));
  8851. }
  8852. else {
  8853. AsyncHnd.UserInfo = NULL; // App specific info, not req
  8854. AsyncHnd.NotificationType = RpcNotificationTypeEvent; // Init the notification event
  8855. AsyncHnd.u.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  8856. if (AsyncHnd.u.hEvent) {
  8857. RpcTryExcept {
  8858. cliSlowLinkDialog(&AsyncHnd, hIfProfileDialog, dwSlowDlgTimeOut, bRetVal, &bRetVal, bDlgLogin);
  8859. }
  8860. RpcExcept(1) {
  8861. dwErr = RpcExceptionCode();
  8862. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: Calling SlowLinkDialog took exception. err = %d"), dwErr));
  8863. }
  8864. RpcEndExcept
  8865. DebugMsg((DM_VERBOSE, TEXT("CheckForSlowLink: waiting on rpc async event")));
  8866. if (WaitForSingleObject(AsyncHnd.u.hEvent, (dwSlowDlgTimeOut + 10)*1000) == WAIT_OBJECT_0) {
  8867. RpcAsyncCompleteCall(&AsyncHnd, (PVOID)&dwErr);
  8868. }
  8869. else {
  8870. dwErr = GetLastError();
  8871. RpcAsyncCancelCall(&AsyncHnd, TRUE);
  8872. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: Timeout occurs. Client not responding"), dwErr));
  8873. }
  8874. // Release the resource
  8875. CloseHandle(AsyncHnd.u.hEvent);
  8876. }
  8877. else {
  8878. dwErr = GetLastError();
  8879. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: create event failed. error %d"), dwErr));
  8880. }
  8881. }
  8882. if (dwErr != ERROR_SUCCESS) {
  8883. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: fail to show message error %d"), GetLastError()));
  8884. }
  8885. ReleaseInterface(&hIfProfileDialog);
  8886. }
  8887. DeleteSidString(szSidUser);
  8888. }
  8889. else {
  8890. DebugMsg((DM_WARNING, TEXT("CheckForSlowLink: Unable to get SID string from token.")));
  8891. }
  8892. if (!lpRPCEndPoint) {
  8893. SLOWLINKDLGINFO info;
  8894. info.dwTimeout = dwSlowDlgTimeOut;
  8895. info.bSyncDefault = bRetVal;
  8896. DebugMsg((DM_VERBOSE, TEXT("CheckForSlowLink: Calling DialogBoxParam")));
  8897. if (bDlgLogin) {
  8898. bRetVal = (BOOL)DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_LOGIN_SLOW_LINK),
  8899. NULL, LoginSlowLinkDlgProc, (LPARAM)&info);
  8900. }
  8901. else {
  8902. bRetVal = (BOOL)DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_LOGOFF_SLOW_LINK),
  8903. NULL, LogoffSlowLinkDlgProc, (LPARAM)&info);
  8904. }
  8905. }
  8906. }
  8907. if (!bRetVal) {
  8908. lpProfile->dwInternalFlags |= PROFILE_SLOW_LINK;
  8909. DebugMsg((DM_VERBOSE, TEXT("CheckForSlowLink: The profile is across a slow link")));
  8910. }
  8911. return bRetVal;
  8912. }
  8913. //*************************************************************
  8914. //
  8915. // LoginSlowLinkDlgProc()
  8916. //
  8917. // Purpose: Dialog box procedure for the slow link dialog
  8918. // at login time
  8919. //
  8920. // Parameters: hDlg - handle to the dialog box
  8921. // uMsg - window message
  8922. // wParam - wParam
  8923. // lParam - lParam
  8924. //
  8925. // Return: TRUE if message was processed
  8926. // FALSE if not
  8927. //
  8928. // Comments:
  8929. //
  8930. // History: Date Author Comment
  8931. // 2/13/96 ericflo Created
  8932. //
  8933. //*************************************************************
  8934. INT_PTR APIENTRY LoginSlowLinkDlgProc (HWND hDlg, UINT uMsg,
  8935. WPARAM wParam, LPARAM lParam)
  8936. {
  8937. TCHAR szBuffer[10];
  8938. static DWORD dwSlowLinkTime;
  8939. BOOL bDownloadDefault;
  8940. switch (uMsg) {
  8941. case WM_INITDIALOG:
  8942. SetForegroundWindow(hDlg);
  8943. CenterWindow (hDlg);
  8944. //
  8945. // Set the default button and focus
  8946. //
  8947. if (((LPSLOWLINKDLGINFO)lParam)->bSyncDefault) {
  8948. SetFocus (GetDlgItem(hDlg, IDC_DOWNLOAD));
  8949. } else {
  8950. HWND hwnd;
  8951. LONG style;
  8952. //
  8953. // Set the default button to Local
  8954. //
  8955. hwnd = GetDlgItem (hDlg, IDC_DOWNLOAD);
  8956. style = GetWindowLong (hwnd, GWL_STYLE);
  8957. style &= ~(BS_DEFPUSHBUTTON | BS_NOTIFY);
  8958. style |= BS_PUSHBUTTON;
  8959. SetWindowLong (hwnd, GWL_STYLE, style);
  8960. hwnd = GetDlgItem (hDlg, IDC_LOCAL);
  8961. style = GetWindowLong (hwnd, GWL_STYLE);
  8962. style &= ~(BS_PUSHBUTTON | BS_DEFPUSHBUTTON);
  8963. style |= (BS_DEFPUSHBUTTON | BS_NOTIFY);
  8964. SetWindowLong (hwnd, GWL_STYLE, style);
  8965. SetFocus (GetDlgItem(hDlg, IDC_LOCAL));
  8966. }
  8967. SetWindowLongPtr (hDlg, DWLP_USER, ((LPSLOWLINKDLGINFO)lParam)->bSyncDefault);
  8968. dwSlowLinkTime = ((LPSLOWLINKDLGINFO)lParam)->dwTimeout;
  8969. wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
  8970. SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
  8971. SetTimer (hDlg, 1, 1000, NULL);
  8972. return FALSE;
  8973. case WM_TIMER:
  8974. if (dwSlowLinkTime >= 1) {
  8975. dwSlowLinkTime--;
  8976. wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
  8977. SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
  8978. } else {
  8979. //
  8980. // Time's up. Do the default action.
  8981. //
  8982. bDownloadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  8983. if (bDownloadDefault) {
  8984. PostMessage (hDlg, WM_COMMAND, IDC_DOWNLOAD, 0);
  8985. } else {
  8986. PostMessage (hDlg, WM_COMMAND, IDC_LOCAL, 0);
  8987. }
  8988. }
  8989. break;
  8990. case WM_COMMAND:
  8991. switch (LOWORD(wParam)) {
  8992. case IDC_DOWNLOAD:
  8993. if (HIWORD(wParam) == BN_KILLFOCUS) {
  8994. bDownloadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  8995. if (bDownloadDefault) {
  8996. KillTimer (hDlg, 1);
  8997. ShowWindow(GetDlgItem(hDlg, IDC_TIMEOUT), SW_HIDE);
  8998. ShowWindow(GetDlgItem(hDlg, IDC_TIMETITLE), SW_HIDE);
  8999. }
  9000. } else if (HIWORD(wParam) == BN_CLICKED) {
  9001. DebugMsg((DM_VERBOSE, TEXT("LoginSlowLinkDlgProc:: Killing DialogBox because download button was clicked")));
  9002. KillTimer (hDlg, 1);
  9003. EndDialog(hDlg, TRUE);
  9004. }
  9005. break;
  9006. case IDC_LOCAL:
  9007. if (HIWORD(wParam) == BN_KILLFOCUS) {
  9008. bDownloadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9009. if (!bDownloadDefault) {
  9010. KillTimer (hDlg, 1);
  9011. ShowWindow(GetDlgItem(hDlg, IDC_TIMEOUT), SW_HIDE);
  9012. ShowWindow(GetDlgItem(hDlg, IDC_TIMETITLE), SW_HIDE);
  9013. }
  9014. break;
  9015. } else if (HIWORD(wParam) == BN_CLICKED) {
  9016. DebugMsg((DM_VERBOSE, TEXT("LoginSlowLinkDlgProc:: Killing DialogBox because local button was clicked")));
  9017. KillTimer (hDlg, 1);
  9018. EndDialog(hDlg, FALSE);
  9019. }
  9020. break;
  9021. case IDCANCEL:
  9022. bDownloadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9023. //
  9024. // Nothing to do. Save the state and return.
  9025. //
  9026. DebugMsg((DM_VERBOSE, TEXT("LoginSlowLinkDlgProc:: Killing DialogBox because local/cancel button was clicked")));
  9027. KillTimer (hDlg, 1);
  9028. //
  9029. // Return Whatever is the default in this case..
  9030. //
  9031. EndDialog(hDlg, bDownloadDefault);
  9032. break;
  9033. default:
  9034. break;
  9035. }
  9036. break;
  9037. }
  9038. return FALSE;
  9039. }
  9040. //*************************************************************
  9041. //
  9042. // LogoffSlowLinkDlgProc()
  9043. //
  9044. // Purpose: Dialog box procedure for the slow link dialog
  9045. // at login time
  9046. //
  9047. // Parameters: hDlg - handle to the dialog box
  9048. // uMsg - window message
  9049. // wParam - wParam
  9050. // lParam - lParam
  9051. //
  9052. // Return: TRUE if message was processed
  9053. // FALSE if not
  9054. //
  9055. // Comments:
  9056. //
  9057. // History: Date Author Comment
  9058. // 2/13/96 ericflo Created
  9059. //
  9060. //*************************************************************
  9061. INT_PTR APIENTRY LogoffSlowLinkDlgProc (HWND hDlg, UINT uMsg,
  9062. WPARAM wParam, LPARAM lParam)
  9063. {
  9064. TCHAR szBuffer[10];
  9065. static DWORD dwSlowLinkTime;
  9066. BOOL bUploadDefault;
  9067. switch (uMsg) {
  9068. case WM_INITDIALOG:
  9069. SetForegroundWindow(hDlg);
  9070. CenterWindow (hDlg);
  9071. //
  9072. // Set the default button and focus
  9073. //
  9074. if (((LPSLOWLINKDLGINFO)lParam)->bSyncDefault) {
  9075. SetFocus (GetDlgItem(hDlg, IDC_UPLOAD));
  9076. } else {
  9077. HWND hwnd;
  9078. LONG style;
  9079. //
  9080. // Set the default button to Local
  9081. //
  9082. hwnd = GetDlgItem (hDlg, IDC_UPLOAD);
  9083. style = GetWindowLong (hwnd, GWL_STYLE);
  9084. style &= ~(BS_DEFPUSHBUTTON | BS_NOTIFY);
  9085. style |= BS_PUSHBUTTON;
  9086. SetWindowLong (hwnd, GWL_STYLE, style);
  9087. hwnd = GetDlgItem (hDlg, IDC_NOUPLOAD);
  9088. style = GetWindowLong (hwnd, GWL_STYLE);
  9089. style &= ~(BS_PUSHBUTTON | BS_DEFPUSHBUTTON);
  9090. style |= (BS_DEFPUSHBUTTON | BS_NOTIFY);
  9091. SetWindowLong (hwnd, GWL_STYLE, style);
  9092. SetFocus (GetDlgItem(hDlg, IDC_NOUPLOAD));
  9093. }
  9094. SetWindowLongPtr (hDlg, DWLP_USER, ((LPSLOWLINKDLGINFO)lParam)->bSyncDefault);
  9095. dwSlowLinkTime = ((LPSLOWLINKDLGINFO)lParam)->dwTimeout;
  9096. wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
  9097. SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
  9098. SetTimer (hDlg, 1, 1000, NULL);
  9099. return FALSE;
  9100. case WM_TIMER:
  9101. if (dwSlowLinkTime >= 1) {
  9102. dwSlowLinkTime--;
  9103. wsprintf (szBuffer, TEXT("%d"), dwSlowLinkTime);
  9104. SetDlgItemText (hDlg, IDC_TIMEOUT, szBuffer);
  9105. } else {
  9106. //
  9107. // Time's up. Do the default action.
  9108. //
  9109. bUploadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9110. if (bUploadDefault) {
  9111. PostMessage (hDlg, WM_COMMAND, IDC_UPLOAD, 0);
  9112. } else {
  9113. PostMessage (hDlg, WM_COMMAND, IDC_NOUPLOAD, 0);
  9114. }
  9115. }
  9116. break;
  9117. case WM_COMMAND:
  9118. switch (LOWORD(wParam)) {
  9119. case IDC_UPLOAD:
  9120. if (HIWORD(wParam) == BN_KILLFOCUS) {
  9121. bUploadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9122. if (bUploadDefault) {
  9123. KillTimer (hDlg, 1);
  9124. ShowWindow(GetDlgItem(hDlg, IDC_TIMEOUT), SW_HIDE);
  9125. ShowWindow(GetDlgItem(hDlg, IDC_TIMETITLE), SW_HIDE);
  9126. }
  9127. } else if (HIWORD(wParam) == BN_CLICKED) {
  9128. DebugMsg((DM_VERBOSE, TEXT("LogoffSlowLinkDlgProc:: Killing DialogBox because upload button was clicked")));
  9129. KillTimer (hDlg, 1);
  9130. EndDialog(hDlg, TRUE);
  9131. }
  9132. break;
  9133. case IDC_NOUPLOAD:
  9134. if (HIWORD(wParam) == BN_KILLFOCUS) {
  9135. bUploadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9136. if (!bUploadDefault) {
  9137. KillTimer (hDlg, 1);
  9138. ShowWindow(GetDlgItem(hDlg, IDC_TIMEOUT), SW_HIDE);
  9139. ShowWindow(GetDlgItem(hDlg, IDC_TIMETITLE), SW_HIDE);
  9140. }
  9141. break;
  9142. } else if (HIWORD(wParam) == BN_CLICKED) {
  9143. DebugMsg((DM_VERBOSE, TEXT("LogoffSlowLinkDlgProc:: Killing DialogBox because Don't Upload button was clicked")));
  9144. KillTimer (hDlg, 1);
  9145. EndDialog(hDlg, FALSE);
  9146. }
  9147. break;
  9148. case IDCANCEL:
  9149. bUploadDefault = (BOOL) GetWindowLongPtr (hDlg, DWLP_USER);
  9150. //
  9151. // Nothing to do. Save the state and return.
  9152. //
  9153. DebugMsg((DM_VERBOSE, TEXT("LogoffSlowLinkDlgProc:: Killing DialogBox because cancel button was clicked")));
  9154. KillTimer (hDlg, 1);
  9155. //
  9156. // Return Whatever is the default in this case..
  9157. //
  9158. EndDialog(hDlg, bUploadDefault);
  9159. break;
  9160. default:
  9161. break;
  9162. }
  9163. break;
  9164. }
  9165. return FALSE;
  9166. }
  9167. //*************************************************************
  9168. //
  9169. // GetUserPreferenceValue()
  9170. //
  9171. // Purpose: Gets the User Preference flags
  9172. //
  9173. // Parameters: hToken - User's token
  9174. //
  9175. // Return: Value
  9176. //
  9177. // Comments:
  9178. //
  9179. // History: Date Author Comment
  9180. // 2/22/96 ericflo Created
  9181. //
  9182. //*************************************************************
  9183. DWORD GetUserPreferenceValue(HANDLE hToken)
  9184. {
  9185. TCHAR LocalProfileKey[MAX_PATH];
  9186. DWORD RegErr, dwType, dwSize, dwTmpVal, dwRetVal = USERINFO_UNDEFINED;
  9187. LPTSTR lpEnd;
  9188. LPTSTR SidString;
  9189. HKEY hkeyProfile, hkeyPolicy;
  9190. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  9191. SYSTEM_POLICIES_KEY,
  9192. 0, KEY_READ,
  9193. &hkeyPolicy) == ERROR_SUCCESS) {
  9194. dwSize = sizeof(dwTmpVal);
  9195. RegQueryValueEx(hkeyPolicy,
  9196. PROFILE_LOCALONLY,
  9197. NULL, &dwType,
  9198. (LPBYTE) &dwTmpVal,
  9199. &dwSize);
  9200. RegCloseKey (hkeyPolicy);
  9201. if (dwTmpVal == 1) {
  9202. dwRetVal = USERINFO_LOCAL;
  9203. return dwRetVal;
  9204. }
  9205. }
  9206. SidString = GetProfileSidString(hToken);
  9207. if (SidString != NULL) {
  9208. //
  9209. // Query for the UserPreference value
  9210. //
  9211. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  9212. lpEnd = CheckSlash (LocalProfileKey);
  9213. lstrcpy(lpEnd, SidString);
  9214. RegErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  9215. LocalProfileKey,
  9216. 0,
  9217. KEY_READ,
  9218. &hkeyProfile);
  9219. if (RegErr == ERROR_SUCCESS) {
  9220. dwSize = sizeof(dwRetVal);
  9221. RegQueryValueEx(hkeyProfile,
  9222. USER_PREFERENCE,
  9223. NULL,
  9224. &dwType,
  9225. (LPBYTE) &dwRetVal,
  9226. &dwSize);
  9227. RegCloseKey (hkeyProfile);
  9228. }
  9229. lstrcat(LocalProfileKey, c_szBAK);
  9230. RegErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  9231. LocalProfileKey,
  9232. 0,
  9233. KEY_READ,
  9234. &hkeyProfile);
  9235. if (RegErr == ERROR_SUCCESS) {
  9236. dwSize = sizeof(dwRetVal);
  9237. RegQueryValueEx(hkeyProfile,
  9238. USER_PREFERENCE,
  9239. NULL,
  9240. &dwType,
  9241. (LPBYTE) &dwRetVal,
  9242. &dwSize);
  9243. RegCloseKey (hkeyProfile);
  9244. }
  9245. DeleteSidString(SidString);
  9246. }
  9247. return dwRetVal;
  9248. }
  9249. //*************************************************************
  9250. //
  9251. // IsTempProfileAllowed()
  9252. //
  9253. // Purpose: Gets the temp profile policy
  9254. //
  9255. // Parameters:
  9256. //
  9257. // Return: true if temp profile can be created, false otherwise
  9258. //
  9259. // Comments:
  9260. //
  9261. // History: Date Author Comment
  9262. // 2/8/99 ushaji Created
  9263. //
  9264. //*************************************************************
  9265. BOOL IsTempProfileAllowed()
  9266. {
  9267. HKEY hKey;
  9268. LONG lResult;
  9269. DWORD dwSize, dwType;
  9270. DWORD dwRetVal = PROFILEERRORACTION_TEMP;
  9271. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  9272. SYSTEM_POLICIES_KEY,
  9273. 0,
  9274. KEY_READ,
  9275. &hKey);
  9276. if (lResult == ERROR_SUCCESS) {
  9277. dwSize = sizeof(DWORD);
  9278. RegQueryValueEx (hKey,
  9279. TEXT("ProfileErrorAction"),
  9280. NULL,
  9281. &dwType,
  9282. (LPBYTE) &dwRetVal,
  9283. &dwSize);
  9284. RegCloseKey (hKey);
  9285. }
  9286. DebugMsg((DM_VERBOSE, TEXT("IsTempProfileAllowed: Returning %d"), (dwRetVal == PROFILEERRORACTION_TEMP)));
  9287. return (dwRetVal == PROFILEERRORACTION_TEMP);
  9288. }
  9289. //*************************************************************
  9290. //
  9291. // MoveUserProfiles()
  9292. //
  9293. // Purpose: Moves all user profiles from source location
  9294. // to the new profile location
  9295. //
  9296. // Parameters: lpSrcDir - Source directory
  9297. // lpDestDir - Destination directory
  9298. //
  9299. // Notes: The source directory should be given in the same
  9300. // format as the pathnames appear in the ProfileList
  9301. // registry key. eg: normally the profile paths
  9302. // are in this form: %SystemRoot%\Profiles. The
  9303. // path passed to this function should be in the unexpanded
  9304. // format.
  9305. //
  9306. //
  9307. // Return: TRUE if successful
  9308. // FALSE if an error occurs
  9309. //
  9310. //*************************************************************
  9311. BOOL MoveUserProfiles (LPCTSTR lpSrcDir, LPCTSTR lpDestDir)
  9312. {
  9313. BOOL bResult = TRUE;
  9314. LONG lResult;
  9315. DWORD dwIndex, dwType, dwSize, dwDisp;
  9316. DWORD dwLength, dwLengthNeeded, dwStrLen;
  9317. PSECURITY_DESCRIPTOR pSD;
  9318. LPTSTR lpEnd, lpNewPathEnd, lpNameEnd;
  9319. TCHAR szName[75];
  9320. TCHAR szTemp[MAX_PATH + 1];
  9321. TCHAR szOldProfilePath[MAX_PATH + 1];
  9322. TCHAR szNewProfilePath[MAX_PATH + 1];
  9323. TCHAR szExpOldProfilePath[MAX_PATH + 1] = {0};
  9324. TCHAR szExpNewProfilePath[MAX_PATH + 1];
  9325. WIN32_FILE_ATTRIBUTE_DATA fad;
  9326. INT iSrcDirLen;
  9327. HKEY hKeyProfileList, hKeyProfile, hKeyFolders;
  9328. FILETIME ftWrite;
  9329. //
  9330. // Make sure we don't try to move on top of ourselves
  9331. //
  9332. if (lstrcmpi (lpSrcDir, lpDestDir) == 0) {
  9333. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Old profiles directory and new profiles directory are the same.")));
  9334. bResult = FALSE;
  9335. goto Exit;
  9336. }
  9337. //
  9338. // Open the profile list
  9339. //
  9340. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  9341. 0, KEY_READ, &hKeyProfileList);
  9342. if (lResult != ERROR_SUCCESS) {
  9343. if (lResult != ERROR_PATH_NOT_FOUND) {
  9344. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to open profile list registry key with %d"), lResult));
  9345. bResult = FALSE;
  9346. }
  9347. goto DoDefaults;
  9348. }
  9349. //
  9350. // Enumerate the profiles
  9351. //
  9352. lstrcpy (szTemp, PROFILE_LIST_PATH);
  9353. lpEnd = CheckSlash (szTemp);
  9354. iSrcDirLen = lstrlen (lpSrcDir);
  9355. dwIndex = 0;
  9356. dwSize = ARRAYSIZE(szName);
  9357. while (RegEnumKeyEx (hKeyProfileList, dwIndex, szName, &dwSize, NULL, NULL,
  9358. NULL, &ftWrite) == ERROR_SUCCESS) {
  9359. //
  9360. // Check if this profile is in use
  9361. //
  9362. if (RegOpenKeyEx(HKEY_USERS, szName, 0, KEY_READ,
  9363. &hKeyProfile) == ERROR_SUCCESS) {
  9364. DebugMsg((DM_VERBOSE, TEXT("MoveUserProfiles: Skipping <%s> because it is in use."), szName));
  9365. RegCloseKey (hKeyProfile);
  9366. goto LoopAgain;
  9367. }
  9368. //
  9369. // Open the key for a specific profile
  9370. //
  9371. lstrcpy (lpEnd, szName);
  9372. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0,
  9373. KEY_READ | KEY_WRITE, &hKeyProfile) == ERROR_SUCCESS) {
  9374. //
  9375. // Query for the previous profile location
  9376. //
  9377. szOldProfilePath[0] = TEXT('\0');
  9378. dwSize = ARRAYSIZE(szOldProfilePath) * sizeof(TCHAR);
  9379. RegQueryValueEx (hKeyProfile, PROFILE_IMAGE_VALUE_NAME, NULL,
  9380. &dwType, (LPBYTE) szOldProfilePath, &dwSize);
  9381. //
  9382. // If the profile is located in the source directory,
  9383. // move it to the new profiles directory.
  9384. //
  9385. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  9386. szOldProfilePath, iSrcDirLen,
  9387. lpSrcDir, iSrcDirLen) == CSTR_EQUAL) {
  9388. //
  9389. // Copy the user's name into a buffer we can change
  9390. //
  9391. lstrcpy (szName, (szOldProfilePath + iSrcDirLen + 1));
  9392. //
  9393. // If the user's name has a .000, .001, etc at the end,
  9394. // remove that.
  9395. //
  9396. dwStrLen = lstrlen(szName);
  9397. if (dwStrLen > 3) {
  9398. lpNameEnd = szName + dwStrLen - 4;
  9399. if (*lpNameEnd == TEXT('.')) {
  9400. *lpNameEnd = TEXT('\0');
  9401. }
  9402. }
  9403. //
  9404. // Call ComputeLocalProfileName to get the new
  9405. // profile directory (this also creates the directory)
  9406. //
  9407. lstrcpy (szNewProfilePath, lpDestDir);
  9408. if (!ComputeLocalProfileName (NULL, szName,
  9409. szNewProfilePath, ARRAYSIZE(szNewProfilePath),
  9410. szExpNewProfilePath, ARRAYSIZE(szExpNewProfilePath),
  9411. NULL, FALSE)) {
  9412. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to generate unique directory name for <%s>"),
  9413. szName));
  9414. goto LoopAgain;
  9415. }
  9416. DebugMsg((DM_VERBOSE, TEXT("MoveUserProfiles: Moving <%s> to <%s>"),
  9417. szOldProfilePath, szNewProfilePath));
  9418. ExpandEnvironmentStrings (szOldProfilePath, szExpOldProfilePath,
  9419. ARRAYSIZE(szExpOldProfilePath));
  9420. //
  9421. // Copy the ACLs from the old location to the new
  9422. //
  9423. dwLength = 1024;
  9424. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc (LPTR, dwLength);
  9425. if (pSD) {
  9426. if (GetFileSecurity (szExpOldProfilePath,
  9427. DACL_SECURITY_INFORMATION,
  9428. pSD, dwLength, &dwLengthNeeded) &&
  9429. (dwLengthNeeded == 0)) {
  9430. SetFileSecurity (szExpNewProfilePath,
  9431. DACL_SECURITY_INFORMATION, pSD);
  9432. } else {
  9433. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to allocate get security descriptor with %d. dwLengthNeeded = %d"),
  9434. GetLastError(), dwLengthNeeded));
  9435. }
  9436. LocalFree (pSD);
  9437. } else {
  9438. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to allocate memory for SD with %d."),
  9439. GetLastError()));
  9440. }
  9441. //
  9442. // Copy the files from the old location to the new
  9443. //
  9444. if (CopyProfileDirectory (szExpOldProfilePath, szExpNewProfilePath,
  9445. CPD_COPYIFDIFFERENT)) {
  9446. DebugMsg((DM_VERBOSE, TEXT("MoveUserProfiles: Profile copied successfully.")));
  9447. //
  9448. // Change the registry to point at the new profile
  9449. //
  9450. lResult = RegSetValueEx (hKeyProfile, PROFILE_IMAGE_VALUE_NAME, 0,
  9451. REG_EXPAND_SZ, (LPBYTE) szNewProfilePath,
  9452. ((lstrlen(szNewProfilePath) + 1) * sizeof(TCHAR)));
  9453. if (lResult == ERROR_SUCCESS) {
  9454. //
  9455. // Delete the old profile
  9456. //
  9457. Delnode (szExpOldProfilePath);
  9458. } else {
  9459. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to set new profile path in registry with %d."), lResult));
  9460. }
  9461. } else {
  9462. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: CopyProfileDirectory failed.")));
  9463. }
  9464. }
  9465. RegCloseKey (hKeyProfile);
  9466. }
  9467. LoopAgain:
  9468. dwIndex++;
  9469. dwSize = ARRAYSIZE(szName);
  9470. }
  9471. RegCloseKey (hKeyProfileList);
  9472. DoDefaults:
  9473. lstrcpy (szOldProfilePath, lpSrcDir);
  9474. ExpandEnvironmentStrings (szOldProfilePath, szExpOldProfilePath,
  9475. ARRAYSIZE(szExpOldProfilePath));
  9476. lpEnd = CheckSlash(szExpOldProfilePath);
  9477. //
  9478. // Now try to move the Default User profile
  9479. //
  9480. lstrcpy (lpEnd, DEFAULT_USER);
  9481. if (GetFileAttributesEx (szExpOldProfilePath, GetFileExInfoStandard, &fad)) {
  9482. dwSize = ARRAYSIZE(szExpNewProfilePath);
  9483. if (!GetDefaultUserProfileDirectoryEx(szExpNewProfilePath, &dwSize, TRUE)) {
  9484. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to query default user profile directory.")));
  9485. goto Exit;
  9486. }
  9487. if (CopyProfileDirectory (szExpOldProfilePath, szExpNewProfilePath,
  9488. CPD_COPYIFDIFFERENT)) {
  9489. Delnode (szExpOldProfilePath);
  9490. }
  9491. }
  9492. //
  9493. // Delnode the Network Default User profile if it exists
  9494. //
  9495. lstrcpy (lpEnd, DEFAULT_USER_NETWORK);
  9496. Delnode (szExpOldProfilePath);
  9497. //
  9498. // Now try to move the All Users profile
  9499. //
  9500. lstrcpy (lpEnd, ALL_USERS);
  9501. if (GetFileAttributesEx (szExpOldProfilePath, GetFileExInfoStandard, &fad)) {
  9502. dwSize = ARRAYSIZE(szExpNewProfilePath);
  9503. if (!GetAllUsersProfileDirectoryEx(szExpNewProfilePath, &dwSize, TRUE)) {
  9504. DebugMsg((DM_WARNING, TEXT("MoveUserProfiles: Failed to query all users profile directory.")));
  9505. goto Exit;
  9506. }
  9507. if (CopyProfileDirectory (szExpOldProfilePath, szExpNewProfilePath,
  9508. CPD_COPYIFDIFFERENT)) {
  9509. Delnode (szExpOldProfilePath);
  9510. }
  9511. }
  9512. //
  9513. // If possible, remove the old profiles directory
  9514. //
  9515. ExpandEnvironmentStrings (lpSrcDir, szExpOldProfilePath,
  9516. ARRAYSIZE(szExpOldProfilePath));
  9517. RemoveDirectory (szExpOldProfilePath);
  9518. Exit:
  9519. return bResult;
  9520. }
  9521. //*************************************************************
  9522. //
  9523. // PrepareProfileForUse()
  9524. //
  9525. // Purpose: Prepares the profile for use on this machine.
  9526. //
  9527. // Parameters: lpProfile - Profile information
  9528. // pEnv - Environment block in per user basis
  9529. //
  9530. // Return: TRUE if successful
  9531. // FALSE if an error occurs
  9532. //
  9533. //*************************************************************
  9534. BOOL PrepareProfileForUse (LPPROFILE lpProfile, LPVOID pEnv)
  9535. {
  9536. TCHAR szTemp[MAX_PATH];
  9537. TCHAR szExpTemp[MAX_PATH];
  9538. HKEY hKey;
  9539. HKEY hKeyShellFolders = NULL;
  9540. DWORD dwSize;
  9541. DWORD dwType;
  9542. DWORD dwDisp;
  9543. DWORD dwStrLen;
  9544. DWORD i;
  9545. DWORD dwErr;
  9546. PSHELL32_API pShell32Api;
  9547. //
  9548. // Load Shell32.dll. Give up if it fails.
  9549. //
  9550. if ( ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  9551. return TRUE;
  9552. }
  9553. //
  9554. // Calculate the length of the user profile environment variable
  9555. //
  9556. dwStrLen = lstrlen (TEXT("%USERPROFILE%"));
  9557. //
  9558. // Open the Shell Folders key
  9559. //
  9560. RegCreateKeyEx(lpProfile->hKeyCurrentUser, SHELL_FOLDERS, 0, 0, 0,
  9561. KEY_WRITE, NULL, &hKeyShellFolders, &dwDisp);
  9562. //
  9563. // Open the User Shell Folders key
  9564. //
  9565. if (RegOpenKeyEx (lpProfile->hKeyCurrentUser,
  9566. USER_SHELL_FOLDERS, 0, KEY_READ,
  9567. &hKey) == ERROR_SUCCESS) {
  9568. //
  9569. // Enumerate the folders we know about
  9570. //
  9571. for (i=0; i < g_dwNumShellFolders; i++) {
  9572. //
  9573. // Query for the unexpanded path name
  9574. //
  9575. szTemp[0] = TEXT('\0');
  9576. dwSize = sizeof(szTemp);
  9577. if (RegQueryValueEx (hKey, c_ShellFolders[i].lpFolderName, NULL,
  9578. &dwType, (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  9579. //
  9580. // Expand the path name
  9581. //
  9582. ExpandUserEnvironmentStrings (pEnv, szTemp, szExpTemp, ARRAYSIZE(szExpTemp));
  9583. //
  9584. // If this is a local directory, create it and set the
  9585. // hidden bit if appropriate
  9586. //
  9587. if (c_ShellFolders[i].bLocal) {
  9588. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  9589. TEXT("%USERPROFILE%"), dwStrLen,
  9590. szTemp, dwStrLen) == CSTR_EQUAL) {
  9591. if (CreateNestedDirectory (szExpTemp, NULL)) {
  9592. if (c_ShellFolders[i].iFolderResourceID != 0) {
  9593. dwErr = pShell32Api->pfnShSetLocalizedName(
  9594. szExpTemp,
  9595. c_ShellFolders[i].lpFolderResourceDLL,
  9596. c_ShellFolders[i].iFolderResourceID );
  9597. if (dwErr != ERROR_SUCCESS) {
  9598. DebugMsg((DM_WARNING, TEXT("PrepareProfileForUse: SHSetLocalizedName failed for directory <%s>. Error = %d"),
  9599. szExpTemp, dwErr));
  9600. }
  9601. }
  9602. if (c_ShellFolders[i].bHidden) {
  9603. SetFileAttributes(szExpTemp, FILE_ATTRIBUTE_HIDDEN);
  9604. } else {
  9605. SetFileAttributes(szExpTemp, FILE_ATTRIBUTE_NORMAL);
  9606. }
  9607. } else {
  9608. DebugMsg((DM_WARNING, TEXT("PrepareProfileForUse: Failed to create directory <%s> with %d."),
  9609. szExpTemp, GetLastError()));
  9610. }
  9611. }
  9612. }
  9613. //
  9614. // Set the expanded path in the Shell Folders key.
  9615. // This helps some apps that look at the Shell Folders
  9616. // key directly instead of using the shell api
  9617. //
  9618. if (hKeyShellFolders) {
  9619. RegSetValueEx (hKeyShellFolders, c_ShellFolders[i].lpFolderName, 0,
  9620. REG_SZ, (LPBYTE) szExpTemp,
  9621. ((lstrlen(szExpTemp) + 1) * sizeof(TCHAR)));
  9622. }
  9623. }
  9624. }
  9625. RegCloseKey (hKey);
  9626. }
  9627. //
  9628. // Close the Shell Folders key
  9629. //
  9630. if (hKeyShellFolders) {
  9631. RegCloseKey (hKeyShellFolders);
  9632. }
  9633. //
  9634. // Now check that the temp directory exists.
  9635. //
  9636. if (RegOpenKeyEx (lpProfile->hKeyCurrentUser,
  9637. TEXT("Environment"), 0, KEY_READ,
  9638. &hKey) == ERROR_SUCCESS) {
  9639. //
  9640. // Check for TEMP
  9641. //
  9642. szTemp[0] = TEXT('\0');
  9643. dwSize = sizeof(szTemp);
  9644. if (RegQueryValueEx (hKey, TEXT("TEMP"), NULL, &dwType,
  9645. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  9646. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  9647. TEXT("%USERPROFILE%"), dwStrLen,
  9648. szTemp, dwStrLen) == CSTR_EQUAL) {
  9649. ExpandUserEnvironmentStrings (pEnv, szTemp, szExpTemp, ARRAYSIZE(szExpTemp));
  9650. if (!CreateNestedDirectory (szExpTemp, NULL)) {
  9651. DebugMsg((DM_WARNING, TEXT("PrepareProfileForUse: Failed to create temp directory <%s> with %d."),
  9652. szExpTemp, GetLastError()));
  9653. }
  9654. }
  9655. }
  9656. //
  9657. // Check for TMP
  9658. //
  9659. szTemp[0] = TEXT('\0');
  9660. dwSize = sizeof(szTemp);
  9661. if (RegQueryValueEx (hKey, TEXT("TMP"), NULL, &dwType,
  9662. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  9663. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  9664. TEXT("%USERPROFILE%"), dwStrLen,
  9665. szTemp, dwStrLen) == CSTR_EQUAL) {
  9666. ExpandUserEnvironmentStrings (pEnv, szTemp, szExpTemp, ARRAYSIZE(szExpTemp));
  9667. if (!CreateNestedDirectory (szExpTemp, NULL)) {
  9668. DebugMsg((DM_WARNING, TEXT("PrepareProfileForUse: Failed to create temp directory with %d."),
  9669. GetLastError()));
  9670. }
  9671. }
  9672. }
  9673. RegCloseKey (hKey);
  9674. }
  9675. return TRUE;
  9676. }
  9677. //*************************************************************
  9678. //
  9679. // DeleteProfile()
  9680. //
  9681. // Purpose: Deletes the profile
  9682. //
  9683. // Parameters:
  9684. //
  9685. // Return: true if successful
  9686. //
  9687. // Comments:
  9688. //
  9689. // History: Date Author Comment
  9690. // 4/12/99 ushaji Created
  9691. // 6/27/00 santanuc Bug Fix #100787
  9692. //
  9693. // TBD: Change some of the DeleteProfileEx calls to DeleteProfile
  9694. //
  9695. //*************************************************************
  9696. BOOL
  9697. DeleteProfile (LPCTSTR lpSidString, LPCTSTR lpProfilePath, LPCTSTR szComputerName)
  9698. {
  9699. LPTSTR lpEnd;
  9700. TCHAR szBuffer[MAX_PATH], szProfilePath[MAX_PATH];
  9701. LONG lResult;
  9702. HKEY hKey = NULL;
  9703. HKEY hKeyCurrentVersion = NULL;
  9704. HKEY hKeyNetCache = NULL;
  9705. DWORD dwType, dwSize;
  9706. BOOL bSuccess = FALSE;
  9707. DWORD dwErr = 0;
  9708. HKEY hKeyLocalLM;
  9709. BOOL bRemoteReg = FALSE;
  9710. BOOL bEnvVarsSet = FALSE;
  9711. TCHAR szOrigSysRoot[MAX_PATH], szOrigSysDrive[MAX_PATH], tDrive;
  9712. TCHAR szShareName[MAX_PATH], szFileSystemName[MAX_PATH];
  9713. DWORD MaxCompLen, FileSysFlags;
  9714. TCHAR szSystemRoot[MAX_PATH], szSystemDrive[MAX_PATH];
  9715. DWORD dwBufferSize;
  9716. TCHAR szTemp[MAX_PATH];
  9717. DWORD dwInternalFlags=0, dwDeleteFlags=0, dwFlags=0;
  9718. LPTSTR szNetComputerName = NULL;
  9719. HMODULE hMsiLib = NULL;
  9720. PFNMSIDELETEUSERDATA pfnMsiDeleteUserData;
  9721. if (!lpSidString) {
  9722. SetLastError(ERROR_INVALID_PARAMETER);
  9723. return FALSE;
  9724. }
  9725. if (szComputerName) {
  9726. if ( !IsUNCPath(szComputerName) ) {
  9727. // Prefixed computer name with slashes if not present
  9728. szNetComputerName = (LPTSTR)LocalAlloc (LPTR, (lstrlen(TEXT("\\\\")) + lstrlen(szComputerName) + 1) * sizeof(TCHAR));
  9729. if (!szNetComputerName) {
  9730. dwErr = GetLastError();
  9731. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to allocate memory for computer name with %d"),dwErr));
  9732. goto Exit;
  9733. }
  9734. lstrcpy(szNetComputerName, TEXT("\\\\"));
  9735. lstrcat(szNetComputerName, szComputerName);
  9736. szComputerName = szNetComputerName;
  9737. }
  9738. GetEnvironmentVariable(TEXT("SystemRoot"), szOrigSysRoot, MAX_PATH);
  9739. GetEnvironmentVariable(TEXT("SystemDrive"), szOrigSysDrive, MAX_PATH);
  9740. lResult = RegConnectRegistry(szComputerName, HKEY_LOCAL_MACHINE, &hKeyLocalLM);
  9741. if (lResult != ERROR_SUCCESS) {
  9742. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to open remote registry %d"), lResult));
  9743. dwErr = lResult;
  9744. goto Exit;
  9745. }
  9746. bRemoteReg = TRUE;
  9747. //
  9748. // Get the value of %SystemRoot% and %SystemDrive% relative to the computer
  9749. //
  9750. lResult = RegOpenKeyEx(hKeyLocalLM,
  9751. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"),
  9752. 0,
  9753. KEY_READ,
  9754. &hKeyCurrentVersion);
  9755. if (lResult != ERROR_SUCCESS) {
  9756. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to open remote registry CurrentVersion %d"), lResult));
  9757. dwErr = lResult;
  9758. goto Exit;
  9759. }
  9760. dwBufferSize = MAX_PATH * sizeof(TCHAR);
  9761. lResult = RegQueryValueEx(hKeyCurrentVersion,
  9762. TEXT("SystemRoot"),
  9763. NULL,
  9764. NULL,
  9765. (BYTE *) szTemp,
  9766. &dwBufferSize);
  9767. RegCloseKey (hKeyCurrentVersion);
  9768. if (lResult != ERROR_SUCCESS) {
  9769. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to open remote registry SystemRoot %d"), lResult));
  9770. dwErr = lResult;
  9771. goto Exit;
  9772. }
  9773. szTemp[1] = TEXT('$');
  9774. //
  9775. // These needs to be set if there are additional places below which uses envvars...
  9776. //
  9777. lstrcpy(szSystemRoot, szComputerName); lstrcat(szSystemRoot, TEXT("\\"));
  9778. lstrcpy(szSystemDrive, szComputerName); lstrcat(szSystemDrive, TEXT("\\"));
  9779. lpEnd = szSystemDrive+lstrlen(szSystemDrive);
  9780. lstrcpyn(lpEnd, szTemp, 3);
  9781. lpEnd = szSystemRoot+lstrlen(szSystemRoot);
  9782. lstrcpy(lpEnd, szTemp);
  9783. SetEnvironmentVariable(TEXT("SystemRoot"), szSystemRoot);
  9784. SetEnvironmentVariable(TEXT("SystemDrive"), szSystemDrive);
  9785. bEnvVarsSet = TRUE;
  9786. }
  9787. else {
  9788. hKeyLocalLM = HKEY_LOCAL_MACHINE;
  9789. }
  9790. //
  9791. // If profile in use then do not delete it
  9792. //
  9793. if (IsProfileInUse(szComputerName, lpSidString)) {
  9794. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Fail to delete profile with sid %s as it is still in use."), lpSidString));
  9795. dwErr = ERROR_INVALID_PARAMETER;
  9796. goto Exit;
  9797. }
  9798. dwErr = GetLastError();
  9799. //
  9800. // Open the profile mapping
  9801. //
  9802. lstrcpy(szProfilePath, PROFILE_LIST_PATH);
  9803. lpEnd = CheckSlash (szProfilePath);
  9804. lstrcpy(lpEnd, lpSidString);
  9805. lResult = RegOpenKeyEx(hKeyLocalLM, szProfilePath, 0,
  9806. KEY_READ, &hKey);
  9807. if (lResult != ERROR_SUCCESS) {
  9808. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to open profile mapping key with error %d"), lResult));
  9809. dwErr = lResult;
  9810. goto Exit;
  9811. }
  9812. dwSize = sizeof(DWORD);
  9813. lResult = RegQueryValueEx (hKey, PROFILE_FLAGS, NULL, &dwType, (LPBYTE)&dwFlags, &dwSize);
  9814. if (ERROR_SUCCESS == lResult && (dwFlags & PI_HIDEPROFILE)) {
  9815. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Fail to delete profile with sid %s as PI_HIDEPROFILE flag is specifed."), lpSidString));
  9816. dwErr = ERROR_INVALID_PARAMETER;
  9817. goto Exit;
  9818. }
  9819. if (!lpProfilePath) {
  9820. TCHAR szTemp[MAX_PATH];
  9821. //
  9822. // Get the profile path...
  9823. //
  9824. dwSize = sizeof(szTemp);
  9825. lResult = RegQueryValueEx (hKey,
  9826. PROFILE_IMAGE_VALUE_NAME,
  9827. NULL,
  9828. &dwType,
  9829. (LPBYTE) szTemp,
  9830. &dwSize);
  9831. dwSize = sizeof(DWORD);
  9832. lResult = RegQueryValueEx (hKey, PROFILE_STATE, NULL, &dwType, (LPBYTE)&dwInternalFlags, &dwSize);
  9833. if (lResult != ERROR_SUCCESS) {
  9834. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to query local profile with error %d"), lResult));
  9835. dwErr = lResult;
  9836. goto Exit;
  9837. }
  9838. if (!ExpandEnvironmentStrings(szTemp, szBuffer, MAX_PATH)) {
  9839. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to expand %s, error %d"), szTemp, GetLastError()));
  9840. dwErr = lResult;
  9841. goto Exit;
  9842. }
  9843. }
  9844. else {
  9845. lstrcpy(szBuffer, lpProfilePath);
  9846. }
  9847. if (dwInternalFlags & PROFILE_THIS_IS_BAK)
  9848. dwDeleteFlags |= DP_DELBACKUP;
  9849. //
  9850. // Do not fail if for some reason we could not delete the profiledir
  9851. //
  9852. bSuccess = DeleteProfileEx(lpSidString, szBuffer, dwDeleteFlags, hKeyLocalLM, szComputerName);
  9853. if (!bSuccess) {
  9854. dwErr = GetLastError();
  9855. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to delete directory, %s with error %d"), szBuffer, dwErr));
  9856. }
  9857. //
  9858. // Delete the user's trash..
  9859. //
  9860. if (szComputerName) {
  9861. lstrcpy (szShareName, szComputerName); lstrcat(szShareName, TEXT("\\"));
  9862. lpEnd = szShareName+lstrlen(szShareName);
  9863. lstrcat(lpEnd, TEXT("A$\\"));
  9864. }
  9865. else {
  9866. lstrcpy(szShareName, TEXT("a:\\"));
  9867. lpEnd = szShareName;
  9868. }
  9869. for (tDrive = TEXT('A'); tDrive <= TEXT('Z'); tDrive++) {
  9870. *lpEnd = tDrive;
  9871. if ((!szComputerName) && (GetDriveType(szShareName) == DRIVE_REMOTE)) {
  9872. DebugMsg((DM_VERBOSE, TEXT("DeleteProfile: Ignoring Drive %s because it is not local"), szShareName));
  9873. continue;
  9874. }
  9875. if (!GetVolumeInformation(szShareName, NULL, 0,
  9876. NULL, &MaxCompLen, &FileSysFlags,
  9877. szFileSystemName, MAX_PATH))
  9878. continue;
  9879. if ((szFileSystemName) && (lstrcmp(szFileSystemName, TEXT("NTFS")) == 0)) {
  9880. TCHAR szRecycleBin[MAX_PATH];
  9881. lstrcpy(szRecycleBin, szShareName);
  9882. lstrcat(szRecycleBin, TEXT("Recycler\\"));
  9883. lstrcat(szRecycleBin, lpSidString);
  9884. Delnode(szRecycleBin);
  9885. DebugMsg((DM_VERBOSE, TEXT("DeleteProfile: Deleting trash directory at %s"), szRecycleBin));
  9886. }
  9887. }
  9888. //
  9889. // Queue for csc cleanup..
  9890. //
  9891. if (RegOpenKeyEx(hKeyLocalLM, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\NetCache"), 0,
  9892. KEY_WRITE, &hKeyNetCache) == ERROR_SUCCESS) {
  9893. HKEY hKeyNextLogOff;
  9894. if (RegCreateKey(hKeyNetCache, TEXT("PurgeAtNextLogoff"), &hKeyNextLogOff) == ERROR_SUCCESS) {
  9895. if (RegSetValueEx(hKeyNextLogOff, lpSidString, 0, REG_SZ, (BYTE *)TEXT(""), sizeof(TCHAR)) == ERROR_SUCCESS) {
  9896. DebugMsg((DM_VERBOSE, TEXT("DeleteProfile: Queued for csc cleanup at next logoff")));
  9897. }
  9898. else {
  9899. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Could not set the Sid Value under NextLogoff key")));
  9900. }
  9901. RegCloseKey(hKeyNextLogOff);
  9902. }
  9903. else {
  9904. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Could not create the PurgeAtNextLogoff key")));
  9905. }
  9906. RegCloseKey(hKeyNetCache);
  9907. }
  9908. else {
  9909. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Could not open the NetCache key")));
  9910. }
  9911. //
  9912. // Delete appmgmt specific stuff..
  9913. //
  9914. if (!ExpandEnvironmentStrings(APPMGMT_DIR_ROOT, szBuffer, MAX_PATH)) {
  9915. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to expand %s, error %d"), APPMGMT_DIR_ROOT, GetLastError()));
  9916. goto Exit;
  9917. }
  9918. //
  9919. // Delete the appmgmt directory
  9920. //
  9921. lpEnd = CheckSlash(szBuffer);
  9922. lstrcpy(lpEnd, lpSidString);
  9923. if (!Delnode(szBuffer)) {
  9924. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to delete the appmgmt dir %s, error %d"), szBuffer, GetLastError()));
  9925. }
  9926. //
  9927. // Reset the environment variables so that api's down the line
  9928. // do not get confused
  9929. //
  9930. if (bEnvVarsSet) {
  9931. SetEnvironmentVariable(TEXT("SystemRoot"), szOrigSysRoot);
  9932. SetEnvironmentVariable(TEXT("SystemDrive"), szOrigSysDrive);
  9933. bEnvVarsSet = FALSE;
  9934. }
  9935. //
  9936. // Delete msi registry values
  9937. //
  9938. lstrcpy(szBuffer, APPMGMT_REG_MANAGED);
  9939. lpEnd = CheckSlash(szBuffer);
  9940. lstrcpy(lpEnd, lpSidString);
  9941. if (!RegDelnode (hKeyLocalLM, szBuffer)) {
  9942. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to delete the appmgmt key %s"), szBuffer));
  9943. }
  9944. //
  9945. // Delete rsop data
  9946. //
  9947. if (!RsopDeleteUserNameSpace((LPTSTR)szComputerName, (LPTSTR)lpSidString)) {
  9948. DebugMsg((DM_WARNING, TEXT("DeleteProfile: Failed to delete rsop data")));
  9949. }
  9950. //
  9951. // Clean Darwin information
  9952. //
  9953. hMsiLib = LoadLibrary(TEXT("msi.dll"));
  9954. if (hMsiLib) {
  9955. pfnMsiDeleteUserData = (PFNMSIDELETEUSERDATA) GetProcAddress(hMsiLib,
  9956. #ifdef UNICODE
  9957. "MsiDeleteUserDataW");
  9958. #else
  9959. "MsiDeleteUserDataA");
  9960. #endif
  9961. if (pfnMsiDeleteUserData) {
  9962. (*pfnMsiDeleteUserData)(lpSidString, szComputerName, NULL);
  9963. }
  9964. else {
  9965. DebugMsg((DM_WARNING, TEXT("DeleteProfile: GetProcAddress returned failure. error %d"), GetLastError()));
  9966. }
  9967. FreeLibrary(hMsiLib);
  9968. }
  9969. else {
  9970. DebugMsg((DM_WARNING, TEXT("DeleteProfile: LoadLibrary returned failure. error %d"), GetLastError()));
  9971. }
  9972. Exit:
  9973. if (hKey)
  9974. RegCloseKey(hKey);
  9975. if (bRemoteReg) {
  9976. RegCloseKey(hKeyLocalLM);
  9977. }
  9978. if ( szNetComputerName )
  9979. LocalFree(szNetComputerName);
  9980. if (bEnvVarsSet) {
  9981. SetEnvironmentVariable(TEXT("SystemRoot"), szOrigSysRoot);
  9982. SetEnvironmentVariable(TEXT("SystemDrive"), szOrigSysDrive);
  9983. }
  9984. SetLastError(dwErr);
  9985. return bSuccess;
  9986. }
  9987. //*************************************************************
  9988. //
  9989. // SetNtUserIniAttributes()
  9990. //
  9991. // Purpose: Sets system-bit on ntuser.ini
  9992. //
  9993. // Parameters:
  9994. //
  9995. // Return: true if successful
  9996. //
  9997. // Comments:
  9998. //
  9999. // History: Date Author Comment
  10000. // 7/7/99 ushaji Created
  10001. //
  10002. //*************************************************************
  10003. BOOL SetNtUserIniAttributes(LPTSTR szDir)
  10004. {
  10005. TCHAR szBuffer[MAX_PATH];
  10006. HANDLE hFileNtUser;
  10007. LPTSTR lpEnd;
  10008. DWORD dwWritten;
  10009. lstrcpy (szBuffer, szDir);
  10010. lpEnd = CheckSlash (szBuffer);
  10011. lstrcpy (lpEnd, c_szNTUserIni);
  10012. //
  10013. // Mark the file with system bit
  10014. //
  10015. hFileNtUser = CreateFile(szBuffer, GENERIC_ALL, 0, NULL, CREATE_NEW,
  10016. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
  10017. if (INVALID_HANDLE_VALUE == hFileNtUser)
  10018. SetFileAttributes (szBuffer, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
  10019. else {
  10020. //
  10021. // The WritePrivateProfile* functions do not write in unicode
  10022. // unless the file already exists in unicode format. Therefore,
  10023. // Precreate a unicode file so that
  10024. // the WritePrivateProfile* functions can preserve the
  10025. // Make sure that the ini file is unicode by writing spaces into it.
  10026. //
  10027. WriteFile(hFileNtUser, L"\xfeff\r\n", 3 * sizeof(WCHAR), &dwWritten, NULL);
  10028. WriteFile(hFileNtUser, L" \r\n", 7 * sizeof(WCHAR),
  10029. &dwWritten, NULL);
  10030. CloseHandle(hFileNtUser);
  10031. }
  10032. return TRUE;
  10033. }
  10034. //*************************************************************
  10035. //
  10036. // CUserProfile::HandleRegKeyLeak
  10037. //
  10038. // Purpose: If registry key leaked, save the hive and call
  10039. // WatchHiveRefCount to get the hive unloaded later
  10040. // when the keys are released.
  10041. //
  10042. // Parameters:
  10043. //
  10044. // lpSidString User's sid in string form.
  10045. // lpProfile User's LPPROFILE structure.
  10046. // bUnloadHiveSucceeded Indicates that we should save the hive
  10047. // to a temp file.
  10048. // dwWatchHiveFlags (in, out) WHRC_ flags.
  10049. // dwCopyTmpHive (out) CPD_ flag to indicate to
  10050. // CopyProfileDirectory whether or not a temp
  10051. // hive file should be used.
  10052. // tszTmpHiveFile (out) The tmp hive file name.
  10053. // privilege.
  10054. //
  10055. // Return: Error code to indicate if the hive is successfully saved to
  10056. // a temp file. If yes, return ERROR_SUCCESS. Otherwise, return
  10057. // an error code that indicates why.
  10058. //
  10059. // Comments:
  10060. //
  10061. // History: Date Author Comment
  10062. // 5/31/00 weiruc Created
  10063. //
  10064. //*************************************************************
  10065. DWORD CUserProfile::HandleRegKeyLeak(LPTSTR lpSidString,
  10066. LPPROFILE lpProfile,
  10067. BOOL bUnloadHiveSucceeded,
  10068. DWORD* dwWatchHiveFlags,
  10069. DWORD* dwCopyTmpHive,
  10070. LPTSTR pTmpHiveFile)
  10071. {
  10072. HRESULT hres;
  10073. HKEY hkCurrentUser = NULL;
  10074. NTSTATUS status;
  10075. BOOLEAN WasEnabled;
  10076. DWORD dwErr = ERROR_SUCCESS;
  10077. TCHAR szErr[MAX_PATH];
  10078. BOOL bAdjustPriv = FALSE;
  10079. HANDLE hToken = NULL;
  10080. LPTSTR lpUserName;
  10081. if(!bUnloadHiveSucceeded) {
  10082. //
  10083. // Reopen the user hive.
  10084. //
  10085. if((dwErr = RegOpenKeyEx(HKEY_USERS,
  10086. lpSidString,
  10087. 0,
  10088. KEY_ALL_ACCESS,
  10089. &hkCurrentUser)) != ERROR_SUCCESS) {
  10090. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: RegOpenKeyEx failed with %08x"), dwErr));
  10091. if(dwErr == ERROR_FILE_NOT_FOUND) {
  10092. //
  10093. // If ERROR_FILE_NOT_FOUND, then the hive has been unloaded
  10094. // between RegUnloadKey and here. Procceed without calling
  10095. // WatchHiveRefCount.
  10096. //
  10097. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: Hive is already unloaded")));
  10098. *dwWatchHiveFlags &= ~WHRC_UNLOAD_HIVE;
  10099. dwErr = ERROR_SUCCESS;
  10100. }
  10101. goto NOTIFY_REGISTRY;
  10102. }
  10103. //
  10104. // Make the tmp hive file name: <user profile directory>\ntuser.tmp
  10105. //
  10106. if(lstrlen(lpProfile->lpLocalProfile) + lstrlen(c_szNTUserTmp) + 2 > MAX_PATH) {
  10107. //
  10108. // If the tmp hive file name exceeds MAX_PATH give up.
  10109. //
  10110. dwErr = ERROR_BAD_PATHNAME;
  10111. goto NOTIFY_REGISTRY;
  10112. }
  10113. lstrcpy(pTmpHiveFile, lpProfile->lpLocalProfile);
  10114. lstrcat(pTmpHiveFile, TEXT("\\"));
  10115. lstrcat(pTmpHiveFile, c_szNTUserTmp);
  10116. //
  10117. // Delete existing tmp file if any.
  10118. //
  10119. DeleteFile(pTmpHiveFile);
  10120. //
  10121. // Flush the hive.
  10122. //
  10123. RegFlushKey(hkCurrentUser);
  10124. //
  10125. // Check to see if we are impersonating.
  10126. //
  10127. if(!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken) || hToken == NULL) {
  10128. bAdjustPriv = TRUE;
  10129. }
  10130. else {
  10131. CloseHandle(hToken);
  10132. }
  10133. if(bAdjustPriv) {
  10134. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  10135. if(!NT_SUCCESS(status)) {
  10136. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: RtlAdjustPrivilege failed with error %08x"), status));
  10137. dwErr = ERROR_ACCESS_DENIED;
  10138. goto NOTIFY_REGISTRY;
  10139. }
  10140. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: RtlAdjustPrivilege succeeded!")));
  10141. }
  10142. //
  10143. // Save the hive to the tmp file.
  10144. //
  10145. if((dwErr = RegSaveKey(hkCurrentUser, pTmpHiveFile, NULL)) != ERROR_SUCCESS) {
  10146. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: RegSaveKey failed with %08x"), dwErr));
  10147. if (!(lpProfile->dwFlags & PI_LITELOAD)) {
  10148. //
  10149. // Only write event log when not in liteload mode.
  10150. // there are known problems with liteLoad loading because
  10151. // of which eventlog can get full during stress
  10152. //
  10153. ReportError(NULL, PI_NOUI, 1, EVENT_FAILED_HIVE_UNLOAD, GetErrString(dwErr, szErr));
  10154. }
  10155. DeleteFile(pTmpHiveFile);
  10156. goto NOTIFY_REGISTRY;
  10157. }
  10158. //
  10159. // Set the hidden attribute on the temp hive file, so that when it get copied in the
  10160. // actual hive file it should not reset the hidden attribute
  10161. //
  10162. if (!SetFileAttributes(pTmpHiveFile, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN)) {
  10163. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: Failed to set the hidden attribute on temp hive file with error %d"), GetLastError()));
  10164. }
  10165. *dwCopyTmpHive = CPD_USETMPHIVEFILE;
  10166. //
  10167. // Log an event only if we schedule the hive for unloading.
  10168. // If it is already scheduled for unloading (RegUnloadKey returns
  10169. // ERROR_WRITE_PROTECT in that case) then do not give this message.
  10170. //
  10171. if (*dwWatchHiveFlags & WHRC_UNLOAD_HIVE) {
  10172. lpUserName = GetUserNameFromSid(lpSidString);
  10173. ReportError(NULL, PI_NOUI | EVENT_WARNING_TYPE, 1, EVENT_HIVE_SAVED, lpUserName);
  10174. if (lpUserName != lpSidString) {
  10175. LocalFree(lpUserName);
  10176. }
  10177. }
  10178. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: RegSaveKey succeeded!")));
  10179. if(bAdjustPriv) {
  10180. //
  10181. // Restore the privilege.
  10182. //
  10183. status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  10184. if (!NT_SUCCESS(status)) {
  10185. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: Failed to restore RESTORE privilege to previous enabled state %08x"), status));
  10186. }
  10187. else {
  10188. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: RtlAdjustPrivilege succeeded!")));
  10189. }
  10190. }
  10191. }
  10192. NOTIFY_REGISTRY:
  10193. if(hkCurrentUser) {
  10194. RegCloseKey(hkCurrentUser);
  10195. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: hkCurrentUser closed")));
  10196. }
  10197. if(*dwWatchHiveFlags) {
  10198. //
  10199. // Watch for the hive ref count.
  10200. //
  10201. if((hres = WatchHiveRefCount(lpSidString, *dwWatchHiveFlags)) != S_OK) {
  10202. DebugMsg((DM_WARNING, TEXT("HandleRegKeyLeak: Calling WatchHiveRefCount failed. err = %08x"), hres));
  10203. }
  10204. else {
  10205. DebugMsg((DM_VERBOSE, TEXT("HandleRegKeyLeak: Calling WatchHiveRefCount (%s) succeeded"), lpSidString));
  10206. }
  10207. }
  10208. //
  10209. // In UnloadUserProfile, Without this registry leak fix, the code
  10210. // goes to Exit immediately
  10211. // if unloading of the user's hive fails without doing any of the
  10212. // stuff below. But with the fix, we'll fall through here and reconcile
  10213. // the local and the central profiles. The code below also cleans up
  10214. // local profiles, i.e., delete temp profiles, guest user profiles,
  10215. // etc. We have 2 choices here:
  10216. // 1. We can let the cleaning up happen, in which case files that
  10217. // are not in use can be cleaned up. This would mean that the
  10218. // next time when the user logs in, his/her profile will no
  10219. // longer be loaded, even though his/her hive might still be
  10220. // loaded. In other words, in TestIfUserProfileLoaded instead
  10221. // of relying simply on testing whether or not the hive is still
  10222. // loaded, we have to actually look at the ref count to tell if
  10223. // a profile is still loaded. In this case the WHRC code will
  10224. // only need to clean up those files that can not be cleaned up
  10225. // here.
  10226. // 2. Do not clean up here. The scenario will remain basically the
  10227. // same. Next time when the user logs on, his/her profile will
  10228. // still be loaded, so no change to TestIfUserProfileLoaded. The
  10229. // WHRC code will handle the complete cleaning up.
  10230. // We implemented choise #2 because it's easier in coding. In the
  10231. // future consider using choice #1.
  10232. //
  10233. return dwErr;
  10234. }
  10235. //*************************************************************
  10236. //
  10237. // AllocAndExpandProfilePath()
  10238. //
  10239. // Purpose: Gets a few predetermined env variables in the profile path
  10240. // expanded
  10241. //
  10242. // Parameters:
  10243. // lpProfile
  10244. //
  10245. // Return: true if successful
  10246. //
  10247. // Comments:
  10248. //
  10249. // Tt gets the environment variables and keeps it locally.
  10250. //
  10251. //*************************************************************
  10252. LPTSTR AllocAndExpandProfilePath(
  10253. LPPROFILEINFO lpProfileInfo)
  10254. {
  10255. TCHAR szUserName[MAX_PATH];
  10256. DWORD dwPathLen=0, cFullPath=0;
  10257. TCHAR szFullPath[MAX_PATH+1];
  10258. LPTSTR pszFullPath=NULL;
  10259. szUserName[0] = TEXT('\0');
  10260. GetEnvironmentVariable (USERNAME_VARIABLE, szUserName, 100);
  10261. SetEnvironmentVariable (USERNAME_VARIABLE, lpProfileInfo->lpUserName);
  10262. //
  10263. // Expand the profile path using current settings
  10264. //
  10265. cFullPath = ExpandEnvironmentStrings(lpProfileInfo->lpProfilePath, szFullPath, MAX_PATH);
  10266. if (cFullPath)
  10267. {
  10268. pszFullPath = (LPTSTR)LocalAlloc(LPTR, (1+ cFullPath) * sizeof(TCHAR));
  10269. if (pszFullPath)
  10270. {
  10271. lstrcpyn( pszFullPath, szFullPath, cFullPath * sizeof(TCHAR));
  10272. }
  10273. }
  10274. else
  10275. {
  10276. pszFullPath = NULL;
  10277. }
  10278. //
  10279. // restore the env block
  10280. //
  10281. if (szUserName[0] != TEXT('\0'))
  10282. SetEnvironmentVariableW (USERNAME_VARIABLE, szUserName);
  10283. else
  10284. SetEnvironmentVariableW (USERNAME_VARIABLE, NULL);
  10285. return(pszFullPath);
  10286. }
  10287. //*************************************************************
  10288. //
  10289. // MAP::MAP()
  10290. //
  10291. // Constructor for class MAP.
  10292. //
  10293. //*************************************************************
  10294. MAP::MAP()
  10295. {
  10296. for(DWORD i = 0; i < MAXIMUM_WAIT_OBJECTS; i++) {
  10297. rghEvents[i] = NULL;
  10298. rgSids[i] = NULL;
  10299. }
  10300. dwItems = 0;
  10301. pNext = NULL;
  10302. }
  10303. //*************************************************************
  10304. //
  10305. // MAP::Delete
  10306. //
  10307. // Delete an work item from a map. Switch the last item into the now
  10308. // empty spot. Caller has to hold the critical section csMap.
  10309. //
  10310. // Parameters:
  10311. //
  10312. // dwIndex index into the work list
  10313. //
  10314. // Return value:
  10315. //
  10316. // None.
  10317. //
  10318. // History:
  10319. //
  10320. // Created weiruc 3/2/2000
  10321. //
  10322. //*************************************************************
  10323. void MAP::Delete(DWORD dwIndex)
  10324. {
  10325. //
  10326. // Switch the last work item into the newly finished work item position.
  10327. //
  10328. if(rghEvents[dwIndex]) {
  10329. CloseHandle(rghEvents[dwIndex]);
  10330. rghEvents[dwIndex] = NULL;
  10331. }
  10332. if(rgSids[dwIndex]) {
  10333. LocalFree(rgSids[dwIndex]);
  10334. rgSids[dwIndex] = NULL;
  10335. }
  10336. if(dwIndex < dwItems - 1) {
  10337. rghEvents[dwIndex] = rghEvents[dwItems - 1];
  10338. rgSids[dwIndex] = rgSids[dwItems - 1];
  10339. }
  10340. rgSids[dwItems - 1] = NULL;
  10341. rghEvents[dwItems - 1] = NULL;
  10342. dwItems--;
  10343. }
  10344. //*************************************************************
  10345. //
  10346. // MAP::Insert
  10347. //
  10348. // Insert an work item into a map. Caller must hold csMap.
  10349. // the items need to be added before the count is changed
  10350. // because WorkerThreadMain accesses the map without holding
  10351. // a lock.
  10352. //
  10353. // Parameters:
  10354. //
  10355. // HANDLE Event to be inserted.
  10356. // LPTSTR Sid string to be inserted.
  10357. //
  10358. // Return value:
  10359. //
  10360. // None.
  10361. //
  10362. // History:
  10363. //
  10364. // Created weiruc 3/2/2000
  10365. //
  10366. //*************************************************************
  10367. void MAP::Insert(HANDLE hEvent, LPTSTR ptszSid)
  10368. {
  10369. rghEvents[dwItems] = hEvent;
  10370. rgSids[dwItems] = ptszSid;
  10371. dwItems++;
  10372. }
  10373. //*************************************************************
  10374. //
  10375. // MAP::GetSid
  10376. //
  10377. // Get a sid by the index; Caller has to hold csMap.
  10378. //
  10379. // Parameters:
  10380. //
  10381. // dwIndex index
  10382. //
  10383. // Return value:
  10384. //
  10385. // The sid.
  10386. //
  10387. // History:
  10388. //
  10389. // Created weiruc 3/2/2000
  10390. //
  10391. //*************************************************************
  10392. LPTSTR MAP::GetSid(DWORD dwIndex)
  10393. {
  10394. LPTSTR ptszTmpSid = rgSids[dwIndex];
  10395. rgSids[dwIndex] = NULL;
  10396. return ptszTmpSid;
  10397. }
  10398. //*************************************************************
  10399. //
  10400. // CHashTable::CHashTable
  10401. //
  10402. // CHashTable class initializer.
  10403. //
  10404. // Parameters:
  10405. //
  10406. // Return value:
  10407. //
  10408. // None.
  10409. //
  10410. // History:
  10411. //
  10412. // Created weiruc 3/2/2000
  10413. //
  10414. //*************************************************************
  10415. void CHashTable::Initialize()
  10416. {
  10417. for(DWORD i = 0; i < NUM_OF_BUCKETS; i++) {
  10418. Table[i] = NULL;
  10419. }
  10420. }
  10421. //*************************************************************
  10422. //
  10423. // CHashTable::Hash
  10424. //
  10425. // Hash a string.
  10426. //
  10427. // Parameters:
  10428. //
  10429. // pctszString the string to be hashed
  10430. //
  10431. // Return value:
  10432. //
  10433. // Hash value.
  10434. //
  10435. // History:
  10436. //
  10437. // Created weiruc 3/2/2000
  10438. //
  10439. //*************************************************************
  10440. DWORD CHashTable::Hash(LPTSTR ptszString)
  10441. {
  10442. DWORD dwHashValue = 0;
  10443. TCHAR* ptch = ptszString;
  10444. while(*ptch != TEXT('\0')) {
  10445. dwHashValue += *ptch;
  10446. ptch++;
  10447. }
  10448. return dwHashValue % NUM_OF_BUCKETS;
  10449. }
  10450. //*************************************************************
  10451. //
  10452. // CHashTable::IsInTable
  10453. //
  10454. // Check to see if a string is already in this hash table. This function
  10455. // is not thread safe. Caller must ensure thread safety when calling this
  10456. // function from multiple threads.
  10457. //
  10458. // Parameters:
  10459. //
  10460. // ptszString the string to be checked.
  10461. // ppCSEntry buffer for the pointer to the CSEntry stored.
  10462. //
  10463. // Return value:
  10464. //
  10465. // TRUE/FALSE
  10466. //
  10467. // History:
  10468. //
  10469. // Created weiruc 5/25/2000
  10470. //
  10471. //*************************************************************
  10472. BOOL CHashTable::IsInTable(LPTSTR ptszString, CSEntry** ppCSEntry)
  10473. {
  10474. DWORD dwHashValue = Hash(ptszString);
  10475. PBUCKET pbucket;
  10476. PBUCKET pTmp;
  10477. //
  10478. // Check to see if ptszString is already in the hash table.
  10479. //
  10480. for(pTmp = Table[dwHashValue]; pTmp != NULL; pTmp = pTmp->pNext) {
  10481. if(lstrcmp(pTmp->ptszString, ptszString) == 0) {
  10482. if (ppCSEntry) {
  10483. *ppCSEntry = pTmp->pEntry;
  10484. }
  10485. return TRUE;
  10486. }
  10487. }
  10488. return FALSE;
  10489. }
  10490. //*************************************************************
  10491. //
  10492. // CHashTable::HashAdd
  10493. //
  10494. // Add a string into the hash table. This function doesn't check to see
  10495. // if the string is already in the table. The caller is responsible for
  10496. // calling IsInTable before calling this function. This function
  10497. // is not thread safe. Caller must ensure thread safety when calling this
  10498. // function from multiple threads.
  10499. //
  10500. // Parameters:
  10501. //
  10502. // ptszString the string to be added.
  10503. // pCSEntry the CS entry to be added
  10504. //
  10505. // Return value:
  10506. //
  10507. // TRUE/FALSE indicating success/failure. The function will fail if
  10508. // the item is already in the hash table, or if we are out of memory.
  10509. //
  10510. // History:
  10511. //
  10512. // Created weiruc 3/2/2000
  10513. //
  10514. //*************************************************************
  10515. BOOL CHashTable::HashAdd(LPTSTR ptszString, CSEntry* pCSEntry)
  10516. {
  10517. DWORD dwHashValue = Hash(ptszString);
  10518. PBUCKET pbucket;
  10519. PBUCKET pTmp;
  10520. pbucket = new BUCKET(ptszString, pCSEntry);
  10521. if(pbucket == NULL) {
  10522. DebugMsg((DM_WARNING, TEXT("Can't insert %s. Out of memory"), ptszString));
  10523. return FALSE;
  10524. }
  10525. pbucket->pNext = Table[dwHashValue];
  10526. Table[dwHashValue] = pbucket;
  10527. DebugMsg((DM_VERBOSE, TEXT("CHashTable::HashAdd: %s added in bucket %d"), ptszString, dwHashValue));
  10528. return TRUE;
  10529. }
  10530. //*************************************************************
  10531. //
  10532. // CHashTable::HashDelete
  10533. //
  10534. // Delete a string from the hash table. This function
  10535. // is not thread safe. Caller must ensure thread safety when calling this
  10536. // function from multiple threads.
  10537. //
  10538. // Parameters:
  10539. //
  10540. // ptszString the string to be deleted.
  10541. //
  10542. // Return value:
  10543. //
  10544. // none.
  10545. //
  10546. // History:
  10547. //
  10548. // Created weiruc 3/2/2000
  10549. //
  10550. //*************************************************************
  10551. void CHashTable::HashDelete(LPTSTR ptszString)
  10552. {
  10553. PBUCKET pPrev, pCur;
  10554. DWORD dwHashValue = Hash(ptszString);
  10555. if(Table[dwHashValue] == NULL) {
  10556. return;
  10557. }
  10558. pCur = Table[dwHashValue];
  10559. if(lstrcmp(pCur->ptszString, ptszString) == 0) {
  10560. Table[dwHashValue] = Table[dwHashValue]->pNext;
  10561. pCur->pNext = NULL;
  10562. delete pCur;
  10563. DebugMsg((DM_VERBOSE, TEXT("CHashTable::HashDelete: %s deleted"), ptszString));
  10564. return;
  10565. }
  10566. for(pPrev = Table[dwHashValue], pCur = pPrev->pNext; pCur != NULL; pPrev = pCur, pCur = pCur->pNext) {
  10567. if(lstrcmp(pCur->ptszString, ptszString) == 0) {
  10568. pPrev->pNext = pCur->pNext;
  10569. pCur->pNext = NULL;
  10570. DebugMsg((DM_VERBOSE, TEXT("CHashTable::HashDelete: %s deleted"), ptszString));
  10571. delete pCur;
  10572. return;
  10573. }
  10574. }
  10575. }
  10576. //*************************************************************
  10577. //
  10578. // Called by and only by console winlogon process.
  10579. //
  10580. //*************************************************************
  10581. void WINAPI InitializeUserProfile()
  10582. {
  10583. cUserProfileManager.Initialize();
  10584. }
  10585. //*************************************************************
  10586. //
  10587. // Called by CreateThread
  10588. //
  10589. //*************************************************************
  10590. DWORD ThreadMain(PMAP pThreadMap)
  10591. {
  10592. return cUserProfileManager.WorkerThreadMain(pThreadMap);
  10593. }
  10594. //*************************************************************
  10595. //
  10596. // CSyncManager::Initialize()
  10597. //
  10598. // Initialize the critical section that protects the CS
  10599. // entries list and the hash table.
  10600. //
  10601. // Parameters:
  10602. //
  10603. // void
  10604. //
  10605. // Return value:
  10606. //
  10607. // TRUE/FALSE to indicate if initialization succeeded or failed.
  10608. //
  10609. // History:
  10610. //
  10611. // 6/16/00 weiruc Created
  10612. //
  10613. //*************************************************************
  10614. BOOL CSyncManager::Initialize()
  10615. {
  10616. BOOL bRet = TRUE;
  10617. cTable.Initialize();
  10618. //
  10619. // Initialize the critical section that protects the cs entry list.
  10620. //
  10621. __try {
  10622. if(!InitializeCriticalSectionAndSpinCount(&cs, 0x80000000)) {
  10623. DebugMsg((DM_WARNING, TEXT("CSyncManager::Initialize: InitializeCriticalSectionAndSpinCount failed with %08x"), GetLastError()));
  10624. bRet = FALSE;
  10625. }
  10626. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::Initialize: critical section initialized")));
  10627. }
  10628. __except(EXCEPTION_EXECUTE_HANDLER) {
  10629. DebugMsg((DM_WARNING, TEXT("CSyncManager::Initialize: InitializeCriticalSection failed")));
  10630. bRet = FALSE;
  10631. }
  10632. return bRet;
  10633. }
  10634. //*************************************************************
  10635. //
  10636. // CSyncManager::EnterLock()
  10637. //
  10638. // Get a user's profile lock.
  10639. //
  10640. // Parameters:
  10641. //
  10642. // pSid - User's sid string
  10643. //
  10644. // Return value:
  10645. //
  10646. // TRUE/FALSE. GetLastError to get error.
  10647. //
  10648. // History:
  10649. //
  10650. // 6/16/00 weiruc Created
  10651. //
  10652. //*************************************************************
  10653. BOOL CSyncManager::EnterLock(LPTSTR pSid, LPTSTR lpRPCEndPoint)
  10654. {
  10655. DWORD dwError = ERROR_SUCCESS;
  10656. CSEntry* pEntry = NULL;
  10657. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::EnterLock <%s>"), pSid));
  10658. EnterCriticalSection(&cs);
  10659. //
  10660. // Look up entry in the hash table.
  10661. //
  10662. if(cTable.IsInTable(pSid, &pEntry)) {
  10663. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::EnterLock: Found existing entry")));
  10664. }
  10665. else {
  10666. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::EnterLock: No existing entry found")));
  10667. pEntry = new CSEntry;
  10668. if(!pEntry) {
  10669. dwError = ERROR_OUTOFMEMORY;
  10670. DebugMsg((DM_WARNING, TEXT("CSyncManager::EnterLock: Can't create new CSEntry %08x"), dwError));
  10671. goto Exit;
  10672. }
  10673. if(!pEntry->Initialize(pSid)) {
  10674. dwError = GetLastError();
  10675. DebugMsg((DM_WARNING, TEXT("CSyncManager::EnterLock: Can not initialize new entry %08x"), dwError));
  10676. goto Exit;
  10677. }
  10678. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::EnterLock: New entry created")));
  10679. //
  10680. // Insert the new entry in the list.
  10681. //
  10682. pEntry->pNext = pCSList;
  10683. pCSList = pEntry;
  10684. //
  10685. // Add the new entry into the hash table.
  10686. //
  10687. cTable.HashAdd(pEntry->pSid, pEntry);
  10688. }
  10689. pEntry->IncrementRefCount();
  10690. LeaveCriticalSection(&cs);
  10691. pEntry->EnterCS();
  10692. pEntry->SetRPCEndPoint(lpRPCEndPoint);
  10693. return TRUE;
  10694. Exit:
  10695. LeaveCriticalSection(&cs);
  10696. if(pEntry) {
  10697. delete pEntry;
  10698. }
  10699. SetLastError(dwError);
  10700. return FALSE;
  10701. }
  10702. //*************************************************************
  10703. //
  10704. // CSyncManager::LeaveLock()
  10705. //
  10706. // Release a user's profile lock
  10707. //
  10708. // Parameters:
  10709. //
  10710. // pSid - The user's sid string
  10711. //
  10712. // Return value:
  10713. //
  10714. // TRUE/FALSE
  10715. //
  10716. // History:
  10717. //
  10718. // 6/16/00 weiruc Created
  10719. //
  10720. //*************************************************************
  10721. BOOL CSyncManager::LeaveLock(LPTSTR pSid)
  10722. {
  10723. BOOL bRet = FALSE;
  10724. DWORD dwError = ERROR_SUCCESS;
  10725. CSEntry* pPrev;
  10726. CSEntry* pCur;
  10727. CSEntry* pToBeDeleted;
  10728. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::LeaveLock <%s>"), pSid));
  10729. EnterCriticalSection(&cs);
  10730. //
  10731. // Look up the critical section entry.
  10732. //
  10733. if(!cTable.IsInTable(pSid, &pCur)) {
  10734. DebugMsg((DM_WARNING, TEXT("CSyncManager::LeaveLock: User not found!!!!")));
  10735. dwError = ERROR_NOT_FOUND;
  10736. goto Exit;
  10737. }
  10738. pCur->LeaveCS();
  10739. bRet = TRUE;
  10740. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::LeaveLock: Lock released")));
  10741. //
  10742. // If there's more user waiting for this lock, return.
  10743. //
  10744. if(!pCur->NoMoreUser()) {
  10745. goto Exit;
  10746. }
  10747. //
  10748. // Nobody is waiting on this lock anymore, delete it from the hash table.
  10749. //
  10750. cTable.HashDelete(pSid);
  10751. //
  10752. // Delete from the cs list.
  10753. //
  10754. pToBeDeleted = pCur;
  10755. if(pCur == pCSList) {
  10756. //
  10757. // Entry is the first one in the list.
  10758. //
  10759. pCSList = pCSList->pNext;
  10760. pCur->Uninitialize();
  10761. delete pCur;
  10762. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::LeaveLock: Lock deleted")));
  10763. } else {
  10764. for(pPrev = pCSList, pCur = pCSList->pNext; pCur; pPrev = pCur, pCur = pCur->pNext) {
  10765. if(pCur == pToBeDeleted) {
  10766. pPrev->pNext = pCur->pNext;
  10767. pCur->Uninitialize();
  10768. delete pCur;
  10769. DebugMsg((DM_VERBOSE, TEXT("CSyncManager::DestroyCSEntry: Entry deleted")));
  10770. goto Exit;
  10771. }
  10772. }
  10773. }
  10774. Exit:
  10775. LeaveCriticalSection(&cs);
  10776. SetLastError(dwError);
  10777. return bRet;
  10778. }
  10779. //*************************************************************
  10780. //
  10781. // CSyncManager::GetRPCEndPoint()
  10782. //
  10783. // Purpose: returns the RPCEndPoint registered by client
  10784. //
  10785. // Parameters:
  10786. //
  10787. // pSid - User's sid string
  10788. //
  10789. // Return:
  10790. //
  10791. // LPTSTR
  10792. //
  10793. // Comments:
  10794. //
  10795. // History: Date Author Comment
  10796. // 10/25/00 santanuc Created
  10797. //
  10798. //*************************************************************
  10799. LPTSTR CSyncManager::GetRPCEndPoint(LPTSTR pSid)
  10800. {
  10801. CSEntry* pEntry = NULL;
  10802. LPTSTR lpRPCEndPoint;
  10803. EnterCriticalSection(&cs);
  10804. //
  10805. // Look up entry in the hash table.
  10806. //
  10807. if(cTable.IsInTable(pSid, &pEntry)) {
  10808. lpRPCEndPoint = pEntry->GetRPCEndPoint();
  10809. }
  10810. else {
  10811. lpRPCEndPoint = NULL;
  10812. }
  10813. LeaveCriticalSection(&cs);
  10814. return lpRPCEndPoint;
  10815. }
  10816. //*************************************************************
  10817. //
  10818. // CSEntry::Initialize()
  10819. //
  10820. // Initialize the user's critical section. This function can
  10821. // only be called by the sync manager.
  10822. //
  10823. // Parameters:
  10824. //
  10825. // pSid - The user's sid string
  10826. //
  10827. // Return value:
  10828. //
  10829. // TRUE/FALSE
  10830. //
  10831. // History:
  10832. //
  10833. // 6/16/00 weiruc Created
  10834. //
  10835. //*************************************************************
  10836. BOOL CSEntry::Initialize(LPTSTR pSidParam)
  10837. {
  10838. BOOL bRet = FALSE;
  10839. DWORD dwError = ERROR_SUCCESS;
  10840. pSid = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pSidParam) + 1) * sizeof(TCHAR));
  10841. if(!pSid) {
  10842. dwError = GetLastError();
  10843. DebugMsg((DM_WARNING, TEXT("CSEntry::Initialize: LocalAlloc failed with %08x"), dwError));
  10844. goto Exit;
  10845. }
  10846. lstrcpy(pSid, pSidParam);
  10847. __try {
  10848. if(!InitializeCriticalSectionAndSpinCount(&csUser, 0x80000000)) {
  10849. dwError = GetLastError();
  10850. DebugMsg((DM_WARNING, TEXT("CSEntry::Initialize: InitializeCriticalSectionAndSpinCount failed with %08x"), dwError));
  10851. }
  10852. else {
  10853. bRet = TRUE;
  10854. }
  10855. }
  10856. __except(EXCEPTION_EXECUTE_HANDLER) {
  10857. dwError = GetExceptionCode();
  10858. DebugMsg((DM_WARNING, TEXT("CSEntry::Initialize: InitializeCriticalSectionAndSpinCount exception %08x"), dwError));
  10859. }
  10860. Exit:
  10861. SetLastError(dwError);
  10862. return bRet;
  10863. }
  10864. //*************************************************************
  10865. //
  10866. // CSEntry::Uninitialize()
  10867. //
  10868. // Delete the user's critical section. This function can
  10869. // only be called by the sync manager.
  10870. //
  10871. // Parameters:
  10872. //
  10873. // void.
  10874. //
  10875. // Return value:
  10876. //
  10877. // void
  10878. //
  10879. // History:
  10880. //
  10881. // 6/16/00 weiruc Created
  10882. //
  10883. //*************************************************************
  10884. void CSEntry::Uninitialize()
  10885. {
  10886. DeleteCriticalSection(&csUser);
  10887. if (pSid) {
  10888. LocalFree(pSid);
  10889. }
  10890. }
  10891. //*************************************************************
  10892. //
  10893. // CSEntry::EnterCS()
  10894. //
  10895. // Enter a user's critical section
  10896. //
  10897. // Parameters:
  10898. //
  10899. // void.
  10900. //
  10901. // Return value:
  10902. //
  10903. // void
  10904. //
  10905. // History:
  10906. //
  10907. // 6/16/00 weiruc Created
  10908. //
  10909. //*************************************************************
  10910. void CSEntry::EnterCS()
  10911. {
  10912. EnterCriticalSection(&csUser);
  10913. }
  10914. //*************************************************************
  10915. //
  10916. // CSEntry::LeaveCS()
  10917. //
  10918. // Leave a user's critical section
  10919. //
  10920. // Parameters:
  10921. //
  10922. // void.
  10923. //
  10924. // Return value:
  10925. //
  10926. // void
  10927. //
  10928. // History:
  10929. //
  10930. // 6/16/00 weiruc Created
  10931. //
  10932. //*************************************************************
  10933. void CSEntry::LeaveCS()
  10934. {
  10935. dwRef--;
  10936. LeaveCriticalSection(&csUser);
  10937. }
  10938. //*************************************************************
  10939. //
  10940. // CSEntry::NoMoreUser()
  10941. //
  10942. // Are there more users?
  10943. //
  10944. // Parameters:
  10945. //
  10946. // void
  10947. //
  10948. // Return value:
  10949. //
  10950. // TRUE/FALSE
  10951. //
  10952. // History:
  10953. //
  10954. // 6/16/00 weiruc Created
  10955. //
  10956. //*************************************************************
  10957. BOOL CSEntry::NoMoreUser()
  10958. {
  10959. return dwRef == 0;
  10960. }
  10961. //*************************************************************
  10962. //
  10963. // CSEntry::IncrementRefCount()
  10964. //
  10965. // Increment the reference count.
  10966. //
  10967. // Parameters:
  10968. //
  10969. // void
  10970. //
  10971. // Return value:
  10972. //
  10973. // void
  10974. //
  10975. // History:
  10976. //
  10977. // 8/24/00 santanuc Created
  10978. //
  10979. //*************************************************************
  10980. void CSEntry::IncrementRefCount()
  10981. {
  10982. dwRef++;
  10983. }
  10984. //*************************************************************
  10985. //
  10986. // CSEntry::SetRPCEndPoint()
  10987. //
  10988. // Store the RPCEndPoint. Memory freed by the ~CSEntry
  10989. //
  10990. // Parameters:
  10991. //
  10992. // lpRPCEndPoint
  10993. //
  10994. // Return value:
  10995. //
  10996. // void
  10997. //
  10998. // History:
  10999. //
  11000. // 8/24/00 santanuc Created
  11001. //
  11002. //*************************************************************
  11003. void CSEntry::SetRPCEndPoint(LPTSTR lpRPCEndPoint)
  11004. {
  11005. if (lpRPCEndPoint) {
  11006. szRPCEndPoint = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lpRPCEndPoint)+1)*sizeof(TCHAR));
  11007. if (szRPCEndPoint) {
  11008. lstrcpy(szRPCEndPoint, lpRPCEndPoint);
  11009. }
  11010. }
  11011. }
  11012. //*************************************************************
  11013. //
  11014. // EnterUserProfileLock()
  11015. //
  11016. // Get the user profile lock for a user
  11017. //
  11018. // Parameters:
  11019. //
  11020. // pSid - The user's sid string
  11021. //
  11022. // Return value:
  11023. //
  11024. // HRESULT
  11025. //
  11026. // History:
  11027. //
  11028. // 6/16/00 weiruc Created
  11029. //
  11030. //*************************************************************
  11031. DWORD WINAPI EnterUserProfileLock(LPTSTR pSid)
  11032. {
  11033. CSEntry* pEntry = NULL;
  11034. DWORD dwErr = ERROR_ACCESS_DENIED;
  11035. handle_t hIfUserProfile;
  11036. BOOL bBindInterface = FALSE;
  11037. if(cUserProfileManager.IsConsoleWinlogon()) {
  11038. if(!cUserProfileManager.EnterUserProfileLockLocal(pSid)) {
  11039. dwErr = GetLastError();
  11040. DebugMsg((DM_WARNING, TEXT("EnterUserProfileLock: GetUserProfileMutex returned %d"), dwErr));
  11041. goto Exit;
  11042. }
  11043. }
  11044. else {
  11045. if (!GetInterface(&hIfUserProfile, cszRPCEndPoint)) {
  11046. dwErr = GetLastError();
  11047. DebugMsg((DM_WARNING, TEXT("EnterUserProfileLock: GetInterface returned %d"), dwErr));
  11048. goto Exit;
  11049. }
  11050. bBindInterface = TRUE;
  11051. RpcTryExcept {
  11052. dwErr = cliEnterUserProfileLockRemote(hIfUserProfile, pSid);
  11053. }
  11054. RpcExcept(1) {
  11055. dwErr = RpcExceptionCode();
  11056. DebugMsg((DM_WARNING, TEXT("EnterUserProfileLock: EnterUserProfileLockRemote took exception error %d"), dwErr));
  11057. }
  11058. RpcEndExcept
  11059. if (dwErr != ERROR_SUCCESS) {
  11060. DebugMsg((DM_WARNING, TEXT("EnterUserProfileLock: EnterUserProfileLockRemote returned error %d"), dwErr));
  11061. goto Exit;
  11062. }
  11063. }
  11064. dwErr = ERROR_SUCCESS;
  11065. Exit:
  11066. if (bBindInterface) {
  11067. if (!ReleaseInterface(&hIfUserProfile)) {
  11068. DebugMsg((DM_WARNING, TEXT("EnterUserProfileLock: ReleaseInterface failed.")));
  11069. }
  11070. }
  11071. //
  11072. // Return.
  11073. //
  11074. SetLastError(dwErr);
  11075. return dwErr;
  11076. }
  11077. //*************************************************************
  11078. //
  11079. // LeaveUserProfileLock()
  11080. //
  11081. // Leave the user profile lock
  11082. //
  11083. // Parameters:
  11084. //
  11085. // pSid - The user's sid string
  11086. //
  11087. // Return value:
  11088. //
  11089. // HRESULT
  11090. //
  11091. // History:
  11092. //
  11093. // 6/16/00 weiruc Created
  11094. //
  11095. //*************************************************************
  11096. DWORD WINAPI LeaveUserProfileLock(LPTSTR pSid)
  11097. {
  11098. CSEntry* pEntry = NULL;
  11099. DWORD dwErr = ERROR_ACCESS_DENIED;
  11100. handle_t hIfUserProfile;
  11101. BOOL bBindInterface = FALSE;
  11102. if(cUserProfileManager.IsConsoleWinlogon()) {
  11103. cUserProfileManager.LeaveUserProfileLockLocal(pSid);
  11104. }
  11105. else {
  11106. if (!GetInterface(&hIfUserProfile, cszRPCEndPoint)) {
  11107. dwErr = GetLastError();
  11108. DebugMsg((DM_WARNING, TEXT("LeaveUserProfileLock: GetInterface returned %d"), dwErr));
  11109. goto Exit;
  11110. }
  11111. bBindInterface = TRUE;
  11112. RpcTryExcept {
  11113. dwErr = cliLeaveUserProfileLockRemote(hIfUserProfile, pSid);
  11114. }
  11115. RpcExcept(1) {
  11116. dwErr = RpcExceptionCode();
  11117. DebugMsg((DM_WARNING, TEXT("LeaveUserProfileLock: LeaveUserProfileLockRemote took exception error %d"), dwErr));
  11118. }
  11119. RpcEndExcept
  11120. if (dwErr != ERROR_SUCCESS) {
  11121. DebugMsg((DM_WARNING, TEXT("LeaveUserProfileLock: LeaveUserProfileLockRemote returned error %d"), dwErr));
  11122. goto Exit;
  11123. }
  11124. }
  11125. dwErr = ERROR_SUCCESS;
  11126. Exit:
  11127. if (bBindInterface) {
  11128. if (!ReleaseInterface(&hIfUserProfile)) {
  11129. DebugMsg((DM_WARNING, TEXT("LeaveUserProfileLock: ReleaseInterface failed.")));
  11130. }
  11131. }
  11132. //
  11133. // Return.
  11134. //
  11135. SetLastError(dwErr);
  11136. return dwErr;
  11137. }
  11138. //*************************************************************
  11139. //
  11140. // IsProfileInUse()
  11141. //
  11142. // Purpose: Determines if the given profile is currently in use
  11143. //
  11144. // Parameters: szComputer - Name of the machine
  11145. // lpSid - Sid (text) to test
  11146. //
  11147. // Return: TRUE if in use
  11148. // FALSE if not
  11149. //
  11150. // Comments:
  11151. //
  11152. // History: Date Author Comment
  11153. // 8/28/00 santanuc Created
  11154. //
  11155. //*************************************************************
  11156. BOOL IsProfileInUse (LPCTSTR szComputer, LPCTSTR lpSid)
  11157. {
  11158. LONG lResult;
  11159. HKEY hKeyUsers, hKeyProfile;
  11160. BOOL bRemoteReg = FALSE;
  11161. BOOL bRetVal = FALSE;
  11162. if (szComputer) {
  11163. lResult = RegConnectRegistry(szComputer, HKEY_USERS, &hKeyUsers);
  11164. if (lResult != ERROR_SUCCESS) {
  11165. DebugMsg((DM_WARNING, TEXT("IsProfileInUse: Failed to open remote registry %d"), lResult));
  11166. return TRUE;
  11167. }
  11168. bRemoteReg = TRUE;
  11169. }
  11170. else {
  11171. hKeyUsers = HKEY_USERS;
  11172. }
  11173. if (RegOpenKeyEx (hKeyUsers, lpSid, 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  11174. RegCloseKey (hKeyProfile);
  11175. bRetVal = TRUE;
  11176. }
  11177. else {
  11178. LPTSTR lpSidClasses;
  11179. lpSidClasses = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lpSid)+lstrlen(TEXT("_Classes"))+1)*sizeof(TCHAR));
  11180. if (lpSidClasses) {
  11181. lstrcpy(lpSidClasses, lpSid);
  11182. lstrcat(lpSidClasses, TEXT("_Classes"));
  11183. if (RegOpenKeyEx (hKeyUsers, lpSidClasses, 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  11184. RegCloseKey (hKeyProfile);
  11185. bRetVal = TRUE;
  11186. }
  11187. LocalFree(lpSidClasses);
  11188. }
  11189. }
  11190. if (bRemoteReg) {
  11191. RegCloseKey(hKeyUsers);
  11192. }
  11193. return bRetVal;
  11194. }
  11195. //*************************************************************
  11196. //
  11197. // IsUIRequired()
  11198. //
  11199. // Purpose: Determines if the profile error message requires
  11200. // If the ref count is > 1 then we do not required
  11201. // error reporting. If ref count is 1 then we check
  11202. //
  11203. //
  11204. // Parameters: hToken - User's token
  11205. //
  11206. // Return: TRUE if error message req
  11207. // FALSE if not
  11208. //
  11209. // Comments:
  11210. //
  11211. // History: Date Author Comment
  11212. // 10/27/00 santanuc Created
  11213. //
  11214. //*************************************************************
  11215. BOOL IsUIRequired(HANDLE hToken)
  11216. {
  11217. LPTSTR lpSidString = GetSidString(hToken);
  11218. BOOL bRetVal = FALSE;
  11219. TCHAR szBuffer[MAX_PATH];
  11220. LPTSTR lpEnd;
  11221. HKEY hKeyProfile;
  11222. DWORD dwType, dwFlags, dwRef, dwSize;
  11223. if (lpSidString) {
  11224. lstrcpy(szBuffer, PROFILE_LIST_PATH);
  11225. lpEnd = CheckSlash (szBuffer);
  11226. lstrcpy(lpEnd, lpSidString);
  11227. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  11228. dwSize = sizeof(DWORD);
  11229. if (RegQueryValueEx (hKeyProfile,
  11230. PROFILE_REF_COUNT,
  11231. NULL,
  11232. &dwType,
  11233. (LPBYTE) &dwRef,
  11234. &dwSize) == ERROR_SUCCESS) {
  11235. if (dwRef == 1) {
  11236. dwSize = sizeof(DWORD);
  11237. if (RegQueryValueEx (hKeyProfile,
  11238. PROFILE_FLAGS,
  11239. NULL,
  11240. &dwType,
  11241. (LPBYTE) &dwFlags,
  11242. &dwSize) == ERROR_SUCCESS) {
  11243. if (!(dwFlags & (PI_NOUI | PI_LITELOAD))) {
  11244. bRetVal = TRUE;
  11245. }
  11246. }
  11247. else {
  11248. DebugMsg((DM_WARNING, TEXT("IsUIRequired: Failed to query value for flags.")));
  11249. }
  11250. }
  11251. }
  11252. else {
  11253. DebugMsg((DM_WARNING, TEXT("IsUIRequired: Failed to query value for ref count.")));
  11254. }
  11255. RegCloseKey(hKeyProfile);
  11256. }
  11257. else {
  11258. DebugMsg((DM_WARNING, TEXT("IsUIRequired: Failed to open key %s"), szBuffer));
  11259. }
  11260. DeleteSidString(lpSidString);
  11261. }
  11262. return bRetVal;
  11263. }
  11264. //*************************************************************
  11265. //
  11266. // CheckRUPShare()
  11267. //
  11268. // Purpose: Determines if the RUP share is CSCed, if it is
  11269. // then issue an event log warning.
  11270. //
  11271. // Parameters: lpProfilePath - User's roaming profile path
  11272. //
  11273. // Return: None
  11274. //
  11275. // Comments:
  11276. //
  11277. //*************************************************************
  11278. void CheckRUPShare(LPTSTR lpProfilePath)
  11279. {
  11280. LPTSTR lpServer, lpShare, lpCopy;
  11281. PSHARE_INFO_1005 pBufPtr1, pBufPtr2;
  11282. BOOL bIssueWarning = FALSE;
  11283. if (!lpProfilePath || !IsUNCPath(lpProfilePath)) {
  11284. return;
  11285. }
  11286. lpCopy = (LPTSTR)LocalAlloc(LPTR, (lstrlen(lpProfilePath)+1) * sizeof(TCHAR));
  11287. if (!lpCopy) {
  11288. DebugMsg((DM_WARNING, TEXT("CheckRUPShare: Failed to allocate memory")));
  11289. return;
  11290. }
  11291. lstrcpy(lpCopy, lpProfilePath);
  11292. ConvertToShareName(lpCopy);
  11293. lpServer = lpCopy;
  11294. lpShare = lpCopy+2; // Skip initial two slashes
  11295. while (*lpShare != TCHAR('\\') && *lpShare != TCHAR('\0'))
  11296. lpShare++;
  11297. if (*lpShare == TCHAR('\\')) {
  11298. *lpShare = TCHAR('\0');
  11299. lpShare++;
  11300. if (NetShareGetInfo(lpServer, lpShare, 1005,
  11301. (LPBYTE *)&pBufPtr1) == ERROR_SUCCESS) {
  11302. if ((pBufPtr1->shi1005_flags & CSC_MASK) == CSC_CACHE_NONE) {
  11303. bIssueWarning = FALSE;
  11304. }
  11305. else if (pBufPtr1->shi1005_flags & SHI1005_FLAGS_DFS_ROOT) {
  11306. //
  11307. // If share is DFS root then we need to check the DfsLink to see
  11308. // whether csc is disabled on it
  11309. //
  11310. // Construct the dfs link
  11311. lstrcpy(lpCopy, lpProfilePath);
  11312. int iDfsLink = 0;
  11313. lpServer = lpCopy;
  11314. lpShare = lpCopy+2; // Skip initial two slashes
  11315. while ((iDfsLink < 3) && *lpShare != TCHAR('\0')) {
  11316. if (*lpShare == TCHAR('\\')) {
  11317. iDfsLink++;
  11318. }
  11319. lpShare++;
  11320. }
  11321. if (*lpShare != TCHAR('\0')) {
  11322. *(lpShare-1) = TCHAR('\0');
  11323. }
  11324. if (iDfsLink >= 2) {
  11325. PDFS_INFO_3 pDfsBuf;
  11326. // Query for the actual server and share
  11327. if (NetDfsGetInfo(lpServer, NULL, NULL, 3,
  11328. (LPBYTE *)&pDfsBuf) == NERR_Success) {
  11329. if (pDfsBuf->NumberOfStorages >= 1) {
  11330. lpServer = (LPTSTR)LocalAlloc(LPTR, (lstrlen(pDfsBuf->Storage->ServerName)+3) * sizeof(WCHAR));
  11331. if (!lpServer) {
  11332. DebugMsg((DM_WARNING, TEXT("CheckRUPShare: Failed to allocate memory")));
  11333. goto Exit;
  11334. }
  11335. lstrcpy(lpServer, TEXT("\\\\"));
  11336. lstrcat(lpServer, pDfsBuf->Storage->ServerName);
  11337. // Get csc information from actual server and share
  11338. if (NetShareGetInfo(lpServer, pDfsBuf->Storage->ShareName, 1005,
  11339. (LPBYTE *)&pBufPtr2) == ERROR_SUCCESS) {
  11340. if ((pBufPtr2->shi1005_flags & CSC_MASK) == CSC_CACHE_NONE) {
  11341. bIssueWarning = FALSE;
  11342. }
  11343. else {
  11344. bIssueWarning = TRUE;
  11345. }
  11346. NetApiBufferFree(pBufPtr2);
  11347. }
  11348. LocalFree(lpServer);
  11349. }
  11350. NetApiBufferFree(pDfsBuf);
  11351. }
  11352. }
  11353. }
  11354. else {
  11355. bIssueWarning = TRUE;
  11356. }
  11357. NetApiBufferFree(pBufPtr1);
  11358. if (bIssueWarning) {
  11359. ReportError(NULL, PI_NOUI | EVENT_WARNING_TYPE, 0, EVENT_CSC_ON_PROFILE_SHARE);
  11360. }
  11361. }
  11362. }
  11363. Exit:
  11364. LocalFree(lpCopy);
  11365. }
  11366. //*************************************************************
  11367. //
  11368. // IsPartialRoamingProfile()
  11369. //
  11370. // Purpose: determines if roaming profile contains a partial
  11371. // copy or not. This is indicated by setting a flag
  11372. // in ntuser.ini.
  11373. //
  11374. // Parameters: lpProfile - User's profile
  11375. //
  11376. // Return: TRUE : If Roaming profile contains a Partial
  11377. // profile due to LITE_LOAD unload.
  11378. // FALSE: otherwise.
  11379. //
  11380. // Comments:
  11381. //
  11382. //*************************************************************
  11383. BOOL IsPartialRoamingProfile(LPPROFILE lpProfile)
  11384. {
  11385. TCHAR szLastUploadState[20];
  11386. LPTSTR szNTUserIni = NULL;
  11387. LPTSTR lpEnd;
  11388. BOOL bRetVal = FALSE;
  11389. //
  11390. // Allocate memory for Local variables to avoid stack overflow
  11391. //
  11392. szNTUserIni = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  11393. if (!szNTUserIni) {
  11394. DebugMsg((DM_WARNING, TEXT("IsPartialRoamingProfile: Out of memory")));
  11395. goto Exit;
  11396. }
  11397. lstrcpy (szNTUserIni, lpProfile->lpRoamingProfile);
  11398. lpEnd = CheckSlash (szNTUserIni);
  11399. lstrcpy (lpEnd, c_szNTUserIni);
  11400. GetPrivateProfileString (PROFILE_LOAD_TYPE,
  11401. PROFILE_LAST_UPLOAD_STATE,
  11402. COMPLETE_PROFILE, szLastUploadState,
  11403. ARRAYSIZE(szLastUploadState),
  11404. szNTUserIni);
  11405. if (lstrcmpi(szLastUploadState, PARTIAL_PROFILE) == 0) {
  11406. bRetVal = TRUE;
  11407. }
  11408. Exit:
  11409. if (szNTUserIni)
  11410. LocalFree(szNTUserIni);
  11411. return bRetVal;
  11412. }
  11413. //*************************************************************
  11414. //
  11415. // TouchLocalHive()
  11416. //
  11417. // Purpose: Check whether in local machine user profile is
  11418. // switching from local to roaming for first time. If
  11419. // yes and we have a existing hive in RUP share then
  11420. // always overwrite the local hive with hive in RUP
  11421. // share. This is to avoid wrong hive usage due to
  11422. // cached login.
  11423. //
  11424. //
  11425. // Parameters: lpProfile - User's profile
  11426. //
  11427. // Return: None
  11428. //
  11429. // Comments:
  11430. //
  11431. //*************************************************************
  11432. void TouchLocalHive(LPPROFILE lpProfile)
  11433. {
  11434. LPTSTR szBuffer = NULL, lpEnd;
  11435. LPTSTR SidString = NULL;
  11436. HKEY hKey = NULL;
  11437. HANDLE hFile = NULL;
  11438. DWORD dwSize, dwType;
  11439. LONG lResult;
  11440. const LONGLONG datetime1980 = 0x01A8E79FE1D58000; // 1/1/80, origin of DOS datetime
  11441. union {
  11442. FILETIME ft;
  11443. LONGLONG datetime;
  11444. };
  11445. if ((lpProfile->dwInternalFlags & PROFILE_NEW_CENTRAL) ||
  11446. (lpProfile->dwInternalFlags & PROFILE_MANDATORY)) {
  11447. goto Exit;
  11448. }
  11449. //
  11450. // Set the time to base
  11451. //
  11452. datetime = datetime1980;
  11453. //
  11454. // Allocate local buffer
  11455. //
  11456. szBuffer = (LPTSTR) LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR));
  11457. if (!szBuffer) {
  11458. DebugMsg((DM_WARNING, TEXT("TouchLocalHive: Out of memory")));
  11459. goto Exit;
  11460. }
  11461. //
  11462. // Get the Sid string for the user
  11463. //
  11464. SidString = GetSidString(lpProfile->hTokenUser);
  11465. if (!SidString) {
  11466. DebugMsg((DM_WARNING, TEXT("TouchLocalHive: Failed to get sid string for user")));
  11467. goto Exit;
  11468. }
  11469. //
  11470. // Open the profile mapping
  11471. //
  11472. lstrcpy(szBuffer, PROFILE_LIST_PATH);
  11473. lpEnd = CheckSlash (szBuffer);
  11474. lstrcpy(lpEnd, SidString);
  11475. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0,
  11476. KEY_READ, &hKey);
  11477. if (lResult != ERROR_SUCCESS) {
  11478. DebugMsg((DM_WARNING, TEXT("TouchLocalHive: Failed to open profile mapping key with error %d"), lResult));
  11479. goto Exit;
  11480. }
  11481. //
  11482. // Query for the central profile path
  11483. //
  11484. dwSize = MAX_PATH * sizeof(TCHAR);
  11485. lResult = RegQueryValueEx (hKey,
  11486. PROFILE_CENTRAL_PROFILE,
  11487. NULL,
  11488. &dwType,
  11489. (LPBYTE) szBuffer,
  11490. &dwSize);
  11491. if (lResult != ERROR_SUCCESS) {
  11492. DebugMsg((DM_VERBOSE, TEXT("TouchLocalHive: Failed to query central profile with error %d"), lResult));
  11493. goto Exit;
  11494. }
  11495. if (szBuffer[0] == TEXT('\0')) {
  11496. //
  11497. // So we are switching from local to roaming profile for first time
  11498. //
  11499. //
  11500. // Make sure we don't overrun our temporary buffer
  11501. //
  11502. if ((lstrlen(lpProfile->lpLocalProfile) + 1 + lstrlen(c_szNTUserDat) + 1) > MAX_PATH) {
  11503. DebugMsg((DM_VERBOSE, TEXT("TouchLocalHive: Failed because temporary buffer is too small.")));
  11504. goto Exit;
  11505. }
  11506. //
  11507. // Copy the local profile path to a temporary buffer
  11508. // we can munge it.
  11509. //
  11510. lstrcpy (szBuffer, lpProfile->lpLocalProfile);
  11511. //
  11512. // Add the slash if appropriate and then tack on
  11513. // ntuser.dat.
  11514. //
  11515. lpEnd = CheckSlash(szBuffer);
  11516. lstrcpy(lpEnd, c_szNTUserDat);
  11517. //
  11518. // See if this file exists
  11519. //
  11520. DebugMsg((DM_VERBOSE, TEXT("TouchLocalHive: Testing <%s>"), szBuffer));
  11521. hFile = CreateFile(szBuffer, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  11522. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  11523. if (hFile != INVALID_HANDLE_VALUE) {
  11524. DebugMsg((DM_VERBOSE, TEXT("TouchLocalHive: Found a user hive.")));
  11525. //
  11526. // Set the local hive time to base i.e 1/1/1980, so that RUP hive
  11527. // overwrites this hive during profile merge
  11528. //
  11529. if (SetFileTime(hFile, NULL, NULL, &ft)) {
  11530. DebugMsg((DM_VERBOSE, TEXT("TouchLocalHive: Touched user hive.")));
  11531. }
  11532. else {
  11533. DebugMsg((DM_WARNING, TEXT("TouchLocalHive: Fail to touch user hive.")));
  11534. }
  11535. CloseHandle(hFile);
  11536. }
  11537. }
  11538. Exit:
  11539. if (szBuffer) {
  11540. LocalFree(szBuffer);
  11541. }
  11542. if (SidString) {
  11543. DeleteSidString(SidString);
  11544. }
  11545. if (hKey) {
  11546. RegCloseKey(hKey);
  11547. }
  11548. }
  11549. //*************************************************************
  11550. //
  11551. // RegisterDialogInterface()
  11552. //
  11553. // Purpose: Registers IProfileDialog interface
  11554. //
  11555. // Parameters: szRPCEndPoint - RPCEndPoint name
  11556. //
  11557. // Return: TRUE if successfully registered
  11558. // FALSE if not
  11559. //
  11560. // Comments:
  11561. //
  11562. // History: Date Author Comment
  11563. // 10/27/00 santanuc Created
  11564. //
  11565. //*************************************************************
  11566. BOOL RegisterDialogInterface(LPTSTR szRPCEndPoint)
  11567. {
  11568. RPC_STATUS status = RPC_S_OK;
  11569. //
  11570. // Specify to use the local rpc protocol sequence
  11571. //
  11572. status = RpcServerUseProtseqEp(cszRPCProtocol,
  11573. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  11574. szRPCEndPoint,
  11575. NULL); // Security descriptor
  11576. if (status != RPC_S_OK && status != RPC_S_DUPLICATE_ENDPOINT) {
  11577. DebugMsg((DM_WARNING, TEXT("RegisterErrorDialogInterface: RpcServerUseProtseqEp fails with error %ld"), status));
  11578. goto Exit;
  11579. }
  11580. //
  11581. // Register the IUserProfile interface
  11582. //
  11583. status = RpcServerRegisterIfEx(IProfileDialog_v1_0_s_ifspec, // interface to register
  11584. NULL, // MgrTypeUuid
  11585. NULL, // MgrEpv; null means use default
  11586. RPC_IF_AUTOLISTEN, // auto-listen interface
  11587. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // max concurrent calls
  11588. NULL); // no callback
  11589. if (status != RPC_S_OK) {
  11590. DebugMsg((DM_WARNING, TEXT("RegisterErrorDialogInterface: RpcServerRegisterIfEx fails with error %ld"), status));
  11591. }
  11592. Exit:
  11593. return (status == RPC_S_OK);
  11594. }
  11595. //*************************************************************
  11596. //
  11597. // UnRegisterDialogInterface()
  11598. //
  11599. // Purpose: UnRegisters IProfileDialog interface
  11600. //
  11601. // Parameters:
  11602. //
  11603. // Return: TRUE if successfully unregistered
  11604. // FALSE if not
  11605. //
  11606. // Comments:
  11607. //
  11608. // History: Date Author Comment
  11609. // 10/27/00 santanuc Created
  11610. //
  11611. //*************************************************************
  11612. BOOL UnRegisterDialogInterface(void)
  11613. {
  11614. RPC_STATUS status = RPC_S_OK;
  11615. // unregister the server endpoint
  11616. status = RpcServerUnregisterIf(IProfileDialog_v1_0_s_ifspec, NULL, TRUE);
  11617. if (status != RPC_S_OK) {
  11618. DebugMsg((DM_WARNING, TEXT("UnRegisterErrorDialogInterface: RpcServerUnregisterIf fails with error %ld"), status));
  11619. }
  11620. return (status == RPC_S_OK);
  11621. }
  11622. //*************************************************************
  11623. //
  11624. // ErrorDialog()
  11625. //
  11626. // Purpose: ErrorDialog api of IProfileDialog interface
  11627. // Display error message on client's desktop
  11628. //
  11629. // Parameters:
  11630. //
  11631. // Return: void
  11632. //
  11633. // Comments:
  11634. //
  11635. // History: Date Author Comment
  11636. // 10/27/00 santanuc Created
  11637. //
  11638. //*************************************************************
  11639. void ErrorDialog(IN PRPC_ASYNC_STATE pAsync, IN handle_t hBindHandle, IN DWORD dwTimeOut, IN LPTSTR lpErrMsg)
  11640. {
  11641. DWORD dwRetVal = ERROR_SUCCESS;
  11642. ErrorDialogEx(dwTimeOut, lpErrMsg);
  11643. RpcAsyncCompleteCall(pAsync, (PVOID)&dwRetVal);
  11644. }
  11645. //*************************************************************
  11646. //
  11647. // SlowLinkDialog()
  11648. //
  11649. // Purpose: SlowLinkDialog api of IProfileDialog interface
  11650. // Display SlowLink message on client's desktop
  11651. //
  11652. // Parameters:
  11653. //
  11654. // Return: void
  11655. //
  11656. // Comments:
  11657. //
  11658. // History: Date Author Comment
  11659. // 10/27/00 santanuc Created
  11660. //
  11661. //*************************************************************
  11662. void SlowLinkDialog(IN PRPC_ASYNC_STATE pAsync, IN handle_t hBindHandle, IN DWORD dwTimeOut, IN BOOL bDefault, OUT BOOL *bpResponse, IN BOOL bDlgLogin)
  11663. {
  11664. SLOWLINKDLGINFO info;
  11665. DWORD dwRetVal = ERROR_SUCCESS;
  11666. info.dwTimeout = dwTimeOut;
  11667. info.bSyncDefault = bDefault;
  11668. DebugMsg((DM_VERBOSE, TEXT("SlowLinkDialog: Calling DialogBoxParam")));
  11669. if (bDlgLogin) {
  11670. *bpResponse = (BOOL)DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_LOGIN_SLOW_LINK),
  11671. NULL, LoginSlowLinkDlgProc, (LPARAM)&info);
  11672. }
  11673. else {
  11674. *bpResponse = (BOOL)DialogBoxParam (g_hDllInstance, MAKEINTRESOURCE(IDD_LOGOFF_SLOW_LINK),
  11675. NULL, LogoffSlowLinkDlgProc, (LPARAM)&info);
  11676. }
  11677. RpcAsyncCompleteCall(pAsync, (PVOID)&dwRetVal);
  11678. }
  11679. //
  11680. // RPC routines
  11681. //
  11682. void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t count)
  11683. {
  11684. DebugMsg((DM_VERBOSE, TEXT("MIDL_user_allocate enter")));
  11685. return(malloc(count));
  11686. }
  11687. void __RPC_USER MIDL_user_free(void __RPC_FAR * p)
  11688. {
  11689. DebugMsg((DM_VERBOSE, TEXT("MIDL_user_free enter")));
  11690. free(p);
  11691. }
  11692. void __RPC_USER PCONTEXT_HANDLE_rundown (PCONTEXT_HANDLE phContext)
  11693. {
  11694. DebugMsg((DM_VERBOSE, TEXT("PCONTEXT_HANDLE_rundown : Client died with open context")));
  11695. ReleaseClientContext_s(&phContext);
  11696. }
  11697. //******************************************************************************
  11698. //
  11699. // CheckRoamingShareOwnership()
  11700. //
  11701. // Purpose: Check the ownership of the roaming user's profile on the server.
  11702. // If the owner is not the user or not an admin, this function will
  11703. // fail, and an error message will be issued. Administrator can set
  11704. // a policy "CompatibleRUPSecurity" to disable this check.
  11705. //
  11706. // Parameters:
  11707. // lpDir - profile directory on the server
  11708. // hTokenUser - user's token
  11709. //
  11710. // Return: S_OK on success, else for failure
  11711. //
  11712. // Comments:
  11713. //
  11714. // History: Date Author Comment
  11715. // 03/21/2002 mingzhu Created
  11716. //
  11717. //******************************************************************************
  11718. HRESULT CheckRoamingShareOwnership(LPTSTR lpDir, HANDLE hTokenUser)
  11719. {
  11720. HRESULT hr = E_FAIL;
  11721. BOOL bDisableCheck = FALSE;
  11722. HKEY hSubKey = NULL;
  11723. DWORD dwRegValue;
  11724. DWORD dwSize;
  11725. DWORD dwType;
  11726. DWORD cbSD;
  11727. BOOL bDefaultOwner;
  11728. DWORD dwErr;
  11729. PSID pSidAdmin = NULL;
  11730. PSID pSidUser = NULL;
  11731. PSID pSidOwner = NULL;
  11732. PSECURITY_DESCRIPTOR psd = NULL;
  11733. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  11734. //
  11735. // Output a debug message for entering the function.
  11736. //
  11737. DebugMsg((DM_VERBOSE, TEXT("CheckRoamingShareOwnership: checking ownership for %s"), lpDir));
  11738. //
  11739. // Check for the policy to see if this check has been disabled
  11740. //
  11741. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
  11742. {
  11743. dwSize = sizeof(dwRegValue);
  11744. if (RegQueryValueEx(hSubKey, TEXT("CompatibleRUPSecurity"), NULL, &dwType, (LPBYTE) &dwRegValue, &dwSize) == ERROR_SUCCESS)
  11745. {
  11746. bDisableCheck = (BOOL)(dwRegValue);
  11747. }
  11748. RegCloseKey(hSubKey);
  11749. }
  11750. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
  11751. {
  11752. dwSize = sizeof(dwRegValue);
  11753. if (RegQueryValueEx(hSubKey, TEXT("CompatibleRUPSecurity"), NULL, &dwType, (LPBYTE) &dwRegValue, &dwSize) == ERROR_SUCCESS)
  11754. {
  11755. bDisableCheck = (BOOL)(dwRegValue);
  11756. }
  11757. RegCloseKey(hSubKey);
  11758. }
  11759. if (bDisableCheck)
  11760. {
  11761. DebugMsg((DM_VERBOSE, TEXT("CheckRoamingShareOwnership: policy set to disable ownership check")));
  11762. hr = S_OK;
  11763. goto Exit;
  11764. }
  11765. //
  11766. // Get the security of the directory, should fail with ERROR_INSUFFICIENT_BUFFER
  11767. //
  11768. GetFileSecurity(lpDir, OWNER_SECURITY_INFORMATION, NULL, 0, &cbSD);
  11769. dwErr = GetLastError();
  11770. if (dwErr != ERROR_INSUFFICIENT_BUFFER)
  11771. {
  11772. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership : GetFileSecurity failed with %d"), dwErr));
  11773. hr = HRESULT_FROM_WIN32(dwErr);
  11774. goto Exit;
  11775. }
  11776. //
  11777. // Allocate memory for SD
  11778. //
  11779. psd = (PSECURITY_DESCRIPTOR) LocalAlloc (LPTR, cbSD);
  11780. if (!psd)
  11781. {
  11782. dwErr = GetLastError();
  11783. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership : LocalAlloc failed with %d"), dwErr));
  11784. hr = HRESULT_FROM_WIN32(dwErr);
  11785. goto Exit;
  11786. }
  11787. //
  11788. // Try it again
  11789. //
  11790. if (!GetFileSecurity(lpDir, OWNER_SECURITY_INFORMATION, psd, cbSD, &cbSD))
  11791. {
  11792. dwErr = GetLastError();
  11793. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership : GetFileSecurity failed with %d"), dwErr));
  11794. hr = HRESULT_FROM_WIN32(dwErr);
  11795. goto Exit;
  11796. }
  11797. //
  11798. // Get the owner in SD
  11799. //
  11800. if (!GetSecurityDescriptorOwner(psd, &pSidOwner, &bDefaultOwner))
  11801. {
  11802. dwErr = GetLastError();
  11803. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership: Failed to get security descriptor owner. Error = %d"), dwErr));
  11804. hr = HRESULT_FROM_WIN32(dwErr);
  11805. goto Exit;
  11806. }
  11807. //
  11808. // Get the Admin sid
  11809. //
  11810. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  11811. 0, 0, 0, 0, 0, 0, &pSidAdmin))
  11812. {
  11813. dwErr = GetLastError();
  11814. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership: Failed to initialize admin sid. Error = %d"), dwErr));
  11815. hr = HRESULT_FROM_WIN32(dwErr);
  11816. goto Exit;
  11817. }
  11818. //
  11819. // Get the user sid
  11820. //
  11821. pSidUser = GetUserSid(hTokenUser);
  11822. if (pSidUser == NULL)
  11823. {
  11824. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership: GetUserSid returned NULL")));
  11825. hr = E_FAIL;
  11826. goto Exit;
  11827. }
  11828. //
  11829. // Check the owner
  11830. //
  11831. if (EqualSid(pSidAdmin, pSidOwner))
  11832. {
  11833. DebugMsg((DM_VERBOSE, TEXT("CheckRoamingShareOwnership: owner is admin")));
  11834. hr = S_OK;
  11835. }
  11836. else if (EqualSid(pSidUser, pSidOwner))
  11837. {
  11838. DebugMsg((DM_VERBOSE, TEXT("CheckRoamingShareOwnership: owner is the right user")));
  11839. hr = S_OK;
  11840. }
  11841. else
  11842. {
  11843. LPTSTR lpSidOwner = NULL;
  11844. if (ConvertSidToStringSid(pSidOwner, &lpSidOwner))
  11845. {
  11846. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership: owner is %s!"), lpSidOwner));
  11847. LocalFree(lpSidOwner);
  11848. }
  11849. else
  11850. {
  11851. DebugMsg((DM_WARNING, TEXT("CheckRoamingShareOwnership: owner is someone else!")));
  11852. }
  11853. hr = HRESULT_FROM_WIN32(ERROR_INVALID_OWNER);
  11854. }
  11855. Exit:
  11856. if (psd)
  11857. {
  11858. LocalFree(psd);
  11859. }
  11860. if (pSidAdmin)
  11861. {
  11862. FreeSid(pSidAdmin);
  11863. }
  11864. if (pSidUser)
  11865. {
  11866. DeleteUserSid(pSidUser);
  11867. }
  11868. return hr;
  11869. }