xref: /reactos/dll/win32/lsasrv/notify.c (revision dd1f0d02)
1620217ceSEric Kohl /*
2620217ceSEric Kohl  * PROJECT:     Local Security Authority Server DLL
3620217ceSEric Kohl  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4620217ceSEric Kohl  * PURPOSE:     LSA policy change notifications
5620217ceSEric Kohl  * COPYRIGHT:   Eric Kohl 2018
6620217ceSEric Kohl  */
7620217ceSEric Kohl 
8620217ceSEric Kohl #include "lsasrv.h"
9620217ceSEric Kohl 
10620217ceSEric Kohl typedef struct _LSA_NOTIFICATION_ENTRY
11620217ceSEric Kohl {
12620217ceSEric Kohl     LIST_ENTRY Entry;
13620217ceSEric Kohl     POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass;
14*dd1f0d02SEric Kohl     CLIENT_ID ClientId;
15620217ceSEric Kohl     HANDLE EventHandle;
16*dd1f0d02SEric Kohl     HANDLE MappedEventHandle;
17620217ceSEric Kohl } LSA_NOTIFICATION_ENTRY, *PLSA_NOTIFICATION_ENTRY;
18620217ceSEric Kohl 
19620217ceSEric Kohl /* GLOBALS *****************************************************************/
20620217ceSEric Kohl 
21620217ceSEric Kohl static LIST_ENTRY NotificationListHead;
22620217ceSEric Kohl static RTL_RESOURCE NotificationListLock;
23620217ceSEric Kohl 
24620217ceSEric Kohl 
25620217ceSEric Kohl /* FUNCTIONS ***************************************************************/
26620217ceSEric Kohl 
27620217ceSEric Kohl VOID
LsapInitNotificationList(VOID)28620217ceSEric Kohl LsapInitNotificationList(VOID)
29620217ceSEric Kohl {
30620217ceSEric Kohl     InitializeListHead(&NotificationListHead);
31620217ceSEric Kohl     RtlInitializeResource(&NotificationListLock);
32620217ceSEric Kohl }
33620217ceSEric Kohl 
34620217ceSEric Kohl 
35620217ceSEric Kohl static
36620217ceSEric Kohl PLSA_NOTIFICATION_ENTRY
LsapGetNotificationEntry(PLSA_API_MSG pRequestMsg)374e32ad36SEric Kohl LsapGetNotificationEntry(
38*dd1f0d02SEric Kohl     PLSA_API_MSG pRequestMsg)
39620217ceSEric Kohl {
40620217ceSEric Kohl     PLIST_ENTRY NotificationEntry;
41620217ceSEric Kohl     PLSA_NOTIFICATION_ENTRY CurrentNotification;
42620217ceSEric Kohl 
43620217ceSEric Kohl     NotificationEntry = NotificationListHead.Flink;
44620217ceSEric Kohl     while (NotificationEntry != &NotificationListHead)
45620217ceSEric Kohl     {
46620217ceSEric Kohl         CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
47620217ceSEric Kohl 
48*dd1f0d02SEric Kohl         if ((CurrentNotification->ClientId.UniqueProcess == pRequestMsg->h.ClientId.UniqueProcess) &&
49*dd1f0d02SEric Kohl             (CurrentNotification->ClientId.UniqueThread == pRequestMsg->h.ClientId.UniqueThread) &&
50*dd1f0d02SEric Kohl             (CurrentNotification->InformationClass == pRequestMsg->PolicyChangeNotify.Request.InformationClass) &&
51*dd1f0d02SEric Kohl             (CurrentNotification->EventHandle == pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle))
52620217ceSEric Kohl             return CurrentNotification;
53620217ceSEric Kohl 
54620217ceSEric Kohl         NotificationEntry = NotificationEntry->Flink;
55620217ceSEric Kohl     }
56620217ceSEric Kohl 
57620217ceSEric Kohl     return NULL;
58620217ceSEric Kohl }
59620217ceSEric Kohl 
60620217ceSEric Kohl 
61*dd1f0d02SEric Kohl static
62620217ceSEric Kohl NTSTATUS
LsapAddNotification(PLSA_API_MSG pRequestMsg)63*dd1f0d02SEric Kohl LsapAddNotification(
64620217ceSEric Kohl     PLSA_API_MSG pRequestMsg)
65620217ceSEric Kohl {
66620217ceSEric Kohl     PLSA_NOTIFICATION_ENTRY pEntry;
67*dd1f0d02SEric Kohl     HANDLE hProcess = NULL;
68620217ceSEric Kohl     NTSTATUS Status = STATUS_SUCCESS;
69620217ceSEric Kohl 
70*dd1f0d02SEric Kohl     TRACE("LsapAddNotification(%p)\n", pRequestMsg);
71620217ceSEric Kohl 
72*dd1f0d02SEric Kohl     /* Allocate a new notification list entry */
73620217ceSEric Kohl     pEntry = RtlAllocateHeap(RtlGetProcessHeap(),
74620217ceSEric Kohl                              HEAP_ZERO_MEMORY,
75620217ceSEric Kohl                              sizeof(LSA_NOTIFICATION_ENTRY));
76620217ceSEric Kohl     if (pEntry == NULL)
77620217ceSEric Kohl     {
78620217ceSEric Kohl         Status = STATUS_INSUFFICIENT_RESOURCES;
79620217ceSEric Kohl         goto done;
80620217ceSEric Kohl     }
81620217ceSEric Kohl 
82*dd1f0d02SEric Kohl     /* Copy the notification data */
83620217ceSEric Kohl     pEntry->InformationClass = pRequestMsg->PolicyChangeNotify.Request.InformationClass;
84620217ceSEric Kohl     pEntry->EventHandle = pRequestMsg->PolicyChangeNotify.Request.NotificationEventHandle;
85*dd1f0d02SEric Kohl     pEntry->ClientId = pRequestMsg->h.ClientId;
86620217ceSEric Kohl 
87*dd1f0d02SEric Kohl     /* Open the client process */
88*dd1f0d02SEric Kohl     Status = NtOpenProcess(&hProcess,
89*dd1f0d02SEric Kohl                            PROCESS_DUP_HANDLE,
90*dd1f0d02SEric Kohl                            NULL,
91*dd1f0d02SEric Kohl                            pEntry->ClientId.UniqueProcess);
92*dd1f0d02SEric Kohl     if (!NT_SUCCESS(Status))
93*dd1f0d02SEric Kohl     {
94*dd1f0d02SEric Kohl         ERR("NtOpenProcess() failed (Status 0x%08lx)\n", Status);
95*dd1f0d02SEric Kohl         goto done;
96*dd1f0d02SEric Kohl     }
97*dd1f0d02SEric Kohl 
98*dd1f0d02SEric Kohl     /* Duplicate the event handle into the current process */
99*dd1f0d02SEric Kohl     Status = NtDuplicateObject(hProcess,
100*dd1f0d02SEric Kohl                                pEntry->EventHandle,
101*dd1f0d02SEric Kohl                                NtCurrentProcess(),
102*dd1f0d02SEric Kohl                                &pEntry->MappedEventHandle,
103*dd1f0d02SEric Kohl                                0,
104*dd1f0d02SEric Kohl                                0,
105*dd1f0d02SEric Kohl                                DUPLICATE_SAME_ACCESS);
106*dd1f0d02SEric Kohl     if (!NT_SUCCESS(Status))
107*dd1f0d02SEric Kohl     {
108*dd1f0d02SEric Kohl         ERR("NtDuplicateObject() failed (Status 0x%08lx)\n", Status);
109*dd1f0d02SEric Kohl         goto done;
110*dd1f0d02SEric Kohl     }
111*dd1f0d02SEric Kohl 
112*dd1f0d02SEric Kohl     /* Insert the new entry into the notification list */
113620217ceSEric Kohl     InsertHeadList(&NotificationListHead,
114620217ceSEric Kohl                    &pEntry->Entry);
115*dd1f0d02SEric Kohl 
116*dd1f0d02SEric Kohl done:
117*dd1f0d02SEric Kohl     if (hProcess != NULL)
118*dd1f0d02SEric Kohl         NtClose(hProcess);
119*dd1f0d02SEric Kohl 
120*dd1f0d02SEric Kohl     if (!NT_SUCCESS(Status))
121*dd1f0d02SEric Kohl     {
122*dd1f0d02SEric Kohl         if (pEntry != NULL)
123*dd1f0d02SEric Kohl             RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
124*dd1f0d02SEric Kohl     }
125*dd1f0d02SEric Kohl 
126*dd1f0d02SEric Kohl     return Status;
127*dd1f0d02SEric Kohl }
128*dd1f0d02SEric Kohl 
129*dd1f0d02SEric Kohl 
130*dd1f0d02SEric Kohl static
131*dd1f0d02SEric Kohl NTSTATUS
LsapRemoveNotification(PLSA_API_MSG pRequestMsg)132*dd1f0d02SEric Kohl LsapRemoveNotification(
133*dd1f0d02SEric Kohl     PLSA_API_MSG pRequestMsg)
134*dd1f0d02SEric Kohl {
135*dd1f0d02SEric Kohl     PLSA_NOTIFICATION_ENTRY pEntry;
136*dd1f0d02SEric Kohl 
137*dd1f0d02SEric Kohl     TRACE("LsapRemoveNotification(%p)\n", pRequestMsg);
138*dd1f0d02SEric Kohl 
139*dd1f0d02SEric Kohl     pEntry = LsapGetNotificationEntry(pRequestMsg);
140*dd1f0d02SEric Kohl     if (pEntry == NULL)
141*dd1f0d02SEric Kohl     {
142*dd1f0d02SEric Kohl         return STATUS_INVALID_HANDLE;
143*dd1f0d02SEric Kohl     }
144*dd1f0d02SEric Kohl 
145*dd1f0d02SEric Kohl     /* Remove the  notification entry from the notification list */
146*dd1f0d02SEric Kohl     RemoveEntryList(&pEntry->Entry);
147*dd1f0d02SEric Kohl 
148*dd1f0d02SEric Kohl     /* Close the mapped event handle */
149*dd1f0d02SEric Kohl     NtClose(pEntry->MappedEventHandle);
150*dd1f0d02SEric Kohl 
151*dd1f0d02SEric Kohl     /* Release the notification entry */
152*dd1f0d02SEric Kohl     RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
153*dd1f0d02SEric Kohl 
154*dd1f0d02SEric Kohl     return STATUS_SUCCESS;
155*dd1f0d02SEric Kohl }
156*dd1f0d02SEric Kohl 
157*dd1f0d02SEric Kohl 
158*dd1f0d02SEric Kohl NTSTATUS
LsapRegisterNotification(PLSA_API_MSG pRequestMsg)159*dd1f0d02SEric Kohl LsapRegisterNotification(
160*dd1f0d02SEric Kohl     PLSA_API_MSG pRequestMsg)
161*dd1f0d02SEric Kohl {
162*dd1f0d02SEric Kohl     NTSTATUS Status;
163*dd1f0d02SEric Kohl 
164*dd1f0d02SEric Kohl     TRACE("LsapRegisterNotification(%p)\n", pRequestMsg);
165*dd1f0d02SEric Kohl 
166*dd1f0d02SEric Kohl     /* Acquire the notification list lock exclusively */
167*dd1f0d02SEric Kohl     RtlAcquireResourceExclusive(&NotificationListLock, TRUE);
168*dd1f0d02SEric Kohl 
169*dd1f0d02SEric Kohl     if (pRequestMsg->PolicyChangeNotify.Request.Register)
170*dd1f0d02SEric Kohl     {
171*dd1f0d02SEric Kohl         /* Register the notification event */
172*dd1f0d02SEric Kohl         Status = LsapAddNotification(pRequestMsg);
173620217ceSEric Kohl     }
174620217ceSEric Kohl     else
175620217ceSEric Kohl     {
1764e32ad36SEric Kohl         /* Unregister the notification event */
177*dd1f0d02SEric Kohl         Status = LsapRemoveNotification(pRequestMsg);
1784e32ad36SEric Kohl     }
1794e32ad36SEric Kohl 
180620217ceSEric Kohl     /* Release the notification list lock */
181620217ceSEric Kohl     RtlReleaseResource(&NotificationListLock);
182620217ceSEric Kohl 
183620217ceSEric Kohl     return Status;
184620217ceSEric Kohl }
185620217ceSEric Kohl 
1864e32ad36SEric Kohl 
1874e32ad36SEric Kohl VOID
LsapNotifyPolicyChange(POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass)1884e32ad36SEric Kohl LsapNotifyPolicyChange(
1894e32ad36SEric Kohl     POLICY_NOTIFICATION_INFORMATION_CLASS InformationClass)
1904e32ad36SEric Kohl {
1914e32ad36SEric Kohl     PLIST_ENTRY NotificationEntry;
1924e32ad36SEric Kohl     PLSA_NOTIFICATION_ENTRY CurrentNotification;
1934e32ad36SEric Kohl 
194*dd1f0d02SEric Kohl     TRACE("LsapNotifyPolicyChange(%lu)\n", InformationClass);
1954e32ad36SEric Kohl 
1964e32ad36SEric Kohl     /* Acquire the notification list lock shared */
1974e32ad36SEric Kohl     RtlAcquireResourceShared(&NotificationListLock, TRUE);
1984e32ad36SEric Kohl 
1994e32ad36SEric Kohl     NotificationEntry = NotificationListHead.Flink;
2004e32ad36SEric Kohl     while (NotificationEntry != &NotificationListHead)
2014e32ad36SEric Kohl     {
2024e32ad36SEric Kohl         CurrentNotification = CONTAINING_RECORD(NotificationEntry, LSA_NOTIFICATION_ENTRY, Entry);
2034e32ad36SEric Kohl 
2044e32ad36SEric Kohl         if (CurrentNotification->InformationClass == InformationClass)
2054e32ad36SEric Kohl         {
206*dd1f0d02SEric Kohl             TRACE("Notify event %p\n", CurrentNotification->MappedEventHandle);
207*dd1f0d02SEric Kohl             NtSetEvent(CurrentNotification->MappedEventHandle, NULL);
2084e32ad36SEric Kohl         }
2094e32ad36SEric Kohl 
2104e32ad36SEric Kohl         NotificationEntry = NotificationEntry->Flink;
2114e32ad36SEric Kohl     }
2124e32ad36SEric Kohl 
2134e32ad36SEric Kohl     /* Release the notification list lock */
2144e32ad36SEric Kohl     RtlReleaseResource(&NotificationListLock);
2154e32ad36SEric Kohl }
2164e32ad36SEric Kohl 
217620217ceSEric Kohl /* EOF */
218