2015-08-16 14:39:44 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2019-08-03 13:04:50 +00:00
|
|
|
PWSTR pszKeyName;
|
|
|
|
PWSTR pszDllName;
|
2015-08-29 15:50:02 +00:00
|
|
|
BOOL bEnabled;
|
|
|
|
BOOL bAsynchronous;
|
|
|
|
BOOL bSafe;
|
|
|
|
BOOL bImpersonate;
|
|
|
|
BOOL bSmartCardLogon;
|
|
|
|
DWORD dwMaxWait;
|
2020-12-21 19:42:40 +00:00
|
|
|
BOOL bSfcNotification;
|
2015-08-16 14:39:44 +00:00
|
|
|
} NOTIFICATION_ITEM, *PNOTIFICATION_ITEM;
|
|
|
|
|
|
|
|
|
|
|
|
static LIST_ENTRY NotificationDllListHead;
|
|
|
|
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2020-12-21 19:42:40 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
AddSfcNotification(VOID)
|
|
|
|
{
|
|
|
|
WCHAR szSfcFileName[MAX_PATH];
|
|
|
|
PNOTIFICATION_ITEM NotificationDll;
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
ExpandEnvironmentStringsW(L"%windir%\\system32\\sfc.dll",
|
|
|
|
szSfcFileName,
|
|
|
|
ARRAYSIZE(szSfcFileName));
|
|
|
|
|
|
|
|
NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(NOTIFICATION_ITEM));
|
|
|
|
if (NotificationDll == NULL)
|
|
|
|
{
|
|
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(wcslen(szSfcFileName) + 1) * sizeof(WCHAR));
|
|
|
|
if (NotificationDll->pszDllName == NULL)
|
|
|
|
{
|
|
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy(NotificationDll->pszDllName, szSfcFileName);
|
|
|
|
|
|
|
|
NotificationDll->bEnabled = TRUE;
|
|
|
|
NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
|
|
|
|
NotificationDll->bSfcNotification = TRUE;
|
|
|
|
|
|
|
|
InsertHeadList(&NotificationDllListHead,
|
|
|
|
&NotificationDll->ListEntry);
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
if (NotificationDll != NULL)
|
|
|
|
{
|
|
|
|
if (NotificationDll->pszDllName != NULL)
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
|
|
|
|
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-16 14:39:44 +00:00
|
|
|
static
|
|
|
|
VOID
|
2019-08-03 13:04:50 +00:00
|
|
|
AddNotificationDll(
|
2015-08-16 14:39:44 +00:00
|
|
|
HKEY hNotifyKey,
|
2019-08-03 13:04:50 +00:00
|
|
|
PWSTR pszKeyName)
|
2015-08-16 14:39:44 +00:00
|
|
|
{
|
|
|
|
HKEY hDllKey = NULL;
|
|
|
|
PNOTIFICATION_ITEM NotificationDll = NULL;
|
2019-08-03 13:04:50 +00:00
|
|
|
DWORD dwSize, dwType;
|
|
|
|
DWORD dwError;
|
2015-08-16 14:39:44 +00:00
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
TRACE("AddNotificationDll(%p %S)\n", hNotifyKey, pszKeyName);
|
2015-08-16 14:39:44 +00:00
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
dwError = RegOpenKeyExW(hNotifyKey,
|
|
|
|
pszKeyName,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hDllKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2015-08-16 14:39:44 +00:00
|
|
|
return;
|
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(NOTIFICATION_ITEM));
|
|
|
|
if (NotificationDll == NULL)
|
2015-08-16 14:39:44 +00:00
|
|
|
{
|
2019-08-03 13:04:50 +00:00
|
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
NotificationDll->pszKeyName = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(wcslen(pszKeyName) + 1) * sizeof(WCHAR));
|
|
|
|
if (NotificationDll->pszKeyName == NULL)
|
|
|
|
{
|
|
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy(NotificationDll->pszKeyName, pszKeyName);
|
|
|
|
|
|
|
|
dwSize = 0;
|
|
|
|
RegQueryValueExW(hDllKey,
|
|
|
|
L"DllName",
|
|
|
|
NULL,
|
|
|
|
&dwType,
|
|
|
|
NULL,
|
|
|
|
&dwSize);
|
|
|
|
if (dwSize == 0)
|
|
|
|
{
|
|
|
|
dwError = ERROR_FILE_NOT_FOUND;
|
|
|
|
goto done;
|
|
|
|
}
|
2015-08-16 14:39:44 +00:00
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwSize);
|
|
|
|
if (NotificationDll->pszDllName == NULL)
|
|
|
|
{
|
|
|
|
dwError = ERROR_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hDllKey,
|
|
|
|
L"DllName",
|
|
|
|
NULL,
|
|
|
|
&dwType,
|
|
|
|
(PBYTE)NotificationDll->pszDllName,
|
|
|
|
&dwSize);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
NotificationDll->bEnabled = TRUE;
|
|
|
|
NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
InsertHeadList(&NotificationDllListHead,
|
|
|
|
&NotificationDll->ListEntry);
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
if (NotificationDll != NULL)
|
2015-08-16 14:39:44 +00:00
|
|
|
{
|
2019-08-03 13:04:50 +00:00
|
|
|
if (NotificationDll->pszKeyName != NULL)
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
|
|
|
|
|
|
|
|
if (NotificationDll->pszDllName != NULL)
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
|
2015-08-16 14:39:44 +00:00
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
|
|
|
|
}
|
2015-08-16 14:39:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hDllKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
InitNotifications(VOID)
|
|
|
|
{
|
|
|
|
HKEY hNotifyKey = NULL;
|
|
|
|
LONG lError;
|
|
|
|
DWORD dwIndex;
|
|
|
|
WCHAR szKeyName[80];
|
|
|
|
DWORD dwKeyName;
|
|
|
|
|
|
|
|
TRACE("InitNotifications()\n");
|
|
|
|
|
|
|
|
InitializeListHead(&NotificationDllListHead);
|
|
|
|
|
2020-12-21 19:42:40 +00:00
|
|
|
AddSfcNotification();
|
|
|
|
|
2015-08-16 14:39:44 +00:00
|
|
|
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(;;)
|
|
|
|
{
|
2022-09-30 18:40:43 +00:00
|
|
|
dwKeyName = ARRAYSIZE(szKeyName);
|
2015-08-16 14:39:44 +00:00
|
|
|
lError = RegEnumKeyExW(hNotifyKey,
|
|
|
|
dwIndex,
|
|
|
|
szKeyName,
|
|
|
|
&dwKeyName,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (lError != ERROR_SUCCESS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
TRACE("Notification DLL: %S\n", szKeyName);
|
2019-08-03 13:04:50 +00:00
|
|
|
AddNotificationDll(hNotifyKey, szKeyName);
|
2015-08-16 14:39:44 +00:00
|
|
|
|
|
|
|
dwIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hNotifyKey);
|
|
|
|
|
|
|
|
TRACE("InitNotifications() done\n");
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
CallNotificationDll(
|
|
|
|
HKEY hNotifyKey,
|
|
|
|
PNOTIFICATION_ITEM NotificationDll,
|
|
|
|
NOTIFICATION_TYPE Type,
|
|
|
|
PWLX_NOTIFICATION_INFO pInfo)
|
|
|
|
{
|
2022-09-30 18:40:43 +00:00
|
|
|
HMODULE hModule;
|
2019-08-03 13:04:50 +00:00
|
|
|
CHAR szFuncBuffer[128];
|
2020-12-21 19:42:40 +00:00
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2019-08-03 13:04:50 +00:00
|
|
|
PWLX_NOTIFY_HANDLER pNotifyHandler;
|
|
|
|
|
2020-12-21 19:42:40 +00:00
|
|
|
if (NotificationDll->bSfcNotification)
|
2019-08-03 13:04:50 +00:00
|
|
|
{
|
2020-12-21 19:42:40 +00:00
|
|
|
switch (Type)
|
|
|
|
{
|
|
|
|
case LogonHandler:
|
|
|
|
strcpy(szFuncBuffer, "SfcWLEventLogon");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LogoffHandler:
|
|
|
|
strcpy(szFuncBuffer, "SfcWLEventLogoff");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-30 18:40:43 +00:00
|
|
|
HKEY hDllKey;
|
|
|
|
DWORD dwSize;
|
|
|
|
DWORD dwType;
|
|
|
|
|
2020-12-21 19:42:40 +00:00
|
|
|
dwError = RegOpenKeyExW(hNotifyKey,
|
|
|
|
NotificationDll->pszKeyName,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hDllKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
TRACE("RegOpenKeyExW()\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwSize = sizeof(szFuncBuffer);
|
|
|
|
dwError = RegQueryValueExA(hDllKey,
|
|
|
|
FuncNames[Type],
|
|
|
|
NULL,
|
|
|
|
&dwType,
|
|
|
|
(PBYTE)szFuncBuffer,
|
|
|
|
&dwSize);
|
2022-09-30 18:40:43 +00:00
|
|
|
|
|
|
|
RegCloseKey(hDllKey);
|
2019-08-03 13:04:50 +00:00
|
|
|
}
|
|
|
|
|
2022-09-30 18:40:43 +00:00
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return;
|
2019-08-03 13:04:50 +00:00
|
|
|
|
2022-09-30 18:40:43 +00:00
|
|
|
hModule = LoadLibraryW(NotificationDll->pszDllName);
|
|
|
|
if (!hModule)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pNotifyHandler = (PWLX_NOTIFY_HANDLER)GetProcAddress(hModule, szFuncBuffer);
|
|
|
|
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
if (pNotifyHandler)
|
|
|
|
pNotifyHandler(pInfo);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
ERR("WL: Exception while running notification %S!%s, Status 0x%08lx\n",
|
|
|
|
NotificationDll->pszDllName, szFuncBuffer, _SEH2_GetExceptionCode());
|
2019-08-03 13:04:50 +00:00
|
|
|
}
|
2022-09-30 18:40:43 +00:00
|
|
|
_SEH2_END;
|
2019-08-03 13:04:50 +00:00
|
|
|
|
2022-09-30 18:40:43 +00:00
|
|
|
FreeLibrary(hModule);
|
2019-08-03 13:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-16 14:39:44 +00:00
|
|
|
VOID
|
2015-08-23 15:48:52 +00:00
|
|
|
CallNotificationDlls(
|
|
|
|
PWLSESSION pSession,
|
|
|
|
NOTIFICATION_TYPE Type)
|
2015-08-16 14:39:44 +00:00
|
|
|
{
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
PNOTIFICATION_ITEM NotificationDll;
|
2015-08-23 15:48:52 +00:00
|
|
|
WLX_NOTIFICATION_INFO Info;
|
2019-08-03 13:04:50 +00:00
|
|
|
HKEY hNotifyKey = NULL;
|
|
|
|
DWORD dwError;
|
2015-08-23 15:48:52 +00:00
|
|
|
|
|
|
|
TRACE("CallNotificationDlls()\n");
|
|
|
|
|
2019-08-03 13:04:50 +00:00
|
|
|
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
|
|
|
|
0,
|
|
|
|
KEY_READ | KEY_ENUMERATE_SUB_KEYS,
|
|
|
|
&hNotifyKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
TRACE("RegOpenKeyExW()\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-23 15:48:52 +00:00
|
|
|
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;
|
2015-08-16 14:39:44 +00:00
|
|
|
|
|
|
|
ListEntry = NotificationDllListHead.Flink;
|
|
|
|
while (ListEntry != &NotificationDllListHead)
|
|
|
|
{
|
2015-08-23 15:48:52 +00:00
|
|
|
TRACE("ListEntry %p\n", ListEntry);
|
|
|
|
|
2015-08-16 14:39:44 +00:00
|
|
|
NotificationDll = CONTAINING_RECORD(ListEntry,
|
|
|
|
NOTIFICATION_ITEM,
|
|
|
|
ListEntry);
|
2015-08-23 15:48:52 +00:00
|
|
|
TRACE("NotificationDll: %p\n", NotificationDll);
|
2015-08-29 15:50:02 +00:00
|
|
|
if (NotificationDll != NULL && NotificationDll->bEnabled)
|
2019-08-03 13:04:50 +00:00
|
|
|
CallNotificationDll(hNotifyKey, NotificationDll, Type, &Info);
|
2015-08-23 15:48:52 +00:00
|
|
|
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
}
|
2019-08-03 13:04:50 +00:00
|
|
|
|
|
|
|
RegCloseKey(hNotifyKey);
|
2015-08-23 15:48:52 +00:00
|
|
|
}
|
2015-08-16 14:39:44 +00:00
|
|
|
|
|
|
|
|
2015-08-23 15:48:52 +00:00
|
|
|
VOID
|
|
|
|
CleanupNotifications(VOID)
|
|
|
|
{
|
|
|
|
PLIST_ENTRY ListEntry;
|
|
|
|
PNOTIFICATION_ITEM NotificationDll;
|
2015-08-16 14:39:44 +00:00
|
|
|
|
2015-08-23 15:48:52 +00:00
|
|
|
ListEntry = NotificationDllListHead.Flink;
|
|
|
|
while (ListEntry != &NotificationDllListHead)
|
|
|
|
{
|
|
|
|
NotificationDll = CONTAINING_RECORD(ListEntry,
|
|
|
|
NOTIFICATION_ITEM,
|
|
|
|
ListEntry);
|
|
|
|
if (NotificationDll != NULL)
|
|
|
|
{
|
2019-08-03 13:04:50 +00:00
|
|
|
if (NotificationDll->pszKeyName != NULL)
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
|
|
|
|
|
|
|
|
if (NotificationDll->pszDllName != NULL)
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
|
2015-08-16 14:39:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
|
|
|
|
|
|
RemoveEntryList(&NotificationDll->ListEntry);
|
2015-08-23 15:48:52 +00:00
|
|
|
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
|
2015-08-16 14:39:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|