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

4476 lines
137 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. #include <aclapi.h>
  13. #include "strsafe.h"
  14. // See ConvertStringSecurityDescriptorToSecurityDescriptor documentation
  15. // for a description of the string security descriptor format.
  16. //
  17. // These ACLs are setup to allow
  18. // System, Administrators, Creator-Owner: Full Control
  19. // Power Users: Modify (RWXD)
  20. // Users: Read (RX)
  21. // Users: Write (folders only)
  22. //
  23. // The combination of "Users: Write (folders only)" and the Creator-Owner ACE
  24. // means that restricted users can create subfolders and files, and have full
  25. // control to files that they create, but they cannot modify or delete files
  26. // created by someone else.
  27. 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)");
  28. 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)");
  29. const TCHAR c_szProfileEnvName[] = TEXT("PROFILES");
  30. BOOL PrependPath(LPCTSTR szFile, LPTSTR szResult, UINT cchResult);
  31. BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
  32. LPTSTR lpProfileName);
  33. void HideSpecialProfiles(void);
  34. void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath);
  35. HRESULT ReaclProfileListEntries();
  36. HRESULT CallFaxServiceAPI();
  37. HRESULT PrepareEnvironmentVariables();
  38. HRESULT SecureCommonProfiles();
  39. HRESULT SecurePerUserProfiles();
  40. //
  41. // Tell whether the setup is a clean install
  42. //
  43. static BOOL g_bCleanInstall;
  44. //*************************************************************
  45. //
  46. // CreateGroup()
  47. //
  48. // Purpose: Creates a program group (sub-directory)
  49. //
  50. // Parameters: lpGroupName - Name of group
  51. // bCommonGroup - Common or Personal group
  52. //
  53. // Return: TRUE if successful
  54. // FALSE if an error occurs
  55. //
  56. // Comments:
  57. //
  58. // History: Date Author Comment
  59. // 8/08/95 ericflo Created
  60. // 3/29/00 AlexArm Split into CreateGroup
  61. // and CreateGroupEx
  62. //
  63. //*************************************************************
  64. BOOL WINAPI CreateGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
  65. {
  66. //
  67. // Call CreateGroupEx with no name.
  68. //
  69. return CreateGroupEx( lpGroupName, bCommonGroup, NULL, 0 );
  70. }
  71. //*************************************************************
  72. //
  73. // CreateGroupEx()
  74. //
  75. // Purpose: Creates a program group (sub-directory) and sets
  76. // the localized name for the program group
  77. //
  78. // Parameters: lpGroupName - Name of group
  79. // bCommonGroup - Common or Personal group
  80. // lpResourceModuleName - Name of the resource module.
  81. // uResourceID - Resource ID for the MUI display name.
  82. //
  83. // Return: TRUE if successful
  84. // FALSE if an error occurs
  85. //
  86. // Comments:
  87. //
  88. // History: Date Author Comment
  89. // 8/08/95 ericflo Created
  90. // 3/29/00 AlexArm Split into CreateGroup
  91. // and CreateGroupEx
  92. //
  93. //*************************************************************
  94. BOOL WINAPI CreateGroupEx(LPCWSTR lpGroupName, BOOL bCommonGroup,
  95. LPCWSTR lpResourceModuleName, UINT uResourceID)
  96. {
  97. TCHAR szDirectory[MAX_PATH];
  98. LPTSTR lpEnd;
  99. LPTSTR lpAdjustedGroupName;
  100. int csidl;
  101. PSHELL32_API pShell32Api;
  102. DWORD dwResult;
  103. UINT cchEnd;
  104. HRESULT hr;
  105. //
  106. // Validate parameters
  107. //
  108. if (!lpGroupName || !(*lpGroupName)) {
  109. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: Failing due to NULL group name.")));
  110. return FALSE;
  111. }
  112. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Entering with <%s>."), lpGroupName));
  113. if ( ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  114. return FALSE;
  115. }
  116. //
  117. // Extract the CSIDL (if any) from lpGroupName
  118. //
  119. csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
  120. if (-1 != csidl)
  121. {
  122. //
  123. // Use this csidl
  124. // WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
  125. //
  126. DebugMsg((DM_VERBOSE,
  127. TEXT("CreateGroupEx: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
  128. csidl));
  129. }
  130. else
  131. {
  132. //
  133. // Default to CSIDL_..._PROGRAMS
  134. //
  135. csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
  136. }
  137. //
  138. // Get the programs directory
  139. //
  140. if (!GetSpecialFolderPath (csidl, szDirectory)) {
  141. return FALSE;
  142. }
  143. //
  144. // Now append the requested directory
  145. //
  146. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  147. if (!lpEnd)
  148. {
  149. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CheckSlashEx failed.")));
  150. return FALSE;
  151. }
  152. hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedGroupName);
  153. if (FAILED(hr))
  154. {
  155. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: StringCchCopy failed.")));
  156. return FALSE;
  157. }
  158. //
  159. // Create the group (directory)
  160. //
  161. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling CreatedNestedDirectory with <%s>"),
  162. szDirectory));
  163. if (!CreateNestedDirectory(szDirectory, NULL)) {
  164. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CreatedNestedDirectory failed.")));
  165. return FALSE;
  166. }
  167. //
  168. // If the localized name is specified, set it.
  169. //
  170. if (lpResourceModuleName != NULL) {
  171. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling SHSetLocalizedName.")));
  172. dwResult = pShell32Api->pfnShSetLocalizedName(szDirectory,
  173. lpResourceModuleName, uResourceID);
  174. if (dwResult != ERROR_SUCCESS) {
  175. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: SHSetLocalizedName failed <0x%x>."),
  176. dwResult));
  177. return FALSE;
  178. }
  179. }
  180. //
  181. // Success
  182. //
  183. pShell32Api->pfnShChangeNotify (SHCNE_MKDIR, SHCNF_PATH, szDirectory, NULL);
  184. DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Leaving successfully.")));
  185. return TRUE;
  186. }
  187. //*************************************************************
  188. //
  189. // DeleteGroup()
  190. //
  191. // Purpose: Deletes a program group (sub-directory)
  192. //
  193. // Parameters: lpGroupName - Name of group
  194. // bCommonGroup - Common or Personal group
  195. //
  196. // Return: TRUE if successful
  197. // FALSE if an error occurs
  198. //
  199. // Comments:
  200. //
  201. // History: Date Author Comment
  202. // 8/10/95 ericflo Created
  203. //
  204. //*************************************************************
  205. BOOL WINAPI DeleteGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
  206. {
  207. TCHAR szDirectory[MAX_PATH];
  208. LPTSTR lpEnd;
  209. LPTSTR lpAdjustedGroupName;
  210. int csidl;
  211. PSHELL32_API pShell32Api;
  212. UINT cchEnd;
  213. HRESULT hr;
  214. //
  215. // Validate parameters
  216. //
  217. if (!lpGroupName || !(*lpGroupName)) {
  218. DebugMsg((DM_WARNING, TEXT("DeleteGroup: Failing due to NULL group name.")));
  219. return FALSE;
  220. }
  221. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Entering with <%s>."), lpGroupName));
  222. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  223. return FALSE;
  224. }
  225. //
  226. // Extract the CSIDL (if any) from lpGroupName
  227. //
  228. csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
  229. if (-1 != csidl)
  230. {
  231. //
  232. // Use this csidl
  233. // WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
  234. //
  235. DebugMsg((DM_VERBOSE,
  236. TEXT("DeleteGroup: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
  237. csidl));
  238. }
  239. else
  240. {
  241. //
  242. // Default to CSIDL_..._PROGRAMS
  243. //
  244. csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
  245. }
  246. //
  247. // Get the programs directory
  248. //
  249. if (!GetSpecialFolderPath (csidl, szDirectory)) {
  250. return FALSE;
  251. }
  252. //
  253. // Now append the requested directory
  254. //
  255. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  256. if (!lpEnd)
  257. {
  258. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CheckSlashEx failed.")));
  259. return FALSE;
  260. }
  261. hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedGroupName);
  262. if (FAILED(hr))
  263. {
  264. DebugMsg((DM_WARNING, TEXT("CreateGroupEx: StringCchCopy failed.")));
  265. return FALSE;
  266. }
  267. //
  268. // Delete the group (directory)
  269. //
  270. if (!Delnode(szDirectory)) {
  271. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Delnode failed.")));
  272. return FALSE;
  273. }
  274. //
  275. // Success
  276. //
  277. pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szDirectory, NULL);
  278. DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Leaving successfully.")));
  279. return TRUE;
  280. }
  281. //*************************************************************
  282. //
  283. // CreateLinkFile()
  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. //
  298. // Return: TRUE if successful
  299. // FALSE if an error occurs
  300. //
  301. // Comments:
  302. //
  303. // History: Date Author Comment
  304. // 3/26/98 ericflo Created
  305. //
  306. //*************************************************************
  307. BOOL WINAPI CreateLinkFile(INT csidl, LPCTSTR lpSubDirectory,
  308. LPCTSTR lpFileName, LPCTSTR lpCommandLine,
  309. LPCTSTR lpIconPath, int iIconIndex,
  310. LPCTSTR lpWorkingDirectory, WORD wHotKey,
  311. int iShowCmd, LPCTSTR lpDescription)
  312. {
  313. return CreateLinkFileEx(csidl, lpSubDirectory, lpFileName, lpCommandLine,
  314. lpIconPath, iIconIndex, lpWorkingDirectory, wHotKey,
  315. iShowCmd, lpDescription, NULL, 0);
  316. }
  317. //*************************************************************
  318. //
  319. // CreateLinkFileEx()
  320. //
  321. // Purpose: Creates a link file in the specified directory
  322. //
  323. // Parameters: cidl - CSIDL_ of a special folder
  324. // lpSubDirectory - Subdirectory of special folder
  325. // lpFileName - File name of item
  326. // lpCommandLine - Command line (including args)
  327. // lpIconPath - Icon path (can be NULL)
  328. // iIconIndex - Index of icon in icon path
  329. // lpWorkingDir - Working directory
  330. // wHotKey - Hot key
  331. // iShowCmd - ShowWindow flag
  332. // lpDescription - Description of the item
  333. // lpResourceModuleName - Name of the resource module.
  334. // uResourceID - Resource ID for the MUI display name.
  335. //
  336. // Return: TRUE if successful
  337. // FALSE if an error occurs
  338. //
  339. // Comments:
  340. //
  341. // History: Date Author Comment
  342. // 3/26/98 ericflo Created
  343. //
  344. //*************************************************************
  345. BOOL WINAPI CreateLinkFileEx(INT csidl, LPCTSTR lpSubDirectory,
  346. LPCTSTR lpFileName, LPCTSTR lpCommandLine,
  347. LPCTSTR lpIconPath, int iIconIndex,
  348. LPCTSTR lpWorkingDirectory, WORD wHotKey,
  349. int iShowCmd, LPCTSTR lpDescription,
  350. LPCWSTR lpResourceModuleName, UINT uResourceID)
  351. {
  352. TCHAR szItem[MAX_PATH];
  353. TCHAR szArgs[MAX_PATH];
  354. TCHAR szLinkName[MAX_PATH];
  355. TCHAR szPath[MAX_PATH];
  356. LPTSTR lpArgs, lpEnd;
  357. IShellLink *psl;
  358. IPersistFile *ppf;
  359. BOOL bRetVal = FALSE;
  360. HINSTANCE hInstOLE32 = NULL;
  361. PFNCOCREATEINSTANCE pfnCoCreateInstance;
  362. PFNCOINITIALIZE pfnCoInitialize;
  363. PFNCOUNINITIALIZE pfnCoUninitialize;
  364. LPTSTR lpAdjustedSubDir = NULL;
  365. PSHELL32_API pShell32Api;
  366. PSHLWAPI_API pShlwapiApi;
  367. DWORD dwResult;
  368. UINT cchEnd;
  369. HRESULT hr;
  370. //
  371. // Verbose output
  372. //
  373. #if DBG
  374. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Entering.")));
  375. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: csidl = <0x%x>."), csidl));
  376. if (lpSubDirectory && *lpSubDirectory) {
  377. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpSubDirectory = <%s>."), lpSubDirectory));
  378. }
  379. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpFileName = <%s>."), lpFileName));
  380. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpCommandLine = <%s>."), lpCommandLine));
  381. if (lpIconPath) {
  382. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpIconPath = <%s>."), lpIconPath));
  383. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iIconIndex = <%d>."), iIconIndex));
  384. }
  385. if (lpWorkingDirectory) {
  386. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpWorkingDirectory = <%s>."), lpWorkingDirectory));
  387. } else {
  388. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null working directory. Setting to %%HOMEDRIVE%%%%HOMEPATH%%")));
  389. }
  390. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: wHotKey = <%d>."), wHotKey));
  391. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iShowCmd = <%d>."), iShowCmd));
  392. if (lpDescription) {
  393. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpDescription = <%s>."), lpDescription));
  394. } else {
  395. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null description.")));
  396. }
  397. #endif
  398. //
  399. // Load a few functions we need
  400. //
  401. hInstOLE32 = LoadLibrary (TEXT("ole32.dll"));
  402. if (!hInstOLE32) {
  403. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to load ole32 with %d."),
  404. GetLastError()));
  405. goto ExitNoFree;
  406. }
  407. pfnCoCreateInstance = (PFNCOCREATEINSTANCE)GetProcAddress (hInstOLE32,
  408. "CoCreateInstance");
  409. if (!pfnCoCreateInstance) {
  410. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoCreateInstance with %d."),
  411. GetLastError()));
  412. goto ExitNoFree;
  413. }
  414. pfnCoInitialize = (PFNCOINITIALIZE)GetProcAddress (hInstOLE32,
  415. "CoInitialize");
  416. if (!pfnCoInitialize) {
  417. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoInitialize with %d."),
  418. GetLastError()));
  419. goto ExitNoFree;
  420. }
  421. pfnCoUninitialize = (PFNCOUNINITIALIZE)GetProcAddress (hInstOLE32,
  422. "CoUninitialize");
  423. if (!pfnCoUninitialize) {
  424. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoUninitialize with %d."),
  425. GetLastError()));
  426. goto ExitNoFree;
  427. }
  428. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  429. goto ExitNoFree;
  430. }
  431. pShlwapiApi = LoadShlwapiApi();
  432. if ( !pShlwapiApi ) {
  433. goto ExitNoFree;
  434. }
  435. //
  436. // Get the special folder directory
  437. // First check if there is a CSIDL in the subdirectory
  438. //
  439. if (lpSubDirectory && *lpSubDirectory) {
  440. int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
  441. if (-1 != csidl2)
  442. {
  443. csidl = csidl2;
  444. DebugMsg((DM_VERBOSE,
  445. TEXT("CreateLinkFileEx: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
  446. csidl));
  447. }
  448. }
  449. szLinkName[0] = TEXT('\0');
  450. if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
  451. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to get profiles directory.")));
  452. goto ExitNoFree;
  453. }
  454. if (lpAdjustedSubDir && *lpAdjustedSubDir) {
  455. if (szLinkName[0] != TEXT('\0')) {
  456. lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
  457. if (!lpEnd)
  458. {
  459. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: CheckSlashEx failed")));
  460. goto ExitNoFree;
  461. }
  462. } else {
  463. lpEnd = szLinkName;
  464. cchEnd = ARRAYSIZE(szLinkName);
  465. }
  466. hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedSubDir);
  467. if (FAILED(hr))
  468. {
  469. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCopy failed")));
  470. goto ExitNoFree;
  471. }
  472. }
  473. //
  474. // Create the target directory
  475. //
  476. if (!CreateNestedDirectory(szLinkName, NULL)) {
  477. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to create subdirectory <%s> with %d"),
  478. szLinkName, GetLastError()));
  479. goto ExitNoFree;
  480. }
  481. //
  482. // Now tack on the filename and extension.
  483. //
  484. lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
  485. if (!lpEnd)
  486. {
  487. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: CheckSlashEx failed")));
  488. goto ExitNoFree;
  489. }
  490. hr = StringCchCopy (lpEnd, cchEnd, lpFileName);
  491. if (FAILED(hr))
  492. {
  493. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCopy failed")));
  494. goto ExitNoFree;
  495. }
  496. hr = StringCchCat (lpEnd, cchEnd, c_szLNK);
  497. if (FAILED(hr))
  498. {
  499. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCat failed")));
  500. goto ExitNoFree;
  501. }
  502. //
  503. // Split the command line into the executable name
  504. // and arguments.
  505. //
  506. StringCchCopy (szItem, ARRAYSIZE(szItem), lpCommandLine);
  507. lpArgs = pShlwapiApi->pfnPathGetArgs(szItem);
  508. if (*lpArgs) {
  509. StringCchCopy (szArgs, ARRAYSIZE(szArgs), lpArgs);
  510. lpArgs--;
  511. while (*lpArgs == TEXT(' ')) {
  512. lpArgs--;
  513. }
  514. lpArgs++;
  515. *lpArgs = TEXT('\0');
  516. } else {
  517. szArgs[0] = TEXT('\0');
  518. }
  519. pShlwapiApi->pfnPathUnquoteSpaces (szItem);
  520. //
  521. // Create an IShellLink object
  522. //
  523. pfnCoInitialize(NULL);
  524. if (FAILED(pfnCoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  525. &IID_IShellLink, (LPVOID*)&psl)))
  526. {
  527. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Could not create instance of IShellLink .")));
  528. goto ExitNoFree;
  529. }
  530. //
  531. // Query for IPersistFile
  532. //
  533. if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
  534. {
  535. DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: QueryInterface of IShellLink failed.")));
  536. goto ExitFreePSL;
  537. }
  538. //
  539. // Set the item information
  540. //
  541. if (lpDescription) {
  542. psl->lpVtbl->SetDescription(psl, lpDescription);
  543. }
  544. PrependPath(szItem, szPath, ARRAYSIZE(szPath));
  545. psl->lpVtbl->SetPath(psl, szPath);
  546. psl->lpVtbl->SetArguments(psl, szArgs);
  547. if (lpWorkingDirectory) {
  548. psl->lpVtbl->SetWorkingDirectory(psl, lpWorkingDirectory);
  549. } else {
  550. psl->lpVtbl->SetWorkingDirectory(psl, TEXT("%HOMEDRIVE%%HOMEPATH%"));
  551. }
  552. PrependPath(lpIconPath, szPath, ARRAYSIZE(szPath));
  553. psl->lpVtbl->SetIconLocation(psl, szPath, iIconIndex);
  554. psl->lpVtbl->SetHotkey(psl, wHotKey);
  555. psl->lpVtbl->SetShowCmd(psl, iShowCmd);
  556. //
  557. // If the localized name is specified, set it.
  558. //
  559. if (lpResourceModuleName != NULL) {
  560. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Calling SHSetLocalizedName on link <%s>."), szLinkName));
  561. ppf->lpVtbl->Save(ppf, szLinkName, TRUE);
  562. dwResult = pShell32Api->pfnShSetLocalizedName(szLinkName,
  563. lpResourceModuleName, uResourceID);
  564. if (dwResult != ERROR_SUCCESS) {
  565. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: SHSetLocalizedName failed <0x%x>."),
  566. dwResult));
  567. goto ExitFreePSL;
  568. }
  569. }
  570. //
  571. // Save the item to disk
  572. //
  573. bRetVal = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
  574. if (bRetVal) {
  575. pShell32Api->pfnShChangeNotify (SHCNE_CREATE, SHCNF_PATH, szLinkName, NULL);
  576. }
  577. //
  578. // Release the IPersistFile object
  579. //
  580. ppf->lpVtbl->Release(ppf);
  581. ExitFreePSL:
  582. //
  583. // Release the IShellLink object
  584. //
  585. psl->lpVtbl->Release(psl);
  586. pfnCoUninitialize();
  587. ExitNoFree:
  588. if (hInstOLE32) {
  589. FreeLibrary (hInstOLE32);
  590. }
  591. //
  592. // Finished.
  593. //
  594. DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Leaving with status of %d."), bRetVal));
  595. return bRetVal;
  596. }
  597. //*************************************************************
  598. //
  599. // DeleteLinkFile()
  600. //
  601. // Purpose: Deletes the specified link file
  602. //
  603. // Parameters: csidl - CSIDL of a special folder
  604. // lpSubDirectory - Subdirectory of special folder
  605. // lpFileName - File name of item
  606. // bDeleteSubDirectory - Delete the subdirectory if possible
  607. //
  608. // Return: TRUE if successful
  609. // FALSE if an error occurs
  610. //
  611. // Comments:
  612. //
  613. // History: Date Author Comment
  614. // 3/26/98 ericflo Created
  615. //
  616. //*************************************************************
  617. BOOL WINAPI DeleteLinkFile(INT csidl, LPCTSTR lpSubDirectory,
  618. LPCTSTR lpFileName, BOOL bDeleteSubDirectory)
  619. {
  620. TCHAR szLinkName[MAX_PATH];
  621. LPTSTR lpEnd;
  622. LPTSTR lpAdjustedSubDir = NULL;
  623. PSHELL32_API pShell32Api;
  624. UINT cchEnd;
  625. HRESULT hr;
  626. //
  627. // Verbose output
  628. //
  629. #if DBG
  630. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Entering.")));
  631. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: csidl = 0x%x."), csidl));
  632. if (lpSubDirectory && *lpSubDirectory) {
  633. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpSubDirectory = <%s>."), lpSubDirectory));
  634. }
  635. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpFileName = <%s>."), lpFileName));
  636. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: bDeleteSubDirectory = %d."), bDeleteSubDirectory));
  637. #endif
  638. if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
  639. return FALSE;
  640. }
  641. //
  642. // Get the special folder directory
  643. // First check if there is a CSIDL in the subdirectory
  644. //
  645. if (lpSubDirectory && *lpSubDirectory) {
  646. int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
  647. if (-1 != csidl2)
  648. {
  649. csidl = csidl2;
  650. DebugMsg((DM_VERBOSE,
  651. TEXT("CreateLinkFile: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
  652. csidl));
  653. }
  654. }
  655. szLinkName[0] = TEXT('\0');
  656. if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
  657. return FALSE;
  658. }
  659. if (lpAdjustedSubDir && *lpAdjustedSubDir) {
  660. if (szLinkName[0] != TEXT('\0')) {
  661. lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
  662. if (!lpEnd)
  663. {
  664. DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: CheckSlashEx failed")));
  665. return FALSE;
  666. }
  667. } else {
  668. lpEnd = szLinkName;
  669. cchEnd = ARRAYSIZE(szLinkName);
  670. }
  671. hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedSubDir);
  672. if (FAILED(hr))
  673. {
  674. DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCopy failed")));
  675. return FALSE;
  676. }
  677. }
  678. //
  679. // Now tack on the filename and extension.
  680. //
  681. lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
  682. if (!lpEnd)
  683. {
  684. DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: CheckSlashEx failed")));
  685. return FALSE;
  686. }
  687. hr = StringCchCopy (lpEnd, cchEnd, lpFileName);
  688. if (FAILED(hr))
  689. {
  690. DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCopy failed")));
  691. return FALSE;
  692. }
  693. hr = StringCchCat (lpEnd, cchEnd, c_szLNK);
  694. if (FAILED(hr))
  695. {
  696. DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCat failed")));
  697. return FALSE;
  698. }
  699. //
  700. // Delete the file
  701. //
  702. if (!DeleteFile (szLinkName)) {
  703. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Failed to delete <%s>. Error = %d"),
  704. szLinkName, GetLastError()));
  705. return FALSE;
  706. }
  707. pShell32Api->pfnShChangeNotify (SHCNE_DELETE, SHCNF_PATH, szLinkName, NULL);
  708. //
  709. // Delete the subdirectory if appropriate (and possible).
  710. //
  711. if (bDeleteSubDirectory) {
  712. *(lpEnd-1) = TEXT('\0');
  713. if (RemoveDirectory(szLinkName)) {
  714. pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szLinkName, NULL);
  715. }
  716. }
  717. //
  718. // Success
  719. //
  720. DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Leaving successfully.")));
  721. return TRUE;
  722. }
  723. //*************************************************************
  724. //
  725. // PrependPath()
  726. //
  727. // Purpose: Expands the given filename to have %systemroot%
  728. // if appropriate
  729. //
  730. // Parameters: lpFile - File to check
  731. // lpResult - Result buffer (MAX_PATH chars in size)
  732. //
  733. // Return: TRUE if successful
  734. // FALSE if an error occurs
  735. //
  736. // Comments:
  737. //
  738. // History: Date Author Comment
  739. // 10/11/95 ericflo Created
  740. //
  741. //*************************************************************
  742. BOOL PrependPath(LPCTSTR lpFile, LPTSTR lpResult, UINT cchResult)
  743. {
  744. TCHAR szReturn [MAX_PATH];
  745. LPTSTR lpFileName;
  746. DWORD dwSysLen;
  747. //
  748. // Verbose Output
  749. //
  750. DebugMsg((DM_VERBOSE, TEXT("PrependPath: Entering with <%s>"),
  751. lpFile ? lpFile : TEXT("NULL")));
  752. if (!lpFile || !*lpFile) {
  753. DebugMsg((DM_VERBOSE, TEXT("PrependPath: lpFile is NULL, setting lpResult to a null string")));
  754. *lpResult = TEXT('\0');
  755. return TRUE;
  756. }
  757. //
  758. // Call SearchPath to find the filename
  759. //
  760. if (!SearchPath (NULL, lpFile, TEXT(".exe"), MAX_PATH, szReturn, &lpFileName)) {
  761. DebugMsg((DM_VERBOSE, TEXT("PrependPath: SearchPath failed with error %d. Using input string"), GetLastError()));
  762. StringCchCopy (lpResult, cchResult, lpFile);
  763. return TRUE;
  764. }
  765. UnExpandSysRoot(szReturn, lpResult, cchResult);
  766. DebugMsg((DM_VERBOSE, TEXT("PrependPath: Leaving with <%s>"), lpResult));
  767. return TRUE;
  768. }
  769. //*************************************************************
  770. //
  771. // SetFilePermissions()
  772. //
  773. // Purpose: Sets the given permissions on a file or directory
  774. //
  775. // Parameters: lpFile - File to set security on
  776. // pszSD - String security descriptor
  777. //
  778. // Return: (BOOL) TRUE if successful
  779. // FALSE if an error occurs
  780. //
  781. // Comments:
  782. //
  783. // History: Date Author Comment
  784. // 01/25/2001 jeffreys Created
  785. //
  786. //*************************************************************
  787. BOOL SetFilePermissions(LPCTSTR lpFile, LPCTSTR pszSD)
  788. {
  789. PSECURITY_DESCRIPTOR pSD = NULL;
  790. BOOL bRetVal = FALSE;
  791. if (ConvertStringSecurityDescriptorToSecurityDescriptor(pszSD, SDDL_REVISION, &pSD, NULL) && pSD)
  792. {
  793. //
  794. // Set the security
  795. //
  796. if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, pSD))
  797. {
  798. bRetVal = TRUE;
  799. }
  800. else
  801. {
  802. DebugMsg((DM_WARNING, TEXT("SetFilePermissions: SetFileSecurity failed. Error = %d"), GetLastError()));
  803. }
  804. LocalFree(pSD);
  805. }
  806. else
  807. {
  808. DebugMsg((DM_WARNING, TEXT("SetFilePermissions: ConvertStringSDToSD failed. Error = %d"), GetLastError()));
  809. }
  810. return bRetVal;
  811. }
  812. //*************************************************************
  813. //
  814. // ConvertCommonGroups()
  815. //
  816. // Purpose: Calls grpconv.exe to convert progman common groups
  817. // to Explorer common groups, and create floppy links.
  818. //
  819. // NT 4 appended " (Common)" to the common groups. For
  820. // NT 5, we are going to remove this tag.
  821. //
  822. // Parameters: none
  823. //
  824. // Return: TRUE if successful
  825. // FALSE if an error occurs
  826. // Comments:
  827. //
  828. // History: Date Author Comment
  829. // 10/1/95 ericflo Created
  830. // 12/5/96 ericflo Remove common tag
  831. //
  832. //*************************************************************
  833. BOOL ConvertCommonGroups (void)
  834. {
  835. STARTUPINFO si;
  836. PROCESS_INFORMATION ProcessInformation;
  837. BOOL Result;
  838. TCHAR szBuffer[MAX_PATH];
  839. TCHAR szBuffer2[MAX_PATH];
  840. DWORD dwType, dwSize, dwConvert;
  841. BOOL bRunGrpConv = TRUE;
  842. LONG lResult;
  843. HKEY hKey;
  844. HANDLE hFile;
  845. WIN32_FIND_DATA fd;
  846. TCHAR szCommon[30] = {0};
  847. UINT cchCommon, cchFileName;
  848. LPTSTR lpTag, lpEnd, lpEnd2;
  849. UINT cchEnd, cchEnd2;
  850. HRESULT hr;
  851. //
  852. // Verbose output
  853. //
  854. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Entering.")));
  855. //
  856. // Check if we have run grpconv before.
  857. //
  858. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  859. TEXT("Software\\Program Groups"),
  860. 0,
  861. KEY_ALL_ACCESS,
  862. &hKey);
  863. if (lResult == ERROR_SUCCESS) {
  864. dwSize = sizeof(dwConvert);
  865. lResult = RegQueryValueEx (hKey,
  866. TEXT("ConvertedToLinks"),
  867. NULL,
  868. &dwType,
  869. (LPBYTE)&dwConvert,
  870. &dwSize);
  871. if (lResult == ERROR_SUCCESS) {
  872. //
  873. // If dwConvert is 1, then grpconv has run before.
  874. // Don't run it again.
  875. //
  876. if (dwConvert) {
  877. bRunGrpConv = FALSE;
  878. }
  879. }
  880. //
  881. // Now set the value to prevent grpconv from running in the future
  882. //
  883. dwConvert = 1;
  884. RegSetValueEx (hKey,
  885. TEXT("ConvertedToLinks"),
  886. 0,
  887. REG_DWORD,
  888. (LPBYTE) &dwConvert,
  889. sizeof(dwConvert));
  890. RegCloseKey (hKey);
  891. }
  892. if (bRunGrpConv) {
  893. //
  894. // Initialize process startup info
  895. //
  896. si.cb = sizeof(STARTUPINFO);
  897. si.lpReserved = NULL;
  898. si.lpDesktop = NULL;
  899. si.lpTitle = NULL;
  900. si.dwFlags = 0;
  901. si.lpReserved2 = NULL;
  902. si.cbReserved2 = 0;
  903. //
  904. // Spawn grpconv
  905. //
  906. StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), TEXT("grpconv -n"));
  907. Result = CreateProcess(
  908. NULL,
  909. szBuffer,
  910. NULL,
  911. NULL,
  912. FALSE,
  913. NORMAL_PRIORITY_CLASS,
  914. NULL,
  915. NULL,
  916. &si,
  917. &ProcessInformation
  918. );
  919. if (!Result) {
  920. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: grpconv failed to start due to error %d."), GetLastError()));
  921. return FALSE;
  922. } else {
  923. //
  924. // Wait for up to 2 minutes
  925. //
  926. WaitForSingleObject(ProcessInformation.hProcess, 120000);
  927. //
  928. // Close our handles to the process and thread
  929. //
  930. CloseHandle(ProcessInformation.hProcess);
  931. CloseHandle(ProcessInformation.hThread);
  932. }
  933. }
  934. //
  935. // Loop through all the program groups in the All Users profile
  936. // and remove the " (Common)" tag.
  937. //
  938. LoadString (g_hDllInstance, IDS_COMMON, szCommon, 30);
  939. cchCommon = lstrlen (szCommon);
  940. if (!GetSpecialFolderPath (CSIDL_COMMON_PROGRAMS, szBuffer2)) {
  941. return FALSE;
  942. }
  943. StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), szBuffer2);
  944. lpEnd = CheckSlashEx (szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
  945. lpEnd2 = CheckSlashEx (szBuffer2, ARRAYSIZE(szBuffer2), &cchEnd2);
  946. if (!lpEnd || !lpEnd2)
  947. {
  948. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: CheckSlashEx failed.")));
  949. return FALSE;
  950. }
  951. hr = StringCchCopy (lpEnd, cchEnd, c_szStarDotStar);
  952. if (FAILED(hr))
  953. {
  954. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
  955. return FALSE;
  956. }
  957. hFile = FindFirstFile (szBuffer, &fd);
  958. if (hFile != INVALID_HANDLE_VALUE) {
  959. do {
  960. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  961. cchFileName = lstrlen (fd.cFileName);
  962. if (cchFileName > cchCommon) {
  963. lpTag = fd.cFileName + cchFileName - cchCommon;
  964. if (!lstrcmpi(lpTag, szCommon)) {
  965. hr = StringCchCopy (lpEnd, cchEnd, fd.cFileName);
  966. if (FAILED(hr))
  967. {
  968. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
  969. continue;
  970. }
  971. *lpTag = TEXT('\0');
  972. hr = StringCchCopy (lpEnd2, cchEnd2, fd.cFileName);
  973. if (FAILED(hr))
  974. {
  975. DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
  976. continue;
  977. }
  978. if (MoveFileEx (szBuffer, szBuffer2, MOVEFILE_REPLACE_EXISTING)) {
  979. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Successfully changed group name:")));
  980. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
  981. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
  982. } else {
  983. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Failed to change group name with error %d."), GetLastError()));
  984. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
  985. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
  986. }
  987. }
  988. }
  989. }
  990. } while (FindNextFile(hFile, &fd));
  991. FindClose (hFile);
  992. }
  993. //
  994. // Success
  995. //
  996. DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Leaving Successfully.")));
  997. return TRUE;
  998. }
  999. //*************************************************************
  1000. //
  1001. // DetermineProfilesLocation()
  1002. //
  1003. // Purpose: Determines if the profiles directory
  1004. // should be in the old NT4 location or
  1005. // the new NT5 location
  1006. //
  1007. // Parameters: none
  1008. //
  1009. // Return: TRUE if successful
  1010. // FALSE if an error occurs
  1011. //
  1012. //*************************************************************
  1013. BOOL WINAPI DetermineProfilesLocation (BOOL bCleanInstall)
  1014. {
  1015. TCHAR szDirectory[MAX_PATH];
  1016. TCHAR szDest[MAX_PATH];
  1017. PTSTR szCurDest;
  1018. PCTSTR szLookAhead;
  1019. WIN32_FILE_ATTRIBUTE_DATA fad;
  1020. DWORD dwSize, dwDisp;
  1021. HKEY hKey;
  1022. LPTSTR lpEnd;
  1023. UINT cchEnd;
  1024. HRESULT hr;
  1025. //
  1026. // Save the clean install flag
  1027. //
  1028. g_bCleanInstall = bCleanInstall;
  1029. //
  1030. // First, try to delete the previous userenv logs
  1031. //
  1032. DeletePreviousLogFiles();
  1033. //
  1034. // Check for an unattended entry first
  1035. //
  1036. if (bCleanInstall) {
  1037. if (FAILED(SafeExpandEnvironmentStrings (TEXT("%SystemRoot%\\System32\\$winnt$.inf"), szDirectory,
  1038. ARRAYSIZE(szDirectory)))) {
  1039. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d"), GetLastError()));
  1040. return FALSE;
  1041. }
  1042. szDest[0] = TEXT('\0');
  1043. GetPrivateProfileString (TEXT("guiunattended"), TEXT("profilesdir"), TEXT(""),
  1044. szDest, MAX_PATH, szDirectory);
  1045. if (szDest[0] != TEXT('\0')) {
  1046. //
  1047. // Since $winnt$.inf is an INF, we must strip out %% pairs
  1048. //
  1049. szCurDest = szDest;
  1050. szLookAhead = szDest;
  1051. #ifdef UNICODE
  1052. while (*szLookAhead) {
  1053. if (szLookAhead[0] == L'%' && szLookAhead[1] == L'%') {
  1054. szLookAhead++; // pair of %%; skip one char
  1055. }
  1056. *szCurDest++ = *szLookAhead++;
  1057. }
  1058. #else
  1059. //
  1060. // This code path is not compiled so it has not been tested
  1061. //
  1062. #error Code written but not tested!
  1063. while (*szLookAhead) {
  1064. if (IsDbcsLeadByte (*szLookAhead)) {
  1065. *szCurDest++ = *szLookAhead++; // copy first half of byte pair
  1066. } else if (*szLookAhead == '%') {
  1067. if (!IsDbcsLeadByte (szLookAhead[1]) && szLookAhead[1] == '%') {
  1068. szLookAhead++; // pair of %%; skip one char
  1069. }
  1070. }
  1071. *szCurDest++ = *szLookAhead++;
  1072. }
  1073. #endif
  1074. *szCurDest = 0;
  1075. //
  1076. // The unattend profile directory exists. We need to set this
  1077. // path in the registry
  1078. //
  1079. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  1080. 0, NULL, REG_OPTION_NON_VOLATILE,
  1081. KEY_WRITE, NULL, &hKey,
  1082. &dwDisp) == ERROR_SUCCESS) {
  1083. if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
  1084. 0, REG_EXPAND_SZ, (LPBYTE) szDest,
  1085. ((lstrlen(szDest) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  1086. DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using unattend location %s for user profiles"), szDest));
  1087. }
  1088. RegCloseKey (hKey);
  1089. }
  1090. }
  1091. } else {
  1092. //
  1093. // By default, the OS will try to use the new location for
  1094. // user profiles, but if we are doing an upgrade of a machine
  1095. // with profiles in the NT4 location, we want to continue
  1096. // to use that location.
  1097. //
  1098. // Build a test path to the old All Users directory on NT4
  1099. // to determine which location to use.
  1100. //
  1101. if (FAILED(SafeExpandEnvironmentStrings (NT4_PROFILES_DIRECTORY, szDirectory,
  1102. ARRAYSIZE(szDirectory)))) {
  1103. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d, setting the dir unexpanded"), GetLastError()));
  1104. return FALSE;
  1105. }
  1106. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1107. if (!lpEnd)
  1108. {
  1109. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: CheckSlashEx failed")));
  1110. return FALSE;
  1111. }
  1112. hr = StringCchCopy (lpEnd, cchEnd, ALL_USERS);
  1113. if (FAILED(hr))
  1114. {
  1115. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: StringCchCopy failed")));
  1116. return FALSE;
  1117. }
  1118. if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
  1119. //
  1120. // An app was found that creates an "All Users" directory under NT4 profiles directory
  1121. // Check for Default User as well.
  1122. //
  1123. hr = StringCchCopy (lpEnd, cchEnd, DEFAULT_USER);
  1124. if (FAILED(hr))
  1125. {
  1126. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: StringCchCopy failed")));
  1127. return FALSE;
  1128. }
  1129. if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
  1130. //
  1131. // The old profiles directory exists. We need to set this
  1132. // path in the registry
  1133. //
  1134. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  1135. 0, NULL, REG_OPTION_NON_VOLATILE,
  1136. KEY_WRITE, NULL, &hKey,
  1137. &dwDisp) == ERROR_SUCCESS) {
  1138. if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
  1139. 0, REG_EXPAND_SZ, (LPBYTE) NT4_PROFILES_DIRECTORY,
  1140. ((lstrlen(NT4_PROFILES_DIRECTORY) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  1141. DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using NT4 location for user profiles")));
  1142. }
  1143. RegCloseKey (hKey);
  1144. }
  1145. }
  1146. }
  1147. }
  1148. //
  1149. // Check if the profiles directory exists.
  1150. //
  1151. dwSize = ARRAYSIZE(szDirectory);
  1152. if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1153. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
  1154. return FALSE;
  1155. }
  1156. if (!CreateSecureAdminDirectory(szDirectory, OTHERSIDS_EVERYONE)) {
  1157. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create profiles subdirectory <%s>. Error = %d."),
  1158. szDirectory, GetLastError()));
  1159. return FALSE;
  1160. }
  1161. //
  1162. // Decide where the Default User profile should be
  1163. //
  1164. if (!CheckProfile (szDirectory, DEFAULT_USER_PROFILE, DEFAULT_USER)) {
  1165. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check default user profile Error = %d."),
  1166. GetLastError()));
  1167. return FALSE;
  1168. }
  1169. //
  1170. // Check if the profiles\Default User directory exists
  1171. //
  1172. dwSize = ARRAYSIZE(szDirectory);
  1173. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1174. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query default user profile directory.")));
  1175. return FALSE;
  1176. }
  1177. if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_EVERYONE)) {
  1178. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create Default User subdirectory <%s>. Error = %d."),
  1179. szDirectory, GetLastError()));
  1180. return FALSE;
  1181. }
  1182. SetFileAttributes (szDirectory, FILE_ATTRIBUTE_HIDDEN);
  1183. //
  1184. // Decide where the All Users profile should be
  1185. //
  1186. dwSize = ARRAYSIZE(szDirectory);
  1187. if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1188. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
  1189. return FALSE;
  1190. }
  1191. if (!CheckProfile (szDirectory, ALL_USERS_PROFILE, ALL_USERS)) {
  1192. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check all users profile Error = %d."),
  1193. GetLastError()));
  1194. return FALSE;
  1195. }
  1196. //
  1197. // Check if the profiles\All Users directory exists
  1198. //
  1199. dwSize = ARRAYSIZE(szDirectory);
  1200. if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1201. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query all users profile directory.")));
  1202. return FALSE;
  1203. }
  1204. //
  1205. // Give additional permissions for power users/everyone
  1206. //
  1207. if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_POWERUSERS | OTHERSIDS_EVERYONE)) {
  1208. DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create All Users subdirectory <%s>. Error = %d."),
  1209. szDirectory, GetLastError()));
  1210. return FALSE;
  1211. }
  1212. //
  1213. // Hide some special profiles like NetworkService etc.
  1214. //
  1215. if (!bCleanInstall) {
  1216. HideSpecialProfiles();
  1217. }
  1218. return TRUE;
  1219. }
  1220. //*************************************************************
  1221. //
  1222. // InitializeProfiles()
  1223. //
  1224. // Purpose: Confirms / Creates the profile, Default User,
  1225. // and All Users directories, and converts any
  1226. // existing common groups.
  1227. //
  1228. // Parameters:
  1229. //
  1230. // Return: TRUE if successful
  1231. // FALSE if an error occurs
  1232. //
  1233. // Comments: This should only be called by GUI mode setup!
  1234. //
  1235. // History: Date Author Comment
  1236. // 8/08/95 ericflo Created
  1237. //
  1238. //*************************************************************
  1239. BOOL WINAPI InitializeProfiles (BOOL bGuiModeSetup)
  1240. {
  1241. TCHAR szDirectory[MAX_PATH];
  1242. TCHAR szSystemProfile[MAX_PATH];
  1243. TCHAR szTemp[MAX_PATH];
  1244. TCHAR szTemp2[MAX_PATH];
  1245. DWORD dwSize;
  1246. DWORD dwDisp;
  1247. LPTSTR lpEnd;
  1248. DWORD i;
  1249. HKEY hKey;
  1250. BOOL bRetVal = FALSE;
  1251. DWORD dwErr;
  1252. PSHELL32_API pShell32Api;
  1253. HRESULT hr;
  1254. UINT cchEnd;
  1255. dwErr = GetLastError();
  1256. //
  1257. // Verbose output
  1258. //
  1259. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Entering.")));
  1260. if (!bGuiModeSetup) {
  1261. //
  1262. // block loading user profile
  1263. //
  1264. if (g_hProfileSetup) {
  1265. ResetEvent (g_hProfileSetup);
  1266. }
  1267. }
  1268. dwErr = LoadShell32Api( &pShell32Api );
  1269. if ( dwErr != ERROR_SUCCESS ) {
  1270. goto Exit;
  1271. }
  1272. //
  1273. // Set the USERPROFILE environment variable
  1274. //
  1275. hr = SafeExpandEnvironmentStrings(SYSTEM_PROFILE_LOCATION, szSystemProfile, MAX_PATH);
  1276. if (FAILED(hr))
  1277. {
  1278. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to enpand env string for system profile.")));
  1279. dwErr = HRESULT_CODE(hr);
  1280. goto Exit;
  1281. }
  1282. //
  1283. // Requery for the default user profile directory (expanded version)
  1284. //
  1285. dwSize = ARRAYSIZE(szDirectory);
  1286. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1287. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
  1288. dwErr = GetLastError();
  1289. goto Exit;
  1290. }
  1291. //
  1292. // Set the USERPROFILE environment variable
  1293. //
  1294. if (!SetEnvironmentVariable (TEXT("USERPROFILE"), szDirectory))
  1295. {
  1296. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to set env var for user profile.")));
  1297. }
  1298. //
  1299. // Create all the folders under Default User
  1300. //
  1301. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1302. if (!lpEnd)
  1303. {
  1304. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to CheckSlashEx.")));
  1305. dwErr = ERROR_BAD_PATHNAME;
  1306. goto Exit;
  1307. }
  1308. //
  1309. // Loop through the shell folders
  1310. //
  1311. for (i=0; i < g_dwNumShellFolders; i++) {
  1312. hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
  1313. if (FAILED(hr))
  1314. {
  1315. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
  1316. dwErr = HRESULT_CODE(hr);
  1317. goto Exit;
  1318. }
  1319. if (!CreateNestedDirectory(szDirectory, NULL)) {
  1320. dwErr = GetLastError();
  1321. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
  1322. szDirectory, dwErr));
  1323. goto Exit;
  1324. }
  1325. if (c_ShellFolders[i].iFolderResourceID != 0) {
  1326. // NOTE this returns an HRESULT
  1327. dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
  1328. c_ShellFolders[i].lpFolderResourceDLL,
  1329. c_ShellFolders[i].iFolderResourceID );
  1330. if (FAILED(dwErr)) {
  1331. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
  1332. szDirectory, dwErr));
  1333. goto Exit;
  1334. }
  1335. }
  1336. if (c_ShellFolders[i].bHidden) {
  1337. SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
  1338. }
  1339. }
  1340. //
  1341. // Remove the %USERPROFILE%\Personal directory if it exists.
  1342. // Windows NT 4.0 had a Personal folder in the root of the
  1343. // user's profile. NT 5.0 renames this folder to My Documents
  1344. //
  1345. if (LoadString (g_hDllInstance, IDS_SH_PERSONAL2, szTemp, ARRAYSIZE(szTemp))) {
  1346. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1347. if (FAILED(hr))
  1348. {
  1349. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy personal2.")));
  1350. dwErr = HRESULT_CODE(hr);
  1351. goto Exit;
  1352. }
  1353. RemoveDirectory(szDirectory);
  1354. }
  1355. //
  1356. // Migrate the Template Directory if it exists. Copy it from %systemroot%\shellnew
  1357. // to Templates directory under default user. Do the same for existing profiles.
  1358. //
  1359. if ((LoadString (g_hDllInstance, IDS_SH_TEMPLATES2, szTemp, ARRAYSIZE(szTemp))) &&
  1360. (SUCCEEDED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2)))) &&
  1361. (LoadString (g_hDllInstance, IDS_SH_TEMPLATES, szTemp, ARRAYSIZE(szTemp)))) {
  1362. //
  1363. // if all of the above succeeded
  1364. //
  1365. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1366. if (FAILED(hr))
  1367. {
  1368. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy template.")));
  1369. }
  1370. else
  1371. {
  1372. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Copying <%s> to %s."), szTemp2, szDirectory));
  1373. CopyProfileDirectory(szTemp2, szDirectory, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE);
  1374. }
  1375. }
  1376. //
  1377. // Remove %USERPROFILE%\Temp if it exists. The Temp directory
  1378. // will now be in the Local Settings folder
  1379. //
  1380. hr = StringCchCopy (lpEnd, cchEnd, TEXT("Temp"));
  1381. if (SUCCEEDED(hr))
  1382. {
  1383. Delnode(szDirectory);
  1384. }
  1385. else
  1386. {
  1387. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy temp.")));
  1388. }
  1389. //
  1390. // Remove %USERPROFILE%\Temporary Internet Files if it exists. The
  1391. // Temporary Internet Files directory will now be in the Local Settings
  1392. // folder
  1393. //
  1394. if (LoadString (g_hDllInstance, IDS_TEMPINTERNETFILES, szTemp, ARRAYSIZE(szTemp))) {
  1395. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1396. if (SUCCEEDED(hr))
  1397. {
  1398. Delnode(szDirectory);
  1399. }
  1400. else
  1401. {
  1402. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy temp internet files.")));
  1403. }
  1404. }
  1405. //
  1406. // Remove %USERPROFILE%\History if it exists. The History
  1407. // directory will now be in the Local Settings folder
  1408. //
  1409. if (LoadString (g_hDllInstance, IDS_HISTORY, szTemp, ARRAYSIZE(szTemp))) {
  1410. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1411. if (SUCCEEDED(hr))
  1412. {
  1413. Delnode(szDirectory);
  1414. }
  1415. else
  1416. {
  1417. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy history.")));
  1418. }
  1419. }
  1420. //
  1421. // Set the User Shell Folder paths in the registry
  1422. //
  1423. hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), USER_SHELL_FOLDERS, NULL, NULL);
  1424. if (FAILED(hr))
  1425. {
  1426. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to append user shell folders to .default.")));
  1427. dwErr = HRESULT_CODE(hr);
  1428. goto Exit;
  1429. }
  1430. hr = StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%USERPROFILE%"));
  1431. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1432. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1433. 0, NULL, REG_OPTION_NON_VOLATILE,
  1434. KEY_READ | KEY_WRITE, NULL, &hKey,
  1435. &dwDisp) == ERROR_SUCCESS) {
  1436. for (i=0; i < g_dwNumShellFolders; i++) {
  1437. if (c_ShellFolders[i].bAddCSIDL) {
  1438. hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
  1439. if (FAILED(hr))
  1440. {
  1441. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
  1442. dwErr = HRESULT_CODE(hr);
  1443. goto Exit;
  1444. }
  1445. RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
  1446. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1447. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1448. }
  1449. }
  1450. RegCloseKey (hKey);
  1451. }
  1452. //
  1453. // Set the Shell Folder paths in the registry
  1454. //
  1455. hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), SHELL_FOLDERS, NULL, NULL);
  1456. if (FAILED(hr))
  1457. {
  1458. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to append user shell folders to .default.")));
  1459. dwErr = HRESULT_CODE(hr);
  1460. goto Exit;
  1461. }
  1462. dwSize = ARRAYSIZE(szDirectory);
  1463. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1464. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
  1465. dwErr = GetLastError();
  1466. goto Exit;
  1467. }
  1468. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1469. if (!lpEnd)
  1470. {
  1471. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: CheckSlashEx failed.")));
  1472. dwErr = ERROR_BAD_PATHNAME;
  1473. goto Exit;
  1474. }
  1475. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1476. 0, NULL, REG_OPTION_NON_VOLATILE,
  1477. KEY_READ | KEY_WRITE, NULL, &hKey,
  1478. &dwDisp) == ERROR_SUCCESS) {
  1479. for (i=0; i < g_dwNumShellFolders; i++) {
  1480. if (c_ShellFolders[i].bAddCSIDL) {
  1481. hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
  1482. if (FAILED(hr))
  1483. {
  1484. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
  1485. dwErr = HRESULT_CODE(hr);
  1486. goto Exit;
  1487. }
  1488. RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
  1489. 0, REG_SZ, (LPBYTE) szDirectory,
  1490. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1491. }
  1492. }
  1493. RegCloseKey (hKey);
  1494. }
  1495. //
  1496. // Set the per user TEMP and TMP environment variables
  1497. //
  1498. if (LoadString (g_hDllInstance, IDS_SH_TEMP,
  1499. szTemp, ARRAYSIZE(szTemp))) {
  1500. StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%USERPROFILE%"));
  1501. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1502. LoadString (g_hDllInstance, IDS_SH_LOCALSETTINGS,
  1503. lpEnd, cchEnd);
  1504. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1505. if (lpEnd)
  1506. {
  1507. hr = StringCchCopy(lpEnd, cchEnd, szTemp);
  1508. if (SUCCEEDED(hr))
  1509. {
  1510. if (RegCreateKeyEx (HKEY_USERS, TEXT(".Default\\Environment"),
  1511. 0, NULL, REG_OPTION_NON_VOLATILE,
  1512. KEY_WRITE, NULL, &hKey,
  1513. &dwDisp) == ERROR_SUCCESS) {
  1514. RegSetValueEx (hKey, TEXT("TEMP"),
  1515. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1516. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1517. RegSetValueEx (hKey, TEXT("TMP"),
  1518. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1519. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1520. RegCloseKey (hKey);
  1521. }
  1522. }
  1523. }
  1524. }
  1525. //
  1526. // Set the user preference exclusion list. This will
  1527. // prevent the Local Settings folder from roaming
  1528. //
  1529. if (LoadString (g_hDllInstance, IDS_EXCLUSIONLIST,
  1530. szDirectory, ARRAYSIZE(szDirectory))) {
  1531. hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), WINLOGON_KEY, NULL, NULL);
  1532. if (RegCreateKeyEx (HKEY_USERS, szTemp,
  1533. 0, NULL, REG_OPTION_NON_VOLATILE,
  1534. KEY_READ | KEY_WRITE, NULL, &hKey,
  1535. &dwDisp) == ERROR_SUCCESS) {
  1536. RegSetValueEx (hKey, TEXT("ExcludeProfileDirs"),
  1537. 0, REG_SZ, (LPBYTE) szDirectory,
  1538. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1539. RegCloseKey (hKey);
  1540. }
  1541. }
  1542. //
  1543. // Requery for the all users profile directory (expanded version)
  1544. //
  1545. dwSize = ARRAYSIZE(szDirectory);
  1546. if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1547. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query all users profile directory.")));
  1548. dwErr = GetLastError();
  1549. goto Exit;
  1550. }
  1551. //
  1552. // Set the ALLUSERSPROFILE environment variable
  1553. //
  1554. SetEnvironmentVariable (TEXT("ALLUSERSPROFILE"), szDirectory);
  1555. //
  1556. // Create all the folders under All Users
  1557. //
  1558. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1559. if (!lpEnd)
  1560. {
  1561. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: CheckSlashEx failed.")));
  1562. dwErr = ERROR_BAD_PATHNAME;
  1563. goto Exit;
  1564. }
  1565. //
  1566. // Loop through the shell folders
  1567. //
  1568. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1569. hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
  1570. if (FAILED(hr))
  1571. {
  1572. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
  1573. c_CommonShellFolders[i].szFolderLocation));
  1574. dwErr = HRESULT_CODE(hr);
  1575. goto Exit;
  1576. }
  1577. if (!CreateNestedDirectory(szDirectory, NULL)) {
  1578. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
  1579. szDirectory, GetLastError()));
  1580. dwErr = GetLastError();
  1581. goto Exit;
  1582. }
  1583. if (c_CommonShellFolders[i].iFolderResourceID != 0) {
  1584. // NOTE this returns an HRESULT
  1585. dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
  1586. c_CommonShellFolders[i].lpFolderResourceDLL,
  1587. c_CommonShellFolders[i].iFolderResourceID );
  1588. if (FAILED(dwErr)) {
  1589. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
  1590. szDirectory, dwErr));
  1591. goto Exit;
  1592. }
  1593. }
  1594. if (c_CommonShellFolders[i].bHidden) {
  1595. SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
  1596. }
  1597. }
  1598. //
  1599. // Unsecure the Documents and App Data folders in the All Users profile
  1600. //
  1601. if (LoadString (g_hDllInstance, IDS_SH_SHAREDDOCS, szTemp, ARRAYSIZE(szTemp))) {
  1602. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1603. if (SUCCEEDED(hr))
  1604. {
  1605. SetFilePermissions(szDirectory, c_szCommonDocumentsACL);
  1606. }
  1607. }
  1608. if (LoadString (g_hDllInstance, IDS_SH_APPDATA, szTemp, ARRAYSIZE(szTemp))) {
  1609. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  1610. if (SUCCEEDED(hr))
  1611. {
  1612. SetFilePermissions(szDirectory, c_szCommonAppDataACL);
  1613. }
  1614. }
  1615. //
  1616. // Set the User Shell Folder paths in the registry
  1617. //
  1618. StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%ALLUSERSPROFILE%"));
  1619. lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
  1620. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS,
  1621. 0, NULL, REG_OPTION_NON_VOLATILE,
  1622. KEY_READ | KEY_WRITE, NULL, &hKey,
  1623. &dwDisp) == ERROR_SUCCESS) {
  1624. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1625. if (c_ShellFolders[i].bAddCSIDL) {
  1626. hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
  1627. if (FAILED(hr))
  1628. {
  1629. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
  1630. c_CommonShellFolders[i].szFolderLocation));
  1631. dwErr = HRESULT_CODE(hr);
  1632. goto Exit;
  1633. }
  1634. RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
  1635. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1636. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1637. }
  1638. }
  1639. RegCloseKey (hKey);
  1640. }
  1641. #if defined(_WIN64)
  1642. //
  1643. // On 64-bit NT, we need to create the user shell folders in
  1644. // the 32-bit view of the registry so that 32-bit app calls
  1645. // to SHGetFolderPath(...CSIDL_COMMON_APPDATA...) would succeed.
  1646. //
  1647. if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS32,
  1648. 0, NULL, REG_OPTION_NON_VOLATILE,
  1649. KEY_READ | KEY_WRITE, NULL, &hKey,
  1650. &dwDisp) == ERROR_SUCCESS) {
  1651. for (i=0; i < g_dwNumCommonShellFolders; i++) {
  1652. if (c_ShellFolders[i].bAddCSIDL) {
  1653. hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
  1654. if (FAILED(hr))
  1655. {
  1656. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
  1657. c_CommonShellFolders[i].szFolderLocation));
  1658. dwErr = HRESULT_CODE(hr);
  1659. goto Exit;
  1660. }
  1661. RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
  1662. 0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
  1663. ((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
  1664. }
  1665. }
  1666. RegCloseKey (hKey);
  1667. }
  1668. #endif
  1669. //
  1670. // Convert any Program Manager common groups
  1671. //
  1672. if (!ConvertCommonGroups()) {
  1673. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ConvertCommonGroups failed.")));
  1674. }
  1675. //
  1676. // Reacl the ProfileList entries
  1677. //
  1678. hr = ReaclProfileListEntries();
  1679. if (FAILED(hr))
  1680. {
  1681. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ReaclProfileListEntries failed, hr = %08X"), hr));
  1682. }
  1683. //
  1684. // Reacl the user profile folders in case of upgrade
  1685. //
  1686. if (!g_bCleanInstall)
  1687. {
  1688. SecureUserProfiles();
  1689. }
  1690. //
  1691. // Set the PROFILES env var, will used by the security template to skip
  1692. // applying the template on the profile directory
  1693. //
  1694. dwSize = ARRAYSIZE(szTemp);
  1695. if (GetProfilesDirectoryEx(szTemp, &dwSize, TRUE))
  1696. {
  1697. if (SetEnvironmentVariable(c_szProfileEnvName, szTemp))
  1698. {
  1699. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: set env var <%s>=%s"), c_szProfileEnvName, szTemp));
  1700. }
  1701. else
  1702. {
  1703. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SetEnvironmentVariable failed, error = %d"), GetLastError()));
  1704. }
  1705. }
  1706. else
  1707. {
  1708. DebugMsg((DM_WARNING, TEXT("InitializeProfiles: GetProfilesDirectoryEx failed, error = %d"), GetLastError()));
  1709. }
  1710. //
  1711. // Success
  1712. //
  1713. DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Leaving successfully.")));
  1714. bRetVal = TRUE;
  1715. Exit:
  1716. if ((!bGuiModeSetup) && (g_hProfileSetup)) {
  1717. SetEvent (g_hProfileSetup);
  1718. }
  1719. SetLastError(dwErr);
  1720. return bRetVal;
  1721. }
  1722. //*************************************************************
  1723. //
  1724. // CheckProfile()
  1725. //
  1726. // Purpose: Checks and creates a storage location for either
  1727. // the Default User or All Users profile
  1728. //
  1729. // Parameters: LPTSTR lpProfilesDir - Root of the profiles
  1730. // LPTSTR lpProfileValue - Profile registry value name
  1731. // LPTSTR lpProfileName - Default profile name
  1732. //
  1733. //
  1734. // Return: TRUE if successful
  1735. // FALSE if an error occurs
  1736. //
  1737. //*************************************************************
  1738. BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
  1739. LPTSTR lpProfileName)
  1740. {
  1741. TCHAR szTemp[MAX_PATH];
  1742. TCHAR szTemp2[MAX_PATH];
  1743. TCHAR szName[MAX_PATH];
  1744. TCHAR szFormat[30];
  1745. DWORD dwSize, dwDisp, dwType;
  1746. LPTSTR lpEnd;
  1747. LONG lResult;
  1748. HKEY hKey;
  1749. INT iStrLen;
  1750. WIN32_FILE_ATTRIBUTE_DATA fad;
  1751. UINT cchEnd;
  1752. HRESULT hr;
  1753. //
  1754. // Open the ProfileList key
  1755. //
  1756. lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
  1757. 0, NULL, REG_OPTION_NON_VOLATILE,
  1758. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  1759. if (lResult != ERROR_SUCCESS) {
  1760. DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to open profile list key with %d."),
  1761. lResult));
  1762. return FALSE;
  1763. }
  1764. //
  1765. // Check the registry to see if this folder is defined already
  1766. //
  1767. dwSize = sizeof(szTemp);
  1768. if (RegQueryValueEx (hKey, lpProfileValue, NULL, &dwType,
  1769. (LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
  1770. RegCloseKey (hKey);
  1771. return TRUE;
  1772. }
  1773. //
  1774. // Generate the default name
  1775. //
  1776. hr = AppendName(szTemp, ARRAYSIZE(szTemp), lpProfilesDir, lpProfileName, &lpEnd, &cchEnd);
  1777. if (FAILED(hr))
  1778. {
  1779. DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to append lpProfileName to lpProfilesDir.")))
  1780. return FALSE;
  1781. }
  1782. StringCchCopy (szName, ARRAYSIZE(szName), lpProfileName);
  1783. //
  1784. // Check if this directory exists
  1785. //
  1786. if (FAILED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2))))
  1787. {
  1788. DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to expand env string.")))
  1789. return FALSE;
  1790. }
  1791. if (GetFileAttributesEx (szTemp2, GetFileExInfoStandard, &fad)) {
  1792. if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1793. //
  1794. // Check if this directory is under the system root.
  1795. // If so, this is ok, we don't need to generate a unique
  1796. // name for this.
  1797. //
  1798. hr = SafeExpandEnvironmentStrings (TEXT("%SystemRoot%"), szTemp, ARRAYSIZE(szTemp));
  1799. if (FAILED(hr))
  1800. {
  1801. DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to %SystemRoot%.")))
  1802. return FALSE;
  1803. }
  1804. iStrLen = lstrlen (szTemp);
  1805. if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  1806. szTemp, iStrLen, szTemp2, iStrLen) != CSTR_EQUAL) {
  1807. //
  1808. // The directory exists already. Use a new name of
  1809. // Profile Name (SystemDirectory)
  1810. //
  1811. // eg: Default User (WINNT)
  1812. //
  1813. lpEnd = szTemp + lstrlen(szTemp) - 1;
  1814. while ((lpEnd > szTemp) && ((*lpEnd) != TEXT('\\')))
  1815. lpEnd--;
  1816. if (*lpEnd == TEXT('\\')) {
  1817. lpEnd++;
  1818. }
  1819. LoadString (g_hDllInstance, IDS_PROFILE_FORMAT, szFormat,
  1820. ARRAYSIZE(szFormat));
  1821. StringCchPrintf (szName, ARRAYSIZE(szName), szFormat, lpProfileName, lpEnd);
  1822. //
  1823. // To prevent reusing the directories, delete it first..
  1824. //
  1825. AppendName(szTemp, ARRAYSIZE(szTemp), lpProfilesDir, szName, NULL, NULL);
  1826. if (SUCCEEDED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2)))) {
  1827. DebugMsg((DM_VERBOSE, TEXT("CheckProfile: Delnoding directory.. %s"), szTemp2));
  1828. Delnode(szTemp2);
  1829. }
  1830. }
  1831. }
  1832. }
  1833. //
  1834. // Save the profile name in the registry
  1835. //
  1836. RegSetValueEx (hKey, lpProfileValue,
  1837. 0, REG_SZ, (LPBYTE) szName,
  1838. ((lstrlen(szName) + 1) * sizeof(TCHAR)));
  1839. RegCloseKey (hKey);
  1840. DebugMsg((DM_VERBOSE, TEXT("CheckProfile: The %s profile is mapped to %s"),
  1841. lpProfileName, szName));
  1842. return TRUE;
  1843. }
  1844. //*************************************************************
  1845. //
  1846. // CreateUserProfile()
  1847. //
  1848. // Purpose: Creates a new user profile, but does not load
  1849. // the hive.
  1850. //
  1851. // Parameters: pSid - SID pointer
  1852. // lpUserName - User name
  1853. // lpUserHive - Optional user hive
  1854. // lpProfileDir - Receives the new profile directory
  1855. // dwDirSize - Size of lpProfileDir
  1856. //
  1857. // Return: TRUE if successful
  1858. // FALSE if an error occurs
  1859. //
  1860. // Comments: If a user hive isn't specified the default user
  1861. // hive will be used.
  1862. //
  1863. // History: Date Author Comment
  1864. // 9/12/95 ericflo Created
  1865. //
  1866. //*************************************************************
  1867. BOOL WINAPI CreateUserProfile (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
  1868. LPTSTR lpProfileDir, DWORD dwDirSize)
  1869. {
  1870. return CreateUserProfileEx(pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, TRUE);
  1871. }
  1872. //*************************************************************
  1873. //
  1874. // CreateUserProfileEx()
  1875. //
  1876. // Purpose: Creates a new user profile, but does not load
  1877. // the hive.
  1878. //
  1879. // Parameters: pSid - SID pointer
  1880. // lpUserName - User name
  1881. // lpUserHive - Optional user hive
  1882. // lpProfileDir - Receives the new profile directory
  1883. // dwDirSize - Size of lpProfileDir
  1884. // bWin9xUpg - Flag to say whether it is win9x upgrade
  1885. //
  1886. // Return: TRUE if successful
  1887. // FALSE if an error occurs
  1888. //
  1889. // Comments: If a user hive isn't specified the default user
  1890. // hive will be used.
  1891. //
  1892. // History: Date Author Comment
  1893. // 9/12/95 ericflo Created
  1894. //
  1895. //*************************************************************
  1896. BOOL WINAPI CreateUserProfileEx (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
  1897. LPTSTR lpProfileDir, DWORD dwDirSize, BOOL bWin9xUpg)
  1898. {
  1899. TCHAR szProfileDir[MAX_PATH];
  1900. TCHAR szExpProfileDir[MAX_PATH] = {0};
  1901. TCHAR szDirectory[MAX_PATH];
  1902. TCHAR LocalProfileKey[MAX_PATH];
  1903. UNICODE_STRING UnicodeString;
  1904. LPTSTR lpSidString, lpEnd, lpSave;
  1905. NTSTATUS NtStatus;
  1906. LONG lResult;
  1907. DWORD dwDisp;
  1908. DWORD dwError;
  1909. DWORD dwSize;
  1910. DWORD dwType;
  1911. HKEY hKey;
  1912. UINT cchEnd;
  1913. HRESULT hr;
  1914. //
  1915. // Check parameters
  1916. //
  1917. if (!lpUserName || !lpUserName[0]) {
  1918. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null username.")));
  1919. return FALSE;
  1920. }
  1921. if (!pSid) {
  1922. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null SID.")));
  1923. return FALSE;
  1924. }
  1925. //
  1926. // Verbose output
  1927. //
  1928. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with <%s>."), lpUserName));
  1929. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with user hive of <%s>."),
  1930. lpUserHive ? lpUserHive : TEXT("NULL")));
  1931. //
  1932. // Convert the sid into text format
  1933. //
  1934. NtStatus = RtlConvertSidToUnicodeString(&UnicodeString, pSid, (BOOLEAN)TRUE);
  1935. if (!NT_SUCCESS(NtStatus)) {
  1936. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x"),
  1937. NtStatus));
  1938. return FALSE;
  1939. }
  1940. lpSidString = UnicodeString.Buffer;
  1941. //
  1942. // Check if this user's profile exists already
  1943. //
  1944. GetProfileListKeyName(LocalProfileKey, ARRAYSIZE(LocalProfileKey), lpSidString);
  1945. szProfileDir[0] = TEXT('\0');
  1946. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
  1947. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  1948. dwSize = sizeof(szProfileDir);
  1949. RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
  1950. &dwType, (LPBYTE) szProfileDir, &dwSize);
  1951. RegCloseKey (hKey);
  1952. }
  1953. if (szProfileDir[0] == TEXT('\0')) {
  1954. //
  1955. // Make the user's directory
  1956. //
  1957. dwSize = ARRAYSIZE(szProfileDir);
  1958. if (!GetProfilesDirectoryEx(szProfileDir, &dwSize, FALSE)) {
  1959. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get profile root directory.")));
  1960. RtlFreeUnicodeString(&UnicodeString);
  1961. return FALSE;
  1962. }
  1963. if (!ComputeLocalProfileName (NULL, lpUserName, szProfileDir, ARRAYSIZE(szProfileDir),
  1964. szExpProfileDir, ARRAYSIZE(szExpProfileDir), pSid, bWin9xUpg)) {
  1965. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to create directory.")));
  1966. RtlFreeUnicodeString(&UnicodeString);
  1967. return FALSE;
  1968. }
  1969. //
  1970. // Copy the default user profile into this directory
  1971. //
  1972. dwSize = ARRAYSIZE(szDirectory);
  1973. if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
  1974. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get default user profile.")));
  1975. RtlFreeUnicodeString(&UnicodeString);
  1976. return FALSE;
  1977. }
  1978. if (lpUserHive) {
  1979. //
  1980. // Copy the default user profile without the hive.
  1981. //
  1982. if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE | CPD_IGNORELONGFILENAMES)) {
  1983. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
  1984. RtlFreeUnicodeString(&UnicodeString);
  1985. return FALSE;
  1986. }
  1987. //
  1988. // Now copy the hive
  1989. //
  1990. hr = AppendName(szDirectory, ARRAYSIZE(szDirectory), szExpProfileDir, c_szNTUserDat, NULL, NULL);
  1991. if (FAILED(hr))
  1992. {
  1993. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to append ntuser.dat.")));
  1994. RtlFreeUnicodeString(&UnicodeString);
  1995. return FALSE;
  1996. }
  1997. if (lstrcmpi (lpUserHive, szDirectory)) {
  1998. if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
  1999. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
  2000. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
  2001. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
  2002. RtlFreeUnicodeString(&UnicodeString);
  2003. return FALSE;
  2004. }
  2005. }
  2006. } else {
  2007. //
  2008. // Copy the default user profile and the hive.
  2009. //
  2010. if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNORELONGFILENAMES)) {
  2011. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
  2012. RtlFreeUnicodeString(&UnicodeString);
  2013. return FALSE;
  2014. }
  2015. }
  2016. //
  2017. // Save the user's profile in the registry.
  2018. //
  2019. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
  2020. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  2021. if (lResult != ERROR_SUCCESS) {
  2022. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, lResult));
  2023. RtlFreeUnicodeString(&UnicodeString);
  2024. return FALSE;
  2025. }
  2026. //
  2027. // Add the profile directory
  2028. //
  2029. lResult = RegSetValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0,
  2030. REG_EXPAND_SZ,
  2031. (LPBYTE)szProfileDir,
  2032. sizeof(TCHAR)*(lstrlen(szProfileDir) + 1));
  2033. if (lResult != ERROR_SUCCESS) {
  2034. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: First RegSetValueEx failed, error = %d."), lResult));
  2035. RegCloseKey (hKey);
  2036. RtlFreeUnicodeString(&UnicodeString);
  2037. return FALSE;
  2038. }
  2039. //
  2040. // Add the users's SID
  2041. //
  2042. lResult = RegSetValueEx(hKey, TEXT("Sid"), 0,
  2043. REG_BINARY, pSid, RtlLengthSid(pSid));
  2044. if (lResult != ERROR_SUCCESS) {
  2045. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Second RegSetValueEx failed, error = %d."), lResult));
  2046. }
  2047. //
  2048. // Close the registry key
  2049. //
  2050. RegCloseKey (hKey);
  2051. } else {
  2052. //
  2053. // The user already has a profile, so just copy the hive if
  2054. // appropriate.
  2055. //
  2056. hr = SafeExpandEnvironmentStrings (szProfileDir, szExpProfileDir,
  2057. ARRAYSIZE(szExpProfileDir));
  2058. if (FAILED(hr))
  2059. {
  2060. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to expand env string.")));
  2061. RtlFreeUnicodeString(&UnicodeString);
  2062. return FALSE;
  2063. }
  2064. if (lpUserHive) {
  2065. //
  2066. // Copy the hive
  2067. //
  2068. hr = AppendName(szDirectory, ARRAYSIZE(szDirectory), szExpProfileDir, c_szNTUserDat, NULL, NULL);
  2069. if (FAILED(hr))
  2070. {
  2071. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to append ntuser.dat.")));
  2072. RtlFreeUnicodeString(&UnicodeString);
  2073. return FALSE;
  2074. }
  2075. SetFileAttributes (szDirectory, FILE_ATTRIBUTE_NORMAL);
  2076. if (lstrcmpi (lpUserHive, szDirectory)) {
  2077. if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
  2078. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
  2079. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
  2080. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
  2081. RtlFreeUnicodeString(&UnicodeString);
  2082. return FALSE;
  2083. }
  2084. }
  2085. }
  2086. }
  2087. //
  2088. // Now load the hive temporary so the security can be fixed
  2089. //
  2090. lpEnd = CheckSlashEx (szExpProfileDir, ARRAYSIZE(szExpProfileDir), &cchEnd);
  2091. lpSave = lpEnd - 1;
  2092. StringCchCopy (lpEnd, cchEnd, c_szNTUserDat);
  2093. lResult = MyRegLoadKey(HKEY_USERS, lpSidString, szExpProfileDir);
  2094. *lpSave = TEXT('\0');
  2095. if (lResult != ERROR_SUCCESS) {
  2096. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to load hive, error = %d."), lResult));
  2097. dwError = GetLastError();
  2098. DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
  2099. RtlFreeUnicodeString(&UnicodeString);
  2100. SetLastError(dwError);
  2101. return FALSE;
  2102. }
  2103. if (!SetupNewHive(NULL, lpSidString, pSid)) {
  2104. DebugMsg((DM_WARNING, TEXT("CreateUserProfile: SetupNewHive failed.")));
  2105. dwError = GetLastError();
  2106. MyRegUnLoadKey(HKEY_USERS, lpSidString);
  2107. DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
  2108. RtlFreeUnicodeString(&UnicodeString);
  2109. SetLastError(dwError);
  2110. return FALSE;
  2111. }
  2112. //
  2113. // Unload the hive
  2114. //
  2115. MyRegUnLoadKey(HKEY_USERS, lpSidString);
  2116. //
  2117. // Free the sid string
  2118. //
  2119. RtlFreeUnicodeString(&UnicodeString);
  2120. //
  2121. // Save the profile path if appropriate
  2122. //
  2123. if (lpProfileDir) {
  2124. if ((DWORD)lstrlen(szExpProfileDir) < dwDirSize) {
  2125. StringCchCopy (lpProfileDir, dwDirSize, szExpProfileDir);
  2126. }
  2127. }
  2128. //
  2129. // Success
  2130. //
  2131. DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Leaving successfully.")));
  2132. return TRUE;
  2133. }
  2134. //*************************************************************************
  2135. //
  2136. // SecureUserProfiles()
  2137. //
  2138. // Description : This function secures user profiles during FAT->NTFS conversion.
  2139. // It will also get called during upgrade in order to secure the
  2140. // profile area where the user has converted the file system before
  2141. // the upgrade.
  2142. //
  2143. // Arguments : None.
  2144. //
  2145. // Return Value: None.
  2146. //
  2147. // History: Date Author Comment
  2148. // 8/8/00 santanuc Created
  2149. // 09/25/2002 mingzhu Added SecureCommonProfiles()
  2150. //
  2151. //*************************************************************************
  2152. void WINAPI SecureUserProfiles(void)
  2153. {
  2154. HRESULT hr = E_FAIL;
  2155. //
  2156. // Put all our work into the exception handler, so we don't corrupt setup
  2157. // and convert.
  2158. //
  2159. __try
  2160. {
  2161. //
  2162. // Secure the per user profile areas
  2163. //
  2164. hr = SecurePerUserProfiles();
  2165. if (FAILED(hr))
  2166. {
  2167. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: SecurePerUserProfiles failed, hr =%08X"), hr));
  2168. }
  2169. //
  2170. // Secure the common profile areas.
  2171. //
  2172. hr = SecureCommonProfiles();
  2173. if (FAILED(hr))
  2174. {
  2175. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: SecureCommonProfile failed, hr =%08X"), hr));
  2176. }
  2177. }
  2178. __except (EXCEPTION_EXECUTE_HANDLER)
  2179. {
  2180. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Exception %d!!!"), GetExceptionCode()));
  2181. }
  2182. }
  2183. //*************************************************************************
  2184. //
  2185. // SecurePerUserProfiles()
  2186. //
  2187. // Description : This function secure (reacl) the per-user profiles under
  2188. // profiles directory, it will loop for each entry in the
  2189. // profile list entry and reacl every profile with the ACL
  2190. // of Admin(F)System(F)ProfileOwner(F).
  2191. //
  2192. // Arguments : None.
  2193. //
  2194. // Return Value: HRESULT.
  2195. //
  2196. // History: Date Author Comment
  2197. // 8/8/00 santanuc Created
  2198. // 09/25/2002 mingzhu Seperated from SecureUserProfiles()
  2199. //
  2200. //*************************************************************************
  2201. HRESULT SecurePerUserProfiles()
  2202. {
  2203. SECURITY_DESCRIPTOR DirSd, FileSd;
  2204. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2205. PACL pDirAcl = NULL, pFileAcl = NULL;
  2206. PSID pSidOwner=NULL, pSidAdmin = NULL, pSidSystem = NULL;
  2207. DWORD cbAcl, aceIndex;
  2208. HKEY hKeyProfilesList, hKeyProfile = NULL;
  2209. TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
  2210. DWORD dwSIDNameSize, dwSize;
  2211. DWORD dwIndex;
  2212. LONG lResult;
  2213. FILETIME ft;
  2214. HRESULT hr;
  2215. //
  2216. // Get the system sid
  2217. //
  2218. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  2219. 0, 0, 0, 0, 0, 0, 0, &pSidSystem)) {
  2220. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize system sid. Error = %d"), GetLastError()));
  2221. goto Exit;
  2222. }
  2223. //
  2224. // Get the Admin sid
  2225. //
  2226. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2227. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2228. 0, 0, 0, 0, &pSidAdmin)) {
  2229. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
  2230. goto Exit;
  2231. }
  2232. //
  2233. // Open the ProfileList key
  2234. //
  2235. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  2236. PROFILE_LIST_PATH,
  2237. 0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
  2238. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to open ProfileList key")));
  2239. goto Exit;
  2240. }
  2241. //
  2242. // Enumerate the profiles
  2243. //
  2244. dwIndex = 0;
  2245. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2246. lResult = RegEnumKeyEx(hKeyProfilesList,
  2247. dwIndex,
  2248. szSIDName,
  2249. &dwSIDNameSize,
  2250. NULL, NULL, NULL, &ft);
  2251. while (lResult == ERROR_SUCCESS) {
  2252. if (RegOpenKeyEx (hKeyProfilesList,
  2253. szSIDName,
  2254. 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  2255. dwSize = sizeof(szProfilePath);
  2256. if (RegQueryValueEx (hKeyProfile,
  2257. PROFILE_IMAGE_VALUE_NAME,
  2258. NULL, NULL,
  2259. (LPBYTE) szProfilePath,
  2260. &dwSize) != ERROR_SUCCESS) {
  2261. goto NextProfile;
  2262. }
  2263. //
  2264. // Expand the profile image filename
  2265. //
  2266. if (FAILED(SafeExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH)))
  2267. {
  2268. goto IssueError;
  2269. }
  2270. //
  2271. // Create the acl for the user profile dir
  2272. //
  2273. //
  2274. // Get the owner sid
  2275. //
  2276. if (AllocateAndInitSidFromString(szSIDName, &pSidOwner) != STATUS_SUCCESS) {
  2277. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to create owner sid."), GetLastError()));
  2278. goto IssueError;
  2279. }
  2280. //
  2281. // Allocate space for the Dir object ACL
  2282. //
  2283. cbAcl = (2 * GetLengthSid (pSidOwner)) +
  2284. (2 * GetLengthSid (pSidSystem)) +
  2285. (2 * GetLengthSid (pSidAdmin)) +
  2286. sizeof(ACL) +
  2287. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2288. pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2289. if (!pDirAcl) {
  2290. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2291. goto IssueError;
  2292. }
  2293. if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
  2294. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
  2295. goto IssueError;
  2296. }
  2297. //
  2298. // Allocate space for File object ACL
  2299. //
  2300. cbAcl = (GetLengthSid (pSidOwner)) +
  2301. (GetLengthSid (pSidSystem)) +
  2302. (GetLengthSid (pSidAdmin)) +
  2303. sizeof(ACL) +
  2304. (3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2305. pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2306. if (!pFileAcl) {
  2307. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2308. goto IssueError;
  2309. }
  2310. if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
  2311. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
  2312. goto IssueError;
  2313. }
  2314. //
  2315. // Add Aces. Non-inheritable ACEs first
  2316. //
  2317. aceIndex = 0;
  2318. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
  2319. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  2320. goto IssueError;
  2321. }
  2322. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
  2323. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  2324. goto IssueError;
  2325. }
  2326. aceIndex++;
  2327. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2328. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  2329. goto IssueError;
  2330. }
  2331. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2332. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  2333. goto IssueError;
  2334. }
  2335. aceIndex++;
  2336. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2337. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2338. goto IssueError;
  2339. }
  2340. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2341. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2342. goto IssueError;
  2343. }
  2344. //
  2345. // Now the Inheritable Aces.
  2346. //
  2347. aceIndex++;
  2348. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidOwner)) {
  2349. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
  2350. goto IssueError;
  2351. }
  2352. aceIndex++;
  2353. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
  2354. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
  2355. goto IssueError;
  2356. }
  2357. aceIndex++;
  2358. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
  2359. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2360. goto IssueError;
  2361. }
  2362. //
  2363. // Put together the security descriptor
  2364. //
  2365. if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
  2366. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2367. goto IssueError;
  2368. }
  2369. if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
  2370. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2371. goto IssueError;
  2372. }
  2373. if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
  2374. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2375. goto IssueError;
  2376. }
  2377. if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
  2378. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2379. goto IssueError;
  2380. }
  2381. //
  2382. // Pass the profile path to SecureProfile for securing
  2383. // the profile dir and nested subdirs and files.
  2384. //
  2385. if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
  2386. goto IssueError;
  2387. }
  2388. goto NextProfile;
  2389. IssueError:
  2390. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to secure %s Profile directory"), szExpandedProfilePath));
  2391. }
  2392. NextProfile:
  2393. // Free the allocated stuffs
  2394. if (hKeyProfile) {
  2395. RegCloseKey(hKeyProfile);
  2396. hKeyProfile = NULL;
  2397. }
  2398. if (pSidOwner) {
  2399. LocalFree(pSidOwner);
  2400. pSidOwner = NULL;
  2401. }
  2402. if (pDirAcl) {
  2403. GlobalFree (pDirAcl);
  2404. pDirAcl = NULL;
  2405. }
  2406. if (pFileAcl) {
  2407. GlobalFree (pFileAcl);
  2408. pFileAcl = NULL;
  2409. }
  2410. //
  2411. // Reset for the next loop
  2412. //
  2413. dwIndex++;
  2414. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2415. lResult = RegEnumKeyEx(hKeyProfilesList,
  2416. dwIndex,
  2417. szSIDName,
  2418. &dwSIDNameSize,
  2419. NULL, NULL, NULL, &ft);
  2420. }
  2421. RegCloseKey(hKeyProfilesList);
  2422. Exit:
  2423. if (pSidSystem) {
  2424. FreeSid(pSidSystem);
  2425. }
  2426. if (pSidAdmin) {
  2427. FreeSid(pSidAdmin);
  2428. }
  2429. return S_OK;
  2430. }
  2431. //*************************************************************************
  2432. //
  2433. // HideSpecialProfiles()
  2434. //
  2435. // Routine Description :
  2436. // This function secures special profiles for which PI_HIDEPROFILE
  2437. // flag is specifed, e.g. LocalService, NetworkService etc. except
  2438. // system account profile. This mark the profile dir as super hidden.
  2439. //
  2440. // Arguments :
  2441. // None.
  2442. //
  2443. // Return Value :
  2444. // None.
  2445. //
  2446. // History: Date Author Comment
  2447. // 8/8/00 santanuc Created
  2448. //
  2449. //*************************************************************************
  2450. void HideSpecialProfiles(void)
  2451. {
  2452. HKEY hKeyProfilesList, hKeyProfile = NULL;
  2453. TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
  2454. DWORD dwSIDNameSize, dwSize;
  2455. DWORD dwIndex, dwFlags;
  2456. LONG lResult;
  2457. FILETIME ft;
  2458. HRESULT hr;
  2459. //
  2460. // Open the ProfileList key
  2461. //
  2462. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  2463. PROFILE_LIST_PATH,
  2464. 0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
  2465. DebugMsg((DM_WARNING, TEXT("HideSpecialProfiles: Failed to open ProfileList key")));
  2466. return;
  2467. }
  2468. //
  2469. // Enumerate the profiles
  2470. //
  2471. dwIndex = 0;
  2472. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2473. lResult = RegEnumKeyEx(hKeyProfilesList,
  2474. dwIndex,
  2475. szSIDName,
  2476. &dwSIDNameSize,
  2477. NULL, NULL, NULL, &ft);
  2478. while (lResult == ERROR_SUCCESS) {
  2479. if (RegOpenKeyEx (hKeyProfilesList,
  2480. szSIDName,
  2481. 0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
  2482. //
  2483. // Process only if PI_HIDEPROFILE flag is set
  2484. //
  2485. dwSize = sizeof(DWORD);
  2486. if (RegQueryValueEx (hKeyProfile,
  2487. PROFILE_FLAGS,
  2488. NULL, NULL,
  2489. (LPBYTE) &dwFlags,
  2490. &dwSize) != ERROR_SUCCESS) {
  2491. goto NextProfile;
  2492. }
  2493. if (!(dwFlags & PI_HIDEPROFILE)) {
  2494. goto NextProfile;
  2495. }
  2496. dwSize = sizeof(szProfilePath);
  2497. if (RegQueryValueEx (hKeyProfile,
  2498. PROFILE_IMAGE_VALUE_NAME,
  2499. NULL, NULL,
  2500. (LPBYTE) szProfilePath,
  2501. &dwSize) != ERROR_SUCCESS) {
  2502. goto NextProfile;
  2503. }
  2504. // Ignore profile for system account
  2505. if (lstrcmp(szProfilePath, SYSTEM_PROFILE_LOCATION) == 0) {
  2506. goto NextProfile;
  2507. }
  2508. //
  2509. // Expand the profile image filename
  2510. //
  2511. hr = SafeExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH);
  2512. if (FAILED(hr))
  2513. {
  2514. goto NextProfile;
  2515. }
  2516. // Mark the profile hidden
  2517. SetFileAttributes(szExpandedProfilePath,
  2518. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
  2519. GetFileAttributes(szExpandedProfilePath));
  2520. }
  2521. NextProfile:
  2522. // Free the allocated stuffs
  2523. if (hKeyProfile) {
  2524. RegCloseKey(hKeyProfile);
  2525. hKeyProfile = NULL;
  2526. }
  2527. //
  2528. // Reset for the next loop
  2529. //
  2530. dwIndex++;
  2531. dwSIDNameSize = ARRAYSIZE(szSIDName);
  2532. lResult = RegEnumKeyEx(hKeyProfilesList,
  2533. dwIndex,
  2534. szSIDName,
  2535. &dwSIDNameSize,
  2536. NULL, NULL, NULL, &ft);
  2537. }
  2538. RegCloseKey(hKeyProfilesList);
  2539. }
  2540. //*************************************************************
  2541. //
  2542. // CopySystemProfile()
  2543. //
  2544. // Purpose: Create the system profile information under
  2545. // ProfileList entry.
  2546. // In case of upgrade copy system profile from older
  2547. // location to new location and delete the old system
  2548. // profile
  2549. //
  2550. // Parameters:
  2551. //
  2552. // Return: TRUE if successful
  2553. // FALSE if an error occurs. Call GetLastError()
  2554. //
  2555. // Comments: This should only be called by GUI mode setup!
  2556. //
  2557. // History: Date Author Comment
  2558. // 03/13/01 santanuc Created
  2559. //
  2560. //*************************************************************
  2561. BOOL WINAPI CopySystemProfile(BOOL bCleanInstall)
  2562. {
  2563. HANDLE hToken = NULL;
  2564. LPTSTR SidString = NULL, lpEnd;
  2565. TCHAR szLocalProfileKey[MAX_PATH], szBuffer[MAX_PATH];
  2566. TCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
  2567. LONG lResult;
  2568. HKEY hKey = NULL, hKeyShellFolders;
  2569. DWORD dwFlags, dwInternalFlags, dwRefCount;
  2570. DWORD dwDisp, dwSize, dwType, i;
  2571. BOOL bCopySystemProfile = TRUE, bCopyFromDefault = TRUE;
  2572. PSID pSystemSid = NULL;
  2573. DWORD dwErr = ERROR_SUCCESS;
  2574. HRESULT hr;
  2575. UINT cchEnd;
  2576. //
  2577. // Set the Profile information for system account i.e sid s-1-5-18
  2578. //
  2579. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
  2580. TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) {
  2581. dwErr = GetLastError();
  2582. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to open system token. Error %d"), dwErr));
  2583. goto Exit;
  2584. }
  2585. //
  2586. // Get the Sid string
  2587. //
  2588. SidString = GetSidString(hToken);
  2589. if (!SidString) {
  2590. dwErr = ERROR_ACCESS_DENIED;
  2591. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid string for system account")));
  2592. goto Exit;
  2593. }
  2594. pSystemSid = GetUserSid(hToken);
  2595. if (!pSystemSid) {
  2596. dwErr = ERROR_ACCESS_DENIED;
  2597. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid for system account")));
  2598. goto Exit;
  2599. }
  2600. //
  2601. // Open the profile mapping
  2602. //
  2603. GetProfileListKeyName(szLocalProfileKey, ARRAYSIZE(szLocalProfileKey), SidString);
  2604. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szLocalProfileKey, 0, 0, 0,
  2605. KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
  2606. if (lResult != ERROR_SUCCESS) {
  2607. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to open profile mapping key. Error %d"), lResult));
  2608. dwErr = lResult;
  2609. goto Exit;
  2610. }
  2611. //
  2612. // Save the flags
  2613. //
  2614. dwFlags = PI_LITELOAD | PI_HIDEPROFILE;
  2615. lResult = RegSetValueEx (hKey,
  2616. PROFILE_FLAGS,
  2617. 0,
  2618. REG_DWORD,
  2619. (LPBYTE) &dwFlags,
  2620. sizeof(DWORD));
  2621. if (lResult != ERROR_SUCCESS) {
  2622. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile flags. Error %d"), lResult));
  2623. }
  2624. //
  2625. // Save the internal flags
  2626. //
  2627. dwInternalFlags = 0;
  2628. lResult = RegSetValueEx (hKey,
  2629. PROFILE_STATE,
  2630. 0,
  2631. REG_DWORD,
  2632. (LPBYTE) &dwInternalFlags,
  2633. sizeof(DWORD));
  2634. if (lResult != ERROR_SUCCESS) {
  2635. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save internal flags. Error %d"), lResult));
  2636. }
  2637. //
  2638. // Save the ref count
  2639. //
  2640. dwRefCount = 1;
  2641. lResult = RegSetValueEx (hKey,
  2642. PROFILE_REF_COUNT,
  2643. 0,
  2644. REG_DWORD,
  2645. (LPBYTE) &dwRefCount,
  2646. sizeof(DWORD));
  2647. if (lResult != ERROR_SUCCESS) {
  2648. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile ref count. Error %d"), lResult));
  2649. }
  2650. //
  2651. // Save the sid
  2652. //
  2653. lResult = RegSetValueEx (hKey,
  2654. TEXT("Sid"),
  2655. 0,
  2656. REG_BINARY,
  2657. (LPBYTE) pSystemSid,
  2658. RtlLengthSid(pSystemSid));
  2659. if (lResult != ERROR_SUCCESS) {
  2660. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile system sid. Error %d"), lResult));
  2661. }
  2662. //
  2663. // Figure out whether any existing system profile exist or not
  2664. // in upgrade scenario
  2665. //
  2666. StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), SYSTEM_PROFILE_LOCATION);
  2667. hr = SafeExpandEnvironmentStrings(szBuffer, szDest, MAX_PATH);
  2668. if (FAILED(hr))
  2669. {
  2670. dwErr = HRESULT_CODE(hr);
  2671. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to expand env string. Error %d"), dwErr));
  2672. goto Exit;
  2673. }
  2674. if (!bCleanInstall) {
  2675. dwSize = ARRAYSIZE(szBuffer) * sizeof(TCHAR);
  2676. lResult = RegQueryValueEx(hKey,
  2677. PROFILE_IMAGE_VALUE_NAME,
  2678. NULL,
  2679. &dwType,
  2680. (LPBYTE) szBuffer,
  2681. &dwSize);
  2682. if (ERROR_SUCCESS == lResult) {
  2683. if (lstrcmp(szBuffer, SYSTEM_PROFILE_LOCATION) == 0) {
  2684. bCopySystemProfile = FALSE;
  2685. }
  2686. else {
  2687. hr = SafeExpandEnvironmentStrings(szBuffer, szSrc, MAX_PATH);
  2688. if (FAILED(hr))
  2689. {
  2690. dwErr = HRESULT_CODE(hr);
  2691. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to expand env string. Error %d"), dwErr));
  2692. goto Exit;
  2693. }
  2694. bCopyFromDefault = FALSE;
  2695. }
  2696. }
  2697. }
  2698. if (bCopySystemProfile) {
  2699. if (!CreateSecureDirectory(NULL, szDest, pSystemSid, FALSE)) {
  2700. dwErr = GetLastError();
  2701. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to create SystemProfile dir. Error %d"), dwErr));
  2702. goto Exit;
  2703. }
  2704. if (bCopyFromDefault) {
  2705. dwSize = ARRAYSIZE(szSrc);
  2706. if (!GetDefaultUserProfileDirectoryEx(szSrc, &dwSize, TRUE)) {
  2707. dwErr = GetLastError();
  2708. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get default user profile. Error %d"), dwErr));
  2709. goto Exit;
  2710. }
  2711. }
  2712. //
  2713. // Copy the existing or Default user profile in System profile location
  2714. //
  2715. if (!CopyProfileDirectoryEx(szSrc, szDest, CPD_IGNOREHIVE | CPD_FORCECOPY | CPD_IGNORECOPYERRORS,
  2716. NULL, NULL)) {
  2717. dwErr = GetLastError();
  2718. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to copy system profile. Error %d"), dwErr));
  2719. goto Exit;
  2720. }
  2721. if (!bCopyFromDefault) {
  2722. Delnode(szSrc);
  2723. }
  2724. }
  2725. SetAclForSystemProfile(pSystemSid, szDest);
  2726. //
  2727. // Save local profile path
  2728. //
  2729. StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), SYSTEM_PROFILE_LOCATION);
  2730. lResult = RegSetValueEx (hKey,
  2731. PROFILE_IMAGE_VALUE_NAME,
  2732. 0,
  2733. REG_EXPAND_SZ,
  2734. (LPBYTE) szBuffer,
  2735. ((lstrlen(szBuffer) + 1) * sizeof(TCHAR)));
  2736. if (lResult != ERROR_SUCCESS) {
  2737. dwErr = lResult;
  2738. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile image path with error %d"), lResult));
  2739. goto Exit;
  2740. }
  2741. //
  2742. // Set the Shell Folder paths in the registry for system account
  2743. //
  2744. hr = AppendName(szBuffer, ARRAYSIZE(szBuffer), TEXT(".Default"), SHELL_FOLDERS, NULL, NULL);
  2745. lpEnd = CheckSlashEx (szDest, ARRAYSIZE(szDest), &cchEnd);
  2746. if (!lpEnd)
  2747. {
  2748. dwErr = ERROR_BAD_PATHNAME;
  2749. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: CheckSlashEx failed.")));
  2750. goto Exit;
  2751. }
  2752. if (RegCreateKeyEx (HKEY_USERS, szBuffer,
  2753. 0, NULL, REG_OPTION_NON_VOLATILE,
  2754. KEY_READ | KEY_WRITE, NULL, &hKeyShellFolders,
  2755. &dwDisp) == ERROR_SUCCESS) {
  2756. for (i=0; i < g_dwNumShellFolders; i++) {
  2757. if (c_ShellFolders[i].bAddCSIDL) {
  2758. hr = StringCchCopy(lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
  2759. if (FAILED(hr))
  2760. {
  2761. dwErr = HRESULT_CODE(hr);
  2762. DebugMsg((DM_WARNING, TEXT("CopySystemProfile: failed to copy %s."), c_ShellFolders[i].szFolderLocation));
  2763. goto Exit;
  2764. }
  2765. RegSetValueEx (hKeyShellFolders, c_ShellFolders[i].lpFolderName,
  2766. 0, REG_SZ, (LPBYTE) szDest,
  2767. ((lstrlen(szDest) + 1) * sizeof(TCHAR)));
  2768. }
  2769. }
  2770. RegCloseKey (hKeyShellFolders);
  2771. }
  2772. Exit:
  2773. if (hToken) {
  2774. CloseHandle(hToken);
  2775. }
  2776. if (SidString) {
  2777. DeleteSidString(SidString);
  2778. }
  2779. if (pSystemSid) {
  2780. DeleteUserSid(pSystemSid);
  2781. }
  2782. if (hKey) {
  2783. RegCloseKey (hKey);
  2784. }
  2785. SetLastError(dwErr);
  2786. return(dwErr == ERROR_SUCCESS ? TRUE : FALSE);
  2787. }
  2788. //*************************************************************************
  2789. //
  2790. // SetAclForSystemProfile()
  2791. //
  2792. // Routine Description :
  2793. // This function secures dir/files of system profile i.e.
  2794. // %windir%\system32\config\systemprofile
  2795. //
  2796. // Arguments :
  2797. // pSidSystem - System sid
  2798. // szExpandedProfilePath - Expanded system profile location
  2799. //
  2800. // Return Value :
  2801. // None.
  2802. //
  2803. // History: Date Author Comment
  2804. // 04/06/01 santanuc Created
  2805. //
  2806. //*************************************************************************
  2807. void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath)
  2808. {
  2809. SECURITY_DESCRIPTOR DirSd, FileSd;
  2810. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  2811. PACL pDirAcl = NULL, pFileAcl = NULL;
  2812. PSID pSidAdmin = NULL;
  2813. DWORD cbAcl, aceIndex;
  2814. //
  2815. // Get the Admin sid
  2816. //
  2817. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  2818. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  2819. 0, 0, 0, 0, &pSidAdmin)) {
  2820. DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
  2821. goto Exit;
  2822. }
  2823. //
  2824. // Allocate space for the Dir object ACL
  2825. //
  2826. cbAcl = (2 * GetLengthSid (pSidSystem)) +
  2827. (2 * GetLengthSid (pSidAdmin)) +
  2828. sizeof(ACL) +
  2829. (4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2830. pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2831. if (!pDirAcl) {
  2832. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2833. goto Exit;
  2834. }
  2835. if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
  2836. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
  2837. goto Exit;
  2838. }
  2839. //
  2840. // Allocate space for File object ACL
  2841. //
  2842. cbAcl = (GetLengthSid (pSidSystem)) +
  2843. (GetLengthSid (pSidAdmin)) +
  2844. sizeof(ACL) +
  2845. (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  2846. pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  2847. if (!pFileAcl) {
  2848. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  2849. goto Exit;
  2850. }
  2851. if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
  2852. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
  2853. goto Exit;
  2854. }
  2855. //
  2856. // Add Aces. Non-inheritable ACEs first
  2857. //
  2858. aceIndex = 0;
  2859. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2860. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2861. goto Exit;
  2862. }
  2863. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
  2864. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2865. goto Exit;
  2866. }
  2867. aceIndex++;
  2868. if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2869. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2870. goto Exit;
  2871. }
  2872. if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
  2873. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2874. goto Exit;
  2875. }
  2876. //
  2877. // Now the Inheritable Aces.
  2878. //
  2879. aceIndex++;
  2880. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
  2881. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
  2882. goto Exit;
  2883. }
  2884. aceIndex++;
  2885. if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
  2886. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  2887. goto Exit;
  2888. }
  2889. //
  2890. // Put together the security descriptor
  2891. //
  2892. if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
  2893. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2894. goto Exit;
  2895. }
  2896. if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
  2897. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2898. goto Exit;
  2899. }
  2900. if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
  2901. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  2902. goto Exit;
  2903. }
  2904. if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
  2905. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
  2906. goto Exit;
  2907. }
  2908. //
  2909. // Pass the profile path to SecureProfile for securing
  2910. // the profile dir and nested subdirs and files.
  2911. //
  2912. if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
  2913. DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to secure %s Profile directory"), szExpandedProfilePath));
  2914. }
  2915. Exit:
  2916. if (pDirAcl) {
  2917. GlobalFree (pDirAcl);
  2918. pDirAcl = NULL;
  2919. }
  2920. if (pFileAcl) {
  2921. GlobalFree (pFileAcl);
  2922. pFileAcl = NULL;
  2923. }
  2924. if (pSidAdmin) {
  2925. FreeSid(pSidAdmin);
  2926. }
  2927. }
  2928. //*************************************************************************
  2929. //
  2930. // ReaclProfileListEntries()
  2931. //
  2932. // Routine Description :
  2933. //
  2934. // This function reset the entries in ProfileList key's security to
  2935. // their parent, which is not writable for user, and add a new subkey
  2936. // named "Reference" to save user reference. By doing this, we can
  2937. // prevent the user from changing their other profile related values.
  2938. //
  2939. // Arguments :
  2940. //
  2941. // Return Value : S_OK for success, else for failure
  2942. //
  2943. // History: Date Author Comment
  2944. // 04/19/2002 mingzhu Created
  2945. //
  2946. //*************************************************************************
  2947. HRESULT ReaclProfileListEntries()
  2948. {
  2949. HRESULT hr = E_FAIL;
  2950. LONG lResult;
  2951. DWORD dwResult;
  2952. HKEY hkeyProfileList = NULL;
  2953. PSECURITY_DESCRIPTOR psdProfileList = NULL;
  2954. PACL paclProfileList = NULL;
  2955. SECURITY_DESCRIPTOR sdEntry;
  2956. DWORD dwIndex;
  2957. FILETIME ft;
  2958. TCHAR szEntryName[MAX_PATH];
  2959. HKEY hkeyEntry = NULL;
  2960. DWORD dwUserPreference;
  2961. DWORD dwSize;
  2962. HKEY hkeyPreference = NULL;
  2963. TCHAR szCentralProfile[MAX_PATH];
  2964. DWORD dwProfileState;
  2965. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : entering")));
  2966. //
  2967. // Check clean install, we don't need to do this for clean installed OS
  2968. //
  2969. if (g_bCleanInstall)
  2970. {
  2971. hr = S_OK;
  2972. goto Exit;
  2973. }
  2974. //
  2975. // Open ProfileList key
  2976. //
  2977. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2978. PROFILE_LIST_PATH,
  2979. 0,
  2980. KEY_READ,
  2981. &hkeyProfileList);
  2982. if (lResult != ERROR_SUCCESS)
  2983. {
  2984. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open ProfileList key, error = %d"), lResult));
  2985. hr = HRESULT_FROM_WIN32(lResult);
  2986. goto Exit;
  2987. }
  2988. //
  2989. // Get the DACL out of it
  2990. //
  2991. dwResult = GetSecurityInfo(hkeyProfileList,
  2992. SE_REGISTRY_KEY,
  2993. DACL_SECURITY_INFORMATION,
  2994. NULL,
  2995. NULL,
  2996. &paclProfileList,
  2997. NULL,
  2998. &psdProfileList);
  2999. if (dwResult != ERROR_SUCCESS)
  3000. {
  3001. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : GetSecurityInfo failed, error = %d"), dwResult));
  3002. hr = HRESULT_FROM_WIN32(dwResult);
  3003. goto Exit;
  3004. }
  3005. //
  3006. // Initialize the SD for sub entries in Profile List, it will have the same DACL as their parent
  3007. //
  3008. if (!InitializeSecurityDescriptor(&sdEntry, SECURITY_DESCRIPTOR_REVISION))
  3009. {
  3010. dwResult = GetLastError();
  3011. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : InitializeSecurityDescriptor failed, error = %d"), dwResult));
  3012. hr = HRESULT_FROM_WIN32(dwResult);
  3013. goto Exit;
  3014. }
  3015. //
  3016. // Set the Dacl with default to TRUE
  3017. //
  3018. if (!SetSecurityDescriptorDacl(&sdEntry, TRUE, paclProfileList, TRUE))
  3019. {
  3020. dwResult = GetLastError();
  3021. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : SetSecurityDescriptorDacl failed, error = %d"), dwResult));
  3022. hr = HRESULT_FROM_WIN32(dwResult);
  3023. goto Exit;
  3024. }
  3025. //
  3026. // Enumerate each subkey entry, for each entry :
  3027. //
  3028. // 1. Set the DACLs
  3029. // 2. For roaming users, create the "Preference" subkey, set Dacls on that to give user write permission
  3030. // 3. Set the user preference value to the new location if it exists
  3031. //
  3032. for (dwIndex = 0; ;dwIndex++)
  3033. {
  3034. //
  3035. // Enumerate subkey
  3036. //
  3037. dwSize = ARRAYSIZE(szEntryName);
  3038. lResult = RegEnumKeyEx(hkeyProfileList,
  3039. dwIndex,
  3040. szEntryName,
  3041. &dwSize,
  3042. NULL,
  3043. NULL,
  3044. NULL,
  3045. &ft);
  3046. if (lResult != ERROR_SUCCESS)
  3047. break;
  3048. //
  3049. // Open it
  3050. //
  3051. lResult = RegOpenKeyEx(hkeyProfileList,
  3052. szEntryName,
  3053. 0,
  3054. KEY_ALL_ACCESS,
  3055. &hkeyEntry);
  3056. if (lResult != ERROR_SUCCESS)
  3057. {
  3058. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open <%s>, error = %d"), szEntryName, lResult));
  3059. goto Next;
  3060. }
  3061. //
  3062. // Set the SD to it,
  3063. //
  3064. lResult = RegSetKeySecurity(hkeyEntry, DACL_SECURITY_INFORMATION, &sdEntry);
  3065. if (lResult != ERROR_SUCCESS)
  3066. {
  3067. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : RegSetKeySecurity failed for <%s>, error = %d"), szEntryName, lResult));
  3068. goto Next;
  3069. }
  3070. //
  3071. // Read the "CentralProfile" value, if it is empty, this is a local user
  3072. //
  3073. szCentralProfile[0] = TEXT('\0');
  3074. dwSize = sizeof(szCentralProfile);
  3075. lResult = RegQueryValueEx(hkeyEntry,
  3076. PROFILE_CENTRAL_PROFILE,
  3077. NULL,
  3078. NULL,
  3079. (LPBYTE) szCentralProfile,
  3080. &dwSize);
  3081. if (lResult != ERROR_SUCCESS)
  3082. {
  3083. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Cannot get central profile for <%s>, user is not roaming."), szEntryName));
  3084. goto Next;
  3085. }
  3086. szCentralProfile[MAX_PATH - 1] = TEXT('\0');
  3087. if (lstrlen(szCentralProfile) == 0)
  3088. {
  3089. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Central profile is empty for <%s>, user is not roaming."), szEntryName));
  3090. goto Next;
  3091. }
  3092. //
  3093. // We got a central profile for the user, check if it belongs to a mandatory/readonly user
  3094. //
  3095. dwSize = sizeof(dwProfileState);
  3096. lResult = RegQueryValueEx(hkeyEntry,
  3097. PROFILE_STATE,
  3098. NULL,
  3099. NULL,
  3100. (LPBYTE) &dwProfileState,
  3101. &dwSize);
  3102. if (lResult != ERROR_SUCCESS)
  3103. {
  3104. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Cannot get profile state for <%s>, not setting the Preference key."), szEntryName));
  3105. goto Next;
  3106. }
  3107. if (dwProfileState & PROFILE_MANDATORY)
  3108. {
  3109. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : <%s>'s profile is mandatory or readonly, not setting the Preference key."), szEntryName));
  3110. goto Next;
  3111. }
  3112. //
  3113. // We got a roaming user here, create the "Prefrence" key, set the ACL on it.
  3114. //
  3115. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Central profile is <%s>, state is <%08X>, user is roaming."), szCentralProfile, dwProfileState));
  3116. hr = SetupPreferenceKey(szEntryName);
  3117. if (FAILED(hr))
  3118. {
  3119. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : SetupPrefrenceKey failed for <%s>, error = %d"), szEntryName, lResult));
  3120. goto Next;
  3121. }
  3122. //
  3123. // Try to see if we have user preference value already set in the entry
  3124. //
  3125. dwSize = sizeof(dwUserPreference);
  3126. lResult = RegQueryValueEx(hkeyEntry,
  3127. USER_PREFERENCE,
  3128. NULL,
  3129. NULL,
  3130. (LPBYTE) &dwUserPreference,
  3131. &dwSize);
  3132. if (lResult != ERROR_SUCCESS)
  3133. {
  3134. goto Next;
  3135. }
  3136. //
  3137. // We found an existing user preference value, set it to the new location
  3138. //
  3139. lResult = RegOpenKeyEx(hkeyEntry,
  3140. PREFERENCE_KEYNAME,
  3141. 0,
  3142. KEY_SET_VALUE,
  3143. &hkeyPreference);
  3144. if (lResult != ERROR_SUCCESS)
  3145. {
  3146. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open <%s> preference key, error = %d"), szEntryName, lResult));
  3147. goto Next;
  3148. }
  3149. lResult = RegSetValueEx(hkeyPreference,
  3150. USER_PREFERENCE,
  3151. 0,
  3152. REG_DWORD,
  3153. (CONST BYTE*) &dwUserPreference,
  3154. sizeof(dwUserPreference));
  3155. if (lResult != ERROR_SUCCESS)
  3156. {
  3157. DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to set <%s> preference value, error = %d"), szEntryName, lResult));
  3158. goto Next;
  3159. }
  3160. Next:
  3161. if (hkeyPreference)
  3162. {
  3163. RegCloseKey(hkeyPreference);
  3164. hkeyPreference = NULL;
  3165. }
  3166. if (hkeyEntry)
  3167. {
  3168. RegCloseKey(hkeyEntry);
  3169. hkeyEntry = NULL;
  3170. }
  3171. }
  3172. Exit:
  3173. if (hkeyProfileList)
  3174. RegCloseKey(hkeyProfileList);
  3175. if (psdProfileList)
  3176. LocalFree(psdProfileList);
  3177. DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : done!")));
  3178. return hr;
  3179. }
  3180. //*****************************************************************************
  3181. //
  3182. // CallFaxServiceAPI()
  3183. //
  3184. // Purpose: Call the SecureFaxServiceDirectories() API in fxsocm.dll to set
  3185. // the special DACLs on some folders under
  3186. // "All Users\Application Data" directory
  3187. //
  3188. // Parameters: None
  3189. //
  3190. // Return: HRESULT
  3191. //
  3192. // Comments:
  3193. //
  3194. // History: Date Author Comment
  3195. // 08/21/2002 mingzhu Created
  3196. //
  3197. //*****************************************************************************
  3198. HRESULT CallFaxServiceAPI()
  3199. {
  3200. HRESULT hr = E_FAIL;
  3201. TCHAR szDir[MAX_PATH];
  3202. HMODULE hFxsocm = NULL;
  3203. DWORD dwErr;
  3204. typedef HRESULT (WINAPI *PFN_FAXAPI)(LPCTSTR);
  3205. PFN_FAXAPI pfnFaxAPI = NULL;
  3206. TCHAR szCommonAppData[MAX_PATH];
  3207. DWORD dwSize;
  3208. LPTSTR lpEnd = NULL;
  3209. DWORD cchEnd;
  3210. TCHAR szTemp[64];
  3211. //
  3212. // Init the debugging
  3213. //
  3214. InitDebugSupport(0);
  3215. //
  3216. // Get the all user profile path
  3217. //
  3218. dwSize = ARRAYSIZE(szCommonAppData);
  3219. if (!GetAllUsersProfileDirectoryEx(szCommonAppData, &dwSize, TRUE))
  3220. {
  3221. dwErr = GetLastError();
  3222. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: GetAllUsersProfileDirectoryEx failed, error = %d"), dwErr));
  3223. hr = HRESULT_FROM_WIN32(dwErr);
  3224. goto Exit;
  3225. }
  3226. //
  3227. // Append the application data to the path
  3228. //
  3229. lpEnd = CheckSlashEx(szCommonAppData, ARRAYSIZE(szCommonAppData), &cchEnd);
  3230. if (!lpEnd)
  3231. {
  3232. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : CheckSlashEx failed!")));
  3233. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  3234. goto Exit;
  3235. }
  3236. if (!LoadString (g_hDllInstance, IDS_SH_APPDATA, szTemp, ARRAYSIZE(szTemp)))
  3237. {
  3238. dwErr = GetLastError();
  3239. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : LoadString failed, error = %d"), dwErr));
  3240. hr = HRESULT_FROM_WIN32(dwErr);
  3241. goto Exit;
  3242. }
  3243. hr = StringCchCopy (lpEnd, cchEnd, szTemp);
  3244. if (FAILED(hr))
  3245. {
  3246. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : StringCchCopy failed, hr = %08X"), hr));
  3247. goto Exit;
  3248. }
  3249. //
  3250. // Load the dll and call the API
  3251. //
  3252. hr = SafeExpandEnvironmentStrings(TEXT("%systemroot%\\system32\\setup\\fxsocm.dll"), szDir, ARRAYSIZE(szDir));
  3253. if (FAILED(hr))
  3254. {
  3255. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: SafeExpandEnvironmentStrings failed, hr = %08X"), hr));
  3256. goto Exit;
  3257. }
  3258. hFxsocm = LoadLibrary(szDir);
  3259. if (!hFxsocm)
  3260. {
  3261. dwErr = GetLastError();
  3262. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: LoadLibrary failed, error = %d"), dwErr));
  3263. hr = HRESULT_FROM_WIN32(dwErr);
  3264. goto Exit;
  3265. }
  3266. pfnFaxAPI = (PFN_FAXAPI) GetProcAddress(hFxsocm, "SecureFaxServiceDirectories");
  3267. if (!pfnFaxAPI)
  3268. {
  3269. dwErr = GetLastError();
  3270. DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: GetProcAddress failed, error = %d"), dwErr));
  3271. hr = HRESULT_FROM_WIN32(dwErr);
  3272. goto Exit;
  3273. }
  3274. hr = pfnFaxAPI(szCommonAppData);
  3275. Exit:
  3276. if (hFxsocm)
  3277. FreeLibrary(hFxsocm);
  3278. return hr;
  3279. }
  3280. //*****************************************************************************
  3281. //
  3282. // SecureCommonProfiles()
  3283. //
  3284. // Purpose: Set the DACLs for the all user's profile and default profile.
  3285. // It will be executed after the FAT->NTFS conversion. We will
  3286. // apply a security template to the all user's profile to ensure
  3287. // a proper DACL for the Windows components, other apps that set
  3288. // specific DACLs under All User's profile will remain everyone(F)
  3289. // since we have no idea what DACL should we set to.
  3290. //
  3291. // Parameters: None
  3292. //
  3293. // Return: HRESULT
  3294. //
  3295. // Comments:
  3296. //
  3297. // History: Date Author Comment
  3298. // 09/18/2002 mingzhu Created
  3299. //
  3300. //*****************************************************************************
  3301. //
  3302. // Required typedefs for the API we need to call, SceConfigSystem.
  3303. //
  3304. #include "secedit.h"
  3305. typedef SCESTATUS (WINAPI *PFN_SceConfigureSystem)
  3306. (
  3307. IN LPTSTR SystemName OPTIONAL,
  3308. IN PCWSTR InfFileName OPTIONAL,
  3309. IN PCWSTR DatabaseName,
  3310. IN PCWSTR LogFileName OPTIONAL,
  3311. IN DWORD ConfigOptions,
  3312. IN AREA_INFORMATION Area,
  3313. IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL,
  3314. IN HANDLE hCallbackWnd OPTIONAL,
  3315. OUT PDWORD pdWarning OPTIONAL
  3316. );
  3317. HRESULT SecureCommonProfiles()
  3318. {
  3319. HRESULT hr = E_FAIL;
  3320. HMODULE hSceCli = NULL;
  3321. DWORD dwErr;
  3322. SCESTATUS status;
  3323. TCHAR szWindows[64];
  3324. TCHAR szInfFile[MAX_PATH]; //TEXT("%SystemRoot%\\Inf\\ProfSec.Inf");
  3325. TCHAR szDatabase[MAX_PATH]; //TEXT("%SystemRoot%\\Security\\Database\\ProfSec.sdb");
  3326. TCHAR szLogFile[MAX_PATH]; //TEXT("%SystemRoot%\\Security\\Log\\ProfSec.log");
  3327. DWORD dwWarning;
  3328. DWORD dwOptions;
  3329. PFN_SceConfigureSystem pfn_SceConfigureSystem = NULL;
  3330. InitDebugSupport(0);
  3331. DebugMsg((DM_VERBOSE, TEXT("SecureCommonProfile: Entering...")));
  3332. //
  3333. // 1. First set a series environment variables that used in the inf file
  3334. //
  3335. PrepareEnvironmentVariables();
  3336. //
  3337. // 2. Load the security library and get the function
  3338. //
  3339. hSceCli = LoadLibrary(TEXT("SceCli.dll"));
  3340. if (!hSceCli)
  3341. {
  3342. dwErr = GetLastError();
  3343. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: LoadLibrary failed, error = %d"), dwErr));
  3344. hr = HRESULT_FROM_WIN32(dwErr);
  3345. goto Exit;
  3346. }
  3347. pfn_SceConfigureSystem = (PFN_SceConfigureSystem) GetProcAddress (hSceCli, "SceConfigureSystem");
  3348. if (!pfn_SceConfigureSystem)
  3349. {
  3350. dwErr = GetLastError();
  3351. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: GetProcAddress failed, error = %d"), dwErr));
  3352. hr = HRESULT_FROM_WIN32(dwErr);
  3353. goto Exit;
  3354. }
  3355. //
  3356. // 3. Get the windows directory
  3357. //
  3358. if (!GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows)))
  3359. {
  3360. dwErr = GetLastError();
  3361. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: GetWindowsDirectory failed, error = %d"), dwErr));
  3362. hr = HRESULT_FROM_WIN32(dwErr);
  3363. goto Exit;
  3364. }
  3365. //
  3366. // 4. Get the path for our INF file
  3367. //
  3368. hr = StringCchPrintf(szInfFile, ARRAYSIZE(szInfFile), TEXT("%s\\Inf\\ProfSec.Inf"), szWindows);
  3369. if (FAILED(hr))
  3370. {
  3371. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
  3372. goto Exit;
  3373. }
  3374. //
  3375. // 5. Get the path for the data base
  3376. //
  3377. hr = StringCchPrintf(szDatabase, ARRAYSIZE(szDatabase), TEXT("%s\\Security\\Database\\ProfSec.sdb"), szWindows);
  3378. if (FAILED(hr))
  3379. {
  3380. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
  3381. goto Exit;
  3382. }
  3383. //
  3384. // 6. Get the path for the log file
  3385. //
  3386. hr = StringCchPrintf(szLogFile, ARRAYSIZE(szLogFile), TEXT("%s\\Security\\Logs\\ProfSec.log"), szWindows);
  3387. if (FAILED(hr))
  3388. {
  3389. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
  3390. goto Exit;
  3391. }
  3392. //
  3393. // 7. Call the API
  3394. //
  3395. dwOptions = SCE_OVERWRITE_DB | SCE_VERBOSE_LOG;
  3396. status = pfn_SceConfigureSystem(NULL, // System Name
  3397. szInfFile, // InfFileName
  3398. szDatabase, // DatabaseName
  3399. szLogFile, // LogFileName
  3400. dwOptions, // Options
  3401. AREA_FILE_SECURITY, // Area information
  3402. NULL, // Area call back
  3403. NULL, // Call back window
  3404. &dwWarning); // Warning
  3405. if (status != SCESTATUS_SUCCESS)
  3406. {
  3407. DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: SceConfigureSystem failed, status = %d, warning = %d"), status, dwWarning));
  3408. hr = E_FAIL;
  3409. goto Exit;
  3410. }
  3411. //
  3412. // Success!
  3413. //
  3414. DebugMsg((DM_VERBOSE, TEXT("SecureCommonProfile: Success!")));
  3415. hr = S_OK;
  3416. Exit:
  3417. if (hSceCli)
  3418. FreeLibrary(hSceCli);
  3419. return hr;
  3420. }
  3421. //*****************************************************************************
  3422. //
  3423. // SetEnvFromResource()
  3424. //
  3425. // Purpose: Get the localized strings for subfolders of all user's profile
  3426. // and set it to the environment variable
  3427. //
  3428. // Parameters:
  3429. //
  3430. // Return: HRESULT
  3431. //
  3432. // Comments:
  3433. //
  3434. // History: Date Author Comment
  3435. // 09/18/2002 mingzhu Created
  3436. //
  3437. //*****************************************************************************
  3438. HRESULT SetEnvFromResource(DWORD dwResID, LPCTSTR szEnvVar, LPTSTR lpEnd, size_t cchEnd, LPTSTR szBuffer)
  3439. {
  3440. HRESULT hr = E_FAIL;
  3441. DWORD dwErr;
  3442. DWORD dwIndex;
  3443. for (dwIndex = 0; dwIndex < g_dwNumCommonShellFolders; dwIndex++)
  3444. {
  3445. if (c_CommonShellFolders[dwIndex].iFolderID == dwResID)
  3446. {
  3447. hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[dwIndex].szFolderLocation);
  3448. if (FAILED(hr))
  3449. {
  3450. DebugMsg((DM_WARNING, TEXT("SetEnvFromResource : StringCchCopy for %s failed, hr = %08X"), szEnvVar, hr));
  3451. goto Exit;
  3452. }
  3453. if (!SetEnvironmentVariable(szEnvVar, szBuffer))
  3454. {
  3455. dwErr = GetLastError();
  3456. DebugMsg((DM_WARNING, TEXT("SetEnvFromResource: SetEnvironmentVariable for %s failed, error = %d"), szEnvVar, dwErr));
  3457. hr = HRESULT_FROM_WIN32(dwErr);
  3458. goto Exit;
  3459. }
  3460. DebugMsg((DM_VERBOSE, TEXT("SetEnvFromResource: set %s = %s"), szEnvVar, szBuffer));
  3461. hr = S_OK;
  3462. goto Exit;
  3463. }
  3464. }
  3465. DebugMsg((DM_VERBOSE, TEXT("SetEnvFromResource: can't find folder name for %s"), szEnvVar));
  3466. hr = S_FALSE;
  3467. Exit:
  3468. return hr;
  3469. }
  3470. //*****************************************************************************
  3471. //
  3472. // PrepareEnvironmentVariables()
  3473. //
  3474. // Purpose: Prepare environment variables used by the profile security
  3475. // template file.
  3476. //
  3477. // Parameters: None
  3478. //
  3479. // Return: HRESULT
  3480. //
  3481. // Comments:
  3482. //
  3483. // History: Date Author Comment
  3484. // 09/18/2002 mingzhu Created
  3485. //
  3486. //*****************************************************************************
  3487. HRESULT PrepareEnvironmentVariables()
  3488. {
  3489. HRESULT hr = E_FAIL;
  3490. TCHAR szBuffer[MAX_PATH];
  3491. DWORD dwSize;
  3492. DWORD dwErr;
  3493. LPTSTR lpEnd;
  3494. UINT cchEnd;
  3495. TCHAR szTemp[MAX_PATH];
  3496. //
  3497. // Set the default user profile path
  3498. //
  3499. dwSize = ARRAYSIZE(szBuffer);
  3500. if (!GetDefaultUserProfileDirectoryEx(szBuffer, &dwSize, TRUE))
  3501. {
  3502. dwErr = GetLastError();
  3503. DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: GetDefaultUserProfileDirectoryEx failed, error = %d"), dwErr));
  3504. }
  3505. else
  3506. {
  3507. if (!SetEnvironmentVariable(TEXT("DEFAULTUSERPROFILE"), szBuffer))
  3508. {
  3509. dwErr = GetLastError();
  3510. DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: SetEnvironmentVariable for default user failed, error = %d"), dwErr));
  3511. }
  3512. }
  3513. //
  3514. // Set the all users profile path
  3515. //
  3516. dwSize = ARRAYSIZE(szBuffer);
  3517. if (!GetAllUsersProfileDirectoryEx(szBuffer, &dwSize, TRUE))
  3518. {
  3519. dwErr = GetLastError();
  3520. DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: GetAllUsersProfileDirectoryEx failed, error = %d"), dwErr));
  3521. }
  3522. else
  3523. {
  3524. if (!SetEnvironmentVariable(TEXT("ALLUSERSPROFILE"), szBuffer))
  3525. {
  3526. dwErr = GetLastError();
  3527. DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: SetEnvironmentVariable failed, error = %d"), dwErr));
  3528. }
  3529. else
  3530. {
  3531. //
  3532. // Set all the subfolders under all user's profile
  3533. //
  3534. lpEnd = CheckSlashEx(szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
  3535. if (!lpEnd)
  3536. {
  3537. DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables : CheckSlashEx failed!")));
  3538. }
  3539. else
  3540. {
  3541. SetEnvFromResource(IDS_SH_APPDATA, TEXT("COMMON_APPDATA"), lpEnd, cchEnd, szBuffer);
  3542. SetEnvFromResource(IDS_SH_DESKTOP, TEXT("COMMON_DESKTOP"), lpEnd, cchEnd, szBuffer);
  3543. SetEnvFromResource(IDS_SH_FAVORITES, TEXT("COMMON_FAVORITES"), lpEnd, cchEnd, szBuffer);
  3544. SetEnvFromResource(IDS_SH_STARTMENU, TEXT("COMMON_STARTMENU"), lpEnd, cchEnd, szBuffer);
  3545. SetEnvFromResource(IDS_SH_TEMPLATES, TEXT("COMMON_TEMPLATES"), lpEnd, cchEnd, szBuffer);
  3546. SetEnvFromResource(IDS_SH_SHAREDDOCS, TEXT("COMMON_DOCS"), lpEnd, cchEnd, szBuffer);
  3547. }
  3548. }
  3549. }
  3550. //
  3551. // Success!
  3552. //
  3553. hr = S_OK;
  3554. return hr;
  3555. }