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

448 lines
12 KiB

  1. //*************************************************************
  2. //
  3. // Group Policy Notification
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1997-1998
  7. // All rights reserved
  8. //
  9. // Notes: There is a small window where notifications
  10. // can be lost. If while processing an eMonitor workitem
  11. // a policy event is Pulsed then that notification will
  12. // be lost. This window can be closed by using two threads.
  13. //
  14. // History: 28-Sep-98 SitaramR Created
  15. //
  16. //*************************************************************
  17. #include "gphdr.h"
  18. //
  19. // Work items for notification thread
  20. //
  21. enum EWorkType { eMonitor, // Monitor events
  22. eTerminate }; // Stop monitoring
  23. //
  24. // Entry in list of registered events
  25. //
  26. typedef struct _GPNOTIFINFO
  27. {
  28. HANDLE hEvent; // Event to be signaled
  29. BOOL bMachine; // Machine policy notifcation ?
  30. struct _GPNOTIFINFO * pNext; // Singly linked list ptr
  31. } GPNOTIFINFO;
  32. typedef struct _GPNOTIFICATION
  33. {
  34. HANDLE hThread; // Notification thread
  35. HANDLE hThreadEvent; // For signaling notification thread (Ordering of fields is important)
  36. HANDLE hMachEvent; // Event signaled by machine policy change
  37. HANDLE hUserEvent; // Event signaled by user policy change
  38. enum EWorkType eWorkType; // Work descrpition for notification thread
  39. GPNOTIFINFO * pNotifList; // List of registered events
  40. } GPNOTIFICATION;
  41. GPNOTIFICATION g_Notif = { NULL,
  42. NULL,
  43. NULL,
  44. NULL,
  45. eMonitor,
  46. NULL };
  47. CRITICAL_SECTION g_NotifyCS; // Lock
  48. //
  49. // Forward decls
  50. //
  51. DWORD WINAPI NotificationThread();
  52. void NotifyEvents( BOOL bMachine );
  53. //*************************************************************
  54. //
  55. // InitNotifSupport, ShutdownNotifSupport
  56. //
  57. // Purpose: Initialization and cleanup routines
  58. //
  59. //*************************************************************
  60. void InitializeNotifySupport()
  61. {
  62. InitializeCriticalSection( &g_NotifyCS );
  63. }
  64. void ShutdownNotifySupport()
  65. {
  66. BOOL fWait = FALSE;
  67. DWORD dwResult;
  68. {
  69. EnterCriticalSection( &g_NotifyCS );
  70. if ( g_Notif.hThread != NULL )
  71. {
  72. //
  73. // Set up terminate workitem and then signal thread
  74. //
  75. fWait = TRUE;
  76. g_Notif.eWorkType = eTerminate;
  77. SetEvent( g_Notif.hThreadEvent );
  78. }
  79. LeaveCriticalSection( &g_NotifyCS );
  80. }
  81. if ( fWait )
  82. WaitForSingleObject( g_Notif.hThread, INFINITE );
  83. {
  84. EnterCriticalSection( &g_NotifyCS );
  85. //
  86. // Close all opened handles
  87. //
  88. if ( g_Notif.hThread != NULL )
  89. CloseHandle( g_Notif.hThread );
  90. if ( g_Notif.hThreadEvent != NULL )
  91. CloseHandle( g_Notif.hThreadEvent );
  92. if ( g_Notif.hUserEvent != NULL )
  93. CloseHandle( g_Notif.hUserEvent );
  94. if ( g_Notif.hMachEvent != NULL )
  95. CloseHandle( g_Notif.hMachEvent );
  96. LeaveCriticalSection( &g_NotifyCS );
  97. }
  98. DeleteCriticalSection( &g_NotifyCS );
  99. }
  100. //*************************************************************
  101. //
  102. // RegisterGPNotification
  103. //
  104. // Purpose: Registers for a group policy change notification
  105. //
  106. // Parameters: hEvent - Event to be notified
  107. // bMachine - If true, then register for
  108. // machine policy notification, else
  109. // user policy notification
  110. //
  111. // Returns: True if successful
  112. // False if error occurs
  113. //
  114. //*************************************************************
  115. BOOL WINAPI RegisterGPNotification( IN HANDLE hEvent, IN BOOL bMachine )
  116. {
  117. BOOL bResult = FALSE;
  118. BOOL bNotifyThread = FALSE;
  119. GPNOTIFINFO *pNotifInfo = NULL;
  120. EnterCriticalSection( &g_NotifyCS );
  121. //
  122. // Create events and thread as needed
  123. //
  124. if ( g_Notif.hThreadEvent == NULL )
  125. {
  126. g_Notif.hThreadEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  127. if ( g_Notif.hThreadEvent == NULL )
  128. goto Exit;
  129. }
  130. if ( g_Notif.hMachEvent == NULL )
  131. {
  132. g_Notif.hMachEvent = OpenEvent (SYNCHRONIZE, FALSE, MACHINE_POLICY_APPLIED_EVENT);
  133. if ( g_Notif.hMachEvent == NULL ) {
  134. DebugMsg((DM_WARNING, TEXT("RegisterGPNotification: CreateEvent failed with %d"),
  135. GetLastError()));
  136. goto Exit;
  137. }
  138. bNotifyThread = TRUE;
  139. }
  140. if ( !bMachine && g_Notif.hUserEvent == NULL )
  141. {
  142. g_Notif.hUserEvent = OpenEvent (SYNCHRONIZE, FALSE, USER_POLICY_APPLIED_EVENT);
  143. if ( g_Notif.hUserEvent == NULL ) {
  144. DebugMsg((DM_WARNING, TEXT("RegisterGPNotification: CreateEvent failed with %d"),
  145. GetLastError()));
  146. goto Exit;
  147. }
  148. bNotifyThread = TRUE;
  149. }
  150. if ( g_Notif.hThread == NULL )
  151. {
  152. DWORD dwThreadId;
  153. g_Notif.hThread = CreateThread( NULL,
  154. 0,
  155. (LPTHREAD_START_ROUTINE) NotificationThread,
  156. 0,
  157. 0,
  158. &dwThreadId );
  159. if ( g_Notif.hThread == NULL ) {
  160. DebugMsg((DM_WARNING, TEXT("RegisterGPNotification: CreateThread failed with %d"),
  161. GetLastError()));
  162. goto Exit;
  163. }
  164. bNotifyThread = TRUE;
  165. }
  166. if ( bNotifyThread )
  167. {
  168. //
  169. // Notify thread that there is a new workitem, possibly
  170. // user event has been added.
  171. //
  172. g_Notif.eWorkType = eMonitor;
  173. SetEvent( g_Notif.hThreadEvent );
  174. }
  175. //
  176. // Add event to beginning of list
  177. //
  178. pNotifInfo = (GPNOTIFINFO *) LocalAlloc( LPTR, sizeof(GPNOTIFINFO) );
  179. if ( pNotifInfo == NULL ) {
  180. DebugMsg((DM_WARNING, TEXT("RegisterGPNotification: LocalAlloc failed with %d"),
  181. GetLastError()));
  182. goto Exit;
  183. }
  184. pNotifInfo->hEvent = hEvent;
  185. pNotifInfo->bMachine = bMachine;
  186. pNotifInfo->pNext = g_Notif.pNotifList;
  187. g_Notif.pNotifList = pNotifInfo;
  188. bResult = TRUE;
  189. Exit:
  190. LeaveCriticalSection( &g_NotifyCS );
  191. return bResult;
  192. }
  193. //*************************************************************
  194. //
  195. // UnregisterGPNotification
  196. //
  197. // Purpose: Removes registration for a group policy change notification
  198. //
  199. // Parameters: hEvent - Event to be removed
  200. //
  201. // Return: True if successful
  202. // False if error occurs
  203. //
  204. //*************************************************************
  205. BOOL WINAPI UnregisterGPNotification( IN HANDLE hEvent )
  206. {
  207. BOOL bFound = FALSE;
  208. GPNOTIFINFO *pTrailPtr = NULL;
  209. GPNOTIFINFO *pCurPtr = NULL;
  210. EnterCriticalSection( &g_NotifyCS );
  211. pCurPtr = g_Notif.pNotifList;
  212. while ( pCurPtr != NULL )
  213. {
  214. if ( pCurPtr->hEvent == hEvent )
  215. {
  216. //
  217. // Found match, so delete entry
  218. //
  219. if ( pTrailPtr == NULL )
  220. {
  221. //
  222. // First elem of list matched
  223. //
  224. g_Notif.pNotifList = pCurPtr->pNext;
  225. }
  226. else
  227. pTrailPtr->pNext = pCurPtr->pNext;
  228. LocalFree( pCurPtr );
  229. bFound = TRUE;
  230. break;
  231. }
  232. //
  233. // Advance down the list
  234. //
  235. pTrailPtr = pCurPtr;
  236. pCurPtr = pCurPtr->pNext;
  237. }
  238. LeaveCriticalSection( &g_NotifyCS );
  239. return bFound;
  240. }
  241. //*************************************************************
  242. //
  243. // CGPNotification::NotificationThread
  244. //
  245. // Purpose: Separate thread for notifications
  246. //
  247. // Returns: 0
  248. //
  249. //*************************************************************
  250. DWORD WINAPI NotificationThread()
  251. {
  252. DWORD cEvents = 2;
  253. BOOL fShutdown = FALSE;
  254. HINSTANCE hInst = LoadLibrary (TEXT("userenv.dll"));
  255. {
  256. EnterCriticalSection( &g_NotifyCS );
  257. //
  258. // The event fields in g_Notif are ordered as hThreadEvent,
  259. // hMachEvent and finally hUserEvent. The first two events have
  260. // to be successfully created in order for this thread to run
  261. // (see asserts). If the user event has been successfully created
  262. // then that too is monitored.
  263. //
  264. DmAssert( g_Notif.hThreadEvent != NULL && g_Notif.hMachEvent != NULL );
  265. if ( g_Notif.hUserEvent != NULL )
  266. cEvents = 3;
  267. LeaveCriticalSection( &g_NotifyCS );
  268. }
  269. while ( !fShutdown )
  270. {
  271. DWORD dwResult = WaitForMultipleObjects( cEvents,
  272. &g_Notif.hThreadEvent,
  273. FALSE,
  274. INFINITE );
  275. EnterCriticalSection( &g_NotifyCS );
  276. if ( dwResult == WAIT_FAILED )
  277. {
  278. DebugMsg((DM_WARNING, TEXT("GPNotification: WaitforMultipleObjects failed")));
  279. fShutdown = TRUE;
  280. }
  281. else if ( dwResult == WAIT_OBJECT_0 )
  282. {
  283. ResetEvent( g_Notif.hThreadEvent );
  284. if ( g_Notif.eWorkType == eMonitor )
  285. {
  286. //
  287. // Start monitoring user events too
  288. //
  289. if ( g_Notif.hUserEvent != NULL )
  290. cEvents = 3;
  291. }
  292. else
  293. fShutdown = TRUE;
  294. }
  295. else if ( dwResult == WAIT_OBJECT_0 + 1 || dwResult == WAIT_OBJECT_0 + 2 )
  296. {
  297. BOOL bMachine = (dwResult == WAIT_OBJECT_0 + 1);
  298. NotifyEvents( bMachine );
  299. if ( g_Notif.pNotifList == NULL )
  300. fShutdown = TRUE;
  301. }
  302. else
  303. {
  304. if ( dwResult == WAIT_ABANDONED_0 || dwResult == WAIT_ABANDONED_0 + 1 )
  305. fShutdown = TRUE;
  306. else
  307. {
  308. CloseHandle( g_Notif.hUserEvent );
  309. g_Notif.hUserEvent = NULL;
  310. cEvents = 2;
  311. }
  312. }
  313. if ( fShutdown )
  314. {
  315. //
  316. // Close all handles and thread
  317. //
  318. CloseHandle( g_Notif.hThreadEvent );
  319. g_Notif.hThreadEvent = NULL;
  320. if ( g_Notif.hMachEvent != NULL )
  321. {
  322. CloseHandle( g_Notif.hMachEvent );
  323. g_Notif.hMachEvent = NULL;
  324. }
  325. if ( g_Notif.hUserEvent != NULL )
  326. {
  327. CloseHandle( g_Notif.hUserEvent );
  328. g_Notif.hUserEvent = NULL;
  329. }
  330. CloseHandle( g_Notif.hThread );
  331. g_Notif.hThread = NULL;
  332. }
  333. LeaveCriticalSection( &g_NotifyCS );
  334. }
  335. if ( hInst != NULL )
  336. FreeLibraryAndExitThread (hInst, 0);
  337. return 0;
  338. }
  339. //*************************************************************
  340. //
  341. // NotifyEvents
  342. //
  343. // Purpose: Notifies registered events
  344. //
  345. // Parameters: bMachine - Is this a machine policy change ?
  346. //
  347. //*************************************************************
  348. void NotifyEvents( BOOL bMachine )
  349. {
  350. GPNOTIFINFO *pNotifInfo = NULL;
  351. pNotifInfo = g_Notif.pNotifList;
  352. while ( pNotifInfo != NULL )
  353. {
  354. if ( pNotifInfo->bMachine == bMachine )
  355. {
  356. SetEvent( pNotifInfo->hEvent );
  357. }
  358. pNotifInfo = pNotifInfo->pNext;
  359. }
  360. }