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.

799 lines
20 KiB

  1. //*************************************************************
  2. // File name: profile.c
  3. //
  4. // Description: Fixes hard coded paths in the registry for
  5. // special folder locations. Also fixes security
  6. // on a few registry keys.
  7. //
  8. // Microsoft Confidential
  9. // Copyright (c) Microsoft Corporation 1996
  10. // All rights reserved
  11. //
  12. //*************************************************************
  13. #include <windows.h>
  14. #include <shlobj.h>
  15. #include <shlwapi.h>
  16. #include <tchar.h>
  17. #include "shmgdefs.h"
  18. #include "res.h"
  19. //*************************************************************
  20. //
  21. // ApplySecurityToRegistryTree()
  22. //
  23. // Purpose: Applies the passed security descriptor to the passed
  24. // key and all its descendants. Only the parts of
  25. // the descriptor inddicated in the security
  26. // info value are actually applied to each registry key.
  27. //
  28. // Parameters: RootKey - Registry key
  29. // pSD - Security Descriptor
  30. //
  31. // Return: ERROR_SUCCESS if successful
  32. //
  33. // Comments:
  34. //
  35. // History: Date Author Comment
  36. // 7/19/95 ericflo Created
  37. // 6/16/96 bobday Stolen directly from USERENV
  38. //
  39. //*************************************************************
  40. DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
  41. {
  42. DWORD Error;
  43. DWORD SubKeyIndex;
  44. LPTSTR SubKeyName;
  45. HKEY SubKey;
  46. DWORD cchSubKeySize = MAX_PATH + 1;
  47. //
  48. // First apply security
  49. //
  50. Error = RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
  51. if (Error != ERROR_SUCCESS) {
  52. return Error;
  53. }
  54. //
  55. // Open each sub-key and apply security to its sub-tree
  56. //
  57. SubKeyIndex = 0;
  58. SubKeyName = GlobalAlloc (GPTR, cchSubKeySize * sizeof(TCHAR));
  59. if (!SubKeyName) {
  60. return GetLastError();
  61. }
  62. while (TRUE) {
  63. //
  64. // Get the next sub-key name
  65. //
  66. Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
  67. if (Error != ERROR_SUCCESS) {
  68. if (Error == ERROR_NO_MORE_ITEMS) {
  69. //
  70. // Successful end of enumeration
  71. //
  72. Error = ERROR_SUCCESS;
  73. } else {
  74. }
  75. break;
  76. }
  77. //
  78. // Open the sub-key
  79. //
  80. Error = RegOpenKeyEx(RootKey,
  81. SubKeyName,
  82. 0,
  83. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  84. &SubKey);
  85. if (Error != ERROR_SUCCESS) {
  86. break;
  87. }
  88. //
  89. // Apply security to the sub-tree
  90. //
  91. Error = ApplySecurityToRegistryTree(SubKey, pSD);
  92. //
  93. // We're finished with the sub-key
  94. //
  95. RegCloseKey(SubKey);
  96. //
  97. // See if we set the security on the sub-tree successfully.
  98. //
  99. if (Error != ERROR_SUCCESS) {
  100. break;
  101. }
  102. //
  103. // Go enumerate the next sub-key
  104. //
  105. SubKeyIndex ++;
  106. }
  107. GlobalFree (SubKeyName);
  108. return Error;
  109. }
  110. //*************************************************************
  111. //
  112. // MakeKeyOrTreeSecure()
  113. //
  114. // Purpose: Sets the attributes on the registry key and possibly sub-keys
  115. // such that Administrators and the OS can delete it and Everyone
  116. // else has read permission only (OR general read/write access)
  117. //
  118. // Parameters: RootKey - Key to set security on
  119. // fWrite - Allow write (or just read)
  120. //
  121. // Return: (BOOL) TRUE if successful
  122. // FALSE if an error occurs
  123. //
  124. // Comments:
  125. //
  126. // History: Date Author Comment
  127. // 11/6/95 ericflo Created
  128. // 06/16/96 bobday Ported from MakeFileSecure in USERENV
  129. //
  130. //*************************************************************
  131. BOOL MakeKeyOrTreeSecure (HKEY RootKey, BOOL fWrite)
  132. {
  133. SECURITY_DESCRIPTOR sd;
  134. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  135. SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
  136. PACL pAcl = NULL;
  137. PSID psidSystem = NULL, psidAdmin = NULL, psidEveryone = NULL;
  138. DWORD cbAcl, aceIndex;
  139. ACE_HEADER * lpAceHeader;
  140. BOOL bRetVal = FALSE;
  141. DWORD Error;
  142. DWORD dwAccess;
  143. if (fWrite) {
  144. dwAccess = KEY_ALL_ACCESS;
  145. } else {
  146. dwAccess = KEY_READ;
  147. }
  148. //
  149. // Get the system sid
  150. //
  151. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  152. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  153. goto Exit;
  154. }
  155. //
  156. // Get the Admin sid
  157. //
  158. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  159. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  160. 0, 0, 0, 0, &psidAdmin)) {
  161. goto Exit;
  162. }
  163. //
  164. // Get the World sid
  165. //
  166. if (!AllocateAndInitializeSid(&authWorld, 1, SECURITY_WORLD_RID,
  167. 0, 0, 0, 0, 0, 0, 0, &psidEveryone)) {
  168. goto Exit;
  169. }
  170. //
  171. // Allocate space for the ACL
  172. //
  173. cbAcl = (3 * GetLengthSid (psidSystem)) +
  174. (3 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
  175. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  176. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  177. if (!pAcl) {
  178. goto Exit;
  179. }
  180. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  181. goto Exit;
  182. }
  183. //
  184. // Add Aces. Non-inheritable ACEs first
  185. //
  186. aceIndex = 0;
  187. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
  188. goto Exit;
  189. }
  190. aceIndex++;
  191. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
  192. goto Exit;
  193. }
  194. aceIndex++;
  195. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccess, psidEveryone)) {
  196. goto Exit;
  197. }
  198. //
  199. // Now the inheritable ACEs
  200. //
  201. if (fWrite) {
  202. dwAccess = GENERIC_ALL;
  203. } else {
  204. dwAccess = GENERIC_READ;
  205. }
  206. aceIndex++;
  207. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  208. goto Exit;
  209. }
  210. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  211. goto Exit;
  212. }
  213. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  214. aceIndex++;
  215. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  216. goto Exit;
  217. }
  218. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  219. goto Exit;
  220. }
  221. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  222. aceIndex++;
  223. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccess, psidEveryone)) {
  224. goto Exit;
  225. }
  226. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  227. goto Exit;
  228. }
  229. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  230. //
  231. // Put together the security descriptor
  232. //
  233. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  234. goto Exit;
  235. }
  236. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  237. goto Exit;
  238. }
  239. //
  240. // Set the security
  241. //
  242. Error = ApplySecurityToRegistryTree(RootKey, &sd);
  243. if (Error == ERROR_SUCCESS) {
  244. bRetVal = TRUE;
  245. }
  246. Exit:
  247. if (psidSystem) {
  248. FreeSid(psidSystem);
  249. }
  250. if (psidAdmin) {
  251. FreeSid(psidAdmin);
  252. }
  253. if (psidEveryone) {
  254. FreeSid(psidEveryone);
  255. }
  256. if (pAcl) {
  257. GlobalFree (pAcl);
  258. }
  259. return bRetVal;
  260. }
  261. void FixUserProfileSecurity( void )
  262. {
  263. HKEY hkeyPolicies;
  264. DWORD Error;
  265. Error = RegOpenKeyEx( HKEY_CURRENT_USER,
  266. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"),
  267. 0,
  268. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  269. &hkeyPolicies);
  270. if (Error == ERROR_SUCCESS)
  271. {
  272. MakeKeyOrTreeSecure(hkeyPolicies, FALSE);
  273. RegCloseKey(hkeyPolicies);
  274. }
  275. }
  276. void FixPoliciesSecurity( void )
  277. {
  278. HKEY hkeyPolicies;
  279. DWORD Error, dwDisp;
  280. Error = RegCreateKeyEx( HKEY_CURRENT_USER,
  281. TEXT("Software\\Policies"),
  282. 0,
  283. NULL,
  284. REG_OPTION_NON_VOLATILE,
  285. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  286. NULL,
  287. &hkeyPolicies,
  288. &dwDisp);
  289. if (Error == ERROR_SUCCESS)
  290. {
  291. MakeKeyOrTreeSecure(hkeyPolicies, FALSE);
  292. RegCloseKey(hkeyPolicies);
  293. }
  294. }
  295. void SetSystemBitOnCAPIDir(void)
  296. {
  297. HRESULT hr;
  298. TCHAR szPath[MAX_PATH];
  299. TCHAR szAppData[MAX_PATH];
  300. DWORD FileAttributes;
  301. if (S_OK == SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szAppData)){
  302. //
  303. // It is better to use tcscpy and tcscat. This is just a temp fix and it is build with
  304. // Unicode anyway. Not worth to include extra header file.
  305. // We do not check error case here. This is just a best effort. If we got error, so what?
  306. // MAX_PATH should be enough for these DIRs. Not worth to take care of \\?\ format.
  307. //
  308. if (SUCCEEDED(StringCchCopy(szPath, ARRAYSIZE(szPath), szAppData)) &&
  309. SUCCEEDED(StringCchCat(szPath, ARRAYSIZE(szPath), TEXT("\\Microsoft\\Protect"))))
  310. {
  311. FileAttributes = GetFileAttributes(szPath);
  312. if ((FileAttributes != -1) && ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) == 0)) {
  313. FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
  314. SetFileAttributes(szPath, FileAttributes);
  315. }
  316. }
  317. if (SUCCEEDED(StringCchCopy(szPath, ARRAYSIZE(szPath), szAppData)) &&
  318. SUCCEEDED(StringCchCat(szPath, ARRAYSIZE(szPath), TEXT("\\Microsoft\\Crypto"))))
  319. {
  320. FileAttributes = GetFileAttributes(szPath);
  321. if ((FileAttributes != -1) && ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) == 0)) {
  322. FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
  323. SetFileAttributes(szPath, FileAttributes);
  324. }
  325. }
  326. }
  327. }
  328. void SetScreensaverOnFriendlyUI()
  329. {
  330. if (IsOS(OS_FRIENDLYLOGONUI) &&
  331. IsOS(OS_FASTUSERSWITCHING))
  332. {
  333. HKEY hkey;
  334. if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_SET_VALUE, &hkey) == ERROR_SUCCESS)
  335. {
  336. TCHAR szTemp[MAX_PATH];
  337. DWORD cbTemp = sizeof(szTemp);
  338. RegSetValueEx(hkey, TEXT("ScreenSaveActive"), 0, REG_SZ, (BYTE*)TEXT("1"), sizeof(TEXT("1")));
  339. if (SHRegGetValue(hkey, NULL, TEXT("SCRNSAVE.EXE"), SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND, NULL, szTemp, &cbTemp) != ERROR_SUCCESS || szTemp[0] == TEXT('\0'))
  340. {
  341. // if the user dosen't already have a screensaver set, then choose one for them!
  342. if (ExpandEnvironmentStrings(TEXT("%SystemRoot%\\System32\\logon.scr"), szTemp, ARRAYSIZE(szTemp)))
  343. {
  344. RegSetValueEx(hkey, TEXT("SCRNSAVE.EXE"), 0, REG_SZ, (BYTE*)szTemp, (lstrlen(szTemp) + 1) * sizeof(TCHAR));
  345. }
  346. }
  347. RegCloseKey(hkey);
  348. }
  349. }
  350. }
  351. #define OTHERSIDS_EVERYONE 1
  352. #define OTHERSIDS_POWERUSERS 2
  353. BOOL MakeFileSecure (LPTSTR lpFile, DWORD dwOtherSids)
  354. {
  355. SECURITY_DESCRIPTOR sd;
  356. SECURITY_ATTRIBUTES sa;
  357. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  358. SID_IDENTIFIER_AUTHORITY authWORLD = SECURITY_WORLD_SID_AUTHORITY;
  359. PACL pAcl = NULL;
  360. PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL, psidPowerUsers = NULL;
  361. PSID psidEveryOne = NULL;
  362. DWORD cbAcl, aceIndex;
  363. ACE_HEADER * lpAceHeader;
  364. BOOL bRetVal = FALSE;
  365. BOOL bAddPowerUsersAce=TRUE;
  366. BOOL bAddEveryOneAce=FALSE;
  367. DWORD dwAccMask;
  368. //
  369. // Get the system sid
  370. //
  371. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  372. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  373. goto Exit;
  374. }
  375. //
  376. // Get the Admin sid
  377. //
  378. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  379. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  380. 0, 0, 0, 0, &psidAdmin)) {
  381. goto Exit;
  382. }
  383. //
  384. // Get the users sid
  385. //
  386. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  387. DOMAIN_ALIAS_RID_USERS,
  388. 0, 0, 0, 0, 0, 0, &psidUsers)) {
  389. goto Exit;
  390. }
  391. //
  392. // Allocate space for the ACL
  393. //
  394. cbAcl = (2 * GetLengthSid (psidSystem)) +
  395. (2 * GetLengthSid (psidAdmin)) +
  396. (2 * GetLengthSid (psidUsers)) +
  397. sizeof(ACL) +
  398. (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  399. //
  400. // Get the power users sid, if required.
  401. // Don't fail if you don't get because it might not be available on DCs??
  402. //
  403. bAddPowerUsersAce = TRUE;
  404. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  405. DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &psidPowerUsers)) {
  406. bAddPowerUsersAce = FALSE;
  407. }
  408. if (bAddPowerUsersAce)
  409. cbAcl += (2 * GetLengthSid (psidPowerUsers)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  410. //
  411. // Get the EveryOne sid, if required.
  412. //
  413. if (dwOtherSids & OTHERSIDS_EVERYONE) {
  414. bAddEveryOneAce = TRUE;
  415. if (!AllocateAndInitializeSid(&authWORLD, 1, SECURITY_WORLD_RID,
  416. 0, 0, 0, 0, 0, 0, 0, &psidEveryOne)) {
  417. goto Exit;
  418. }
  419. }
  420. if (bAddEveryOneAce)
  421. cbAcl += (2 * GetLengthSid (psidEveryOne)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  422. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  423. if (!pAcl) {
  424. goto Exit;
  425. }
  426. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  427. goto Exit;
  428. }
  429. //
  430. // Add Aces. Non-inheritable ACEs first
  431. //
  432. aceIndex = 0;
  433. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
  434. goto Exit;
  435. }
  436. aceIndex++;
  437. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
  438. goto Exit;
  439. }
  440. aceIndex++;
  441. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidUsers)) {
  442. goto Exit;
  443. }
  444. if (bAddPowerUsersAce) {
  445. //
  446. // By default give read permissions, otherwise give modify permissions
  447. //
  448. dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)):
  449. (GENERIC_READ | GENERIC_EXECUTE);
  450. aceIndex++;
  451. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*dwAccMask,*/ psidPowerUsers)) {
  452. goto Exit;
  453. }
  454. }
  455. if (bAddEveryOneAce) {
  456. aceIndex++;
  457. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidEveryOne)) {
  458. goto Exit;
  459. }
  460. }
  461. //
  462. // Now the inheritable ACEs
  463. //
  464. aceIndex++;
  465. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
  466. goto Exit;
  467. }
  468. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  469. goto Exit;
  470. }
  471. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  472. aceIndex++;
  473. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
  474. goto Exit;
  475. }
  476. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  477. goto Exit;
  478. }
  479. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  480. aceIndex++;
  481. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidUsers)) {
  482. goto Exit;
  483. }
  484. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  485. goto Exit;
  486. }
  487. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  488. if (bAddPowerUsersAce) {
  489. aceIndex++;
  490. dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)):
  491. (GENERIC_READ | GENERIC_EXECUTE);
  492. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*dwAccMask,*/ psidPowerUsers)) {
  493. goto Exit;
  494. }
  495. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  496. goto Exit;
  497. }
  498. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  499. }
  500. if (bAddEveryOneAce) {
  501. aceIndex++;
  502. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidEveryOne)) {
  503. goto Exit;
  504. }
  505. if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
  506. goto Exit;
  507. }
  508. lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  509. }
  510. //
  511. // Put together the security descriptor
  512. //
  513. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  514. goto Exit;
  515. }
  516. if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
  517. goto Exit;
  518. }
  519. //
  520. // Set the security
  521. //
  522. if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, &sd)) {
  523. bRetVal = TRUE;
  524. } else {
  525. }
  526. Exit:
  527. if (psidSystem) {
  528. FreeSid(psidSystem);
  529. }
  530. if (psidAdmin) {
  531. FreeSid(psidAdmin);
  532. }
  533. if (psidUsers) {
  534. FreeSid(psidUsers);
  535. }
  536. if ((bAddPowerUsersAce) && (psidPowerUsers)) {
  537. FreeSid(psidPowerUsers);
  538. }
  539. if ((bAddEveryOneAce) && (psidEveryOne)) {
  540. FreeSid(psidEveryOne);
  541. }
  542. if (pAcl) {
  543. GlobalFree (pAcl);
  544. }
  545. return bRetVal;
  546. }
  547. #ifdef SHMG_DBG
  548. void SHMGLogErrMsg(char *szErrMsg, DWORD dwError)
  549. {
  550. DWORD dwBytesWritten = 0;
  551. char szMsg[256];
  552. static HANDLE hLogFile = 0;
  553. if (!hLogFile) {
  554. hLogFile = CreateFile(_T("shmgrate.log"), GENERIC_WRITE,
  555. FILE_SHARE_WRITE, 0,
  556. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
  557. }
  558. StringCchPrintf(szMsg, ARRAYSIZE(szMsg), "%s : (%X)\r\n", szErrMsg, dwError);
  559. WriteFile(hLogFile, szMsg, strlen(szMsg), &dwBytesWritten, 0);
  560. }
  561. #endif
  562. void
  563. FixHtmlHelp(
  564. void
  565. )
  566. {
  567. TCHAR AppDataPath[MAX_PATH*2];
  568. TCHAR HtmlHelpPath[MAX_PATH];
  569. SHMGLogErrMsg("FixHtmlHelp Called",0);
  570. if (SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, AppDataPath) == S_OK &&
  571. LoadString( GetModuleHandle(NULL), IDS_HTML_HELP_DIR, HtmlHelpPath, sizeof(HtmlHelpPath)/sizeof(WCHAR) ) > 0)
  572. {
  573. if (SUCCEEDED(StringCchCat(AppDataPath, ARRAYSIZE(AppDataPath), HtmlHelpPath)))
  574. {
  575. if (CreateDirectory( AppDataPath, NULL ))
  576. {
  577. if (!MakeFileSecure(AppDataPath,OTHERSIDS_EVERYONE|OTHERSIDS_POWERUSERS))
  578. SHMGLogErrMsg("Could not apply security attributes", 0);
  579. }
  580. else
  581. SHMGLogErrMsg("Could not create the directory", GetLastError());
  582. }
  583. else
  584. SHMGLogErrMsg("Could not compose the path -- path too long", 0);
  585. }
  586. else
  587. SHMGLogErrMsg("Could not get APPDATA path", GetLastError());
  588. }