3 * Copyright (C) 2006 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: lib/userenv/gpolicy.c
23 * PURPOSE: Group policy functions
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 typedef struct _GP_NOTIFY
35 struct _GP_NOTIFY
*Next
;
38 } GP_NOTIFY
, *PGP_NOTIFY
;
46 static const WCHAR szLocalGPApplied
[] = L
"userenv: User Group Policy has been applied";
47 static const WCHAR szLocalGPMutex
[] = L
"userenv: user policy mutex";
48 static const WCHAR szMachineGPApplied
[] = L
"Global\\userenv: Machine Group Policy has been applied";
49 static const WCHAR szMachineGPMutex
[] = L
"Global\\userenv: machine policy mutex";
51 static CRITICAL_SECTION GPNotifyLock
;
52 static PGP_NOTIFY NotificationList
= NULL
;
53 static GP_ACTION GPNotificationAction
= gpaUpdate
;
54 static HANDLE hNotificationThread
= NULL
;
55 static HANDLE hNotificationThreadEvent
= NULL
;
56 static HANDLE hLocalGPAppliedEvent
= NULL
;
57 static HANDLE hMachineGPAppliedEvent
= NULL
;
60 InitializeGPNotifications(VOID
)
62 InitializeCriticalSection(&GPNotifyLock
);
66 UninitializeGPNotifications(VOID
)
68 EnterCriticalSection(&GPNotifyLock
);
70 /* rundown the notification thread */
71 if (hNotificationThread
!= NULL
)
73 ASSERT(hNotificationThreadEvent
!= NULL
);
75 /* notify the thread */
76 GPNotificationAction
= gpaTerminate
;
77 SetEvent(hNotificationThreadEvent
);
79 LeaveCriticalSection(&GPNotifyLock
);
81 /* wait for the thread to terminate itself */
82 WaitForSingleObject(hNotificationThread
,
85 EnterCriticalSection(&GPNotifyLock
);
87 if (hNotificationThread
!= NULL
)
89 /* the handle should be closed by the thread,
90 just in case that didn't happen for an unknown reason */
91 CloseHandle(hNotificationThread
);
92 hNotificationThread
= NULL
;
96 if (hNotificationThreadEvent
!= NULL
)
98 CloseHandle(hNotificationThreadEvent
);
99 hNotificationThreadEvent
= NULL
;
102 LeaveCriticalSection(&GPNotifyLock
);
104 DeleteCriticalSection(&GPNotifyLock
);
108 NotifyGPEvents(IN BOOL bMachine
)
110 PGP_NOTIFY Notify
= NotificationList
;
112 while (Notify
!= NULL
)
114 if (Notify
->bMachine
== bMachine
)
116 SetEvent(Notify
->hEvent
);
119 Notify
= Notify
->Next
;
124 GPNotificationThreadProc(IN LPVOID lpParameter
)
127 DWORD WaitResult
, WaitCount
;
128 HANDLE WaitHandles
[3];
130 /* reference the library so we don't screw up if the application
131 causes the DLL to unload while this thread is still running */
132 if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
136 ASSERT(hModule
== hInstance
);
138 EnterCriticalSection(&GPNotifyLock
);
140 ASSERT(hNotificationThreadEvent
!= NULL
);
141 WaitHandles
[0] = hNotificationThreadEvent
;
144 ASSERT(hMachineGPAppliedEvent
!= NULL
);
146 if (NotificationList
== NULL
)
150 WaitHandles
[1] = hMachineGPAppliedEvent
;
152 if (hLocalGPAppliedEvent
!= NULL
)
154 WaitHandles
[2] = hLocalGPAppliedEvent
;
158 LeaveCriticalSection(&GPNotifyLock
);
160 WaitResult
= WaitForMultipleObjects(WaitCount
,
165 EnterCriticalSection(&GPNotifyLock
);
167 if (WaitResult
!= WAIT_FAILED
)
169 if (WaitResult
== WAIT_OBJECT_0
)
171 ResetEvent(hNotificationThreadEvent
);
173 if (GPNotificationAction
== gpaTerminate
)
175 /* terminate the thread */
179 else if (WaitResult
== WAIT_OBJECT_0
+ 1 || WaitResult
== WAIT_OBJECT_0
+ 2)
181 /* group policies have been applied */
182 if (NotificationList
!= NULL
)
184 NotifyGPEvents((WaitResult
== WAIT_OBJECT_0
+ 1));
187 else if (WaitResult
== WAIT_ABANDONED_0
+ 2)
189 /* In case the local group policies event was abandoned, keep watching!
190 But close the handle as it's no longer of any use. */
191 if (hLocalGPAppliedEvent
!= NULL
)
193 CloseHandle(hLocalGPAppliedEvent
);
194 hLocalGPAppliedEvent
= NULL
;
197 else if (WaitResult
== WAIT_ABANDONED_0
|| WaitResult
== WAIT_ABANDONED_0
+ 1)
199 /* terminate the thread if the machine group policies event was abandoned
200 or for some reason the rundown event got abandoned. */
205 DPRINT("Unexpected wait result watching the group policy events: 0x%x\n", WaitResult
);
210 if (NotificationList
== NULL
)
218 /* cleanup handles no longer used */
219 ASSERT(hNotificationThread
!= NULL
);
220 ASSERT(hNotificationThreadEvent
!= NULL
);
222 CloseHandle(hNotificationThread
);
223 CloseHandle(hNotificationThreadEvent
);
224 hNotificationThread
= NULL
;
225 hNotificationThreadEvent
= NULL
;
227 if (hLocalGPAppliedEvent
!= NULL
)
229 CloseHandle(hLocalGPAppliedEvent
);
230 hLocalGPAppliedEvent
= NULL
;
232 if (hMachineGPAppliedEvent
!= NULL
)
234 CloseHandle(hMachineGPAppliedEvent
);
235 hMachineGPAppliedEvent
= NULL
;
238 LeaveCriticalSection(&GPNotifyLock
);
240 /* dereference the library and exit */
241 FreeLibraryAndExitThread(hModule
,
246 DPRINT1("Referencing the library failed!\n");
253 CreateGPEvent(IN BOOL bMachine
,
254 IN PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
257 SECURITY_ATTRIBUTES SecurityAttributes
;
259 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
260 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
261 SecurityAttributes
.bInheritHandle
= FALSE
;
263 hEvent
= CreateEventW(&SecurityAttributes
,
266 (bMachine
? szMachineGPApplied
: szLocalGPApplied
));
272 RegisterGPNotification(IN HANDLE hEvent
,
276 PSECURITY_DESCRIPTOR lpSecurityDescriptor
= NULL
;
279 EnterCriticalSection(&GPNotifyLock
);
281 /* create the thread notification event */
282 if (hNotificationThreadEvent
== NULL
)
284 hNotificationThreadEvent
= CreateEvent(NULL
,
288 if (hNotificationThreadEvent
== NULL
)
294 /* create or open the machine group policy event */
295 if (hMachineGPAppliedEvent
== NULL
)
297 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
298 if (lpSecurityDescriptor
== NULL
)
303 hMachineGPAppliedEvent
= CreateGPEvent(TRUE
,
304 lpSecurityDescriptor
);
305 if (hMachineGPAppliedEvent
== NULL
)
311 /* create or open the local group policy event only if necessary */
312 if (!bMachine
&& hLocalGPAppliedEvent
== NULL
)
314 if (lpSecurityDescriptor
== NULL
)
316 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
317 if (lpSecurityDescriptor
== NULL
)
323 hLocalGPAppliedEvent
= CreateGPEvent(FALSE
,
324 lpSecurityDescriptor
);
325 if (hLocalGPAppliedEvent
== NULL
)
331 if (hNotificationThread
== NULL
)
333 hNotificationThread
= CreateThread(NULL
,
335 GPNotificationThreadProc
,
341 if (hNotificationThread
!= NULL
)
343 Notify
= (PGP_NOTIFY
)LocalAlloc(LMEM_FIXED
,
347 /* add the item to the beginning of the list */
348 Notify
->Next
= NotificationList
;
349 Notify
->hEvent
= hEvent
;
350 Notify
->bMachine
= bMachine
;
352 NotificationList
= Notify
;
354 /* notify the thread */
355 GPNotificationAction
= gpaUpdate
;
356 SetEvent(hNotificationThreadEvent
);
363 LeaveCriticalSection(&GPNotifyLock
);
365 if (lpSecurityDescriptor
!= NULL
)
367 LocalFree((HLOCAL
)lpSecurityDescriptor
);
370 /* NOTE: don't delete the events or close the handles created */
376 UnregisterGPNotification(IN HANDLE hEvent
)
378 PGP_NOTIFY Notify
= NULL
, *NotifyLink
;
381 EnterCriticalSection(&GPNotifyLock
);
383 Notify
= NotificationList
;
384 NotifyLink
= &NotificationList
;
386 while (Notify
!= NULL
)
388 if (Notify
->hEvent
== hEvent
)
390 /* remove and free the item */
391 *NotifyLink
= Notify
->Next
;
392 LocalFree((HLOCAL
)Notify
);
394 /* notify the thread */
395 if (hNotificationThread
!= NULL
&&
396 hNotificationThreadEvent
!= NULL
)
398 GPNotificationAction
= gpaUpdate
;
399 SetEvent(hNotificationThreadEvent
);
406 NotifyLink
= &Notify
->Next
;
407 Notify
= Notify
->Next
;
410 LeaveCriticalSection(&GPNotifyLock
);
416 EnterCriticalPolicySection(IN BOOL bMachine
)
418 SECURITY_ATTRIBUTES SecurityAttributes
;
419 PSECURITY_DESCRIPTOR lpSecurityDescriptor
;
422 /* create or open the mutex */
423 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
424 if (lpSecurityDescriptor
== NULL
)
429 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
430 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
431 SecurityAttributes
.bInheritHandle
= FALSE
;
433 hSection
= CreateMutexW(&SecurityAttributes
,
435 (bMachine
? szMachineGPMutex
: szLocalGPMutex
));
437 if (hSection
!= NULL
)
439 /* wait up to 10 seconds */
440 if (WaitForSingleObject(hSection
,
441 60000) != WAIT_FAILED
)
446 CloseHandle(hSection
);
453 LeaveCriticalPolicySection(IN HANDLE hSection
)
457 if (hSection
== NULL
)
459 SetLastError(ERROR_INVALID_PARAMETER
);
463 Ret
= ReleaseMutex(hSection
);
464 CloseHandle(hSection
);