- partially implemented RegisterGPNotification() and UnregisterGPNotification() (depends on GetModuleHandleEx which is not yet implemented)
- use debug.h
Modified: trunk/reactos/lib/userenv/desktop.c
Modified: trunk/reactos/lib/userenv/directory.c
Modified: trunk/reactos/lib/userenv/environment.c
Added: trunk/reactos/lib/userenv/gpolicy.c
Modified: trunk/reactos/lib/userenv/internal.h
Modified: trunk/reactos/lib/userenv/misc.c
Modified: trunk/reactos/lib/userenv/profile.c
Modified: trunk/reactos/lib/userenv/registry.c
Modified: trunk/reactos/lib/userenv/setup.c
Modified: trunk/reactos/lib/userenv/userenv.c
Modified: trunk/reactos/lib/userenv/userenv.def
Modified: trunk/reactos/lib/userenv/userenv.xml

Modified: trunk/reactos/lib/userenv/desktop.c
--- trunk/reactos/lib/userenv/desktop.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/desktop.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 /* FUNCTIONS ***************************************************************/
 
 static BOOL

Modified: trunk/reactos/lib/userenv/directory.c
--- trunk/reactos/lib/userenv/directory.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/directory.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 /* FUNCTIONS ***************************************************************/
 
 BOOL STDCALL

Modified: trunk/reactos/lib/userenv/environment.c
--- trunk/reactos/lib/userenv/environment.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/environment.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 static BOOL
 SetUserEnvironmentVariable (LPVOID *Environment,
 			    LPWSTR lpName,

Added: trunk/reactos/lib/userenv/gpolicy.c
--- trunk/reactos/lib/userenv/gpolicy.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/gpolicy.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -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 <w3seek@reactos.com>
+ */
+
+#include <precomp.h>
+
+#define NDEBUG
+#include <debug.h>
+
+
+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;
+}
Property changes on: trunk/reactos/lib/userenv/gpolicy.c
___________________________________________________________________
Name: svn:keywords
   + author date revision
Name: svn:eol-style
   + native

Modified: trunk/reactos/lib/userenv/internal.h
--- trunk/reactos/lib/userenv/internal.h	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/internal.h	2006-01-11 22:40:31 UTC (rev 20792)
@@ -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 @@
 GetUserSidFromToken (HANDLE hToken,
 		     PUNICODE_STRING SidString);
 
+PVOID
+CreateDefaultSD(VOID);
+
 /* profile.c */
 BOOL
 AppendSystemPostfix (LPWSTR lpName,
@@ -109,6 +98,14 @@
 /* userenv.c */
 extern HINSTANCE hInstance;
 
+/* gpolicy.c */
+
+VOID
+InitializeGPNotifications(VOID);
+
+VOID
+UninitializeGPNotifications(VOID);
+
 #endif /* _INTERNAL_H */
 
 /* EOF */

Modified: trunk/reactos/lib/userenv/misc.c
--- trunk/reactos/lib/userenv/misc.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/misc.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 /* FUNCTIONS ***************************************************************/
 
 LPWSTR
@@ -109,6 +112,13 @@
   return TRUE;
 }
 
+PVOID
+CreateDefaultSD(VOID)
+{
+    /* FIXME - create a default security descriptor */
+    return NULL;
+}
+
 /* Dynamic DLL loading interface **********************************************/
 
 /* OLE32.DLL import table */

Modified: trunk/reactos/lib/userenv/profile.c
--- trunk/reactos/lib/userenv/profile.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/profile.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 /* FUNCTIONS ***************************************************************/
 
 BOOL

Modified: trunk/reactos/lib/userenv/registry.c
--- trunk/reactos/lib/userenv/registry.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/registry.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,7 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
 
+
 /* FUNCTIONS ***************************************************************/
 
 static BOOL

Modified: trunk/reactos/lib/userenv/setup.c
--- trunk/reactos/lib/userenv/setup.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/setup.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,6 +27,10 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
+
+
 typedef struct _FOLDERDATA
 {
   LPWSTR lpValueName;

Modified: trunk/reactos/lib/userenv/userenv.c
--- trunk/reactos/lib/userenv/userenv.c	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/userenv.c	2006-01-11 22:40:31 UTC (rev 20792)
@@ -27,6 +27,9 @@
 
 #include <precomp.h>
 
+#define NDEBUG
+#include <debug.h>
+
 HINSTANCE hInstance = NULL;
 
 BOOL WINAPI
@@ -37,9 +40,11 @@
   if (fdwReason == DLL_PROCESS_ATTACH)
     {
        hInstance = hinstDLL;
+       InitializeGPNotifications();
     }
   else if (fdwReason == DLL_PROCESS_DETACH)
     {
+        UninitializeGPNotifications();
     }
 
   return TRUE;

Modified: trunk/reactos/lib/userenv/userenv.def
--- trunk/reactos/lib/userenv/userenv.def	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/userenv.def	2006-01-11 22:40:31 UTC (rev 20792)
@@ -31,5 +31,7 @@
 GetUserProfileDirectoryW@12
 LoadUserProfileA@8
 LoadUserProfileW@8
+RegisterGPNotification@8
 UnloadUserProfile@8
+UnregisterGPNotification@4
 ;EOF

Modified: trunk/reactos/lib/userenv/userenv.xml
--- trunk/reactos/lib/userenv/userenv.xml	2006-01-11 22:13:02 UTC (rev 20791)
+++ trunk/reactos/lib/userenv/userenv.xml	2006-01-11 22:40:31 UTC (rev 20792)
@@ -13,6 +13,7 @@
 	<file>desktop.c</file>
 	<file>directory.c</file>
 	<file>environment.c</file>
+	<file>gpolicy.c</file>
 	<file>misc.c</file>
 	<file>profile.c</file>
 	<file>registry.c</file>