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.

2344 lines
74 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Support for registry policies
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "gphdr.h"
  11. #include <strsafe.h>
  12. static BOOL ExtractKeyOrValueName( LPBYTE * ppData, LPTSTR pszName, DWORD dwNameCch );
  13. //*************************************************************
  14. //
  15. // DeleteRegistryValue()
  16. //
  17. // Purpose: Callback from ParseRegistryFile that deletes
  18. // registry policies
  19. //
  20. // Parameters: lpGPOInfo - GPO Information
  21. // lpKeyName - Key name
  22. // lpValueName - Value name
  23. // dwType - Registry data type
  24. // lpData - Registry data
  25. // pwszGPO - Gpo
  26. // pwszSOM - Sdou that the Gpo is linked to
  27. // pHashTable - Hash table for registry keys
  28. //
  29. // Return: TRUE if successful
  30. // FALSE if an error occurs
  31. //
  32. //*************************************************************
  33. BOOL DeleteRegistryValue (LPGPOINFO lpGPOInfo, LPTSTR lpKeyName,
  34. LPTSTR lpValueName, DWORD dwType,
  35. DWORD dwDataLength, LPBYTE lpData,
  36. WCHAR *pwszGPO,
  37. WCHAR *pwszSOM, REGHASHTABLE *pHashTable)
  38. {
  39. DWORD dwDisp;
  40. HKEY hSubKey;
  41. LONG lResult;
  42. INT iStrLen;
  43. TCHAR szPolicies1[] = TEXT("Software\\Policies");
  44. TCHAR szPolicies2[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies");
  45. XLastError xe;
  46. //
  47. // Check if there is a keyname
  48. //
  49. if (!lpKeyName || !(*lpKeyName)) {
  50. return TRUE;
  51. }
  52. //
  53. // Check if the key is in one of the policies keys
  54. //
  55. iStrLen = lstrlen(szPolicies1);
  56. if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE, szPolicies1,
  57. iStrLen, lpKeyName, iStrLen) != CSTR_EQUAL) {
  58. iStrLen = lstrlen(szPolicies2);
  59. if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE, szPolicies2,
  60. iStrLen, lpKeyName, iStrLen) != CSTR_EQUAL) {
  61. return TRUE;
  62. }
  63. }
  64. //
  65. // Check if the value name starts with **
  66. //
  67. if (lpValueName && (lstrlen(lpValueName) > 1)) {
  68. if ( (*lpValueName == TEXT('*')) && (*(lpValueName+1) == TEXT('*')) ) {
  69. return TRUE;
  70. }
  71. }
  72. //
  73. // We found a value that needs to be deleted
  74. //
  75. if (RegCleanUpValue (lpGPOInfo->hKeyRoot, lpKeyName, lpValueName)) {
  76. DebugMsg((DM_VERBOSE, TEXT("DeleteRegistryValue: Deleted %s\\%s"),
  77. lpKeyName, lpValueName));
  78. } else {
  79. xe = GetLastError();
  80. DebugMsg((DM_WARNING, TEXT("DeleteRegistryValue: Failed to delete %s\\%s"),
  81. lpKeyName, lpValueName));
  82. return FALSE;
  83. }
  84. return TRUE;
  85. }
  86. //*************************************************************
  87. //
  88. // SetRegPermissionsOnPoliciesKey()
  89. //
  90. // Purpose: Set permissions on the policy keys to add LocalSystem permission
  91. // and become the owner
  92. //
  93. // Parameters: lpGPOInfo - GPT information
  94. //
  95. // Return: TRUE if successful
  96. // FALSE if an error occurs
  97. //
  98. // Ideally it should set the owner and permissions for each subkey but that is
  99. // proportinal to the number of subkeys
  100. //
  101. //*************************************************************
  102. BOOL SetRegPermissionsOnPoliciesKey(LPGPOINFO lpGPOInfo, LPTSTR szSubKey)
  103. {
  104. NTSTATUS Status = STATUS_SUCCESS;
  105. BOOLEAN WasEnabled = FALSE;
  106. SECURITY_DESCRIPTOR sd;
  107. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  108. PSID psidSystem = NULL;
  109. HKEY hSubKey = NULL;
  110. BOOL bElevated = FALSE;
  111. BOOL bRet = TRUE;
  112. XLastError xe;
  113. DWORD dwErr = ERROR_SUCCESS;
  114. DWORD dwDisp = 0;
  115. DebugMsg((DM_VERBOSE, TEXT("SetRegPermissionsOnPoliciesKey: Resetting permission on the policy key")));
  116. if (lpGPOInfo->dwFlags & GP_MACHINE)
  117. {
  118. return TRUE;
  119. }
  120. DmAssert((szSubKey) && (szSubKey[0]));
  121. // presetup the sd etc. before elevating privileges
  122. //
  123. // Get the system sid
  124. //
  125. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  126. 0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
  127. xe = GetLastError();
  128. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to initialize system sid. Error = %d"), GetLastError()));
  129. goto Exit;
  130. }
  131. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
  132. xe = GetLastError();
  133. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to initialize security descriptor. Error = %d"), GetLastError()));
  134. goto Exit;
  135. }
  136. if (!SetSecurityDescriptorOwner(&sd, psidSystem, FALSE)) {
  137. xe = GetLastError();
  138. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to set security descriptor owner. Error = %d"), GetLastError()));
  139. goto Exit;
  140. }
  141. Status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  142. if (!(NT_SUCCESS(Status))) {
  143. xe = RtlNtStatusToDosError(Status);
  144. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to enable privilege. Error = %d"), (DWORD)xe));
  145. goto Exit;
  146. }
  147. bElevated = TRUE;
  148. //
  149. // Open the registry key
  150. //
  151. dwErr = RegOpenKeyEx(lpGPOInfo->hKeyRoot,
  152. szSubKey,
  153. 0,
  154. WRITE_OWNER,
  155. &hSubKey);
  156. if (dwErr != ERROR_SUCCESS) {
  157. if (dwErr == ERROR_FILE_NOT_FOUND)
  158. {
  159. bRet = TRUE;
  160. }
  161. else {
  162. xe = dwErr;
  163. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to open reg key. Error = %d"), (DWORD)xe));
  164. }
  165. goto Exit;
  166. }
  167. dwErr = RegSetKeySecurity (hSubKey, OWNER_SECURITY_INFORMATION, &sd);
  168. RegCloseKey(hSubKey);
  169. if (dwErr != ERROR_SUCCESS) {
  170. xe = dwErr;
  171. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to set security, error = %d"), dwErr));
  172. goto Exit;
  173. }
  174. if (bElevated)
  175. {
  176. Status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  177. if (!NT_SUCCESS(Status)) {
  178. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to restore privilege to previous enabled state")));
  179. // nothing more we can do
  180. }
  181. else {
  182. bElevated = FALSE;
  183. }
  184. }
  185. if (!MakeRegKeySecure(lpGPOInfo->hToken,
  186. lpGPOInfo->hKeyRoot,
  187. szSubKey)) {
  188. xe = GetLastError();
  189. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to secure reg key.")));
  190. goto Exit;
  191. }
  192. bRet = TRUE;
  193. Exit:
  194. if (psidSystem) {
  195. FreeSid(psidSystem);
  196. }
  197. if (bElevated)
  198. {
  199. Status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  200. if (!NT_SUCCESS(Status)) {
  201. DebugMsg((DM_WARNING, TEXT("SetRegPermissionsOnPoliciesKey: Failed to restore privilege to previous enabled state")));
  202. // nothing more we can do
  203. }
  204. }
  205. return bRet;
  206. }
  207. //*************************************************************
  208. //
  209. // ResetPolicies()
  210. //
  211. // Purpose: Resets the Policies and old Policies key to their
  212. // original state.
  213. //
  214. // Parameters: lpGPOInfo - GPT information
  215. // lpArchive - Name of archive file
  216. //
  217. //
  218. // Return: TRUE if successful
  219. // FALSE if an error occurs
  220. //
  221. //*************************************************************
  222. BOOL ResetPolicies (LPGPOINFO lpGPOInfo, LPTSTR lpArchive)
  223. {
  224. HKEY hKey;
  225. LONG lResult;
  226. DWORD dwDisp, dwValue = 0x91;
  227. XLastError xe;
  228. DebugMsg((DM_VERBOSE, TEXT("ResetPolicies: Entering.")));
  229. //
  230. // change ownership of the key and make sure that localsystem has full control
  231. //
  232. if (!SetRegPermissionsOnPoliciesKey(lpGPOInfo, TEXT("Software\\Policies")))
  233. {
  234. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to set permissions on the policy key(1) with %d"), GetLastError()));
  235. return FALSE;
  236. }
  237. if (!SetRegPermissionsOnPoliciesKey(lpGPOInfo, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies")))
  238. {
  239. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to set permissions on the policy key(2) with %d"), GetLastError()));
  240. return FALSE;
  241. }
  242. //
  243. // Parse the archive file and delete any policies
  244. //
  245. if (!ParseRegistryFile (lpGPOInfo, lpArchive,
  246. DeleteRegistryValue, NULL, NULL, NULL, NULL, FALSE )) {
  247. DWORD Status;
  248. xe = GetLastError();
  249. DebugMsg((DM_WARNING, TEXT("ResetPolicies: ParseRegistryFile failed with error %d. deleting policy keys"), GetLastError()));
  250. if ((Status = RegDelnode(lpGPOInfo->hKeyRoot, TEXT("Software\\Policies"))) != ERROR_SUCCESS)
  251. {
  252. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to delete the reg key with %d"), Status));
  253. }
  254. if ((Status = RegDelnode(lpGPOInfo->hKeyRoot, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"))) != ERROR_SUCCESS)
  255. {
  256. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to delete the reg key with %d"), Status));
  257. }
  258. // cannot fail if the path is too long
  259. }
  260. //
  261. // Recreate the new policies key
  262. //
  263. lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
  264. TEXT("Software\\Policies"),
  265. 0, NULL, REG_OPTION_NON_VOLATILE,
  266. KEY_WRITE, NULL, &hKey, &dwDisp);
  267. if (lResult == ERROR_SUCCESS) {
  268. //
  269. // Re-apply security
  270. //
  271. RegCloseKey (hKey);
  272. if (!MakeRegKeySecure((lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
  273. lpGPOInfo->hKeyRoot,
  274. TEXT("Software\\Policies"))) {
  275. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to secure reg key.")));
  276. }
  277. } else {
  278. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to create reg key with %d."), lResult));
  279. }
  280. //
  281. // Recreate the old policies key
  282. //
  283. lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
  284. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"),
  285. 0, NULL, REG_OPTION_NON_VOLATILE,
  286. KEY_WRITE, NULL, &hKey, &dwDisp);
  287. if (lResult == ERROR_SUCCESS) {
  288. //
  289. // Re-apply security
  290. //
  291. RegCloseKey (hKey);
  292. if (!MakeRegKeySecure((lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
  293. lpGPOInfo->hKeyRoot,
  294. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"))) {
  295. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to secure reg key.")));
  296. }
  297. } else {
  298. DebugMsg((DM_WARNING, TEXT("ResetPolicies: Failed to create reg key with %d."), lResult));
  299. }
  300. //
  301. // If this is user policy, reset the NoDriveTypeAutoRun default value
  302. //
  303. if (!(lpGPOInfo->dwFlags & GP_MACHINE)) {
  304. // override the default value with what the shell team wants on server
  305. if ((g_ProductType == PT_SERVER) || (g_ProductType == PT_DC))
  306. {
  307. DebugMsg((DM_VERBOSE, TEXT("ResetPolicies: resetting shell autorun value for server.")));
  308. dwValue = 0x95;
  309. }
  310. if (RegCreateKeyEx (lpGPOInfo->hKeyRoot,
  311. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"),
  312. 0, NULL, REG_OPTION_NON_VOLATILE,
  313. KEY_WRITE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  314. RegSetValueEx (hKey, TEXT("NoDriveTypeAutoRun"), 0,
  315. REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue));
  316. RegCloseKey (hKey);
  317. }
  318. }
  319. DebugMsg((DM_VERBOSE, TEXT("ResetPolicies: Leaving.")));
  320. return TRUE;
  321. }
  322. //*************************************************************
  323. //
  324. // ArchiveRegistryValue()
  325. //
  326. // Purpose: Archives a registry value in the specified file
  327. //
  328. // Parameters: hFile - File handle of archive file
  329. // lpKeyName - Key name
  330. // lpValueName - Value name
  331. // dwType - Registry value type
  332. // dwDataLength - Registry value size
  333. // lpData - Registry value
  334. //
  335. // Return: TRUE if successful
  336. // FALSE if an error occurs
  337. //
  338. //*************************************************************
  339. BOOL ArchiveRegistryValue(HANDLE hFile, LPWSTR lpKeyName,
  340. LPWSTR lpValueName, DWORD dwType,
  341. DWORD dwDataLength, LPBYTE lpData)
  342. {
  343. BOOL bResult = FALSE;
  344. DWORD dwBytesWritten;
  345. DWORD dwTemp;
  346. const WCHAR cOpenBracket = L'[';
  347. const WCHAR cCloseBracket = L']';
  348. const WCHAR cSemiColon = L';';
  349. XLastError xe;
  350. //
  351. // Write the entry to the text file.
  352. //
  353. // Format:
  354. //
  355. // [keyname;valuename;type;datalength;data]
  356. //
  357. // open bracket
  358. if (!WriteFile (hFile, &cOpenBracket, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  359. dwBytesWritten != sizeof(WCHAR))
  360. {
  361. xe = GetLastError();
  362. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write open bracket with %d"),
  363. GetLastError()));
  364. goto Exit;
  365. }
  366. // key name
  367. dwTemp = (lstrlen (lpKeyName) + 1) * sizeof (WCHAR);
  368. if (!WriteFile (hFile, lpKeyName, dwTemp, &dwBytesWritten, NULL) ||
  369. dwBytesWritten != dwTemp)
  370. {
  371. xe = GetLastError();
  372. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write key name with %d"),
  373. GetLastError()));
  374. goto Exit;
  375. }
  376. // semicolon
  377. if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  378. dwBytesWritten != sizeof(WCHAR))
  379. {
  380. xe = GetLastError();
  381. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
  382. GetLastError()));
  383. goto Exit;
  384. }
  385. // value name
  386. dwTemp = (lstrlen (lpValueName) + 1) * sizeof (WCHAR);
  387. if (!WriteFile (hFile, lpValueName, dwTemp, &dwBytesWritten, NULL) ||
  388. dwBytesWritten != dwTemp)
  389. {
  390. xe = GetLastError();
  391. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write value name with %d"),
  392. GetLastError()));
  393. goto Exit;
  394. }
  395. // semicolon
  396. if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  397. dwBytesWritten != sizeof(WCHAR))
  398. {
  399. xe = GetLastError();
  400. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
  401. GetLastError()));
  402. goto Exit;
  403. }
  404. // type
  405. if (!WriteFile (hFile, &dwType, sizeof(DWORD), &dwBytesWritten, NULL) ||
  406. dwBytesWritten != sizeof(DWORD))
  407. {
  408. xe = GetLastError();
  409. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data type with %d"),
  410. GetLastError()));
  411. goto Exit;
  412. }
  413. // semicolon
  414. if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  415. dwBytesWritten != sizeof(WCHAR))
  416. {
  417. xe = GetLastError();
  418. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
  419. GetLastError()));
  420. goto Exit;
  421. }
  422. // data length
  423. if (!WriteFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesWritten, NULL) ||
  424. dwBytesWritten != sizeof(DWORD))
  425. {
  426. xe = GetLastError();
  427. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data type with %d"),
  428. GetLastError()));
  429. goto Exit;
  430. }
  431. // semicolon
  432. if (!WriteFile (hFile, &cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  433. dwBytesWritten != sizeof(WCHAR))
  434. {
  435. xe = GetLastError();
  436. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write semicolon with %d"),
  437. GetLastError()));
  438. goto Exit;
  439. }
  440. // data
  441. if (!WriteFile (hFile, lpData, dwDataLength, &dwBytesWritten, NULL) ||
  442. dwBytesWritten != dwDataLength)
  443. {
  444. xe = GetLastError();
  445. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write data with %d"),
  446. GetLastError()));
  447. goto Exit;
  448. }
  449. // close bracket
  450. if (!WriteFile (hFile, &cCloseBracket, sizeof(WCHAR), &dwBytesWritten, NULL) ||
  451. dwBytesWritten != sizeof(WCHAR))
  452. {
  453. xe = GetLastError();
  454. DebugMsg((DM_WARNING, TEXT("ArchiveRegistryValue: Failed to write close bracket with %d"),
  455. GetLastError()));
  456. goto Exit;
  457. }
  458. //
  459. // Sucess
  460. //
  461. bResult = TRUE;
  462. Exit:
  463. return bResult;
  464. }
  465. //*************************************************************
  466. //
  467. // ParseRegistryFile()
  468. //
  469. // Purpose: Parses a registry.pol file
  470. //
  471. // Parameters: lpGPOInfo - GPO information
  472. // lpRegistry - Path to registry.pol
  473. // pfnRegFileCallback - Callback function
  474. // hArchive - Handle to archive file
  475. // pwszGPO - Gpo
  476. // pwszSOM - Sdou that the Gpo is linked to
  477. // pHashTable - Hash table for registry keys
  478. //
  479. //
  480. // Return: TRUE if successful
  481. // FALSE if an error occurs
  482. //
  483. //*************************************************************
  484. BOOL ParseRegistryFile (LPGPOINFO lpGPOInfo, LPTSTR lpRegistry,
  485. PFNREGFILECALLBACK pfnRegFileCallback,
  486. HANDLE hArchive, WCHAR *pwszGPO,
  487. WCHAR *pwszSOM, REGHASHTABLE *pHashTable,
  488. BOOL bRsopPlanningMode)
  489. {
  490. HANDLE hFile = INVALID_HANDLE_VALUE;
  491. BOOL bResult = FALSE;
  492. DWORD dwTemp, dwBytesRead, dwType, dwDataLength;
  493. LPWSTR lpKeyName = 0, lpValueName = 0, lpTemp;
  494. LPBYTE lpData = NULL;
  495. WCHAR chTemp;
  496. HANDLE hOldToken;
  497. XLastError xe;
  498. //
  499. // Verbose output
  500. //
  501. DebugMsg((DM_VERBOSE, TEXT("ParseRegistryFile: Entering with <%s>."),
  502. lpRegistry));
  503. //
  504. // Open the registry file
  505. //
  506. if(!bRsopPlanningMode) {
  507. if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken)) {
  508. xe = GetLastError();
  509. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to impersonate user")));
  510. goto Exit;
  511. }
  512. }
  513. hFile = CreateFile (lpRegistry, GENERIC_READ, FILE_SHARE_READ, NULL,
  514. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  515. NULL);
  516. if(!bRsopPlanningMode) {
  517. RevertToUser(&hOldToken);
  518. }
  519. if (hFile == INVALID_HANDLE_VALUE) {
  520. if ((GetLastError() == ERROR_FILE_NOT_FOUND) ||
  521. (GetLastError() == ERROR_PATH_NOT_FOUND))
  522. {
  523. bResult = TRUE;
  524. goto Exit;
  525. }
  526. else
  527. {
  528. xe = GetLastError();
  529. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: CreateFile failed with %d"),
  530. GetLastError()));
  531. CEvents ev(TRUE, EVENT_NO_REGISTRY);
  532. ev.AddArg(lpRegistry); ev.AddArgWin32Error(GetLastError()); ev.Report();
  533. goto Exit;
  534. }
  535. }
  536. //
  537. // Allocate buffers to hold the keyname, valuename, and data
  538. //
  539. lpKeyName = (LPWSTR) LocalAlloc (LPTR, MAX_KEYNAME_SIZE * sizeof(WCHAR));
  540. if (!lpKeyName)
  541. {
  542. xe = GetLastError();
  543. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory with %d"),
  544. GetLastError()));
  545. goto Exit;
  546. }
  547. lpValueName = (LPWSTR) LocalAlloc (LPTR, MAX_VALUENAME_SIZE * sizeof(WCHAR));
  548. if (!lpValueName)
  549. {
  550. xe = GetLastError();
  551. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory with %d"),
  552. GetLastError()));
  553. goto Exit;
  554. }
  555. //
  556. // Read the header block
  557. //
  558. // 2 DWORDS, signature (PReg) and version number and 2 newlines
  559. //
  560. if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) ||
  561. dwBytesRead != sizeof(dwTemp))
  562. {
  563. xe = ERROR_INVALID_DATA;
  564. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read signature with %d"),
  565. GetLastError()));
  566. goto Exit;
  567. }
  568. if (dwTemp != REGFILE_SIGNATURE)
  569. {
  570. xe = ERROR_INVALID_DATA;
  571. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Invalid file signature")));
  572. goto Exit;
  573. }
  574. if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) ||
  575. dwBytesRead != sizeof(dwTemp))
  576. {
  577. xe = ERROR_INVALID_DATA;
  578. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read version number with %d"),
  579. GetLastError()));
  580. goto Exit;
  581. }
  582. if (dwTemp != REGISTRY_FILE_VERSION)
  583. {
  584. xe = ERROR_INVALID_DATA;
  585. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Invalid file version")));
  586. goto Exit;
  587. }
  588. //
  589. // Read the data
  590. //
  591. while (TRUE)
  592. {
  593. //
  594. // Read the first character. It will either be a [ or the end
  595. // of the file.
  596. //
  597. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  598. {
  599. if (GetLastError() != ERROR_HANDLE_EOF)
  600. {
  601. xe = ERROR_INVALID_DATA;
  602. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
  603. GetLastError()));
  604. goto Exit;
  605. }
  606. break;
  607. }
  608. if ((dwBytesRead == 0) || (chTemp != L'['))
  609. {
  610. break;
  611. }
  612. //
  613. // Read the keyname
  614. //
  615. lpTemp = lpKeyName;
  616. dwTemp = 0;
  617. while (dwTemp < MAX_KEYNAME_SIZE)
  618. {
  619. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  620. {
  621. xe = ERROR_INVALID_DATA;
  622. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read keyname character with %d"),
  623. GetLastError()));
  624. goto Exit;
  625. }
  626. *lpTemp++ = chTemp;
  627. if (chTemp == TEXT('\0'))
  628. break;
  629. dwTemp++;
  630. }
  631. if (dwTemp >= MAX_KEYNAME_SIZE)
  632. {
  633. xe = ERROR_INVALID_DATA;
  634. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Keyname exceeded max size")));
  635. goto Exit;
  636. }
  637. //
  638. // Read the semi-colon
  639. //
  640. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  641. {
  642. if (GetLastError() != ERROR_HANDLE_EOF)
  643. {
  644. xe = ERROR_INVALID_DATA;
  645. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
  646. GetLastError()));
  647. goto Exit;
  648. }
  649. break;
  650. }
  651. if ((dwBytesRead == 0) || (chTemp != L';'))
  652. {
  653. break;
  654. }
  655. //
  656. // Read the valuename
  657. //
  658. lpTemp = lpValueName;
  659. dwTemp = 0;
  660. while (dwTemp < MAX_VALUENAME_SIZE)
  661. {
  662. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  663. {
  664. xe = ERROR_INVALID_DATA;
  665. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read valuename character with %d"),
  666. GetLastError()));
  667. goto Exit;
  668. }
  669. *lpTemp++ = chTemp;
  670. if (chTemp == TEXT('\0'))
  671. break;
  672. dwTemp++;
  673. }
  674. if (dwTemp >= MAX_VALUENAME_SIZE)
  675. {
  676. xe = ERROR_INVALID_DATA;
  677. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Valuename exceeded max size")));
  678. goto Exit;
  679. }
  680. //
  681. // Read the semi-colon
  682. //
  683. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  684. {
  685. if (GetLastError() != ERROR_HANDLE_EOF)
  686. {
  687. xe = ERROR_INVALID_DATA;
  688. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read first character with %d"),
  689. GetLastError()));
  690. goto Exit;
  691. }
  692. break;
  693. }
  694. if ((dwBytesRead == 0) || (chTemp != L';'))
  695. {
  696. break;
  697. }
  698. //
  699. // Read the type
  700. //
  701. if (!ReadFile (hFile, &dwType, sizeof(DWORD), &dwBytesRead, NULL))
  702. {
  703. xe = ERROR_INVALID_DATA;
  704. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read type with %d"),
  705. GetLastError()));
  706. goto Exit;
  707. }
  708. //
  709. // Skip semicolon
  710. //
  711. if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  712. {
  713. xe = ERROR_INVALID_DATA;
  714. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip semicolon with %d"),
  715. GetLastError()));
  716. goto Exit;
  717. }
  718. //
  719. // Read the data length
  720. //
  721. if (!ReadFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesRead, NULL))
  722. {
  723. xe = ERROR_INVALID_DATA;
  724. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to data length with %d"),
  725. GetLastError()));
  726. goto Exit;
  727. }
  728. //
  729. // Skip semicolon
  730. //
  731. if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  732. {
  733. xe = ERROR_INVALID_DATA;
  734. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip semicolon with %d"),
  735. GetLastError()));
  736. goto Exit;
  737. }
  738. //
  739. // Allocate memory for data
  740. //
  741. lpData = (LPBYTE) LocalAlloc (LPTR, dwDataLength);
  742. if (!lpData)
  743. {
  744. xe = GetLastError();
  745. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to allocate memory for data with %d"),
  746. GetLastError()));
  747. goto Exit;
  748. }
  749. //
  750. // Read data
  751. //
  752. if (!ReadFile (hFile, lpData, dwDataLength, &dwBytesRead, NULL))
  753. {
  754. xe = ERROR_INVALID_DATA;
  755. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to read data with %d"),
  756. GetLastError()));
  757. goto Exit;
  758. }
  759. //
  760. // Skip closing bracket
  761. //
  762. if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL))
  763. {
  764. xe = ERROR_INVALID_DATA;
  765. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Failed to skip closing bracket with %d"),
  766. GetLastError()));
  767. goto Exit;
  768. }
  769. if (chTemp != L']')
  770. {
  771. xe = ERROR_INVALID_DATA;
  772. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Expected to find ], but found %c"),
  773. chTemp));
  774. goto Exit;
  775. }
  776. //
  777. // Call the callback function
  778. //
  779. if (!pfnRegFileCallback (lpGPOInfo, lpKeyName, lpValueName,
  780. dwType, dwDataLength, lpData,
  781. pwszGPO, pwszSOM, pHashTable ))
  782. {
  783. xe = GetLastError();
  784. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: Callback function returned false.")));
  785. goto Exit;
  786. }
  787. //
  788. // Archive the data if appropriate
  789. //
  790. if (hArchive) {
  791. if (!ArchiveRegistryValue(hArchive, lpKeyName, lpValueName,
  792. dwType, dwDataLength, lpData)) {
  793. DebugMsg((DM_WARNING, TEXT("ParseRegistryFile: ArchiveRegistryValue returned false.")));
  794. }
  795. }
  796. LocalFree (lpData);
  797. lpData = NULL;
  798. }
  799. bResult = TRUE;
  800. Exit:
  801. //
  802. // Finished
  803. //
  804. if ( !bResult )
  805. {
  806. CEvents ev(TRUE, EVENT_REGISTRY_TEMPLATE_ERROR);
  807. ev.AddArg(lpRegistry ? lpRegistry : TEXT("")); ev.AddArgWin32Error( xe ); ev.Report();
  808. }
  809. DebugMsg((DM_VERBOSE, TEXT("ParseRegistryFile: Leaving.")));
  810. if (lpData) {
  811. LocalFree (lpData);
  812. }
  813. if ( hFile != INVALID_HANDLE_VALUE ) {
  814. CloseHandle (hFile);
  815. }
  816. if ( lpKeyName ) {
  817. LocalFree (lpKeyName);
  818. }
  819. if ( lpValueName ) {
  820. LocalFree (lpValueName);
  821. }
  822. return bResult;
  823. }
  824. //*************************************************************
  825. //
  826. // ProcessRegistryValue()
  827. //
  828. // Purpose: Callback passed to ParseRegistryFile from ProcessRegistryFiles. Invokes AddRegHashEntry
  829. // with appropriate parameters depending on the registry policy settings.
  830. //
  831. // Parameters:
  832. // pUnused - Not used. It si there only to conform to the signature
  833. // expected by ParseRegistryFile.
  834. // lpKeyName - registry key name
  835. // lpValueName - Registry value name
  836. // dwType - Registry value type
  837. // dwDataLength - Length of registry value data.
  838. // lpData - Regsitry value data
  839. // *pwszGPO - GPO associated with this registry setting
  840. // *pwszSOM - SOM associated with the GPO
  841. // *pHashTable - Hash table containing registry policy data for a policy target.
  842. //
  843. // Return: TRUE if successful
  844. // FALSE if an error occurs
  845. //
  846. //*************************************************************
  847. BOOL ProcessRegistryValue ( void* pUnused,
  848. LPTSTR lpKeyName,
  849. LPTSTR lpValueName,
  850. DWORD dwType,
  851. DWORD dwDataLength,
  852. LPBYTE lpData,
  853. WCHAR *pwszGPO,
  854. WCHAR *pwszSOM,
  855. REGHASHTABLE *pHashTable)
  856. {
  857. BOOL bLoggingOk = TRUE;
  858. BOOL bStatus;
  859. //
  860. // Special case some values
  861. //
  862. if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  863. TEXT("**del."), 6, lpValueName, 6) == 2)
  864. {
  865. LPTSTR lpRealValueName = lpValueName + 6;
  866. //
  867. // Delete one specific value
  868. //
  869. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
  870. lpRealValueName, 0, 0, NULL,
  871. pwszGPO, pwszSOM, lpValueName, TRUE );
  872. }
  873. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  874. TEXT("**delvals."), 10, lpValueName, 10) == 2)
  875. {
  876. //
  877. // Delete all values in the destination key
  878. //
  879. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEALLVALUES, lpKeyName,
  880. NULL, 0, 0, NULL,
  881. pwszGPO, pwszSOM, lpValueName, TRUE );
  882. }
  883. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  884. TEXT("**DeleteValues"), 14, lpValueName, 14) == 2)
  885. {
  886. TCHAR szValueName[MAX_VALUENAME_SIZE];
  887. bLoggingOk = TRUE;
  888. while ( *lpData )
  889. {
  890. bStatus = ExtractKeyOrValueName( &lpData, szValueName, MAX_VALUENAME_SIZE );
  891. // This failure must be fatal.
  892. if ( ! bStatus )
  893. {
  894. bLoggingOk = FALSE;
  895. break;
  896. }
  897. //
  898. // Failures here have always allowed processing to continue. Not sure
  899. // why, but not worth risking some wierd regression to change it.
  900. //
  901. bStatus = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
  902. szValueName, 0, 0, NULL,
  903. pwszGPO, pwszSOM, lpValueName, TRUE );
  904. if ( ! bStatus )
  905. bLoggingOk = FALSE;
  906. }
  907. }
  908. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  909. TEXT("**DeleteKeys"), 12, lpValueName, 12) == 2)
  910. {
  911. TCHAR szKeyName[MAX_KEYNAME_SIZE];
  912. bLoggingOk = TRUE;
  913. while ( *lpData )
  914. {
  915. bStatus = ExtractKeyOrValueName( &lpData, szKeyName, MAX_KEYNAME_SIZE );
  916. // This failure must be fatal.
  917. if ( ! bStatus )
  918. {
  919. bLoggingOk = FALSE;
  920. break;
  921. }
  922. //
  923. // Failures here have always allowed processing to continue. Not sure
  924. // why, but not worth risking some wierd regression to change it.
  925. //
  926. bStatus = AddRegHashEntry( pHashTable, REG_DELETEKEY, lpKeyName,
  927. NULL, 0, 0, NULL,
  928. pwszGPO, pwszSOM, lpValueName, TRUE );
  929. if ( ! bStatus )
  930. bLoggingOk = FALSE;
  931. }
  932. }
  933. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  934. TEXT("**soft."), 7, lpValueName, 7) == 2)
  935. {
  936. //
  937. // In planning mode we will assume the value does not exist in the target computer.
  938. // Therefore, we set it if no value exists in the hash table.
  939. //
  940. // Soft add is dealt with differently in planning mode vs. diag mode.
  941. // In diag mode, check is done while processing policy and it is logged as a add value
  942. // if the key doesn't exist.
  943. // In planning mode, key is not supposed to exist beforehand and the hash table itself is
  944. // used to determine whether to add the key or not.
  945. LPTSTR lpRealValueName = lpValueName + 7;
  946. bLoggingOk = AddRegHashEntry( pHashTable, REG_SOFTADDVALUE, lpKeyName,
  947. lpRealValueName, dwType, dwDataLength, lpData,
  948. pwszGPO, pwszSOM, lpValueName, TRUE );
  949. }
  950. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  951. TEXT("**SecureKey"), 11, lpValueName, 11) == 2)
  952. {
  953. // There is nothing to do here.
  954. } else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  955. TEXT("**Comment:"), 10, lpValueName, 10) == 2)
  956. {
  957. //
  958. // Comment - can be ignored
  959. //
  960. }
  961. else
  962. {
  963. //
  964. // AddRegHashEntry needs to log a key being logged but no values.
  965. //
  966. bLoggingOk = AddRegHashEntry( pHashTable, REG_ADDVALUE, lpKeyName,
  967. lpValueName, dwType, dwDataLength, lpData,
  968. pwszGPO, pwszSOM, TEXT(""), TRUE );
  969. }
  970. return bLoggingOk;
  971. }
  972. //*************************************************************
  973. //
  974. // ResetRegKeySecurity
  975. //
  976. // Purpose: Resets the security on a user's key
  977. //
  978. // Parameters: hKeyRoot - Handle to the root of the hive
  979. // lpKeyName - Subkey name
  980. //
  981. //
  982. // Return: TRUE if successful
  983. // FALSE if an error occurs
  984. //
  985. //*************************************************************
  986. BOOL ResetRegKeySecurity (HKEY hKeyRoot, LPTSTR lpKeyName)
  987. {
  988. PSECURITY_DESCRIPTOR pSD = NULL;
  989. DWORD dwSize = 0;
  990. LONG lResult;
  991. HKEY hSubKey;
  992. XLastError xe;
  993. RegGetKeySecurity(hKeyRoot, DACL_SECURITY_INFORMATION, pSD, &dwSize);
  994. if (!dwSize) {
  995. DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: RegGetKeySecurity returned 0")));
  996. return FALSE;
  997. }
  998. pSD = LocalAlloc (LPTR, dwSize);
  999. if (!pSD) {
  1000. xe = GetLastError();
  1001. DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to allocate memory")));
  1002. return FALSE;
  1003. }
  1004. lResult = RegGetKeySecurity(hKeyRoot, DACL_SECURITY_INFORMATION, pSD, &dwSize);
  1005. if (lResult != ERROR_SUCCESS) {
  1006. xe = GetLastError();
  1007. DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to query key security with %d"),
  1008. lResult));
  1009. LocalFree (pSD);
  1010. return FALSE;
  1011. }
  1012. lResult = RegOpenKeyEx(hKeyRoot,
  1013. lpKeyName,
  1014. 0,
  1015. WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
  1016. &hSubKey);
  1017. if (lResult != ERROR_SUCCESS) {
  1018. xe = GetLastError();
  1019. DebugMsg((DM_WARNING, TEXT("ResetRegKeySecurity: Failed to open sub key with %d"),
  1020. lResult));
  1021. LocalFree (pSD);
  1022. return FALSE;
  1023. }
  1024. lResult = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, pSD);
  1025. RegCloseKey (hSubKey);
  1026. LocalFree (pSD);
  1027. if (lResult != ERROR_SUCCESS) {
  1028. xe = GetLastError();
  1029. DebugMsg((DM_WARNING, TEXT("ResetRegKeySecure: Failed to set security, error = %d"), lResult));
  1030. return FALSE;
  1031. }
  1032. return TRUE;
  1033. }
  1034. //*************************************************************
  1035. //
  1036. // SetRegistryValue()
  1037. //
  1038. // Purpose: Callback from ParseRegistryFile that sets
  1039. // registry policies
  1040. //
  1041. // Parameters: lpGPOInfo - GPO Information
  1042. // lpKeyName - Key name
  1043. // lpValueName - Value name
  1044. // dwType - Registry data type
  1045. // lpData - Registry data
  1046. // pwszGPO - Gpo
  1047. // pwszSOM - Sdou that the Gpo is linked to
  1048. // pHashTable - Hash table for registry keys
  1049. //
  1050. // Return: TRUE if successful
  1051. // FALSE if an error occurs
  1052. //
  1053. //*************************************************************
  1054. BOOL SetRegistryValue (LPGPOINFO lpGPOInfo, LPTSTR lpKeyName,
  1055. LPTSTR lpValueName, DWORD dwType,
  1056. DWORD dwDataLength, LPBYTE lpData,
  1057. WCHAR *pwszGPO,
  1058. WCHAR *pwszSOM, REGHASHTABLE *pHashTable)
  1059. {
  1060. DWORD dwDisp;
  1061. HKEY hSubKey;
  1062. LONG lResult;
  1063. BOOL bLoggingOk = TRUE;
  1064. BOOL bRsopLogging = (pHashTable != NULL); // Is diagnostic mode Rsop logging enabled ?
  1065. BOOL bUseValueName = FALSE;
  1066. BOOL bRegOpSuccess = TRUE;
  1067. XLastError xe;
  1068. //
  1069. // Special case some values
  1070. //
  1071. if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1072. TEXT("**del."), 6, lpValueName, 6) == 2)
  1073. {
  1074. LPTSTR lpRealValueName = lpValueName + 6;
  1075. //
  1076. // Delete one specific value
  1077. //
  1078. lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
  1079. lpKeyName, 0, KEY_WRITE, &hSubKey);
  1080. if (lResult == ERROR_SUCCESS)
  1081. {
  1082. lResult = RegDeleteValue(hSubKey, lpRealValueName);
  1083. if ((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND))
  1084. {
  1085. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted value <%s>."),
  1086. lpRealValueName));
  1087. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1088. CEvents ev(FALSE, EVENT_DELETED_VALUE);
  1089. ev.AddArg(lpRealValueName); ev.Report();
  1090. }
  1091. if ( bRsopLogging ) {
  1092. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
  1093. lpRealValueName, 0, 0, NULL,
  1094. pwszGPO, pwszSOM, lpValueName, TRUE );
  1095. if (!bLoggingOk) {
  1096. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE <%s>."), lpRealValueName));
  1097. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1098. }
  1099. }
  1100. }
  1101. else
  1102. {
  1103. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to delete value <%s> with %d"),
  1104. lpRealValueName, lResult));
  1105. xe = lResult;
  1106. CEvents ev(TRUE, EVENT_FAIL_DELETE_VALUE);
  1107. ev.AddArg(lpRealValueName); ev.AddArgWin32Error(lResult); ev.Report();
  1108. bRegOpSuccess = FALSE;
  1109. }
  1110. RegCloseKey (hSubKey);
  1111. }
  1112. else if (lResult == ERROR_FILE_NOT_FOUND) {
  1113. //
  1114. // Log into rsop even if the key is not found
  1115. //
  1116. if ( bRsopLogging ) {
  1117. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
  1118. lpRealValueName, 0, 0, NULL,
  1119. pwszGPO, pwszSOM, lpValueName, TRUE );
  1120. if (!bLoggingOk) {
  1121. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1122. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE (notfound) <%s>."), lpRealValueName));
  1123. }
  1124. }
  1125. }
  1126. }
  1127. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1128. TEXT("**delvals."), 10, lpValueName, 10) == 2)
  1129. {
  1130. //
  1131. // Delete all values in the destination key
  1132. //
  1133. lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
  1134. lpKeyName, 0, KEY_WRITE | KEY_READ, &hSubKey);
  1135. if (lResult == ERROR_SUCCESS)
  1136. {
  1137. if (!bRsopLogging)
  1138. bRegOpSuccess = DeleteAllValues(hSubKey);
  1139. else
  1140. bRegOpSuccess = RsopDeleteAllValues(hSubKey, pHashTable, lpKeyName,
  1141. pwszGPO, pwszSOM, lpValueName, &bLoggingOk );
  1142. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted all values in <%s>."),
  1143. lpKeyName));
  1144. RegCloseKey (hSubKey);
  1145. if (!bRegOpSuccess) {
  1146. xe = GetLastError();
  1147. }
  1148. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: DeleteAllvalues finished for %s. bRegOpSuccess = %s, bLoggingOk = %s."),
  1149. lpKeyName, (bRegOpSuccess ? TEXT("TRUE") : TEXT("FALSE")), (bLoggingOk ? TEXT("TRUE") : TEXT("FALSE"))));
  1150. }
  1151. else if (lResult == ERROR_FILE_NOT_FOUND) {
  1152. //
  1153. // Log into rsop even if the key is not found
  1154. // as just deleteallvalues
  1155. //
  1156. if ( bRsopLogging ) {
  1157. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEALLVALUES, lpKeyName,
  1158. NULL, 0, 0, NULL,
  1159. pwszGPO, pwszSOM, lpValueName, TRUE );
  1160. if (!bLoggingOk) {
  1161. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEALLVALUES (notfound) key - <%s>, value <%s>."), lpKeyName, lpValueName));
  1162. }
  1163. }
  1164. }
  1165. }
  1166. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1167. TEXT("**DeleteValues"), 14, lpValueName, 14) == 2)
  1168. {
  1169. TCHAR szValueName[MAX_VALUENAME_SIZE];
  1170. LONG lKeyResult;
  1171. //
  1172. // Delete the values (semi-colon separated)
  1173. //
  1174. lKeyResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
  1175. lpKeyName, 0, KEY_WRITE, &hSubKey);
  1176. while ( *lpData )
  1177. {
  1178. szValueName[0] = 0;
  1179. if ( ExtractKeyOrValueName( &lpData, szValueName, MAX_VALUENAME_SIZE ) )
  1180. lResult = ERROR_SUCCESS;
  1181. else
  1182. lResult = ERROR_INVALID_DATA;
  1183. // Check for OpenKey failures.
  1184. if ( (lResult == ERROR_SUCCESS) &&
  1185. (lKeyResult != ERROR_SUCCESS) && (lKeyResult != ERROR_FILE_NOT_FOUND) )
  1186. lResult = lKeyResult;
  1187. if ( (lKeyResult == ERROR_SUCCESS) && (lResult == ERROR_SUCCESS) )
  1188. {
  1189. lResult = RegDeleteValue (hSubKey, szValueName);
  1190. if ((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND))
  1191. {
  1192. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted value <%s>."),
  1193. szValueName));
  1194. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1195. CEvents ev(FALSE, EVENT_DELETED_VALUE);
  1196. ev.AddArg(szValueName); ev.Report();
  1197. }
  1198. }
  1199. }
  1200. //
  1201. // Checking if value name is valid, key open succeeded, and no unexpected
  1202. // error from value deletion. Note that lKeyResult is not needed because
  1203. // it's value was factored into lResult above.
  1204. //
  1205. if ( (lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND) )
  1206. {
  1207. if ( bRsopLogging ) {
  1208. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEVALUE, lpKeyName,
  1209. szValueName, 0, 0, NULL,
  1210. pwszGPO, pwszSOM, lpValueName, TRUE );
  1211. if (!bLoggingOk)
  1212. {
  1213. //
  1214. // The debug message has always been different for the case where the key
  1215. // existed and where the key did not exist. This is merging what used
  1216. // to be duplicated code.
  1217. //
  1218. if ( ERROR_SUCCESS == lKeyResult )
  1219. {
  1220. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE value <%s>."), szValueName));
  1221. }
  1222. else
  1223. {
  1224. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEVALUE value (not found case) <%s>."), szValueName));
  1225. }
  1226. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1227. }
  1228. }
  1229. }
  1230. else
  1231. {
  1232. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to delete value <%s> with %d"),
  1233. szValueName, lResult));
  1234. CEvents ev(TRUE, EVENT_FAIL_DELETE_VALUE);
  1235. ev.AddArg(szValueName); ev.AddArgWin32Error(lResult); ev.Report();
  1236. xe = lResult;
  1237. bRegOpSuccess = FALSE;
  1238. if ( ERROR_INVALID_DATA == lResult )
  1239. break;
  1240. }
  1241. }
  1242. // lKeyResult is not changed after the intial call to RegOpenKey.
  1243. if (lKeyResult == ERROR_SUCCESS)
  1244. {
  1245. RegCloseKey (hSubKey);
  1246. }
  1247. }
  1248. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1249. TEXT("**DeleteKeys"), 12, lpValueName, 12) == 2)
  1250. {
  1251. TCHAR szKeyName[MAX_KEYNAME_SIZE];
  1252. BOOL bStatus;
  1253. while ( *lpData )
  1254. {
  1255. bStatus = ExtractKeyOrValueName( &lpData, szKeyName, MAX_KEYNAME_SIZE );
  1256. if ( bStatus )
  1257. {
  1258. lResult = RegDelnode (lpGPOInfo->hKeyRoot, szKeyName);
  1259. if ( ERROR_SUCCESS == lResult )
  1260. {
  1261. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Deleted key <%s>."),
  1262. szKeyName));
  1263. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1264. CEvents ev(FALSE, EVENT_DELETED_KEY);
  1265. ev.AddArg(szKeyName); ev.Report();
  1266. }
  1267. }
  1268. }
  1269. else
  1270. {
  1271. lResult = ERROR_INVALID_DATA;
  1272. }
  1273. if ( lResult != ERROR_SUCCESS )
  1274. {
  1275. xe = lResult;
  1276. bRegOpSuccess = FALSE;
  1277. // This is fatal and we must bail out, szKeyName is bad so skip the DebugMsg.
  1278. if ( ERROR_INVALID_DATA == lResult )
  1279. break;
  1280. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: RegDelnode for key <%s>."), szKeyName));
  1281. }
  1282. if ( bRsopLogging ) {
  1283. bLoggingOk = AddRegHashEntry( pHashTable, REG_DELETEKEY, szKeyName,
  1284. NULL, 0, 0, NULL,
  1285. pwszGPO, pwszSOM, lpValueName, TRUE );
  1286. if (!bLoggingOk) {
  1287. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_DELETEKEY <%s>."), szKeyName));
  1288. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1289. }
  1290. }
  1291. }
  1292. }
  1293. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1294. TEXT("**soft."), 7, lpValueName, 7) == 2)
  1295. {
  1296. //
  1297. // "soft" value, only set this if it doesn't already
  1298. // exist in destination
  1299. //
  1300. lResult = RegOpenKeyEx (lpGPOInfo->hKeyRoot,
  1301. lpKeyName, 0, KEY_QUERY_VALUE, &hSubKey);
  1302. if (lResult == ERROR_SUCCESS)
  1303. {
  1304. TCHAR TmpValueData[MAX_PATH+1];
  1305. DWORD dwSize=sizeof(TmpValueData);
  1306. lResult = RegQueryValueEx(hSubKey, lpValueName + 7,
  1307. NULL,NULL,(LPBYTE) TmpValueData,
  1308. &dwSize);
  1309. RegCloseKey (hSubKey);
  1310. if (lResult != ERROR_SUCCESS)
  1311. {
  1312. lpValueName += 7;
  1313. bUseValueName = TRUE;
  1314. goto SetValue;
  1315. }
  1316. }
  1317. }
  1318. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1319. TEXT("**SecureKey"), 11, lpValueName, 11) == 2)
  1320. {
  1321. //
  1322. // Secure / unsecure a key (user only)
  1323. //
  1324. if (!(lpGPOInfo->dwFlags & GP_MACHINE))
  1325. {
  1326. if (*((LPDWORD)lpData) == 1)
  1327. {
  1328. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Securing key <%s>."),
  1329. lpKeyName));
  1330. bRegOpSuccess = MakeRegKeySecure(lpGPOInfo->hToken, lpGPOInfo->hKeyRoot, lpKeyName);
  1331. }
  1332. else
  1333. {
  1334. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Unsecuring key <%s>."),
  1335. lpKeyName));
  1336. bRegOpSuccess = ResetRegKeySecurity (lpGPOInfo->hKeyRoot, lpKeyName);
  1337. }
  1338. if (!bRegOpSuccess) {
  1339. xe = GetLastError();
  1340. }
  1341. }
  1342. }
  1343. else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1344. TEXT("**Comment:"), 10, lpValueName, 10) == 2)
  1345. {
  1346. //
  1347. // Comment - can be ignored
  1348. //
  1349. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: Found comment %s."),
  1350. (lpValueName+10)));
  1351. }
  1352. else
  1353. {
  1354. SetValue:
  1355. //
  1356. // Save registry value
  1357. //
  1358. lResult = RegCreateKeyEx (lpGPOInfo->hKeyRoot,
  1359. lpKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
  1360. KEY_WRITE, NULL, &hSubKey, &dwDisp);
  1361. if (lResult == ERROR_SUCCESS)
  1362. {
  1363. if ((dwType == REG_NONE) && (dwDataLength == 0) &&
  1364. (*lpValueName == L'\0'))
  1365. {
  1366. lResult = ERROR_SUCCESS;
  1367. }
  1368. else
  1369. {
  1370. lResult = RegSetValueEx (hSubKey, lpValueName, 0, dwType,
  1371. lpData, dwDataLength);
  1372. }
  1373. if ( bRsopLogging ) {
  1374. bLoggingOk = AddRegHashEntry( pHashTable, REG_ADDVALUE, lpKeyName,
  1375. lpValueName, dwType, dwDataLength, lpData,
  1376. pwszGPO, pwszSOM, bUseValueName ? lpValueName : TEXT(""), TRUE );
  1377. if (!bLoggingOk) {
  1378. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: AddRegHashEntry failed for REG_ADDVALUE key <%s>, value <%s>."), lpKeyName, lpValueName));
  1379. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1380. }
  1381. }
  1382. RegCloseKey (hSubKey);
  1383. if (lResult == ERROR_SUCCESS)
  1384. {
  1385. switch (dwType) {
  1386. case REG_SZ:
  1387. case REG_EXPAND_SZ:
  1388. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s => %s [OK]"),
  1389. lpValueName, (LPTSTR)lpData));
  1390. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1391. CEvents ev(FALSE, EVENT_SET_STRING_VALUE);
  1392. ev.AddArg(lpValueName); ev.AddArg((LPTSTR)lpData); ev.Report();
  1393. }
  1394. break;
  1395. case REG_DWORD:
  1396. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s => %d [OK]"),
  1397. lpValueName, *((LPDWORD)lpData)));
  1398. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1399. CEvents ev(FALSE, EVENT_SET_DWORD_VALUE);
  1400. ev.AddArg(lpValueName); ev.AddArg((DWORD)*lpData); ev.Report();
  1401. }
  1402. break;
  1403. case REG_NONE:
  1404. break;
  1405. default:
  1406. DebugMsg((DM_VERBOSE, TEXT("SetRegistryValue: %s was set successfully"),
  1407. lpValueName));
  1408. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1409. CEvents ev(FALSE, EVENT_SET_UNKNOWN_VALUE);
  1410. ev.AddArg(lpValueName); ev.Report();
  1411. }
  1412. break;
  1413. }
  1414. if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1415. TEXT("Control Panel\\Colors"), 20, lpKeyName, 20) == 2) {
  1416. lpGPOInfo->dwFlags |= GP_REGPOLICY_CPANEL;
  1417. } else if (CompareString (LOCALE_INVARIANT, NORM_IGNORECASE,
  1418. TEXT("Control Panel\\Desktop"), 21, lpKeyName, 21) == 2) {
  1419. lpGPOInfo->dwFlags |= GP_REGPOLICY_CPANEL;
  1420. }
  1421. }
  1422. else
  1423. {
  1424. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to set value <%s> with %d"),
  1425. lpValueName, lResult));
  1426. xe = lResult;
  1427. CEvents ev(TRUE, EVENT_FAILED_SET);
  1428. ev.AddArg(lpValueName); ev.AddArgWin32Error(lResult); ev.Report();
  1429. bRegOpSuccess = FALSE;
  1430. }
  1431. }
  1432. else
  1433. {
  1434. DebugMsg((DM_WARNING, TEXT("SetRegistryValue: Failed to open key <%s> with %d"),
  1435. lpKeyName, lResult));
  1436. xe = lResult;
  1437. CEvents ev(TRUE, EVENT_FAILED_CREATE);
  1438. ev.AddArg(lpKeyName); ev.AddArgWin32Error(lResult); ev.Report();
  1439. bRegOpSuccess = FALSE;
  1440. }
  1441. }
  1442. return bLoggingOk && bRegOpSuccess;
  1443. }
  1444. BOOL ExtractKeyOrValueName( LPBYTE * ppData, LPTSTR pszName, DWORD dwNameCch )
  1445. {
  1446. LPTSTR lpszNameBegin, lpszNameEnd;
  1447. lpszNameBegin = (LPTSTR) *ppData;
  1448. while ( *lpszNameBegin == TEXT(' ') )
  1449. lpszNameBegin++;
  1450. lpszNameEnd = lpszNameBegin;
  1451. while ( *lpszNameEnd && *lpszNameEnd != TEXT(';') )
  1452. lpszNameEnd++;
  1453. if ( dwNameCch < (DWORD) (lpszNameEnd - lpszNameBegin + 1) )
  1454. {
  1455. DebugMsg((DM_WARNING,
  1456. TEXT("Key or value name %s of size %d exceeds maximum. Further processing aborted."),
  1457. pszName,
  1458. lpszNameEnd - lpszNameBegin));
  1459. return FALSE;
  1460. }
  1461. (void) StringCchCopyN( pszName, dwNameCch, lpszNameBegin, lpszNameEnd - lpszNameBegin );
  1462. pszName[lpszNameEnd - lpszNameBegin] = 0;
  1463. while ( *lpszNameEnd == TEXT(';') )
  1464. lpszNameEnd++;
  1465. *ppData = (LPBYTE) lpszNameEnd;
  1466. return TRUE;
  1467. }
  1468. //*************************************************************
  1469. //
  1470. // ProcessGPORegistryPolicy()
  1471. //
  1472. // Purpose: Proceses GPO registry policy
  1473. //
  1474. // Parameters: lpGPOInfo - GPO information
  1475. // pChangedGPOList - Link list of changed GPOs
  1476. //
  1477. // Notes: This function is called in the context of
  1478. // local system, which allows us to create the
  1479. // directory, write to the file etc.
  1480. //
  1481. // Return: TRUE if successful
  1482. // FALSE if an error occurs
  1483. //
  1484. //*************************************************************
  1485. BOOL ProcessGPORegistryPolicy (LPGPOINFO lpGPOInfo,
  1486. PGROUP_POLICY_OBJECT pChangedGPOList, HRESULT *phrRsopLogging)
  1487. {
  1488. PGROUP_POLICY_OBJECT lpGPO;
  1489. TCHAR szPath[MAX_PATH];
  1490. TCHAR szBuffer[MAX_PATH];
  1491. TCHAR szKeyName[100];
  1492. LPTSTR lpEnd, lpGPOComment;
  1493. HANDLE hFile;
  1494. DWORD dwTemp, dwBytesWritten;
  1495. REGHASHTABLE *pHashTable = NULL;
  1496. WIN32_FIND_DATA findData;
  1497. ADMFILEINFO *pAdmFileCache = NULL;
  1498. XLastError xe;
  1499. HRESULT hr = S_OK;
  1500. BOOL bStatus = FALSE;
  1501. *phrRsopLogging = S_OK;
  1502. //
  1503. // Claim the registry lock before starting registry processing -- this will
  1504. // allow internal components to synchronize on registry processing rather than
  1505. // all policy processing, which means a much shorter wait time
  1506. //
  1507. // We wait for 60 seconds -- if the application does not release the lock
  1508. // in that time, we continue, as 60 seconds should be sufficient to read
  1509. // a few registry settings
  1510. //
  1511. HANDLE hRegistrySection = EnterCriticalPolicySectionEx(
  1512. lpGPOInfo->dwFlags & GP_MACHINE,
  1513. 60000,
  1514. ECP_REGISTRY_ONLY);
  1515. if ( ! hRegistrySection )
  1516. {
  1517. goto ProcessGPORegistryPolicy_Exit;
  1518. }
  1519. //
  1520. // Get the path name to the appropriate profile
  1521. //
  1522. szPath[0] = TEXT('\0');
  1523. dwTemp = ARRAYSIZE(szPath);
  1524. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  1525. GetAllUsersProfileDirectoryEx(szPath, &dwTemp, TRUE);
  1526. } else {
  1527. GetUserProfileDirectory(lpGPOInfo->hToken, szPath, &dwTemp);
  1528. }
  1529. if (szPath[0] == TEXT('\0')) {
  1530. xe = GetLastError();
  1531. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to get path to profile root")));
  1532. goto ProcessGPORegistryPolicy_Exit;
  1533. }
  1534. //
  1535. // Tack on the archive file name
  1536. //
  1537. DmAssert( lstrlen(szPath) + lstrlen(TEXT("\\ntuser.pol")) < MAX_PATH );
  1538. hr = StringCchCat (szPath, sizeof(szPath)/sizeof(WCHAR), TEXT("\\ntuser.pol"));
  1539. if (FAILED(hr)) {
  1540. xe = HRESULT_CODE(hr);
  1541. goto ProcessGPORegistryPolicy_Exit;
  1542. }
  1543. //
  1544. // Delete any existing policies
  1545. //
  1546. if (!ResetPolicies (lpGPOInfo, szPath)) {
  1547. xe = GetLastError();
  1548. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ResetPolicies failed.")));
  1549. // couldn't undo the values set in local ntuser.pol
  1550. // seems like the best we can do is abandon cleanup and
  1551. // and apply new policies.
  1552. // If we return here, the user has a better chance of not
  1553. // getting tattooed though...
  1554. // event is already logged
  1555. }
  1556. //
  1557. // Delete the old archive file
  1558. //
  1559. SetFileAttributes (szPath, FILE_ATTRIBUTE_NORMAL);
  1560. DeleteFile (szPath);
  1561. //
  1562. // Recreate the archive file
  1563. //
  1564. hFile = CreateFile (szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1565. FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_FLAG_SEQUENTIAL_SCAN,
  1566. NULL);
  1567. if (hFile == INVALID_HANDLE_VALUE)
  1568. {
  1569. xe = GetLastError();
  1570. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to create archive file with %d"),
  1571. GetLastError()));
  1572. goto ProcessGPORegistryPolicy_Exit;
  1573. }
  1574. //
  1575. // Set the header information in the archive file
  1576. //
  1577. dwTemp = REGFILE_SIGNATURE;
  1578. if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) ||
  1579. dwBytesWritten != sizeof(dwTemp))
  1580. {
  1581. xe = GetLastError();
  1582. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to write signature with %d"),
  1583. GetLastError()));
  1584. CloseHandle (hFile);
  1585. goto ProcessGPORegistryPolicy_Exit;
  1586. }
  1587. dwTemp = REGISTRY_FILE_VERSION;
  1588. if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) ||
  1589. dwBytesWritten != sizeof(dwTemp))
  1590. {
  1591. xe = GetLastError();
  1592. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to write version number with %d"),
  1593. GetLastError()));
  1594. CloseHandle (hFile);
  1595. goto ProcessGPORegistryPolicy_Exit;
  1596. }
  1597. if ( lpGPOInfo->pWbemServices ) {
  1598. //
  1599. // If Rsop logging is enabled, setup hash table
  1600. //
  1601. pHashTable = AllocHashTable();
  1602. if ( pHashTable == NULL ) {
  1603. CloseHandle (hFile);
  1604. *phrRsopLogging = HRESULT_FROM_WIN32(GetLastError());
  1605. xe = GetLastError();
  1606. goto ProcessGPORegistryPolicy_Exit;
  1607. }
  1608. }
  1609. //
  1610. // Now loop through the GPOs applying the registry.pol files
  1611. //
  1612. lpGPO = pChangedGPOList;
  1613. while ( lpGPO ) {
  1614. //
  1615. // Add the source GPO comment
  1616. //
  1617. DWORD dwCommentLength = lstrlen(lpGPO->lpDisplayName) + 25;
  1618. lpGPOComment = (LPTSTR) LocalAlloc (LPTR, (dwCommentLength) * sizeof(TCHAR));
  1619. if (lpGPOComment) {
  1620. hr = StringCchCopy (szKeyName, ARRAYSIZE(szKeyName), TEXT("Software\\Policies\\Microsoft\\Windows\\Group Policy Objects\\"));
  1621. ASSERT(SUCCEEDED(hr));
  1622. hr = StringCchCat (szKeyName, ARRAYSIZE(szKeyName), lpGPO->szGPOName);
  1623. ASSERT(SUCCEEDED(hr));
  1624. hr = StringCchCopy (lpGPOComment, dwCommentLength, TEXT("**Comment:GPO Name: "));
  1625. ASSERT(SUCCEEDED(hr));
  1626. hr = StringCchCat (lpGPOComment, dwCommentLength, lpGPO->lpDisplayName);
  1627. ASSERT(SUCCEEDED(hr));
  1628. if (!ArchiveRegistryValue(hFile, szKeyName, lpGPOComment, REG_SZ, 0, NULL)) {
  1629. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ArchiveRegistryValue returned false.")));
  1630. }
  1631. LocalFree (lpGPOComment);
  1632. }
  1633. //
  1634. // Build the path to registry.pol
  1635. //
  1636. DmAssert( lstrlen(lpGPO->lpFileSysPath) + lstrlen(c_szRegistryPol) + 1 < MAX_PATH );
  1637. hr = StringCchCopy (szBuffer, sizeof(szBuffer)/sizeof(WCHAR), lpGPO->lpFileSysPath);
  1638. if (FAILED(hr)) {
  1639. xe = HRESULT_CODE(hr);
  1640. CloseHandle (hFile);
  1641. FreeHashTable( pHashTable );
  1642. goto ProcessGPORegistryPolicy_Exit;
  1643. }
  1644. lpEnd = CheckSlash (szBuffer);
  1645. hr = StringCchCopy (lpEnd, sizeof(szBuffer)/sizeof(WCHAR) - (lpEnd - szBuffer), c_szRegistryPol);
  1646. if (FAILED(hr)) {
  1647. xe = ERROR_INSUFFICIENT_BUFFER;
  1648. CloseHandle (hFile);
  1649. FreeHashTable( pHashTable );
  1650. goto ProcessGPORegistryPolicy_Exit;
  1651. }
  1652. if (!ParseRegistryFile (lpGPOInfo, szBuffer, SetRegistryValue, hFile,
  1653. lpGPO->lpDSPath, lpGPO->lpLink, pHashTable, FALSE )) {
  1654. xe = GetLastError();
  1655. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ParseRegistryFile failed.")));
  1656. CloseHandle (hFile);
  1657. FreeHashTable( pHashTable );
  1658. // no logging is done in any case
  1659. goto ProcessGPORegistryPolicy_Exit;
  1660. }
  1661. if ( lpGPOInfo->pWbemServices ) {
  1662. //
  1663. // Log Adm data
  1664. //
  1665. HANDLE hFindFile;
  1666. WIN32_FILE_ATTRIBUTE_DATA attrData;
  1667. DWORD dwFilePathSize = lstrlen( lpGPO->lpFileSysPath );
  1668. TCHAR szComputerName[3*MAX_COMPUTERNAME_LENGTH + 1];
  1669. DWORD dwSize;
  1670. dwSize = 3*MAX_COMPUTERNAME_LENGTH + 1;
  1671. if (!GetComputerName(szComputerName, &dwSize)) {
  1672. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Couldn't get the computer Name with error %d."), GetLastError()));
  1673. szComputerName[0] = TEXT('\0');
  1674. }
  1675. dwSize = dwFilePathSize + MAX_PATH;
  1676. WCHAR *pwszEnd;
  1677. WCHAR *pwszFile = (WCHAR *) LocalAlloc( LPTR, dwSize * sizeof(WCHAR) );
  1678. if ( pwszFile == 0 ) {
  1679. xe = GetLastError();
  1680. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: ParseRegistryFile failed to allocate memory.")));
  1681. CloseHandle (hFile);
  1682. FreeHashTable( pHashTable );
  1683. // no logging is done in any case
  1684. goto ProcessGPORegistryPolicy_Exit;
  1685. }
  1686. hr = StringCchCopy( pwszFile, dwSize, lpGPO->lpFileSysPath );
  1687. ASSERT(SUCCEEDED(hr));
  1688. //
  1689. // Strip off trailing 'machine' or 'user'
  1690. //
  1691. pwszEnd = pwszFile + lstrlen( pwszFile );
  1692. if ( lpGPOInfo->dwFlags & GP_MACHINE )
  1693. pwszEnd -= 7; // length of "machine"
  1694. else
  1695. pwszEnd -= 4; // length of "user"
  1696. hr = StringCchCopy( pwszEnd, dwSize - (pwszEnd - pwszFile), L"Adm\\*.adm");
  1697. ASSERT(SUCCEEDED(hr));
  1698. //
  1699. // Remember end point so that the actual Adm filename can be
  1700. // easily concatenated.
  1701. //
  1702. pwszEnd = pwszEnd + lstrlen( L"Adm\\" );
  1703. //
  1704. // Enumerate all Adm files
  1705. //
  1706. hFindFile = FindFirstFile( pwszFile, &findData);
  1707. if ( hFindFile != INVALID_HANDLE_VALUE )
  1708. {
  1709. do
  1710. {
  1711. if ( !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1712. {
  1713. DmAssert( dwFilePathSize + lstrlen(findData.cFileName) + lstrlen( L"\\Adm\\" ) < dwSize );
  1714. hr = StringCchCopy( pwszEnd, dwSize - (pwszEnd - pwszFile), findData.cFileName);
  1715. if (FAILED(hr)) {
  1716. if (pHashTable->hrError == S_OK)
  1717. pHashTable->hrError = ERROR_INSUFFICIENT_BUFFER;
  1718. }
  1719. else {
  1720. ZeroMemory (&attrData, sizeof(attrData));
  1721. if ( GetFileAttributesEx (pwszFile, GetFileExInfoStandard, &attrData ) != 0 ) {
  1722. if ( !AddAdmFile( pwszFile, lpGPO->lpDSPath, &attrData.ftLastWriteTime,
  1723. szComputerName, &pAdmFileCache ) ) {
  1724. DebugMsg((DM_WARNING,
  1725. TEXT("ProcessGPORegistryPolicy: AddAdmFile failed.")));
  1726. if (pHashTable->hrError == S_OK)
  1727. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1728. }
  1729. }
  1730. }
  1731. } // if findData & file_attr_dir
  1732. } while ( FindNextFile(hFindFile, &findData) );// do
  1733. FindClose(hFindFile);
  1734. } // if hfindfile
  1735. LocalFree( pwszFile );
  1736. } // if rsoploggingenabled
  1737. lpGPO = lpGPO->pNext;
  1738. }
  1739. //
  1740. // Log registry data to Cimom database
  1741. //
  1742. if ( lpGPOInfo->pWbemServices ) {
  1743. if ( ! LogRegistryRsopData( lpGPOInfo->dwFlags, pHashTable, lpGPOInfo->pWbemServices ) ) {
  1744. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Registry Rsop data. Continuing.")));
  1745. if (pHashTable->hrError == S_OK)
  1746. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1747. }
  1748. if ( ! LogAdmRsopData( pAdmFileCache, lpGPOInfo->pWbemServices ) ) {
  1749. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Adm Rsop data. Continuing.")));
  1750. if (pHashTable->hrError == S_OK)
  1751. pHashTable->hrError = HRESULT_FROM_WIN32(GetLastError());
  1752. }
  1753. *phrRsopLogging = pHashTable->hrError;
  1754. }
  1755. FreeHashTable( pHashTable );
  1756. FreeAdmFileCache( pAdmFileCache );
  1757. CloseHandle (hFile);
  1758. #if 0
  1759. //
  1760. // Set the security on the file
  1761. //
  1762. if (!MakeFileSecure (szPath, 0)) {
  1763. DebugMsg((DM_WARNING, TEXT("ProcessGPORegistryPolicy: Failed to set security on the group policy registry file with %d"),
  1764. GetLastError()));
  1765. }
  1766. #endif
  1767. bStatus = TRUE;
  1768. ProcessGPORegistryPolicy_Exit:
  1769. if ( hRegistrySection )
  1770. {
  1771. LeaveCriticalPolicySection( hRegistrySection );
  1772. }
  1773. return bStatus;
  1774. }
  1775. //*************************************************************
  1776. //
  1777. // AddAdmFile()
  1778. //
  1779. // Purpose: Prepends to list of Adm files
  1780. //
  1781. // Parameters: pwszFile - File path
  1782. // pwszGPO - Gpo
  1783. // pftWrite - Last write time
  1784. // ppAdmFileCache - List of Adm files processed
  1785. //
  1786. //*************************************************************
  1787. BOOL AddAdmFile( WCHAR *pwszFile, WCHAR *pwszGPO, FILETIME *pftWrite, WCHAR *szComputerName,
  1788. ADMFILEINFO **ppAdmFileCache )
  1789. {
  1790. XPtrLF<WCHAR> xszLongPath;
  1791. LPTSTR pwszUNCPath;
  1792. DebugMsg((DM_VERBOSE, TEXT("AllocAdmFileInfo: Adding File name <%s> to the Adm list."), pwszFile));
  1793. if ((szComputerName) && (*szComputerName) && (!IsUNCPath(pwszFile))) {
  1794. xszLongPath = MakePathUNC(pwszFile, szComputerName);
  1795. if (!xszLongPath) {
  1796. DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to Make the path UNC with error %d."), GetLastError()));
  1797. return FALSE;
  1798. }
  1799. pwszUNCPath = xszLongPath;
  1800. }
  1801. else
  1802. pwszUNCPath = pwszFile;
  1803. ADMFILEINFO *pAdmInfo = AllocAdmFileInfo( pwszUNCPath, pwszGPO, pftWrite );
  1804. if ( pAdmInfo == NULL )
  1805. return FALSE;
  1806. pAdmInfo->pNext = *ppAdmFileCache;
  1807. *ppAdmFileCache = pAdmInfo;
  1808. return TRUE;
  1809. }
  1810. //*************************************************************
  1811. //
  1812. // FreeAdmFileCache()
  1813. //
  1814. // Purpose: Frees Adm File list
  1815. //
  1816. // Parameters: pAdmFileCache - List of Adm files to free
  1817. //
  1818. //
  1819. //*************************************************************
  1820. void FreeAdmFileCache( ADMFILEINFO *pAdmFileCache )
  1821. {
  1822. ADMFILEINFO *pNext;
  1823. while ( pAdmFileCache ) {
  1824. pNext = pAdmFileCache->pNext;
  1825. FreeAdmFileInfo( pAdmFileCache );
  1826. pAdmFileCache = pNext;
  1827. }
  1828. }
  1829. //*************************************************************
  1830. //
  1831. // AllocAdmFileInfo()
  1832. //
  1833. // Purpose: Allocates a new struct for ADMFILEINFO
  1834. //
  1835. // Parameters: pwszFile - File name
  1836. // pwszGPO - Gpo
  1837. // pftWrite - Last write time
  1838. //
  1839. //
  1840. //*************************************************************
  1841. ADMFILEINFO * AllocAdmFileInfo( WCHAR *pwszFile, WCHAR *pwszGPO, FILETIME *pftWrite )
  1842. {
  1843. XLastError xe;
  1844. HRESULT hr = S_OK;
  1845. ADMFILEINFO *pAdmFileInfo = (ADMFILEINFO *) LocalAlloc( LPTR, sizeof(ADMFILEINFO) );
  1846. if ( pAdmFileInfo == NULL ) {
  1847. DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
  1848. return NULL;
  1849. }
  1850. pAdmFileInfo->pwszFile = (WCHAR *) LocalAlloc( LPTR, (lstrlen(pwszFile) + 1) * sizeof(WCHAR) );
  1851. if ( pAdmFileInfo->pwszFile == NULL ) {
  1852. xe = GetLastError();
  1853. DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
  1854. LocalFree( pAdmFileInfo );
  1855. return NULL;
  1856. }
  1857. pAdmFileInfo->pwszGPO = (WCHAR *) LocalAlloc( LPTR, (lstrlen(pwszGPO) + 1) * sizeof(WCHAR) );
  1858. if ( pAdmFileInfo->pwszGPO == NULL ) {
  1859. xe = GetLastError();
  1860. DebugMsg((DM_WARNING, TEXT("AllocAdmFileInfo: Failed to allocate memory.")));
  1861. LocalFree( pAdmFileInfo->pwszFile );
  1862. LocalFree( pAdmFileInfo );
  1863. return NULL;
  1864. }
  1865. hr = StringCchCopy( pAdmFileInfo->pwszFile, lstrlen(pwszFile) + 1, pwszFile );
  1866. ASSERT(SUCCEEDED(hr));
  1867. hr = StringCchCopy( pAdmFileInfo->pwszGPO, lstrlen(pwszGPO) + 1, pwszGPO );
  1868. ASSERT(SUCCEEDED(hr));
  1869. pAdmFileInfo->ftWrite = *pftWrite;
  1870. return pAdmFileInfo;
  1871. }
  1872. //*************************************************************
  1873. //
  1874. // FreeAdmFileInfo()
  1875. //
  1876. // Purpose: Deletes a ADMFILEINFO struct
  1877. //
  1878. // Parameters: pAdmFileInfo - Struct to delete
  1879. // pftWrite - Last write time
  1880. //
  1881. //
  1882. //*************************************************************
  1883. void FreeAdmFileInfo( ADMFILEINFO *pAdmFileInfo )
  1884. {
  1885. if ( pAdmFileInfo ) {
  1886. LocalFree( pAdmFileInfo->pwszFile );
  1887. LocalFree( pAdmFileInfo->pwszGPO );
  1888. LocalFree( pAdmFileInfo );
  1889. }
  1890. }