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.

3928 lines
97 KiB

  1. //*************************************************************
  2. //
  3. // Profile.c - User Profile tab
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1996
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include "sysdm.h"
  14. #include <shellapi.h>
  15. #include <shlobj.h>
  16. #include <shlobjp.h>
  17. #include <userenv.h>
  18. #include <userenvp.h>
  19. #include <getuser.h>
  20. #include <objsel.h>
  21. #define TEMP_PROFILE TEXT("Temp profile (sysdm.cpl)")
  22. #define USER_CRED_LOCATION TEXT("Application Data\\Microsoft\\Credentials")
  23. #define PROFILE_MAPPING TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList")
  24. #define WINLOGON_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon")
  25. #define SYSTEM_POLICIES_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\System")
  26. #define READONLY_RUP TEXT("ReadOnlyProfile")
  27. #define PROFILE_LOCALONLY TEXT("LocalProfile")
  28. #define PRF_USERSID 1
  29. //
  30. // Globals
  31. //
  32. const TCHAR c_szNTUserIni[] = TEXT("ntuser.ini");
  33. #define PROFILE_GENERAL_SECTION TEXT("General")
  34. #define PROFILE_EXCLUSION_LIST TEXT("ExclusionList")
  35. DWORD g_dwProfileSize;
  36. //
  37. // Help ID's
  38. //
  39. // IDH_USERPROFILE + 20 is used in the OpenUserBrowser routine.
  40. //
  41. DWORD aUserProfileHelpIds[] = {
  42. IDC_UP_LISTVIEW, (IDH_USERPROFILE + 0),
  43. IDC_UP_DELETE, (IDH_USERPROFILE + 1),
  44. IDC_UP_TYPE, (IDH_USERPROFILE + 2),
  45. IDC_UP_COPY, (IDH_USERPROFILE + 3),
  46. IDC_UP_ICON, (DWORD) -1,
  47. IDC_UP_TEXT, (DWORD) -1,
  48. // Change Type dialog
  49. IDC_UPTYPE_LOCAL, (IDH_USERPROFILE + 4),
  50. IDC_UPTYPE_FLOAT, (IDH_USERPROFILE + 5),
  51. // removed IDC_UPTYPE_SLOW, IDC_UPTYPE_SLOW_TEXT
  52. IDC_UPTYPE_GROUP, (IDH_USERPROFILE + 12),
  53. // Copy To dialog
  54. IDC_COPY_PROFILE, (IDH_USERPROFILE + 7),
  55. IDC_COPY_PATH, (IDH_USERPROFILE + 7),
  56. IDC_COPY_BROWSE, (IDH_USERPROFILE + 8),
  57. IDC_COPY_USER, (IDH_USERPROFILE + 9),
  58. IDC_COPY_CHANGE, (IDH_USERPROFILE + 10),
  59. IDC_COPY_GROUP, (IDH_USERPROFILE + 9),
  60. 0, 0
  61. };
  62. //
  63. // Local function proto-types
  64. //
  65. BOOL InitUserProfileDlg (HWND hDlg, LPARAM lParam);
  66. BOOL FillListView (HWND hDlg, BOOL bAdmin);
  67. LPTSTR CheckSlash (LPTSTR lpDir);
  68. BOOL RecurseDirectory (LPTSTR lpDir, LPTSTR lpExcludeList);
  69. VOID UPSave (HWND hDlg);
  70. VOID UPCleanUp (HWND hDlg);
  71. BOOL IsProfileInUse (LPTSTR lpSid);
  72. void UPDoItemChanged(HWND hDlg, int idCtl);
  73. void UPDeleteProfile(HWND hDlg);
  74. void UPChangeType(HWND hDlg);
  75. void UPOnLink(WPARAM wParam);
  76. INT_PTR APIENTRY ChangeTypeDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  77. void UPCopyProfile(HWND hDlg);
  78. INT_PTR APIENTRY UPCopyDlgProc (HWND hDlg, UINT uMsg,WPARAM wParam, LPARAM lParam);
  79. BOOL UPCreateProfile (HWND hDlg, LPUPCOPYINFO lpUPCopyInfo, LPTSTR lpDest, PSECURITY_DESCRIPTOR pSecDesc);
  80. VOID UPDisplayErrorMessage(HWND hWnd, UINT uiSystemError, LPTSTR szMsgPrefix);
  81. BOOL ApplyHiveSecurity(LPTSTR lpHiveName, PSID pSid);
  82. LPTSTR CheckSemicolon (LPTSTR lpDir);
  83. LPTSTR ConvertExclusionList (LPCTSTR lpSourceDir, LPCTSTR lpExclusionList);
  84. BOOL ReadExclusionList(LPTSTR szExcludeList, DWORD dwExclSize);
  85. BOOL ReadExclusionListFromIniFile(LPCTSTR lpSourceDir, LPTSTR szExcludeList, DWORD dwExclSize);
  86. HRESULT UPGetUserSelection(HWND hDlg, LPUSERDETAILS lpUserDetails);
  87. BOOL ConfirmDirectory(HWND hDlg, LPTSTR szDir);
  88. //*************************************************************
  89. //
  90. // UserProfileDlgProc()
  91. //
  92. // Purpose: Dialog box procedure for profile tab
  93. //
  94. // Parameters: hDlg - handle to the dialog box
  95. // uMsg - window message
  96. // wParam - wParam
  97. // lParam - lParam
  98. //
  99. // Return: TRUE if message was processed
  100. // FALSE if not
  101. //
  102. // Comments:
  103. //
  104. // History: Date Author Comment
  105. // 10/11/95 ericflo Created
  106. //
  107. //*************************************************************
  108. INT_PTR APIENTRY UserProfileDlgProc (HWND hDlg, UINT uMsg,
  109. WPARAM wParam, LPARAM lParam)
  110. {
  111. switch (uMsg) {
  112. case WM_INITDIALOG:
  113. if (!InitUserProfileDlg (hDlg, lParam)) {
  114. EndDialog(hDlg, FALSE);
  115. }
  116. return TRUE;
  117. case WM_NOTIFY:
  118. switch (((NMHDR FAR*)lParam)->code)
  119. {
  120. case LVN_ITEMCHANGED:
  121. UPDoItemChanged(hDlg, (int) wParam);
  122. break;
  123. case LVN_ITEMACTIVATE:
  124. PostMessage (hDlg, WM_COMMAND, IDC_UP_TYPE, 0);
  125. break;
  126. case LVN_COLUMNCLICK:
  127. break;
  128. case NM_CLICK:
  129. case NM_RETURN:
  130. UPOnLink(wParam);
  131. break;
  132. default:
  133. return FALSE;
  134. }
  135. break;
  136. case WM_DESTROY:
  137. UPCleanUp (hDlg);
  138. break;
  139. case WM_COMMAND:
  140. switch (LOWORD(wParam)) {
  141. case IDC_UP_DELETE:
  142. UPDeleteProfile(hDlg);
  143. break;
  144. case IDC_UP_TYPE:
  145. UPChangeType(hDlg);
  146. break;
  147. case IDC_UP_COPY:
  148. UPCopyProfile(hDlg);
  149. break;
  150. case IDOK:
  151. UPSave(hDlg);
  152. EndDialog(hDlg, FALSE);
  153. break;
  154. case IDCANCEL:
  155. EndDialog(hDlg, FALSE);
  156. break;
  157. default:
  158. break;
  159. }
  160. break;
  161. case WM_HELP: // F1
  162. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  163. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  164. break;
  165. case WM_CONTEXTMENU: // right mouse click
  166. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  167. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  168. return (TRUE);
  169. }
  170. return (FALSE);
  171. }
  172. //*************************************************************
  173. //
  174. // InitUserProfileDlg()
  175. //
  176. // Purpose: Initializes the User Profiles page
  177. //
  178. // Parameters: hDlg - Dialog box handle
  179. //
  180. // Return: TRUE if successful
  181. // FALSE if an error occurs
  182. //
  183. // Comments:
  184. //
  185. // History: Date Author Comment
  186. // 1/26/96 ericflo Created
  187. //
  188. //*************************************************************
  189. BOOL InitUserProfileDlg (HWND hDlg, LPARAM lParam)
  190. {
  191. TCHAR szHeaderName[30];
  192. LV_COLUMN col;
  193. RECT rc;
  194. HWND hLV;
  195. INT iTotal = 0, iCurrent;
  196. HWND hwndTemp;
  197. BOOL bAdmin;
  198. HCURSOR hOldCursor;
  199. hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  200. hLV = GetDlgItem(hDlg, IDC_UP_LISTVIEW);
  201. // Set extended LV style for whole line selection
  202. SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  203. //
  204. // Insert Columns
  205. //
  206. GetClientRect (hLV, &rc);
  207. LoadString(hInstance, IDS_UP_NAME, szHeaderName, 30);
  208. col.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  209. col.fmt = LVCFMT_LEFT;
  210. iCurrent = (int)(rc.right * .40);
  211. iTotal += iCurrent;
  212. col.cx = iCurrent;
  213. col.pszText = szHeaderName;
  214. col.iSubItem = 0;
  215. ListView_InsertColumn (hLV, 0, &col);
  216. LoadString(hInstance, IDS_UP_SIZE, szHeaderName, 30);
  217. iCurrent = (int)(rc.right * .15);
  218. iTotal += iCurrent;
  219. col.cx = iCurrent;
  220. col.fmt = LVCFMT_RIGHT;
  221. col.iSubItem = 1;
  222. ListView_InsertColumn (hLV, 1, &col);
  223. LoadString(hInstance, IDS_UP_TYPE, szHeaderName, 30);
  224. col.iSubItem = 2;
  225. iCurrent = (int)(rc.right * .15);
  226. iTotal += iCurrent;
  227. col.cx = iCurrent;
  228. col.fmt = LVCFMT_LEFT;
  229. ListView_InsertColumn (hLV, 2, &col);
  230. LoadString(hInstance, IDS_UP_STATUS, szHeaderName, 30);
  231. col.iSubItem = 3;
  232. iCurrent = (int)(rc.right * .15);
  233. iTotal += iCurrent;
  234. col.cx = iCurrent;
  235. col.fmt = LVCFMT_LEFT;
  236. ListView_InsertColumn (hLV, 3, &col);
  237. LoadString(hInstance, IDS_UP_MOD, szHeaderName, 30);
  238. col.iSubItem = 4;
  239. col.cx = rc.right - iTotal - GetSystemMetrics(SM_CYHSCROLL);
  240. col.fmt = LVCFMT_LEFT;
  241. ListView_InsertColumn (hLV, 4, &col);
  242. bAdmin = IsUserAdmin();
  243. if (!bAdmin) {
  244. RECT rc;
  245. POINT pt;
  246. //
  247. // If the user is not an admin, then we hide the
  248. // delete and copy to buttons
  249. //
  250. hwndTemp = GetDlgItem (hDlg, IDC_UP_DELETE);
  251. GetWindowRect (hwndTemp, &rc);
  252. EnableWindow (hwndTemp, FALSE);
  253. ShowWindow (hwndTemp, SW_HIDE);
  254. hwndTemp = GetDlgItem (hDlg, IDC_UP_COPY);
  255. EnableWindow (hwndTemp, FALSE);
  256. ShowWindow (hwndTemp, SW_HIDE);
  257. //
  258. // Move the Change Type button over
  259. //
  260. pt.x = rc.left;
  261. pt.y = rc.top;
  262. ScreenToClient (hDlg, &pt);
  263. SetWindowPos (GetDlgItem (hDlg, IDC_UP_TYPE),
  264. HWND_TOP, pt.x, pt.y, 0, 0,
  265. SWP_NOSIZE | SWP_NOZORDER);
  266. }
  267. if (IsOS(OS_ANYSERVER))
  268. {
  269. //
  270. // Adjust the text displayed for the Users & Passwords link.
  271. // There is no Control Panel applet per se on Server. The functionality
  272. // is accessed through MMC.
  273. //
  274. TCHAR szTitle[80];
  275. if (0 < LoadString(hInstance, IDS_UP_UPLINK_SERVER, szTitle, ARRAYSIZE(szTitle)))
  276. {
  277. SetWindowText(GetDlgItem(hDlg, IDC_UP_UPLINK), szTitle);
  278. }
  279. }
  280. //
  281. // Fill the user accounts
  282. //
  283. if (!FillListView (hDlg, bAdmin)) {
  284. SetCursor(hOldCursor);
  285. return FALSE;
  286. }
  287. SetCursor(hOldCursor);
  288. return TRUE;
  289. }
  290. //*************************************************************
  291. //
  292. // AddUser()
  293. //
  294. // Purpose: Adds a new user to the listview
  295. //
  296. //
  297. // Parameters: hDlg - handle to the dialog box
  298. // lpSid - Sid (text form)
  299. //
  300. //
  301. // Return: TRUE if successful
  302. // FALSE if an error occurs
  303. //
  304. // Comments:
  305. //
  306. // History: Date Author Comment
  307. // 1/26/96 ericflo Created
  308. //
  309. //*************************************************************
  310. BOOL AddUser (HWND hDlg, LPTSTR lpSid, DWORD dwFlags)
  311. {
  312. LONG Error;
  313. HKEY hKeyPolicy, hKeyProfile;
  314. TCHAR szBuffer[2*MAX_PATH];
  315. TCHAR szBuffer2[MAX_PATH];
  316. TCHAR szTemp[100];
  317. TCHAR szTemp2[100];
  318. DWORD dwTempSize = 100, dwTemp2Size = 100;
  319. PSID pSid;
  320. DWORD dwSize, dwType, dwProfileFlags;
  321. SID_NAME_USE SidName;
  322. LV_ITEM item;
  323. INT iItem;
  324. HWND hwndTemp;
  325. HKEY hkeyUser;
  326. HANDLE hFile;
  327. WIN32_FIND_DATA fd;
  328. LPTSTR lpEnd;
  329. SYSTEMTIME systime;
  330. FILETIME ftLocal;
  331. TCHAR szProfileSize[20];
  332. INT iTypeID, iStatusID;
  333. DWORD dwProfileType, dwProfileStatus, dwSysProfileType=0;
  334. LPUSERINFO lpUserInfo;
  335. BOOL bCentralAvailable = FALSE, bAccountUnknown;
  336. TCHAR szExcludeList[2*MAX_PATH+1];
  337. LPTSTR lpExcludeList = NULL;
  338. //
  339. // Open the user's info
  340. //
  341. wsprintf (szBuffer, TEXT("%s\\%s"), PROFILE_MAPPING, lpSid);
  342. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  343. szBuffer,
  344. 0,
  345. KEY_READ,
  346. &hkeyUser);
  347. if (Error != ERROR_SUCCESS) {
  348. return FALSE;
  349. }
  350. //
  351. // If PI_HIDEPROFILE flag is set then do not display
  352. // the user in system applet
  353. //
  354. dwSize = sizeof(DWORD);
  355. Error = RegQueryValueEx (hkeyUser,
  356. TEXT("Flags"),
  357. NULL,
  358. &dwType,
  359. (LPBYTE) &dwProfileFlags,
  360. &dwSize);
  361. if (Error == ERROR_SUCCESS && (dwProfileFlags & PI_HIDEPROFILE)) {
  362. RegCloseKey (hkeyUser);
  363. return FALSE;
  364. }
  365. //
  366. // Query for the user's central profile location
  367. //
  368. dwSize = MAX_PATH * sizeof(TCHAR);
  369. Error = RegQueryValueEx (hkeyUser,
  370. TEXT("CentralProfile"),
  371. NULL,
  372. &dwType,
  373. (LPBYTE) szBuffer2,
  374. &dwSize);
  375. if ((Error == ERROR_SUCCESS) && (szBuffer2[0] != TEXT('\0'))) {
  376. bCentralAvailable = TRUE;
  377. }
  378. //
  379. // Query for the user's local profile
  380. //
  381. dwSize = MAX_PATH * sizeof(TCHAR);
  382. Error = RegQueryValueEx (hkeyUser,
  383. TEXT("ProfileImagePath"),
  384. NULL,
  385. &dwType,
  386. (LPBYTE) szBuffer2,
  387. &dwSize);
  388. if (Error != ERROR_SUCCESS) {
  389. RegCloseKey (hkeyUser);
  390. return FALSE;
  391. }
  392. //
  393. // Profile paths need to be expanded
  394. //
  395. ExpandEnvironmentStrings (szBuffer2, szBuffer, MAX_PATH);
  396. lstrcpy (szBuffer2, szBuffer);
  397. //
  398. // Test if the directory exists.
  399. //
  400. hFile = FindFirstFile (szBuffer, &fd);
  401. if (hFile == INVALID_HANDLE_VALUE) {
  402. RegCloseKey (hkeyUser);
  403. return FALSE;
  404. }
  405. FindClose (hFile);
  406. //
  407. // Get the time stamp of the profile
  408. //
  409. lpEnd = CheckSlash (szBuffer);
  410. lstrcpy (lpEnd, TEXT("ntuser.dat"));
  411. //
  412. // Look for a normal user profile
  413. //
  414. hFile = FindFirstFile (szBuffer, &fd);
  415. if (hFile == INVALID_HANDLE_VALUE) {
  416. //
  417. // Try a mandatory user profile
  418. //
  419. lstrcpy (lpEnd, TEXT("ntuser.man"));
  420. hFile = FindFirstFile (szBuffer, &fd);
  421. if (hFile == INVALID_HANDLE_VALUE) {
  422. RegCloseKey (hkeyUser);
  423. return FALSE;
  424. }
  425. }
  426. FindClose (hFile);
  427. *lpEnd = TEXT('\0');
  428. //
  429. // Get the exclusionlist from the registry or ini files
  430. //
  431. if (dwFlags & PRF_USERSID)
  432. ReadExclusionList(szExcludeList, 2*MAX_PATH);
  433. else
  434. ReadExclusionListFromIniFile(szBuffer, szExcludeList, 2*MAX_PATH);
  435. //
  436. // Convert the exclusionlist read from the registry to a Null terminated list
  437. // readable by recursedirectory.
  438. //
  439. if (szExcludeList[0] != TEXT('\0'))
  440. lpExcludeList = ConvertExclusionList (szBuffer, szExcludeList);
  441. else
  442. lpExcludeList = NULL;
  443. //
  444. // Get the profile size
  445. //
  446. g_dwProfileSize = 0;
  447. *lpEnd = TEXT('\0');
  448. if (!RecurseDirectory (szBuffer, lpExcludeList)) {
  449. RegCloseKey (hkeyUser);
  450. if (lpExcludeList) {
  451. LocalFree (lpExcludeList);
  452. }
  453. return FALSE;
  454. }
  455. StrFormatByteSize((LONGLONG)g_dwProfileSize, szProfileSize, ARRAYSIZE(szProfileSize));
  456. //
  457. // check out the state information to determine profile status.
  458. // If the user is not logged on currently then report the status
  459. // of last session.
  460. //
  461. Error = RegQueryValueEx (hkeyUser,
  462. TEXT("State"),
  463. NULL,
  464. &dwType,
  465. (LPBYTE) &dwSysProfileType,
  466. &dwSize);
  467. //
  468. // The constants being used come from
  469. // windows\gina\userenv\profile\profile.h
  470. //
  471. if (dwSysProfileType & 0x00008000) {
  472. dwProfileStatus = USERINFO_BACKUP;
  473. }
  474. else if (dwSysProfileType & 0x00000001) {
  475. dwProfileStatus = USERINFO_MANDATORY;
  476. }
  477. else if ((dwSysProfileType & 0x00000800) ||
  478. (dwSysProfileType & 0x00000080)) {
  479. dwProfileStatus = USERINFO_TEMP;
  480. }
  481. else if (dwSysProfileType & 0x00000010) {
  482. dwProfileStatus = USERINFO_FLOATING;
  483. }
  484. else {
  485. dwProfileStatus = USERINFO_LOCAL;
  486. }
  487. if (dwSysProfileType & 0x00000001) {
  488. dwProfileType = USERINFO_MANDATORY;
  489. }
  490. else {
  491. if (bCentralAvailable) {
  492. dwProfileType = USERINFO_FLOATING;
  493. }
  494. else {
  495. dwProfileType = USERINFO_LOCAL;
  496. }
  497. // Check User Preference
  498. dwSize = sizeof(dwProfileType);
  499. Error = RegQueryValueEx (hkeyUser,
  500. TEXT("UserPreference"),
  501. NULL,
  502. &dwType,
  503. (LPBYTE) &dwProfileType,
  504. &dwSize);
  505. // Check User Preference in .bak if exist
  506. wsprintf (szBuffer, TEXT("%s\\%s.bak"), PROFILE_MAPPING, lpSid);
  507. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  508. szBuffer,
  509. 0,
  510. KEY_READ,
  511. &hKeyProfile);
  512. if (Error == ERROR_SUCCESS) {
  513. dwSize = sizeof(dwProfileType);
  514. RegQueryValueEx(hKeyProfile,
  515. TEXT("UserPreference"),
  516. NULL,
  517. &dwType,
  518. (LPBYTE) &dwProfileType,
  519. &dwSize);
  520. RegCloseKey (hKeyProfile);
  521. }
  522. // Check machine policy for disabling roaming profile
  523. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  524. SYSTEM_POLICIES_KEY,
  525. 0, KEY_READ,
  526. &hKeyPolicy) == ERROR_SUCCESS) {
  527. DWORD dwTmpVal, dwSize, dwType;
  528. dwSize = sizeof(dwTmpVal);
  529. Error = RegQueryValueEx(hKeyPolicy,
  530. PROFILE_LOCALONLY,
  531. NULL, &dwType,
  532. (LPBYTE) &dwTmpVal,
  533. &dwSize);
  534. RegCloseKey (hKeyPolicy);
  535. if (Error == ERROR_SUCCESS && dwTmpVal == 1) {
  536. dwProfileType = USERINFO_LOCAL;
  537. }
  538. }
  539. if (dwProfileType == USERINFO_FLOATING) {
  540. BOOL bReadOnly = FALSE;
  541. HKEY hSubKey;
  542. //
  543. // Check for a roaming profile security/read only preference
  544. //
  545. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  546. &hSubKey) == ERROR_SUCCESS) {
  547. dwSize = sizeof(bReadOnly);
  548. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  549. (LPBYTE) &bReadOnly, &dwSize);
  550. RegCloseKey(hSubKey);
  551. }
  552. //
  553. // Check for a roaming profile security/read only policy
  554. //
  555. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ,
  556. &hSubKey) == ERROR_SUCCESS) {
  557. dwSize = sizeof(bReadOnly);
  558. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  559. (LPBYTE) &bReadOnly, &dwSize);
  560. RegCloseKey(hSubKey);
  561. }
  562. if (bReadOnly) {
  563. dwProfileType = USERINFO_READONLY;
  564. }
  565. }
  566. }
  567. switch (dwProfileStatus) {
  568. case USERINFO_MANDATORY:
  569. iStatusID = IDS_UP_MANDATORY;
  570. break;
  571. case USERINFO_BACKUP:
  572. iStatusID = IDS_UP_BACKUP;
  573. break;
  574. case USERINFO_TEMP:
  575. iStatusID = IDS_UP_TEMP;
  576. break;
  577. case USERINFO_FLOATING:
  578. iStatusID = IDS_UP_FLOATING;
  579. break;
  580. default:
  581. iStatusID = IDS_UP_LOCAL;
  582. break;
  583. }
  584. switch (dwProfileType) {
  585. case USERINFO_MANDATORY:
  586. iTypeID = IDS_UP_MANDATORY;
  587. break;
  588. case USERINFO_READONLY:
  589. iTypeID = IDS_UP_READONLY;
  590. break;
  591. case USERINFO_FLOATING:
  592. iTypeID = IDS_UP_FLOATING;
  593. break;
  594. default:
  595. iTypeID = IDS_UP_LOCAL;
  596. break;
  597. }
  598. //
  599. // Get the friendly display name
  600. //
  601. Error = RegQueryValueEx (hkeyUser, TEXT("Sid"), NULL, &dwType, NULL, &dwSize);
  602. if (Error != ERROR_SUCCESS) {
  603. RegCloseKey (hkeyUser);
  604. return FALSE;
  605. }
  606. pSid = MemAlloc (LPTR, dwSize);
  607. if (!pSid) {
  608. RegCloseKey (hkeyUser);
  609. return FALSE;
  610. }
  611. Error = RegQueryValueEx (hkeyUser,
  612. TEXT("Sid"),
  613. NULL,
  614. &dwType,
  615. (LPBYTE)pSid,
  616. &dwSize);
  617. if (Error != ERROR_SUCCESS) {
  618. RegCloseKey (hkeyUser);
  619. return FALSE;
  620. }
  621. //
  622. // Get the friendly names
  623. //
  624. szTemp[0] = TEXT('\0');
  625. if (!LookupAccountSid (NULL, pSid, szTemp, &dwTempSize,
  626. szTemp2, &dwTemp2Size, &SidName)) {
  627. //
  628. // Unknown account
  629. //
  630. LoadString (hInstance, IDS_UP_ACCUNKNOWN, szBuffer, MAX_PATH);
  631. bAccountUnknown = TRUE;
  632. } else {
  633. if (szTemp[0] != TEXT('\0')) {
  634. //
  635. // Build the display name
  636. //
  637. wsprintf (szBuffer, TEXT("%s\\%s"), szTemp2, szTemp);
  638. bAccountUnknown = FALSE;
  639. } else {
  640. //
  641. // Account deleted.
  642. //
  643. LoadString (hInstance, IDS_UP_ACCDELETED, szBuffer, MAX_PATH);
  644. bAccountUnknown = TRUE;
  645. }
  646. }
  647. //
  648. // Allocate a UserInfo structure
  649. //
  650. lpUserInfo = (LPUSERINFO) MemAlloc(LPTR, (sizeof(USERINFO) +
  651. (lstrlen (lpSid) + 1) * sizeof(TCHAR) +
  652. (lstrlen (szBuffer2) + 1) * sizeof(TCHAR) +
  653. (lstrlen (szBuffer) + 1) * sizeof(TCHAR)));
  654. if (!lpUserInfo) {
  655. MemFree (pSid);
  656. RegCloseKey (hkeyUser);
  657. return FALSE;
  658. }
  659. lpUserInfo->dwFlags = (bCentralAvailable ? USERINFO_FLAG_CENTRAL_AVAILABLE : 0);
  660. lpUserInfo->dwFlags |= (bAccountUnknown ? USERINFO_FLAG_ACCOUNT_UNKNOWN : 0);
  661. lpUserInfo->lpSid = (LPTSTR)((LPBYTE)lpUserInfo + sizeof(USERINFO));
  662. lpUserInfo->lpProfile = (LPTSTR) (lpUserInfo->lpSid + lstrlen(lpSid) + 1);
  663. lpUserInfo->lpUserName = (LPTSTR) (lpUserInfo->lpProfile + lstrlen(szBuffer2) + 1);
  664. lstrcpy (lpUserInfo->lpSid, lpSid);
  665. lstrcpy (lpUserInfo->lpProfile, szBuffer2);
  666. lpUserInfo->dwProfileType = dwProfileType;
  667. lpUserInfo->dwProfileStatus = dwProfileStatus;
  668. lstrcpy (lpUserInfo->lpUserName, szBuffer);
  669. //
  670. // Add the item to the listview
  671. //
  672. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  673. item.mask = LVIF_TEXT | LVIF_PARAM;
  674. item.iItem = 0;
  675. item.iSubItem = 0;
  676. item.pszText = szBuffer;
  677. item.lParam = (LPARAM) lpUserInfo;
  678. iItem = ListView_InsertItem (hwndTemp, &item);
  679. //
  680. // Add the profile size
  681. //
  682. item.mask = LVIF_TEXT;
  683. item.iItem = iItem;
  684. item.iSubItem = 1;
  685. item.pszText = szProfileSize;
  686. SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  687. //
  688. // Add the profile type
  689. //
  690. LoadString (hInstance, iTypeID, szTemp, 100);
  691. item.mask = LVIF_TEXT;
  692. item.iItem = iItem;
  693. item.iSubItem = 2;
  694. item.pszText = szTemp;
  695. SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  696. //
  697. // Add the profile status
  698. //
  699. LoadString (hInstance, iStatusID, szTemp, 100);
  700. item.mask = LVIF_TEXT;
  701. item.iItem = iItem;
  702. item.iSubItem = 3;
  703. item.pszText = szTemp;
  704. SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  705. //
  706. // Convert it to local time
  707. //
  708. if (!FileTimeToLocalFileTime(&fd.ftLastAccessTime, &ftLocal)) {
  709. ftLocal = fd.ftLastAccessTime;
  710. }
  711. //
  712. // Add the time/date stamp
  713. //
  714. FileTimeToSystemTime (&ftLocal, &systime);
  715. GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime,
  716. NULL, szBuffer, MAX_PATH);
  717. item.mask = LVIF_TEXT;
  718. item.iItem = iItem;
  719. item.iSubItem = 4;
  720. item.pszText = szBuffer;
  721. SendMessage (hwndTemp, LVM_SETITEMTEXT, iItem, (LPARAM) &item);
  722. //
  723. // Free the sid
  724. //
  725. MemFree (pSid);
  726. if (lpExcludeList) {
  727. LocalFree (lpExcludeList);
  728. }
  729. RegCloseKey (hkeyUser);
  730. return TRUE;
  731. }
  732. //*************************************************************
  733. //
  734. // FillListView()
  735. //
  736. // Purpose: Fills the listview with either all the profiles
  737. // or just the current user profile depending if
  738. // the user has Admin privilages
  739. //
  740. // Parameters: hDlg - Dialog box handle
  741. // bAdmin - User an admin
  742. //
  743. //
  744. // Return: TRUE if successful
  745. // FALSE if an error occurs
  746. //
  747. // Comments:
  748. //
  749. // History: Date Author Comment
  750. // 1/26/96 ericflo Created
  751. //
  752. //*************************************************************
  753. BOOL FillListView (HWND hDlg, BOOL bAdmin)
  754. {
  755. LV_ITEM item;
  756. BOOL bRetVal = FALSE;
  757. LPTSTR lpUserSid;
  758. lpUserSid = GetSidString();
  759. //
  760. // If the current user has admin privilages, then
  761. // he/she can see all the profiles on this machine,
  762. // otherwise the user only gets their profile.
  763. //
  764. if (bAdmin) {
  765. DWORD SubKeyIndex = 0;
  766. TCHAR SubKeyName[100];
  767. DWORD cchSubKeySize;
  768. HKEY hkeyProfiles;
  769. LONG Error;
  770. //
  771. // Open the profile list
  772. //
  773. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  774. PROFILE_MAPPING,
  775. 0,
  776. KEY_READ,
  777. &hkeyProfiles);
  778. if (Error != ERROR_SUCCESS) {
  779. if (lpUserSid)
  780. DeleteSidString (lpUserSid);
  781. return FALSE;
  782. }
  783. cchSubKeySize = 100;
  784. while (TRUE) {
  785. //
  786. // Get the next sub-key name
  787. //
  788. Error = RegEnumKey(hkeyProfiles, SubKeyIndex, SubKeyName, cchSubKeySize);
  789. if (Error != ERROR_SUCCESS) {
  790. if (Error == ERROR_NO_MORE_ITEMS) {
  791. //
  792. // Successful end of enumeration
  793. //
  794. Error = ERROR_SUCCESS;
  795. }
  796. break;
  797. }
  798. if ((lpUserSid) && (lstrcmp(SubKeyName, lpUserSid) == 0))
  799. AddUser (hDlg, SubKeyName, PRF_USERSID);
  800. else
  801. AddUser (hDlg, SubKeyName, 0);
  802. //
  803. // Go enumerate the next sub-key
  804. //
  805. SubKeyIndex ++;
  806. }
  807. //
  808. // Close the registry
  809. //
  810. RegCloseKey (hkeyProfiles);
  811. bRetVal = ((Error == ERROR_SUCCESS) ? TRUE : FALSE);
  812. } else {
  813. //
  814. // The current user doesn't have admin privilages
  815. //
  816. if (lpUserSid) {
  817. AddUser (hDlg, lpUserSid, PRF_USERSID);
  818. bRetVal = TRUE;
  819. }
  820. }
  821. if (bRetVal) {
  822. //
  823. // Select the first item
  824. //
  825. item.mask = LVIF_STATE;
  826. item.iItem = 0;
  827. item.iSubItem = 0;
  828. item.state = LVIS_SELECTED | LVIS_FOCUSED;
  829. item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  830. SendDlgItemMessage (hDlg, IDC_UP_LISTVIEW,
  831. LVM_SETITEMSTATE, 0, (LPARAM) &item);
  832. }
  833. if (lpUserSid)
  834. DeleteSidString (lpUserSid);
  835. return (bRetVal);
  836. }
  837. //*************************************************************
  838. //
  839. // CheckSemicolon()
  840. //
  841. // Purpose: Checks for an ending slash and adds one if
  842. // it is missing.
  843. //
  844. // Parameters: lpDir - directory
  845. //
  846. // Return: Pointer to the end of the string
  847. //
  848. // Comments:
  849. //
  850. // History: Date Author Comment
  851. // 6/19/95 ericlfo Created
  852. //
  853. //*************************************************************
  854. LPTSTR CheckSemicolon (LPTSTR lpDir)
  855. {
  856. LPTSTR lpEnd;
  857. lpEnd = lpDir + lstrlen(lpDir);
  858. if (*(lpEnd - 1) != TEXT(';')) {
  859. *lpEnd = TEXT(';');
  860. lpEnd++;
  861. *lpEnd = TEXT('\0');
  862. }
  863. return lpEnd;
  864. }
  865. //*************************************************************
  866. //
  867. // ReadExclusionList()
  868. //
  869. // Purpose: Reads the exclusionlist for the user from the
  870. // hkcu part of the registry
  871. //
  872. // Parameters: szExclusionList - Buffer for exclusionList to be read into
  873. // dwSize - Size of the buffer
  874. //
  875. // Return: FALSE on error
  876. //
  877. //*************************************************************
  878. BOOL ReadExclusionList(LPTSTR szExcludeList, DWORD dwExclSize)
  879. {
  880. TCHAR szExcludeList2[MAX_PATH];
  881. TCHAR szExcludeList1[MAX_PATH];
  882. HKEY hKey;
  883. DWORD dwSize, dwType;
  884. //
  885. // Check for a list of directories to exclude both user preferences
  886. // and user policy
  887. //
  888. szExcludeList1[0] = TEXT('\0');
  889. if (RegOpenKeyEx (HKEY_CURRENT_USER,
  890. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
  891. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  892. dwSize = sizeof(szExcludeList1);
  893. RegQueryValueEx (hKey,
  894. TEXT("ExcludeProfileDirs"),
  895. NULL,
  896. &dwType,
  897. (LPBYTE) szExcludeList1,
  898. &dwSize);
  899. RegCloseKey (hKey);
  900. }
  901. szExcludeList2[0] = TEXT('\0');
  902. if (RegOpenKeyEx (HKEY_CURRENT_USER,
  903. SYSTEM_POLICIES_KEY,
  904. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  905. dwSize = sizeof(szExcludeList2);
  906. RegQueryValueEx (hKey,
  907. TEXT("ExcludeProfileDirs"),
  908. NULL,
  909. &dwType,
  910. (LPBYTE) szExcludeList2,
  911. &dwSize);
  912. RegCloseKey (hKey);
  913. }
  914. //
  915. // Merge the user preferences and policy together
  916. //
  917. szExcludeList[0] = TEXT('\0');
  918. if (szExcludeList1[0] != TEXT('\0')) {
  919. CheckSemicolon(szExcludeList1);
  920. lstrcpy (szExcludeList, szExcludeList1);
  921. }
  922. if (szExcludeList2[0] != TEXT('\0')) {
  923. lstrcat (szExcludeList, szExcludeList2);
  924. }
  925. return TRUE;
  926. }
  927. //*************************************************************
  928. //
  929. // ReadExclusionListFromIniFile()
  930. //
  931. // Purpose: Reads the exclusionlist for the user from the
  932. // ntuser.ini from the local profile
  933. //
  934. // Parameters:
  935. // (in) lpSourceDir - Profile Directory
  936. // szExclusionList - Buffer for exclusionList to be read into
  937. // dwSize - Size of the buffer
  938. //
  939. // Return: FALSE on error
  940. //
  941. //
  942. //*************************************************************
  943. BOOL ReadExclusionListFromIniFile(LPCTSTR lpSourceDir, LPTSTR szExcludeList, DWORD dwExclSize)
  944. {
  945. TCHAR szNTUserIni[MAX_PATH];
  946. LPTSTR lpEnd;
  947. //
  948. // Get the exclusion list from the cache
  949. //
  950. szExcludeList[0] = TEXT('\0');
  951. lstrcpy (szNTUserIni, lpSourceDir);
  952. lpEnd = CheckSlash (szNTUserIni);
  953. lstrcpy(lpEnd, c_szNTUserIni);
  954. GetPrivateProfileString (PROFILE_GENERAL_SECTION,
  955. PROFILE_EXCLUSION_LIST,
  956. TEXT(""), szExcludeList,
  957. dwExclSize,
  958. szNTUserIni);
  959. return TRUE;
  960. }
  961. //*************************************************************
  962. //
  963. // ConvertExclusionList()
  964. //
  965. // Purpose: Converts the semi-colon profile relative exclusion
  966. // list to fully qualified null terminated exclusion
  967. // list
  968. //
  969. // Parameters: lpSourceDir - Profile root directory
  970. // lpExclusionList - List of directories to exclude
  971. //
  972. // Return: List if successful
  973. // NULL if an error occurs
  974. //
  975. //*************************************************************
  976. LPTSTR ConvertExclusionList (LPCTSTR lpSourceDir, LPCTSTR lpExclusionList)
  977. {
  978. LPTSTR lpExcludeList = NULL, lpInsert, lpEnd, lpTempList;
  979. LPCTSTR lpTemp, lpDir;
  980. TCHAR szTemp[MAX_PATH];
  981. DWORD dwSize = 2; // double null terminator
  982. DWORD dwStrLen;
  983. //
  984. // Setup a temp buffer to work with
  985. //
  986. lstrcpy (szTemp, lpSourceDir);
  987. lpEnd = CheckSlash (szTemp);
  988. //
  989. // Loop through the list
  990. //
  991. lpTemp = lpDir = lpExclusionList;
  992. while (*lpTemp) {
  993. //
  994. // Look for the semicolon separator
  995. //
  996. while (*lpTemp && ((*lpTemp) != TEXT(';'))) {
  997. lpTemp++;
  998. }
  999. //
  1000. // Remove any leading spaces
  1001. //
  1002. while (*lpDir == TEXT(' ')) {
  1003. lpDir++;
  1004. }
  1005. //
  1006. // Put the directory name on the temp buffer
  1007. //
  1008. lstrcpyn (lpEnd, lpDir, (int)(lpTemp - lpDir + 1));
  1009. //
  1010. // Add the string to the exclusion list
  1011. //
  1012. if (lpExcludeList) {
  1013. dwStrLen = lstrlen (szTemp) + 1;
  1014. dwSize += dwStrLen;
  1015. lpTempList = (LPTSTR) LocalReAlloc (lpExcludeList, dwSize * sizeof(TCHAR),
  1016. LMEM_MOVEABLE | LMEM_ZEROINIT);
  1017. if (!lpTempList) {
  1018. LocalFree (lpExcludeList);
  1019. lpExcludeList = NULL;
  1020. goto Exit;
  1021. }
  1022. lpExcludeList = lpTempList;
  1023. lpInsert = lpExcludeList + dwSize - dwStrLen - 1;
  1024. lstrcpy (lpInsert, szTemp);
  1025. } else {
  1026. dwSize += lstrlen (szTemp);
  1027. lpExcludeList = (LPTSTR) LocalAlloc (LPTR, dwSize * sizeof(TCHAR));
  1028. if (!lpExcludeList) {
  1029. goto Exit;
  1030. }
  1031. lstrcpy (lpExcludeList, szTemp);
  1032. }
  1033. //
  1034. // If we are at the end of the exclusion list, we're done
  1035. //
  1036. if (!(*lpTemp)) {
  1037. goto Exit;
  1038. }
  1039. //
  1040. // Prep for the next entry
  1041. //
  1042. lpTemp++;
  1043. lpDir = lpTemp;
  1044. }
  1045. Exit:
  1046. return lpExcludeList;
  1047. }
  1048. //*************************************************************
  1049. //
  1050. // RecurseDirectory()
  1051. //
  1052. // Purpose: Recurses through the subdirectories counting the size.
  1053. //
  1054. // Parameters: lpDir - Directory
  1055. //
  1056. // Return: TRUE if successful
  1057. // FALSE if an error occurs
  1058. //
  1059. // Comments:
  1060. //
  1061. // History: Date Author Comment
  1062. // 1/30/96 ericflo Created
  1063. //
  1064. // Notes:
  1065. // The buffer size expected is MAX_PATH+4 for some internal processing
  1066. // We should fix this to be better post Win 2K.
  1067. //*************************************************************
  1068. BOOL RecurseDirectory (LPTSTR lpDir, LPTSTR lpExcludeList)
  1069. {
  1070. HANDLE hFile = INVALID_HANDLE_VALUE;
  1071. WIN32_FIND_DATA fd;
  1072. LPTSTR lpEnd, lpTemp;
  1073. BOOL bResult = TRUE;
  1074. BOOL bSkip;
  1075. //
  1076. // Setup the ending pointer
  1077. //
  1078. lpEnd = CheckSlash (lpDir);
  1079. //
  1080. // Append *.* to the source directory
  1081. //
  1082. lstrcpy(lpEnd, TEXT("*.*"));
  1083. //
  1084. // Search through the source directory
  1085. //
  1086. hFile = FindFirstFile(lpDir, &fd);
  1087. if (hFile == INVALID_HANDLE_VALUE) {
  1088. if ( (GetLastError() == ERROR_FILE_NOT_FOUND) ||
  1089. (GetLastError() == ERROR_PATH_NOT_FOUND) ) {
  1090. //
  1091. // bResult is already initialized to TRUE, so
  1092. // just fall through.
  1093. //
  1094. } else {
  1095. bResult = FALSE;
  1096. }
  1097. goto RecurseDir_Exit;
  1098. }
  1099. do {
  1100. //
  1101. // Append the file / directory name to the working buffer
  1102. //
  1103. // skip the file if the path > MAX_PATH
  1104. if ((1+lstrlen(fd.cFileName)+lstrlen(lpDir)+lstrlen(TEXT("\\*.*"))) >= 2*MAX_PATH) {
  1105. continue;
  1106. }
  1107. lstrcpy (lpEnd, fd.cFileName);
  1108. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1109. //
  1110. // Check for "." and ".."
  1111. //
  1112. if (!lstrcmpi(fd.cFileName, TEXT("."))) {
  1113. continue;
  1114. }
  1115. if (!lstrcmpi(fd.cFileName, TEXT(".."))) {
  1116. continue;
  1117. }
  1118. //
  1119. // Check if this directory should be excluded
  1120. //
  1121. if (lpExcludeList) {
  1122. bSkip = FALSE;
  1123. lpTemp = lpExcludeList;
  1124. while (*lpTemp) {
  1125. if (lstrcmpi (lpTemp, lpDir) == 0) {
  1126. bSkip = TRUE;
  1127. break;
  1128. }
  1129. lpTemp += lstrlen (lpTemp) + 1;
  1130. }
  1131. if (bSkip)
  1132. continue;
  1133. }
  1134. //
  1135. // Found a directory.
  1136. //
  1137. // 1) Change into that subdirectory on the source drive.
  1138. // 2) Recurse down that tree.
  1139. // 3) Back up one level.
  1140. //
  1141. //
  1142. // Recurse the subdirectory
  1143. //
  1144. if (!RecurseDirectory(lpDir, lpExcludeList)) {
  1145. bResult = FALSE;
  1146. goto RecurseDir_Exit;
  1147. }
  1148. } else {
  1149. //
  1150. // Found a file, add the filesize
  1151. //
  1152. g_dwProfileSize += fd.nFileSizeLow;
  1153. }
  1154. //
  1155. // Find the next entry
  1156. //
  1157. } while (FindNextFile(hFile, &fd));
  1158. RecurseDir_Exit:
  1159. //
  1160. // Remove the file / directory name appended above
  1161. //
  1162. *lpEnd = TEXT('\0');
  1163. //
  1164. // Close the search handle
  1165. //
  1166. if (hFile != INVALID_HANDLE_VALUE) {
  1167. FindClose(hFile);
  1168. }
  1169. return bResult;
  1170. }
  1171. //*************************************************************
  1172. //
  1173. // UPCleanUp()
  1174. //
  1175. // Purpose: Free's resources for this dialog box
  1176. //
  1177. // Parameters: hDlg - Dialog box handle
  1178. //
  1179. // Return: void
  1180. //
  1181. // Comments:
  1182. //
  1183. // History: Date Author Comment
  1184. // 1/31/96 ericflo Created
  1185. //
  1186. //*************************************************************
  1187. VOID UPCleanUp (HWND hDlg)
  1188. {
  1189. int i, n;
  1190. HWND hwndTemp;
  1191. LPUSERINFO lpUserInfo;
  1192. LV_ITEM item;
  1193. //
  1194. // Free memory used for the listview items
  1195. //
  1196. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1197. n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1198. item.mask = LVIF_PARAM;
  1199. item.iSubItem = 0;
  1200. for (i = 0; i < n; i++) {
  1201. item.iItem = i;
  1202. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1203. lpUserInfo = (LPUSERINFO) item.lParam;
  1204. } else {
  1205. lpUserInfo = NULL;
  1206. }
  1207. if (lpUserInfo) {
  1208. MemFree (lpUserInfo);
  1209. }
  1210. }
  1211. }
  1212. //*************************************************************
  1213. //
  1214. // UPSave()
  1215. //
  1216. // Purpose: Saves the settings
  1217. //
  1218. // Parameters: hDlg - Dialog box handle
  1219. //
  1220. // Return: void
  1221. //
  1222. // Comments:
  1223. //
  1224. // History: Date Author Comment
  1225. // 1/31/96 ericflo Created
  1226. //
  1227. //*************************************************************
  1228. VOID UPSave (HWND hDlg)
  1229. {
  1230. int i, n;
  1231. HWND hwndTemp;
  1232. LPUSERINFO lpUserInfo;
  1233. LV_ITEM item;
  1234. TCHAR szBuffer[MAX_PATH];
  1235. HKEY hkeyUser;
  1236. LONG Error;
  1237. //
  1238. // Save type info
  1239. //
  1240. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1241. n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1242. item.mask = LVIF_PARAM;
  1243. item.iSubItem = 0;
  1244. for (i = 0; i < n; i++) {
  1245. item.iItem = i;
  1246. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1247. lpUserInfo = (LPUSERINFO) item.lParam;
  1248. } else {
  1249. lpUserInfo = NULL;
  1250. }
  1251. if (lpUserInfo) {
  1252. if (lpUserInfo->dwFlags & USERINFO_FLAG_DIRTY) {
  1253. lpUserInfo->dwFlags &= ~USERINFO_FLAG_DIRTY;
  1254. wsprintf (szBuffer, TEXT("%s\\%s"), PROFILE_MAPPING,
  1255. lpUserInfo->lpSid);
  1256. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1257. szBuffer,
  1258. 0,
  1259. KEY_WRITE,
  1260. &hkeyUser);
  1261. if (Error != ERROR_SUCCESS) {
  1262. continue;
  1263. }
  1264. RegSetValueEx (hkeyUser,
  1265. TEXT("UserPreference"),
  1266. 0,
  1267. REG_DWORD,
  1268. (LPBYTE) &lpUserInfo->dwProfileType,
  1269. sizeof(DWORD));
  1270. RegCloseKey(hkeyUser);
  1271. }
  1272. }
  1273. }
  1274. }
  1275. //*************************************************************
  1276. //
  1277. // IsProfileInUse()
  1278. //
  1279. // Purpose: Determines if the given profile is currently in use
  1280. //
  1281. // Parameters: lpSid - Sid (text) to test
  1282. //
  1283. // Return: TRUE if in use
  1284. // FALSE if not
  1285. //
  1286. // Comments:
  1287. //
  1288. // History: Date Author Comment
  1289. // 2/7/96 ericflo Created
  1290. //
  1291. //*************************************************************
  1292. BOOL IsProfileInUse (LPTSTR lpSid)
  1293. {
  1294. LONG lResult;
  1295. HKEY hkeyProfile;
  1296. lResult = RegOpenKeyEx (HKEY_USERS, lpSid, 0, KEY_READ, &hkeyProfile);
  1297. if (lResult == ERROR_SUCCESS) {
  1298. RegCloseKey (hkeyProfile);
  1299. return TRUE;
  1300. }
  1301. return FALSE;
  1302. }
  1303. void UPDoItemChanged(HWND hDlg, int idCtl)
  1304. {
  1305. int selection;
  1306. HWND hwndTemp;
  1307. LPUSERINFO lpUserInfo;
  1308. LV_ITEM item;
  1309. hwndTemp = GetDlgItem (hDlg, idCtl);
  1310. selection = GetSelectedItem (hwndTemp);
  1311. if (selection != -1)
  1312. {
  1313. item.mask = LVIF_PARAM;
  1314. item.iItem = selection;
  1315. item.iSubItem = 0;
  1316. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1317. lpUserInfo = (LPUSERINFO) item.lParam;
  1318. } else {
  1319. lpUserInfo = NULL;
  1320. }
  1321. if (lpUserInfo) {
  1322. //
  1323. // Set the "Delete" button state
  1324. //
  1325. if (IsProfileInUse(lpUserInfo->lpSid)) {
  1326. EnableWindow (GetDlgItem (hDlg, IDC_UP_DELETE), FALSE);
  1327. } else {
  1328. EnableWindow (GetDlgItem (hDlg, IDC_UP_DELETE), TRUE);
  1329. }
  1330. //
  1331. // Set the "Change Type" button state
  1332. //
  1333. OSVERSIONINFOEXW version;
  1334. version.dwOSVersionInfoSize = sizeof(version);
  1335. if (GetVersionEx((LPOSVERSIONINFO)&version) &&
  1336. (version.wSuiteMask & VER_SUITE_PERSONAL)) {
  1337. ShowWindow(GetDlgItem (hDlg, IDC_UP_TYPE), SW_HIDE);
  1338. }
  1339. else if((lpUserInfo->dwProfileType == USERINFO_MANDATORY) ||
  1340. (lpUserInfo->dwProfileType == USERINFO_BACKUP)) {
  1341. EnableWindow (GetDlgItem (hDlg, IDC_UP_TYPE), FALSE);
  1342. } else {
  1343. EnableWindow (GetDlgItem (hDlg, IDC_UP_TYPE), TRUE);
  1344. }
  1345. //
  1346. // Set the "Copy To" button state
  1347. //
  1348. if ((lpUserInfo->dwFlags & USERINFO_FLAG_ACCOUNT_UNKNOWN) ||
  1349. IsProfileInUse(lpUserInfo->lpSid)) {
  1350. EnableWindow (GetDlgItem (hDlg, IDC_UP_COPY), FALSE);
  1351. } else {
  1352. EnableWindow (GetDlgItem (hDlg, IDC_UP_COPY), TRUE);
  1353. }
  1354. }
  1355. }
  1356. else {
  1357. //
  1358. // If nothing is selected set all buttons to inactive
  1359. //
  1360. EnableWindow (GetDlgItem (hDlg, IDC_UP_DELETE), FALSE);
  1361. EnableWindow (GetDlgItem (hDlg, IDC_UP_TYPE), FALSE);
  1362. EnableWindow (GetDlgItem (hDlg, IDC_UP_COPY), FALSE);
  1363. }
  1364. }
  1365. //*************************************************************
  1366. void
  1367. UPOnLink(WPARAM wParam)
  1368. {
  1369. switch(wParam)
  1370. {
  1371. case IDC_UP_UPLINK:
  1372. {
  1373. SHELLEXECUTEINFO execinfo = {0};
  1374. execinfo.cbSize = sizeof(execinfo);
  1375. execinfo.nShow = SW_SHOW;
  1376. execinfo.lpVerb = TEXT("open");
  1377. execinfo.lpFile = TEXT("control");
  1378. execinfo.lpParameters = TEXT("userpasswords");
  1379. ShellExecuteEx(&execinfo);
  1380. }
  1381. break;
  1382. default:
  1383. break;
  1384. }
  1385. }
  1386. //*************************************************************
  1387. //
  1388. // UPDeleteProfile()
  1389. //
  1390. // Purpose: Deletes a user's profile
  1391. //
  1392. // Parameters: hDlg - Dialog box handle
  1393. //
  1394. // Return:
  1395. //
  1396. // Comments:
  1397. //
  1398. // History: Date Author Comment
  1399. // 2/8/96 ericflo Created
  1400. //
  1401. //*************************************************************
  1402. void UPDeleteProfile(HWND hDlg)
  1403. {
  1404. int selection;
  1405. HWND hwndTemp;
  1406. LPUSERINFO lpUserInfo;
  1407. LV_ITEM item;
  1408. TCHAR szName[100];
  1409. TCHAR szBuffer1[100];
  1410. TCHAR szBuffer2[200];
  1411. HCURSOR hOldCursor;
  1412. //
  1413. // Get the selected profile
  1414. //
  1415. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1416. selection = GetSelectedItem (hwndTemp);
  1417. if (selection == -1) {
  1418. return;
  1419. }
  1420. item.mask = LVIF_PARAM;
  1421. item.iItem = selection;
  1422. item.iSubItem = 0;
  1423. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1424. lpUserInfo = (LPUSERINFO) item.lParam;
  1425. } else {
  1426. lpUserInfo = NULL;
  1427. }
  1428. if (!lpUserInfo) {
  1429. return;
  1430. }
  1431. //
  1432. // Confirm that the user really wants to delete the profile
  1433. //
  1434. szBuffer1[0] = TEXT('\0');
  1435. ListView_GetItemText (hwndTemp, selection, 0, szName, 100);
  1436. LoadString (hInstance, IDS_UP_CONFIRM, szBuffer1, 100);
  1437. wsprintf (szBuffer2, szBuffer1, szName);
  1438. LoadString (hInstance, IDS_UP_CONFIRMTITLE, szBuffer1, 100);
  1439. if (MessageBox (hDlg, szBuffer2, szBuffer1,
  1440. MB_ICONQUESTION | MB_DEFBUTTON2| MB_YESNO) == IDNO) {
  1441. return;
  1442. }
  1443. //
  1444. // Delete the profile and remove the entry from the listview
  1445. //
  1446. hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  1447. if (!DeleteProfile (lpUserInfo->lpSid, NULL, NULL)) {
  1448. TCHAR szMsg[MAX_PATH];
  1449. szMsg[0] = TEXT('\0');
  1450. LoadString (hInstance, IDS_UP_DELETE_ERROR, szMsg, MAX_PATH-1);
  1451. UPDisplayErrorMessage(hDlg, GetLastError(), szMsg);
  1452. }
  1453. if (ListView_DeleteItem(hwndTemp, selection)) {
  1454. MemFree (lpUserInfo);
  1455. }
  1456. //
  1457. // Select another item
  1458. //
  1459. if (selection > 0) {
  1460. selection--;
  1461. }
  1462. item.mask = LVIF_STATE;
  1463. item.iItem = selection;
  1464. item.iSubItem = 0;
  1465. item.state = LVIS_SELECTED | LVIS_FOCUSED;
  1466. item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  1467. SendDlgItemMessage (hDlg, IDC_UP_LISTVIEW,
  1468. LVM_SETITEMSTATE, selection, (LPARAM) &item);
  1469. SetCursor(hOldCursor);
  1470. }
  1471. //*************************************************************
  1472. //
  1473. // UPChangeType()
  1474. //
  1475. // Purpose: Display the "Change Type" dialog box
  1476. //
  1477. // Parameters: hDlg - Dialog box handle
  1478. //
  1479. // Return: void
  1480. //
  1481. // Comments:
  1482. //
  1483. // History: Date Author Comment
  1484. // 2/09/96 ericflo Created
  1485. //
  1486. //*************************************************************
  1487. void UPChangeType(HWND hDlg)
  1488. {
  1489. int selection, iTypeID;
  1490. HWND hwndTemp;
  1491. LPUSERINFO lpUserInfo;
  1492. LV_ITEM item;
  1493. TCHAR szType[100];
  1494. //
  1495. // Get the selected profile
  1496. //
  1497. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1498. selection = GetSelectedItem (hwndTemp);
  1499. if (selection == -1) {
  1500. return;
  1501. }
  1502. item.mask = LVIF_PARAM;
  1503. item.iItem = selection;
  1504. item.iSubItem = 0;
  1505. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1506. lpUserInfo = (LPUSERINFO) item.lParam;
  1507. } else {
  1508. lpUserInfo = NULL;
  1509. }
  1510. if (!lpUserInfo) {
  1511. return;
  1512. }
  1513. // if profile type is mandatory then don't display change type dialog box.
  1514. // Although change type button is disabled for mandatory profile this function
  1515. // can be still executed with double clicking on profile item.
  1516. if (lpUserInfo->dwProfileType == USERINFO_MANDATORY ||
  1517. lpUserInfo->dwProfileType == USERINFO_BACKUP) {
  1518. return;
  1519. }
  1520. //
  1521. // Display the Change Type dialog
  1522. //
  1523. if (!DialogBoxParam (hInstance, MAKEINTRESOURCE(IDD_UP_TYPE), hDlg,
  1524. ChangeTypeDlgProc, (LPARAM)lpUserInfo)) {
  1525. return;
  1526. }
  1527. //
  1528. // Activate the Apply button
  1529. //
  1530. PropSheet_Changed(GetParent(hDlg), hDlg);
  1531. //
  1532. // Mark this item as 'dirty' so it will be saved
  1533. //
  1534. lpUserInfo->dwFlags |= USERINFO_FLAG_DIRTY;
  1535. //
  1536. // Fix the 'Type' field in the display
  1537. //
  1538. switch (lpUserInfo->dwProfileType) {
  1539. case USERINFO_MANDATORY:
  1540. iTypeID = IDS_UP_MANDATORY;
  1541. break;
  1542. case USERINFO_READONLY:
  1543. iTypeID = IDS_UP_READONLY;
  1544. break;
  1545. case USERINFO_FLOATING:
  1546. iTypeID = IDS_UP_FLOATING;
  1547. break;
  1548. default:
  1549. iTypeID = IDS_UP_LOCAL;
  1550. break;
  1551. }
  1552. LoadString (hInstance, iTypeID, szType, 100);
  1553. item.mask = LVIF_TEXT;
  1554. item.iItem = selection;
  1555. item.iSubItem = 2;
  1556. item.pszText = szType;
  1557. SendMessage (hwndTemp, LVM_SETITEMTEXT, selection, (LPARAM) &item);
  1558. }
  1559. //*************************************************************
  1560. //
  1561. // ChangeTypeDlgProc()
  1562. //
  1563. // Purpose: Dialog box procedure for changing the profile type
  1564. //
  1565. // Parameters: hDlg - handle to the dialog box
  1566. // uMsg - window message
  1567. // wParam - wParam
  1568. // lParam - lParam
  1569. //
  1570. // Return: TRUE if message was processed
  1571. // FALSE if not
  1572. //
  1573. // Comments:
  1574. //
  1575. // History: Date Author Comment
  1576. // 2/9/96 ericflo Created
  1577. //
  1578. //*************************************************************
  1579. INT_PTR APIENTRY ChangeTypeDlgProc (HWND hDlg, UINT uMsg,
  1580. WPARAM wParam, LPARAM lParam)
  1581. {
  1582. LPUSERINFO lpUserInfo;
  1583. HKEY hKeyPolicy;
  1584. switch (uMsg) {
  1585. case WM_INITDIALOG:
  1586. lpUserInfo = (LPUSERINFO) lParam;
  1587. if (!lpUserInfo) {
  1588. EndDialog(hDlg, FALSE);
  1589. }
  1590. else {
  1591. TCHAR szMsg[MAX_PATH], szMsg1[MAX_PATH];
  1592. szMsg[0] = TEXT('\0');
  1593. LoadString (hInstance, IDS_UP_CHANGETYPEMSG, szMsg, MAX_PATH);
  1594. wsprintf (szMsg1, szMsg, lpUserInfo->lpUserName);
  1595. SetDlgItemText (hDlg, IDC_UPTYPE_GROUP, szMsg1);
  1596. }
  1597. SetWindowLongPtr (hDlg, GWLP_USERDATA, (LPARAM) lpUserInfo);
  1598. if (lpUserInfo->dwFlags & USERINFO_FLAG_CENTRAL_AVAILABLE) {
  1599. if (lpUserInfo->dwProfileType == USERINFO_LOCAL) {
  1600. CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1601. IDC_UPTYPE_LOCAL);
  1602. if (lpUserInfo->dwProfileStatus == USERINFO_TEMP) {
  1603. EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_FLOAT), FALSE);
  1604. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1605. SetDefButton(hDlg, IDCANCEL);
  1606. }
  1607. else if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1608. SYSTEM_POLICIES_KEY,
  1609. 0, KEY_READ,
  1610. &hKeyPolicy) == ERROR_SUCCESS) {
  1611. DWORD dwTmpVal, dwSize, dwType;
  1612. dwSize = sizeof(dwTmpVal);
  1613. RegQueryValueEx(hKeyPolicy,
  1614. PROFILE_LOCALONLY,
  1615. NULL, &dwType,
  1616. (LPBYTE) &dwTmpVal,
  1617. &dwSize);
  1618. RegCloseKey (hKeyPolicy);
  1619. if (dwTmpVal == 1) {
  1620. EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_FLOAT), FALSE);
  1621. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1622. SetDefButton(hDlg, IDCANCEL);
  1623. }
  1624. }
  1625. }
  1626. else if (lpUserInfo->dwProfileStatus == USERINFO_TEMP) {
  1627. CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1628. IDC_UPTYPE_FLOAT);
  1629. EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_LOCAL), FALSE);
  1630. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1631. SetDefButton(hDlg, IDCANCEL);
  1632. }
  1633. else { // ProfileType is USERINFO_FLOATING
  1634. CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1635. IDC_UPTYPE_FLOAT);
  1636. }
  1637. } else {
  1638. CheckRadioButton (hDlg, IDC_UPTYPE_LOCAL, IDC_UPTYPE_FLOAT,
  1639. IDC_UPTYPE_LOCAL);
  1640. EnableWindow (GetDlgItem(hDlg, IDC_UPTYPE_FLOAT), FALSE);
  1641. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1642. SetDefButton(hDlg, IDCANCEL);
  1643. }
  1644. return TRUE;
  1645. case WM_COMMAND:
  1646. switch (LOWORD(wParam)) {
  1647. case IDOK:
  1648. lpUserInfo = (LPUSERINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1649. if (!lpUserInfo) {
  1650. EndDialog (hDlg, FALSE);
  1651. break;
  1652. }
  1653. //
  1654. // Determine what the user wants
  1655. //
  1656. if (IsDlgButtonChecked(hDlg, IDC_UPTYPE_LOCAL)) {
  1657. lpUserInfo->dwProfileType = USERINFO_LOCAL;
  1658. } else {
  1659. BOOL bReadOnly = FALSE;
  1660. HKEY hSubKey;
  1661. DWORD dwSize, dwType;
  1662. //
  1663. // Check for a roaming profile security/read only preference
  1664. //
  1665. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  1666. &hSubKey) == ERROR_SUCCESS) {
  1667. dwSize = sizeof(bReadOnly);
  1668. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  1669. (LPBYTE) &bReadOnly, &dwSize);
  1670. RegCloseKey(hSubKey);
  1671. }
  1672. //
  1673. // Check for a roaming profile security/read only policy
  1674. //
  1675. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ,
  1676. &hSubKey) == ERROR_SUCCESS) {
  1677. dwSize = sizeof(bReadOnly);
  1678. RegQueryValueEx(hSubKey, READONLY_RUP, NULL, &dwType,
  1679. (LPBYTE) &bReadOnly, &dwSize);
  1680. RegCloseKey(hSubKey);
  1681. }
  1682. if (bReadOnly) {
  1683. lpUserInfo->dwProfileType = USERINFO_READONLY;
  1684. }
  1685. else {
  1686. lpUserInfo->dwProfileType = USERINFO_FLOATING;
  1687. }
  1688. }
  1689. EndDialog(hDlg, TRUE);
  1690. break;
  1691. case IDCANCEL:
  1692. EndDialog(hDlg, FALSE);
  1693. break;
  1694. default:
  1695. break;
  1696. }
  1697. break;
  1698. case WM_HELP: // F1
  1699. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  1700. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1701. break;
  1702. case WM_CONTEXTMENU: // right mouse click
  1703. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  1704. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  1705. return (TRUE);
  1706. }
  1707. return (FALSE);
  1708. }
  1709. //*************************************************************
  1710. //
  1711. // UPInitCopyDlg()
  1712. //
  1713. // Purpose: Initializes the copy profile dialog
  1714. //
  1715. // Parameters: hDlg - Dialog box handle
  1716. // lParam - lParam (lpUserInfo)
  1717. //
  1718. // Return: TRUE if successful
  1719. // FALSE if an error occurs
  1720. //
  1721. // Comments:
  1722. //
  1723. // History: Date Author Comment
  1724. // 2/26/96 ericflo Created
  1725. //
  1726. //*************************************************************
  1727. BOOL UPInitCopyDlg (HWND hDlg, LPARAM lParam)
  1728. {
  1729. LPUSERINFO lpUserInfo;
  1730. LPUPCOPYINFO lpUPCopyInfo;
  1731. HKEY hKey;
  1732. LONG lResult;
  1733. TCHAR szBuffer[MAX_PATH];
  1734. TCHAR szTemp[100];
  1735. TCHAR szTemp2[100];
  1736. DWORD dwTempSize = 100, dwTemp2Size = 100;
  1737. PSID pSid;
  1738. DWORD dwSize, dwType;
  1739. SID_NAME_USE SidName;
  1740. lpUserInfo = (LPUSERINFO) lParam;
  1741. if (!lpUserInfo) {
  1742. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1743. return FALSE;
  1744. }
  1745. //
  1746. // Create a CopyInfo structure
  1747. //
  1748. lpUPCopyInfo = (LPUPCOPYINFO) MemAlloc(LPTR, sizeof(UPCOPYINFO));
  1749. if (!lpUPCopyInfo) {
  1750. return FALSE;
  1751. }
  1752. lpUPCopyInfo->dwFlags = 0;
  1753. lpUPCopyInfo->lpUserInfo = lpUserInfo;
  1754. lpUPCopyInfo->bDefaultSecurity = TRUE;
  1755. //
  1756. // Get the user's sid
  1757. //
  1758. wsprintf (szBuffer, TEXT("%s\\%s"), PROFILE_MAPPING, lpUserInfo->lpSid);
  1759. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1760. szBuffer,
  1761. 0,
  1762. KEY_READ,
  1763. &hKey);
  1764. if (lResult != ERROR_SUCCESS) {
  1765. MemFree (lpUPCopyInfo);
  1766. SetLastError(lResult);
  1767. return FALSE;
  1768. }
  1769. //
  1770. // Query for the sid size
  1771. //
  1772. dwSize = 0;
  1773. lResult = RegQueryValueEx (hKey,
  1774. TEXT("Sid"),
  1775. NULL,
  1776. &dwType,
  1777. NULL,
  1778. &dwSize);
  1779. if (lResult != ERROR_SUCCESS) {
  1780. RegCloseKey (hKey);
  1781. MemFree (lpUPCopyInfo);
  1782. SetLastError(lResult);
  1783. return FALSE;
  1784. }
  1785. //
  1786. // Actually get the sid
  1787. //
  1788. pSid = MemAlloc (LPTR, dwSize);
  1789. if (!pSid) {
  1790. RegCloseKey (hKey);
  1791. MemFree (lpUPCopyInfo);
  1792. SetLastError(ERROR_OUTOFMEMORY);
  1793. return FALSE;
  1794. }
  1795. lResult = RegQueryValueEx (hKey,
  1796. TEXT("Sid"),
  1797. NULL,
  1798. &dwType,
  1799. (LPBYTE) pSid,
  1800. &dwSize);
  1801. if (lResult != ERROR_SUCCESS) {
  1802. RegCloseKey (hKey);
  1803. MemFree (pSid);
  1804. MemFree (lpUPCopyInfo);
  1805. SetLastError(lResult);
  1806. return FALSE;
  1807. }
  1808. lpUPCopyInfo->pSid = pSid;
  1809. RegCloseKey (hKey);
  1810. //
  1811. // Get the friendly name
  1812. //
  1813. if (!LookupAccountSid (NULL, pSid, szTemp, &dwTempSize,
  1814. szTemp2, &dwTemp2Size, &SidName)) {
  1815. MemFree (pSid);
  1816. MemFree (lpUPCopyInfo);
  1817. return FALSE;
  1818. }
  1819. //
  1820. // Display nothing in the edit control till user sets it
  1821. // explicitly
  1822. //
  1823. szBuffer[0] = TEXT('\0');
  1824. SetDlgItemText (hDlg, IDC_COPY_USER, szBuffer);
  1825. //
  1826. // Save the copyinfo structure in the extra words
  1827. //
  1828. SetWindowLongPtr (hDlg, GWLP_USERDATA, (LPARAM) lpUPCopyInfo);
  1829. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  1830. SetDefButton(hDlg, IDCANCEL);
  1831. return TRUE;
  1832. }
  1833. //*************************************************************
  1834. //
  1835. // UPCopyProfile()
  1836. //
  1837. // Purpose: Displays the copy profile dialog box
  1838. //
  1839. // Parameters: hDlg - Dialog box handle
  1840. //
  1841. // Return: void
  1842. //
  1843. // Comments:
  1844. //
  1845. // History: Date Author Comment
  1846. // 2/13/96 ericflo Created
  1847. //
  1848. //*************************************************************
  1849. void UPCopyProfile(HWND hDlg)
  1850. {
  1851. int selection, iTypeID;
  1852. HWND hwndTemp;
  1853. LPUSERINFO lpUserInfo;
  1854. LV_ITEM item;
  1855. //
  1856. // Get the selected profile
  1857. //
  1858. hwndTemp = GetDlgItem (hDlg, IDC_UP_LISTVIEW);
  1859. selection = GetSelectedItem (hwndTemp);
  1860. if (selection == -1) {
  1861. return;
  1862. }
  1863. item.mask = LVIF_PARAM;
  1864. item.iItem = selection;
  1865. item.iSubItem = 0;
  1866. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1867. lpUserInfo = (LPUSERINFO) item.lParam;
  1868. } else {
  1869. lpUserInfo = NULL;
  1870. }
  1871. if (!lpUserInfo) {
  1872. return;
  1873. }
  1874. //
  1875. // Display the Copy Profile dialog
  1876. //
  1877. if (!DialogBoxParam (hInstance, MAKEINTRESOURCE(IDD_UP_COPY), hDlg,
  1878. UPCopyDlgProc, (LPARAM)lpUserInfo)) {
  1879. return;
  1880. }
  1881. }
  1882. //*************************************************************
  1883. //
  1884. // UPCopyDlgProc()
  1885. //
  1886. // Purpose: Dialog box procedure for copying a profile
  1887. //
  1888. // Parameters: hDlg - handle to the dialog box
  1889. // uMsg - window message
  1890. // wParam - wParam
  1891. // lParam - lParam
  1892. //
  1893. // Return: TRUE if message was processed
  1894. // FALSE if not
  1895. //
  1896. // Comments:
  1897. //
  1898. // History: Date Author Comment
  1899. // 2/13/96 ericflo Created
  1900. //
  1901. //*************************************************************
  1902. INT_PTR APIENTRY UPCopyDlgProc (HWND hDlg, UINT uMsg,
  1903. WPARAM wParam, LPARAM lParam)
  1904. {
  1905. LPUPCOPYINFO lpUPCopyInfo;
  1906. WIN32_FILE_ATTRIBUTE_DATA fad;
  1907. switch (uMsg) {
  1908. case WM_INITDIALOG:
  1909. if (!UPInitCopyDlg(hDlg, lParam)) {
  1910. UPDisplayErrorMessage(hDlg, GetLastError(), NULL);
  1911. EndDialog(hDlg, FALSE);
  1912. }
  1913. return TRUE;
  1914. case WM_COMMAND:
  1915. switch (LOWORD(wParam)) {
  1916. case IDOK:
  1917. {
  1918. TCHAR szDir[MAX_PATH];
  1919. TCHAR szTemp[MAX_PATH];
  1920. HCURSOR hOldCursor;
  1921. lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1922. if (!lpUPCopyInfo) {
  1923. EndDialog (hDlg, FALSE);
  1924. break;
  1925. }
  1926. GetDlgItemText (hDlg, IDC_COPY_PATH, szTemp, MAX_PATH);
  1927. if (ExpandEnvironmentStrings (szTemp, szDir, MAX_PATH) > MAX_PATH) {
  1928. lstrcpy (szDir, szTemp);
  1929. }
  1930. //
  1931. // If the directory already exists "Warn the user"
  1932. //
  1933. if (GetFileAttributesEx (szDir, GetFileExInfoStandard, &fad)) {
  1934. if (!ConfirmDirectory(hDlg, szDir))
  1935. break;
  1936. //
  1937. // If it is just a file, delete it
  1938. //
  1939. // If it is a directory and if the user has decided the
  1940. // user that needs to have permissions, then delete the directory.
  1941. // and set ACLs using this Sid.
  1942. //
  1943. // Otherwise if the directory doesn't exist use the default ACLs.
  1944. // if it does exist, use the current ACLs
  1945. //
  1946. if (!(fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  1947. SetFileAttributes(szDir, FILE_ATTRIBUTE_NORMAL);
  1948. DeleteFile(szDir);
  1949. }
  1950. else if (!(lpUPCopyInfo->bDefaultSecurity)) {
  1951. if (!Delnode(szDir)) {
  1952. WCHAR szTitle[100], szMsgFmt[100], szMessage[600];
  1953. if (!LoadString (hInstance, IDS_UP_ERRORTITLE, szTitle, 100))
  1954. break;
  1955. if (!LoadString (hInstance, IDS_UP_DELNODE_ERROR, szMsgFmt, 100))
  1956. break;
  1957. wsprintf(szMessage, szMsgFmt, szDir);
  1958. MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_ICONSTOP);
  1959. break;
  1960. }
  1961. }
  1962. }
  1963. hOldCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));
  1964. if (!UPCreateProfile (hDlg, lpUPCopyInfo, szDir, NULL)) {
  1965. SetCursor(hOldCursor);
  1966. break;
  1967. }
  1968. MemFree (lpUPCopyInfo->pSid);
  1969. MemFree (lpUPCopyInfo);
  1970. SetCursor(hOldCursor);
  1971. EndDialog(hDlg, TRUE);
  1972. }
  1973. break;
  1974. case IDCANCEL:
  1975. lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  1976. if (lpUPCopyInfo) {
  1977. MemFree (lpUPCopyInfo->pSid);
  1978. MemFree(lpUPCopyInfo);
  1979. }
  1980. EndDialog(hDlg, FALSE);
  1981. break;
  1982. case IDC_COPY_BROWSE:
  1983. {
  1984. BROWSEINFO BrowseInfo;
  1985. TCHAR szBuffer[MAX_PATH];
  1986. LPITEMIDLIST pidl;
  1987. LoadString(hInstance, IDS_UP_DIRPICK, szBuffer, MAX_PATH);
  1988. BrowseInfo.hwndOwner = hDlg;
  1989. BrowseInfo.pidlRoot = NULL;
  1990. BrowseInfo.pszDisplayName = szBuffer;
  1991. BrowseInfo.lpszTitle = szBuffer;
  1992. BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
  1993. BrowseInfo.lpfn = NULL;
  1994. BrowseInfo.lParam = 0;
  1995. pidl = SHBrowseForFolder (&BrowseInfo);
  1996. if (pidl) {
  1997. SHGetPathFromIDList(pidl, szBuffer);
  1998. SHFree (pidl);
  1999. SetDlgItemText (hDlg, IDC_COPY_PATH, szBuffer);
  2000. SetFocus (GetDlgItem(hDlg, IDOK));
  2001. }
  2002. }
  2003. break;
  2004. case IDC_COPY_PATH:
  2005. if (HIWORD(wParam) == EN_UPDATE) {
  2006. if (SendDlgItemMessage(hDlg, IDC_COPY_PATH,
  2007. EM_LINELENGTH, 0, 0)) {
  2008. EnableWindow (GetDlgItem(hDlg, IDOK), TRUE);
  2009. SetDefButton(hDlg, IDOK);
  2010. } else {
  2011. EnableWindow (GetDlgItem(hDlg, IDOK), FALSE);
  2012. SetDefButton(hDlg, IDCANCEL);
  2013. }
  2014. }
  2015. break;
  2016. case IDC_COPY_PROFILE:
  2017. SetFocus (GetDlgItem(hDlg, IDC_COPY_PATH));
  2018. break;
  2019. case IDC_COPY_CHANGE:
  2020. {
  2021. LPUSERDETAILS lpUserDetails;
  2022. DWORD dwSize = 1024;
  2023. TCHAR szUserName[200];
  2024. PSID pNewSid;
  2025. lpUPCopyInfo = (LPUPCOPYINFO) GetWindowLongPtr(hDlg, GWLP_USERDATA);
  2026. if (!lpUPCopyInfo) {
  2027. EndDialog (hDlg, FALSE);
  2028. break;
  2029. }
  2030. lpUserDetails = (LPUSERDETAILS) MemAlloc (LPTR, dwSize);
  2031. if (!lpUserDetails) {
  2032. break;
  2033. }
  2034. if (UPGetUserSelection(hDlg, lpUserDetails) != S_OK) {
  2035. MemFree(lpUserDetails);
  2036. break;
  2037. }
  2038. // Save our new sid
  2039. //
  2040. lpUPCopyInfo->bDefaultSecurity = FALSE; // at this point user has selected a Sid
  2041. MemFree (lpUPCopyInfo->pSid);
  2042. lpUPCopyInfo->pSid = lpUserDetails->psidUser;
  2043. // Update the edit control
  2044. lstrcpy(szUserName, lpUserDetails->pszDomainName);
  2045. lstrcat(szUserName, TEXT("\\"));
  2046. lstrcat(szUserName, lpUserDetails->pszAccountName);
  2047. SetDlgItemText (hDlg, IDC_COPY_USER, szUserName);
  2048. MemFree(lpUserDetails->pszDomainName);
  2049. MemFree(lpUserDetails->pszAccountName);
  2050. // Cleanup
  2051. MemFree (lpUserDetails);
  2052. }
  2053. break;
  2054. default:
  2055. break;
  2056. }
  2057. break;
  2058. case WM_HELP: // F1
  2059. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
  2060. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  2061. break;
  2062. case WM_CONTEXTMENU: // right mouse click
  2063. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  2064. (DWORD_PTR) (LPSTR) aUserProfileHelpIds);
  2065. return (TRUE);
  2066. }
  2067. return (FALSE);
  2068. }
  2069. //*************************************************************
  2070. //
  2071. // ConfirmDirectory()
  2072. //
  2073. // Purpose: Confirms the directory selected
  2074. //
  2075. // Parameters:
  2076. // hDlg - handle to the parent Dialogbox
  2077. // szDir - Direcory selected by user that exists
  2078. //
  2079. // Return: TRUE if it is confirmed
  2080. // FALSE if not
  2081. //
  2082. // Comments:
  2083. //
  2084. // History: Date Author Comment
  2085. // 6/24/99 ushaji Created
  2086. //
  2087. //*************************************************************
  2088. BOOL ConfirmDirectory(HWND hDlg, LPTSTR szDir)
  2089. {
  2090. LPTSTR szMsgTemplate=NULL, szMsg1=NULL, szMsg=NULL;
  2091. BOOL bRetVal = FALSE;
  2092. szMsgTemplate = (LPTSTR) MemAlloc(LPTR, sizeof(TCHAR)*MAX_PATH);
  2093. if (!szMsgTemplate)
  2094. goto Exit;
  2095. szMsg1 = (LPTSTR) MemAlloc(LPTR, sizeof(TCHAR)*MAX_PATH);
  2096. if (!szMsg1)
  2097. goto Exit;
  2098. szMsg = (LPTSTR) MemAlloc(LPTR, sizeof(TCHAR)*(500+MAX_PATH));
  2099. if (!szMsg)
  2100. goto Exit;
  2101. if (!LoadString (hInstance, IDS_UP_CONFIRMCOPYMSG, szMsgTemplate, MAX_PATH)) {
  2102. goto Exit;
  2103. }
  2104. wsprintf (szMsg, szMsgTemplate, szDir);
  2105. if (!LoadString (hInstance, IDS_UP_CONFIRMCOPYTITLE, szMsg1, MAX_PATH)) {
  2106. goto Exit;
  2107. }
  2108. if (MessageBox(hDlg, szMsg, szMsg1,
  2109. MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
  2110. bRetVal = TRUE;
  2111. Exit:
  2112. if (szMsgTemplate)
  2113. MemFree(szMsgTemplate);
  2114. if (szMsg)
  2115. MemFree(szMsg);
  2116. if (szMsg1)
  2117. MemFree(szMsg1);
  2118. return bRetVal;
  2119. }
  2120. //*************************************************************
  2121. //
  2122. // UPGetUserSelection()
  2123. //
  2124. // Purpose: Shows a UI and gets the user to select a
  2125. // username
  2126. //
  2127. // Parameters: hDlg - Parent window handle
  2128. // lpUserDetails - Pointer to an allocated user details
  2129. // structure which gets filled up if required
  2130. //
  2131. //
  2132. // Return: TRUE if successful
  2133. // FALSE if an error occurs or user chooses cancel
  2134. //
  2135. // Comments:
  2136. //
  2137. // History: Date Author Comment
  2138. // 4/14/99 ushaji adapted from Rahulth
  2139. //
  2140. //*************************************************************
  2141. HRESULT UPGetUserSelection(HWND hDlg, LPUSERDETAILS lpUserDetails)
  2142. {
  2143. PCWSTR apwszAttribs[] = {L"ObjectSid"};
  2144. DWORD dwError = ERROR_SUCCESS;
  2145. HRESULT hr = S_FALSE;
  2146. IDsObjectPicker * pDsObjectPicker = NULL;
  2147. DSOP_INIT_INFO InitInfo;
  2148. const ULONG cbNumScopes = 3;
  2149. DSOP_SCOPE_INIT_INFO ascopes[cbNumScopes];
  2150. IDataObject * pdo = NULL;
  2151. STGMEDIUM stgmedium = {TYMED_HGLOBAL, NULL};
  2152. UINT cf = 0;
  2153. PDS_SELECTION_LIST pDsSelList = NULL;
  2154. FORMATETC formatetc = {
  2155. (CLIPFORMAT)cf,
  2156. NULL,
  2157. DVASPECT_CONTENT,
  2158. -1,
  2159. TYMED_HGLOBAL
  2160. };
  2161. PDS_SELECTION pDsSelection = NULL;
  2162. BOOL bAllocatedStgMedium = FALSE;
  2163. SAFEARRAY * pVariantArr = NULL;
  2164. PSID pSid = NULL;
  2165. SID_NAME_USE eUse;
  2166. DWORD dwNameLen, dwDomLen, dwSize;
  2167. ZeroMemory(lpUserDetails, sizeof(USERDETAILS));
  2168. // This code is not uninitializing COM.
  2169. hr = CoInitialize(NULL);
  2170. if (FAILED(hr))
  2171. {
  2172. goto Exit;
  2173. }
  2174. hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void **) &pDsObjectPicker);
  2175. if (FAILED(hr))
  2176. {
  2177. goto Exit;
  2178. }
  2179. //Initialize the scopes
  2180. ZeroMemory (ascopes, cbNumScopes * sizeof (DSOP_SCOPE_INIT_INFO));
  2181. ascopes[0].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  2182. ascopes[0].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
  2183. ascopes[0].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
  2184. ascopes[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS |
  2185. DSOP_FILTER_BUILTIN_GROUPS |
  2186. DSOP_FILTER_WELL_KNOWN_PRINCIPALS |
  2187. DSOP_FILTER_UNIVERSAL_GROUPS_DL |
  2188. DSOP_FILTER_UNIVERSAL_GROUPS_SE |
  2189. DSOP_FILTER_GLOBAL_GROUPS_DL |
  2190. DSOP_FILTER_GLOBAL_GROUPS_SE |
  2191. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_DL |
  2192. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  2193. ascopes[1].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  2194. ascopes[1].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  2195. ascopes[1].FilterFlags.Uplevel.flBothModes =
  2196. ascopes[0].FilterFlags.Uplevel.flBothModes;
  2197. ascopes[2].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  2198. ascopes[2].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER |
  2199. DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN |
  2200. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN;
  2201. ascopes[2].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS |
  2202. DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS |
  2203. DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS |
  2204. DSOP_DOWNLEVEL_FILTER_WORLD |
  2205. DSOP_DOWNLEVEL_FILTER_AUTHENTICATED_USER |
  2206. DSOP_DOWNLEVEL_FILTER_DIALUP |
  2207. DSOP_DOWNLEVEL_FILTER_INTERACTIVE |
  2208. DSOP_DOWNLEVEL_FILTER_NETWORK;
  2209. //Populate the InitInfo structure that is used to initialize the object
  2210. //picker.
  2211. ZeroMemory (&InitInfo, sizeof (InitInfo));
  2212. InitInfo.cbSize = sizeof (InitInfo);
  2213. InitInfo.cDsScopeInfos = cbNumScopes;
  2214. InitInfo.aDsScopeInfos = ascopes;
  2215. InitInfo.cAttributesToFetch = 1;
  2216. InitInfo.apwzAttributeNames = apwszAttribs;
  2217. hr = pDsObjectPicker->Initialize (&InitInfo);
  2218. if (FAILED(hr))
  2219. {
  2220. goto Exit;
  2221. }
  2222. hr = pDsObjectPicker->InvokeDialog (hDlg, &pdo);
  2223. if (FAILED(hr))
  2224. {
  2225. goto Exit;
  2226. }
  2227. if (S_FALSE == hr)
  2228. { //the user hit cancel
  2229. goto Exit;
  2230. }
  2231. //if we are here, the user chose, OK, so find out what group was chosen
  2232. cf = RegisterClipboardFormat (CFSTR_DSOP_DS_SELECTION_LIST);
  2233. if (0 == cf)
  2234. {
  2235. hr = HRESULT_FROM_WIN32(GetLastError());
  2236. goto Exit;
  2237. }
  2238. //set the clipformat for the formatetc structure
  2239. formatetc.cfFormat = (CLIPFORMAT)cf;
  2240. hr = pdo->GetData (&formatetc, &stgmedium);
  2241. if (FAILED(hr))
  2242. {
  2243. goto Exit;
  2244. }
  2245. bAllocatedStgMedium = TRUE;
  2246. pDsSelList = (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
  2247. if (NULL == pDsSelList)
  2248. {
  2249. hr = HRESULT_FROM_WIN32(GetLastError());
  2250. goto Exit;
  2251. }
  2252. if (!pDsSelList->cItems) //some item must have been selected
  2253. {
  2254. hr = E_UNEXPECTED;
  2255. goto Exit;
  2256. }
  2257. pDsSelection = &(pDsSelList->aDsSelection[0]);
  2258. //we must get the ObjectSid attribute, otherwise we fail
  2259. if (! (VT_ARRAY & pDsSelection->pvarFetchedAttributes->vt))
  2260. {
  2261. hr = E_UNEXPECTED;
  2262. goto Exit;
  2263. }
  2264. pVariantArr = pDsSelection->pvarFetchedAttributes->parray;
  2265. pSid = (PSID) pVariantArr->pvData;
  2266. //store away the string representation of this sid
  2267. dwSize = GetLengthSid (pSid);
  2268. lpUserDetails->psidUser = MemAlloc (LPTR, dwSize);
  2269. if (!lpUserDetails->psidUser) {
  2270. hr = E_OUTOFMEMORY;
  2271. goto Exit;
  2272. }
  2273. if (!CopySid (dwSize, lpUserDetails->psidUser, pSid)) {
  2274. hr = HRESULT_FROM_WIN32(GetLastError());
  2275. goto Exit;
  2276. }
  2277. lpUserDetails->pszDomainName = (LPTSTR) MemAlloc (LPTR, MAX_PATH);
  2278. lpUserDetails->pszAccountName = (LPTSTR) MemAlloc (LPTR, MAX_PATH);
  2279. if ((!lpUserDetails->pszDomainName) || (!lpUserDetails->pszAccountName)) {
  2280. hr = E_OUTOFMEMORY;
  2281. goto Exit;
  2282. }
  2283. dwNameLen = dwDomLen = MAX_PATH;
  2284. if (!LookupAccountSid (NULL, pSid, lpUserDetails->pszAccountName, &dwNameLen,
  2285. lpUserDetails->pszDomainName, &dwDomLen,
  2286. &eUse))
  2287. {
  2288. hr = HRESULT_FROM_WIN32(GetLastError());
  2289. goto Exit;
  2290. }
  2291. hr = S_OK;
  2292. Exit:
  2293. if (pDsSelList)
  2294. GlobalUnlock (stgmedium.hGlobal);
  2295. if (bAllocatedStgMedium)
  2296. ReleaseStgMedium (&stgmedium);
  2297. if (pdo)
  2298. pdo->Release();
  2299. if (pDsObjectPicker)
  2300. pDsObjectPicker->Release ();
  2301. if (hr != S_OK) {
  2302. if (lpUserDetails->psidUser)
  2303. MemFree(lpUserDetails->psidUser);
  2304. if (lpUserDetails->pszDomainName)
  2305. MemFree(lpUserDetails->pszDomainName);
  2306. if (lpUserDetails->pszAccountName)
  2307. MemFree(lpUserDetails->pszAccountName);
  2308. }
  2309. return hr;
  2310. }
  2311. //*************************************************************
  2312. //
  2313. // UPCreateProfile()
  2314. //
  2315. // Purpose: Creates a copy of the specified profile with
  2316. // the correct security.
  2317. //
  2318. // Parameters: lpUPCopyInfo - Copy Dialog information
  2319. // lpDest - Destination directory
  2320. // pNewSecDesc - New security descriptor
  2321. //
  2322. // Return: TRUE if successful
  2323. // FALSE if an error occurs
  2324. //
  2325. // Comments:
  2326. //
  2327. // History: Date Author Comment
  2328. // 2/13/96 ericflo Created
  2329. //
  2330. //*************************************************************
  2331. BOOL UPCreateProfile (HWND hDlg, LPUPCOPYINFO lpUPCopyInfo, LPTSTR lpDest,
  2332. PSECURITY_DESCRIPTOR pNewSecDesc)
  2333. {
  2334. HKEY RootKey, hKey;
  2335. SECURITY_DESCRIPTOR sd;
  2336. SECURITY_ATTRIBUTES sa;
  2337. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2338. PACL pAcl = NULL;
  2339. PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL;
  2340. DWORD cbAcl, AceIndex, dwSize, dwType;
  2341. ACE_HEADER * lpAceHeader;
  2342. HANDLE hFile;
  2343. BOOL bMandatory = FALSE;
  2344. TCHAR szTempPath[MAX_PATH];
  2345. TCHAR szBuffer[MAX_PATH];
  2346. TCHAR szHive[MAX_PATH];
  2347. BOOL bRetVal = FALSE;
  2348. HKEY hKeyProfile;
  2349. LONG Error;
  2350. LPTSTR lpEnd;
  2351. TCHAR szExcludeList1[MAX_PATH];
  2352. TCHAR szExcludeList2[MAX_PATH];
  2353. TCHAR szExcludeList[2 * MAX_PATH];
  2354. DWORD dwErr = 0;
  2355. BOOL bSecurityFailed = TRUE;
  2356. // Getting the previous last error so that we can set the last error to this in the end.
  2357. dwErr = GetLastError();
  2358. if (!lpDest || !(*lpDest)) {
  2359. SetLastError(ERROR_INVALID_PARAMETER);
  2360. return FALSE;
  2361. }
  2362. //
  2363. // Create the security descriptor
  2364. //
  2365. //
  2366. // User Sid
  2367. //
  2368. psidUser = lpUPCopyInfo->pSid;
  2369. //
  2370. // Get the system sid
  2371. //
  2372. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  2373. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  2374. dwErr = GetLastError();
  2375. goto Exit;
  2376. }
  2377. //
  2378. // Get the admin sid
  2379. //
  2380. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2381. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2382. 0, 0, 0, 0, &psidAdmin)) {
  2383. dwErr = GetLastError();
  2384. goto Exit;
  2385. }
  2386. //
  2387. // Allocate space for the ACL
  2388. //
  2389. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  2390. (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  2391. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2392. pAcl = (PACL) MemAlloc(LPTR, cbAcl);
  2393. if (!pAcl) {
  2394. dwErr = GetLastError();
  2395. goto Exit;
  2396. }
  2397. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  2398. dwErr = GetLastError();
  2399. goto Exit;
  2400. }
  2401. //
  2402. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  2403. //
  2404. AceIndex = 0;
  2405. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidUser)) {
  2406. dwErr = GetLastError();
  2407. goto Exit;
  2408. }
  2409. AceIndex++;
  2410. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  2411. dwErr = GetLastError();
  2412. goto Exit;
  2413. }
  2414. AceIndex++;
  2415. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  2416. dwErr = GetLastError();
  2417. goto Exit;
  2418. }
  2419. //
  2420. // Now the inheritable ACEs
  2421. //
  2422. AceIndex++;
  2423. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  2424. dwErr = GetLastError();
  2425. goto Exit;
  2426. }
  2427. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2428. dwErr = GetLastError();
  2429. goto Exit;
  2430. }
  2431. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2432. AceIndex++;
  2433. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  2434. dwErr = GetLastError();
  2435. goto Exit;
  2436. }
  2437. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2438. dwErr = GetLastError();
  2439. goto Exit;
  2440. }
  2441. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2442. AceIndex++;
  2443. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  2444. dwErr = GetLastError();
  2445. goto Exit;
  2446. }
  2447. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2448. dwErr = GetLastError();
  2449. goto Exit;
  2450. }
  2451. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2452. //
  2453. // Put together the security descriptor
  2454. //
  2455. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  2456. dwErr = GetLastError();
  2457. goto Exit;
  2458. }
  2459. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  2460. dwErr = GetLastError();
  2461. goto Exit;
  2462. }
  2463. //
  2464. // Add the security descriptor to the sa structure
  2465. //
  2466. sa.nLength = sizeof(sa);
  2467. sa.lpSecurityDescriptor = &sd;
  2468. sa.bInheritHandle = FALSE;
  2469. //
  2470. // Create the destination directory
  2471. //
  2472. if (!CreateNestedDirectory (lpDest, &sa)) {
  2473. dwErr = GetLastError();
  2474. goto Exit;
  2475. }
  2476. //
  2477. // Save/copy the user's profile to a temp file
  2478. //
  2479. if (!GetTempPath(MAX_PATH, szTempPath)) {
  2480. dwErr = GetLastError();
  2481. goto Exit;
  2482. }
  2483. if (!GetTempFileName (szTempPath, TEXT("TMP"), 0, szBuffer)) {
  2484. dwErr = GetLastError();
  2485. goto Exit;
  2486. }
  2487. DeleteFile (szBuffer);
  2488. //
  2489. // Determine if we are working with a mandatory profile
  2490. //
  2491. lstrcpy (szHive, lpUPCopyInfo->lpUserInfo->lpProfile);
  2492. lpEnd = CheckSlash(szHive);
  2493. lstrcpy (lpEnd, TEXT("ntuser.man"));
  2494. hFile = CreateFile(szHive, GENERIC_READ, FILE_SHARE_READ, NULL,
  2495. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2496. if (hFile != INVALID_HANDLE_VALUE) {
  2497. CloseHandle (hFile);
  2498. bMandatory = TRUE;
  2499. }
  2500. //
  2501. // Test if the requested profile is in use.
  2502. //
  2503. if (IsProfileInUse (lpUPCopyInfo->lpUserInfo->lpSid)) {
  2504. Error = RegOpenKeyEx (HKEY_USERS, lpUPCopyInfo->lpUserInfo->lpSid, 0,
  2505. KEY_READ, &hKeyProfile);
  2506. if (Error != ERROR_SUCCESS) {
  2507. dwErr = Error;
  2508. goto Exit;
  2509. }
  2510. Error = MyRegSaveKey (hKeyProfile, szBuffer);
  2511. RegCloseKey (hKeyProfile);
  2512. if (Error != ERROR_SUCCESS) {
  2513. DeleteFile (szBuffer);
  2514. dwErr = Error;
  2515. goto Exit;
  2516. }
  2517. } else {
  2518. if (!bMandatory) {
  2519. lstrcpy (lpEnd, TEXT("ntuser.dat"));
  2520. }
  2521. if (!CopyFile(szHive, szBuffer, FALSE)) {
  2522. dwErr = GetLastError();
  2523. goto Exit;
  2524. }
  2525. }
  2526. //
  2527. // Apply security to the hive
  2528. //
  2529. Error = MyRegLoadKey (HKEY_USERS, TEMP_PROFILE, szBuffer);
  2530. if (Error != ERROR_SUCCESS) {
  2531. DeleteFile (szBuffer);
  2532. dwErr = Error;
  2533. goto Exit;
  2534. }
  2535. bRetVal = ApplyHiveSecurity(TEMP_PROFILE, psidUser);
  2536. //
  2537. // Query for the user's exclusion list
  2538. //
  2539. if (bRetVal) {
  2540. //
  2541. // Open the root of the user's profile
  2542. //
  2543. if (RegOpenKeyEx(HKEY_USERS, TEMP_PROFILE, 0, KEY_READ, &RootKey) == ERROR_SUCCESS) {
  2544. //
  2545. // Check for a list of directories to exclude both user preferences
  2546. // and user policy
  2547. //
  2548. szExcludeList1[0] = TEXT('\0');
  2549. if (RegOpenKeyEx (RootKey,
  2550. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
  2551. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  2552. dwSize = sizeof(szExcludeList1);
  2553. RegQueryValueEx (hKey,
  2554. TEXT("ExcludeProfileDirs"),
  2555. NULL,
  2556. &dwType,
  2557. (LPBYTE) szExcludeList1,
  2558. &dwSize);
  2559. RegCloseKey (hKey);
  2560. }
  2561. szExcludeList2[0] = TEXT('\0');
  2562. if (RegOpenKeyEx (RootKey,
  2563. TEXT("Software\\Policies\\Microsoft\\Windows\\System"),
  2564. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  2565. dwSize = sizeof(szExcludeList2);
  2566. RegQueryValueEx (hKey,
  2567. TEXT("ExcludeProfileDirs"),
  2568. NULL,
  2569. &dwType,
  2570. (LPBYTE) szExcludeList2,
  2571. &dwSize);
  2572. RegCloseKey (hKey);
  2573. }
  2574. //
  2575. // Merge the user preferences and policy together
  2576. //
  2577. szExcludeList[0] = TEXT('\0');
  2578. if (szExcludeList1[0] != TEXT('\0')) {
  2579. lstrcpy (szExcludeList, szExcludeList1);
  2580. }
  2581. if (szExcludeList2[0] != TEXT('\0')) {
  2582. if (szExcludeList[0] != TEXT('\0')) {
  2583. lstrcat (szExcludeList, TEXT(";"));
  2584. }
  2585. lstrcat (szExcludeList, szExcludeList2);
  2586. }
  2587. // Always exclude USER_CRED_LOCATION
  2588. if (szExcludeList[0] != TEXT('\0')) {
  2589. lstrcat (szExcludeList, TEXT(";"));
  2590. }
  2591. lstrcat(szExcludeList, USER_CRED_LOCATION);
  2592. RegCloseKey (RootKey);
  2593. }
  2594. }
  2595. if (!bRetVal) {
  2596. DeleteFile (szBuffer);
  2597. lstrcat (szBuffer, TEXT(".log"));
  2598. DeleteFile (szBuffer);
  2599. dwErr = GetLastError();
  2600. goto Exit;
  2601. }
  2602. //
  2603. // Unload the hive
  2604. //
  2605. Error = MyRegUnLoadKey(HKEY_USERS, TEMP_PROFILE);
  2606. if (Error != ERROR_SUCCESS) {
  2607. DeleteFile (szBuffer);
  2608. lstrcat (szBuffer, TEXT(".log"));
  2609. DeleteFile (szBuffer);
  2610. dwErr = Error;
  2611. goto Exit;
  2612. }
  2613. //
  2614. // if it has come till here, we have managed to set the ACLs correctly
  2615. //
  2616. bSecurityFailed = FALSE;
  2617. //
  2618. // Copy the profile without the hive
  2619. //
  2620. bRetVal = CopyProfileDirectoryEx (lpUPCopyInfo->lpUserInfo->lpProfile,
  2621. lpDest,
  2622. CPD_IGNOREHIVE |
  2623. CPD_COPYIFDIFFERENT |
  2624. CPD_SYNCHRONIZE |
  2625. CPD_USEEXCLUSIONLIST |
  2626. CPD_IGNORESECURITY |
  2627. CPD_DELDESTEXCLUSIONS,
  2628. NULL,
  2629. (szExcludeList[0] != TEXT('\0')) ?
  2630. szExcludeList : NULL);
  2631. if (!bRetVal) {
  2632. dwErr = GetLastError();
  2633. DeleteFile(szBuffer);
  2634. lstrcat (szBuffer, TEXT(".log"));
  2635. DeleteFile (szBuffer);
  2636. goto Exit;
  2637. }
  2638. //
  2639. // Now copy the hive
  2640. //
  2641. lstrcpy (szHive, lpDest);
  2642. lpEnd = CheckSlash (szHive);
  2643. if (bMandatory) {
  2644. lstrcpy (lpEnd, TEXT("ntuser.man"));
  2645. } else {
  2646. lstrcpy (lpEnd, TEXT("ntuser.dat"));
  2647. }
  2648. //
  2649. // Setting the file attributes first
  2650. //
  2651. SetFileAttributes (szHive, FILE_ATTRIBUTE_NORMAL);
  2652. bRetVal = CopyFile (szBuffer, szHive, FALSE);
  2653. if (!bRetVal) {
  2654. TCHAR szMsg[MAX_PATH], szMsgTemplate[MAX_PATH];
  2655. dwErr = GetLastError();
  2656. szMsg[0] = szMsgTemplate[0] = TEXT('\0');
  2657. LoadString (hInstance, IDS_UP_COPYHIVE_ERROR, szMsgTemplate, MAX_PATH-1);
  2658. wsprintf(szMsg, szMsgTemplate, szHive);
  2659. UPDisplayErrorMessage(hDlg, dwErr, szMsg);
  2660. }
  2661. //
  2662. // Delete the temp file (and log file)
  2663. //
  2664. DeleteFile (szBuffer);
  2665. lstrcat (szBuffer, TEXT(".log"));
  2666. DeleteFile (szBuffer);
  2667. Exit:
  2668. //
  2669. // Free the sids and acl
  2670. //
  2671. if (psidSystem) {
  2672. FreeSid(psidSystem);
  2673. }
  2674. if (psidAdmin) {
  2675. FreeSid(psidAdmin);
  2676. }
  2677. if (pAcl) {
  2678. MemFree (pAcl);
  2679. }
  2680. if ((!bRetVal) && (bSecurityFailed)) {
  2681. TCHAR szMsg[MAX_PATH];
  2682. szMsg[0] = TEXT('\0');
  2683. LoadString (hInstance, IDS_UP_SETSECURITY_ERROR, szMsg, MAX_PATH-1);
  2684. UPDisplayErrorMessage(hDlg, dwErr, szMsg);
  2685. }
  2686. SetLastError(dwErr);
  2687. return (bRetVal);
  2688. }
  2689. //*************************************************************
  2690. //
  2691. // UPDisplayErrorMessage()
  2692. //
  2693. // Purpose: Display an error message
  2694. //
  2695. // Parameters: hWnd - parent window handle
  2696. // uiSystemError - Error code
  2697. //
  2698. // Return: void
  2699. //
  2700. // Comments:
  2701. //
  2702. // History: Date Author Comment
  2703. // 2/14/96 ericflo Created
  2704. //
  2705. //*************************************************************
  2706. VOID UPDisplayErrorMessage(HWND hWnd, UINT uiSystemError, LPTSTR szMsgPrefix)
  2707. {
  2708. TCHAR szMessage[MAX_PATH];
  2709. TCHAR szTitle[100];
  2710. LPTSTR lpEnd;
  2711. if (szMsgPrefix) {
  2712. lstrcpy(szMessage, szMsgPrefix);
  2713. }
  2714. else {
  2715. szMessage[0] = TEXT('\0');
  2716. }
  2717. lpEnd = szMessage+lstrlen(szMessage);
  2718. //
  2719. // retrieve the string matching the Win32 system error
  2720. //
  2721. FormatMessage(
  2722. FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
  2723. NULL,
  2724. uiSystemError,
  2725. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  2726. lpEnd,
  2727. MAX_PATH-lstrlen(szMessage),
  2728. NULL);
  2729. //
  2730. // display a message box with this error
  2731. //
  2732. LoadString (hInstance, IDS_UP_ERRORTITLE, szTitle, 100);
  2733. MessageBox(hWnd, szMessage, szTitle, MB_OK | MB_ICONSTOP);
  2734. return;
  2735. }
  2736. //*************************************************************
  2737. //
  2738. // ApplySecurityToRegistryTree()
  2739. //
  2740. // Purpose: Applies the passed security descriptor to the passed
  2741. // key and all its descendants. Only the parts of
  2742. // the descriptor inddicated in the security
  2743. // info value are actually applied to each registry key.
  2744. //
  2745. // Parameters: RootKey - Registry key
  2746. // pSD - Security Descriptor
  2747. //
  2748. // Return: ERROR_SUCCESS if successful
  2749. //
  2750. // Comments:
  2751. //
  2752. // History: Date Author Comment
  2753. // 7/19/95 ericflo Created
  2754. //
  2755. //*************************************************************
  2756. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
  2757. {
  2758. DWORD Error;
  2759. DWORD SubKeyIndex;
  2760. LPTSTR SubKeyName;
  2761. HKEY SubKey;
  2762. DWORD cchSubKeySize = MAX_PATH + 1;
  2763. //
  2764. // First apply security
  2765. //
  2766. RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
  2767. //
  2768. // Open each sub-key and apply security to its sub-tree
  2769. //
  2770. SubKeyIndex = 0;
  2771. SubKeyName = (LPTSTR) MemAlloc (LPTR, cchSubKeySize * sizeof(TCHAR));
  2772. if (!SubKeyName) {
  2773. return GetLastError();
  2774. }
  2775. while (TRUE) {
  2776. //
  2777. // Get the next sub-key name
  2778. //
  2779. Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
  2780. if (Error != ERROR_SUCCESS) {
  2781. if (Error == ERROR_NO_MORE_ITEMS) {
  2782. //
  2783. // Successful end of enumeration
  2784. //
  2785. Error = ERROR_SUCCESS;
  2786. }
  2787. break;
  2788. }
  2789. //
  2790. // Open the sub-key
  2791. //
  2792. Error = RegOpenKeyEx(RootKey,
  2793. SubKeyName,
  2794. 0,
  2795. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  2796. &SubKey);
  2797. if (Error == ERROR_SUCCESS) {
  2798. //
  2799. // Apply security to the sub-tree
  2800. //
  2801. ApplySecurityToRegistryTree(SubKey, pSD);
  2802. //
  2803. // We're finished with the sub-key
  2804. //
  2805. RegCloseKey(SubKey);
  2806. }
  2807. //
  2808. // Go enumerate the next sub-key
  2809. //
  2810. SubKeyIndex ++;
  2811. }
  2812. MemFree (SubKeyName);
  2813. return Error;
  2814. }
  2815. //*************************************************************
  2816. //
  2817. // ApplyHiveSecurity()
  2818. //
  2819. // Purpose: Initializes the new user hive created by copying
  2820. // the default hive.
  2821. //
  2822. // Parameters: lpHiveName - Name of hive in HKEY_USERS
  2823. // pSid - Sid (used by CreateNewUser)
  2824. //
  2825. // Return: TRUE if successful
  2826. // FALSE if an error occurs
  2827. //
  2828. // Comments:
  2829. //
  2830. // History: Date Author Comment
  2831. // 7/18/95 ericflo Created
  2832. //
  2833. //*************************************************************
  2834. BOOL ApplyHiveSecurity(LPTSTR lpHiveName, PSID pSid)
  2835. {
  2836. DWORD Error;
  2837. HKEY RootKey;
  2838. SECURITY_DESCRIPTOR sd;
  2839. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2840. PACL pAcl = NULL;
  2841. PSID psidUser = pSid, psidSystem = NULL, psidAdmin = NULL;
  2842. DWORD cbAcl, AceIndex;
  2843. ACE_HEADER * lpAceHeader;
  2844. BOOL bRetVal = FALSE;
  2845. //
  2846. // Get the system sid
  2847. //
  2848. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  2849. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  2850. goto Exit;
  2851. }
  2852. //
  2853. // Get the admin sid
  2854. //
  2855. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2856. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2857. 0, 0, 0, 0, &psidAdmin)) {
  2858. goto Exit;
  2859. }
  2860. //
  2861. // Allocate space for the ACL
  2862. //
  2863. cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
  2864. (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  2865. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2866. pAcl = (PACL) MemAlloc(LPTR, cbAcl);
  2867. if (!pAcl) {
  2868. goto Exit;
  2869. }
  2870. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  2871. goto Exit;
  2872. }
  2873. //
  2874. // Add Aces for User, System, and Admin. Non-inheritable ACEs first
  2875. //
  2876. AceIndex = 0;
  2877. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
  2878. goto Exit;
  2879. }
  2880. AceIndex++;
  2881. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  2882. goto Exit;
  2883. }
  2884. AceIndex++;
  2885. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  2886. goto Exit;
  2887. }
  2888. //
  2889. // Now the inheritable ACEs
  2890. //
  2891. AceIndex++;
  2892. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
  2893. goto Exit;
  2894. }
  2895. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2896. goto Exit;
  2897. }
  2898. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2899. AceIndex++;
  2900. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  2901. goto Exit;
  2902. }
  2903. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2904. goto Exit;
  2905. }
  2906. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2907. AceIndex++;
  2908. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  2909. goto Exit;
  2910. }
  2911. if (!GetAce(pAcl, AceIndex, (void **)&lpAceHeader)) {
  2912. goto Exit;
  2913. }
  2914. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  2915. //
  2916. // Put together the security descriptor
  2917. //
  2918. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  2919. goto Exit;
  2920. }
  2921. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  2922. goto Exit;
  2923. }
  2924. //
  2925. // Open the root of the user's profile
  2926. //
  2927. Error = RegOpenKeyEx(HKEY_USERS,
  2928. lpHiveName,
  2929. 0,
  2930. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  2931. &RootKey);
  2932. if (Error == ERROR_SUCCESS) {
  2933. //
  2934. // Set the security descriptor on the entire tree
  2935. //
  2936. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  2937. if (Error == ERROR_SUCCESS) {
  2938. bRetVal = TRUE;
  2939. }
  2940. RegFlushKey (RootKey);
  2941. RegCloseKey(RootKey);
  2942. }
  2943. Exit:
  2944. //
  2945. // Free the sids and acl
  2946. //
  2947. if (psidSystem) {
  2948. FreeSid(psidSystem);
  2949. }
  2950. if (psidAdmin) {
  2951. FreeSid(psidAdmin);
  2952. }
  2953. if (pAcl) {
  2954. MemFree (pAcl);
  2955. }
  2956. return(bRetVal);
  2957. }