xref: /reactos/base/system/winlogon/notify.c (revision 139a3d66)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Winlogon
4  * FILE:            base/system/winlogon/notify.c
5  * PURPOSE:         Logon notifications
6  * PROGRAMMERS:     Eric Kohl
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "winlogon.h"
12 
13 /* GLOBALS ******************************************************************/
14 
15 
16 // void Event_Handler_Function_Name(PWLX_NOTIFICATION_INFO pInfo);
17 typedef VOID (WINAPI *PWLX_NOTIFY_HANDLER)(PWLX_NOTIFICATION_INFO pInfo);
18 
19 static PSTR FuncNames[LastHandler] =
20 {
21     "Logon",
22     "Logoff",
23     "Lock",
24     "Unlock",
25     "Startup",
26     "Shutdown",
27     "StartScreenSaver",
28     "StopScreenSaver",
29     "Disconnect",
30     "Reconnect",
31     "StartShell",
32     "PostShell"
33 };
34 
35 typedef struct _NOTIFICATION_ITEM
36 {
37     LIST_ENTRY ListEntry;
38     PWSTR pszKeyName;
39     PWSTR pszDllName;
40     BOOL bEnabled;
41     BOOL bAsynchronous;
42     BOOL bSafe;
43     BOOL bImpersonate;
44     BOOL bSmartCardLogon;
45     DWORD dwMaxWait;
46 } NOTIFICATION_ITEM, *PNOTIFICATION_ITEM;
47 
48 
49 static LIST_ENTRY NotificationDllListHead;
50 
51 
52 /* FUNCTIONS *****************************************************************/
53 
54 static
55 VOID
56 AddNotificationDll(
57     HKEY hNotifyKey,
58     PWSTR pszKeyName)
59 {
60     HKEY hDllKey = NULL;
61     PNOTIFICATION_ITEM NotificationDll = NULL;
62     DWORD dwSize, dwType;
63     DWORD dwError;
64 
65     TRACE("AddNotificationDll(%p %S)\n", hNotifyKey, pszKeyName);
66 
67     dwError = RegOpenKeyExW(hNotifyKey,
68                             pszKeyName,
69                             0,
70                             KEY_READ,
71                             &hDllKey);
72     if (dwError != ERROR_SUCCESS)
73         return;
74 
75     NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
76                                       HEAP_ZERO_MEMORY,
77                                       sizeof(NOTIFICATION_ITEM));
78     if (NotificationDll == NULL)
79     {
80         dwError = ERROR_OUTOFMEMORY;
81         goto done;
82     }
83 
84     NotificationDll->pszKeyName = RtlAllocateHeap(RtlGetProcessHeap(),
85                                                   HEAP_ZERO_MEMORY,
86                                                   (wcslen(pszKeyName) + 1) * sizeof(WCHAR));
87     if (NotificationDll->pszKeyName == NULL)
88     {
89         dwError = ERROR_OUTOFMEMORY;
90         goto done;
91     }
92 
93     wcscpy(NotificationDll->pszKeyName, pszKeyName);
94 
95     dwSize = 0;
96     RegQueryValueExW(hDllKey,
97                      L"DllName",
98                      NULL,
99                      &dwType,
100                      NULL,
101                      &dwSize);
102     if (dwSize == 0)
103     {
104         dwError = ERROR_FILE_NOT_FOUND;
105         goto done;
106     }
107 
108     NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(),
109                                                   HEAP_ZERO_MEMORY,
110                                                   dwSize);
111     if (NotificationDll->pszDllName == NULL)
112     {
113         dwError = ERROR_OUTOFMEMORY;
114         goto done;
115     }
116 
117     dwError = RegQueryValueExW(hDllKey,
118                                L"DllName",
119                                NULL,
120                                &dwType,
121                                (PBYTE)NotificationDll->pszDllName,
122                                &dwSize);
123     if (dwError != ERROR_SUCCESS)
124         goto done;
125 
126     NotificationDll->bEnabled = TRUE;
127     NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
128 
129     dwSize = sizeof(BOOL);
130     RegQueryValueExW(hDllKey,
131                      L"Asynchronous",
132                      NULL,
133                      &dwType,
134                      (PBYTE)&NotificationDll->bAsynchronous,
135                      &dwSize);
136 
137     dwSize = sizeof(BOOL);
138     RegQueryValueExW(hDllKey,
139                      L"Enabled",
140                      NULL,
141                      &dwType,
142                      (PBYTE)&NotificationDll->bEnabled,
143                      &dwSize);
144 
145     dwSize = sizeof(BOOL);
146     RegQueryValueExW(hDllKey,
147                      L"Impersonate",
148                      NULL,
149                      &dwType,
150                      (PBYTE)&NotificationDll->bImpersonate,
151                      &dwSize);
152 
153     dwSize = sizeof(BOOL);
154     RegQueryValueExW(hDllKey,
155                      L"Safe",
156                      NULL,
157                      &dwType,
158                      (PBYTE)&NotificationDll->bSafe,
159                      &dwSize);
160 
161     dwSize = sizeof(BOOL);
162     RegQueryValueExW(hDllKey,
163                      L"SmartCardLogonNotify",
164                      NULL,
165                      &dwType,
166                      (PBYTE)&NotificationDll->bSmartCardLogon,
167                      &dwSize);
168 
169     dwSize = sizeof(DWORD);
170     RegQueryValueExW(hDllKey,
171                      L"MaxWait",
172                      NULL,
173                      &dwType,
174                      (PBYTE)&NotificationDll->dwMaxWait,
175                      &dwSize);
176 
177     InsertHeadList(&NotificationDllListHead,
178                    &NotificationDll->ListEntry);
179 
180 done:
181     if (dwError != ERROR_SUCCESS)
182     {
183         if (NotificationDll != NULL)
184         {
185             if (NotificationDll->pszKeyName != NULL)
186                 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
187 
188             if (NotificationDll->pszDllName != NULL)
189                 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
190 
191             RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
192         }
193     }
194 
195     RegCloseKey(hDllKey);
196 }
197 
198 
199 BOOL
200 InitNotifications(VOID)
201 {
202     HKEY hNotifyKey = NULL;
203     LONG lError;
204     DWORD dwIndex;
205     WCHAR szKeyName[80];
206     DWORD dwKeyName;
207 
208     TRACE("InitNotifications()\n");
209 
210     InitializeListHead(&NotificationDllListHead);
211 
212     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
213                            L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
214                            0,
215                            KEY_READ | KEY_ENUMERATE_SUB_KEYS,
216                            &hNotifyKey);
217     if (lError != ERROR_SUCCESS)
218     {
219         TRACE("RegOpenKeyExW()\n");
220         return TRUE;
221     }
222 
223     dwIndex = 0;
224     for(;;)
225     {
226         dwKeyName = 80 * sizeof(WCHAR);
227         lError = RegEnumKeyExW(hNotifyKey,
228                                dwIndex,
229                                szKeyName,
230                                &dwKeyName,
231                                NULL,
232                                NULL,
233                                NULL,
234                                NULL);
235         if (lError != ERROR_SUCCESS)
236             break;
237 
238         TRACE("Notification DLL: %S\n", szKeyName);
239         AddNotificationDll(hNotifyKey, szKeyName);
240 
241         dwIndex++;
242     }
243 
244     RegCloseKey(hNotifyKey);
245 
246     TRACE("InitNotifications() done\n");
247 
248     return TRUE;
249 }
250 
251 
252 static
253 VOID
254 CallNotificationDll(
255     HKEY hNotifyKey,
256     PNOTIFICATION_ITEM NotificationDll,
257     NOTIFICATION_TYPE Type,
258     PWLX_NOTIFICATION_INFO pInfo)
259 {
260     HKEY hDllKey = NULL;
261     HMODULE hModule = NULL;
262     CHAR szFuncBuffer[128];
263     DWORD dwSize;
264     DWORD dwType;
265     DWORD dwError;
266     PWLX_NOTIFY_HANDLER pNotifyHandler;
267 
268     dwError = RegOpenKeyExW(hNotifyKey,
269                             NotificationDll->pszKeyName,
270                             0,
271                             KEY_READ,
272                             &hDllKey);
273     if (dwError != ERROR_SUCCESS)
274     {
275         TRACE("RegOpenKeyExW()\n");
276         return;
277     }
278 
279     dwSize = sizeof(szFuncBuffer);
280     dwError = RegQueryValueExA(hDllKey,
281                                FuncNames[Type],
282                                NULL,
283                                &dwType,
284                                (PBYTE)szFuncBuffer,
285                                &dwSize);
286     if (dwError == ERROR_SUCCESS)
287     {
288         hModule = LoadLibraryW(NotificationDll->pszDllName);
289         if (hModule != NULL)
290         {
291             pNotifyHandler = (PWLX_NOTIFY_HANDLER)GetProcAddress(hModule, szFuncBuffer);
292             if (pNotifyHandler != NULL)
293                 pNotifyHandler(pInfo);
294 
295             FreeLibrary(hModule);
296         }
297     }
298 
299     RegCloseKey(hDllKey);
300 }
301 
302 
303 VOID
304 CallNotificationDlls(
305     PWLSESSION pSession,
306     NOTIFICATION_TYPE Type)
307 {
308     PLIST_ENTRY ListEntry;
309     PNOTIFICATION_ITEM NotificationDll;
310     WLX_NOTIFICATION_INFO Info;
311     HKEY hNotifyKey = NULL;
312     DWORD dwError;
313 
314     TRACE("CallNotificationDlls()\n");
315 
316     dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
317                             L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
318                             0,
319                             KEY_READ | KEY_ENUMERATE_SUB_KEYS,
320                             &hNotifyKey);
321     if (dwError != ERROR_SUCCESS)
322     {
323         TRACE("RegOpenKeyExW()\n");
324         return;
325     }
326 
327     Info.Size = sizeof(WLX_NOTIFICATION_INFO);
328 
329     switch (Type)
330     {
331         case LogoffHandler:
332         case ShutdownHandler:
333             Info.Flags = 3;
334             break;
335 
336         default:
337             Info.Flags = 0;
338             break;
339     }
340 
341     Info.UserName = NULL; //UserName;
342     Info.Domain = NULL; //Domain;
343     Info.WindowStation = pSession->InteractiveWindowStationName;
344     Info.hToken = pSession->UserToken;
345 
346     switch (Type)
347     {
348         case LogonHandler:
349         case StartShellHandler:
350             Info.hDesktop = pSession->ApplicationDesktop;
351             break;
352 
353         case StartScreenSaverHandler:
354             Info.hDesktop = pSession->ApplicationDesktop;
355             break;
356 
357         default:
358             Info.hDesktop = pSession->WinlogonDesktop;
359             break;
360     }
361 
362     Info.pStatusCallback = NULL;
363 
364     ListEntry = NotificationDllListHead.Flink;
365     while (ListEntry != &NotificationDllListHead)
366     {
367 TRACE("ListEntry %p\n", ListEntry);
368 
369         NotificationDll = CONTAINING_RECORD(ListEntry,
370                                             NOTIFICATION_ITEM,
371                                             ListEntry);
372 TRACE("NotificationDll: %p\n", NotificationDll);
373         if (NotificationDll != NULL && NotificationDll->bEnabled)
374             CallNotificationDll(hNotifyKey, NotificationDll, Type, &Info);
375 
376         ListEntry = ListEntry->Flink;
377     }
378 
379     RegCloseKey(hNotifyKey);
380 }
381 
382 
383 VOID
384 CleanupNotifications(VOID)
385 {
386     PLIST_ENTRY ListEntry;
387     PNOTIFICATION_ITEM NotificationDll;
388 
389     ListEntry = NotificationDllListHead.Flink;
390     while (ListEntry != &NotificationDllListHead)
391     {
392         NotificationDll = CONTAINING_RECORD(ListEntry,
393                                             NOTIFICATION_ITEM,
394                                             ListEntry);
395         if (NotificationDll != NULL)
396         {
397             if (NotificationDll->pszKeyName != NULL)
398                 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
399 
400             if (NotificationDll->pszDllName != NULL)
401                 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
402         }
403 
404         ListEntry = ListEntry->Flink;
405 
406         RemoveEntryList(&NotificationDll->ListEntry);
407 
408         RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
409     }
410 }
411 
412 /* EOF */
413