/* * 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 */