[LSASRV] Improve the policy change registration code and notify registered events

This commit is contained in:
Eric Kohl 2021-02-21 18:05:11 +01:00
parent d4d897ccb7
commit dd1f0d02bc

View file

@ -11,7 +11,9 @@ 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 *****************************************************************/
@ -33,8 +35,7 @@ LsapInitNotificationList(VOID)
static
PLSA_NOTIFICATION_ENTRY
LsapGetNotificationEntry(
HANDLE EventHandle,
POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass)
PLSA_API_MSG pRequestMsg)
{
PLIST_ENTRY NotificationEntry;
PLSA_NOTIFICATION_ENTRY CurrentNotification;
@ -44,8 +45,10 @@ LsapGetNotificationEntry(
{
CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
if ((CurrentNotification->EventHandle == EventHandle) &&
(CurrentNotification->InformationClass == InformationClass))
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;
@ -55,14 +58,110 @@ LsapGetNotificationEntry(
}
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)
{
PLSA_NOTIFICATION_ENTRY pEntry;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS Status;
FIXME("LsapRegisterNotification(%p)\n", pRequestMsg);
TRACE("LsapRegisterNotification(%p)\n", pRequestMsg);
/* Acquire the notification list lock exclusively */
RtlAcquireResourceExclusive(&NotificationListLock, TRUE);
@ -70,37 +169,14 @@ LsapRegisterNotification(
if (pRequestMsg->PolicyChangeNotify.Request.Register)
{
/* Register the notification event */
pEntry = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(LSA_NOTIFICATION_ENTRY));
if (pEntry == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
pEntry->InformationClass = pRequestMsg->PolicyChangeNotify.Request.InformationClass;
pEntry->EventHandle = pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle;
InsertHeadList(&NotificationListHead,
&pEntry->Entry);
Status = LsapAddNotification(pRequestMsg);
}
else
{
/* Unregister the notification event */
pEntry = LsapGetNotificationEntry(pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle,
pRequestMsg->PolicyChangeNotify.Request.InformationClass);
if (pEntry == NULL)
{
Status = STATUS_INVALID_HANDLE;
goto done;
}
RemoveEntryList(&pEntry->Entry);
RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
Status = LsapRemoveNotification(pRequestMsg);
}
done:
/* Release the notification list lock */
RtlReleaseResource(&NotificationListLock);
@ -115,7 +191,7 @@ LsapNotifyPolicyChange(
PLIST_ENTRY NotificationEntry;
PLSA_NOTIFICATION_ENTRY CurrentNotification;
FIXME("LsapNotifyPolicyChange(%lu)\n", InformationClass);
TRACE("LsapNotifyPolicyChange(%lu)\n", InformationClass);
/* Acquire the notification list lock shared */
RtlAcquireResourceShared(&NotificationListLock, TRUE);
@ -127,8 +203,8 @@ LsapNotifyPolicyChange(
if (CurrentNotification->InformationClass == InformationClass)
{
FIXME("Notify event %p\n", CurrentNotification->EventHandle);
TRACE("Notify event %p\n", CurrentNotification->MappedEventHandle);
NtSetEvent(CurrentNotification->MappedEventHandle, NULL);
}
NotificationEntry = NotificationEntry->Flink;