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: dll/win32/userenv/gpolicy.c
23 * PURPOSE: Group policy functions
24 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
32 typedef struct _GP_NOTIFY
34 struct _GP_NOTIFY
*Next
;
37 } GP_NOTIFY
, *PGP_NOTIFY
;
45 static const WCHAR szLocalGPApplied
[] = L
"userenv: User Group Policy has been applied";
46 static const WCHAR szLocalGPMutex
[] = L
"userenv: user policy mutex";
47 static const WCHAR szLocalGPRefreshEvent
[] = L
"userenv: user policy refresh event";
48 static const WCHAR szLocalGPForceRefreshEvent
[] = L
"userenv: user policy force refresh event";
49 static const WCHAR szLocalGPDoneEvent
[] = L
"userenv: User Policy Foreground Done Event";
50 static const WCHAR szMachineGPApplied
[] = L
"Global\\userenv: Machine Group Policy has been applied";
51 static const WCHAR szMachineGPMutex
[] = L
"Global\\userenv: machine policy mutex";
52 static const WCHAR szMachineGPRefreshEvent
[] = L
"Global\\userenv: machine policy refresh event";
53 static const WCHAR szMachineGPForceRefreshEvent
[] = L
"Global\\userenv: machine policy force refresh event";
54 static const WCHAR szMachineGPDoneEvent
[] = L
"Global\\userenv: Machine Policy Foreground Done Event";
56 static CRITICAL_SECTION GPNotifyLock
;
57 static PGP_NOTIFY NotificationList
= NULL
;
58 static GP_ACTION GPNotificationAction
= gpaUpdate
;
59 static HANDLE hNotificationThread
= NULL
;
60 static HANDLE hNotificationThreadEvent
= NULL
;
61 static HANDLE hLocalGPAppliedEvent
= NULL
;
62 static HANDLE hMachineGPAppliedEvent
= NULL
;
65 InitializeGPNotifications(VOID
)
67 InitializeCriticalSection(&GPNotifyLock
);
71 UninitializeGPNotifications(VOID
)
73 EnterCriticalSection(&GPNotifyLock
);
75 /* rundown the notification thread */
76 if (hNotificationThread
!= NULL
)
78 ASSERT(hNotificationThreadEvent
!= NULL
);
80 /* notify the thread */
81 GPNotificationAction
= gpaTerminate
;
82 SetEvent(hNotificationThreadEvent
);
84 LeaveCriticalSection(&GPNotifyLock
);
86 /* wait for the thread to terminate itself */
87 WaitForSingleObject(hNotificationThread
,
90 EnterCriticalSection(&GPNotifyLock
);
92 if (hNotificationThread
!= NULL
)
94 /* the handle should be closed by the thread,
95 just in case that didn't happen for an unknown reason */
96 CloseHandle(hNotificationThread
);
97 hNotificationThread
= NULL
;
101 if (hNotificationThreadEvent
!= NULL
)
103 CloseHandle(hNotificationThreadEvent
);
104 hNotificationThreadEvent
= NULL
;
107 LeaveCriticalSection(&GPNotifyLock
);
109 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
;
132 GPNotificationThreadProc(IN LPVOID lpParameter
)
135 DWORD WaitResult
, WaitCount
;
136 HANDLE WaitHandles
[3];
138 /* reference the library so we don't screw up if the application
139 causes the DLL to unload while this thread is still running */
140 if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
144 ASSERT(hModule
== hInstance
);
146 EnterCriticalSection(&GPNotifyLock
);
148 ASSERT(hNotificationThreadEvent
!= NULL
);
149 WaitHandles
[0] = hNotificationThreadEvent
;
152 ASSERT(hMachineGPAppliedEvent
!= NULL
);
154 if (NotificationList
== NULL
)
158 WaitHandles
[1] = hMachineGPAppliedEvent
;
160 if (hLocalGPAppliedEvent
!= NULL
)
162 WaitHandles
[2] = hLocalGPAppliedEvent
;
166 LeaveCriticalSection(&GPNotifyLock
);
168 WaitResult
= WaitForMultipleObjects(WaitCount
,
173 EnterCriticalSection(&GPNotifyLock
);
175 if (WaitResult
!= WAIT_FAILED
)
177 if (WaitResult
== WAIT_OBJECT_0
)
179 ResetEvent(hNotificationThreadEvent
);
181 if (GPNotificationAction
== gpaTerminate
)
183 /* terminate the thread */
187 else if (WaitResult
== WAIT_OBJECT_0
+ 1 || WaitResult
== WAIT_OBJECT_0
+ 2)
189 /* group policies have been applied */
190 if (NotificationList
!= NULL
)
192 NotifyGPEvents((WaitResult
== WAIT_OBJECT_0
+ 1));
195 else if (WaitResult
== WAIT_ABANDONED_0
+ 2)
197 /* In case the local group policies event was abandoned, keep watching!
198 But close the handle as it's no longer of any use. */
199 if (hLocalGPAppliedEvent
!= NULL
)
201 CloseHandle(hLocalGPAppliedEvent
);
202 hLocalGPAppliedEvent
= NULL
;
205 else if (WaitResult
== WAIT_ABANDONED_0
|| WaitResult
== WAIT_ABANDONED_0
+ 1)
207 /* terminate the thread if the machine group policies event was abandoned
208 or for some reason the rundown event got abandoned. */
213 DPRINT("Unexpected wait result watching the group policy events: 0x%x\n", WaitResult
);
218 if (NotificationList
== NULL
)
226 /* cleanup handles no longer used */
227 ASSERT(hNotificationThread
!= NULL
);
228 ASSERT(hNotificationThreadEvent
!= NULL
);
230 CloseHandle(hNotificationThread
);
231 CloseHandle(hNotificationThreadEvent
);
232 hNotificationThread
= NULL
;
233 hNotificationThreadEvent
= NULL
;
235 if (hLocalGPAppliedEvent
!= NULL
)
237 CloseHandle(hLocalGPAppliedEvent
);
238 hLocalGPAppliedEvent
= NULL
;
240 if (hMachineGPAppliedEvent
!= NULL
)
242 CloseHandle(hMachineGPAppliedEvent
);
243 hMachineGPAppliedEvent
= NULL
;
246 LeaveCriticalSection(&GPNotifyLock
);
248 /* dereference the library and exit */
249 FreeLibraryAndExitThread(hModule
,
254 DPRINT1("Referencing the library failed!\n");
262 CreateGPEvent(IN BOOL bMachine
,
263 IN PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
266 SECURITY_ATTRIBUTES SecurityAttributes
;
268 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
269 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
270 SecurityAttributes
.bInheritHandle
= FALSE
;
272 hEvent
= CreateEventW(&SecurityAttributes
,
275 (bMachine
? szMachineGPApplied
: szLocalGPApplied
));
282 RegisterGPNotification(IN HANDLE hEvent
,
286 PSECURITY_DESCRIPTOR lpSecurityDescriptor
= NULL
;
289 EnterCriticalSection(&GPNotifyLock
);
291 /* create the thread notification event */
292 if (hNotificationThreadEvent
== NULL
)
294 hNotificationThreadEvent
= CreateEvent(NULL
,
298 if (hNotificationThreadEvent
== NULL
)
304 /* create or open the machine group policy event */
305 if (hMachineGPAppliedEvent
== NULL
)
307 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
308 if (lpSecurityDescriptor
== NULL
)
313 hMachineGPAppliedEvent
= CreateGPEvent(TRUE
,
314 lpSecurityDescriptor
);
315 if (hMachineGPAppliedEvent
== NULL
)
321 /* create or open the local group policy event only if necessary */
322 if (!bMachine
&& hLocalGPAppliedEvent
== NULL
)
324 if (lpSecurityDescriptor
== NULL
)
326 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
327 if (lpSecurityDescriptor
== NULL
)
333 hLocalGPAppliedEvent
= CreateGPEvent(FALSE
,
334 lpSecurityDescriptor
);
335 if (hLocalGPAppliedEvent
== NULL
)
341 if (hNotificationThread
== NULL
)
343 hNotificationThread
= CreateThread(NULL
,
345 GPNotificationThreadProc
,
351 if (hNotificationThread
!= NULL
)
353 Notify
= (PGP_NOTIFY
)LocalAlloc(LMEM_FIXED
,
357 /* add the item to the beginning of the list */
358 Notify
->Next
= NotificationList
;
359 Notify
->hEvent
= hEvent
;
360 Notify
->bMachine
= bMachine
;
362 NotificationList
= Notify
;
364 /* notify the thread */
365 GPNotificationAction
= gpaUpdate
;
366 SetEvent(hNotificationThreadEvent
);
373 LeaveCriticalSection(&GPNotifyLock
);
375 if (lpSecurityDescriptor
!= NULL
)
377 LocalFree((HLOCAL
)lpSecurityDescriptor
);
380 /* NOTE: don't delete the events or close the handles created */
387 UnregisterGPNotification(IN HANDLE hEvent
)
389 PGP_NOTIFY Notify
= NULL
, *NotifyLink
;
392 EnterCriticalSection(&GPNotifyLock
);
394 Notify
= NotificationList
;
395 NotifyLink
= &NotificationList
;
397 while (Notify
!= NULL
)
399 if (Notify
->hEvent
== hEvent
)
401 /* remove and free the item */
402 *NotifyLink
= Notify
->Next
;
403 LocalFree((HLOCAL
)Notify
);
405 /* notify the thread */
406 if (hNotificationThread
!= NULL
&&
407 hNotificationThreadEvent
!= NULL
)
409 GPNotificationAction
= gpaUpdate
;
410 SetEvent(hNotificationThreadEvent
);
417 NotifyLink
= &Notify
->Next
;
418 Notify
= Notify
->Next
;
421 LeaveCriticalSection(&GPNotifyLock
);
428 RefreshPolicy(IN BOOL bMachine
)
433 hEvent
= OpenEventW(EVENT_MODIFY_STATE
,
435 (bMachine
? szMachineGPRefreshEvent
: szLocalGPRefreshEvent
));
438 Ret
= SetEvent(hEvent
);
442 /* return TRUE even if the mutex doesn't exist! */
448 RefreshPolicyEx(IN BOOL bMachine
,
451 if (dwOptions
& ~RP_FORCE
)
453 SetLastError(ERROR_INVALID_PARAMETER
);
457 if (dwOptions
& RP_FORCE
)
462 hEvent
= OpenEventW(EVENT_MODIFY_STATE
,
464 (bMachine
? szMachineGPForceRefreshEvent
: szLocalGPForceRefreshEvent
));
467 Ret
= SetEvent(hEvent
);
471 /* return TRUE even if the mutex doesn't exist! */
476 return RefreshPolicy(bMachine
);
482 EnterCriticalPolicySection(IN BOOL bMachine
)
484 SECURITY_ATTRIBUTES SecurityAttributes
;
485 PSECURITY_DESCRIPTOR lpSecurityDescriptor
;
488 /* create or open the mutex */
489 lpSecurityDescriptor
= CreateDefaultSecurityDescriptor();
490 if (lpSecurityDescriptor
!= NULL
)
492 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
493 SecurityAttributes
.lpSecurityDescriptor
= lpSecurityDescriptor
;
494 SecurityAttributes
.bInheritHandle
= FALSE
;
496 hSection
= CreateMutexW(&SecurityAttributes
,
498 (bMachine
? szMachineGPMutex
: szLocalGPMutex
));
500 LocalFree((HLOCAL
)lpSecurityDescriptor
);
502 if (hSection
!= NULL
)
504 /* wait up to 10 minutes */
505 if (WaitForSingleObject(hSection
,
506 600000) != WAIT_FAILED
)
511 CloseHandle(hSection
);
520 LeaveCriticalPolicySection(IN HANDLE hSection
)
524 if (hSection
== NULL
)
526 SetLastError(ERROR_INVALID_PARAMETER
);
530 Ret
= ReleaseMutex(hSection
);
531 CloseHandle(hSection
);
538 WaitForUserPolicyForegroundProcessing(VOID
)
543 hEvent
= OpenEventW(SYNCHRONIZE
,
548 Ret
= WaitForSingleObject(hEvent
,
549 INFINITE
) != WAIT_FAILED
;
558 WaitForMachinePolicyForegroundProcessing(VOID
)
563 hEvent
= OpenEventW(SYNCHRONIZE
,
565 szMachineGPDoneEvent
);
568 Ret
= WaitForSingleObject(hEvent
,
569 INFINITE
) != WAIT_FAILED
;
580 _In_ LPCSTR pMachineName
,
582 _In_ GUID
*pGuidExtension
,
583 _Out_ PGROUP_POLICY_OBJECTA
*ppGPOList
586 DPRINT1("GetAppliedGPOListA is UNIMPLEMENTED!\n");
587 return ERROR_CALL_NOT_IMPLEMENTED
;
594 _In_ LPCWSTR pMachineName
,
596 _In_ GUID
*pGuidExtension
,
597 _Out_ PGROUP_POLICY_OBJECTW
*ppGPOList
600 DPRINT1("GetAppliedGPOListW is UNIMPLEMENTED!\n");
601 return ERROR_CALL_NOT_IMPLEMENTED
;