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

4308 lines
134 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Support
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "gphdr.h"
  11. //
  12. // DS Object class types
  13. //
  14. TCHAR szDSClassAny[] = TEXT("(objectClass=*)");
  15. TCHAR szDSClassGPO[] = TEXT("groupPolicyContainer");
  16. TCHAR szDSClassSite[] = TEXT("site");
  17. TCHAR szDSClassDomain[] = TEXT("domainDNS");
  18. TCHAR szDSClassOU[] = TEXT("organizationalUnit");
  19. TCHAR szObjectClass[] = TEXT("objectClass");
  20. TCHAR wszKerberos[] = TEXT("Kerberos");
  21. //
  22. // Global flags for Gpo shutdown processing. These are accessed outside
  23. // the lock because its value is either 0 or 1. Even if there is a race,
  24. // all it means is that shutdown will start one iteration later.
  25. //
  26. BOOL g_bStopMachGPOProcessing = FALSE;
  27. BOOL g_bStopUserGPOProcessing = FALSE;
  28. //
  29. // Critical section for handling concurrent, asynchronous completion
  30. //
  31. CRITICAL_SECTION g_GPOCS;
  32. //
  33. // Global pointers for maintaining asynchronous completion context
  34. //
  35. LPGPINFOHANDLE g_pMachGPInfo = 0;
  36. LPGPINFOHANDLE g_pUserGPInfo = 0;
  37. //
  38. // Status UI critical section, callback, and proto-types
  39. //
  40. CRITICAL_SECTION g_StatusCallbackCS;
  41. PFNSTATUSMESSAGECALLBACK g_pStatusMessageCallback = NULL;
  42. DWORD WINAPI
  43. SetPreviousFgPolicyRefreshInfo( LPWSTR szUserSid,
  44. FgPolicyRefreshInfo info );
  45. DWORD WINAPI
  46. SetNextFgPolicyRefreshInfo( LPWSTR szUserSid,
  47. FgPolicyRefreshInfo info );
  48. DWORD WINAPI
  49. GetCurrentFgPolicyRefreshInfo( LPWSTR szUserSid,
  50. FgPolicyRefreshInfo* pInfo );
  51. //*************************************************************
  52. //
  53. // ApplyGroupPolicy()
  54. //
  55. // Purpose: Processes group policy
  56. //
  57. // Parameters: dwFlags - Processing flags
  58. // hToken - Token (user or machine)
  59. // hEvent - Termination event for background thread
  60. // hKeyRoot - Root registry key (HKCU or HKLM)
  61. // pStatusCallback - Callback function for display status messages
  62. //
  63. // Return: Thread handle if successful
  64. // NULL if an error occurs
  65. //
  66. //*************************************************************
  67. HANDLE WINAPI ApplyGroupPolicy (DWORD dwFlags, HANDLE hToken, HANDLE hEvent,
  68. HKEY hKeyRoot, PFNSTATUSMESSAGECALLBACK pStatusCallback)
  69. {
  70. HANDLE hThread = NULL;
  71. DWORD dwThreadID;
  72. LPGPOINFO lpGPOInfo = NULL;
  73. SECURITY_ATTRIBUTES sa;
  74. OLE32_API *pOle32Api = NULL;
  75. XPtrLF<SECURITY_DESCRIPTOR> xsd;
  76. CSecDesc Csd;
  77. XLastError xe;
  78. //
  79. // Verbose output
  80. //
  81. DebugMsg((DM_VERBOSE, TEXT("ApplyGroupPolicy: Entering. Flags = %x"), dwFlags));
  82. //
  83. // Save the status UI callback function
  84. //
  85. EnterCriticalSection (&g_StatusCallbackCS);
  86. g_pStatusMessageCallback = pStatusCallback;
  87. LeaveCriticalSection (&g_StatusCallbackCS);
  88. //
  89. // Allocate a GPOInfo structure to work with.
  90. //
  91. lpGPOInfo = (LPGPOINFO) LocalAlloc (LPTR, sizeof(GPOINFO));
  92. if (!lpGPOInfo) {
  93. xe = GetLastError();
  94. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: Failed to alloc lpGPOInfo (%d)."),
  95. GetLastError()));
  96. CEvents ev(TRUE, EVENT_FAILED_ALLOCATION);
  97. ev.AddArgWin32Error(GetLastError()); ev.Report();
  98. goto Exit;
  99. }
  100. lpGPOInfo->dwFlags = dwFlags;
  101. lpGPOInfo->hToken = hToken;
  102. lpGPOInfo->hEvent = hEvent;
  103. lpGPOInfo->hKeyRoot = hKeyRoot;
  104. if (dwFlags & GP_MACHINE) {
  105. lpGPOInfo->pStatusCallback = MachinePolicyCallback;
  106. } else {
  107. lpGPOInfo->pStatusCallback = UserPolicyCallback;
  108. }
  109. //
  110. // Create an event so other processes can trigger policy
  111. // to be applied immediately
  112. //
  113. Csd.AddLocalSystem();
  114. Csd.AddAdministrators();
  115. if (!(dwFlags & GP_MACHINE)) {
  116. //
  117. // User events
  118. //
  119. XPtrLF<SID> xSid = (SID *)GetUserSid(hToken);
  120. if (!xSid) {
  121. xe = GetLastError();
  122. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: Failed to find user Sid %d"),
  123. GetLastError()));
  124. CEvents ev(TRUE, EVENT_FAILED_SETACLS);
  125. ev.AddArgWin32Error(GetLastError()); ev.Report();
  126. goto Exit;
  127. }
  128. Csd.AddSid((SID *)xSid,
  129. GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
  130. }
  131. else {
  132. //
  133. // Machine Events
  134. // Allow Everyone Access by default but can be overridden by policy or preference
  135. //
  136. DWORD dwUsersDenied = 0;
  137. HKEY hSubKey;
  138. DWORD dwType=0, dwSize=0;
  139. //
  140. // Check for a preference
  141. //
  142. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0, KEY_READ,
  143. &hSubKey) == ERROR_SUCCESS) {
  144. dwSize = sizeof(dwUsersDenied);
  145. RegQueryValueEx(hSubKey, MACHPOLICY_DENY_USERS, NULL, &dwType,
  146. (LPBYTE) &dwUsersDenied, &dwSize);
  147. RegCloseKey(hSubKey);
  148. }
  149. //
  150. // Check for a policy
  151. //
  152. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0, KEY_READ,
  153. &hSubKey) == ERROR_SUCCESS) {
  154. dwSize = sizeof(dwUsersDenied);
  155. RegQueryValueEx(hSubKey, MACHPOLICY_DENY_USERS, NULL, &dwType,
  156. (LPBYTE) &dwUsersDenied, &dwSize);
  157. RegCloseKey(hSubKey);
  158. }
  159. if (!dwUsersDenied) {
  160. Csd.AddAuthUsers(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
  161. }
  162. }
  163. xsd = Csd.MakeSD();
  164. if (!xsd) {
  165. xe = GetLastError();
  166. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: Failed to create Security Descriptor with %d"),
  167. GetLastError()));
  168. CEvents ev(TRUE, EVENT_FAILED_SETACLS);
  169. ev.AddArgWin32Error(GetLastError()); ev.Report();
  170. goto Exit;
  171. }
  172. sa.lpSecurityDescriptor = (SECURITY_DESCRIPTOR *)xsd;
  173. sa.bInheritHandle = FALSE;
  174. sa.nLength = sizeof(sa);
  175. lpGPOInfo->hTriggerEvent = CreateEvent (&sa, FALSE, FALSE,
  176. (dwFlags & GP_MACHINE) ?
  177. MACHINE_POLICY_REFRESH_EVENT : USER_POLICY_REFRESH_EVENT);
  178. lpGPOInfo->hForceTriggerEvent = CreateEvent (&sa, FALSE, FALSE,
  179. (dwFlags & GP_MACHINE) ?
  180. MACHINE_POLICY_FORCE_REFRESH_EVENT : USER_POLICY_FORCE_REFRESH_EVENT);
  181. //
  182. // Create the notification events.
  183. // These should already be created in InitializePolicyProcessing..
  184. //
  185. lpGPOInfo->hNotifyEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE,
  186. (dwFlags & GP_MACHINE) ?
  187. MACHINE_POLICY_APPLIED_EVENT : USER_POLICY_APPLIED_EVENT);
  188. //
  189. // Create the needfg event
  190. //
  191. lpGPOInfo->hNeedFGEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE,
  192. (dwFlags & GP_MACHINE) ?
  193. MACHINE_POLICY_REFRESH_NEEDFG_EVENT :
  194. USER_POLICY_REFRESH_NEEDFG_EVENT);
  195. //
  196. // Create the done event
  197. //
  198. lpGPOInfo->hDoneEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE,
  199. (dwFlags & GP_MACHINE) ?
  200. MACHINE_POLICY_DONE_EVENT :
  201. USER_POLICY_DONE_EVENT);
  202. //
  203. // Initilialize shutdown gpo processing support
  204. //
  205. if ( dwFlags & GP_MACHINE )
  206. g_bStopMachGPOProcessing = FALSE;
  207. else
  208. g_bStopUserGPOProcessing = FALSE;
  209. pOle32Api = LoadOle32Api();
  210. if ( pOle32Api == NULL ) {
  211. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: Failed to load ole32.dll.") ));
  212. }
  213. else {
  214. HRESULT hr = pOle32Api->pfnCoInitializeEx( NULL, COINIT_MULTITHREADED );
  215. if ( SUCCEEDED(hr) ) {
  216. lpGPOInfo->bFGCoInitialized = TRUE;
  217. }
  218. else {
  219. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: CoInitializeEx failed with 0x%x."), hr ));
  220. }
  221. }
  222. if ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND )
  223. {
  224. lpGPOInfo->dwFlags |= GP_BACKGROUND_THREAD;
  225. }
  226. //
  227. // Process the GPOs
  228. //
  229. ProcessGPOs(lpGPOInfo);
  230. if ( lpGPOInfo->bFGCoInitialized ) {
  231. pOle32Api->pfnCoUnInitialize();
  232. lpGPOInfo->bFGCoInitialized = FALSE;
  233. }
  234. if ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND )
  235. {
  236. lpGPOInfo->dwFlags &= ~GP_ASYNC_FOREGROUND;
  237. lpGPOInfo->dwFlags &= ~GP_BACKGROUND_THREAD;
  238. }
  239. //
  240. // If requested, create a background thread to keep updating
  241. // the profile from the gpos
  242. //
  243. if (lpGPOInfo->dwFlags & GP_BACKGROUND_REFRESH) {
  244. //
  245. // Create a thread which sleeps and processes GPOs
  246. //
  247. hThread = CreateThread (NULL, 64*1024, // 64k as the stack size
  248. (LPTHREAD_START_ROUTINE) GPOThread,
  249. (LPVOID) lpGPOInfo, CREATE_SUSPENDED, &dwThreadID);
  250. if (!hThread) {
  251. xe = GetLastError();
  252. DebugMsg((DM_WARNING, TEXT("ApplyGroupPolicy: Failed to create background thread (%d)."),
  253. GetLastError()));
  254. goto Exit;
  255. }
  256. SetThreadPriority (hThread, THREAD_PRIORITY_IDLE);
  257. lpGPOInfo->pStatusCallback = NULL;
  258. ResumeThread (hThread);
  259. //
  260. // Reset the status UI callback function
  261. //
  262. EnterCriticalSection (&g_StatusCallbackCS);
  263. g_pStatusMessageCallback = NULL;
  264. LeaveCriticalSection (&g_StatusCallbackCS);
  265. DebugMsg((DM_VERBOSE, TEXT("ApplyGroupPolicy: Leaving successfully.")));
  266. return hThread;
  267. }
  268. DebugMsg((DM_VERBOSE, TEXT("ApplyGroupPolicy: Background refresh not requested. Leaving successfully.")));
  269. hThread = (HANDLE) 1;
  270. Exit:
  271. EnterCriticalSection( &g_GPOCS );
  272. if ( dwFlags & GP_MACHINE ) {
  273. if ( g_pMachGPInfo )
  274. LocalFree( g_pMachGPInfo );
  275. g_pMachGPInfo = 0;
  276. } else {
  277. if ( g_pUserGPInfo )
  278. LocalFree( g_pUserGPInfo );
  279. g_pUserGPInfo = 0;
  280. }
  281. LeaveCriticalSection( &g_GPOCS );
  282. if (lpGPOInfo) {
  283. if (lpGPOInfo->hTriggerEvent) {
  284. CloseHandle (lpGPOInfo->hTriggerEvent);
  285. }
  286. if (lpGPOInfo->hForceTriggerEvent) {
  287. CloseHandle (lpGPOInfo->hForceTriggerEvent);
  288. }
  289. if (lpGPOInfo->hNotifyEvent) {
  290. CloseHandle (lpGPOInfo->hNotifyEvent);
  291. }
  292. if (lpGPOInfo->hNeedFGEvent) {
  293. CloseHandle (lpGPOInfo->hNeedFGEvent);
  294. }
  295. if (lpGPOInfo->lpwszSidUser)
  296. DeleteSidString( lpGPOInfo->lpwszSidUser );
  297. if (lpGPOInfo->szName)
  298. LocalFree(lpGPOInfo->szName);
  299. if (lpGPOInfo->szTargetName)
  300. LocalFree(lpGPOInfo->szTargetName);
  301. LocalFree (lpGPOInfo);
  302. }
  303. //
  304. // Reset the status UI callback function
  305. //
  306. EnterCriticalSection (&g_StatusCallbackCS);
  307. g_pStatusMessageCallback = NULL;
  308. LeaveCriticalSection (&g_StatusCallbackCS);
  309. return hThread;
  310. }
  311. extern "C" void ProfileProcessGPOs( void* );
  312. //*************************************************************
  313. //
  314. // GPOThread()
  315. //
  316. // Purpose: Background thread for GPO processing.
  317. //
  318. // Parameters: lpGPOInfo - GPO info
  319. //
  320. // Return: 0
  321. //
  322. //*************************************************************
  323. DWORD WINAPI GPOThread (LPGPOINFO lpGPOInfo)
  324. {
  325. HINSTANCE hInst;
  326. HKEY hKey;
  327. HANDLE hHandles[4] = {NULL, NULL, NULL, NULL};
  328. DWORD dwType, dwSize, dwResult;
  329. DWORD dwTimeout, dwOffset;
  330. BOOL bSetBkGndFlag, bForceBkGndFlag;
  331. TCHAR szEventName[60];
  332. LARGE_INTEGER DueTime;
  333. HRESULT hr;
  334. ULONG TTLMinutes;
  335. XLastError xe;
  336. OLE32_API *pOle32Api = LoadOle32Api();
  337. hInst = LoadLibrary (TEXT("userenv.dll"));
  338. hHandles[0] = lpGPOInfo->hEvent;
  339. hHandles[1] = lpGPOInfo->hTriggerEvent;
  340. hHandles[2] = lpGPOInfo->hForceTriggerEvent;
  341. for (;;)
  342. {
  343. //
  344. // Initialize
  345. //
  346. bForceBkGndFlag = FALSE;
  347. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  348. if (lpGPOInfo->iMachineRole == 3) {
  349. dwTimeout = GP_DEFAULT_REFRESH_RATE_DC;
  350. dwOffset = GP_DEFAULT_REFRESH_RATE_OFFSET_DC;
  351. } else {
  352. dwTimeout = GP_DEFAULT_REFRESH_RATE;
  353. dwOffset = GP_DEFAULT_REFRESH_RATE_OFFSET;
  354. }
  355. } else {
  356. dwTimeout = GP_DEFAULT_REFRESH_RATE;
  357. dwOffset = GP_DEFAULT_REFRESH_RATE_OFFSET;
  358. }
  359. //
  360. // Query for the refresh timer value and max offset
  361. //
  362. if (RegOpenKeyEx (lpGPOInfo->hKeyRoot,
  363. SYSTEM_POLICIES_KEY,
  364. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  365. if ((lpGPOInfo->iMachineRole == 3) && (lpGPOInfo->dwFlags & GP_MACHINE)) {
  366. dwSize = sizeof(dwTimeout);
  367. RegQueryValueEx (hKey,
  368. TEXT("GroupPolicyRefreshTimeDC"),
  369. NULL,
  370. &dwType,
  371. (LPBYTE) &dwTimeout,
  372. &dwSize);
  373. dwSize = sizeof(dwOffset);
  374. RegQueryValueEx (hKey,
  375. TEXT("GroupPolicyRefreshTimeOffsetDC"),
  376. NULL,
  377. &dwType,
  378. (LPBYTE) &dwOffset,
  379. &dwSize);
  380. } else {
  381. dwSize = sizeof(dwTimeout);
  382. RegQueryValueEx (hKey,
  383. TEXT("GroupPolicyRefreshTime"),
  384. NULL,
  385. &dwType,
  386. (LPBYTE) &dwTimeout,
  387. &dwSize);
  388. dwSize = sizeof(dwOffset);
  389. RegQueryValueEx (hKey,
  390. TEXT("GroupPolicyRefreshTimeOffset"),
  391. NULL,
  392. &dwType,
  393. (LPBYTE) &dwOffset,
  394. &dwSize);
  395. }
  396. RegCloseKey (hKey);
  397. }
  398. //
  399. // Limit the timeout to once every 64800 minutes (45 days)
  400. //
  401. if (dwTimeout >= 64800) {
  402. dwTimeout = 64800;
  403. }
  404. //
  405. // Convert seconds to milliseconds
  406. //
  407. dwTimeout = dwTimeout * 60 * 1000;
  408. //
  409. // Limit the offset to 1440 minutes (24 hours)
  410. //
  411. if (dwOffset >= 1440) {
  412. dwOffset = 1440;
  413. }
  414. //
  415. // Special case 0 milliseconds to be 7 seconds
  416. //
  417. if (dwTimeout == 0) {
  418. dwTimeout = 7000;
  419. } else {
  420. //
  421. // If there is an offset, pick a random number
  422. // from 0 to dwOffset and then add it to the timeout
  423. //
  424. if (dwOffset) {
  425. dwOffset = GetTickCount() % dwOffset;
  426. dwOffset = dwOffset * 60 * 1000;
  427. dwTimeout += dwOffset;
  428. }
  429. }
  430. //
  431. // Setup the timer
  432. //
  433. if (dwTimeout >= 60000) {
  434. DebugMsg((DM_VERBOSE, TEXT("GPOThread: Next refresh will happen in %d minutes"),
  435. ((dwTimeout / 1000) / 60)));
  436. } else {
  437. DebugMsg((DM_VERBOSE, TEXT("GPOThread: Next refresh will happen in %d seconds"),
  438. (dwTimeout / 1000)));
  439. }
  440. wsprintf (szEventName, TEXT("userenv: refresh timer for %d:%d"),
  441. GetCurrentProcessId(), GetCurrentThreadId());
  442. hHandles[3] = CreateWaitableTimer (NULL, TRUE, szEventName);
  443. if (hHandles[3] == NULL) {
  444. xe = GetLastError();
  445. DebugMsg((DM_WARNING, TEXT("GPOThread: CreateWaitableTimer failed with error %d"),
  446. GetLastError()));
  447. CEvents ev(TRUE, EVENT_FAILED_TIMER);
  448. ev.AddArg( TEXT("CreateWaitableTimer")); ev.AddArgWin32Error(GetLastError()); ev.Report();
  449. break;
  450. }
  451. DueTime.QuadPart = UInt32x32To64(10000, dwTimeout);
  452. DueTime.QuadPart *= -1;
  453. if (!SetWaitableTimer (hHandles[3], &DueTime, 0, NULL, 0, FALSE)) {
  454. xe = GetLastError();
  455. DebugMsg((DM_WARNING, TEXT("GPOThread: Failed to set timer with error %d"),
  456. GetLastError()));
  457. CEvents ev(TRUE, EVENT_FAILED_TIMER);
  458. ev.AddArg(TEXT("SetWaitableTimer")); ev.AddArgWin32Error(GetLastError()); ev.Report();
  459. break;
  460. }
  461. dwResult = WaitForMultipleObjects( 4, hHandles, FALSE, INFINITE );
  462. if ( (dwResult - WAIT_OBJECT_0) == 0 )
  463. {
  464. //
  465. // for machine policy thread, this is a shutdown.
  466. // for user policy thread, this is a logoff.
  467. //
  468. goto ExitLoop;
  469. }
  470. else if ( (dwResult - WAIT_OBJECT_0) == 2 ) {
  471. bForceBkGndFlag = TRUE;
  472. }
  473. else if ( dwResult == WAIT_FAILED )
  474. {
  475. xe = GetLastError();
  476. DebugMsg( ( DM_WARNING, L"GPOThread: MsgWaitForMultipleObjects with error %d", GetLastError() ) );
  477. CEvents ev(TRUE, EVENT_FAILED_TIMER);
  478. ev.AddArg(TEXT("WaitForMultipleObjects")); ev.AddArgWin32Error(GetLastError()); ev.Report();
  479. goto ExitLoop;
  480. }
  481. //
  482. // Check if we should set the background flag. We offer this
  483. // option for the test team's automation tests. They need to
  484. // simulate logon / boot policy without actually logging on or
  485. // booting the machine.
  486. //
  487. bSetBkGndFlag = TRUE;
  488. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  489. WINLOGON_KEY,
  490. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  491. dwSize = sizeof(bSetBkGndFlag);
  492. RegQueryValueEx (hKey,
  493. TEXT("SetGroupPolicyBackgroundFlag"),
  494. NULL,
  495. &dwType,
  496. (LPBYTE) &bSetBkGndFlag,
  497. &dwSize);
  498. RegCloseKey (hKey);
  499. }
  500. lpGPOInfo->dwFlags &= ~GP_REGPOLICY_CPANEL;
  501. lpGPOInfo->dwFlags &= ~GP_SLOW_LINK;
  502. lpGPOInfo->dwFlags &= ~GP_VERBOSE;
  503. lpGPOInfo->dwFlags &= ~GP_BACKGROUND_THREAD;
  504. lpGPOInfo->dwFlags &= ~GP_FORCED_REFRESH;
  505. //
  506. // In case of forced refresh flag, we override the extensions nobackground policy and prevent
  507. // it from getting skipped early on in the processing. We bypass the history logic and force
  508. // policy to be applied for extensions that do not care abt. whether they are run in the
  509. // foreground or background. for only foreground extensions we write a registry value saying
  510. // that the extension needs to override the history logic when they get applied in the foreground
  511. // next.
  512. // In addition we pulse the needfg event so that the calling app knows a reboot/relogon is needed
  513. // for application of fgonly extensions
  514. //
  515. if (bForceBkGndFlag) {
  516. lpGPOInfo->dwFlags |= GP_FORCED_REFRESH;
  517. }
  518. //
  519. // Set the background thread flag so components known
  520. // when they are being called from the background thread
  521. // vs the main thread.
  522. //
  523. if (bSetBkGndFlag) {
  524. lpGPOInfo->dwFlags |= GP_BACKGROUND_THREAD;
  525. }
  526. if ( !lpGPOInfo->bBGCoInitialized && pOle32Api != NULL ) {
  527. hr = pOle32Api->pfnCoInitializeEx( NULL, COINIT_MULTITHREADED );
  528. if ( SUCCEEDED(hr) ) {
  529. lpGPOInfo->bBGCoInitialized = TRUE;
  530. }
  531. }
  532. ProcessGPOs(lpGPOInfo);
  533. if ( lpGPOInfo->dwFlags & GP_MACHINE ) {
  534. //
  535. // Delete garbage-collectable namespaces under root\rsop that are
  536. // older than 1 week. We can have a policy to configure this time-to-live value.
  537. //
  538. TTLMinutes = 24 * 60;
  539. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  540. WINLOGON_KEY,
  541. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  542. dwSize = sizeof(TTLMinutes);
  543. RegQueryValueEx (hKey,
  544. TEXT("RSoPGarbageCollectionInterval"),
  545. NULL,
  546. &dwType,
  547. (LPBYTE) &TTLMinutes,
  548. &dwSize);
  549. RegCloseKey (hKey);
  550. }
  551. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  552. SYSTEM_POLICIES_KEY,
  553. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  554. dwSize = sizeof(TTLMinutes);
  555. RegQueryValueEx (hKey,
  556. TEXT("RSoPGarbageCollectionInterval"),
  557. NULL,
  558. &dwType,
  559. (LPBYTE) &TTLMinutes,
  560. &dwSize);
  561. RegCloseKey (hKey);
  562. }
  563. //
  564. // Synchronize with other processes that may be concurrently creating namespaces,
  565. // during diagnostic mode or planning mode data generation.
  566. //
  567. XCriticalPolicySection xCritSect( EnterCriticalPolicySection(TRUE ) );
  568. if ( xCritSect )
  569. GarbageCollectNamespaces(TTLMinutes);
  570. }
  571. CloseHandle (hHandles[3]);
  572. hHandles[3] = NULL;
  573. }
  574. ExitLoop:
  575. //
  576. // Cleanup
  577. //
  578. if (hHandles[3]) {
  579. CloseHandle (hHandles[3]);
  580. }
  581. if (lpGPOInfo->hTriggerEvent) {
  582. CloseHandle (lpGPOInfo->hTriggerEvent);
  583. }
  584. if (lpGPOInfo->hForceTriggerEvent) {
  585. CloseHandle (lpGPOInfo->hForceTriggerEvent);
  586. }
  587. if (lpGPOInfo->hNotifyEvent) {
  588. CloseHandle (lpGPOInfo->hNotifyEvent);
  589. }
  590. if (lpGPOInfo->hNeedFGEvent) {
  591. CloseHandle (lpGPOInfo->hNeedFGEvent);
  592. }
  593. if (lpGPOInfo->hDoneEvent) {
  594. CloseHandle (lpGPOInfo->hDoneEvent);
  595. }
  596. if ( lpGPOInfo->bBGCoInitialized ) {
  597. OLE32_API *pOle32Api = LoadOle32Api();
  598. if ( pOle32Api == NULL ) {
  599. DebugMsg((DM_WARNING, TEXT("GPOThread: Failed to load ole32.dll.") ));
  600. }
  601. else {
  602. pOle32Api->pfnCoUnInitialize();
  603. lpGPOInfo->bBGCoInitialized = FALSE;
  604. }
  605. }
  606. EnterCriticalSection( &g_GPOCS );
  607. if ( lpGPOInfo->dwFlags & GP_MACHINE ) {
  608. if ( g_pMachGPInfo )
  609. LocalFree( g_pMachGPInfo );
  610. g_pMachGPInfo = 0;
  611. } else {
  612. if ( g_pUserGPInfo )
  613. LocalFree( g_pUserGPInfo );
  614. g_pUserGPInfo = 0;
  615. }
  616. LeaveCriticalSection( &g_GPOCS );
  617. if (lpGPOInfo->lpwszSidUser)
  618. DeleteSidString( lpGPOInfo->lpwszSidUser );
  619. if (lpGPOInfo->szName)
  620. LocalFree(lpGPOInfo->szName);
  621. if (lpGPOInfo->szTargetName)
  622. LocalFree(lpGPOInfo->szTargetName);
  623. LocalFree (lpGPOInfo);
  624. FreeLibraryAndExitThread (hInst, 0);
  625. return 0;
  626. }
  627. //*************************************************************
  628. //
  629. // GPOExceptionFilter()
  630. //
  631. // Purpose: Exception filter when procssing GPO extensions
  632. //
  633. // Parameters: pExceptionPtrs - Pointer to exception pointer
  634. //
  635. // Returns: EXCEPTION_EXECUTE_HANDLER
  636. //
  637. //*************************************************************
  638. LONG GPOExceptionFilter( PEXCEPTION_POINTERS pExceptionPtrs )
  639. {
  640. PEXCEPTION_RECORD pExr = pExceptionPtrs->ExceptionRecord;
  641. PCONTEXT pCxr = pExceptionPtrs->ContextRecord;
  642. DebugMsg(( DM_WARNING, L"GPOExceptionFilter: Caught exception 0x%x, exr = 0x%x, cxr = 0x%x\n",
  643. pExr->ExceptionCode, pExr, pCxr ));
  644. DmAssert( ! L"Caught unhandled exception when processing group policy extension" );
  645. return EXCEPTION_EXECUTE_HANDLER;
  646. }
  647. BOOL WINAPI
  648. GetFgPolicySetting( HKEY hKeyRoot );
  649. //*************************************************************
  650. //
  651. // ProcessGPOs()
  652. //
  653. // Purpose: Processes GPOs
  654. //
  655. // Parameters: lpGPOInfo - GPO information
  656. //
  657. // Return: TRUE if successful
  658. // FALSE if an error occurs
  659. //
  660. //*************************************************************
  661. BOOL ProcessGPOs (LPGPOINFO lpGPOInfo)
  662. {
  663. BOOL bRetVal = FALSE;
  664. DWORD dwThreadID;
  665. HANDLE hThread;
  666. DWORD dwType, dwSize, dwResult;
  667. HKEY hKey;
  668. BOOL bResult;
  669. PDOMAIN_CONTROLLER_INFO pDCI = NULL;
  670. LPTSTR lpDomain = NULL;
  671. LPTSTR lpName = NULL;
  672. LPTSTR lpDomainDN = NULL;
  673. LPTSTR lpComputerName;
  674. PGROUP_POLICY_OBJECT lpGPO = NULL;
  675. PGROUP_POLICY_OBJECT lpGPOTemp;
  676. BOOL bAllSkipped;
  677. LPGPEXT lpExt;
  678. LPGPINFOHANDLE pGPHandle = NULL;
  679. ASYNCCOMPLETIONHANDLE pAsyncHandle = 0;
  680. HANDLE hOldToken;
  681. UINT uExtensionCount = 0;
  682. PNETAPI32_API pNetAPI32;
  683. DWORD dwUserPolicyMode = 0;
  684. DWORD dwCurrentTime = 0;
  685. INT iRole;
  686. BOOL bSlow;
  687. BOOL bForceNeedFG = FALSE;
  688. CLocator locator;
  689. RSOPEXTSTATUS gpCoreStatus;
  690. XLastError xe;
  691. LPWSTR szNetworkName = 0;
  692. FgPolicyRefreshInfo info = { GP_ReasonUnknown, GP_ModeAsyncForeground };
  693. PTOKEN_GROUPS pTokenGroups = NULL;
  694. BOOL bAsyncFg = lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND ? TRUE : FALSE;
  695. LPWSTR szPolicyMode = 0;
  696. if ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND )
  697. {
  698. szPolicyMode = L"Async forground";
  699. }
  700. else if ( !( lpGPOInfo->dwFlags & GP_BACKGROUND_REFRESH ) )
  701. {
  702. szPolicyMode = L"Sync forground";
  703. }
  704. else
  705. {
  706. szPolicyMode = L"Background";
  707. }
  708. //
  709. // Allow debugging level to be changed dynamically between
  710. // policy refreshes.
  711. //
  712. InitDebugSupport( FALSE );
  713. //
  714. // Debug spew
  715. //
  716. memset(&gpCoreStatus, 0, sizeof(gpCoreStatus));
  717. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  718. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  719. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  720. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs: Starting computer Group Policy (%s) processing..."),szPolicyMode ));
  721. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  722. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  723. } else {
  724. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  725. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  726. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs: Starting user Group Policy (%s) processing..."),szPolicyMode ));
  727. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  728. DebugMsg(( DM_VERBOSE, TEXT("ProcessGPOs:")));
  729. }
  730. if ( !( lpGPOInfo->dwFlags & GP_MACHINE ) && lpGPOInfo->lpwszSidUser )
  731. {
  732. lpGPOInfo->lpwszSidUser = GetSidString( lpGPOInfo->hToken );
  733. if ( lpGPOInfo->lpwszSidUser == 0 )
  734. {
  735. xe = GetLastError();
  736. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetSidString failed.")));
  737. CEvents ev(TRUE, EVENT_FAILED_GET_SID); ev.Report();
  738. goto Exit;
  739. }
  740. }
  741. GetSystemTimeAsFileTime(&gpCoreStatus.ftStartTime);
  742. gpCoreStatus.bValid = TRUE;
  743. //
  744. // Check if we should be verbose to the event log
  745. //
  746. if (CheckForVerbosePolicy()) {
  747. lpGPOInfo->dwFlags |= GP_VERBOSE;
  748. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Verbose output to eventlog requested.")));
  749. }
  750. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  751. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  752. CEvents ev(FALSE, EVENT_START_MACHINE_POLICY); ev.Report();
  753. } else {
  754. CEvents ev(FALSE, EVENT_START_USER_POLICY); ev.Report();
  755. }
  756. }
  757. //
  758. // Claim the critical section
  759. //
  760. lpGPOInfo->hCritSection = EnterCriticalPolicySection((lpGPOInfo->dwFlags & GP_MACHINE));
  761. if (!lpGPOInfo->hCritSection) {
  762. xe = GetLastError();
  763. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to claim the policy critical section with %d."),
  764. GetLastError()));
  765. CEvents ev(TRUE, EVENT_FAILED_CRITICAL_SECTION);
  766. ev.AddArgWin32Error(GetLastError()); ev.Report();
  767. goto Exit;
  768. }
  769. //
  770. // Set the security on the Group Policy registry key
  771. //
  772. if (!MakeRegKeySecure((lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : lpGPOInfo->hToken,
  773. lpGPOInfo->hKeyRoot,
  774. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy"))) {
  775. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to secure reg key.")));
  776. }
  777. //
  778. // Check if user's sid has changed
  779. // Check the change in user's sid before doing any rsop logging..
  780. //
  781. if ( !CheckForChangedSid( lpGPOInfo, &locator ) ) {
  782. xe = GetLastError();
  783. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Check for changed sid failed")));
  784. goto Exit;
  785. }
  786. //
  787. // This flag will be used for all further Rsop Logging..
  788. //
  789. lpGPOInfo->bRsopLogging = RsopLoggingEnabled();
  790. //
  791. // Load netapi32
  792. //
  793. pNetAPI32 = LoadNetAPI32();
  794. if (!pNetAPI32) {
  795. xe = GetLastError();
  796. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to load netapi32 with %d."),
  797. GetLastError()));
  798. goto Exit;
  799. }
  800. //
  801. // Get the role of this computer
  802. //
  803. if (!GetMachineRole (&iRole)) {
  804. xe = GetLastError();
  805. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the role of the computer.")));
  806. CEvents ev(TRUE, EVENT_FAILED_ROLE); ev.Report();
  807. goto Exit;
  808. }
  809. lpGPOInfo->iMachineRole = iRole;
  810. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Machine role is %d."), iRole));
  811. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  812. switch (iRole) {
  813. case 0:
  814. {
  815. CEvents ev(FALSE, EVENT_ROLE_STANDALONE); ev.Report();
  816. break;
  817. }
  818. case 1:
  819. {
  820. CEvents ev(FALSE, EVENT_ROLE_DOWNLEVEL_DOMAIN); ev.Report();
  821. break;
  822. }
  823. default:
  824. {
  825. CEvents ev(FALSE, EVENT_ROLE_DS_DOMAIN); ev.Report();
  826. break;
  827. }
  828. }
  829. }
  830. //
  831. // If we are going to apply policy from the DS
  832. // query for the user's DN name, domain name, etc
  833. //
  834. if (lpGPOInfo->dwFlags & GP_APPLY_DS_POLICY)
  835. {
  836. //
  837. // Query for the user's domain name
  838. //
  839. if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken))
  840. {
  841. xe = GetLastError();
  842. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to impersonate user")));
  843. goto Exit;
  844. }
  845. lpDomain = MyGetDomainName ();
  846. RevertToUser(&hOldToken);
  847. if (!lpDomain) {
  848. xe = GetLastError();
  849. dwResult = GetLastError();
  850. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: MyGetDomainName failed with %d."),
  851. dwResult));
  852. goto Exit;
  853. }
  854. //
  855. // Query for the DS server name
  856. //
  857. DWORD dwAdapterIndex = (DWORD) -1;
  858. dwResult = GetDomainControllerInfo( pNetAPI32,
  859. lpDomain,
  860. DS_DIRECTORY_SERVICE_REQUIRED | DS_IS_FLAT_NAME
  861. | DS_RETURN_DNS_NAME |
  862. ((lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD) ? DS_BACKGROUND_ONLY : 0),
  863. lpGPOInfo->hKeyRoot,
  864. &pDCI,
  865. &bSlow,
  866. &dwAdapterIndex );
  867. if (dwResult != ERROR_SUCCESS) {
  868. xe = dwResult;
  869. if ((dwResult == ERROR_BAD_NETPATH) ||
  870. (dwResult == ERROR_NETWORK_UNREACHABLE) ||
  871. (dwResult == ERROR_NO_SUCH_DOMAIN)) {
  872. //
  873. // couldn't find DC. Nothing more we can do, abort
  874. //
  875. if ( (!(lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD)) ||
  876. (lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND) ||
  877. (lpGPOInfo->iMachineRole == 3) )
  878. {
  879. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: The DC for domain %s is not available. aborting"),
  880. lpDomain));
  881. CEvents ev(TRUE, EVENT_FAILED_DSNAME);
  882. ev.AddArgWin32Error(dwResult); ev.Report();
  883. }
  884. else {
  885. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: The DC for domain %s is not available."), lpDomain));
  886. if (lpGPOInfo->dwFlags & GP_VERBOSE)
  887. {
  888. CEvents ev(FALSE, EVENT_FAILED_DSNAME);
  889. ev.AddArgWin32Error(dwResult); ev.Report();
  890. }
  891. }
  892. } else {
  893. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: DSGetDCName failed with %d."),
  894. dwResult));
  895. CEvents ev(TRUE, EVENT_FAILED_DSNAME);
  896. ev.AddArgWin32Error(dwResult); ev.Report();
  897. }
  898. goto Exit;
  899. } else {
  900. //
  901. // success, slow link?
  902. //
  903. if (bSlow) {
  904. lpGPOInfo->dwFlags |= GP_SLOW_LINK;
  905. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  906. CEvents ev(FALSE, EVENT_SLOWLINK); ev.Report();
  907. }
  908. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: A slow link was detected.")));
  909. }
  910. if ( ( lpGPOInfo->dwFlags & GP_MACHINE ) != 0 )
  911. {
  912. dwResult = GetNetworkName( &szNetworkName, dwAdapterIndex );
  913. if ( dwResult != ERROR_SUCCESS )
  914. {
  915. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetNetworkName failed with %d."), dwResult ));
  916. }
  917. else
  918. {
  919. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: network name is %s"), szNetworkName ? szNetworkName : L"" ));
  920. }
  921. }
  922. }
  923. //
  924. // Get the user's DN name
  925. //
  926. if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken)) {
  927. xe = GetLastError();
  928. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to impersonate user")));
  929. goto Exit;
  930. }
  931. lpName = MyGetUserName (NameFullyQualifiedDN);
  932. RevertToUser(&hOldToken);
  933. if (!lpName) {
  934. xe = GetLastError();
  935. dwResult = GetLastError();
  936. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: MyGetUserName failed with %d."),
  937. dwResult));
  938. CEvents ev(TRUE, EVENT_FAILED_USERNAME);
  939. ev.AddArgWin32Error(dwResult); ev.Report();
  940. goto Exit;
  941. }
  942. lpDomainDN = pDCI->DomainName;
  943. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  944. CEvents ev(FALSE, EVENT_USERNAME); ev.AddArg(L"%.500s", lpName); ev.Report();
  945. CEvents ev1(FALSE, EVENT_DOMAINNAME); ev1.AddArg(L"%.500s", lpDomain); ev1.Report();
  946. CEvents ev2(FALSE, EVENT_DCNAME); ev2.AddArg(pDCI->DomainControllerName); ev2.Report();
  947. }
  948. lpGPOInfo->lpDNName = lpName;
  949. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: User name is: %s, Domain name is: %s"),
  950. lpName, lpDomain));
  951. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Domain controller is: %s Domain DN is %s"),
  952. pDCI->DomainControllerName, lpDomainDN));
  953. if (!(lpGPOInfo->dwFlags & GP_MACHINE)) {
  954. CallDFS(pDCI->DomainName, pDCI->DomainControllerName);
  955. }
  956. //
  957. // Save the DC name in the registry for future reference
  958. //
  959. DWORD dwDisp;
  960. if (RegCreateKeyEx (lpGPOInfo->hKeyRoot,
  961. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History"),
  962. 0, NULL, REG_OPTION_NON_VOLATILE,
  963. KEY_SET_VALUE, NULL, &hKey, &dwDisp) == ERROR_SUCCESS)
  964. {
  965. dwSize = (lstrlen(pDCI->DomainControllerName) + 1) * sizeof(TCHAR);
  966. RegSetValueEx (hKey, TEXT("DCName"), 0, REG_SZ,
  967. (LPBYTE) pDCI->DomainControllerName, dwSize);
  968. if ( ( lpGPOInfo->dwFlags & GP_MACHINE ) != 0 )
  969. {
  970. LPWSTR szTemp = szNetworkName ? szNetworkName : L"";
  971. dwSize = ( wcslen( szTemp ) + 1 ) * sizeof( WCHAR );
  972. RegSetValueEx( hKey,
  973. L"NetworkName",
  974. 0,
  975. REG_SZ,
  976. (LPBYTE) szTemp,
  977. dwSize );
  978. }
  979. RegCloseKey (hKey);
  980. }
  981. }
  982. //
  983. // Read the group policy extensions from the registry
  984. //
  985. if ( !ReadGPExtensions( lpGPOInfo ) )
  986. {
  987. xe = GetLastError();
  988. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: ReadGPExtensions failed.")));
  989. CEvents ev(TRUE, EVENT_READ_EXT_FAILED); ev.Report();
  990. goto Exit;
  991. }
  992. //
  993. // Get the user policy mode if appropriate
  994. //
  995. if (!(lpGPOInfo->dwFlags & GP_MACHINE)) {
  996. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  997. SYSTEM_POLICIES_KEY,
  998. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  999. dwSize = sizeof(dwUserPolicyMode);
  1000. RegQueryValueEx (hKey,
  1001. TEXT("UserPolicyMode"),
  1002. NULL,
  1003. &dwType,
  1004. (LPBYTE) &dwUserPolicyMode,
  1005. &dwSize);
  1006. RegCloseKey (hKey);
  1007. }
  1008. if (dwUserPolicyMode > 0) {
  1009. if (!(lpGPOInfo->dwFlags & GP_APPLY_DS_POLICY)) {
  1010. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Loopback is not allowed for downlevel or local user accounts. Loopback will be disabled.")));
  1011. CEvents ev(FALSE, EVENT_LOOPBACK_DISABLED1); ev.Report();
  1012. dwUserPolicyMode = 0;
  1013. }
  1014. if (dwUserPolicyMode > 0) {
  1015. if (lpGPOInfo->iMachineRole < 2) {
  1016. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Loopback is not allowed on machines joined to a downlevel domain or running standalone. Loopback will be disabled.")));
  1017. CEvents ev(TRUE, EVENT_LOOPBACK_DISABLED2); ev.Report();
  1018. dwUserPolicyMode = 0;
  1019. }
  1020. }
  1021. }
  1022. }
  1023. if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken)) {
  1024. xe = GetLastError();
  1025. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to impersonate user")));
  1026. CEvents ev(TRUE, EVENT_FAILED_IMPERSONATE);
  1027. ev.AddArgWin32Error(GetLastError()); ev.Report();
  1028. goto Exit;
  1029. }
  1030. //
  1031. // Read each of the extensions status..
  1032. //
  1033. if (!ReadExtStatus(lpGPOInfo)) {
  1034. // event logged by ReadExtStatus
  1035. xe = GetLastError();
  1036. RevertToUser(&hOldToken);
  1037. goto Exit;
  1038. }
  1039. //
  1040. // Check if any extensions can be skipped. If there is ever a case where
  1041. // all extensions can be skipped, then exit successfully right after this check.
  1042. // Currently RegistryExtension is always run unless there are no GPO changes,
  1043. // but the GPO changes check is done much later.
  1044. //
  1045. if ( !CheckForSkippedExtensions( lpGPOInfo, FALSE ) ) {
  1046. xe = GetLastError();
  1047. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Checking extensions for skipping failed")));
  1048. //
  1049. // LogEvent() is called by CheckForSkippedExtensions()
  1050. //
  1051. RevertToUser(&hOldToken);
  1052. goto Exit;
  1053. }
  1054. LPWSTR szSiteName;
  1055. dwResult = pNetAPI32->pfnDsGetSiteName(0, &szSiteName);
  1056. if ( dwResult != ERROR_SUCCESS )
  1057. {
  1058. if ( dwResult == ERROR_NO_SITENAME )
  1059. {
  1060. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: No site name defined. Skipping site policy.")));
  1061. if ( lpGPOInfo->dwFlags & GP_VERBOSE )
  1062. {
  1063. CEvents ev(TRUE, EVENT_NO_SITENAME);
  1064. ev.Report();
  1065. }
  1066. szSiteName = 0;
  1067. }
  1068. else
  1069. {
  1070. xe = dwResult;
  1071. CEvents ev(TRUE, EVENT_FAILED_QUERY_SITE);
  1072. ev.AddArgWin32Error(dwResult); ev.Report();
  1073. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: DSGetSiteName failed with %d, exiting."), dwResult));
  1074. RevertToUser(&hOldToken);
  1075. goto Exit;
  1076. }
  1077. }
  1078. lpGPOInfo->szSiteName = szSiteName;
  1079. //
  1080. // Query for the GPO list based upon the mode
  1081. //
  1082. // 0 is normal
  1083. // 1 is merge. Merge user list + machine list
  1084. // 2 is replace. use machine list instead of user list
  1085. //
  1086. if (dwUserPolicyMode == 0) {
  1087. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for normal policy mode")));
  1088. bResult = GetGPOInfo ((lpGPOInfo->dwFlags & GP_MACHINE) ? GPO_LIST_FLAG_MACHINE : 0,
  1089. lpDomainDN, lpName, NULL, &lpGPOInfo->lpGPOList,
  1090. &lpGPOInfo->lpSOMList,
  1091. &lpGPOInfo->lpGpContainerList,
  1092. pNetAPI32, TRUE, 0, szSiteName, 0, &locator);
  1093. if (!bResult) {
  1094. xe = GetLastError();
  1095. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetGPOInfo failed.")));
  1096. CEvents ev(TRUE, EVENT_GPO_QUERY_FAILED); ev.Report();
  1097. }
  1098. } else if (dwUserPolicyMode == 2) {
  1099. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for replacement user policy mode")));
  1100. lpComputerName = MyGetComputerName (NameFullyQualifiedDN);
  1101. if (lpComputerName) {
  1102. PDOMAIN_CONTROLLER_INFO pDCInfo;
  1103. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Using computer name %s for query."), lpComputerName));
  1104. dwResult = pNetAPI32->pfnDsGetDcName( 0,
  1105. 0,
  1106. 0,
  1107. 0,
  1108. DS_DIRECTORY_SERVICE_REQUIRED |
  1109. ((lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD) ? DS_BACKGROUND_ONLY : 0),
  1110. &pDCInfo);
  1111. if ( dwResult == 0 )
  1112. {
  1113. bResult = GetGPOInfo (0, pDCInfo->DomainName, lpComputerName, NULL,
  1114. &lpGPOInfo->lpGPOList,
  1115. &lpGPOInfo->lpLoopbackSOMList,
  1116. &lpGPOInfo->lpLoopbackGpContainerList,
  1117. pNetAPI32, FALSE, 0, szSiteName, 0, &locator );
  1118. if (!bResult) {
  1119. xe = GetLastError();
  1120. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetGPOInfo failed.")));
  1121. CEvents ev(TRUE, EVENT_GPO_QUERY_FAILED); ev.Report();
  1122. }
  1123. pNetAPI32->pfnNetApiBufferFree( pDCInfo );
  1124. }
  1125. else
  1126. {
  1127. xe = dwResult;
  1128. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the computer domain name with %d"),
  1129. GetLastError()));
  1130. CEvents ev(TRUE, EVENT_NO_MACHINE_DOMAIN);
  1131. ev.AddArg(lpComputerName); ev.AddArgWin32Error(GetLastError()); ev.Report();
  1132. bResult = FALSE;
  1133. }
  1134. LocalFree (lpComputerName);
  1135. } else {
  1136. xe = GetLastError();
  1137. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the computer name with %d"),
  1138. GetLastError()));
  1139. CEvents ev(TRUE, EVENT_FAILED_MACHINENAME);
  1140. ev.AddArgWin32Error(GetLastError()); ev.Report();
  1141. bResult = FALSE;
  1142. }
  1143. } else {
  1144. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Calling GetGPOInfo for merging user policy mode")));
  1145. lpComputerName = MyGetComputerName (NameFullyQualifiedDN);
  1146. if (lpComputerName) {
  1147. lpGPOInfo->lpGPOList = NULL;
  1148. bResult = GetGPOInfo (0, lpDomainDN, lpName, NULL,
  1149. &lpGPOInfo->lpGPOList,
  1150. &lpGPOInfo->lpSOMList,
  1151. &lpGPOInfo->lpGpContainerList,
  1152. pNetAPI32, FALSE, 0, szSiteName, 0, &locator );
  1153. if (bResult) {
  1154. PDOMAIN_CONTROLLER_INFO pDCInfo;
  1155. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Using computer name %s for query."), lpComputerName));
  1156. lpGPO = NULL;
  1157. dwResult = pNetAPI32->pfnDsGetDcName( 0,
  1158. 0,
  1159. 0,
  1160. 0,
  1161. DS_DIRECTORY_SERVICE_REQUIRED |
  1162. ((lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD) ? DS_BACKGROUND_ONLY : 0),
  1163. &pDCInfo);
  1164. if ( dwResult == 0 )
  1165. {
  1166. bResult = GetGPOInfo (0, pDCInfo->DomainName, lpComputerName, NULL,
  1167. &lpGPO,
  1168. &lpGPOInfo->lpLoopbackSOMList,
  1169. &lpGPOInfo->lpLoopbackGpContainerList,
  1170. pNetAPI32, FALSE, 0, szSiteName, 0, &locator );
  1171. if (bResult) {
  1172. if (lpGPOInfo->lpGPOList && lpGPO) {
  1173. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Both user and machine lists are defined. Merging them together.")));
  1174. //
  1175. // Need to merge the lists together
  1176. //
  1177. lpGPOTemp = lpGPOInfo->lpGPOList;
  1178. while (lpGPOTemp->pNext) {
  1179. lpGPOTemp = lpGPOTemp->pNext;
  1180. }
  1181. lpGPOTemp->pNext = lpGPO;
  1182. } else if (!lpGPOInfo->lpGPOList && lpGPO) {
  1183. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Only machine list is defined.")));
  1184. lpGPOInfo->lpGPOList = lpGPO;
  1185. } else {
  1186. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Only user list is defined.")));
  1187. }
  1188. } else {
  1189. xe = GetLastError();
  1190. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetGPOInfo failed for computer name.")));
  1191. CEvents ev(TRUE, EVENT_GPO_QUERY_FAILED); ev.Report();
  1192. }
  1193. pNetAPI32->pfnNetApiBufferFree( pDCInfo );
  1194. }
  1195. else
  1196. {
  1197. xe = dwResult;
  1198. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the computer domain name with %d"),
  1199. GetLastError()));
  1200. CEvents ev(TRUE, EVENT_NO_MACHINE_DOMAIN);
  1201. ev.AddArg(lpComputerName); ev.AddArgWin32Error(GetLastError()); ev.Report();
  1202. bResult = FALSE;
  1203. }
  1204. } else {
  1205. xe = GetLastError();
  1206. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetGPOInfo failed for user name.")));
  1207. CEvents ev(TRUE, EVENT_GPO_QUERY_FAILED); ev.Report();
  1208. }
  1209. LocalFree (lpComputerName);
  1210. } else {
  1211. xe = GetLastError();
  1212. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the computer name with %d"),
  1213. GetLastError()));
  1214. CEvents ev(TRUE, EVENT_FAILED_MACHINENAME);
  1215. ev.AddArgWin32Error(GetLastError()); ev.Report();
  1216. bResult = FALSE;
  1217. }
  1218. }
  1219. if (!RevertToUser(&hOldToken)) {
  1220. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to revert to self")));
  1221. }
  1222. if (!bResult) {
  1223. goto Exit;
  1224. }
  1225. bResult = SetupGPOFilter( lpGPOInfo );
  1226. if (!bResult) {
  1227. xe = GetLastError();
  1228. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: SetupGPOFilter failed.")));
  1229. CEvents ev(TRUE, EVENT_SETUP_GPOFILTER_FAILED); ev.Report();
  1230. goto Exit;
  1231. }
  1232. //
  1233. // Log Gpo info to WMI's database
  1234. //
  1235. //
  1236. // Need to check if the security group membership has changed the first time around
  1237. //
  1238. if ( !(lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD) || (lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND) ) {
  1239. if ((lpGPOInfo->dwFlags & GP_MACHINE) && (lpGPOInfo->dwFlags & GP_APPLY_DS_POLICY)) {
  1240. HANDLE hLocToken=NULL;
  1241. //
  1242. // if it is machine policy processing, get the machine token so that we can check
  1243. // security group membership using the right token. This causes GetMachineToken to be called twice
  1244. // but moving it to the beginning requires too much change.
  1245. //
  1246. hLocToken = GetMachineToken();
  1247. if (hLocToken) {
  1248. CheckGroupMembership( lpGPOInfo, hLocToken, &lpGPOInfo->bMemChanged, &lpGPOInfo->bUserLocalMemChanged, &pTokenGroups);
  1249. CloseHandle(hLocToken);
  1250. }
  1251. else {
  1252. xe = GetLastError();
  1253. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get the machine token with %d"), GetLastError()));
  1254. goto Exit;
  1255. }
  1256. }
  1257. else {
  1258. //
  1259. // In the user case just use the token passed in
  1260. //
  1261. CheckGroupMembership( lpGPOInfo, lpGPOInfo->hToken, &lpGPOInfo->bMemChanged, &lpGPOInfo->bUserLocalMemChanged, &pTokenGroups);
  1262. }
  1263. }
  1264. if ( lpGPOInfo->bRsopLogging )
  1265. {
  1266. if ( SetRsopTargetName(lpGPOInfo) )
  1267. {
  1268. RSOPSESSIONDATA rsopSessionData;
  1269. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Logging Data for Target <%s>."), lpGPOInfo->szTargetName));
  1270. //
  1271. // fill up the rsop data
  1272. //
  1273. rsopSessionData.pwszTargetName = lpGPOInfo->szName;
  1274. rsopSessionData.pwszSOM = lpGPOInfo->lpDNName ? GetSomPath( lpGPOInfo->lpDNName ) : TEXT("Local");
  1275. rsopSessionData.pSecurityGroups = pTokenGroups;
  1276. rsopSessionData.bLogSecurityGroup = lpGPOInfo->bMemChanged || lpGPOInfo->bUserLocalMemChanged;
  1277. rsopSessionData.pwszSite = lpGPOInfo->szSiteName;
  1278. rsopSessionData.bMachine = (lpGPOInfo->dwFlags & GP_MACHINE);
  1279. rsopSessionData.bSlowLink = bSlow;
  1280. //
  1281. // Fill in the current time
  1282. //
  1283. BOOL bStateChanged = FALSE;
  1284. BOOL bLinkChanged = FALSE;
  1285. BOOL bNoState = FALSE;
  1286. //
  1287. // log RSoP data only when policy has changed
  1288. //
  1289. dwResult = ComparePolicyState( lpGPOInfo, &bLinkChanged, &bStateChanged, &bNoState );
  1290. if ( dwResult != ERROR_SUCCESS )
  1291. {
  1292. DebugMsg((DM_WARNING, L"ProcessGPOs: ComparePolicyState failed %d, assuming policy changed.", dwResult ));
  1293. }
  1294. //
  1295. // bStateChanged is TRUE if dwResult is not kosher
  1296. //
  1297. if ( bStateChanged || bNoState || bLinkChanged || (lpGPOInfo->dwFlags & GP_FORCED_REFRESH) ||
  1298. lpGPOInfo->bMemChanged || lpGPOInfo->bUserLocalMemChanged ) {
  1299. //
  1300. // Any changes get the wmi interface
  1301. //
  1302. lpGPOInfo->bRsopLogging =
  1303. GetWbemServices( lpGPOInfo, RSOP_NS_DIAG_ROOT, FALSE, &(lpGPOInfo->bRsopCreated), &(lpGPOInfo->pWbemServices) );
  1304. if (!lpGPOInfo->bRsopLogging)
  1305. {
  1306. CEvents ev(TRUE, EVENT_FAILED_WBEM_SERVICES); ev.Report();
  1307. }
  1308. else
  1309. {
  1310. //
  1311. // all changes except link changes
  1312. //
  1313. if ( bStateChanged || bNoState || (lpGPOInfo->dwFlags & GP_FORCED_REFRESH) )
  1314. {
  1315. //
  1316. // treat no state as newly created
  1317. //
  1318. lpGPOInfo->bRsopCreated = (lpGPOInfo->bRsopCreated || bNoState);
  1319. lpGPOInfo->bRsopLogging = LogExtSessionStatus( lpGPOInfo->pWbemServices,
  1320. 0,
  1321. TRUE,
  1322. lpGPOInfo->bRsopCreated || (lpGPOInfo->dwFlags & GP_FORCED_REFRESH)
  1323. /* log the event sources only if the namespace is newly created or force refresh */
  1324. );
  1325. if (!lpGPOInfo->bRsopLogging)
  1326. {
  1327. CEvents ev(TRUE, EVENT_FAILED_RSOPCORE_SESSION_STATUS); ev.AddArgWin32Error(GetLastError()); ev.Report();
  1328. }
  1329. else
  1330. {
  1331. bResult = LogRsopData( lpGPOInfo, &rsopSessionData );
  1332. if (!bResult)
  1333. {
  1334. CEvents ev(TRUE, EVENT_RSOP_FAILED); ev.Report();
  1335. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Rsop data. Continuing.")));
  1336. lpGPOInfo->bRsopLogging = FALSE;
  1337. }
  1338. else
  1339. {
  1340. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Logged Rsop Data successfully.")));
  1341. //
  1342. // save state only when policy has changed and RSoP logging is successful
  1343. //
  1344. dwResult = SavePolicyState( lpGPOInfo );
  1345. if ( dwResult != ERROR_SUCCESS )
  1346. {
  1347. DebugMsg((DM_WARNING, L"ProcessGPOs: SavePolicyState failed %d.", dwResult ));
  1348. }
  1349. }
  1350. }
  1351. }
  1352. else if ( bLinkChanged || lpGPOInfo->bMemChanged || lpGPOInfo->bUserLocalMemChanged )
  1353. {
  1354. bResult = LogSessionData( lpGPOInfo, &rsopSessionData );
  1355. if (!bResult)
  1356. {
  1357. CEvents ev(TRUE, EVENT_RSOP_FAILED); ev.Report();
  1358. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error when logging Rsop session. Continuing.")));
  1359. lpGPOInfo->bRsopLogging = FALSE;
  1360. }
  1361. else
  1362. {
  1363. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Logged Rsop Session successfully.")));
  1364. //
  1365. // save state only when policy has changed and RSoP logging is successful
  1366. //
  1367. dwResult = SaveLinkState( lpGPOInfo );
  1368. if ( dwResult != ERROR_SUCCESS )
  1369. {
  1370. DebugMsg((DM_WARNING, L"ProcessGPOs: SaveLinkState failed %d.", dwResult ));
  1371. }
  1372. }
  1373. }
  1374. }
  1375. }
  1376. }
  1377. else
  1378. {
  1379. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Error querying for targetname. not logging Gpos.Error = %d"), GetLastError()));
  1380. }
  1381. }
  1382. DebugPrintGPOList( lpGPOInfo );
  1383. //================================================================
  1384. //
  1385. // Now walk through the list of extensions
  1386. //
  1387. //================================================================
  1388. EnterCriticalSection( &g_GPOCS );
  1389. pGPHandle = (LPGPINFOHANDLE) LocalAlloc( LPTR, sizeof(GPINFOHANDLE) );
  1390. //
  1391. // Continue even if pGPHandle is 0, because all it means is that async completions (if any)
  1392. // will fail. Remove old asynch completion context.
  1393. //
  1394. if ( pGPHandle )
  1395. pGPHandle->pGPOInfo = lpGPOInfo;
  1396. if ( lpGPOInfo->dwFlags & GP_MACHINE ) {
  1397. if ( g_pMachGPInfo )
  1398. LocalFree( g_pMachGPInfo );
  1399. g_pMachGPInfo = pGPHandle;
  1400. } else {
  1401. if ( g_pUserGPInfo )
  1402. LocalFree( g_pUserGPInfo );
  1403. g_pUserGPInfo = pGPHandle;
  1404. }
  1405. LeaveCriticalSection( &g_GPOCS );
  1406. pAsyncHandle = (ASYNCCOMPLETIONHANDLE) pGPHandle;
  1407. dwCurrentTime = GetCurTime();
  1408. lpExt = lpGPOInfo->lpExtensions;
  1409. //
  1410. // Before going in, get the thread token and reset the thread token in case
  1411. // one of the extensions hit an exception.
  1412. //
  1413. if (!OpenThreadToken (GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ,
  1414. TRUE, &hOldToken)) {
  1415. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: OpenThreadToken failed with error %d, assuming thread is not impersonating"), GetLastError()));
  1416. hOldToken = NULL;
  1417. }
  1418. while ( lpExt )
  1419. {
  1420. BOOL bProcessGPOs, bNoChanges, bUsePerUserLocalSetting;
  1421. PGROUP_POLICY_OBJECT pDeletedGPOList;
  1422. DWORD dwRet;
  1423. HRESULT hrCSERsopStatus = S_OK;
  1424. GPEXTSTATUS gpExtStatus;
  1425. //
  1426. // Check for early shutdown or user logoff
  1427. //
  1428. if ( (lpGPOInfo->dwFlags & GP_MACHINE) && g_bStopMachGPOProcessing
  1429. || !(lpGPOInfo->dwFlags & GP_MACHINE) && g_bStopUserGPOProcessing ) {
  1430. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Aborting GPO processing due to machine shutdown or logoff")));
  1431. CEvents ev(TRUE, EVENT_GPO_PROC_STOPPED); ev.Report();
  1432. break;
  1433. }
  1434. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: -----------------------")));
  1435. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Processing extension %s"),
  1436. lpExt->lpDisplayName));
  1437. //
  1438. // The extension has not gotten skipped at this point
  1439. //
  1440. bUsePerUserLocalSetting = lpExt->dwUserLocalSetting && !(lpGPOInfo->dwFlags & GP_MACHINE);
  1441. //
  1442. // read the CSEs status
  1443. //
  1444. ReadStatus( lpExt->lpKeyName,
  1445. lpGPOInfo,
  1446. bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : 0,
  1447. &gpExtStatus );
  1448. //
  1449. // Reset lpGPOInfo->lpGPOList based on extension filter list. If the extension
  1450. // is being called to do delete processing on the history then the current GpoList
  1451. // is null.
  1452. //
  1453. if ( lpExt->bHistoryProcessing )
  1454. {
  1455. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Extension %s is being called to do delete processing on cached history."),
  1456. lpExt->lpDisplayName));
  1457. lpGPOInfo->lpGPOList = NULL;
  1458. }
  1459. else
  1460. FilterGPOs( lpExt, lpGPOInfo );
  1461. DebugPrintGPOList( lpGPOInfo );
  1462. if ( !CheckGPOs( lpExt, lpGPOInfo, dwCurrentTime,
  1463. &bProcessGPOs, &bNoChanges, &pDeletedGPOList ) )
  1464. {
  1465. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: CheckGPOs failed.")));
  1466. lpExt = lpExt->pNext;
  1467. continue;
  1468. }
  1469. if ( lpExt->dwNoBackgroundPolicy && ( lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD ) )
  1470. {
  1471. if ( bProcessGPOs && ( pDeletedGPOList || lpGPOInfo->lpGPOList || lpExt->bRsopTransition ) )
  1472. {
  1473. info.mode = GP_ModeSyncForeground;
  1474. info.reason = GP_ReasonCSERequiresSync;
  1475. }
  1476. }
  1477. if ( lpExt->bSkipped )
  1478. {
  1479. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Extension %s skipped with flags 0x%x."),
  1480. lpExt->lpDisplayName, lpGPOInfo->dwFlags));
  1481. if (lpGPOInfo->dwFlags & GP_VERBOSE)
  1482. {
  1483. CEvents ev(FALSE, EVENT_EXT_SKIPPED);
  1484. ev.AddArg(lpExt->lpDisplayName); ev.AddArgHex(lpGPOInfo->dwFlags); ev.Report();
  1485. }
  1486. lpExt = lpExt->pNext;
  1487. continue;
  1488. }
  1489. if ( bProcessGPOs )
  1490. {
  1491. if ( !pDeletedGPOList && !lpGPOInfo->lpGPOList && !lpExt->bRsopTransition )
  1492. {
  1493. DebugMsg((DM_VERBOSE,
  1494. TEXT("ProcessGPOs: Extension %s skipped because both deleted and changed GPO lists are empty."),
  1495. lpExt->lpDisplayName ));
  1496. if (lpGPOInfo->dwFlags & GP_VERBOSE)
  1497. {
  1498. CEvents ev(FALSE, EVENT_EXT_HAS_EMPTY_LISTS);
  1499. ev.AddArg(lpExt->lpDisplayName); ev.Report();
  1500. }
  1501. lpExt = lpExt->pNext;
  1502. continue;
  1503. }
  1504. if ( !(lpExt->bForcedRefreshNextFG) )
  1505. {
  1506. if ( lpExt->dwEnableAsynch )
  1507. {
  1508. //
  1509. // Save now to shadow area to avoid race between thread that returns from
  1510. // ProcessGPOList and the thread that does ProcessGroupPolicyCompleted and
  1511. // reads from shadow area.
  1512. //
  1513. SaveGPOList( lpExt->lpKeyName, lpGPOInfo,
  1514. HKEY_LOCAL_MACHINE,
  1515. bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : NULL,
  1516. TRUE, lpGPOInfo->lpGPOList );
  1517. }
  1518. dwRet = E_FAIL;
  1519. __try
  1520. {
  1521. dwRet = ProcessGPOList( lpExt, lpGPOInfo, pDeletedGPOList,
  1522. lpGPOInfo->lpGPOList, bNoChanges, pAsyncHandle, &hrCSERsopStatus );
  1523. }
  1524. __except( GPOExceptionFilter( GetExceptionInformation() ) )
  1525. {
  1526. SetThreadToken(NULL, hOldToken);
  1527. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Extension %s ProcessGroupPolicy threw unhandled exception 0x%x."),
  1528. lpExt->lpDisplayName, GetExceptionCode() ));
  1529. CEvents ev(TRUE, EVENT_CAUGHT_EXCEPTION);
  1530. ev.AddArg(lpExt->lpDisplayName); ev.AddArgHex(GetExceptionCode()); ev.Report();
  1531. }
  1532. SetThreadToken(NULL, hOldToken);
  1533. FreeGPOList( pDeletedGPOList );
  1534. pDeletedGPOList = NULL;
  1535. if ( dwRet == ERROR_SUCCESS || dwRet == ERROR_OVERRIDE_NOCHANGES )
  1536. {
  1537. //
  1538. // ERROR_OVERRIDE_NOCHANGES means that extension processed the list and so the cached list
  1539. // must be updated, but the extension will be called the next time even if there are
  1540. // no changes. Duplicate the saved data in the PerUserLocalSetting case to allow for deleted
  1541. // GPO information to be generated from a combination of HKCU and HKLM\{sid-user} data.
  1542. //
  1543. SaveGPOList( lpExt->lpKeyName, lpGPOInfo,
  1544. HKEY_LOCAL_MACHINE,
  1545. NULL,
  1546. FALSE, lpGPOInfo->lpGPOList );
  1547. if ( bUsePerUserLocalSetting )
  1548. {
  1549. SaveGPOList( lpExt->lpKeyName, lpGPOInfo,
  1550. HKEY_LOCAL_MACHINE,
  1551. lpGPOInfo->lpwszSidUser,
  1552. FALSE, lpGPOInfo->lpGPOList );
  1553. }
  1554. uExtensionCount++;
  1555. //
  1556. // the CSE required sync foreground previously and now returned ERROR_OVERRIDE_NOCHANGES,
  1557. // maintain the require sync foreground refresh flag
  1558. //
  1559. if ( gpExtStatus.dwStatus == ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED &&
  1560. dwRet == ERROR_OVERRIDE_NOCHANGES )
  1561. {
  1562. info.mode = GP_ModeSyncForeground;
  1563. info.reason = GP_ReasonCSESyncError;
  1564. }
  1565. }
  1566. else if ( dwRet == E_PENDING )
  1567. {
  1568. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Extension %s ProcessGroupPolicy returned e_pending."),
  1569. lpExt->lpDisplayName));
  1570. }
  1571. else if ( dwRet == ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED )
  1572. {
  1573. //
  1574. // a CSE returned ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED.
  1575. // Raise a flag to sync foreground refresh.
  1576. //
  1577. info.mode = GP_ModeSyncForeground;
  1578. info.reason = GP_ReasonCSERequiresSync;
  1579. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Extension %s ProcessGroupPolicy returned sync_foreground."),
  1580. lpExt->lpDisplayName));
  1581. if ( lpGPOInfo->dwFlags & GP_FORCED_REFRESH )
  1582. {
  1583. bForceNeedFG = TRUE;
  1584. }
  1585. }
  1586. else
  1587. {
  1588. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Extension %s ProcessGroupPolicy failed, status 0x%x."),
  1589. lpExt->lpDisplayName, dwRet));
  1590. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1591. CEvents ev(FALSE, EVENT_CHANGES_FAILED);
  1592. ev.AddArg(lpExt->lpDisplayName); ev.AddArgWin32Error(dwRet); ev.Report();
  1593. }
  1594. //
  1595. // the CSE required foreground previously and now returned an error,
  1596. // maintain the require sync foreground refresh flag
  1597. //
  1598. if ( gpExtStatus.dwStatus == ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED )
  1599. {
  1600. info.mode = GP_ModeSyncForeground;
  1601. info.reason = GP_ReasonCSESyncError;
  1602. }
  1603. }
  1604. //
  1605. // Fill up the status data.
  1606. //
  1607. ZeroMemory( &gpExtStatus, sizeof(gpExtStatus) );
  1608. gpExtStatus.dwSlowLink = (lpGPOInfo->dwFlags & GP_SLOW_LINK) != 0;
  1609. gpExtStatus.dwRsopLogging = lpGPOInfo->bRsopLogging;
  1610. gpExtStatus.dwStatus = dwRet;
  1611. gpExtStatus.dwTime = dwCurrentTime;
  1612. gpExtStatus.bForceRefresh = bForceNeedFG;
  1613. gpExtStatus.dwRsopStatus = hrCSERsopStatus;
  1614. WriteStatus(lpExt->lpKeyName,
  1615. lpGPOInfo,
  1616. bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : NULL,
  1617. &gpExtStatus);
  1618. }
  1619. else
  1620. {
  1621. //
  1622. // if it is force refresh next time around, all we need to do is readstatus and
  1623. // writestatus back with forcerefresh value set.
  1624. //
  1625. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Extensions %s needs to run in ForeGround. Skipping after setting forceflag."),
  1626. lpExt->lpDisplayName));
  1627. if ( gpExtStatus.bStatus )
  1628. {
  1629. gpExtStatus.bForceRefresh = TRUE;
  1630. WriteStatus( lpExt->lpKeyName, lpGPOInfo,
  1631. bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : NULL,
  1632. &gpExtStatus );
  1633. }
  1634. else
  1635. {
  1636. //
  1637. // We can ignore this because absence of a status automatically means processing
  1638. //
  1639. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Couldn't read status data for %s. Error %d. ignoring.. "),
  1640. lpExt->lpDisplayName, GetLastError()));
  1641. }
  1642. //
  1643. // There is a policy that can only be force refreshed in foreground
  1644. //
  1645. bForceNeedFG = TRUE;
  1646. }
  1647. }
  1648. //
  1649. // Process next extension
  1650. //
  1651. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: -----------------------")));
  1652. lpExt = lpExt->pNext;
  1653. }
  1654. if ( hOldToken )
  1655. {
  1656. CloseHandle(hOldToken);
  1657. }
  1658. //================================================================
  1659. //
  1660. // Success
  1661. //
  1662. //================================================================
  1663. bRetVal = TRUE;
  1664. Exit:
  1665. //
  1666. // change engine modes only if there is no error
  1667. //
  1668. if ( bRetVal )
  1669. {
  1670. //
  1671. // if policy sez sync. mark it sync
  1672. //
  1673. if ( GetFgPolicySetting( HKEY_LOCAL_MACHINE ) )
  1674. {
  1675. info.mode = GP_ModeSyncForeground;
  1676. info.reason = GP_ReasonSyncPolicy;
  1677. }
  1678. //
  1679. // async only on Pro
  1680. //
  1681. OSVERSIONINFOEXW version;
  1682. version.dwOSVersionInfoSize = sizeof(version);
  1683. if ( !GetVersionEx( (LPOSVERSIONINFO) &version ) )
  1684. {
  1685. //
  1686. // conservatively assume non Pro SKU
  1687. //
  1688. info.mode = GP_ModeSyncForeground;
  1689. info.reason = GP_ReasonSKU;
  1690. }
  1691. else
  1692. {
  1693. if ( version.wProductType != VER_NT_WORKSTATION )
  1694. {
  1695. //
  1696. // force sync refresh on non Pro SKU
  1697. //
  1698. info.mode = GP_ModeSyncForeground;
  1699. info.reason = GP_ReasonSKU;
  1700. }
  1701. }
  1702. if ( !( lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD ) || ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND ) )
  1703. {
  1704. //
  1705. // set the previous info only in the foreground refreshes
  1706. //
  1707. LPWSTR szSid = lpGPOInfo->dwFlags & GP_MACHINE ? 0 : lpGPOInfo->lpwszSidUser;
  1708. FgPolicyRefreshInfo curInfo = { GP_ReasonUnknown, GP_ModeUnknown };
  1709. if ( GetCurrentFgPolicyRefreshInfo( szSid, &curInfo ) != ERROR_SUCCESS )
  1710. {
  1711. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: GetCurrentFgPolicyRefreshInfo failed.")));
  1712. }
  1713. else
  1714. {
  1715. if ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND )
  1716. {
  1717. curInfo.mode = GP_ModeAsyncForeground;
  1718. }
  1719. else
  1720. {
  1721. curInfo.mode = GP_ModeSyncForeground;
  1722. }
  1723. if ( SetPreviousFgPolicyRefreshInfo( szSid, curInfo ) != ERROR_SUCCESS )
  1724. {
  1725. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: SetPreviousFgPolicyRefreshInfo failed.") ));
  1726. }
  1727. }
  1728. }
  1729. if ( info.mode == GP_ModeSyncForeground )
  1730. {
  1731. //
  1732. // need sync foreground, set in all refreshes
  1733. //
  1734. LPWSTR szSid = lpGPOInfo->dwFlags & GP_MACHINE ? 0 : lpGPOInfo->lpwszSidUser;
  1735. if ( SetNextFgPolicyRefreshInfo( szSid, info ) != ERROR_SUCCESS )
  1736. {
  1737. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: SetNextFgPolicyRefreshInfo failed.")));
  1738. }
  1739. }
  1740. else if ( info.mode == GP_ModeAsyncForeground )
  1741. {
  1742. //
  1743. // sync foreground policy successfully applied, nobody needs sync foreground,
  1744. // reset the GP_ModeSyncForeground only in the async foreground and background
  1745. // refreshes
  1746. //
  1747. LPWSTR szSid = lpGPOInfo->dwFlags & GP_MACHINE ? 0 : lpGPOInfo->lpwszSidUser;
  1748. if ( !( lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD ) &&
  1749. !( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND ) )
  1750. {
  1751. if ( SetNextFgPolicyRefreshInfo( szSid, info ) != ERROR_SUCCESS )
  1752. {
  1753. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: SetNextFgPolicyRefreshInfo failed.")));
  1754. }
  1755. }
  1756. }
  1757. }
  1758. if ( !lpGPOInfo->pWbemServices )
  1759. {
  1760. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: No WMI logging done in this policy cycle.")));
  1761. }
  1762. if (!bRetVal)
  1763. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Processing failed with error %d."), (DWORD)(xe)));
  1764. GetSystemTimeAsFileTime(&gpCoreStatus.ftEndTime);
  1765. gpCoreStatus.bValid = TRUE;
  1766. gpCoreStatus.dwStatus = bRetVal ?
  1767. ERROR_SUCCESS:
  1768. ((xe ==ERROR_SUCCESS) ? E_FAIL : xe);
  1769. // if rsop logging is not supported gp core status will appear dirty
  1770. gpCoreStatus.dwLoggingStatus = RsopLoggingEnabled() ? ((lpGPOInfo->bRsopLogging) ? S_OK : E_FAIL) : HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1771. // No point in checking for error code here.
  1772. // The namespace is marked dirty. Diagnostic mode provider should expect all
  1773. // values here or mark the namespace dirty.
  1774. if ((lpGPOInfo->dwFlags & GP_MACHINE) || (lpGPOInfo->lpwszSidUser)) {
  1775. SaveLoggingStatus(
  1776. (lpGPOInfo->dwFlags & GP_MACHINE) ? NULL : (lpGPOInfo->lpwszSidUser),
  1777. NULL, &gpCoreStatus);
  1778. }
  1779. //
  1780. // Unload the Group Policy Extensions
  1781. //
  1782. UnloadGPExtensions (lpGPOInfo);
  1783. FreeLists( lpGPOInfo );
  1784. lpGPOInfo->lpGPOList = NULL;
  1785. lpGPOInfo->lpExtFilterList = NULL;
  1786. if (szNetworkName) {
  1787. LocalFree (szNetworkName );
  1788. szNetworkName = NULL;
  1789. }
  1790. FreeSOMList( lpGPOInfo->lpSOMList );
  1791. FreeSOMList( lpGPOInfo->lpLoopbackSOMList );
  1792. FreeGpContainerList( lpGPOInfo->lpGpContainerList );
  1793. FreeGpContainerList( lpGPOInfo->lpLoopbackGpContainerList );
  1794. if ( lpGPOInfo->szSiteName )
  1795. {
  1796. pNetAPI32->pfnNetApiBufferFree(lpGPOInfo->szSiteName);
  1797. lpGPOInfo->szSiteName = 0;
  1798. }
  1799. lpGPOInfo->lpSOMList = NULL;
  1800. lpGPOInfo->lpLoopbackSOMList = NULL;
  1801. lpGPOInfo->lpGpContainerList = NULL;
  1802. lpGPOInfo->lpLoopbackGpContainerList = NULL;
  1803. lpGPOInfo->bRsopCreated = FALSE; // reset this to false always.
  1804. // we will know in the next iteration
  1805. ReleaseWbemServices( lpGPOInfo );
  1806. //
  1807. // Token groups can change only at logon time, so reset to false
  1808. //
  1809. lpGPOInfo->bMemChanged = FALSE;
  1810. lpGPOInfo->bUserLocalMemChanged = FALSE;
  1811. //
  1812. // We migrate the policy data from old sid only at logon time.
  1813. // reset it to false.
  1814. //
  1815. lpGPOInfo->bSidChanged = FALSE;
  1816. if (pDCI) {
  1817. pNetAPI32->pfnNetApiBufferFree(pDCI);
  1818. }
  1819. lpGPOInfo->lpDNName = 0;
  1820. if (lpName) {
  1821. LocalFree (lpName);
  1822. }
  1823. if (lpDomain) {
  1824. LocalFree (lpDomain);
  1825. }
  1826. if (pTokenGroups) {
  1827. LocalFree(pTokenGroups);
  1828. pTokenGroups = NULL;
  1829. }
  1830. //
  1831. // Release the critical section
  1832. //
  1833. if (lpGPOInfo->hCritSection) {
  1834. LeaveCriticalPolicySection (lpGPOInfo->hCritSection);
  1835. lpGPOInfo->hCritSection = NULL;
  1836. }
  1837. //
  1838. // Announce that policies have changed
  1839. //
  1840. if (bRetVal) {
  1841. //
  1842. // This needs to be set before NotifyEvent
  1843. //
  1844. if (bForceNeedFG)
  1845. {
  1846. info.reason = GP_ReasonSyncForced;
  1847. info.mode = GP_ModeSyncForeground;
  1848. LPWSTR szSid = lpGPOInfo->dwFlags & GP_MACHINE ? 0 : lpGPOInfo->lpwszSidUser;
  1849. if ( SetNextFgPolicyRefreshInfo( szSid, info ) != ERROR_SUCCESS )
  1850. {
  1851. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: SetNextFgPolicyRefreshInfo failed.")));
  1852. }
  1853. else
  1854. {
  1855. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Forced option changed policy mode.")));
  1856. }
  1857. DmAssert(lpGPOInfo->dwFlags & GP_FORCED_REFRESH);
  1858. SetEvent(lpGPOInfo->hNeedFGEvent);
  1859. }
  1860. if (uExtensionCount) {
  1861. //
  1862. // First, update User with new colors, bitmaps, etc.
  1863. //
  1864. if (lpGPOInfo->dwFlags & GP_REGPOLICY_CPANEL) {
  1865. //
  1866. // Something has changed in the control panel section
  1867. // Start control.exe with the /policy switch so the
  1868. // display is refreshed.
  1869. //
  1870. RefreshDisplay (lpGPOInfo);
  1871. }
  1872. //
  1873. // Notify anyone waiting on an event handle
  1874. //
  1875. if (lpGPOInfo->hNotifyEvent) {
  1876. PulseEvent (lpGPOInfo->hNotifyEvent);
  1877. }
  1878. //
  1879. // Create a thread to broadcast the WM_SETTINGCHANGE message
  1880. //
  1881. // copy the data to another structure so that this thread can safely free its structures
  1882. LPPOLICYCHANGEDINFO lpPolicyChangedInfo;
  1883. lpPolicyChangedInfo = (LPPOLICYCHANGEDINFO)LocalAlloc(LPTR, sizeof(POLICYCHANGEDINFO));
  1884. if (lpPolicyChangedInfo)
  1885. {
  1886. HANDLE hProc;
  1887. BOOL bDupSucceeded = TRUE;
  1888. lpPolicyChangedInfo->bMachine = (lpGPOInfo->dwFlags & GP_MACHINE) ? 1 : 0;
  1889. if (!(lpPolicyChangedInfo->bMachine))
  1890. {
  1891. hProc = GetCurrentProcess();
  1892. if( hProc == NULL ) {
  1893. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to get process handle with error (%d)."), GetLastError()));
  1894. bDupSucceeded = FALSE;
  1895. }
  1896. if (bDupSucceeded &&
  1897. (!DuplicateHandle(
  1898. hProc, // Source of the handle
  1899. lpGPOInfo->hToken, // Source handle
  1900. hProc, // Target of the handle
  1901. &(lpPolicyChangedInfo->hToken), // Target handle
  1902. 0, // ignored since DUPLICATE_SAME_ACCESS is set
  1903. FALSE, // no inherit on the handle
  1904. DUPLICATE_SAME_ACCESS
  1905. ))) {
  1906. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to open duplicate token handle with error (%d)."), GetLastError()));
  1907. bDupSucceeded = FALSE;
  1908. }
  1909. }
  1910. if (bDupSucceeded) {
  1911. hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) PolicyChangedThread,
  1912. (LPVOID) lpPolicyChangedInfo,
  1913. CREATE_SUSPENDED, &dwThreadID);
  1914. if (hThread) {
  1915. SetThreadPriority (hThread, THREAD_PRIORITY_IDLE);
  1916. ResumeThread (hThread);
  1917. CloseHandle (hThread);
  1918. } else {
  1919. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to create background thread (%d)."),
  1920. GetLastError()));
  1921. // free the resources if the thread didn't get launched
  1922. if (!(lpPolicyChangedInfo->bMachine)) {
  1923. if (lpPolicyChangedInfo->hToken) {
  1924. CloseHandle(lpPolicyChangedInfo->hToken);
  1925. lpPolicyChangedInfo->hToken = NULL;
  1926. }
  1927. }
  1928. LocalFree(lpPolicyChangedInfo);
  1929. }
  1930. }
  1931. else {
  1932. LocalFree(lpPolicyChangedInfo);
  1933. }
  1934. }
  1935. else {
  1936. DebugMsg((DM_WARNING, TEXT("ProcessGPOs: Failed to allocate memory for policy changed structure with %d."), GetLastError()));
  1937. }
  1938. }
  1939. }
  1940. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  1941. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  1942. CEvents ev(FALSE, EVENT_MACHINE_POLICY_APPLIED); ev.Report();
  1943. } else {
  1944. CEvents ev(FALSE, EVENT_USER_POLICY_APPLIED); ev.Report();
  1945. }
  1946. }
  1947. if (lpGPOInfo->hDoneEvent) {
  1948. PulseEvent (lpGPOInfo->hDoneEvent);
  1949. }
  1950. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  1951. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Computer Group Policy has been applied.")));
  1952. } else {
  1953. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: User Group Policy has been applied.")));
  1954. }
  1955. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOs: Leaving with %d."), bRetVal));
  1956. return bRetVal;
  1957. }
  1958. //*************************************************************
  1959. //
  1960. // PolicyChangedThread()
  1961. //
  1962. // Purpose: Sends the WM_SETTINGCHANGE message announcing
  1963. // that policy has changed. This is done on a
  1964. // separate thread because this could take many
  1965. // seconds to succeed if an application is hung
  1966. //
  1967. // Parameters: lpPolicyChangedInfo - GPO info
  1968. //
  1969. // Return: 0
  1970. //
  1971. //*************************************************************
  1972. DWORD WINAPI PolicyChangedThread (LPPOLICYCHANGEDINFO lpPolicyChangedInfo)
  1973. {
  1974. HINSTANCE hInst;
  1975. NTSTATUS Status;
  1976. BOOLEAN WasEnabled;
  1977. HANDLE hOldToken = NULL;
  1978. XLastError xe;
  1979. hInst = LoadLibrary (TEXT("userenv.dll"));
  1980. DebugMsg((DM_VERBOSE, TEXT("PolicyChangedThread: Calling UpdateUser with %d."), lpPolicyChangedInfo->bMachine));
  1981. // impersonate and update system parameter if it is not machine
  1982. if (!(lpPolicyChangedInfo->bMachine)) {
  1983. if (!ImpersonateUser(lpPolicyChangedInfo->hToken, &hOldToken))
  1984. {
  1985. xe = GetLastError();
  1986. DebugMsg((DM_WARNING, TEXT("PolicyChangedThread: Failed to impersonate user")));
  1987. goto Exit;
  1988. }
  1989. if (!UpdatePerUserSystemParameters(NULL, UPUSP_POLICYCHANGE)) {
  1990. DebugMsg((DM_WARNING, TEXT("PolicyChangedThread: UpdateUser failed with %d."), GetLastError()));
  1991. // ignoring error and continuing the next notifications
  1992. }
  1993. if (!RevertToUser(&hOldToken)) {
  1994. xe = GetLastError();
  1995. DebugMsg((DM_WARNING, TEXT("PolicyChangedThread: Failed to revert user")));
  1996. goto Exit;
  1997. }
  1998. }
  1999. DebugMsg((DM_VERBOSE, TEXT("PolicyChangedThread: Broadcast message for %d."), lpPolicyChangedInfo->bMachine));
  2000. //
  2001. // Broadcast the WM_SETTINGCHANGE message
  2002. //
  2003. Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  2004. if ( NT_SUCCESS(Status) )
  2005. {
  2006. DWORD dwBSM = BSM_ALLDESKTOPS | BSM_APPLICATIONS;
  2007. BroadcastSystemMessage (BSF_IGNORECURRENTTASK | BSF_FORCEIFHUNG,
  2008. &dwBSM,
  2009. WM_SETTINGCHANGE,
  2010. lpPolicyChangedInfo->bMachine, (LPARAM) TEXT("Policy"));
  2011. RtlAdjustPrivilege(SE_TCB_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  2012. }
  2013. DebugMsg((DM_VERBOSE, TEXT("PolicyChangedThread: Leaving")));
  2014. Exit:
  2015. if (!(lpPolicyChangedInfo->bMachine)) {
  2016. if (lpPolicyChangedInfo->hToken) {
  2017. CloseHandle(lpPolicyChangedInfo->hToken);
  2018. lpPolicyChangedInfo->hToken = NULL;
  2019. }
  2020. }
  2021. LocalFree(lpPolicyChangedInfo);
  2022. FreeLibraryAndExitThread (hInst, 0);
  2023. return 0;
  2024. }
  2025. //*************************************************************
  2026. //
  2027. // GetCurTime()
  2028. //
  2029. // Purpose: Returns current time in minutes, or 0 if there
  2030. // is a failure
  2031. //
  2032. //*************************************************************
  2033. DWORD GetCurTime()
  2034. {
  2035. DWORD dwCurTime = 0;
  2036. LARGE_INTEGER liCurTime;
  2037. if ( NT_SUCCESS( NtQuerySystemTime( &liCurTime) ) ) {
  2038. if ( RtlTimeToSecondsSince1980 ( &liCurTime, &dwCurTime) ) {
  2039. dwCurTime /= 60; // seconds to minutes
  2040. }
  2041. }
  2042. return dwCurTime;
  2043. }
  2044. //*************************************************************
  2045. //
  2046. // LoadGPExtension()
  2047. //
  2048. // Purpose: Loads a GP extension.
  2049. //
  2050. // Parameters: lpExt -- GP extension
  2051. // bRsopPlanningMode -- Is this during Rsop planning mode ?
  2052. //
  2053. // Return: TRUE if successful
  2054. // FALSE if an error occurs
  2055. //
  2056. //*************************************************************
  2057. BOOL LoadGPExtension( LPGPEXT lpExt, BOOL bRsopPlanningMode )
  2058. {
  2059. XLastError xe;
  2060. if ( !lpExt->bRegistryExt && lpExt->hInstance == NULL )
  2061. {
  2062. lpExt->hInstance = LoadLibrary( lpExt->lpDllName );
  2063. if ( lpExt->hInstance )
  2064. {
  2065. if ( lpExt->bNewInterface )
  2066. {
  2067. lpExt->pEntryPointEx = (PFNPROCESSGROUPPOLICYEX)GetProcAddress(lpExt->hInstance,
  2068. lpExt->lpFunctionName);
  2069. if ( lpExt->pEntryPointEx == NULL )
  2070. {
  2071. xe = GetLastError();
  2072. DebugMsg((DM_WARNING,
  2073. TEXT("LoadGPExtension: Failed to query ProcessGroupPolicyEx function entry point in dll <%s> with %d"),
  2074. lpExt->lpDllName, GetLastError()));
  2075. CEvents ev(TRUE, EVENT_EXT_FUNCEX_FAIL);
  2076. ev.AddArg(lpExt->lpDllName); ev.Report();
  2077. return FALSE;
  2078. }
  2079. }
  2080. else
  2081. {
  2082. lpExt->pEntryPoint = (PFNPROCESSGROUPPOLICY)GetProcAddress(lpExt->hInstance,
  2083. lpExt->lpFunctionName);
  2084. if ( lpExt->pEntryPoint == NULL )
  2085. {
  2086. xe = GetLastError();
  2087. DebugMsg((DM_WARNING,
  2088. TEXT("LoadGPExtension: Failed to query ProcessGroupPolicy function entry point in dll <%s> with %d"),
  2089. lpExt->lpDllName, GetLastError()));
  2090. CEvents ev(TRUE, EVENT_EXT_FUNC_FAIL);
  2091. ev.AddArg(lpExt->lpDllName); ev.Report();
  2092. return FALSE;
  2093. }
  2094. }
  2095. if ( bRsopPlanningMode ) {
  2096. if ( lpExt->lpRsopFunctionName ) {
  2097. lpExt->pRsopEntryPoint = (PFNGENERATEGROUPPOLICY)GetProcAddress(lpExt->hInstance,
  2098. lpExt->lpRsopFunctionName);
  2099. if ( lpExt->pRsopEntryPoint == NULL )
  2100. {
  2101. xe = GetLastError();
  2102. DebugMsg((DM_WARNING,
  2103. TEXT("LoadGPExtension: Failed to query GenerateGroupPolicy function entry point in dll <%s> with %d"),
  2104. lpExt->lpDllName, GetLastError()));
  2105. CEvents ev(TRUE, EVENT_EXT_FUNCRSOP_FAIL);
  2106. ev.AddArg(lpExt->lpDisplayName); ev.AddArg(lpExt->lpDllName); ev.Report();
  2107. return FALSE;
  2108. }
  2109. } else {
  2110. xe = ERROR_PROC_NOT_FOUND;
  2111. DebugMsg((DM_WARNING,
  2112. TEXT("LoadGPExtension: Failed to find Rsop entry point in dll <%s>"), lpExt->lpDllName ));
  2113. return FALSE;
  2114. }
  2115. }
  2116. }
  2117. else
  2118. {
  2119. xe = GetLastError();
  2120. DebugMsg((DM_WARNING, TEXT("LoadGPExtension: Failed to load dll <%s> with %d"),
  2121. lpExt->lpDllName, GetLastError()));
  2122. CEvents ev(TRUE, EVENT_EXT_LOAD_FAIL);
  2123. ev.AddArg(lpExt->lpDllName); ev.AddArgWin32Error(GetLastError()); ev.Report();
  2124. return FALSE;
  2125. }
  2126. }
  2127. return TRUE;
  2128. }
  2129. //*************************************************************
  2130. //
  2131. // UnloadGPExtensions()
  2132. //
  2133. // Purpose: Unloads the Group Policy extension dlls
  2134. //
  2135. // Parameters: lpGPOInfo - GP Information
  2136. //
  2137. //
  2138. // Return: TRUE if successful
  2139. // FALSE if an error occurs
  2140. //
  2141. //*************************************************************
  2142. BOOL UnloadGPExtensions (LPGPOINFO lpGPOInfo)
  2143. {
  2144. if ( !lpGPOInfo )
  2145. {
  2146. return TRUE;
  2147. }
  2148. LPGPEXT lpExt, lpTemp;
  2149. lpExt = lpGPOInfo->lpExtensions;
  2150. while ( lpExt )
  2151. {
  2152. lpTemp = lpExt->pNext;
  2153. if ( lpExt->hInstance )
  2154. {
  2155. FreeLibrary( lpExt->hInstance );
  2156. }
  2157. if ( lpExt->szEventLogSources )
  2158. {
  2159. LocalFree( lpExt->szEventLogSources );
  2160. }
  2161. if (lpExt->lpPrevStatus)
  2162. {
  2163. LocalFree(lpExt->lpPrevStatus);
  2164. }
  2165. LocalFree( lpExt );
  2166. lpExt = lpTemp;
  2167. }
  2168. lpGPOInfo->lpExtensions = 0;
  2169. return TRUE;
  2170. }
  2171. //*************************************************************
  2172. //
  2173. // ProcessGPOList()
  2174. //
  2175. // Purpose: Calls client side extensions to process gpos
  2176. //
  2177. // Parameters: lpExt - GP extension
  2178. // lpGPOInfo - GPT Information
  2179. // pDeletedGPOList - Deleted GPOs
  2180. // pChangedGPOList - New/changed GPOs
  2181. // bNoChanges - True if there are no GPO changes
  2182. // and GPO processing is forced
  2183. // pAsyncHandle - Context for async completion
  2184. //
  2185. // Return: TRUE if successful
  2186. // FALSE if an error occurs
  2187. //
  2188. //*************************************************************
  2189. DWORD ProcessGPOList (LPGPEXT lpExt,
  2190. LPGPOINFO lpGPOInfo,
  2191. PGROUP_POLICY_OBJECT pDeletedGPOList,
  2192. PGROUP_POLICY_OBJECT pChangedGPOList,
  2193. BOOL bNoChanges, ASYNCCOMPLETIONHANDLE pAsyncHandle,
  2194. HRESULT *phrRsopStatus )
  2195. {
  2196. LPTSTR lpGPTPath, lpDSPath;
  2197. INT iStrLen;
  2198. DWORD dwRet = ERROR_SUCCESS;
  2199. DWORD dwFlags = 0;
  2200. PGROUP_POLICY_OBJECT lpGPO;
  2201. TCHAR szStatusFormat[50];
  2202. TCHAR szVerbose[100];
  2203. DWORD dwSlowLinkCur = (lpGPOInfo->dwFlags & GP_SLOW_LINK) != 0;
  2204. IWbemServices *pLocalWbemServices;
  2205. HRESULT hr2 = S_OK;
  2206. *phrRsopStatus=S_OK;
  2207. //
  2208. // Verbose output
  2209. //
  2210. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Entering for extension %s"), lpExt->lpDisplayName));
  2211. if (lpGPOInfo->pStatusCallback) {
  2212. LoadString (g_hDllInstance, IDS_CALLEXTENSION, szStatusFormat, ARRAYSIZE(szStatusFormat));
  2213. wsprintf (szVerbose, szStatusFormat, lpExt->lpDisplayName);
  2214. lpGPOInfo->pStatusCallback(TRUE, szVerbose);
  2215. }
  2216. if (lpGPOInfo->dwFlags & GP_MACHINE) {
  2217. dwFlags |= GPO_INFO_FLAG_MACHINE;
  2218. }
  2219. if (lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD)
  2220. {
  2221. dwFlags |= GPO_INFO_FLAG_BACKGROUND;
  2222. }
  2223. if ( lpGPOInfo->dwFlags & GP_ASYNC_FOREGROUND )
  2224. {
  2225. dwFlags |= GPO_INFO_FLAG_ASYNC_FOREGROUND;
  2226. }
  2227. if (lpGPOInfo->dwFlags & GP_SLOW_LINK) {
  2228. dwFlags |= GPO_INFO_FLAG_SLOWLINK;
  2229. }
  2230. if ( dwSlowLinkCur != lpExt->lpPrevStatus->dwSlowLink ) {
  2231. dwFlags |= GPO_INFO_FLAG_LINKTRANSITION;
  2232. }
  2233. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  2234. dwFlags |= GPO_INFO_FLAG_VERBOSE;
  2235. }
  2236. if ( bNoChanges ) {
  2237. dwFlags |= GPO_INFO_FLAG_NOCHANGES;
  2238. }
  2239. //
  2240. // flag safe mode boot to CSE so that they can made a decision
  2241. // whether or not to apply policy
  2242. //
  2243. if ( GetSystemMetrics( SM_CLEANBOOT ) )
  2244. {
  2245. dwFlags |= GPO_INFO_FLAG_SAFEMODE_BOOT;
  2246. }
  2247. if (lpExt->bRsopTransition) {
  2248. dwFlags |= GPO_INFO_FLAG_LOGRSOP_TRANSITION;
  2249. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Passing in the rsop transition flag to Extension %s"),
  2250. lpExt->lpDisplayName));
  2251. }
  2252. if ( (lpGPOInfo->dwFlags & GP_FORCED_REFRESH) ||
  2253. ((!(lpGPOInfo->dwFlags & GP_BACKGROUND_THREAD)) && (lpExt->lpPrevStatus->bForceRefresh))) {
  2254. dwFlags |= GPO_INFO_FLAG_FORCED_REFRESH;
  2255. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Passing in the force refresh flag to Extension %s"),
  2256. lpExt->lpDisplayName));
  2257. }
  2258. //
  2259. // if it is rsop transition or changes case get the intf ptr
  2260. //
  2261. if ( (lpGPOInfo->bRsopLogging) &&
  2262. ((lpExt->bRsopTransition) || (!bNoChanges) || (dwFlags & GPO_INFO_FLAG_FORCED_REFRESH)) ) {
  2263. if (!(lpGPOInfo->pWbemServices) ) {
  2264. BOOL bCreated;
  2265. //
  2266. // Note that this code shouldn't be creating a namespace ever..
  2267. //
  2268. if (!GetWbemServices(lpGPOInfo, RSOP_NS_DIAG_ROOT, FALSE, NULL, &(lpGPOInfo->pWbemServices))) {
  2269. DebugMsg((DM_WARNING, TEXT("ProcessGPOList: Couldn't get the wbemservices intf pointer")));
  2270. lpGPOInfo->bRsopLogging = FALSE;
  2271. hr2 = *phrRsopStatus = E_FAIL;
  2272. }
  2273. }
  2274. pLocalWbemServices = lpGPOInfo->pWbemServices;
  2275. }
  2276. else {
  2277. pLocalWbemServices = NULL;
  2278. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: No changes. CSE will not be passed in the IwbemServices intf ptr")));
  2279. }
  2280. dwRet = ERROR_SUCCESS;
  2281. if ( lpExt->bRegistryExt )
  2282. {
  2283. //
  2284. // Registry pseudo extension.
  2285. //
  2286. //
  2287. // Log the extension specific status
  2288. //
  2289. if (pLocalWbemServices) {
  2290. lpGPOInfo->bRsopLogging = LogExtSessionStatus( pLocalWbemServices,
  2291. lpExt,
  2292. TRUE,
  2293. (lpExt->bRsopTransition || (dwFlags & GPO_INFO_FLAG_FORCED_REFRESH)
  2294. || (!bNoChanges)));
  2295. if (!lpGPOInfo->bRsopLogging) {
  2296. hr2 = E_FAIL;
  2297. }
  2298. }
  2299. if (!ProcessGPORegistryPolicy (lpGPOInfo, pChangedGPOList, phrRsopStatus)) {
  2300. DebugMsg((DM_WARNING, TEXT("ProcessGPOList: ProcessGPORegistryPolicy failed.")));
  2301. dwRet = E_FAIL;
  2302. }
  2303. } else { // if lpExt->bRegistryExt
  2304. //
  2305. // Regular extension
  2306. //
  2307. BOOL *pbAbort;
  2308. ASYNCCOMPLETIONHANDLE pAsyncHandleTemp;
  2309. if ( lpExt->dwRequireRegistry ) {
  2310. GPEXTSTATUS gpExtStatus;
  2311. ReadStatus( c_szRegistryExtName, lpGPOInfo, NULL, &gpExtStatus );
  2312. if ( !gpExtStatus.bStatus || gpExtStatus.dwStatus != ERROR_SUCCESS ) {
  2313. DebugMsg((DM_VERBOSE,
  2314. TEXT("ProcessGPOList: Skipping extension %s due to failed Registry extension."),
  2315. lpExt->lpDisplayName));
  2316. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  2317. CEvents ev(FALSE, EVENT_EXT_SKIPPED_DUETO_FAILED_REG);
  2318. ev.AddArg(lpExt->lpDisplayName); ev.Report();
  2319. }
  2320. dwRet = E_FAIL;
  2321. goto Exit;
  2322. }
  2323. }
  2324. //
  2325. // Log the extension specific status
  2326. //
  2327. if (pLocalWbemServices)
  2328. {
  2329. lpGPOInfo->bRsopLogging = LogExtSessionStatus( pLocalWbemServices,
  2330. lpExt,
  2331. lpExt->bNewInterface,
  2332. (lpExt->bRsopTransition || (dwFlags & GPO_INFO_FLAG_FORCED_REFRESH)
  2333. || (!bNoChanges)));
  2334. if (!lpGPOInfo->bRsopLogging) {
  2335. hr2 = E_FAIL;
  2336. }
  2337. }
  2338. if ( !LoadGPExtension( lpExt, FALSE ) ) {
  2339. DebugMsg((DM_WARNING, TEXT("ProcessGPOList: LoadGPExtension %s failed."), lpExt->lpDisplayName));
  2340. dwRet = E_FAIL;
  2341. goto Exit;
  2342. }
  2343. if ( lpGPOInfo->dwFlags & GP_MACHINE )
  2344. pbAbort = &g_bStopMachGPOProcessing;
  2345. else
  2346. pbAbort = &g_bStopUserGPOProcessing;
  2347. //
  2348. // Check if asynchronous processing is enabled
  2349. //
  2350. if ( lpExt->dwEnableAsynch )
  2351. pAsyncHandleTemp = pAsyncHandle;
  2352. else
  2353. pAsyncHandleTemp = 0;
  2354. if ( lpExt->bNewInterface ) {
  2355. dwRet = lpExt->pEntryPointEx( dwFlags,
  2356. lpGPOInfo->hToken,
  2357. lpGPOInfo->hKeyRoot,
  2358. pDeletedGPOList,
  2359. pChangedGPOList,
  2360. pAsyncHandleTemp,
  2361. pbAbort,
  2362. lpGPOInfo->pStatusCallback,
  2363. pLocalWbemServices,
  2364. phrRsopStatus);
  2365. } else {
  2366. dwRet = lpExt->pEntryPoint( dwFlags,
  2367. lpGPOInfo->hToken,
  2368. lpGPOInfo->hKeyRoot,
  2369. pDeletedGPOList,
  2370. pChangedGPOList,
  2371. pAsyncHandleTemp,
  2372. pbAbort,
  2373. lpGPOInfo->pStatusCallback );
  2374. }
  2375. RevertToSelf();
  2376. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Extension %s returned 0x%x."),
  2377. lpExt->lpDisplayName, dwRet));
  2378. if ( dwRet != ERROR_SUCCESS &&
  2379. dwRet != ERROR_OVERRIDE_NOCHANGES &&
  2380. dwRet != E_PENDING &&
  2381. dwRet != ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED )
  2382. {
  2383. CEvents ev(TRUE, EVENT_EXT_FAILED);
  2384. ev.AddArg(lpExt->lpDisplayName); ev.Report();
  2385. }
  2386. } // else of if lpext->bregistryext
  2387. if (pLocalWbemServices) {
  2388. if ((dwRet != E_PENDING) && (SUCCEEDED(*phrRsopStatus)) && (lpExt->bNewInterface)) {
  2389. //
  2390. // for the legacy extensions it will be marked clean
  2391. //
  2392. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Extension %s was able to log data. RsopStatus = 0x%x, dwRet = %d, Clearing the dirty bit"),
  2393. lpExt->lpDisplayName, *phrRsopStatus, dwRet));
  2394. UpdateExtSessionStatus(pLocalWbemServices, lpExt->lpKeyName, FALSE, dwRet);
  2395. }
  2396. else {
  2397. if (!lpExt->bNewInterface) {
  2398. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Extension %s doesn't support rsop logging"),
  2399. lpExt->lpDisplayName));
  2400. UpdateExtSessionStatus(pLocalWbemServices, lpExt->lpKeyName, TRUE, dwRet);
  2401. }
  2402. else if (FAILED(*phrRsopStatus)) {
  2403. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Extension %s was not able to log data. Error = 0x%x, dwRet = %d,leaving the log dirty"),
  2404. lpExt->lpDisplayName, *phrRsopStatus, dwRet ));
  2405. CEvents ev(TRUE, EVENT_EXT_RSOP_FAILED);
  2406. ev.AddArg(lpExt->lpDisplayName); ev.Report();
  2407. UpdateExtSessionStatus(pLocalWbemServices, lpExt->lpKeyName, TRUE, dwRet);
  2408. }
  2409. }
  2410. }
  2411. else {
  2412. DebugMsg((DM_VERBOSE, TEXT("ProcessGPOList: Extension %s status was not updated because there was no changes and no transition or rsop wasn't enabled"),
  2413. lpExt->lpDisplayName));
  2414. }
  2415. //
  2416. // if any of the things provider is supposed to log fails, log it as an error
  2417. // so that provider tries to log it again next time
  2418. //
  2419. *phrRsopStatus = (SUCCEEDED(*phrRsopStatus)) && (FAILED(hr2)) ? hr2 : *phrRsopStatus;
  2420. *phrRsopStatus = (!lpExt->bNewInterface) ? HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) : *phrRsopStatus;
  2421. Exit:
  2422. return dwRet;
  2423. }
  2424. //*************************************************************
  2425. //
  2426. // RefreshDisplay()
  2427. //
  2428. // Purpose: Starts control.exe
  2429. //
  2430. // Parameters: lpGPOInfo - GPT information
  2431. //
  2432. // Return: TRUE if successful
  2433. // FALSE if an error occurs
  2434. //
  2435. //*************************************************************
  2436. BOOL RefreshDisplay (LPGPOINFO lpGPOInfo)
  2437. {
  2438. STARTUPINFO si;
  2439. PROCESS_INFORMATION pi;
  2440. TCHAR szCmdLine[50];
  2441. BOOL Result;
  2442. HANDLE hOldToken;
  2443. //
  2444. // Verbose output
  2445. //
  2446. DebugMsg((DM_VERBOSE, TEXT("RefreshDisplay: Starting control.exe")));
  2447. //
  2448. // Initialize process startup info
  2449. //
  2450. si.cb = sizeof(STARTUPINFO);
  2451. si.lpReserved = NULL;
  2452. si.lpTitle = NULL;
  2453. si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
  2454. si.dwFlags = 0;
  2455. si.wShowWindow = SW_HIDE;
  2456. si.lpReserved2 = NULL;
  2457. si.cbReserved2 = 0;
  2458. si.lpDesktop = TEXT("");
  2459. //
  2460. // Impersonate the user so we get access checked correctly on
  2461. // the file we're trying to execute
  2462. //
  2463. if (!ImpersonateUser(lpGPOInfo->hToken, &hOldToken)) {
  2464. DebugMsg((DM_WARNING, TEXT("RefreshDisplay: Failed to impersonate user")));
  2465. return FALSE;
  2466. }
  2467. //
  2468. // Create the app
  2469. //
  2470. lstrcpy (szCmdLine, TEXT("control /policy"));
  2471. Result = CreateProcessAsUser(lpGPOInfo->hToken, NULL, szCmdLine, NULL,
  2472. NULL, FALSE, 0, NULL, NULL, &si, &pi);
  2473. //
  2474. // Revert to being 'ourself'
  2475. //
  2476. if (!RevertToUser(&hOldToken)) {
  2477. DebugMsg((DM_WARNING, TEXT("RefreshDisplay: Failed to revert to self")));
  2478. }
  2479. if (Result) {
  2480. WaitForSingleObject (pi.hProcess, 120000);
  2481. CloseHandle (pi.hThread);
  2482. CloseHandle (pi.hProcess);
  2483. } else {
  2484. DebugMsg((DM_WARNING, TEXT("RefreshDisplay: Failed to start control.exe with %d"), GetLastError()));
  2485. }
  2486. return(Result);
  2487. }
  2488. //*************************************************************
  2489. //
  2490. // RefreshPolicy()
  2491. //
  2492. // Purpose: External api that causes policy to be refreshed now
  2493. //
  2494. // Parameters: bMachine - Machine policy vs user policy
  2495. //
  2496. // Return: TRUE if successful
  2497. // FALSE if not
  2498. //
  2499. //*************************************************************
  2500. BOOL WINAPI RefreshPolicy (BOOL bMachine)
  2501. {
  2502. HANDLE hEvent;
  2503. DebugMsg((DM_VERBOSE, TEXT("RefreshPolicy: Entering with %d"), bMachine));
  2504. hEvent = OpenEvent (EVENT_MODIFY_STATE, FALSE,
  2505. bMachine ? MACHINE_POLICY_REFRESH_EVENT : USER_POLICY_REFRESH_EVENT);
  2506. if (hEvent) {
  2507. BOOL bRet = SetEvent (hEvent);
  2508. CloseHandle (hEvent);
  2509. if (!bRet) {
  2510. DebugMsg((DM_WARNING, TEXT("RefreshPolicy: Failed to set event with %d"), GetLastError()));
  2511. return FALSE;
  2512. }
  2513. } else {
  2514. DebugMsg((DM_WARNING, TEXT("RefreshPolicy: Failed to open event with %d"), GetLastError()));
  2515. return FALSE;
  2516. }
  2517. DebugMsg((DM_VERBOSE, TEXT("RefreshPolicy: Leaving.")));
  2518. return TRUE;
  2519. }
  2520. //*************************************************************
  2521. //
  2522. // RefreshPolicyEx()
  2523. //
  2524. // Purpose: External api that causes policy to be refreshed now
  2525. //
  2526. // Parameters: bMachine - Machine policy vs user policy.
  2527. // This API is synchronous and waits for the refresh to
  2528. // finish.
  2529. //
  2530. // Return: TRUE if successful
  2531. // FALSE if not
  2532. //
  2533. //*************************************************************
  2534. BOOL WINAPI RefreshPolicyEx (BOOL bMachine, DWORD dwOption)
  2535. {
  2536. XHandle xhEvent;
  2537. if (!dwOption)
  2538. return RefreshPolicy(bMachine);
  2539. if (dwOption == RP_FORCE) {
  2540. DebugMsg((DM_VERBOSE, TEXT("RefreshPolicyEx: Entering with force refresh %d"), bMachine));
  2541. xhEvent = OpenEvent (EVENT_MODIFY_STATE, FALSE,
  2542. bMachine ? MACHINE_POLICY_FORCE_REFRESH_EVENT : USER_POLICY_FORCE_REFRESH_EVENT);
  2543. }
  2544. else {
  2545. DebugMsg((DM_WARNING, TEXT("RefreshPolicyEx: Invalid option")));
  2546. SetLastError(ERROR_INVALID_PARAMETER);
  2547. return FALSE;
  2548. }
  2549. if (!xhEvent) {
  2550. DebugMsg((DM_WARNING, TEXT("RefreshPolicyEx: Failed to open event with %d"), GetLastError()));
  2551. return FALSE;
  2552. }
  2553. if (!SetEvent (xhEvent)) {
  2554. DebugMsg((DM_WARNING, TEXT("RefreshPolicyEx: Failed to set event with %d"), GetLastError()));
  2555. return FALSE;
  2556. }
  2557. DebugMsg((DM_VERBOSE, TEXT("RefreshPolicyEx: Leaving.")));
  2558. return TRUE;
  2559. }
  2560. //*************************************************************
  2561. //
  2562. // EnterCriticalPolicySection()
  2563. //
  2564. // Purpose: External api that causes policy to pause
  2565. // This allows an application to pause policy
  2566. // so that values don't change while it reads
  2567. // the settings.
  2568. //
  2569. // Parameters: bMachine - Pause machine policy or user policy
  2570. // dwTimeOut- Amount of time to wait for the policy handle
  2571. // dwFlags - Various flags. Look at the defn.
  2572. //
  2573. // Return: TRUE if successful
  2574. // FALSE if not
  2575. //
  2576. //*************************************************************
  2577. HANDLE WINAPI EnterCriticalPolicySectionEx (BOOL bMachine, DWORD dwTimeOut, DWORD dwFlags )
  2578. {
  2579. HANDLE hSection;
  2580. DWORD dwRet;
  2581. //
  2582. // Open the mutex
  2583. //
  2584. hSection = OpenMutex (SYNCHRONIZE, FALSE,
  2585. (bMachine ? MACHINE_POLICY_MUTEX : USER_POLICY_MUTEX));
  2586. if (!hSection) {
  2587. DebugMsg((DM_WARNING, TEXT("EnterCriticalPolicySection: Failed to open mutex with %d"),
  2588. GetLastError()));
  2589. return NULL;
  2590. }
  2591. //
  2592. // Claim the mutex
  2593. //
  2594. dwRet = WaitForSingleObject (hSection, dwTimeOut);
  2595. if ( dwRet == WAIT_FAILED) {
  2596. DebugMsg((DM_WARNING, TEXT("EnterCriticalPolicySection: Failed to wait on the mutex. Error = %d."),
  2597. GetLastError()));
  2598. CloseHandle( hSection );
  2599. return NULL;
  2600. }
  2601. if ( (dwFlags & ECP_FAIL_ON_WAIT_TIMEOUT) && (dwRet == WAIT_TIMEOUT) ) {
  2602. DebugMsg((DM_WARNING, TEXT("EnterCriticalPolicySection: Wait timed out on the mutex.")));
  2603. CloseHandle( hSection );
  2604. SetLastError(dwRet);
  2605. return NULL;
  2606. }
  2607. DebugMsg((DM_VERBOSE, TEXT("EnterCriticalPolicySection: %s critical section has been claimed. Handle = 0x%x"),
  2608. (bMachine ? TEXT("Machine") : TEXT("User")), hSection));
  2609. return hSection;
  2610. }
  2611. //*************************************************************
  2612. //
  2613. // LeaveCriticalPolicySection()
  2614. //
  2615. // Purpose: External api that causes policy to resume
  2616. // This api assumes the app has called
  2617. // EnterCriticalPolicySection first
  2618. //
  2619. // Parameters: hSection - mutex handle
  2620. //
  2621. // Return: TRUE if successful
  2622. // FALSE if not
  2623. //
  2624. //*************************************************************
  2625. BOOL WINAPI LeaveCriticalPolicySection (HANDLE hSection)
  2626. {
  2627. if (!hSection) {
  2628. DebugMsg((DM_WARNING, TEXT("LeaveCriticalPolicySection: null mutex handle.")));
  2629. SetLastError(ERROR_INVALID_PARAMETER);
  2630. return FALSE;
  2631. }
  2632. ReleaseMutex (hSection);
  2633. CloseHandle (hSection);
  2634. DebugMsg((DM_VERBOSE, TEXT("LeaveCriticalPolicySection: Critical section 0x%x has been released."),
  2635. hSection));
  2636. return TRUE;
  2637. }
  2638. //*************************************************************
  2639. //
  2640. // EnterCriticalPolicySection()
  2641. //
  2642. // Purpose: External api that causes policy to pause
  2643. // This allows an application to pause policy
  2644. // so that values don't change while it reads
  2645. // the settings.
  2646. //
  2647. // Parameters: bMachine - Pause machine policy or user policy
  2648. //
  2649. // Return: TRUE if successful
  2650. // FALSE if not
  2651. //
  2652. //*************************************************************
  2653. HANDLE WINAPI EnterCriticalPolicySection (BOOL bMachine)
  2654. {
  2655. return EnterCriticalPolicySectionEx(bMachine, 600000, 0);
  2656. }
  2657. //*************************************************************
  2658. //
  2659. // FreeGpoInfo()
  2660. //
  2661. // Purpose: Deletes an LPGPOINFO struct
  2662. //
  2663. // Parameters: pGpoInfo - Gpo info to free
  2664. //
  2665. //*************************************************************
  2666. BOOL FreeGpoInfo( LPGPOINFO pGpoInfo )
  2667. {
  2668. if ( pGpoInfo == NULL )
  2669. return TRUE;
  2670. FreeLists( pGpoInfo );
  2671. FreeSOMList( pGpoInfo->lpSOMList );
  2672. FreeSOMList( pGpoInfo->lpLoopbackSOMList );
  2673. FreeGpContainerList( pGpoInfo->lpGpContainerList );
  2674. FreeGpContainerList( pGpoInfo->lpLoopbackGpContainerList );
  2675. LocalFree( pGpoInfo->lpDNName );
  2676. RsopDeleteToken( pGpoInfo->pRsopToken );
  2677. ReleaseWbemServices( pGpoInfo );
  2678. LocalFree( pGpoInfo );
  2679. return TRUE;
  2680. }
  2681. //*************************************************************
  2682. //
  2683. // FreeGPOList()
  2684. //
  2685. // Purpose: Free's the link list of GPOs
  2686. //
  2687. // Parameters: pGPOList - Pointer to the head of the list
  2688. //
  2689. //
  2690. // Return: TRUE if successful
  2691. // FALSE if an error occurs
  2692. //
  2693. //*************************************************************
  2694. BOOL WINAPI FreeGPOList (PGROUP_POLICY_OBJECT pGPOList)
  2695. {
  2696. PGROUP_POLICY_OBJECT pGPOTemp;
  2697. while (pGPOList) {
  2698. pGPOTemp = pGPOList->pNext;
  2699. LocalFree (pGPOList);
  2700. pGPOList = pGPOTemp;
  2701. }
  2702. return TRUE;
  2703. }
  2704. //*************************************************************
  2705. //
  2706. // FreeLists()
  2707. //
  2708. // Purpose: Free's the lpExtFilterList and/or lpGPOList
  2709. //
  2710. // Parameters: lpGPOInfo - GPO info
  2711. //
  2712. //*************************************************************
  2713. void FreeLists( LPGPOINFO lpGPOInfo )
  2714. {
  2715. LPEXTFILTERLIST pExtFilterList = lpGPOInfo->lpExtFilterList;
  2716. //
  2717. // If bXferToExtList is True then it means that lpGPOInfo->lpExtFilterList
  2718. // owns the list of GPOs. Otherwise lpGPOInfo->lpGPOList owns the list
  2719. // of GPOs.
  2720. //
  2721. while ( pExtFilterList ) {
  2722. LPEXTFILTERLIST pTemp = pExtFilterList->pNext;
  2723. FreeExtList( pExtFilterList->lpExtList );
  2724. if ( lpGPOInfo->bXferToExtList )
  2725. LocalFree( pExtFilterList->lpGPO );
  2726. LocalFree( pExtFilterList );
  2727. pExtFilterList = pTemp;
  2728. }
  2729. if ( !lpGPOInfo->bXferToExtList )
  2730. FreeGPOList( lpGPOInfo->lpGPOList );
  2731. }
  2732. //*************************************************************
  2733. //
  2734. // FreeExtList()
  2735. //
  2736. // Purpose: Free's the lpExtList
  2737. //
  2738. // Parameters: pExtList - Extensions list
  2739. //
  2740. //*************************************************************
  2741. void FreeExtList( LPEXTLIST pExtList )
  2742. {
  2743. while (pExtList) {
  2744. LPEXTLIST pTemp = pExtList->pNext;
  2745. LocalFree( pExtList );
  2746. pExtList = pTemp;
  2747. }
  2748. }
  2749. //*************************************************************
  2750. //
  2751. // ShutdownGPOProcessing()
  2752. //
  2753. // Purpose: Begins aborting GPO processing
  2754. //
  2755. // Parameters: bMachine - Shutdown machine or user processing ?
  2756. //
  2757. //*************************************************************
  2758. void WINAPI ShutdownGPOProcessing( BOOL bMachine )
  2759. {
  2760. if ( bMachine )
  2761. g_bStopMachGPOProcessing = TRUE;
  2762. else
  2763. g_bStopUserGPOProcessing = TRUE;
  2764. }
  2765. //*************************************************************
  2766. //
  2767. // InitializeGPOCriticalSection, CloseGPOCriticalSection
  2768. //
  2769. // Purpose: Initialization and cleanup routines for critical sections
  2770. //
  2771. //*************************************************************
  2772. void InitializeGPOCriticalSection()
  2773. {
  2774. InitializeCriticalSection( &g_GPOCS );
  2775. InitializeCriticalSection( &g_StatusCallbackCS );
  2776. }
  2777. void CloseGPOCriticalSection()
  2778. {
  2779. DeleteCriticalSection( &g_StatusCallbackCS );
  2780. DeleteCriticalSection( &g_GPOCS );
  2781. }
  2782. //*************************************************************
  2783. //
  2784. // ProcessGroupPolicyCompletedEx()
  2785. //
  2786. // Purpose: Callback for asynchronous completion of an extension
  2787. //
  2788. // Parameters: refExtensionId - Unique guid of extension
  2789. // pAsyncHandle - Completion context
  2790. // dwStatus - Asynchronous completion status
  2791. // hrRsopStatus - Rsop Logging Status
  2792. //
  2793. // Returns: Win32 error code
  2794. //
  2795. //*************************************************************
  2796. DWORD ProcessGroupPolicyCompletedEx( REFGPEXTENSIONID extensionGuid,
  2797. ASYNCCOMPLETIONHANDLE pAsyncHandle,
  2798. DWORD dwStatus, HRESULT hrRsopStatus )
  2799. {
  2800. DWORD dwRet = E_FAIL;
  2801. TCHAR szExtension[64];
  2802. PGROUP_POLICY_OBJECT pGPOList = NULL;
  2803. LPGPOINFO lpGPOInfo = NULL;
  2804. BOOL bUsePerUserLocalSetting = FALSE;
  2805. DWORD dwCurrentTime = GetCurTime();
  2806. LPGPINFOHANDLE pGPHandle = (LPGPINFOHANDLE) pAsyncHandle;
  2807. if ( extensionGuid == 0 )
  2808. return ERROR_INVALID_PARAMETER;
  2809. GuidToString( extensionGuid, szExtension );
  2810. DebugMsg((DM_VERBOSE, TEXT("ProcessGroupPolicyCompleted: Entering. Extension = %s, dwStatus = 0x%x"),
  2811. szExtension, dwStatus));
  2812. EnterCriticalSection( &g_GPOCS );
  2813. if ( !(pGPHandle == g_pMachGPInfo || pGPHandle == g_pUserGPInfo) ) {
  2814. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion is stale"),
  2815. szExtension));
  2816. goto Exit;
  2817. }
  2818. DmAssert( pGPHandle->pGPOInfo != NULL );
  2819. if ( pGPHandle->pGPOInfo == NULL ) {
  2820. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion has invalid pGPHandle->pGPOInfo"),
  2821. szExtension));
  2822. goto Exit;
  2823. }
  2824. lpGPOInfo = pGPHandle->pGPOInfo;
  2825. if ( (lpGPOInfo->dwFlags & GP_MACHINE) && g_bStopMachGPOProcessing
  2826. || !(lpGPOInfo->dwFlags & GP_MACHINE) && g_bStopUserGPOProcessing ) {
  2827. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion, aborting due to machine shutdown or logoff"),
  2828. szExtension));
  2829. CEvents ev(TRUE, EVENT_GPO_PROC_STOPPED); ev.Report();
  2830. goto Exit;
  2831. }
  2832. if ( dwStatus != ERROR_SUCCESS ) {
  2833. //
  2834. // Extension returned error code, so no need to update history
  2835. //
  2836. dwRet = ERROR_SUCCESS;
  2837. goto Exit;
  2838. }
  2839. if ( pGPHandle == 0 ) {
  2840. DebugMsg((DM_WARNING, TEXT("Extension %s is using 0 as asynchronous completion handle"),
  2841. szExtension));
  2842. goto Exit;
  2843. }
  2844. bUsePerUserLocalSetting = !(lpGPOInfo->dwFlags & GP_MACHINE)
  2845. && ExtensionHasPerUserLocalSetting( szExtension, HKEY_LOCAL_MACHINE );
  2846. if ( ReadGPOList( szExtension, lpGPOInfo->hKeyRoot,
  2847. HKEY_LOCAL_MACHINE,
  2848. lpGPOInfo->lpwszSidUser,
  2849. TRUE, &pGPOList ) ) {
  2850. if ( SaveGPOList( szExtension, lpGPOInfo,
  2851. HKEY_LOCAL_MACHINE,
  2852. NULL,
  2853. FALSE, pGPOList ) ) {
  2854. if ( bUsePerUserLocalSetting ) {
  2855. if ( SaveGPOList( szExtension, lpGPOInfo,
  2856. HKEY_LOCAL_MACHINE,
  2857. lpGPOInfo->lpwszSidUser,
  2858. FALSE, pGPOList ) ) {
  2859. dwRet = ERROR_SUCCESS;
  2860. } else {
  2861. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion, failed to save GPOList"),
  2862. szExtension));
  2863. }
  2864. } else
  2865. dwRet = ERROR_SUCCESS;
  2866. } else {
  2867. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion, failed to save GPOList"),
  2868. szExtension));
  2869. }
  2870. } else {
  2871. DebugMsg((DM_WARNING, TEXT("Extension %s asynchronous completion, failed to read shadow GPOList"),
  2872. szExtension));
  2873. }
  2874. Exit:
  2875. FgPolicyRefreshInfo info = { GP_ReasonUnknown, GP_ModeAsyncForeground };
  2876. LPWSTR szSid = lpGPOInfo->dwFlags & GP_MACHINE ? 0 : lpGPOInfo->lpwszSidUser;
  2877. DWORD dwError;
  2878. if ( dwStatus == ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED )
  2879. {
  2880. FgPolicyRefreshInfo curInfo = { GP_ReasonUnknown, GP_ModeUnknown };
  2881. GetCurrentFgPolicyRefreshInfo( szSid, &curInfo );
  2882. SetPreviousFgPolicyRefreshInfo( szSid, curInfo );
  2883. info.mode = GP_ModeSyncForeground;
  2884. info.reason = GP_ReasonCSERequiresSync;
  2885. dwError = SetNextFgPolicyRefreshInfo( szSid,
  2886. info );
  2887. if ( dwError != ERROR_SUCCESS )
  2888. {
  2889. DebugMsg((DM_VERBOSE, TEXT("ProcessGroupPolicyCompletedEx: SetNextFgPolicyRefreshInfo failed, %x."), dwError ));
  2890. }
  2891. }
  2892. if ( dwRet == ERROR_SUCCESS )
  2893. {
  2894. //
  2895. // clear E_PENDING status code with status returned
  2896. //
  2897. BOOL bUsePerUserLocalSetting = !(lpGPOInfo->dwFlags & GP_MACHINE) && lpGPOInfo->lpwszSidUser != NULL;
  2898. GPEXTSTATUS gpExtStatus;
  2899. gpExtStatus.dwSlowLink = (lpGPOInfo->dwFlags & GP_SLOW_LINK) != 0;
  2900. gpExtStatus.dwRsopLogging = lpGPOInfo->bRsopLogging;
  2901. gpExtStatus.dwStatus = dwStatus;
  2902. gpExtStatus.dwTime = dwCurrentTime;
  2903. gpExtStatus.bForceRefresh = FALSE;
  2904. WriteStatus( szExtension, lpGPOInfo,
  2905. bUsePerUserLocalSetting ? lpGPOInfo->lpwszSidUser : NULL,
  2906. &gpExtStatus);
  2907. //
  2908. // Building up a dummy gpExt structure so that we can log the info required.
  2909. //
  2910. GPEXT gpExt;
  2911. TCHAR szSubKey[MAX_PATH]; // same as the path in readgpextensions
  2912. HKEY hKey;
  2913. TCHAR szDisplayName[MAX_PATH];
  2914. DWORD dwSize, dwType;
  2915. CHAR szFunctionName[100];
  2916. gpExt.lpKeyName = szExtension;
  2917. lstrcpy(szSubKey, GP_EXTENSIONS);
  2918. CheckSlash(szSubKey);
  2919. lstrcat(szSubKey, szExtension);
  2920. //
  2921. // Read the displayname so that we can log it..
  2922. //
  2923. szDisplayName[0] = TEXT('\0');
  2924. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  2925. szSubKey,
  2926. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  2927. dwSize = sizeof(szDisplayName);
  2928. if (RegQueryValueEx (hKey, NULL, NULL,
  2929. &dwType, (LPBYTE) szDisplayName,
  2930. &dwSize) != ERROR_SUCCESS) {
  2931. lstrcpyn (szDisplayName, szExtension, ARRAYSIZE(szDisplayName));
  2932. }
  2933. dwSize = sizeof(szFunctionName);
  2934. if ( RegQueryValueExA (hKey, "ProcessGroupPolicyEx", NULL,
  2935. &dwType, (LPBYTE) szFunctionName,
  2936. &dwSize) == ERROR_SUCCESS ) {
  2937. gpExt.bNewInterface = TRUE;
  2938. }
  2939. RegCloseKey(hKey);
  2940. }
  2941. gpExt.lpDisplayName = szDisplayName;
  2942. if ((lpGPOInfo->bRsopLogging)) {
  2943. XInterface<IWbemServices> xWbemServices;
  2944. GetWbemServices( lpGPOInfo, RSOP_NS_DIAG_ROOT, TRUE, FALSE, &xWbemServices);
  2945. if (xWbemServices) {
  2946. if (!gpExt.bNewInterface) {
  2947. DebugMsg((DM_VERBOSE, TEXT("ProcessGroupPolicyCompletedEx: Extension %s doesn't support rsop logging."),
  2948. szExtension));
  2949. UpdateExtSessionStatus(xWbemServices, szExtension, TRUE, dwRet);
  2950. }
  2951. else if (SUCCEEDED(hrRsopStatus)) {
  2952. DebugMsg((DM_VERBOSE, TEXT("ProcessGroupPolicyCompletedEx: Extension %s was able to log data. Error = 0x%x, dwRet = %d. Clearing the dirty bit"),
  2953. szExtension, hrRsopStatus, dwStatus));
  2954. UpdateExtSessionStatus(xWbemServices, szExtension, FALSE, dwRet);
  2955. }
  2956. else {
  2957. DebugMsg((DM_VERBOSE, TEXT("ProcessroupPolicyCompletedEx: Extension %s was not able to log data. Error = 0x%x, dwRet = %d. leaving the log dirty"),
  2958. szExtension, hrRsopStatus, dwStatus));
  2959. CEvents ev(TRUE, EVENT_EXT_RSOP_FAILED);
  2960. ev.AddArg(gpExt.lpDisplayName); ev.Report();
  2961. UpdateExtSessionStatus(xWbemServices, szExtension, TRUE, dwRet);
  2962. }
  2963. }
  2964. }
  2965. }
  2966. LeaveCriticalSection( &g_GPOCS );
  2967. DebugMsg((DM_VERBOSE, TEXT("ProcessGroupPolicyCompleted: Leaving. Extension = %s, Return status dwRet = 0x%x"),
  2968. szExtension, dwRet));
  2969. return dwRet;
  2970. }
  2971. //*************************************************************
  2972. //
  2973. // ProcessGroupPolicyCompleted()
  2974. //
  2975. // Purpose: Callback for asynchronous completion of an extension
  2976. //
  2977. // Parameters: refExtensionId - Unique guid of extension
  2978. // pAsyncHandle - Completion context
  2979. // dwStatus - Asynchronous completion status
  2980. //
  2981. // Returns: Win32 error code
  2982. //
  2983. //*************************************************************
  2984. DWORD ProcessGroupPolicyCompleted( REFGPEXTENSIONID extensionGuid,
  2985. ASYNCCOMPLETIONHANDLE pAsyncHandle,
  2986. DWORD dwStatus )
  2987. {
  2988. //
  2989. // Mark RSOP data as clean for legacy extensions
  2990. //
  2991. return ProcessGroupPolicyCompletedEx(extensionGuid, pAsyncHandle, dwStatus,
  2992. HRESULT_FROM_WIN32(S_OK));
  2993. }
  2994. //*************************************************************
  2995. //
  2996. // DebugPrintGPOList()
  2997. //
  2998. // Purpose: Prints GPO list
  2999. //
  3000. // Parameters: lpGPOInfo - GPO Info
  3001. //
  3002. //*************************************************************
  3003. void DebugPrintGPOList( LPGPOINFO lpGPOInfo )
  3004. {
  3005. //
  3006. // If we are in verbose mode, put the list of GPOs in the event log
  3007. //
  3008. PGROUP_POLICY_OBJECT lpGPO = NULL;
  3009. DWORD dwSize;
  3010. #if DBG
  3011. if (TRUE) {
  3012. #else
  3013. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  3014. #endif
  3015. LPTSTR lpTempList;
  3016. dwSize = 10;
  3017. lpGPO = lpGPOInfo->lpGPOList;
  3018. while (lpGPO) {
  3019. if (lpGPO->lpDisplayName) {
  3020. dwSize += (lstrlen (lpGPO->lpDisplayName) + 4);
  3021. }
  3022. lpGPO = lpGPO->pNext;
  3023. }
  3024. lpTempList = (LPWSTR) LocalAlloc (LPTR, (dwSize * sizeof(TCHAR)));
  3025. if (lpTempList) {
  3026. lstrcpy (lpTempList, TEXT(""));
  3027. lpGPO = lpGPOInfo->lpGPOList;
  3028. while (lpGPO) {
  3029. if (lpGPO->lpDisplayName) {
  3030. lstrcat (lpTempList, TEXT("\""));
  3031. lstrcat (lpTempList, lpGPO->lpDisplayName);
  3032. lstrcat (lpTempList, TEXT("\" "));
  3033. }
  3034. lpGPO = lpGPO->pNext;
  3035. }
  3036. if (lpGPOInfo->dwFlags & GP_VERBOSE) {
  3037. CEvents ev(FALSE, EVENT_GPO_LIST);
  3038. ev.AddArg(lpTempList); ev.Report();
  3039. }
  3040. DebugMsg((DM_VERBOSE, TEXT("DebugPrintGPOList: List of GPO(s) to process: %s"),
  3041. lpTempList));
  3042. LocalFree (lpTempList);
  3043. }
  3044. }
  3045. }
  3046. //*************************************************************
  3047. //
  3048. // UserPolicyCallback()
  3049. //
  3050. // Purpose: Callback function for status UI messages
  3051. //
  3052. // Parameters: bVerbose - Verbose message or not
  3053. // lpMessage - Message text
  3054. //
  3055. // Return: ERROR_SUCCESS if successful
  3056. // Win32 error code if an error occurs
  3057. //
  3058. //*************************************************************
  3059. DWORD UserPolicyCallback (BOOL bVerbose, LPWSTR lpMessage)
  3060. {
  3061. WCHAR szMsg[100];
  3062. LPWSTR lpMsg;
  3063. DWORD dwResult = ERROR_INVALID_FUNCTION;
  3064. if (lpMessage) {
  3065. lpMsg = lpMessage;
  3066. } else {
  3067. LoadString (g_hDllInstance, IDS_USER_SETTINGS, szMsg, 100);
  3068. lpMsg = szMsg;
  3069. }
  3070. DebugMsg((DM_VERBOSE, TEXT("UserPolicyCallback: Setting status UI to %s"), lpMsg));
  3071. EnterCriticalSection (&g_StatusCallbackCS);
  3072. if (g_pStatusMessageCallback) {
  3073. dwResult = g_pStatusMessageCallback(bVerbose, lpMsg);
  3074. } else {
  3075. DebugMsg((DM_VERBOSE, TEXT("UserPolicyCallback: Extension requested status UI when status UI is not available.")));
  3076. }
  3077. LeaveCriticalSection (&g_StatusCallbackCS);
  3078. return dwResult;
  3079. }
  3080. //*************************************************************
  3081. //
  3082. // MachinePolicyCallback()
  3083. //
  3084. // Purpose: Callback function for status UI messages
  3085. //
  3086. // Parameters: bVerbose - Verbose message or not
  3087. // lpMessage - Message text
  3088. //
  3089. // Return: ERROR_SUCCESS if successful
  3090. // Win32 error code if an error occurs
  3091. //
  3092. //*************************************************************
  3093. DWORD MachinePolicyCallback (BOOL bVerbose, LPWSTR lpMessage)
  3094. {
  3095. WCHAR szMsg[100];
  3096. LPWSTR lpMsg;
  3097. DWORD dwResult = ERROR_INVALID_FUNCTION;
  3098. if (lpMessage) {
  3099. lpMsg = lpMessage;
  3100. } else {
  3101. LoadString (g_hDllInstance, IDS_COMPUTER_SETTINGS, szMsg, 100);
  3102. lpMsg = szMsg;
  3103. }
  3104. DebugMsg((DM_VERBOSE, TEXT("MachinePolicyCallback: Setting status UI to %s"), lpMsg));
  3105. EnterCriticalSection (&g_StatusCallbackCS);
  3106. if (g_pStatusMessageCallback) {
  3107. dwResult = g_pStatusMessageCallback(bVerbose, lpMsg);
  3108. } else {
  3109. DebugMsg((DM_VERBOSE, TEXT("MachinePolicyCallback: Extension requested status UI when status UI is not available.")));
  3110. }
  3111. LeaveCriticalSection (&g_StatusCallbackCS);
  3112. return dwResult;
  3113. }
  3114. //*************************************************************
  3115. //
  3116. // CallDFS()
  3117. //
  3118. // Purpose: Calls DFS to initialize the domain / DC name
  3119. //
  3120. // Parameters: lpDomainName - Domain name
  3121. // lpDCName - DC name
  3122. //
  3123. // Return: TRUE if successful
  3124. // FALSE if an error occurs
  3125. //
  3126. //*************************************************************
  3127. //
  3128. // Once upon a time when this file was a C file,
  3129. // the definition of POINTER_TO_OFFSET looked like this,
  3130. //
  3131. // #define POINTER_TO_OFFSET(field, buffer) \
  3132. // ( ((PCHAR)field) -= ((ULONG_PTR)buffer) )
  3133. //
  3134. // Now, that we have decided to end antiquity and made this a C++ file,
  3135. // the new definition is,
  3136. //
  3137. #define POINTER_TO_OFFSET(field, buffer) \
  3138. ( field = (LPWSTR) ( (PCHAR)field -(ULONG_PTR)buffer ) )
  3139. NTSTATUS CallDFS(LPWSTR lpDomainName, LPWSTR lpDCName)
  3140. {
  3141. HANDLE DfsDeviceHandle = NULL;
  3142. PDFS_SPC_REFRESH_INFO DfsInfo;
  3143. ULONG lpDomainNameLen, lpDCNameLen, sizeNeeded;
  3144. OBJECT_ATTRIBUTES objectAttributes;
  3145. IO_STATUS_BLOCK ioStatusBlock;
  3146. NTSTATUS status;
  3147. UNICODE_STRING unicodeServerName;
  3148. lpDomainNameLen = (wcslen(lpDomainName) + 1) * sizeof(WCHAR);
  3149. lpDCNameLen = (wcslen(lpDCName) + 1) * sizeof(WCHAR);
  3150. sizeNeeded = sizeof(DFS_SPC_REFRESH_INFO) + lpDomainNameLen + lpDCNameLen;
  3151. DfsInfo = (PDFS_SPC_REFRESH_INFO)LocalAlloc(LPTR, sizeNeeded);
  3152. if (DfsInfo == NULL) {
  3153. DebugMsg((DM_WARNING, TEXT("CallDFS: LocalAlloc failed with %d"), GetLastError()));
  3154. return STATUS_INSUFFICIENT_RESOURCES;
  3155. }
  3156. DfsInfo->DomainName = (WCHAR *)((PCHAR)DfsInfo + sizeof(DFS_SPC_REFRESH_INFO));
  3157. DfsInfo->DCName = (WCHAR *)((PCHAR)DfsInfo->DomainName + lpDomainNameLen);
  3158. RtlCopyMemory(DfsInfo->DomainName,
  3159. lpDomainName,
  3160. lpDomainNameLen);
  3161. RtlCopyMemory(DfsInfo->DCName,
  3162. lpDCName,
  3163. lpDCNameLen);
  3164. POINTER_TO_OFFSET(DfsInfo->DomainName, DfsInfo);
  3165. POINTER_TO_OFFSET(DfsInfo->DCName, DfsInfo);
  3166. RtlInitUnicodeString( &unicodeServerName, L"\\Dfs");
  3167. InitializeObjectAttributes(
  3168. &objectAttributes,
  3169. &unicodeServerName,
  3170. OBJ_CASE_INSENSITIVE,
  3171. NULL,
  3172. NULL
  3173. );
  3174. status = NtOpenFile(
  3175. &DfsDeviceHandle,
  3176. SYNCHRONIZE | FILE_WRITE_DATA,
  3177. &objectAttributes,
  3178. &ioStatusBlock,
  3179. 0,
  3180. FILE_SYNCHRONOUS_IO_NONALERT
  3181. );
  3182. if (!NT_SUCCESS(status) ) {
  3183. DebugMsg((DM_WARNING, TEXT("CallDFS: NtOpenFile failed with 0x%x"), status));
  3184. LocalFree(DfsInfo);
  3185. return status;
  3186. }
  3187. status = NtFsControlFile(
  3188. DfsDeviceHandle,
  3189. NULL,
  3190. NULL,
  3191. NULL,
  3192. &ioStatusBlock,
  3193. FSCTL_DFS_SPC_REFRESH,
  3194. DfsInfo, sizeNeeded,
  3195. NULL, 0);
  3196. if (!NT_SUCCESS(status) ) {
  3197. DebugMsg((DM_WARNING, TEXT("CallDFS: NtFsControlFile failed with 0x%x"), status));
  3198. }
  3199. LocalFree(DfsInfo);
  3200. NtClose(DfsDeviceHandle);
  3201. return status;
  3202. }
  3203. //*************************************************************
  3204. //
  3205. // InitializePolicyProcessing
  3206. //
  3207. // Purpose: Initialises mutexes corresponding to user and machine
  3208. //
  3209. // Parameters: bMachine - Whether it is machine or user
  3210. //
  3211. // Return:
  3212. //
  3213. // Comments:
  3214. // These events/Mutexes need to be initialised right at the beginning
  3215. // because the ACls on these needs to be set before ApplyGroupPolicy can
  3216. // be called..
  3217. //
  3218. //*************************************************************
  3219. BOOL InitializePolicyProcessing(BOOL bMachine)
  3220. {
  3221. HANDLE hSection, hEvent;
  3222. XPtrLF<SECURITY_DESCRIPTOR> xsd;
  3223. SECURITY_ATTRIBUTES sa;
  3224. CSecDesc Csd;
  3225. XLastError xe;
  3226. Csd.AddLocalSystem();
  3227. Csd.AddAdministrators();
  3228. Csd.AddEveryOne(SYNCHRONIZE);
  3229. xsd = Csd.MakeSD();
  3230. if (!xsd) {
  3231. xe = GetLastError();
  3232. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create Security Descriptor with %d"),
  3233. GetLastError()));
  3234. // since this is happening in dll load we cannot log an event at this point..
  3235. return FALSE;
  3236. }
  3237. sa.lpSecurityDescriptor = (SECURITY_DESCRIPTOR *)xsd;
  3238. sa.bInheritHandle = FALSE;
  3239. sa.nLength = sizeof(sa);
  3240. //
  3241. // Synch mutex for group policies
  3242. //
  3243. hSection = CreateMutex (&sa, FALSE,
  3244. (bMachine ? MACHINE_POLICY_MUTEX : USER_POLICY_MUTEX));
  3245. if (!hSection) {
  3246. xe = GetLastError();
  3247. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create mutex with %d"),
  3248. GetLastError()));
  3249. return FALSE;
  3250. }
  3251. if (bMachine)
  3252. g_hPolicyCritMutexMach = hSection;
  3253. else
  3254. g_hPolicyCritMutexUser = hSection;
  3255. //
  3256. // Group Policy Notification events
  3257. //
  3258. //
  3259. // Create the changed notification event
  3260. //
  3261. hEvent = CreateEvent (&sa, TRUE, FALSE,
  3262. (bMachine) ? MACHINE_POLICY_APPLIED_EVENT : USER_POLICY_APPLIED_EVENT);
  3263. if (!hEvent) {
  3264. xe = GetLastError();
  3265. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create NotifyEvent with %d"),
  3266. GetLastError()));
  3267. return FALSE;
  3268. }
  3269. if (bMachine)
  3270. g_hPolicyNotifyEventMach = hEvent;
  3271. else
  3272. g_hPolicyNotifyEventUser = hEvent;
  3273. //
  3274. // Create the needfg event
  3275. //
  3276. hEvent = CreateEvent (&sa, FALSE, FALSE,
  3277. (bMachine) ? MACHINE_POLICY_REFRESH_NEEDFG_EVENT : USER_POLICY_REFRESH_NEEDFG_EVENT);
  3278. if (!hEvent) {
  3279. xe = GetLastError();
  3280. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create NeedFGEvent with %d"),
  3281. GetLastError()));
  3282. return FALSE;
  3283. }
  3284. if (bMachine)
  3285. g_hPolicyNeedFGEventMach = hEvent;
  3286. else
  3287. g_hPolicyNeedFGEventUser = hEvent;
  3288. //
  3289. // Create the done event
  3290. //
  3291. hEvent = CreateEvent (&sa, TRUE, FALSE,
  3292. (bMachine) ? MACHINE_POLICY_DONE_EVENT : USER_POLICY_DONE_EVENT);
  3293. if (!hEvent) {
  3294. xe = GetLastError();
  3295. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create hNotifyDoneEvent with %d"),
  3296. GetLastError()));
  3297. return FALSE;
  3298. }
  3299. if (bMachine)
  3300. g_hPolicyDoneEventMach = hEvent;
  3301. else
  3302. g_hPolicyDoneEventUser = hEvent;
  3303. //
  3304. // Create the machine policy - user policy sync event
  3305. //
  3306. if ( bMachine )
  3307. {
  3308. hEvent = CreateEvent( &sa,
  3309. TRUE,
  3310. FALSE,
  3311. MACH_POLICY_FOREGROUND_DONE_EVENT );
  3312. if ( !hEvent )
  3313. {
  3314. xe = GetLastError();
  3315. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create m/c-user policy sync event with %d"),
  3316. GetLastError()));
  3317. return FALSE;
  3318. }
  3319. else
  3320. {
  3321. g_hPolicyForegroundDoneEventMach = hEvent;
  3322. }
  3323. }
  3324. else
  3325. {
  3326. hEvent = CreateEvent( &sa,
  3327. TRUE,
  3328. FALSE,
  3329. USER_POLICY_FOREGROUND_DONE_EVENT );
  3330. if ( !hEvent )
  3331. {
  3332. xe = GetLastError();
  3333. DebugMsg((DM_WARNING, TEXT("InitializePolicyProcessing: Failed to create user policy/logon script sync event with %d"),
  3334. GetLastError()));
  3335. return FALSE;
  3336. }
  3337. else
  3338. {
  3339. g_hPolicyForegroundDoneEventUser = hEvent;
  3340. }
  3341. }
  3342. DebugMsg((DM_VERBOSE, TEXT("InitializePolicyProcessing: Initialised %s Mutex/Events"),
  3343. bMachine ? TEXT("Machine"): TEXT("User")));
  3344. return TRUE;
  3345. }
  3346. USERENVAPI
  3347. DWORD
  3348. WINAPI
  3349. WaitForUserPolicyForegroundProcessing()
  3350. {
  3351. DWORD dwError = ERROR_SUCCESS;
  3352. HANDLE hEvent = OpenEvent( SYNCHRONIZE, FALSE, USER_POLICY_FOREGROUND_DONE_EVENT );
  3353. if ( hEvent )
  3354. {
  3355. if ( WaitForSingleObject( hEvent, INFINITE ) == WAIT_FAILED )
  3356. {
  3357. dwError = GetLastError();
  3358. DebugMsg((DM_VERBOSE, TEXT("WaitForUserPolicyForegroundProcessing: Failed, %x"), dwError ));
  3359. }
  3360. CloseHandle( hEvent );
  3361. }
  3362. else
  3363. {
  3364. dwError = GetLastError();
  3365. DebugMsg((DM_VERBOSE, TEXT("WaitForUserPolicyForegroundProcessing: Failed, %x"), dwError ));
  3366. }
  3367. return dwError;
  3368. }
  3369. USERENVAPI
  3370. DWORD
  3371. WINAPI
  3372. WaitForMachinePolicyForegroundProcessing()
  3373. {
  3374. DWORD dwError = ERROR_SUCCESS;
  3375. HANDLE hEvent = OpenEvent( SYNCHRONIZE, FALSE, MACH_POLICY_FOREGROUND_DONE_EVENT );
  3376. if ( hEvent )
  3377. {
  3378. if ( WaitForSingleObject( hEvent, INFINITE ) == WAIT_FAILED )
  3379. {
  3380. dwError = GetLastError();
  3381. DebugMsg((DM_VERBOSE, TEXT("WaitForMachinePolicyForegroundProcessing: Failed, %x"), dwError ));
  3382. }
  3383. CloseHandle( hEvent );
  3384. }
  3385. else
  3386. {
  3387. dwError = GetLastError();
  3388. DebugMsg((DM_VERBOSE, TEXT("WaitForMachinePolicyForegroundProcessing: Failed, %x"), dwError ));
  3389. }
  3390. return dwError;
  3391. }
  3392. extern "C" DWORD
  3393. SignalUserPolicyForegroundProcessingDone()
  3394. {
  3395. DWORD dwError = ERROR_SUCCESS;
  3396. if ( !SetEvent( g_hPolicyForegroundDoneEventUser ) )
  3397. {
  3398. dwError = GetLastError();
  3399. DebugMsg((DM_VERBOSE, TEXT("SignalUserPolicyForegroundProcessingDone: Failed, %x"), dwError ));
  3400. }
  3401. return dwError;
  3402. }
  3403. extern "C" DWORD
  3404. SignalMachinePolicyForegroundProcessingDone()
  3405. {
  3406. DWORD dwError = ERROR_SUCCESS;
  3407. if ( !SetEvent( g_hPolicyForegroundDoneEventMach ) )
  3408. {
  3409. dwError = GetLastError();
  3410. DebugMsg((DM_VERBOSE, TEXT("SignalForMachinePolicyForegroundProcessingDone: Failed, %x"), dwError ));
  3411. }
  3412. return dwError;
  3413. }