mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 03:27:31 +00:00
218 lines
5.9 KiB
C
218 lines
5.9 KiB
C
/*
|
|
* PROJECT: Local Security Authority Server DLL
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: LSA policy change notifications
|
|
* COPYRIGHT: Eric Kohl 2018
|
|
*/
|
|
|
|
#include "lsasrv.h"
|
|
|
|
typedef struct _LSA_NOTIFICATION_ENTRY
|
|
{
|
|
LIST_ENTRY Entry;
|
|
POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass;
|
|
CLIENT_ID ClientId;
|
|
HANDLE EventHandle;
|
|
HANDLE MappedEventHandle;
|
|
} LSA_NOTIFICATION_ENTRY, *PLSA_NOTIFICATION_ENTRY;
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
static LIST_ENTRY NotificationListHead;
|
|
static RTL_RESOURCE NotificationListLock;
|
|
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
VOID
|
|
LsapInitNotificationList(VOID)
|
|
{
|
|
InitializeListHead(&NotificationListHead);
|
|
RtlInitializeResource(&NotificationListLock);
|
|
}
|
|
|
|
|
|
static
|
|
PLSA_NOTIFICATION_ENTRY
|
|
LsapGetNotificationEntry(
|
|
PLSA_API_MSG pRequestMsg)
|
|
{
|
|
PLIST_ENTRY NotificationEntry;
|
|
PLSA_NOTIFICATION_ENTRY CurrentNotification;
|
|
|
|
NotificationEntry = NotificationListHead.Flink;
|
|
while (NotificationEntry != &NotificationListHead)
|
|
{
|
|
CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
|
|
|
|
if ((CurrentNotification->ClientId.UniqueProcess == pRequestMsg->h.ClientId.UniqueProcess) &&
|
|
(CurrentNotification->ClientId.UniqueThread == pRequestMsg->h.ClientId.UniqueThread) &&
|
|
(CurrentNotification->InformationClass == pRequestMsg->PolicyChangeNotify.Request.InformationClass) &&
|
|
(CurrentNotification->EventHandle == pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle))
|
|
return CurrentNotification;
|
|
|
|
NotificationEntry = NotificationEntry->Flink;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddNotification(
|
|
PLSA_API_MSG pRequestMsg)
|
|
{
|
|
PLSA_NOTIFICATION_ENTRY pEntry;
|
|
HANDLE hProcess = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
TRACE("LsapAddNotification(%p)\n", pRequestMsg);
|
|
|
|
/* Allocate a new notification list entry */
|
|
pEntry = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(LSA_NOTIFICATION_ENTRY));
|
|
if (pEntry == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
/* Copy the notification data */
|
|
pEntry->InformationClass = pRequestMsg->PolicyChangeNotify.Request.InformationClass;
|
|
pEntry->EventHandle = pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle;
|
|
pEntry->ClientId = pRequestMsg->h.ClientId;
|
|
|
|
/* Open the client process */
|
|
Status = NtOpenProcess(&hProcess,
|
|
PROCESS_DUP_HANDLE,
|
|
NULL,
|
|
pEntry->ClientId.UniqueProcess);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtOpenProcess() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Duplicate the event handle into the current process */
|
|
Status = NtDuplicateObject(hProcess,
|
|
pEntry->EventHandle,
|
|
NtCurrentProcess(),
|
|
&pEntry->MappedEventHandle,
|
|
0,
|
|
0,
|
|
DUPLICATE_SAME_ACCESS);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtDuplicateObject() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Insert the new entry into the notification list */
|
|
InsertHeadList(&NotificationListHead,
|
|
&pEntry->Entry);
|
|
|
|
done:
|
|
if (hProcess != NULL)
|
|
NtClose(hProcess);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pEntry != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapRemoveNotification(
|
|
PLSA_API_MSG pRequestMsg)
|
|
{
|
|
PLSA_NOTIFICATION_ENTRY pEntry;
|
|
|
|
TRACE("LsapRemoveNotification(%p)\n", pRequestMsg);
|
|
|
|
pEntry = LsapGetNotificationEntry(pRequestMsg);
|
|
if (pEntry == NULL)
|
|
{
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
/* Remove the notification entry from the notification list */
|
|
RemoveEntryList(&pEntry->Entry);
|
|
|
|
/* Close the mapped event handle */
|
|
NtClose(pEntry->MappedEventHandle);
|
|
|
|
/* Release the notification entry */
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapRegisterNotification(
|
|
PLSA_API_MSG pRequestMsg)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
TRACE("LsapRegisterNotification(%p)\n", pRequestMsg);
|
|
|
|
/* Acquire the notification list lock exclusively */
|
|
RtlAcquireResourceExclusive(&NotificationListLock, TRUE);
|
|
|
|
if (pRequestMsg->PolicyChangeNotify.Request.Register)
|
|
{
|
|
/* Register the notification event */
|
|
Status = LsapAddNotification(pRequestMsg);
|
|
}
|
|
else
|
|
{
|
|
/* Unregister the notification event */
|
|
Status = LsapRemoveNotification(pRequestMsg);
|
|
}
|
|
|
|
/* Release the notification list lock */
|
|
RtlReleaseResource(&NotificationListLock);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
LsapNotifyPolicyChange(
|
|
POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass)
|
|
{
|
|
PLIST_ENTRY NotificationEntry;
|
|
PLSA_NOTIFICATION_ENTRY CurrentNotification;
|
|
|
|
TRACE("LsapNotifyPolicyChange(%lu)\n", InformationClass);
|
|
|
|
/* Acquire the notification list lock shared */
|
|
RtlAcquireResourceShared(&NotificationListLock, TRUE);
|
|
|
|
NotificationEntry = NotificationListHead.Flink;
|
|
while (NotificationEntry != &NotificationListHead)
|
|
{
|
|
CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
|
|
|
|
if (CurrentNotification->InformationClass == InformationClass)
|
|
{
|
|
TRACE("Notify event %p\n", CurrentNotification->MappedEventHandle);
|
|
NtSetEvent(CurrentNotification->MappedEventHandle, NULL);
|
|
}
|
|
|
|
NotificationEntry = NotificationEntry->Flink;
|
|
}
|
|
|
|
/* Release the notification list lock */
|
|
RtlReleaseResource(&NotificationListLock);
|
|
}
|
|
|
|
/* EOF */
|