Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / base / system / winlogon / notify.c
diff --git a/base/system/winlogon/notify.c b/base/system/winlogon/notify.c
new file mode 100644 (file)
index 0000000..6c20e0f
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Winlogon
+ * FILE:            base/system/winlogon/notify.c
+ * PURPOSE:         Logon notifications
+ * PROGRAMMERS:     Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "winlogon.h"
+
+/* GLOBALS ******************************************************************/
+
+
+// void Event_Handler_Function_Name(PWLX_NOTIFICATION_INFO pInfo);
+typedef VOID (WINAPI *PWLX_NOTIFY_HANDLER)(PWLX_NOTIFICATION_INFO pInfo);
+
+static PSTR FuncNames[LastHandler] =
+{
+    "Logon",
+    "Logoff",
+    "Lock",
+    "Unlock",
+    "Startup",
+    "Shutdown",
+    "StartScreenSaver",
+    "StopScreenSaver",
+    "Disconnect",
+    "Reconnect",
+    "StartShell",
+    "PostShell"
+};
+
+typedef struct _NOTIFICATION_ITEM
+{
+    LIST_ENTRY ListEntry;
+
+    HINSTANCE hInstance;
+    BOOL bEnabled;
+    BOOL bAsynchronous;
+    BOOL bSafe;
+    BOOL bImpersonate;
+    BOOL bSmartCardLogon;
+    DWORD dwMaxWait;
+    PWLX_NOTIFY_HANDLER Handler[LastHandler];
+} NOTIFICATION_ITEM, *PNOTIFICATION_ITEM;
+
+
+static LIST_ENTRY NotificationDllListHead;
+
+
+/* FUNCTIONS *****************************************************************/
+
+PWLX_NOTIFY_HANDLER
+GetNotificationHandler(
+    HKEY hDllKey,
+    HINSTANCE hInstance,
+    PSTR pNotification)
+{
+    CHAR szFuncBuffer[128];
+    DWORD dwSize;
+    DWORD dwType;
+    LONG lError;
+
+    dwSize = 128;
+    lError = RegQueryValueExA(hDllKey,
+                              pNotification,
+                              NULL,
+                              &dwType,
+                              (PBYTE)szFuncBuffer,
+                              &dwSize);
+    if (lError == ERROR_SUCCESS)
+    {
+        return (PWLX_NOTIFY_HANDLER)GetProcAddress(hInstance, szFuncBuffer);
+    }
+
+    return NULL;
+}
+
+
+static
+VOID
+LoadNotificationDll(
+    HKEY hNotifyKey,
+    PWSTR pKeyName)
+{
+    HKEY hDllKey = NULL;
+    PNOTIFICATION_ITEM NotificationDll = NULL;
+    LONG lError;
+    WCHAR szBuffer[80];
+    DWORD dwSize;
+    DWORD dwType;
+    HINSTANCE hInstance;
+    NOTIFICATION_TYPE i;
+
+    TRACE("LoadNotificationDll(%p %S)\n", hNotifyKey, pKeyName);
+
+    lError = RegOpenKeyExW(hNotifyKey,
+                           pKeyName,
+                           0,
+                           KEY_READ,
+                           &hDllKey);
+    if (lError != ERROR_SUCCESS)
+        return;
+
+    dwSize = 80 * sizeof(WCHAR);
+    lError = RegQueryValueExW(hDllKey,
+                              L"DllName",
+                              NULL,
+                              &dwType,
+                              (PBYTE)szBuffer,
+                              &dwSize);
+    if (lError == ERROR_SUCCESS)
+    {
+        hInstance = LoadLibraryW(szBuffer);
+        if (hInstance == NULL)
+            return;
+
+        NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
+                                          HEAP_ZERO_MEMORY,
+                                          sizeof(NOTIFICATION_ITEM));
+        if (NotificationDll == NULL)
+        {
+            FreeLibrary(hInstance);
+            return;
+        }
+
+        NotificationDll->bEnabled = TRUE;
+        NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
+        NotificationDll->hInstance = hInstance;
+
+        dwSize = sizeof(BOOL);
+        RegQueryValueExW(hDllKey,
+                         L"Asynchronous",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->bAsynchronous,
+                         &dwSize);
+
+        dwSize = sizeof(BOOL);
+        RegQueryValueExW(hDllKey,
+                         L"Enabled",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->bEnabled,
+                         &dwSize);
+
+        dwSize = sizeof(BOOL);
+        RegQueryValueExW(hDllKey,
+                         L"Impersonate",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->bImpersonate,
+                         &dwSize);
+
+        dwSize = sizeof(BOOL);
+        RegQueryValueExW(hDllKey,
+                         L"Safe",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->bSafe,
+                         &dwSize);
+
+        dwSize = sizeof(BOOL);
+        RegQueryValueExW(hDllKey,
+                         L"SmartCardLogonNotify",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->bSmartCardLogon,
+                         &dwSize);
+
+        dwSize = sizeof(DWORD);
+        RegQueryValueExW(hDllKey,
+                         L"MaxWait",
+                         NULL,
+                         &dwType,
+                         (PBYTE)&NotificationDll->dwMaxWait,
+                         &dwSize);
+
+        for (i = LogonHandler; i < LastHandler; i++)
+        {
+            NotificationDll->Handler[i] = GetNotificationHandler(hDllKey, hInstance, FuncNames[i]);
+            TRACE("%s: %p\n", FuncNames[i], NotificationDll->Handler[i]);
+        }
+
+        InsertHeadList(&NotificationDllListHead,
+                       &NotificationDll->ListEntry);
+    }
+
+    RegCloseKey(hDllKey);
+}
+
+
+BOOL
+InitNotifications(VOID)
+{
+    HKEY hNotifyKey = NULL;
+    LONG lError;
+    DWORD dwIndex;
+    WCHAR szKeyName[80];
+    DWORD dwKeyName;
+
+    TRACE("InitNotifications()\n");
+
+    InitializeListHead(&NotificationDllListHead);
+
+    lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                           L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
+                           0,
+                           KEY_READ | KEY_ENUMERATE_SUB_KEYS,
+                           &hNotifyKey);
+    if (lError != ERROR_SUCCESS)
+    {
+        TRACE("RegOpenKeyExW()\n");
+        return TRUE;
+    }
+
+    dwIndex = 0;
+    for(;;)
+    {
+        dwKeyName = 80 * sizeof(WCHAR);
+        lError = RegEnumKeyExW(hNotifyKey,
+                               dwIndex,
+                               szKeyName,
+                               &dwKeyName,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL);
+        if (lError != ERROR_SUCCESS)
+            break;
+
+        TRACE("Notification DLL: %S\n", szKeyName);
+        LoadNotificationDll(hNotifyKey, szKeyName);
+
+        dwIndex++;
+    }
+
+    RegCloseKey(hNotifyKey);
+
+    TRACE("InitNotifications() done\n");
+
+    return TRUE;
+}
+
+
+VOID
+CallNotificationDlls(
+    PWLSESSION pSession,
+    NOTIFICATION_TYPE Type)
+{
+    PLIST_ENTRY ListEntry;
+    PNOTIFICATION_ITEM NotificationDll;
+    WLX_NOTIFICATION_INFO Info;
+
+    TRACE("CallNotificationDlls()\n");
+
+    Info.Size = sizeof(WLX_NOTIFICATION_INFO);
+
+    switch (Type)
+    {
+        case LogoffHandler:
+        case ShutdownHandler:
+            Info.Flags = 3;
+            break;
+
+        default:
+            Info.Flags = 0;
+            break;
+    }
+
+    Info.UserName = NULL; //UserName;
+    Info.Domain = NULL; //Domain;
+    Info.WindowStation = pSession->InteractiveWindowStationName;
+    Info.hToken = pSession->UserToken;
+
+    switch (Type)
+    {
+        case LogonHandler:
+        case StartShellHandler:
+            Info.hDesktop = pSession->ApplicationDesktop;
+            break;
+
+        case StartScreenSaverHandler:
+            Info.hDesktop = pSession->ApplicationDesktop;
+            break;
+
+        default:
+            Info.hDesktop = pSession->WinlogonDesktop;
+            break;
+    }
+
+    Info.pStatusCallback = NULL;
+
+    ListEntry = NotificationDllListHead.Flink;
+    while (ListEntry != &NotificationDllListHead)
+    {
+TRACE("ListEntry %p\n", ListEntry);
+
+        NotificationDll = CONTAINING_RECORD(ListEntry,
+                                            NOTIFICATION_ITEM,
+                                            ListEntry);
+TRACE("NotificationDll: %p\n", NotificationDll);
+        if (NotificationDll != NULL && NotificationDll->bEnabled)
+        {
+TRACE("NotificationDll->Handler: %p\n", NotificationDll->Handler[Type]);
+            if (NotificationDll->Handler[Type] != NULL)
+                NotificationDll->Handler[Type](&Info);
+        }
+
+        ListEntry = ListEntry->Flink;
+    }
+}
+
+
+VOID
+CleanupNotifications(VOID)
+{
+    PLIST_ENTRY ListEntry;
+    PNOTIFICATION_ITEM NotificationDll;
+
+    ListEntry = NotificationDllListHead.Flink;
+    while (ListEntry != &NotificationDllListHead)
+    {
+        NotificationDll = CONTAINING_RECORD(ListEntry,
+                                            NOTIFICATION_ITEM,
+                                            ListEntry);
+        if (NotificationDll != NULL)
+        {
+            FreeLibrary(NotificationDll->hInstance);
+        }
+
+        ListEntry = ListEntry->Flink;
+
+        RemoveEntryList(&NotificationDll->ListEntry);
+
+        RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
+    }
+}
+
+/* EOF */