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

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