Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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