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

3311 lines
96 KiB

  1. //*************************************************************
  2. //
  3. // SETUP.C - API's used by setup to create groups/items
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1995
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include <uenv.h>
  11. #include <sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor
  12. // See ConvertStringSecurityDescriptorToSecurityDescriptor documentation
  13. // for a description of the string security descriptor format.
  14. //
  15. // These ACLs are setup to allow
  16. // System, Administrators, Creator-Owner: Full Control
  17. // Power Users: Modify (RWXD)
  18. // Users: Read (RX)
  19. // Users: Write (folders only)
  20. //
  21. // The combination of "Users: Write (folders only)" and the Creator-Owner ACE
  22. // means that restricted users can create subfolders and files, and have full
  23. // control to files that they create, but they cannot modify or delete files
  24. // created by someone else.
  25. const TCHAR c_szCommonDocumentsACL[] = TEXT("D:P(A;CIOI;GA;;;SY)(A;CIOI;GA;;;BA)(A;CIOIIO;GA;;;CO)(A;CIOI;GRGWGXSD;;;PU)(A;CIOI;GRGX;;;BU)(A;CI;0x116;;;BU)");
  26. const TCHAR c_szCommonAppDataACL[] = TEXT("D:P(A;CIOI;GA;;;SY)(A;CIOI;GA;;;BA)(A;CIOIIO;GA;;;CO)(A;CIOI;GRGWGXSD;;;PU)(A;CIOI;GRGX;;;BU)(A;CI;0x116;;;BU)");
  27. BOOL PrependPath(LPCTSTR szFile, LPTSTR szResult);
  28. BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
  29. LPTSTR lpProfileName);
  30. void HideSpecialProfiles(void);
  31. void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath);
  32. //*************************************************************
  33. //
  34. // CreateGroup()
  35. //
  36. // Purpose: Creates a program group (sub-directory)
  37. //
  38. // Parameters: lpGroupName - Name of group
  39. // bCommonGroup - Common or Personal group
  40. //
  41. // Return: TRUE if successful
  42. // FALSE if an error occurs
  43. //
  44. // Comments:
  45. //
  46. // History: Date Author Comment
  47. // 8/08/95 ericflo Created
  48. // 3/29/00 AlexArm Split into CreateGroup
  49. // and CreateGroupEx
  50. //
  51. //*************************************************************
  52. BOOL WINAPI CreateGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
  53. {
  54. //
  55. // Call CreateGroupEx with no name.
  56. //
  57. return CreateGroupEx( lpGroupName, bCommonGroup, NULL, 0 );
  58. }
  59. //*************************************************************
  60. //
  61. // CreateGroupEx()
  62. //
  63. // Purpose: Creates a program group (sub-directory) and sets
  64. // the localized name for the program group
  65. //
  66. // Parameters: lpGroupName - Name of group
  67. // bCommonGroup - Common or Personal group
  68. // lpResourceModuleName - Name of the resource module.
  69. // uResourceID - Resource ID for the MUI display name.
  70. //
  71. // Return: TRUE if successful
  72. // FALSE if an error occurs
  73. //
  74. // Comments:
  75. //
  76. // History: Date Author Comment
  77. // 8/08/95 ericflo Created
  78. // 3/29/00 AlexArm Split into CreateGroup
  79. // and CreateGroupEx
  80. //
  81. //*************************************************************
  82. BOOL WINAPI CreateGroupEx(LPCWSTR lpGroupName, BOOL bCommonGroup,
  83. LPCWSTR lpResourceModuleName, UINT uResourceID)
  84. {
  85. TCHAR szDirectory[MAX_PATH];
  86. LPTSTR lpEnd;
  87. LPTSTR lpAdjustedGroupName;
  88. int csidl;
  89. PSHELL32_API pShell32Api;
  90. DWORD dwResult;
  91. //
  92. // Validate parameters
  93. //
  94. if (!lpGroupName || !(*lpGroupName)) {
  95. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: Failing due to NULL group name.")));
  96. return FALSE;
  97. }
  98. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Entering with <%s>."), lpGroupName));
  99. if ( ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  100. return FALSE;
  101. }
  102. //
  103. // Extract the CSIDL (if any) from lpGroupName
  104. //
  105. csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
  106. if (-1 != csidl)
  107. {
  108. //
  109. // Use this csidl
  110. // WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
  111. //
  112. DebugMsg((DM_VERBOSE,
  113. TEXT("CreateGroupEx: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
  114. csidl));
  115. }
  116. else
  117. {
  118. //
  119. // Default to CSIDL_..._PROGRAMS
  120. //
  121. csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
  122. }
  123. //
  124. // Get the programs directory
  125. //
  126. if (!GetSpecialFolderPath (csidl, szDirectory)) {
  127. return FALSE;
  128. }
  129. //
  130. // Now append the requested directory
  131. //
  132. lpEnd = CheckSlash (szDirectory);
  133. lstrcpy (lpEnd, lpAdjustedGroupName);
  134. //
  135. // Create the group (directory)
  136. //
  137. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling CreatedNestedDirectory with <%s>"),
  138. szDirectory));
  139. if (!CreateNestedDirectory(szDirectory, NULL)) {
  140. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: CreatedNestedDirectory failed.")));
  141. return FALSE;
  142. }
  143. //
  144. // If the localized name is specified, set it.
  145. //
  146. if (lpResourceModuleName != NULL) {
  147. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling SHSetLocalizedName.")));
  148. dwResult = pShell32Api->pfnShSetLocalizedName(szDirectory,
  149. lpResourceModuleName, uResourceID);
  150. if (dwResult != ERROR_SUCCESS) {
  151. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: SHSetLocalizedName failed <0x%x>."),
  152. dwResult));
  153. return FALSE;
  154. }
  155. }
  156. //
  157. // Success
  158. //
  159. pShell32Api->pfnShChangeNotify (SHCNE_MKDIR, SHCNF_PATH, szDirectory, NULL);
  160. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Leaving successfully.")));
  161. return TRUE;
  162. }
  163. //*************************************************************
  164. //
  165. // DeleteGroup()
  166. //
  167. // Purpose: Deletes a program group (sub-directory)
  168. //
  169. // Parameters: lpGroupName - Name of group
  170. // bCommonGroup - Common or Personal group
  171. //
  172. // Return: TRUE if successful
  173. // FALSE if an error occurs
  174. //
  175. // Comments:
  176. //
  177. // History: Date Author Comment
  178. // 8/10/95 ericflo Created
  179. //
  180. //*************************************************************
  181. BOOL WINAPI DeleteGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
  182. {
  183. TCHAR szDirectory[MAX_PATH];
  184. LPTSTR lpEnd;
  185. LPTSTR lpAdjustedGroupName;
  186. int csidl;
  187. PSHELL32_API pShell32Api;
  188. //
  189. // Validate parameters
  190. //
  191. if (!lpGroupName || !(*lpGroupName)) {
  192. DebugMsg((DM_WARNING, TEXT("DeleteGroup: Failing due to NULL group name.")));
  193. return FALSE;
  194. }
  195. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Entering with <%s>."), lpGroupName));
  196. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  197. return FALSE;
  198. }
  199. //
  200. // Extract the CSIDL (if any) from lpGroupName
  201. //
  202. csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
  203. if (-1 != csidl)
  204. {
  205. //
  206. // Use this csidl
  207. // WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
  208. //
  209. DebugMsg((DM_VERBOSE,
  210. TEXT("DeleteGroup: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
  211. csidl));
  212. }
  213. else
  214. {
  215. //
  216. // Default to CSIDL_..._PROGRAMS
  217. //
  218. csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
  219. }
  220. //
  221. // Get the programs directory
  222. //
  223. if (!GetSpecialFolderPath (csidl, szDirectory)) {
  224. return FALSE;
  225. }
  226. //
  227. // Now append the requested directory
  228. //
  229. lpEnd = CheckSlash (szDirectory);
  230. lstrcpy (lpEnd, lpAdjustedGroupName);
  231. //
  232. // Delete the group (directory)
  233. //
  234. if (!Delnode(szDirectory)) {
  235. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Delnode failed.")));
  236. return FALSE;
  237. }
  238. //
  239. // Success
  240. //
  241. pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szDirectory, NULL);
  242. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Leaving successfully.")));
  243. return TRUE;
  244. }
  245. //*************************************************************
  246. //
  247. // CreateLinkFile()
  248. //
  249. // Purpose: Creates a link file in the specified directory
  250. //
  251. // Parameters: cidl - CSIDL_ of a special folder
  252. // lpSubDirectory - Subdirectory of special folder
  253. // lpFileName - File name of item
  254. // lpCommandLine - Command line (including args)
  255. // lpIconPath - Icon path (can be NULL)
  256. // iIconIndex - Index of icon in icon path
  257. // lpWorkingDir - Working directory
  258. // wHotKey - Hot key
  259. // iShowCmd - ShowWindow flag
  260. // lpDescription - Description of the item
  261. //
  262. // Return: TRUE if successful
  263. // FALSE if an error occurs
  264. //
  265. // Comments:
  266. //
  267. // History: Date Author Comment
  268. // 3/26/98 ericflo Created
  269. //
  270. //*************************************************************
  271. BOOL WINAPI CreateLinkFile(INT csidl, LPCTSTR lpSubDirectory,
  272. LPCTSTR lpFileName, LPCTSTR lpCommandLine,
  273. LPCTSTR lpIconPath, int iIconIndex,
  274. LPCTSTR lpWorkingDirectory, WORD wHotKey,
  275. int iShowCmd, LPCTSTR lpDescription)
  276. {
  277. return CreateLinkFileEx(csidl, lpSubDirectory, lpFileName, lpCommandLine,
  278. lpIconPath, iIconIndex, lpWorkingDirectory, wHotKey,
  279. iShowCmd, lpDescription, NULL, 0);
  280. }
  281. //*************************************************************
  282. //
  283. // CreateLinkFileEx()
  284. //
  285. // Purpose: Creates a link file in the specified directory
  286. //
  287. // Parameters: cidl - CSIDL_ of a special folder
  288. // lpSubDirectory - Subdirectory of special folder
  289. // lpFileName - File name of item
  290. // lpCommandLine - Command line (including args)
  291. // lpIconPath - Icon path (can be NULL)
  292. // iIconIndex - Index of icon in icon path
  293. // lpWorkingDir - Working directory
  294. // wHotKey - Hot key
  295. // iShowCmd - ShowWindow flag
  296. // lpDescription - Description of the item
  297. // lpResourceModuleName - Name of the resource module.
  298. // uResourceID - Resource ID for the MUI display name.
  299. //
  300. // Return: TRUE if successful
  301. // FALSE if an error occurs
  302. //
  303. // Comments:
  304. //
  305. // History: Date Author Comment
  306. // 3/26/98 ericflo Created
  307. //
  308. //*************************************************************
  309. BOOL WINAPI CreateLinkFileEx(INT csidl, LPCTSTR lpSubDirectory,
  310. LPCTSTR lpFileName, LPCTSTR lpCommandLine,
  311. LPCTSTR lpIconPath, int iIconIndex,
  312. LPCTSTR lpWorkingDirectory, WORD wHotKey,
  313. int iShowCmd, LPCTSTR lpDescription,
  314. LPCWSTR lpResourceModuleName, UINT uResourceID)
  315. {
  316. TCHAR szItem[MAX_PATH];
  317. TCHAR szArgs[MAX_PATH];
  318. TCHAR szLinkName[MAX_PATH];
  319. TCHAR szPath[MAX_PATH];
  320. LPTSTR lpArgs, lpEnd;
  321. IShellLink *psl;
  322. IPersistFile *ppf;
  323. BOOL bRetVal = FALSE;
  324. HINSTANCE hInstOLE32 = NULL;
  325. PFNCOCREATEINSTANCE pfnCoCreateInstance;
  326. PFNCOINITIALIZE pfnCoInitialize;
  327. PFNCOUNINITIALIZE pfnCoUninitialize;
  328. LPTSTR lpAdjustedSubDir = NULL;
  329. PSHELL32_API pShell32Api;
  330. PSHLWAPI_API pShlwapiApi;
  331. DWORD dwResult;
  332. //
  333. // Verbose output
  334. //
  335. #if DBG
  336. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Entering.")));
  337. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: csidl = <0x%x>."), csidl));
  338. if (lpSubDirectory && *lpSubDirectory) {
  339. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpSubDirectory = <%s>."), lpSubDirectory));
  340. }
  341. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpFileName = <%s>."), lpFileName));
  342. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpCommandLine = <%s>."), lpCommandLine));
  343. if (lpIconPath) {
  344. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpIconPath = <%s>."), lpIconPath));
  345. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iIconIndex = <%d>."), iIconIndex));
  346. }
  347. if (lpWorkingDirectory) {
  348. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpWorkingDirectory = <%s>."), lpWorkingDirectory));
  349. } else {
  350. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null working directory. Setting to %%HOMEDRIVE%%%%HOMEPATH%%")));
  351. }
  352. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: wHotKey = <%d>."), wHotKey));
  353. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iShowCmd = <%d>."), iShowCmd));
  354. if (lpDescription) {
  355. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpDescription = <%s>."), lpDescription));
  356. } else {
  357. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null description.")));
  358. }
  359. #endif
  360. //
  361. // Load a few functions we need
  362. //
  363. hInstOLE32 = LoadLibrary (TEXT("ole32.dll"));
  364. if (!hInstOLE32) {
  365. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to load ole32 with %d."),
  366. GetLastError()));
  367. goto ExitNoFree;
  368. }
  369. pfnCoCreateInstance = (PFNCOCREATEINSTANCE)GetProcAddress (hInstOLE32,
  370. "CoCreateInstance");
  371. if (!pfnCoCreateInstance) {
  372. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoCreateInstance with %d."),
  373. GetLastError()));
  374. goto ExitNoFree;
  375. }
  376. pfnCoInitialize = (PFNCOINITIALIZE)GetProcAddress (hInstOLE32,
  377. "CoInitialize");
  378. if (!pfnCoInitialize) {
  379. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoInitialize with %d."),
  380. GetLastError()));
  381. goto ExitNoFree;
  382. }
  383. pfnCoUninitialize = (PFNCOUNINITIALIZE)GetProcAddress (hInstOLE32,
  384. "CoUninitialize");
  385. if (!pfnCoUninitialize) {
  386. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoUninitialize with %d."),
  387. GetLastError()));
  388. goto ExitNoFree;
  389. }
  390. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  391. goto ExitNoFree;
  392. }
  393. pShlwapiApi = LoadShlwapiApi();
  394. if ( !pShlwapiApi ) {
  395. goto ExitNoFree;
  396. }
  397. //
  398. // Get the special folder directory
  399. // First check if there is a CSIDL in the subdirectory
  400. //
  401. if (lpSubDirectory && *lpSubDirectory) {
  402. int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
  403. if (-1 != csidl2)
  404. {
  405. csidl = csidl2;
  406. DebugMsg((DM_VERBOSE,
  407. TEXT("CreateLinkFileEx: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
  408. csidl));
  409. }
  410. }
  411. szLinkName[0] = TEXT('\0');
  412. if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
  413. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to get profiles directory.")));
  414. goto ExitNoFree;
  415. }
  416. if (lpAdjustedSubDir && *lpAdjustedSubDir) {
  417. if (szLinkName[0] != TEXT('\0')) {
  418. lpEnd = CheckSlash (szLinkName);
  419. } else {
  420. lpEnd = szLinkName;
  421. }
  422. lstrcpy (lpEnd, lpAdjustedSubDir);
  423. }
  424. //
  425. // Create the target directory
  426. //
  427. if (!CreateNestedDirectory(szLinkName, NULL)) {
  428. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to create subdirectory <%s> with %d"),
  429. szLinkName, GetLastError()));
  430. goto ExitNoFree;
  431. }
  432. //
  433. // Now tack on the filename and extension.
  434. //
  435. lpEnd = CheckSlash (szLinkName);
  436. lstrcpy (lpEnd, lpFileName);
  437. lstrcat (lpEnd, c_szLNK);
  438. //
  439. // Split the command line into the executable name
  440. // and arguments.
  441. //
  442. lstrcpy (szItem, lpCommandLine);
  443. lpArgs = pShlwapiApi->pfnPathGetArgs(szItem);
  444. if (*lpArgs) {
  445. lstrcpy (szArgs, lpArgs);
  446. lpArgs--;
  447. while (*lpArgs == TEXT(' ')) {
  448. lpArgs--;
  449. }
  450. lpArgs++;
  451. *lpArgs = TEXT('\0');
  452. } else {
  453. szArgs[0] = TEXT('\0');
  454. }
  455. pShlwapiApi->pfnPathUnquoteSpaces (szItem);
  456. //
  457. // Create an IShellLink object
  458. //
  459. pfnCoInitialize(NULL);
  460. if (FAILED(pfnCoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  461. &IID_IShellLink, (LPVOID*)&psl)))
  462. {
  463. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Could not create instance of IShellLink .")));
  464. goto ExitNoFree;
  465. }
  466. //
  467. // Query for IPersistFile
  468. //
  469. if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
  470. {
  471. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: QueryInterface of IShellLink failed.")));
  472. goto ExitFreePSL;
  473. }
  474. //
  475. // Set the item information
  476. //
  477. if (lpDescription) {
  478. psl->lpVtbl->SetDescription(psl, lpDescription);
  479. }
  480. PrependPath(szItem, szPath);
  481. psl->lpVtbl->SetPath(psl, szPath);
  482. psl->lpVtbl->SetArguments(psl, szArgs);
  483. if (lpWorkingDirectory) {
  484. psl->lpVtbl->SetWorkingDirectory(psl, lpWorkingDirectory);
  485. } else {
  486. psl->lpVtbl->SetWorkingDirectory(psl, TEXT("%HOMEDRIVE%%HOMEPATH%"));
  487. }
  488. PrependPath(lpIconPath, szPath);
  489. psl->lpVtbl->SetIconLocation(psl, szPath, iIconIndex);
  490. psl->lpVtbl->SetHotkey(psl, wHotKey);
  491. psl->lpVtbl->SetShowCmd(psl, iShowCmd);
  492. //
  493. // If the localized name is specified, set it.
  494. //
  495. if (lpResourceModuleName != NULL) {
  496. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Calling SHSetLocalizedName on link <%s>."), szLinkName));
  497. ppf->lpVtbl->Save(ppf, szLinkName, TRUE);
  498. dwResult = pShell32Api->pfnShSetLocalizedName(szLinkName,
  499. lpResourceModuleName, uResourceID);
  500. if (dwResult != ERROR_SUCCESS) {
  501. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: SHSetLocalizedName failed <0x%x>."),
  502. dwResult));
  503. goto ExitFreePSL;
  504. }
  505. }
  506. //
  507. // Save the item to disk
  508. //
  509. bRetVal = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
  510. if (bRetVal) {
  511. pShell32Api->pfnShChangeNotify (SHCNE_CREATE, SHCNF_PATH, szLinkName, NULL);
  512. }
  513. //
  514. // Release the IPersistFile object
  515. //
  516. ppf->lpVtbl->Release(ppf);
  517. ExitFreePSL:
  518. //
  519. // Release the IShellLink object
  520. //
  521. psl->lpVtbl->Release(psl);
  522. pfnCoUninitialize();
  523. ExitNoFree:
  524. if (hInstOLE32) {
  525. FreeLibrary (hInstOLE32);
  526. }
  527. //
  528. // Finished.
  529. //
  530. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Leaving with status of %d."), bRetVal));
  531. return bRetVal;
  532. }
  533. //*************************************************************
  534. //
  535. // DeleteLinkFile()
  536. //
  537. // Purpose: Deletes the specified link file
  538. //
  539. // Parameters: csidl - CSIDL of a special folder
  540. // lpSubDirectory - Subdirectory of special folder
  541. // lpFileName - File name of item
  542. // bDeleteSubDirectory - Delete the subdirectory if possible
  543. //
  544. // Return: TRUE if successful
  545. // FALSE if an error occurs
  546. //
  547. // Comments:
  548. //
  549. // History: Date Author Comment
  550. // 3/26/98 ericflo Created
  551. //
  552. //*************************************************************
  553. BOOL WINAPI DeleteLinkFile(INT csidl, LPCTSTR lpSubDirectory,
  554. LPCTSTR lpFileName, BOOL bDeleteSubDirectory)
  555. {
  556. TCHAR szLinkName[MAX_PATH];
  557. LPTSTR lpEnd;
  558. LPTSTR lpAdjustedSubDir = NULL;
  559. PSHELL32_API pShell32Api;
  560. //
  561. // Verbose output
  562. //
  563. #if DBG
  564. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Entering.")));
  565. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: csidl = 0x%x."), csidl));
  566. if (lpSubDirectory && *lpSubDirectory) {
  567. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpSubDirectory = <%s>."), lpSubDirectory));
  568. }
  569. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpFileName = <%s>."), lpFileName));
  570. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: bDeleteSubDirectory = %d."), bDeleteSubDirectory));
  571. #endif
  572. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  573. return FALSE;
  574. }
  575. //
  576. // Get the special folder directory
  577. // First check if there is a CSIDL in the subdirectory
  578. //
  579. if (lpSubDirectory && *lpSubDirectory) {
  580. int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
  581. if (-1 != csidl2)
  582. {
  583. csidl = csidl2;
  584. DebugMsg((DM_VERBOSE,
  585. TEXT("CreateLinkFile: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
  586. csidl));
  587. }
  588. }
  589. szLinkName[0] = TEXT('\0');
  590. if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
  591. return FALSE;
  592. }
  593. if (lpAdjustedSubDir && *lpAdjustedSubDir) {
  594. if (szLinkName[0] != TEXT('\0')) {
  595. lpEnd = CheckSlash (szLinkName);
  596. } else {
  597. lpEnd = szLinkName;
  598. }
  599. lstrcpy (lpEnd, lpAdjustedSubDir);
  600. }
  601. //
  602. // Now tack on the filename and extension.
  603. //
  604. lpEnd = CheckSlash (szLinkName);
  605. lstrcpy (lpEnd, lpFileName);
  606. lstrcat (lpEnd, c_szLNK);
  607. //
  608. // Delete the file
  609. //
  610. if (!DeleteFile (szLinkName)) {
  611. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Failed to delete <%s>. Error = %d"),
  612. szLinkName, GetLastError()));
  613. return FALSE;
  614. }
  615. pShell32Api->pfnShChangeNotify (SHCNE_DELETE, SHCNF_PATH, szLinkName, NULL);
  616. //
  617. // Delete the subdirectory if appropriate (and possible).
  618. //
  619. if (bDeleteSubDirectory) {
  620. *(lpEnd-1) = TEXT('\0');
  621. if (RemoveDirectory(szLinkName)) {
  622. pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szLinkName, NULL);
  623. }
  624. }
  625. //
  626. // Success
  627. //
  628. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Leaving successfully.")));
  629. return TRUE;
  630. }
  631. //*************************************************************
  632. //
  633. // PrependPath()
  634. //
  635. // Purpose: Expands the given filename to have %systemroot%
  636. // if appropriate
  637. //
  638. // Parameters: lpFile - File to check
  639. // lpResult - Result buffer (MAX_PATH chars in size)
  640. //
  641. // Return: TRUE if successful
  642. // FALSE if an error occurs
  643. //
  644. // Comments:
  645. //
  646. // History: Date Author Comment
  647. // 10/11/95 ericflo Created
  648. //
  649. //*************************************************************
  650. BOOL PrependPath(LPCTSTR lpFile, LPTSTR lpResult)
  651. {
  652. TCHAR szReturn [MAX_PATH];
  653. TCHAR szSysRoot[MAX_PATH];
  654. LPTSTR lpFileName;
  655. DWORD dwSysLen;
  656. //
  657. // Verbose Output
  658. //
  659. DebugMsg((DM_VERBOSE, TEXT("PrependPath: Entering with <%s>"),
  660. lpFile ? lpFile : TEXT("NULL")));
  661. if (!lpFile || !*lpFile) {
  662. DebugMsg((DM_VERBOSE, TEXT("PrependPath: lpFile is NULL, setting lpResult to a null string")));
  663. *lpResult = TEXT('\0');
  664. return TRUE;
  665. }
  666. //
  667. // Call SearchPath to find the filename
  668. //
  669. if (!SearchPath (NULL, lpFile, TEXT(".exe"), MAX_PATH, szReturn, &lpFileName)) {
  670. DebugMsg((DM_VERBOSE, TEXT("PrependPath: SearchPath failed with error %d. Using input string"), GetLastError()));
  671. lstrcpy (lpResult, lpFile);
  672. return TRUE;
  673. }
  674. UnExpandSysRoot(szReturn, lpResult);
  675. DebugMsg((DM_VERBOSE, TEXT("PrependPath: Leaving with <%s>"), lpResult));
  676. return TRUE;
  677. }
  678. //*************************************************************
  679. //
  680. // SetFilePermissions()
  681. //
  682. // Purpose: Sets the given permissions on a file or directory
  683. //
  684. // Parameters: lpFile - File to set security on
  685. // pszSD - String security descriptor
  686. //
  687. // Return: (BOOL) TRUE if successful
  688. // FALSE if an error occurs
  689. //
  690. // Comments:
  691. //
  692. // History: Date Author Comment
  693. // 01/25/2001 jeffreys Created
  694. //
  695. //*************************************************************
  696. BOOL SetFilePermissions(LPCTSTR lpFile, LPCTSTR pszSD)
  697. {
  698. PSECURITY_DESCRIPTOR pSD;
  699. BOOL bRetVal = FALSE;
  700. if (ConvertStringSecurityDescriptorToSecurityDescriptor(pszSD, SDDL_REVISION, &pSD, NULL))
  701. {
  702. //
  703. // Set the security
  704. //
  705. if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, pSD))
  706. {
  707. bRetVal = TRUE;
  708. }
  709. else
  710. {
  711. DebugMsg((DM_WARNING, TEXT("SetFilePermissions: SetFileSecurity failed. Error = %d"), GetLastError()));
  712. }
  713. LocalFree(pSD);
  714. }
  715. else
  716. {
  717. DebugMsg((DM_WARNING, TEXT("SetFilePermissions: ConvertStringSDToSD failed. Error = %d"), GetLastError()));
  718. }
  719. return bRetVal;
  720. }
  721. //*************************************************************
  722. //
  723. // ConvertCommonGroups()
  724. //
  725. // Purpose: Calls grpconv.exe to convert progman common groups
  726. // to Explorer common groups, and create floppy links.
  727. //
  728. // NT 4 appended " (Common)" to the common groups. For
  729. // NT 5, we are going to remove this tag.
  730. //
  731. // Parameters: none
  732. //
  733. // Return: TRUE if successful
  734. // FALSE if an error occurs
  735. // Comments:
  736. //
  737. // History: Date Author Comment
  738. // 10/1/95 ericflo Created
  739. // 12/5/96 ericflo Remove common tag
  740. //
  741. //*************************************************************
  742. BOOL ConvertCommonGroups (void)
  743. {
  744. STARTUPINFO si;
  745. PROCESS_INFORMATION ProcessInformation;
  746. BOOL Result;
  747. TCHAR szBuffer[MAX_PATH];
  748. TCHAR szBuffer2[MAX_PATH];
  749. DWORD dwType, dwSize, dwConvert;
  750. BOOL bRunGrpConv = TRUE;
  751. LONG lResult;
  752. HKEY hKey;
  753. HANDLE hFile;
  754. WIN32_FIND_DATA fd;
  755. TCHAR szCommon[30] = {0};
  756. UINT cchCommon, cchFileName;
  757. LPTSTR lpTag, lpEnd, lpEnd2;
  758. //
  759. // Verbose output
  760. //
  761. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Entering.")));
  762. //
  763. // Check if we have run grpconv before.
  764. //
  765. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  766. TEXT("Software\\Program Groups"),
  767. 0,
  768. KEY_ALL_ACCESS,
  769. &hKey);
  770. if (lResult == ERROR_SUCCESS) {
  771. dwSize = sizeof(dwConvert);
  772. lResult = RegQueryValueEx (hKey,
  773. TEXT("ConvertedToLinks"),
  774. NULL,
  775. &dwType,
  776. (LPBYTE)&dwConvert,
  777. &dwSize);
  778. if (lResult == ERROR_SUCCESS) {
  779. //
  780. // If dwConvert is 1, then grpconv has run before.
  781. // Don't run it again.
  782. //
  783. if (dwConvert) {
  784. bRunGrpConv = FALSE;
  785. }
  786. }
  787. //
  788. // Now set the value to prevent grpconv from running in the future
  789. //
  790. dwConvert = 1;
  791. RegSetValueEx (hKey,
  792. TEXT("ConvertedToLinks"),
  793. 0,
  794. REG_DWORD,
  795. (LPBYTE) &dwConvert,
  796. sizeof(dwConvert));
  797. RegCloseKey (hKey);
  798. }
  799. if (bRunGrpConv) {
  800. //
  801. // Initialize process startup info
  802. //
  803. si.cb = sizeof(STARTUPINFO);
  804. si.lpReserved = NULL;
  805. si.lpDesktop = NULL;
  806. si.lpTitle = NULL;
  807. si.dwFlags = 0;
  808. si.lpReserved2 = NULL;
  809. si.cbReserved2 = 0;
  810. //
  811. // Spawn grpconv
  812. //
  813. lstrcpy (szBuffer, TEXT("grpconv -n"));
  814. Result = CreateProcess(
  815. NULL,
  816. szBuffer,
  817. NULL,
  818. NULL,
  819. FALSE,
  820. NORMAL_PRIORITY_CLASS,
  821. NULL,
  822. NULL,
  823. &si,
  824. &ProcessInformation
  825. );
  826. if (!Result) {
  827. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: grpconv failed to start due to error %d."), GetLastError()));
  828. return FALSE;
  829. } else {
  830. //
  831. // Wait for up to 2 minutes
  832. //
  833. WaitForSingleObject(ProcessInformation.hProcess, 120000);
  834. //
  835. // Close our handles to the process and thread
  836. //
  837. CloseHandle(ProcessInformation.hProcess);
  838. CloseHandle(ProcessInformation.hThread);
  839. }
  840. }
  841. //
  842. // Loop through all the program groups in the All Users profile
  843. // and remove the " (Common)" tag.
  844. //
  845. LoadString (g_hDllInstance, IDS_COMMON, szCommon, 30);
  846. cchCommon = lstrlen (szCommon);
  847. if (!GetSpecialFolderPath (CSIDL_COMMON_PROGRAMS, szBuffer2)) {
  848. return FALSE;
  849. }
  850. lstrcpy (szBuffer, szBuffer2);
  851. lpEnd = CheckSlash (szBuffer);
  852. lpEnd2 = CheckSlash (szBuffer2);
  853. lstrcpy (lpEnd, c_szStarDotStar);
  854. hFile = FindFirstFile (szBuffer, &fd);
  855. if (hFile != INVALID_HANDLE_VALUE) {
  856. do {
  857. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  858. cchFileName = lstrlen (fd.cFileName);
  859. if (cchFileName > cchCommon) {
  860. lpTag = fd.cFileName + cchFileName - cchCommon;
  861. if (!lstrcmpi(lpTag, szCommon)) {
  862. lstrcpy (lpEnd, fd.cFileName);
  863. *lpTag = TEXT('\0');
  864. lstrcpy (lpEnd2, fd.cFileName);
  865. if (MoveFileEx (szBuffer, szBuffer2, MOVEFILE_REPLACE_EXISTING)) {
  866. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Successfully changed group name:")));
  867. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
  868. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
  869. } else {
  870. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Failed to change group name with error %d."), GetLastError()));
  871. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
  872. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
  873. }
  874. }
  875. }
  876. }
  877. } while (FindNextFile(hFile, &fd));
  878. FindClose (hFile);
  879. }
  880. //
  881. // Success
  882. //
  883. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Leaving Successfully.")));
  884. return TRUE;
  885. }
  886. //*************************************************************
  887. //
  888. // DetermineProfilesLocation()
  889. //
  890. // Purpose: Determines if the profiles directory
  891. // should be in the old NT4 location or
  892. // the new NT5 location
  893. //
  894. // Parameters: none
  895. //
  896. // Return: TRUE if successful
  897. // FALSE if an error occurs
  898. //
  899. //*************************************************************
  900. BOOL WINAPI DetermineProfilesLocation (BOOL bCleanInstall)
  901. {
  902. TCHAR szDirectory[MAX_PATH];
  903. TCHAR szDest[MAX_PATH];
  904. PTSTR szCurDest;
  905. PCTSTR szLookAhead;
  906. WIN32_FILE_ATTRIBUTE_DATA fad;
  907. DWORD dwSize, dwDisp;
  908. HKEY hKey;
  909. LPTSTR lpEnd;
  910. //
  911. // Check for an unattended entry first
  912. //
  913. if (bCleanInstall) {
  914. if (!ExpandEnvironmentStrings (TEXT("%SystemRoot%\\System32\\$winnt$.inf"), szDirectory,
  915. ARRAYSIZE(szDirectory))) {
  916. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d"), GetLastError()));
  917. return FALSE;
  918. }
  919. szDest[0] = TEXT('\0');
  920. GetPrivateProfileString (TEXT("guiunattended"), TEXT("profilesdir"), TEXT(""),
  921. szDest, MAX_PATH, szDirectory);
  922. if (szDest[0] != TEXT('\0')) {
  923. //
  924. // Since $winnt$.inf is an INF, we must strip out %% pairs
  925. //
  926. szCurDest = szDest;
  927. szLookAhead = szDest;
  928. #ifdef UNICODE
  929. while (*szLookAhead) {
  930. if (szLookAhead[0] == L'%' && szLookAhead[1] == L'%') {
  931. szLookAhead++; // pair of %%; skip one char
  932. }
  933. *szCurDest++ = *szLookAhead++;
  934. }
  935. #else
  936. //
  937. // This code path is not compiled so it has not been tested
  938. //
  939. #error Code written but not tested!
  940. while (*szLookAhead) {
  941. if (IsDbcsLeadByte (*szLookAhead)) {
  942. *szCurDest++ = *szLookAhead++; // copy first half of byte pair
  943. } else if (*szLookAhead == '%') {
  944. if (!IsDbcsLeadByte (szLookAhead[1]) && szLookAhead[1] == '%') {
  945. szLookAhead++; // pair of %%; skip one char
  946. }
  947. }
  948. *szCurDest++ = *szLookAhead++;
  949. }
  950. #endif
  951. *szCurDest = 0;
  952. //
  953. // The unattend profile directory exists. We need to set this
  954. // path in the registry
  955. //
  956. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  957. 0, NULL, REG_OPTION_NON_VOLATILE,
  958. KEY_WRITE, NULL, &hKey,
  959. &dwDisp) == ERROR_SUCCESS) {
  960. if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
  961. 0, REG_EXPAND_SZ, (LPBYTE) szDest,
  962. ((lstrlen(szDest) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  963. DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using unattend location %s for user profiles"), szDest));
  964. }
  965. RegCloseKey (hKey);
  966. }
  967. }
  968. } else {
  969. //
  970. // By default, the OS will try to use the new location for
  971. // user profiles, but if we are doing an upgrade of a machine
  972. // with profiles in the NT4 location, we want to continue
  973. // to use that location.
  974. //
  975. // Build a test path to the old All Users directory on NT4
  976. // to determine which location to use.
  977. //
  978. if (!ExpandEnvironmentStrings (NT4_PROFILES_DIRECTORY, szDirectory,
  979. ARRAYSIZE(szDirectory))) {
  980. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d, setting the dir unexpanded"), GetLastError()));
  981. return FALSE;
  982. }
  983. lpEnd = CheckSlash (szDirectory);
  984. lstrcpy (lpEnd, ALL_USERS);
  985. if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
  986. //
  987. // An app was found that creates an "All Users" directory under NT4 profiles directory
  988. // Check for Default User as well.
  989. //
  990. lstrcpy (lpEnd, DEFAULT_USER);
  991. if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
  992. //
  993. // The old profiles directory exists. We need to set this
  994. // path in the registry
  995. //
  996. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  997. 0, NULL, REG_OPTION_NON_VOLATILE,
  998. KEY_WRITE, NULL, &hKey,
  999. &dwDisp) == ERROR_SUCCESS) {
  1000. if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
  1001. 0, REG_EXPAND_SZ, (LPBYTE) NT4_PROFILES_DIRECTORY,
  1002. ((lstrlen(NT4_PROFILES_DIRECTORY) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  1003. DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using NT4 location for user profiles")));
  1004. }
  1005. RegCloseKey (hKey);
  1006. }
  1007. }
  1008. }
  1009. }
  1010. //
  1011. // Check if the profiles directory exists.
  1012. //
  1013. dwSize = ARRAYSIZE(szDirectory);
  1014. if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1015. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
  1016. return FALSE;
  1017. }
  1018. if (!CreateSecureAdminDirectory(szDirectory, OTHERSIDS_EVERYONE)) {
  1019. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create profiles subdirectory <%s>. Error = %d."),
  1020. szDirectory, GetLastError()));
  1021. return FALSE;
  1022. }
  1023. //
  1024. // Decide where the Default User profile should be
  1025. //
  1026. if (!CheckProfile (szDirectory, DEFAULT_USER_PROFILE, DEFAULT_USER)) {
  1027. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check default user profile Error = %d."),
  1028. GetLastError()));
  1029. return FALSE;
  1030. }
  1031. //
  1032. // Check if the profiles\Default User directory exists
  1033. //
  1034. dwSize = ARRAYSIZE(szDirectory);
  1035. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1036. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query default user profile directory.")));
  1037. return FALSE;
  1038. }
  1039. if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_EVERYONE)) {
  1040. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create Default User subdirectory <%s>. Error = %d."),
  1041. szDirectory, GetLastError()));
  1042. return FALSE;
  1043. }
  1044. SetFileAttributes (szDirectory, FILE_ATTRIBUTE_HIDDEN);
  1045. //
  1046. // Decide where the All Users profile should be
  1047. //
  1048. dwSize = ARRAYSIZE(szDirectory);
  1049. if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1050. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
  1051. return FALSE;
  1052. }
  1053. if (!CheckProfile (szDirectory, ALL_USERS_PROFILE, ALL_USERS)) {
  1054. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check all users profile Error = %d."),
  1055. GetLastError()));
  1056. return FALSE;
  1057. }
  1058. //
  1059. // Check if the profiles\All Users directory exists
  1060. //
  1061. dwSize = ARRAYSIZE(szDirectory);
  1062. if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1063. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query all users profile directory.")));
  1064. return FALSE;
  1065. }
  1066. //
  1067. // Give additional permissions for power users/everyone
  1068. //
  1069. if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_POWERUSERS | OTHERSIDS_EVERYONE)) {
  1070. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create All Users subdirectory <%s>. Error = %d."),
  1071. szDirectory, GetLastError()));
  1072. return FALSE;
  1073. }
  1074. //
  1075. // Hide some special profiles like NetworkService etc.
  1076. //
  1077. if (!bCleanInstall) {
  1078. HideSpecialProfiles();
  1079. }
  1080. return TRUE;
  1081. }
  1082. //*************************************************************
  1083. //
  1084. // InitializeProfiles()
  1085. //
  1086. // Purpose: Confirms / Creates the profile, Default User,
  1087. // and All Users directories, and converts any
  1088. // existing common groups.
  1089. //
  1090. // Parameters:
  1091. //
  1092. // Return: TRUE if successful
  1093. // FALSE if an error occurs
  1094. //
  1095. // Comments: This should only be called by GUI mode setup!
  1096. //
  1097. // History: Date Author Comment
  1098. // 8/08/95 ericflo Created
  1099. //
  1100. //*************************************************************
  1101. BOOL WINAPI InitializeProfiles (BOOL bGuiModeSetup)
  1102. {
  1103. TCHAR szDirectory[MAX_PATH];
  1104. TCHAR szSystemProfile[MAX_PATH];
  1105. TCHAR szTemp[MAX_PATH];
  1106. TCHAR szTemp2[MAX_PATH];
  1107. DWORD dwSize;
  1108. DWORD dwDisp;
  1109. LPTSTR lpEnd;
  1110. DWORD i;
  1111. HKEY hKey;
  1112. SECURITY_DESCRIPTOR sd;
  1113. SECURITY_ATTRIBUTES sa;
  1114. BOOL bRetVal = FALSE;
  1115. DWORD dwErr;
  1116. PSHELL32_API pShell32Api;
  1117. dwErr = GetLastError();
  1118. //
  1119. // Verbose output
  1120. //
  1121. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Entering.")));
  1122. //
  1123. // Create a named mutex that represents GUI mode setup running.
  1124. // This allows other processes that load userenv to detect that
  1125. // setup is running.
  1126. //
  1127. InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
  1128. SetSecurityDescriptorDacl (
  1129. &sd,
  1130. TRUE, // Dacl present
  1131. NULL, // NULL Dacl
  1132. FALSE // Not defaulted
  1133. );
  1134. sa.lpSecurityDescriptor = &sd;
  1135. sa.bInheritHandle = FALSE;
  1136. sa.nLength = sizeof(sa);
  1137. if (!bGuiModeSetup) {
  1138. //
  1139. // block loading user profile
  1140. //
  1141. if (g_hProfileSetup) {
  1142. ResetEvent (g_hProfileSetup);
  1143. }
  1144. }
  1145. dwErr = LoadShell32Api( &pShell32Api );
  1146. if ( dwErr != ERROR_SUCCESS ) {
  1147. goto Exit;
  1148. }
  1149. //
  1150. // Set the USERPROFILE environment variable
  1151. //
  1152. ExpandEnvironmentStrings(SYSTEM_PROFILE_LOCATION, szSystemProfile, MAX_PATH);
  1153. //
  1154. // Requery for the default user profile directory (expanded version)
  1155. //
  1156. dwSize = ARRAYSIZE(szDirectory);
  1157. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1158. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
  1159. dwErr = GetLastError();
  1160. goto Exit;
  1161. }
  1162. //
  1163. // Set the USERPROFILE environment variable
  1164. //
  1165. SetEnvironmentVariable (TEXT("USERPROFILE"), szDirectory);
  1166. //
  1167. // Create all the folders under Default User
  1168. //
  1169. lpEnd = CheckSlash (szDirectory);
  1170. //
  1171. // Loop through the shell folders
  1172. //
  1173. for (i=0; i < g_dwNumShellFolders; i++) {
  1174. lstrcpy (lpEnd, c_ShellFolders[i].szFolderLocation);
  1175. if (!CreateNestedDirectory(szDirectory, NULL)) {
  1176. dwErr = GetLastError();
  1177. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
  1178. szDirectory, dwErr));
  1179. goto Exit;
  1180. }
  1181. if (c_ShellFolders[i].iFolderResourceID != 0) {
  1182. // NOTE this returns an HRESULT
  1183. dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
  1184. c_ShellFolders[i].lpFolderResourceDLL,
  1185. c_ShellFolders[i].iFolderResourceID );
  1186. if (FAILED(dwErr)) {
  1187. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
  1188. szDirectory, dwErr));
  1189. goto Exit;
  1190. }
  1191. }
  1192. if (c_ShellFolders[i].bHidden) {
  1193. SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
  1194. }
  1195. }
  1196. //
  1197. // Remove the %USERPROFILE%\Personal directory if it exists.
  1198. // Windows NT 4.0 had a Personal folder in the root of the
  1199. // user's profile. NT 5.0 renames this folder to My Documents
  1200. //
  1201. if (LoadString (g_hDllInstance, IDS_SH_PERSONAL2, szTemp, ARRAYSIZE(szTemp))) {
  1202. lstrcpy (lpEnd, szTemp);
  1203. RemoveDirectory(szDirectory);
  1204. }
  1205. //
  1206. // Migrate the Template Directory if it exists. Copy it from %systemroot%\shellnew
  1207. // to Templates directory under default user. Do the same for existing profiles.
  1208. //
  1209. if ((LoadString (g_hDllInstance, IDS_SH_TEMPLATES2, szTemp, ARRAYSIZE(szTemp))) &&
  1210. (ExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2))) &&
  1211. (LoadString (g_hDllInstance, IDS_SH_TEMPLATES, szTemp, ARRAYSIZE(szTemp)))) {
  1212. //
  1213. // if all of the above succeeded
  1214. //
  1215. lstrcpy (lpEnd, szTemp);
  1216. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Copying <%s> to %s. Error = %d"), szTemp2, szDirectory));
  1217. CopyProfileDirectory(szTemp2, szDirectory, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE);
  1218. }
  1219. //
  1220. // Remove %USERPROFILE%\Temp if it exists. The Temp directory
  1221. // will now be in the Local Settings folder
  1222. //
  1223. lstrcpy (lpEnd, TEXT("Temp"));
  1224. Delnode(szDirectory);
  1225. //
  1226. // Remove %USERPROFILE%\Temporary Internet Files if it exists. The
  1227. // Temporary Internet Files directory will now be in the Local Settings
  1228. // folder
  1229. //
  1230. if (LoadString (g_hDllInstance, IDS_TEMPINTERNETFILES, szTemp, ARRAYSIZE(szTemp))) {
  1231. lstrcpy (lpEnd, szTemp);
  1232. Delnode(szDirectory);
  1233. }
  1234. //
  1235. // Remove %USERPROFILE%\History if it exists. The History
  1236. // directory will now be in the Local Settings folder
  1237. //
  1238. if (LoadString (g_hDllInstance, IDS_HISTORY, szTemp, ARRAYSIZE(szTemp))) {
  1239. lstrcpy (lpEnd, szTemp);
  1240. Delnode(szDirectory);
  1241. }
  1242. //
  1243. // Set the User Shell Folder paths in the registry
  1244. //
  1245. lstrcpy (szTemp, TEXT(".Default"));
  1246. lpEnd = CheckSlash (szTemp);
  1247. lstrcpy(lpEnd, USER_SHELL_FOLDERS);
  1248. lstrcpy (szDirectory, TEXT("%USERPROFILE%"));
  1249. lpEnd = CheckSlash (szDirectory);
  1250. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1251. 0, NULL, REG_OPTION_NON_VOLATILE,
  1252. KEY_READ | KEY_WRITE, NULL, &hKey,
  1253. &dwDisp) == ERROR_SUCCESS) {
  1254. for (i=0; i < g_dwNumShellFolders; i++) {
  1255. if (c_ShellFolders[i].bAddCSIDL) {
  1256. lstrcpy (lpEnd, c_ShellFolders[i].szFolderLocation);
  1257. RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
  1258. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1259. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1260. }
  1261. }
  1262. RegCloseKey (hKey);
  1263. }
  1264. //
  1265. // Set the Shell Folder paths in the registry
  1266. //
  1267. lstrcpy (szTemp, TEXT(".Default"));
  1268. lpEnd = CheckSlash (szTemp);
  1269. lstrcpy(lpEnd, SHELL_FOLDERS);
  1270. dwSize = ARRAYSIZE(szDirectory);
  1271. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1272. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
  1273. dwErr = GetLastError();
  1274. goto Exit;
  1275. }
  1276. lpEnd = CheckSlash (szDirectory);
  1277. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1278. 0, NULL, REG_OPTION_NON_VOLATILE,
  1279. KEY_READ | KEY_WRITE, NULL, &hKey,
  1280. &dwDisp) == ERROR_SUCCESS) {
  1281. for (i=0; i < g_dwNumShellFolders; i++) {
  1282. if (c_ShellFolders[i].bAddCSIDL) {
  1283. lstrcpy (lpEnd, c_ShellFolders[i].szFolderLocation);
  1284. RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
  1285. 0, REG_SZ, (LPBYTE) szDirectory,
  1286. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1287. }
  1288. }
  1289. RegCloseKey (hKey);
  1290. }
  1291. //
  1292. // Set the per user TEMP and TMP environment variables
  1293. //
  1294. if (LoadString (g_hDllInstance, IDS_SH_TEMP,
  1295. szTemp, ARRAYSIZE(szTemp))) {
  1296. lstrcpy (szDirectory, TEXT("%USERPROFILE%"));
  1297. lpEnd = CheckSlash (szDirectory);
  1298. LoadString (g_hDllInstance, IDS_SH_LOCALSETTINGS,
  1299. lpEnd, ARRAYSIZE(szTemp)-(lstrlen(szDirectory)));
  1300. lpEnd = CheckSlash (szDirectory);
  1301. lstrcpy (lpEnd, szTemp);
  1302. if (RegCreateKeyEx (HKEY_USERS, TEXT(".Default\\Environment"),
  1303. 0, NULL, REG_OPTION_NON_VOLATILE,
  1304. KEY_WRITE, NULL, &hKey,
  1305. &dwDisp) == ERROR_SUCCESS) {
  1306. RegSetValueEx (hKey, TEXT("TEMP"),
  1307. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1308. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1309. RegSetValueEx (hKey, TEXT("TMP"),
  1310. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1311. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1312. RegCloseKey (hKey);
  1313. }
  1314. }
  1315. //
  1316. // Set the user preference exclusion list. This will
  1317. // prevent the Local Settings folder from roaming
  1318. //
  1319. if (LoadString (g_hDllInstance, IDS_EXCLUSIONLIST,
  1320. szDirectory, ARRAYSIZE(szDirectory))) {
  1321. lstrcpy (szTemp, TEXT(".Default"));
  1322. lpEnd = CheckSlash (szTemp);
  1323. lstrcpy(lpEnd, WINLOGON_KEY);
  1324. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1325. 0, NULL, REG_OPTION_NON_VOLATILE,
  1326. KEY_READ | KEY_WRITE, NULL, &hKey,
  1327. &dwDisp) == ERROR_SUCCESS) {
  1328. RegSetValueEx (hKey, TEXT("ExcludeProfileDirs"),
  1329. 0, REG_SZ, (LPBYTE) szDirectory,
  1330. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1331. RegCloseKey (hKey);
  1332. }
  1333. }
  1334. //
  1335. // Requery for the all users profile directory (expanded version)
  1336. //
  1337. dwSize = ARRAYSIZE(szDirectory);
  1338. if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1339. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query all users profile directory.")));
  1340. dwErr = GetLastError();
  1341. goto Exit;
  1342. }
  1343. //
  1344. // Set the ALLUSERSPROFILE environment variable
  1345. //
  1346. SetEnvironmentVariable (TEXT("ALLUSERSPROFILE"), szDirectory);
  1347. //
  1348. // Create all the folders under All Users
  1349. //
  1350. lpEnd = CheckSlash (szDirectory);
  1351. //
  1352. // Loop through the shell folders
  1353. //
  1354. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1355. lstrcpy (lpEnd, c_CommonShellFolders[i].szFolderLocation);
  1356. if (!CreateNestedDirectory(szDirectory, NULL)) {
  1357. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
  1358. szDirectory, GetLastError()));
  1359. dwErr = GetLastError();
  1360. goto Exit;
  1361. }
  1362. if (c_CommonShellFolders[i].iFolderResourceID != 0) {
  1363. // NOTE this returns an HRESULT
  1364. dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
  1365. c_CommonShellFolders[i].lpFolderResourceDLL,
  1366. c_CommonShellFolders[i].iFolderResourceID );
  1367. if (FAILED(dwErr)) {
  1368. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
  1369. szDirectory, dwErr));
  1370. goto Exit;
  1371. }
  1372. }
  1373. if (c_CommonShellFolders[i].bHidden) {
  1374. SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
  1375. }
  1376. }
  1377. //
  1378. // Unsecure the Documents and App Data folders in the All Users profile
  1379. //
  1380. if (LoadString (g_hDllInstance, IDS_SH_SHAREDDOCS, szTemp, ARRAYSIZE(szTemp))) {
  1381. lstrcpy (lpEnd, szTemp);
  1382. SetFilePermissions(szDirectory, c_szCommonDocumentsACL);
  1383. }
  1384. if (LoadString (g_hDllInstance, IDS_SH_APPDATA, szTemp, ARRAYSIZE(szTemp))) {
  1385. lstrcpy (lpEnd, szTemp);
  1386. SetFilePermissions(szDirectory, c_szCommonAppDataACL);
  1387. }
  1388. //
  1389. // Set the User Shell Folder paths in the registry
  1390. //
  1391. lstrcpy (szDirectory, TEXT("%ALLUSERSPROFILE%"));
  1392. lpEnd = CheckSlash (szDirectory);
  1393. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS,
  1394. 0, NULL, REG_OPTION_NON_VOLATILE,
  1395. KEY_READ | KEY_WRITE, NULL, &hKey,
  1396. &dwDisp) == ERROR_SUCCESS) {
  1397. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1398. if (c_ShellFolders[i].bAddCSIDL) {
  1399. lstrcpy (lpEnd, c_CommonShellFolders[i].szFolderLocation);
  1400. RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
  1401. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1402. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1403. }
  1404. }
  1405. RegCloseKey (hKey);
  1406. }
  1407. #if defined(_WIN64)
  1408. //
  1409. // On 64-bit NT, we need to create the user shell folders in
  1410. // the 32-bit view of the registry so that 32-bit app calls
  1411. // to SHGetFolderPath(...CSIDL_COMMON_APPDATA...) would succeed.
  1412. //
  1413. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS32,
  1414. 0, NULL, REG_OPTION_NON_VOLATILE,
  1415. KEY_READ | KEY_WRITE, NULL, &hKey,
  1416. &dwDisp) == ERROR_SUCCESS) {
  1417. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1418. if (c_ShellFolders[i].bAddCSIDL) {
  1419. lstrcpy (lpEnd, c_CommonShellFolders[i].szFolderLocation);
  1420. RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
  1421. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1422. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1423. }
  1424. }
  1425. RegCloseKey (hKey);
  1426. }
  1427. #endif
  1428. //
  1429. // Convert any Program Manager common groups
  1430. //
  1431. if (!ConvertCommonGroups()) {
  1432. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ConvertCommonGroups failed.")));
  1433. }
  1434. //
  1435. // Success
  1436. //
  1437. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Leaving successfully.")));
  1438. bRetVal = TRUE;
  1439. Exit:
  1440. if ((!bGuiModeSetup) && (g_hProfileSetup)) {
  1441. SetEvent (g_hProfileSetup);
  1442. }
  1443. SetLastError(dwErr);
  1444. return bRetVal;
  1445. }
  1446. //*************************************************************
  1447. //
  1448. // CheckProfile()
  1449. //
  1450. // Purpose: Checks and creates a storage location for either
  1451. // the Default User or All Users profile
  1452. //
  1453. // Parameters: LPTSTR lpProfilesDir - Root of the profiles
  1454. // LPTSTR lpProfileValue - Profile registry value name
  1455. // LPTSTR lpProfileName - Default profile name
  1456. //
  1457. //
  1458. // Return: TRUE if successful
  1459. // FALSE if an error occurs
  1460. //
  1461. //*************************************************************
  1462. BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
  1463. LPTSTR lpProfileName)
  1464. {
  1465. TCHAR szTemp[MAX_PATH];
  1466. TCHAR szTemp2[MAX_PATH];
  1467. TCHAR szName[MAX_PATH];
  1468. TCHAR szFormat[30];
  1469. DWORD dwSize, dwDisp, dwType;
  1470. LPTSTR lpEnd;
  1471. LONG lResult;
  1472. HKEY hKey;
  1473. INT iStrLen;
  1474. WIN32_FILE_ATTRIBUTE_DATA fad;
  1475. //
  1476. // Open the ProfileList key
  1477. //
  1478. lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  1479. 0, NULL, REG_OPTION_NON_VOLATILE,
  1480. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  1481. if (lResult != ERROR_SUCCESS) {
  1482. DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to open profile list key with %d."),
  1483. lResult));
  1484. return FALSE;
  1485. }
  1486. //
  1487. // Check the registry to see if this folder is defined already
  1488. //
  1489. dwSize = sizeof(szTemp);
  1490. if (RegQueryValueEx (hKey, lpProfileValue, NULL, &dwType,
  1491. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  1492. RegCloseKey (hKey);
  1493. return TRUE;
  1494. }
  1495. //
  1496. // Generate the default name
  1497. //
  1498. lstrcpy (szTemp, lpProfilesDir);
  1499. lpEnd = CheckSlash (szTemp);
  1500. lstrcpy (lpEnd, lpProfileName);
  1501. lstrcpy (szName, lpProfileName);
  1502. //
  1503. // Check if this directory exists
  1504. //
  1505. ExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2));
  1506. if (GetFileAttributesEx (szTemp2, GetFileExInfoStandard, &fad)) {
  1507. if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1508. //
  1509. // Check if this directory is under the system root.
  1510. // If so, this is ok, we don't need to generate a unique
  1511. // name for this.
  1512. //
  1513. ExpandEnvironmentStrings (TEXT("%SystemRoot%"), szTemp,
  1514. ARRAYSIZE(szTemp));
  1515. iStrLen = lstrlen (szTemp);
  1516. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1517. szTemp, iStrLen, szTemp2, iStrLen) != CSTR_EQUAL) {
  1518. //
  1519. // The directory exists already. Use a new name of
  1520. // Profile Name (SystemDirectory)
  1521. //
  1522. // eg: Default User (WINNT)
  1523. //
  1524. lpEnd = szTemp + lstrlen(szTemp) - 1;
  1525. while ((lpEnd > szTemp) && ((*lpEnd) != TEXT('\\')))
  1526. lpEnd--;
  1527. if (*lpEnd == TEXT('\\')) {
  1528. lpEnd++;
  1529. }
  1530. LoadString (g_hDllInstance, IDS_PROFILE_FORMAT, szFormat,
  1531. ARRAYSIZE(szFormat));
  1532. wsprintf (szName, szFormat, lpProfileName, lpEnd);
  1533. //
  1534. // To prevent reusing the directories, delete it first..
  1535. //
  1536. lstrcpy (szTemp, lpProfilesDir);
  1537. lpEnd = CheckSlash (szTemp);
  1538. lstrcpy (lpEnd, szName);
  1539. if (ExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2))) {
  1540. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Delnoding directory.. %s"), szTemp2));
  1541. Delnode(szTemp2);
  1542. }
  1543. }
  1544. }
  1545. }
  1546. //
  1547. // Save the profile name in the registry
  1548. //
  1549. RegSetValueEx (hKey, lpProfileValue,
  1550. 0, REG_SZ, (LPBYTE) szName,
  1551. ((lstrlen(szName) + 1) * sizeof(TCHAR)));
  1552. RegCloseKey (hKey);
  1553. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: The %s profile is mapped to %s"),
  1554. lpProfileName, szName));
  1555. return TRUE;
  1556. }
  1557. //*************************************************************
  1558. //
  1559. // CreateUserProfile()
  1560. //
  1561. // Purpose: Creates a new user profile, but does not load
  1562. // the hive.
  1563. //
  1564. // Parameters: pSid - SID pointer
  1565. // lpUserName - User name
  1566. // lpUserHive - Optional user hive
  1567. // lpProfileDir - Receives the new profile directory
  1568. // dwDirSize - Size of lpProfileDir
  1569. //
  1570. // Return: TRUE if successful
  1571. // FALSE if an error occurs
  1572. //
  1573. // Comments: If a user hive isn't specified the default user
  1574. // hive will be used.
  1575. //
  1576. // History: Date Author Comment
  1577. // 9/12/95 ericflo Created
  1578. //
  1579. //*************************************************************
  1580. BOOL WINAPI CreateUserProfile (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
  1581. LPTSTR lpProfileDir, DWORD dwDirSize)
  1582. {
  1583. return CreateUserProfileEx(pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, TRUE);
  1584. }
  1585. //*************************************************************
  1586. //
  1587. // CreateUserProfileEx()
  1588. //
  1589. // Purpose: Creates a new user profile, but does not load
  1590. // the hive.
  1591. //
  1592. // Parameters: pSid - SID pointer
  1593. // lpUserName - User name
  1594. // lpUserHive - Optional user hive
  1595. // lpProfileDir - Receives the new profile directory
  1596. // dwDirSize - Size of lpProfileDir
  1597. // bWin9xUpg - Flag to say whether it is win9x upgrade
  1598. //
  1599. // Return: TRUE if successful
  1600. // FALSE if an error occurs
  1601. //
  1602. // Comments: If a user hive isn't specified the default user
  1603. // hive will be used.
  1604. //
  1605. // History: Date Author Comment
  1606. // 9/12/95 ericflo Created
  1607. //
  1608. //*************************************************************
  1609. BOOL WINAPI CreateUserProfileEx (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
  1610. LPTSTR lpProfileDir, DWORD dwDirSize, BOOL bWin9xUpg)
  1611. {
  1612. TCHAR szProfileDir[MAX_PATH];
  1613. TCHAR szExpProfileDir[MAX_PATH] = {0};
  1614. TCHAR szDirectory[MAX_PATH];
  1615. TCHAR LocalProfileKey[MAX_PATH];
  1616. UNICODE_STRING UnicodeString;
  1617. LPTSTR lpSidString, lpEnd, lpSave;
  1618. NTSTATUS NtStatus;
  1619. LONG lResult;
  1620. DWORD dwDisp;
  1621. DWORD dwError;
  1622. DWORD dwSize;
  1623. DWORD dwType;
  1624. HKEY hKey;
  1625. //
  1626. // Check parameters
  1627. //
  1628. if (!lpUserName || !lpUserName[0]) {
  1629. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null username.")));
  1630. return FALSE;
  1631. }
  1632. if (!pSid) {
  1633. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null SID.")));
  1634. return FALSE;
  1635. }
  1636. //
  1637. // Verbose output
  1638. //
  1639. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with <%s>."), lpUserName));
  1640. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with user hive of <%s>."),
  1641. lpUserHive ? lpUserHive : TEXT("NULL")));
  1642. //
  1643. // Convert the sid into text format
  1644. //
  1645. NtStatus = RtlConvertSidToUnicodeString(&UnicodeString, pSid, (BOOLEAN)TRUE);
  1646. if (!NT_SUCCESS(NtStatus)) {
  1647. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x"),
  1648. NtStatus));
  1649. return FALSE;
  1650. }
  1651. lpSidString = UnicodeString.Buffer;
  1652. //
  1653. // Check if this user's profile exists already
  1654. //
  1655. lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
  1656. lstrcat(LocalProfileKey, TEXT("\\"));
  1657. lstrcat(LocalProfileKey, lpSidString);
  1658. szProfileDir[0] = TEXT('\0');
  1659. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
  1660. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  1661. dwSize = sizeof(szProfileDir);
  1662. RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
  1663. &dwType, (LPBYTE) szProfileDir, &dwSize);
  1664. RegCloseKey (hKey);
  1665. }
  1666. if (szProfileDir[0] == TEXT('\0')) {
  1667. //
  1668. // Make the user's directory
  1669. //
  1670. dwSize = ARRAYSIZE(szProfileDir);
  1671. if (!GetProfilesDirectoryEx(szProfileDir, &dwSize, FALSE)) {
  1672. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get profile root directory.")));
  1673. RtlFreeUnicodeString(&UnicodeString);
  1674. return FALSE;
  1675. }
  1676. if (!ComputeLocalProfileName (NULL, lpUserName, szProfileDir, ARRAYSIZE(szProfileDir),
  1677. szExpProfileDir, ARRAYSIZE(szExpProfileDir), pSid, bWin9xUpg)) {
  1678. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to create directory.")));
  1679. RtlFreeUnicodeString(&UnicodeString);
  1680. return FALSE;
  1681. }
  1682. //
  1683. // Copy the default user profile into this directory
  1684. //
  1685. dwSize = ARRAYSIZE(szDirectory);
  1686. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1687. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get default user profile.")));
  1688. RtlFreeUnicodeString(&UnicodeString);
  1689. return FALSE;
  1690. }
  1691. if (lpUserHive) {
  1692. //
  1693. // Copy the default user profile without the hive.
  1694. //
  1695. if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE | CPD_IGNORELONGFILENAMES)) {
  1696. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
  1697. RtlFreeUnicodeString(&UnicodeString);
  1698. return FALSE;
  1699. }
  1700. //
  1701. // Now copy the hive
  1702. //
  1703. lstrcpy (szDirectory, szExpProfileDir);
  1704. lpEnd = CheckSlash (szDirectory);
  1705. lstrcpy (lpEnd, c_szNTUserDat);
  1706. if (lstrcmpi (lpUserHive, szDirectory)) {
  1707. if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
  1708. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
  1709. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
  1710. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
  1711. RtlFreeUnicodeString(&UnicodeString);
  1712. return FALSE;
  1713. }
  1714. }
  1715. } else {
  1716. //
  1717. // Copy the default user profile and the hive.
  1718. //
  1719. if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNORELONGFILENAMES)) {
  1720. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
  1721. RtlFreeUnicodeString(&UnicodeString);
  1722. return FALSE;
  1723. }
  1724. }
  1725. //
  1726. // Save the user's profile in the registry.
  1727. //
  1728. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  1729. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  1730. if (lResult != ERROR_SUCCESS) {
  1731. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, lResult));
  1732. RtlFreeUnicodeString(&UnicodeString);
  1733. return FALSE;
  1734. }
  1735. //
  1736. // Add the profile directory
  1737. //
  1738. lResult = RegSetValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0,
  1739. REG_EXPAND_SZ,
  1740. (LPBYTE)szProfileDir,
  1741. sizeof(TCHAR)*(lstrlen(szProfileDir) + 1));
  1742. if (lResult != ERROR_SUCCESS) {
  1743. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: First RegSetValueEx failed, error = %d."), lResult));
  1744. RegCloseKey (hKey);
  1745. RtlFreeUnicodeString(&UnicodeString);
  1746. return FALSE;
  1747. }
  1748. //
  1749. // Add the users's SID
  1750. //
  1751. lResult = RegSetValueEx(hKey, TEXT("Sid"), 0,
  1752. REG_BINARY, pSid, RtlLengthSid(pSid));
  1753. if (lResult != ERROR_SUCCESS) {
  1754. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Second RegSetValueEx failed, error = %d."), lResult));
  1755. }
  1756. //
  1757. // Close the registry key
  1758. //
  1759. RegCloseKey (hKey);
  1760. } else {
  1761. //
  1762. // The user already has a profile, so just copy the hive if
  1763. // appropriate.
  1764. //
  1765. ExpandEnvironmentStrings (szProfileDir, szExpProfileDir,
  1766. ARRAYSIZE(szExpProfileDir));
  1767. if (lpUserHive) {
  1768. //
  1769. // Copy the hive
  1770. //
  1771. lstrcpy (szDirectory, szExpProfileDir);
  1772. lpEnd = CheckSlash (szDirectory);
  1773. lstrcpy (lpEnd, c_szNTUserDat);
  1774. SetFileAttributes (szDirectory, FILE_ATTRIBUTE_NORMAL);
  1775. if (lstrcmpi (lpUserHive, szDirectory)) {
  1776. if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
  1777. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
  1778. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
  1779. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
  1780. RtlFreeUnicodeString(&UnicodeString);
  1781. return FALSE;
  1782. }
  1783. }
  1784. }
  1785. }
  1786. //
  1787. // Now load the hive temporary so the security can be fixed
  1788. //
  1789. lpEnd = CheckSlash (szExpProfileDir);
  1790. lpSave = lpEnd - 1;
  1791. lstrcpy (lpEnd, c_szNTUserDat);
  1792. lResult = MyRegLoadKey(HKEY_USERS, lpSidString, szExpProfileDir);
  1793. *lpSave = TEXT('\0');
  1794. if (lResult != ERROR_SUCCESS) {
  1795. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to load hive, error = %d."), lResult));
  1796. dwError = GetLastError();
  1797. DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
  1798. RtlFreeUnicodeString(&UnicodeString);
  1799. SetLastError(dwError);
  1800. return FALSE;
  1801. }
  1802. if (!SetupNewHive(NULL, lpSidString, pSid)) {
  1803. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: SetupNewHive failed.")));
  1804. dwError = GetLastError();
  1805. MyRegUnLoadKey(HKEY_USERS, lpSidString);
  1806. DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
  1807. RtlFreeUnicodeString(&UnicodeString);
  1808. SetLastError(dwError);
  1809. return FALSE;
  1810. }
  1811. //
  1812. // Unload the hive
  1813. //
  1814. MyRegUnLoadKey(HKEY_USERS, lpSidString);
  1815. //
  1816. // Free the sid string
  1817. //
  1818. RtlFreeUnicodeString(&UnicodeString);
  1819. //
  1820. // Save the profile path if appropriate
  1821. //
  1822. if (lpProfileDir) {
  1823. if ((DWORD)lstrlen(szExpProfileDir) < dwDirSize) {
  1824. lstrcpy (lpProfileDir, szExpProfileDir);
  1825. }
  1826. }
  1827. //
  1828. // Success
  1829. //
  1830. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Leaving successfully.")));
  1831. return TRUE;
  1832. }
  1833. //*************************************************************************
  1834. //
  1835. // SecureUserProfiles()
  1836. //
  1837. // Routine Description :
  1838. // This function secures user profiles during FAT->NTFS conversion.
  1839. // The function loops through all profiles registered under current
  1840. // OS and sets the security for the corresponding profile directory
  1841. // and nested subdirs. Assumption is the function will be called
  1842. // only during FAT->NTFS conversion.
  1843. //
  1844. // Arguments :
  1845. // None.
  1846. //
  1847. // Return Value :
  1848. // None.
  1849. //
  1850. // History: Date Author Comment
  1851. // 8/8/00 santanuc Created
  1852. //
  1853. //*************************************************************************
  1854. void WINAPI SecureUserProfiles(void)
  1855. {
  1856. SECURITY_DESCRIPTOR DirSd, FileSd;
  1857. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  1858. PACL pDirAcl = NULL, pFileAcl = NULL;
  1859. PSID pSidOwner=NULL, pSidAdmin = NULL, pSidSystem = NULL;
  1860. DWORD cbAcl, aceIndex;
  1861. HKEY hKeyProfilesList, hKeyProfile = NULL;
  1862. TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
  1863. DWORD dwSIDNameSize, dwSize;
  1864. DWORD dwIndex;
  1865. LONG lResult;
  1866. FILETIME ft;
  1867. //
  1868. // Get the system sid
  1869. //
  1870. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  1871. 0, 0, 0, 0, 0, 0, 0, &pSidSystem)) {
  1872. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize system sid. Error = %d"), GetLastError()));
  1873. goto Exit;
  1874. }
  1875. //
  1876. // Get the Admin sid
  1877. //
  1878. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  1879. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  1880. 0, 0, 0, 0, &pSidAdmin)) {
  1881. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
  1882. goto Exit;
  1883. }
  1884. //
  1885. // Open the ProfileList key
  1886. //
  1887. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1888. PROFILE_LIST_PATH,
  1889. 0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
  1890. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to open ProfileList key")));
  1891. goto Exit;
  1892. }
  1893. //
  1894. // Enumerate the profiles
  1895. //
  1896. dwIndex = 0;
  1897. dwSIDNameSize = ARRAYSIZE(szSIDName);
  1898. lResult = RegEnumKeyEx(hKeyProfilesList,
  1899. dwIndex,
  1900. szSIDName,
  1901. &dwSIDNameSize,
  1902. NULL, NULL, NULL, &ft);
  1903. while (lResult == ERROR_SUCCESS) {
  1904. if (RegOpenKeyEx (hKeyProfilesList,
  1905. szSIDName,
  1906. 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  1907. dwSize = sizeof(szProfilePath);
  1908. if (RegQueryValueEx (hKeyProfile,
  1909. PROFILE_IMAGE_VALUE_NAME,
  1910. NULL, NULL,
  1911. (LPBYTE) szProfilePath,
  1912. &dwSize) != ERROR_SUCCESS) {
  1913. goto NextProfile;
  1914. }
  1915. //
  1916. // Expand the profile image filename
  1917. //
  1918. ExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH);
  1919. //
  1920. // Create the acl for the user profile dir
  1921. //
  1922. //
  1923. // Get the owner sid
  1924. //
  1925. if (AllocateAndInitSidFromString(szSIDName, &pSidOwner) != STATUS_SUCCESS) {
  1926. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to create owner sid."), GetLastError()));
  1927. goto IssueError;
  1928. }
  1929. //
  1930. // Allocate space for the Dir object ACL
  1931. //
  1932. cbAcl = (2 * GetLengthSid (pSidOwner)) +
  1933. (2 * GetLengthSid (pSidSystem)) +
  1934. (2 * GetLengthSid (pSidAdmin)) +
  1935. sizeof(ACL) +
  1936. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1937. pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  1938. if (!pDirAcl) {
  1939. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  1940. goto IssueError;
  1941. }
  1942. if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
  1943. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
  1944. goto IssueError;
  1945. }
  1946. //
  1947. // Allocate space for File object ACL
  1948. //
  1949. cbAcl = (GetLengthSid (pSidOwner)) +
  1950. (GetLengthSid (pSidSystem)) +
  1951. (GetLengthSid (pSidAdmin)) +
  1952. sizeof(ACL) +
  1953. (3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  1954. pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  1955. if (!pFileAcl) {
  1956. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  1957. goto IssueError;
  1958. }
  1959. if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
  1960. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
  1961. goto IssueError;
  1962. }
  1963. //
  1964. // Add Aces. Non-inheritable ACEs first
  1965. //
  1966. aceIndex = 0;
  1967. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
  1968. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  1969. goto IssueError;
  1970. }
  1971. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
  1972. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  1973. goto IssueError;
  1974. }
  1975. aceIndex++;
  1976. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  1977. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  1978. goto IssueError;
  1979. }
  1980. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  1981. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  1982. goto IssueError;
  1983. }
  1984. aceIndex++;
  1985. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  1986. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  1987. goto IssueError;
  1988. }
  1989. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  1990. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  1991. goto IssueError;
  1992. }
  1993. //
  1994. // Now the Inheritable Aces.
  1995. //
  1996. aceIndex++;
  1997. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidOwner)) {
  1998. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  1999. goto IssueError;
  2000. }
  2001. aceIndex++;
  2002. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
  2003. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  2004. goto IssueError;
  2005. }
  2006. aceIndex++;
  2007. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
  2008. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2009. goto IssueError;
  2010. }
  2011. //
  2012. // Put together the security descriptor
  2013. //
  2014. if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
  2015. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2016. goto IssueError;
  2017. }
  2018. if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
  2019. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2020. goto IssueError;
  2021. }
  2022. if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
  2023. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2024. goto IssueError;
  2025. }
  2026. if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
  2027. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2028. goto IssueError;
  2029. }
  2030. //
  2031. // Pass the profile path to SecureProfile for securing
  2032. // the profile dir and nested subdirs and files.
  2033. //
  2034. if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
  2035. goto IssueError;
  2036. }
  2037. goto NextProfile;
  2038. IssueError:
  2039. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to secure %s Profile directory"), szExpandedProfilePath));
  2040. }
  2041. NextProfile:
  2042. // Free the allocated stuffs
  2043. if (hKeyProfile) {
  2044. RegCloseKey(hKeyProfile);
  2045. hKeyProfile = NULL;
  2046. }
  2047. if (pSidOwner) {
  2048. FreeSid(pSidOwner);
  2049. pSidOwner = NULL;
  2050. }
  2051. if (pDirAcl) {
  2052. GlobalFree (pDirAcl);
  2053. pDirAcl = NULL;
  2054. }
  2055. if (pFileAcl) {
  2056. GlobalFree (pFileAcl);
  2057. pFileAcl = NULL;
  2058. }
  2059. //
  2060. // Reset for the next loop
  2061. //
  2062. dwIndex++;
  2063. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2064. lResult = RegEnumKeyEx(hKeyProfilesList,
  2065. dwIndex,
  2066. szSIDName,
  2067. &dwSIDNameSize,
  2068. NULL, NULL, NULL, &ft);
  2069. }
  2070. RegCloseKey(hKeyProfilesList);
  2071. Exit:
  2072. if (pSidSystem) {
  2073. FreeSid(pSidSystem);
  2074. }
  2075. if (pSidAdmin) {
  2076. FreeSid(pSidAdmin);
  2077. }
  2078. }
  2079. //*************************************************************************
  2080. //
  2081. // HideSpecialProfiles()
  2082. //
  2083. // Routine Description :
  2084. // This function secures special profiles for which PI_HIDEPROFILE
  2085. // flag is specifed, e.g. LocalService, NetworkService etc. except
  2086. // system account profile. This mark the profile dir as super hidden.
  2087. //
  2088. // Arguments :
  2089. // None.
  2090. //
  2091. // Return Value :
  2092. // None.
  2093. //
  2094. // History: Date Author Comment
  2095. // 8/8/00 santanuc Created
  2096. //
  2097. //*************************************************************************
  2098. void HideSpecialProfiles(void)
  2099. {
  2100. HKEY hKeyProfilesList, hKeyProfile = NULL;
  2101. TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
  2102. DWORD dwSIDNameSize, dwSize;
  2103. DWORD dwIndex, dwFlags;
  2104. LONG lResult;
  2105. FILETIME ft;
  2106. //
  2107. // Open the ProfileList key
  2108. //
  2109. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  2110. PROFILE_LIST_PATH,
  2111. 0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
  2112. DebugMsg((DM_WARNING, TEXT("HideSpecialProfiles: Failed to open ProfileList key")));
  2113. return;
  2114. }
  2115. //
  2116. // Enumerate the profiles
  2117. //
  2118. dwIndex = 0;
  2119. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2120. lResult = RegEnumKeyEx(hKeyProfilesList,
  2121. dwIndex,
  2122. szSIDName,
  2123. &dwSIDNameSize,
  2124. NULL, NULL, NULL, &ft);
  2125. while (lResult == ERROR_SUCCESS) {
  2126. if (RegOpenKeyEx (hKeyProfilesList,
  2127. szSIDName,
  2128. 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  2129. //
  2130. // Process only if PI_HIDEPROFILE flag is set
  2131. //
  2132. dwSize = sizeof(DWORD);
  2133. if (RegQueryValueEx (hKeyProfile,
  2134. PROFILE_FLAGS,
  2135. NULL, NULL,
  2136. (LPBYTE) &dwFlags,
  2137. &dwSize) != ERROR_SUCCESS) {
  2138. goto NextProfile;
  2139. }
  2140. if (!(dwFlags & PI_HIDEPROFILE)) {
  2141. goto NextProfile;
  2142. }
  2143. dwSize = sizeof(szProfilePath);
  2144. if (RegQueryValueEx (hKeyProfile,
  2145. PROFILE_IMAGE_VALUE_NAME,
  2146. NULL, NULL,
  2147. (LPBYTE) szProfilePath,
  2148. &dwSize) != ERROR_SUCCESS) {
  2149. goto NextProfile;
  2150. }
  2151. // Ignore profile for system account
  2152. if (lstrcmp(szProfilePath, SYSTEM_PROFILE_LOCATION) == 0) {
  2153. goto NextProfile;
  2154. }
  2155. //
  2156. // Expand the profile image filename
  2157. //
  2158. ExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH);
  2159. // Mark the profile hidden
  2160. SetFileAttributes(szExpandedProfilePath,
  2161. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
  2162. GetFileAttributes(szExpandedProfilePath));
  2163. }
  2164. NextProfile:
  2165. // Free the allocated stuffs
  2166. if (hKeyProfile) {
  2167. RegCloseKey(hKeyProfile);
  2168. hKeyProfile = NULL;
  2169. }
  2170. //
  2171. // Reset for the next loop
  2172. //
  2173. dwIndex++;
  2174. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2175. lResult = RegEnumKeyEx(hKeyProfilesList,
  2176. dwIndex,
  2177. szSIDName,
  2178. &dwSIDNameSize,
  2179. NULL, NULL, NULL, &ft);
  2180. }
  2181. RegCloseKey(hKeyProfilesList);
  2182. }
  2183. //*************************************************************
  2184. //
  2185. // CopySystemProfile()
  2186. //
  2187. // Purpose: Create the system profile information under
  2188. // ProfileList entry.
  2189. // In case of upgrade copy system profile from older
  2190. // location to new location and delete the old system
  2191. // profile
  2192. //
  2193. // Parameters:
  2194. //
  2195. // Return: TRUE if successful
  2196. // FALSE if an error occurs. Call GetLastError()
  2197. //
  2198. // Comments: This should only be called by GUI mode setup!
  2199. //
  2200. // History: Date Author Comment
  2201. // 03/13/01 santanuc Created
  2202. //
  2203. //*************************************************************
  2204. BOOL WINAPI CopySystemProfile(BOOL bCleanInstall)
  2205. {
  2206. HANDLE hToken = NULL;
  2207. LPTSTR SidString = NULL, lpEnd;
  2208. TCHAR szLocalProfileKey[MAX_PATH], szBuffer[MAX_PATH];
  2209. TCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
  2210. LONG lResult;
  2211. HKEY hKey = NULL, hKeyShellFolders;
  2212. DWORD dwFlags, dwInternalFlags, dwRefCount;
  2213. DWORD dwDisp, dwSize, dwType, i;
  2214. BOOL bCopySystemProfile = TRUE, bCopyFromDefault = TRUE;
  2215. PSID pSystemSid = NULL;
  2216. DWORD dwErr = ERROR_SUCCESS;
  2217. //
  2218. // Set the Profile information for system account i.e sid s-1-5-18
  2219. //
  2220. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
  2221. TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) {
  2222. dwErr = GetLastError();
  2223. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to open system token. Error %d"), dwErr));
  2224. goto Exit;
  2225. }
  2226. //
  2227. // Get the Sid string
  2228. //
  2229. SidString = GetSidString(hToken);
  2230. if (!SidString) {
  2231. dwErr = ERROR_ACCESS_DENIED;
  2232. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid string for system account")));
  2233. goto Exit;
  2234. }
  2235. pSystemSid = GetUserSid(hToken);
  2236. if (!pSystemSid) {
  2237. dwErr = ERROR_ACCESS_DENIED;
  2238. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid for system account")));
  2239. goto Exit;
  2240. }
  2241. //
  2242. // Open the profile mapping
  2243. //
  2244. lstrcpy(szLocalProfileKey, PROFILE_LIST_PATH);
  2245. lpEnd = CheckSlash (szLocalProfileKey);
  2246. lstrcpy(lpEnd, SidString);
  2247. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szLocalProfileKey, 0, 0, 0,
  2248. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  2249. if (lResult != ERROR_SUCCESS) {
  2250. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to open profile mapping key. Error %d"), lResult));
  2251. dwErr = lResult;
  2252. goto Exit;
  2253. }
  2254. //
  2255. // Save the flags
  2256. //
  2257. dwFlags = PI_LITELOAD | PI_HIDEPROFILE;
  2258. lResult = RegSetValueEx (hKey,
  2259. PROFILE_FLAGS,
  2260. 0,
  2261. REG_DWORD,
  2262. (LPBYTE) &dwFlags,
  2263. sizeof(DWORD));
  2264. if (lResult != ERROR_SUCCESS) {
  2265. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile flags. Error %d"), lResult));
  2266. }
  2267. //
  2268. // Save the internal flags
  2269. //
  2270. dwInternalFlags = 0;
  2271. lResult = RegSetValueEx (hKey,
  2272. PROFILE_STATE,
  2273. 0,
  2274. REG_DWORD,
  2275. (LPBYTE) &dwInternalFlags,
  2276. sizeof(DWORD));
  2277. if (lResult != ERROR_SUCCESS) {
  2278. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save internal flags. Error %d"), lResult));
  2279. }
  2280. //
  2281. // Save the ref count
  2282. //
  2283. dwRefCount = 1;
  2284. lResult = RegSetValueEx (hKey,
  2285. PROFILE_REF_COUNT,
  2286. 0,
  2287. REG_DWORD,
  2288. (LPBYTE) &dwRefCount,
  2289. sizeof(DWORD));
  2290. if (lResult != ERROR_SUCCESS) {
  2291. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile ref count. Error %d"), lResult));
  2292. }
  2293. //
  2294. // Save the sid
  2295. //
  2296. lResult = RegSetValueEx (hKey,
  2297. TEXT("Sid"),
  2298. 0,
  2299. REG_BINARY,
  2300. (LPBYTE) pSystemSid,
  2301. RtlLengthSid(pSystemSid));
  2302. if (lResult != ERROR_SUCCESS) {
  2303. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile system sid. Error %d"), lResult));
  2304. }
  2305. //
  2306. // Figure out whether any existing system profile exist or not
  2307. // in upgrade scenario
  2308. //
  2309. lstrcpy(szBuffer, SYSTEM_PROFILE_LOCATION);
  2310. ExpandEnvironmentStrings(szBuffer, szDest, MAX_PATH);
  2311. if (!bCleanInstall) {
  2312. dwSize = ARRAYSIZE(szBuffer) * sizeof(TCHAR);
  2313. lResult = RegQueryValueEx(hKey,
  2314. PROFILE_IMAGE_VALUE_NAME,
  2315. NULL,
  2316. &dwType,
  2317. (LPBYTE) szBuffer,
  2318. &dwSize);
  2319. if (ERROR_SUCCESS == lResult) {
  2320. if (lstrcmp(szBuffer, SYSTEM_PROFILE_LOCATION) == 0) {
  2321. bCopySystemProfile = FALSE;
  2322. }
  2323. else {
  2324. ExpandEnvironmentStrings(szBuffer, szSrc, MAX_PATH);
  2325. bCopyFromDefault = FALSE;
  2326. }
  2327. }
  2328. }
  2329. if (bCopySystemProfile) {
  2330. if (!CreateSecureDirectory(NULL, szDest, pSystemSid, FALSE)) {
  2331. dwErr = GetLastError();
  2332. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to create SystemProfile dir. Error %d"), dwErr));
  2333. goto Exit;
  2334. }
  2335. if (bCopyFromDefault) {
  2336. dwSize = ARRAYSIZE(szSrc);
  2337. if (!GetDefaultUserProfileDirectoryEx(szSrc, &dwSize, TRUE)) {
  2338. dwErr = GetLastError();
  2339. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get default user profile. Error %d"), dwErr));
  2340. goto Exit;
  2341. }
  2342. }
  2343. //
  2344. // Copy the existing or Default user profile in System profile location
  2345. //
  2346. if (!CopyProfileDirectoryEx(szSrc, szDest, CPD_IGNOREHIVE | CPD_FORCECOPY | CPD_IGNORECOPYERRORS,
  2347. NULL, NULL)) {
  2348. dwErr = GetLastError();
  2349. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to copy system profile. Error %d"), dwErr));
  2350. goto Exit;
  2351. }
  2352. if (!bCopyFromDefault) {
  2353. Delnode(szSrc);
  2354. }
  2355. }
  2356. SetAclForSystemProfile(pSystemSid, szDest);
  2357. //
  2358. // Save local profile path
  2359. //
  2360. lstrcpy(szBuffer, SYSTEM_PROFILE_LOCATION);
  2361. lResult = RegSetValueEx (hKey,
  2362. PROFILE_IMAGE_VALUE_NAME,
  2363. 0,
  2364. REG_EXPAND_SZ,
  2365. (LPBYTE) szBuffer,
  2366. ((lstrlen(szBuffer) + 1) * sizeof(TCHAR)));
  2367. if (lResult != ERROR_SUCCESS) {
  2368. dwErr = lResult;
  2369. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile image path with error %d"), lResult));
  2370. goto Exit;
  2371. }
  2372. //
  2373. // Set the Shell Folder paths in the registry for system account
  2374. //
  2375. lstrcpy (szBuffer, TEXT(".Default"));
  2376. lpEnd = CheckSlash (szBuffer);
  2377. lstrcpy(lpEnd, SHELL_FOLDERS);
  2378. lpEnd = CheckSlash (szDest);
  2379. if (RegCreateKeyEx (HKEY_USERS, szBuffer,
  2380. 0, NULL, REG_OPTION_NON_VOLATILE,
  2381. KEY_READ | KEY_WRITE, NULL, &hKeyShellFolders,
  2382. &dwDisp) == ERROR_SUCCESS) {
  2383. for (i=0; i < g_dwNumShellFolders; i++) {
  2384. if (c_ShellFolders[i].bAddCSIDL) {
  2385. lstrcpy (lpEnd, c_ShellFolders[i].szFolderLocation);
  2386. RegSetValueEx (hKeyShellFolders, c_ShellFolders[i].lpFolderName,
  2387. 0, REG_SZ, (LPBYTE) szDest,
  2388. ((lstrlen(szDest) + 1) * sizeof(TCHAR)));
  2389. }
  2390. }
  2391. RegCloseKey (hKeyShellFolders);
  2392. }
  2393. Exit:
  2394. if (hToken) {
  2395. CloseHandle(hToken);
  2396. }
  2397. if (SidString) {
  2398. DeleteSidString(SidString);
  2399. }
  2400. if (pSystemSid) {
  2401. DeleteUserSid(pSystemSid);
  2402. }
  2403. if (hKey) {
  2404. RegCloseKey (hKey);
  2405. }
  2406. SetLastError(dwErr);
  2407. return(dwErr == ERROR_SUCCESS ? TRUE : FALSE);
  2408. }
  2409. //*************************************************************************
  2410. //
  2411. // SetAclForSystemProfile()
  2412. //
  2413. // Routine Description :
  2414. // This function secures dir/files of system profile i.e.
  2415. // %windir%\system32\config\systemprofile
  2416. //
  2417. // Arguments :
  2418. // pSidSystem - System sid
  2419. // szExpandedProfilePath - Expanded system profile location
  2420. //
  2421. // Return Value :
  2422. // None.
  2423. //
  2424. // History: Date Author Comment
  2425. // 04/06/01 santanuc Created
  2426. //
  2427. //*************************************************************************
  2428. void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath)
  2429. {
  2430. SECURITY_DESCRIPTOR DirSd, FileSd;
  2431. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2432. PACL pDirAcl = NULL, pFileAcl = NULL;
  2433. PSID pSidAdmin = NULL;
  2434. DWORD cbAcl, aceIndex;
  2435. //
  2436. // Get the Admin sid
  2437. //
  2438. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2439. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2440. 0, 0, 0, 0, &pSidAdmin)) {
  2441. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
  2442. goto Exit;
  2443. }
  2444. //
  2445. // Allocate space for the Dir object ACL
  2446. //
  2447. cbAcl = (2 * GetLengthSid (pSidSystem)) +
  2448. (2 * GetLengthSid (pSidAdmin)) +
  2449. sizeof(ACL) +
  2450. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2451. pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2452. if (!pDirAcl) {
  2453. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2454. goto Exit;
  2455. }
  2456. if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
  2457. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
  2458. goto Exit;
  2459. }
  2460. //
  2461. // Allocate space for File object ACL
  2462. //
  2463. cbAcl = (GetLengthSid (pSidSystem)) +
  2464. (GetLengthSid (pSidAdmin)) +
  2465. sizeof(ACL) +
  2466. (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2467. pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2468. if (!pFileAcl) {
  2469. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2470. goto Exit;
  2471. }
  2472. if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
  2473. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
  2474. goto Exit;
  2475. }
  2476. //
  2477. // Add Aces. Non-inheritable ACEs first
  2478. //
  2479. aceIndex = 0;
  2480. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2481. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2482. goto Exit;
  2483. }
  2484. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2485. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2486. goto Exit;
  2487. }
  2488. aceIndex++;
  2489. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2490. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2491. goto Exit;
  2492. }
  2493. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2494. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2495. goto Exit;
  2496. }
  2497. //
  2498. // Now the Inheritable Aces.
  2499. //
  2500. aceIndex++;
  2501. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
  2502. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2503. goto Exit;
  2504. }
  2505. aceIndex++;
  2506. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
  2507. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2508. goto Exit;
  2509. }
  2510. //
  2511. // Put together the security descriptor
  2512. //
  2513. if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
  2514. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2515. goto Exit;
  2516. }
  2517. if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
  2518. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2519. goto Exit;
  2520. }
  2521. if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
  2522. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2523. goto Exit;
  2524. }
  2525. if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
  2526. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2527. goto Exit;
  2528. }
  2529. //
  2530. // Pass the profile path to SecureProfile for securing
  2531. // the profile dir and nested subdirs and files.
  2532. //
  2533. if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
  2534. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to secure %s Profile directory"), szExpandedProfilePath));
  2535. }
  2536. Exit:
  2537. if (pDirAcl) {
  2538. GlobalFree (pDirAcl);
  2539. pDirAcl = NULL;
  2540. }
  2541. if (pFileAcl) {
  2542. GlobalFree (pFileAcl);
  2543. pFileAcl = NULL;
  2544. }
  2545. if (pSidAdmin) {
  2546. FreeSid(pSidAdmin);
  2547. }
  2548. }