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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 szLocalGPRefreshEvent
[] = L
"userenv: user policy refresh event";
49 static const WCHAR szLocalGPForceRefreshEvent
[] = L
"userenv: user policy force refresh event";
50 static const WCHAR szLocalGPDoneEvent
[] = L
"userenv: User Policy Foreground Done Event";
51 static const WCHAR szMachineGPApplied
[] = L
"Global\\userenv: Machine Group Policy has been applied";
52 static const WCHAR szMachineGPMutex
[] = L
"Global\\userenv: machine policy mutex";
53 static const WCHAR szMachineGPRefreshEvent
[] = L
"Global\\userenv: machine policy refresh event";
54 static const WCHAR szMachineGPForceRefreshEvent
[] = L
"Global\\userenv: machine policy force refresh event";
55 static const WCHAR szMachineGPDoneEvent
[] = L
"Global\\userenv: Machine Policy Foreground Done Event";
57 static CRITICAL_SECTION GPNotifyLock
;
58 static PGP_NOTIFY NotificationList
= NULL
;
59 static GP_ACTION GPNotificationAction
= gpaUpdate
;
60 static HANDLE hNotificationThread
= NULL
;
61 static HANDLE hNotificationThreadEvent
= NULL
;
62 static HANDLE hLocalGPAppliedEvent
= NULL
;
63 static HANDLE hMachineGPAppliedEvent
= NULL
;
66 InitializeGPNotifications(VOID
)
68 InitializeCriticalSection(&GPNotifyLock
);
72 UninitializeGPNotifications(VOID
)
74 EnterCriticalSection(&GPNotifyLock
);
76 /* rundown the notification thread */
77 if (hNotificationThread
!= NULL
)
79 ASSERT(hNotificationThreadEvent
!= NULL
);
81 /* notify the thread */
82 GPNotificationAction
= gpaTerminate
;
83 SetEvent(hNotificationThreadEvent
);
85 LeaveCriticalSection(&GPNotifyLock
);
87 /* wait for the thread to terminate itself */
88 WaitForSingleObject(hNotificationThread
,
91 EnterCriticalSection(&GPNotifyLock
);
93 if (hNotificationThread
!= NULL
)
95 /* the handle should be closed by the thread,
96 just in case that didn't happen for an unknown reason */
97 CloseHandle(hNotificationThread
);
98 hNotificationThread
= NULL
;
102 if (hNotificationThreadEvent
!= NULL
)
104 CloseHandle(hNotificationThreadEvent
);
105 hNotificationThreadEvent
= NULL
;
108 LeaveCriticalSection(&GPNotifyLock
);
110 DeleteCriticalSection(&GPNotifyLock
);
114 NotifyGPEvents(IN BOOL bMachine
)
116 PGP_NOTIFY Notify
= NotificationList
;
118 while (Notify
!= NULL
)
120 if (Notify
->bMachine
== bMachine
)
122 SetEvent(Notify
->hEvent
);
125 Notify
= Notify
->Next
;
130 GPNotificationThreadProc(IN LPVOID lpParameter
)
133 DWORD WaitResult
, WaitCount
;
134 HANDLE WaitHandles
[3];
136 /* reference the library so we don't screw up if the application
137 causes the DLL to unload while this thread is still running */
138 if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
142 ASSERT(hModule
== hInstance
);
144 EnterCriticalSection(&GPNotifyLock
);
146 ASSERT(hNotificationThreadEvent
!= NULL
);
147 WaitHandles
[0] = hNotificationThreadEvent
;
150 ASSERT(hMachineGPAppliedEvent
!= NULL
);
152 if (NotificationList
== NULL
)
156 WaitHandles
[1] = hMachineGPAppliedEvent
;
158 if (hLocalGPAppliedEvent
!= NULL
)
160 WaitHandles
[2] = hLocalGPAppliedEvent
;
164 LeaveCriticalSection(&GPNotifyLock
);
166 WaitResult
= WaitForMultipleObjects(WaitCount
,
171 EnterCriticalSection(&GPNotifyLock
);
173 if (WaitResult
!= WAIT_FAILED
)
175 if (WaitResult
== WAIT_OBJECT_0
)
177 ResetEvent(hNotificationThreadEvent
);
179 if (GPNotificationAction
== gpaTerminate
)
181 /* terminate the thread */
185 else if (WaitResult
== WAIT_OBJECT_0
+ 1 || WaitResult
== WAIT_OBJECT_0
+ 2)
187 /* group policies have been applied */
188 if (NotificationList
!= NULL
)
190 NotifyGPEvents((WaitResult
== WAIT_OBJECT_0
+ 1));
193 else if (WaitResult
== WAIT_ABANDONED_0
+ 2)
195 /* In case the local group policies event was abandoned, keep watching!
196 But close the handle as it's no longer of any use. */
197 if (hLocalGPAppliedEvent
!= NULL
)
199 CloseHandle(hLocalGPAppliedEvent
);
200 hLocalGPAppliedEvent
= NULL
;
203 else if (WaitResult
== WAIT_ABANDONED_0
|| WaitResult
== WAIT_ABANDONED_0
+ 1)
205 /* terminate the thread if the machine group policies event was abandoned
206 or for some reason the rundown event got abandoned. */
211 DPRINT("Unexpected wait result watching the group policy events: 0x%x\n", WaitResult
);
216 if (NotificationList
== NULL
)
224 /* cleanup handles no longer used */
225 ASSERT(hNotificationThread
!= NULL
);
226 ASSERT(hNotificationThreadEvent
!= NULL
);
228 CloseHandle(hNotificationThread
);
229 CloseHandle(hNotificationThreadEvent
);
230 hNotificationThread
= NULL
;
231 hNotificationThreadEvent
= NULL
;
233 if (hLocalGPAppliedEvent
!= NULL
)
235 CloseHandle(hLocalGPAppliedEvent
);
236 hLocalGPAppliedEvent
= NULL
;
238 if (hMachineGPAppliedEvent
!= NULL
)
240 CloseHandle(hMachineGPAppliedEvent
);
241 hMachineGPAppliedEvent
= NULL
;
244 LeaveCriticalSection(&GPNotifyLock
);
246 /* dereference the library and exit */
247 FreeLibraryAndExitThread(hModule
,
252 DPRINT1("Referencing the library failed!\n");
259 CreateGPEvent(IN BOOL bMachine
,
260 IN PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
263 SECURITY_ATTRIBUTES SecurityAttributes
;
265 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
266 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
267 SecurityAttributes
.bInheritHandle
= FALSE
;
269 hEvent
= CreateEventW(&SecurityAttributes
,
272 (bMachine
? szMachineGPApplied
: szLocalGPApplied
));
278 RegisterGPNotification(IN HANDLE hEvent
,
282 PSECURITY_DESCRIPTOR lpSecurityDescriptor
= NULL
;
285 EnterCriticalSection(&GPNotifyLock
);
287 /* create the thread notification event */
288 if (hNotificationThreadEvent
== NULL
)
290 hNotificationThreadEvent
= CreateEvent(NULL
,
294 if (hNotificationThreadEvent
== NULL
)
300 /* create or open the machine group policy event */
301 if (hMachineGPAppliedEvent
== NULL
)
303 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
304 if (lpSecurityDescriptor
== NULL
)
309 hMachineGPAppliedEvent
= CreateGPEvent(TRUE
,
310 lpSecurityDescriptor
);
311 if (hMachineGPAppliedEvent
== NULL
)
317 /* create or open the local group policy event only if necessary */
318 if (!bMachine
&& hLocalGPAppliedEvent
== NULL
)
320 if (lpSecurityDescriptor
== NULL
)
322 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
323 if (lpSecurityDescriptor
== NULL
)
329 hLocalGPAppliedEvent
= CreateGPEvent(FALSE
,
330 lpSecurityDescriptor
);
331 if (hLocalGPAppliedEvent
== NULL
)
337 if (hNotificationThread
== NULL
)
339 hNotificationThread
= CreateThread(NULL
,
341 GPNotificationThreadProc
,
347 if (hNotificationThread
!= NULL
)
349 Notify
= (PGP_NOTIFY
)LocalAlloc(LMEM_FIXED
,
353 /* add the item to the beginning of the list */
354 Notify
->Next
= NotificationList
;
355 Notify
->hEvent
= hEvent
;
356 Notify
->bMachine
= bMachine
;
358 NotificationList
= Notify
;
360 /* notify the thread */
361 GPNotificationAction
= gpaUpdate
;
362 SetEvent(hNotificationThreadEvent
);
369 LeaveCriticalSection(&GPNotifyLock
);
371 if (lpSecurityDescriptor
!= NULL
)
373 LocalFree((HLOCAL
)lpSecurityDescriptor
);
376 /* NOTE: don't delete the events or close the handles created */
382 UnregisterGPNotification(IN HANDLE hEvent
)
384 PGP_NOTIFY Notify
= NULL
, *NotifyLink
;
387 EnterCriticalSection(&GPNotifyLock
);
389 Notify
= NotificationList
;
390 NotifyLink
= &NotificationList
;
392 while (Notify
!= NULL
)
394 if (Notify
->hEvent
== hEvent
)
396 /* remove and free the item */
397 *NotifyLink
= Notify
->Next
;
398 LocalFree((HLOCAL
)Notify
);
400 /* notify the thread */
401 if (hNotificationThread
!= NULL
&&
402 hNotificationThreadEvent
!= NULL
)
404 GPNotificationAction
= gpaUpdate
;
405 SetEvent(hNotificationThreadEvent
);
412 NotifyLink
= &Notify
->Next
;
413 Notify
= Notify
->Next
;
416 LeaveCriticalSection(&GPNotifyLock
);
422 RefreshPolicy(IN BOOL bMachine
)
427 hEvent
= OpenEventW(EVENT_MODIFY_STATE
,
429 (bMachine
? szMachineGPRefreshEvent
: szLocalGPRefreshEvent
));
432 Ret
= SetEvent(hEvent
);
436 /* return TRUE even if the mutex doesn't exist! */
441 RefreshPolicyEx(IN BOOL bMachine
,
444 if (dwOptions
& ~RP_FORCE
)
446 SetLastError(ERROR_INVALID_PARAMETER
);
450 if (dwOptions
& RP_FORCE
)
455 hEvent
= OpenEventW(EVENT_MODIFY_STATE
,
457 (bMachine
? szMachineGPForceRefreshEvent
: szLocalGPForceRefreshEvent
));
460 Ret
= SetEvent(hEvent
);
464 /* return TRUE even if the mutex doesn't exist! */
469 return RefreshPolicy(bMachine
);
474 EnterCriticalPolicySection(IN BOOL bMachine
)
476 SECURITY_ATTRIBUTES SecurityAttributes
;
477 PSECURITY_DESCRIPTOR lpSecurityDescriptor
;
480 /* create or open the mutex */
481 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
482 if (lpSecurityDescriptor
!= NULL
)
484 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
485 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
486 SecurityAttributes
.bInheritHandle
= FALSE
;
488 hSection
= CreateMutexW(&SecurityAttributes
,
490 (bMachine
? szMachineGPMutex
: szLocalGPMutex
));
492 LocalFree((HLOCAL
)lpSecurityDescriptor
);
494 if (hSection
!= NULL
)
496 /* wait up to 10 minutes */
497 if (WaitForSingleObject(hSection
,
498 600000) != WAIT_FAILED
)
503 CloseHandle(hSection
);
511 LeaveCriticalPolicySection(IN HANDLE hSection
)
515 if (hSection
== NULL
)
517 SetLastError(ERROR_INVALID_PARAMETER
);
521 Ret
= ReleaseMutex(hSection
);
522 CloseHandle(hSection
);
528 WaitForUserPolicyForegroundProcessing(VOID
)
533 hEvent
= OpenEventW(SYNCHRONIZE
,
538 Ret
= WaitForSingleObject(hEvent
,
539 INFINITE
) != WAIT_FAILED
;
547 WaitForMachinePolicyForegroundProcessing(VOID
)
552 hEvent
= OpenEventW(SYNCHRONIZE
,
554 szMachineGPDoneEvent
);
557 Ret
= WaitForSingleObject(hEvent
,
558 INFINITE
) != WAIT_FAILED
;