From bfce7c398c8ae30df32ef73907d792b2394e292b Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Wed, 11 Jan 2006 22:40:31 +0000 Subject: [PATCH] - partially implemented RegisterGPNotification() and UnregisterGPNotification() (depends on GetModuleHandleEx which is not yet implemented) - use debug.h svn path=/trunk/; revision=20792 --- reactos/lib/userenv/desktop.c | 3 + reactos/lib/userenv/directory.c | 3 + reactos/lib/userenv/environment.c | 3 + reactos/lib/userenv/gpolicy.c | 403 ++++++++++++++++++++++++++++++ reactos/lib/userenv/internal.h | 25 +- reactos/lib/userenv/misc.c | 10 + reactos/lib/userenv/profile.c | 3 + reactos/lib/userenv/registry.c | 3 + reactos/lib/userenv/setup.c | 4 + reactos/lib/userenv/userenv.c | 5 + reactos/lib/userenv/userenv.def | 2 + reactos/lib/userenv/userenv.xml | 1 + 12 files changed, 451 insertions(+), 14 deletions(-) create mode 100644 reactos/lib/userenv/gpolicy.c diff --git a/reactos/lib/userenv/desktop.c b/reactos/lib/userenv/desktop.c index 5615810df63..10b5dfdd949 100644 --- a/reactos/lib/userenv/desktop.c +++ b/reactos/lib/userenv/desktop.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ diff --git a/reactos/lib/userenv/directory.c b/reactos/lib/userenv/directory.c index 5b68190b444..b96ac4eb9e6 100644 --- a/reactos/lib/userenv/directory.c +++ b/reactos/lib/userenv/directory.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ diff --git a/reactos/lib/userenv/environment.c b/reactos/lib/userenv/environment.c index 8e378bf16b6..5e9f969071b 100644 --- a/reactos/lib/userenv/environment.c +++ b/reactos/lib/userenv/environment.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + static BOOL SetUserEnvironmentVariable (LPVOID *Environment, diff --git a/reactos/lib/userenv/gpolicy.c b/reactos/lib/userenv/gpolicy.c new file mode 100644 index 00000000000..31b359c4b16 --- /dev/null +++ b/reactos/lib/userenv/gpolicy.c @@ -0,0 +1,403 @@ +/* + * ReactOS kernel + * Copyright (C) 2006 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/userenv/gpolicy.c + * PURPOSE: Group policy functions + * PROGRAMMER: Thomas Weidenmueller + */ + +#include + +#define NDEBUG +#include + + +typedef struct _GP_NOTIFY +{ + struct _GP_NOTIFY *Next; + HANDLE hEvent; + BOOL bMachine; +} GP_NOTIFY, *PGP_NOTIFY; + +typedef enum +{ + gpaUpdate = 0, + gpaTerminate +} GP_ACTION; + +static const WCHAR szLocalGPApplied[] = L"userenv: User Group Policy has been applied"; +static const WCHAR szMachineGPApplied[] = L"Global\\userenv: Machine Group Policy has been applied"; + +static CRITICAL_SECTION GPNotifyLock; +static PGP_NOTIFY NotificationList = NULL; +static GP_ACTION GPNotificationAction = gpaUpdate; +static HANDLE hNotificationThread = NULL; +static HANDLE hNotificationThreadEvent = NULL; +static HANDLE hLocalGPAppliedEvent = NULL; +static HANDLE hMachineGPAppliedEvent = NULL; + +VOID +InitializeGPNotifications(VOID) +{ + InitializeCriticalSection(&GPNotifyLock); +} + +VOID +UninitializeGPNotifications(VOID) +{ + EnterCriticalSection(&GPNotifyLock); + + /* rundown the notification thread */ + if (hNotificationThread != NULL) + { + ASSERT(hNotificationThreadEvent != NULL); + + /* notify the thread */ + GPNotificationAction = gpaTerminate; + SetEvent(hNotificationThreadEvent); + + LeaveCriticalSection(&GPNotifyLock); + + /* wait for the thread to terminate itself */ + WaitForSingleObject(hNotificationThread, + INFINITE); + + EnterCriticalSection(&GPNotifyLock); + + if (hNotificationThread != NULL) + { + /* the handle should be closed by the thread, + just in case that didn't happen for an unknown reason */ + CloseHandle(hNotificationThread); + hNotificationThread = NULL; + } + } + + if (hNotificationThreadEvent != NULL) + { + CloseHandle(hNotificationThreadEvent); + hNotificationThreadEvent = NULL; + } + + LeaveCriticalSection(&GPNotifyLock); + + DeleteCriticalSection(&GPNotifyLock); +} + +static VOID +NotifyGPEvents(IN BOOL bMachine) +{ + PGP_NOTIFY Notify = NotificationList; + + while (Notify != NULL) + { + if (Notify->bMachine == bMachine) + { + SetEvent(Notify->hEvent); + } + + Notify = Notify->Next; + } +} + +static DWORD WINAPI +GPNotificationThreadProc(IN LPVOID lpParameter) +{ + HMODULE hModule; + DWORD WaitResult, WaitCount; + HANDLE WaitHandles[3]; + + /* reference the library so we don't screw up if the application + causes the DLL to unload while this thread is still running */ + if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCWSTR)hInstance, + &hModule)) + { + ASSERT(hModule == hInstance); + + EnterCriticalSection(&GPNotifyLock); + + ASSERT(hNotificationThreadEvent != NULL); + WaitHandles[0] = hNotificationThreadEvent; + for (;;) + { + ASSERT(hMachineGPAppliedEvent != NULL); + + if (NotificationList == NULL) + break; + + WaitCount = 2; + WaitHandles[1] = hMachineGPAppliedEvent; + + if (hLocalGPAppliedEvent != NULL) + { + WaitHandles[2] = hLocalGPAppliedEvent; + WaitCount++; + } + + LeaveCriticalSection(&GPNotifyLock); + + WaitResult = WaitForMultipleObjects(WaitCount, + WaitHandles, + FALSE, + INFINITE); + + EnterCriticalSection(&GPNotifyLock); + + if (WaitResult != WAIT_FAILED) + { + if (WaitResult == WAIT_OBJECT_0) + { + ResetEvent(hNotificationThreadEvent); + + if (GPNotificationAction == gpaTerminate) + { + /* terminate the thread */ + break; + } + } + else if (WaitResult == WAIT_OBJECT_0 + 1 || WaitResult == WAIT_OBJECT_0 + 2) + { + /* group policies have been applied */ + if (NotificationList != NULL) + { + NotifyGPEvents((WaitResult == WAIT_OBJECT_0 + 1)); + } + } + else if (WaitResult == WAIT_ABANDONED_0 + 2) + { + /* In case the local group policies event was abandoned, keep watching! + But close the handle as it's no longer of any use. */ + if (hLocalGPAppliedEvent != NULL) + { + CloseHandle(hLocalGPAppliedEvent); + hLocalGPAppliedEvent = NULL; + } + } + else if (WaitResult == WAIT_ABANDONED_0 || WaitResult == WAIT_ABANDONED_0 + 1) + { + /* terminate the thread if the machine group policies event was abandoned + or for some reason the rundown event got abandoned. */ + break; + } + else + { + DPRINT("Unexpected wait result watching the group policy events: 0x%x\n", WaitResult); + ASSERT(FALSE); + break; + } + + if (NotificationList == NULL) + break; + } + else + break; + + } + + /* cleanup handles no longer used */ + ASSERT(hNotificationThread != NULL); + ASSERT(hNotificationThreadEvent != NULL); + + CloseHandle(hNotificationThread); + CloseHandle(hNotificationThreadEvent); + hNotificationThread = NULL; + hNotificationThreadEvent = NULL; + + if (hLocalGPAppliedEvent != NULL) + { + CloseHandle(hLocalGPAppliedEvent); + hLocalGPAppliedEvent = NULL; + } + if (hMachineGPAppliedEvent != NULL) + { + CloseHandle(hMachineGPAppliedEvent); + hMachineGPAppliedEvent = NULL; + } + + LeaveCriticalSection(&GPNotifyLock); + + /* dereference the library and exit */ + FreeLibraryAndExitThread(hModule, + 0); + } + else + { + DPRINT1("Referencing the library failed!\n"); + } + + return 1; +} + +static HANDLE +CreateGPEvent(IN BOOL bMachine, + IN PVOID lpSecurityDescriptor) +{ + HANDLE hEvent; + SECURITY_ATTRIBUTES SecurityAttributes; + + SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + SecurityAttributes.lpSecurityDescriptor = lpSecurityDescriptor; + SecurityAttributes.bInheritHandle = FALSE; + + hEvent = CreateEventW((lpSecurityDescriptor != NULL ? &SecurityAttributes : NULL), + TRUE, + FALSE, + (bMachine ? szMachineGPApplied : szLocalGPApplied)); + + return hEvent; +} + +BOOL WINAPI +RegisterGPNotification(IN HANDLE hEvent, + IN BOOL bMachine) +{ + PGP_NOTIFY Notify; + PVOID lpSecurityDescriptor = NULL; + BOOL Ret = FALSE; + + EnterCriticalSection(&GPNotifyLock); + + /* create the thread notification event */ + if (hNotificationThreadEvent == NULL) + { + hNotificationThreadEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + if (hNotificationThreadEvent == NULL) + { + goto Cleanup; + } + } + + /* create or open the machine group policy event */ + if (hMachineGPAppliedEvent == NULL) + { + lpSecurityDescriptor = CreateDefaultSD(); + + hMachineGPAppliedEvent = CreateGPEvent(TRUE, + lpSecurityDescriptor); + if (hMachineGPAppliedEvent == NULL) + { + goto Cleanup; + } + } + + /* create or open the local group policy event only if necessary */ + if (!bMachine && hLocalGPAppliedEvent == NULL) + { + if (lpSecurityDescriptor == NULL) + { + lpSecurityDescriptor = CreateDefaultSD(); + } + + hLocalGPAppliedEvent = CreateGPEvent(FALSE, + lpSecurityDescriptor); + if (hLocalGPAppliedEvent == NULL) + { + goto Cleanup; + } + } + + if (hNotificationThread == NULL) + { + hNotificationThread = CreateThread(NULL, + 0, + GPNotificationThreadProc, + NULL, + 0, + NULL); + } + + if (hNotificationThread != NULL) + { + Notify = (PGP_NOTIFY)LocalAlloc(LMEM_FIXED, + sizeof(GP_NOTIFY)); + if (Notify != NULL) + { + /* add the item to the beginning of the list */ + Notify->Next = NotificationList; + Notify->hEvent = hEvent; + Notify->bMachine = bMachine; + + NotificationList = Notify; + + /* notify the thread */ + GPNotificationAction = gpaUpdate; + SetEvent(hNotificationThreadEvent); + + Ret = TRUE; + } + } + +Cleanup: + LeaveCriticalSection(&GPNotifyLock); + + if (lpSecurityDescriptor != NULL) + { + LocalFree((HLOCAL)lpSecurityDescriptor); + } + + /* NOTE: don't delete the events or close the handles created */ + + return Ret; +} + +BOOL WINAPI +UnregisterGPNotification(IN HANDLE hEvent) +{ + PGP_NOTIFY Notify = NULL, *NotifyLink; + BOOL Ret = FALSE; + + EnterCriticalSection(&GPNotifyLock); + + Notify = NotificationList; + NotifyLink = &NotificationList; + + while (Notify != NULL) + { + if (Notify->hEvent == hEvent) + { + /* remove and free the item */ + *NotifyLink = Notify->Next; + LocalFree((HLOCAL)Notify); + + /* notify the thread */ + if (hNotificationThread != NULL && + hNotificationThreadEvent != NULL) + { + GPNotificationAction = gpaUpdate; + SetEvent(hNotificationThreadEvent); + } + + Ret = TRUE; + break; + } + + NotifyLink = &Notify->Next; + Notify = Notify->Next; + } + + LeaveCriticalSection(&GPNotifyLock); + + return Ret; +} diff --git a/reactos/lib/userenv/internal.h b/reactos/lib/userenv/internal.h index 4731596cf66..6f1f92bc4d5 100644 --- a/reactos/lib/userenv/internal.h +++ b/reactos/lib/userenv/internal.h @@ -28,20 +28,6 @@ #ifndef _INTERNAL_H #define _INTERNAL_H -/* debug.h */ -void -DebugPrint (char* fmt,...); - -#define DPRINT1 DebugPrint("(%s:%d) ",__FILE__,__LINE__), DebugPrint -#define CHECKPOINT1 do { DebugPrint("%s:%d\n",__FILE__,__LINE__); } while(0); - -#ifdef __GNUC__ -#define DPRINT(args...) -#else -#define DPRINT -#endif /* __GNUC__ */ -#define CHECKPOINT - /* directory.c */ BOOL CopyDirectory (LPCWSTR lpDestinationPath, @@ -91,6 +77,9 @@ BOOL GetUserSidFromToken (HANDLE hToken, PUNICODE_STRING SidString); +PVOID +CreateDefaultSD(VOID); + /* profile.c */ BOOL AppendSystemPostfix (LPWSTR lpName, @@ -109,6 +98,14 @@ UpdateUsersShellFolderSettings(LPCWSTR lpUserProfilePath, /* userenv.c */ extern HINSTANCE hInstance; +/* gpolicy.c */ + +VOID +InitializeGPNotifications(VOID); + +VOID +UninitializeGPNotifications(VOID); + #endif /* _INTERNAL_H */ /* EOF */ diff --git a/reactos/lib/userenv/misc.c b/reactos/lib/userenv/misc.c index 4921bc2bae1..c3756af0998 100644 --- a/reactos/lib/userenv/misc.c +++ b/reactos/lib/userenv/misc.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ @@ -109,6 +112,13 @@ GetUserSidFromToken (HANDLE hToken, return TRUE; } +PVOID +CreateDefaultSD(VOID) +{ + /* FIXME - create a default security descriptor */ + return NULL; +} + /* Dynamic DLL loading interface **********************************************/ /* OLE32.DLL import table */ diff --git a/reactos/lib/userenv/profile.c b/reactos/lib/userenv/profile.c index 2c7889150e9..ed3d6053e50 100644 --- a/reactos/lib/userenv/profile.c +++ b/reactos/lib/userenv/profile.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ diff --git a/reactos/lib/userenv/registry.c b/reactos/lib/userenv/registry.c index 12007e82494..a277d071f40 100644 --- a/reactos/lib/userenv/registry.c +++ b/reactos/lib/userenv/registry.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + /* FUNCTIONS ***************************************************************/ diff --git a/reactos/lib/userenv/setup.c b/reactos/lib/userenv/setup.c index e5fde8f4ebd..8ed3b251430 100644 --- a/reactos/lib/userenv/setup.c +++ b/reactos/lib/userenv/setup.c @@ -27,6 +27,10 @@ #include +#define NDEBUG +#include + + typedef struct _FOLDERDATA { LPWSTR lpValueName; diff --git a/reactos/lib/userenv/userenv.c b/reactos/lib/userenv/userenv.c index 259a7453d1f..9c08e205891 100644 --- a/reactos/lib/userenv/userenv.c +++ b/reactos/lib/userenv/userenv.c @@ -27,6 +27,9 @@ #include +#define NDEBUG +#include + HINSTANCE hInstance = NULL; BOOL WINAPI @@ -37,9 +40,11 @@ DllMain (HINSTANCE hinstDLL, if (fdwReason == DLL_PROCESS_ATTACH) { hInstance = hinstDLL; + InitializeGPNotifications(); } else if (fdwReason == DLL_PROCESS_DETACH) { + UninitializeGPNotifications(); } return TRUE; diff --git a/reactos/lib/userenv/userenv.def b/reactos/lib/userenv/userenv.def index 7d29009d2c1..f47a5e04d73 100644 --- a/reactos/lib/userenv/userenv.def +++ b/reactos/lib/userenv/userenv.def @@ -31,5 +31,7 @@ GetUserProfileDirectoryA@12 GetUserProfileDirectoryW@12 LoadUserProfileA@8 LoadUserProfileW@8 +RegisterGPNotification@8 UnloadUserProfile@8 +UnregisterGPNotification@4 ;EOF diff --git a/reactos/lib/userenv/userenv.xml b/reactos/lib/userenv/userenv.xml index e88e5bf4d4a..86d86eb5010 100644 --- a/reactos/lib/userenv/userenv.xml +++ b/reactos/lib/userenv/userenv.xml @@ -13,6 +13,7 @@ desktop.c directory.c environment.c + gpolicy.c misc.c profile.c registry.c