reactos/base/system/winlogon/notify.c

342 lines
8.7 KiB
C

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