xref: /reactos/base/system/winlogon/notify.c (revision c2c66aff)
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 
39     HINSTANCE hInstance;
40     BOOL bEnabled;
41     BOOL bAsynchronous;
42     BOOL bSafe;
43     BOOL bImpersonate;
44     BOOL bSmartCardLogon;
45     DWORD dwMaxWait;
46     PWLX_NOTIFY_HANDLER Handler[LastHandler];
47 } NOTIFICATION_ITEM, *PNOTIFICATION_ITEM;
48 
49 
50 static LIST_ENTRY NotificationDllListHead;
51 
52 
53 /* FUNCTIONS *****************************************************************/
54 
55 PWLX_NOTIFY_HANDLER
56 GetNotificationHandler(
57     HKEY hDllKey,
58     HINSTANCE hInstance,
59     PSTR pNotification)
60 {
61     CHAR szFuncBuffer[128];
62     DWORD dwSize;
63     DWORD dwType;
64     LONG lError;
65 
66     dwSize = 128;
67     lError = RegQueryValueExA(hDllKey,
68                               pNotification,
69                               NULL,
70                               &dwType,
71                               (PBYTE)szFuncBuffer,
72                               &dwSize);
73     if (lError == ERROR_SUCCESS)
74     {
75         return (PWLX_NOTIFY_HANDLER)GetProcAddress(hInstance, szFuncBuffer);
76     }
77 
78     return NULL;
79 }
80 
81 
82 static
83 VOID
84 LoadNotificationDll(
85     HKEY hNotifyKey,
86     PWSTR pKeyName)
87 {
88     HKEY hDllKey = NULL;
89     PNOTIFICATION_ITEM NotificationDll = NULL;
90     LONG lError;
91     WCHAR szBuffer[80];
92     DWORD dwSize;
93     DWORD dwType;
94     HINSTANCE hInstance;
95     NOTIFICATION_TYPE i;
96 
97     TRACE("LoadNotificationDll(%p %S)\n", hNotifyKey, pKeyName);
98 
99     lError = RegOpenKeyExW(hNotifyKey,
100                            pKeyName,
101                            0,
102                            KEY_READ,
103                            &hDllKey);
104     if (lError != ERROR_SUCCESS)
105         return;
106 
107     dwSize = 80 * sizeof(WCHAR);
108     lError = RegQueryValueExW(hDllKey,
109                               L"DllName",
110                               NULL,
111                               &dwType,
112                               (PBYTE)szBuffer,
113                               &dwSize);
114     if (lError == ERROR_SUCCESS)
115     {
116         hInstance = LoadLibraryW(szBuffer);
117         if (hInstance == NULL)
118             return;
119 
120         NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
121                                           HEAP_ZERO_MEMORY,
122                                           sizeof(NOTIFICATION_ITEM));
123         if (NotificationDll == NULL)
124         {
125             FreeLibrary(hInstance);
126             return;
127         }
128 
129         NotificationDll->bEnabled = TRUE;
130         NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
131         NotificationDll->hInstance = hInstance;
132 
133         dwSize = sizeof(BOOL);
134         RegQueryValueExW(hDllKey,
135                          L"Asynchronous",
136                          NULL,
137                          &dwType,
138                          (PBYTE)&NotificationDll->bAsynchronous,
139                          &dwSize);
140 
141         dwSize = sizeof(BOOL);
142         RegQueryValueExW(hDllKey,
143                          L"Enabled",
144                          NULL,
145                          &dwType,
146                          (PBYTE)&NotificationDll->bEnabled,
147                          &dwSize);
148 
149         dwSize = sizeof(BOOL);
150         RegQueryValueExW(hDllKey,
151                          L"Impersonate",
152                          NULL,
153                          &dwType,
154                          (PBYTE)&NotificationDll->bImpersonate,
155                          &dwSize);
156 
157         dwSize = sizeof(BOOL);
158         RegQueryValueExW(hDllKey,
159                          L"Safe",
160                          NULL,
161                          &dwType,
162                          (PBYTE)&NotificationDll->bSafe,
163                          &dwSize);
164 
165         dwSize = sizeof(BOOL);
166         RegQueryValueExW(hDllKey,
167                          L"SmartCardLogonNotify",
168                          NULL,
169                          &dwType,
170                          (PBYTE)&NotificationDll->bSmartCardLogon,
171                          &dwSize);
172 
173         dwSize = sizeof(DWORD);
174         RegQueryValueExW(hDllKey,
175                          L"MaxWait",
176                          NULL,
177                          &dwType,
178                          (PBYTE)&NotificationDll->dwMaxWait,
179                          &dwSize);
180 
181         for (i = LogonHandler; i < LastHandler; i++)
182         {
183             NotificationDll->Handler[i] = GetNotificationHandler(hDllKey, hInstance, FuncNames[i]);
184             TRACE("%s: %p\n", FuncNames[i], NotificationDll->Handler[i]);
185         }
186 
187         InsertHeadList(&NotificationDllListHead,
188                        &NotificationDll->ListEntry);
189     }
190 
191     RegCloseKey(hDllKey);
192 }
193 
194 
195 BOOL
196 InitNotifications(VOID)
197 {
198     HKEY hNotifyKey = NULL;
199     LONG lError;
200     DWORD dwIndex;
201     WCHAR szKeyName[80];
202     DWORD dwKeyName;
203 
204     TRACE("InitNotifications()\n");
205 
206     InitializeListHead(&NotificationDllListHead);
207 
208     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
209                            L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
210                            0,
211                            KEY_READ | KEY_ENUMERATE_SUB_KEYS,
212                            &hNotifyKey);
213     if (lError != ERROR_SUCCESS)
214     {
215         TRACE("RegOpenKeyExW()\n");
216         return TRUE;
217     }
218 
219     dwIndex = 0;
220     for(;;)
221     {
222         dwKeyName = 80 * sizeof(WCHAR);
223         lError = RegEnumKeyExW(hNotifyKey,
224                                dwIndex,
225                                szKeyName,
226                                &dwKeyName,
227                                NULL,
228                                NULL,
229                                NULL,
230                                NULL);
231         if (lError != ERROR_SUCCESS)
232             break;
233 
234         TRACE("Notification DLL: %S\n", szKeyName);
235         LoadNotificationDll(hNotifyKey, szKeyName);
236 
237         dwIndex++;
238     }
239 
240     RegCloseKey(hNotifyKey);
241 
242     TRACE("InitNotifications() done\n");
243 
244     return TRUE;
245 }
246 
247 
248 VOID
249 CallNotificationDlls(
250     PWLSESSION pSession,
251     NOTIFICATION_TYPE Type)
252 {
253     PLIST_ENTRY ListEntry;
254     PNOTIFICATION_ITEM NotificationDll;
255     WLX_NOTIFICATION_INFO Info;
256 
257     TRACE("CallNotificationDlls()\n");
258 
259     Info.Size = sizeof(WLX_NOTIFICATION_INFO);
260 
261     switch (Type)
262     {
263         case LogoffHandler:
264         case ShutdownHandler:
265             Info.Flags = 3;
266             break;
267 
268         default:
269             Info.Flags = 0;
270             break;
271     }
272 
273     Info.UserName = NULL; //UserName;
274     Info.Domain = NULL; //Domain;
275     Info.WindowStation = pSession->InteractiveWindowStationName;
276     Info.hToken = pSession->UserToken;
277 
278     switch (Type)
279     {
280         case LogonHandler:
281         case StartShellHandler:
282             Info.hDesktop = pSession->ApplicationDesktop;
283             break;
284 
285         case StartScreenSaverHandler:
286             Info.hDesktop = pSession->ApplicationDesktop;
287             break;
288 
289         default:
290             Info.hDesktop = pSession->WinlogonDesktop;
291             break;
292     }
293 
294     Info.pStatusCallback = NULL;
295 
296     ListEntry = NotificationDllListHead.Flink;
297     while (ListEntry != &NotificationDllListHead)
298     {
299 TRACE("ListEntry %p\n", ListEntry);
300 
301         NotificationDll = CONTAINING_RECORD(ListEntry,
302                                             NOTIFICATION_ITEM,
303                                             ListEntry);
304 TRACE("NotificationDll: %p\n", NotificationDll);
305         if (NotificationDll != NULL && NotificationDll->bEnabled)
306         {
307 TRACE("NotificationDll->Handler: %p\n", NotificationDll->Handler[Type]);
308             if (NotificationDll->Handler[Type] != NULL)
309                 NotificationDll->Handler[Type](&Info);
310         }
311 
312         ListEntry = ListEntry->Flink;
313     }
314 }
315 
316 
317 VOID
318 CleanupNotifications(VOID)
319 {
320     PLIST_ENTRY ListEntry;
321     PNOTIFICATION_ITEM NotificationDll;
322 
323     ListEntry = NotificationDllListHead.Flink;
324     while (ListEntry != &NotificationDllListHead)
325     {
326         NotificationDll = CONTAINING_RECORD(ListEntry,
327                                             NOTIFICATION_ITEM,
328                                             ListEntry);
329         if (NotificationDll != NULL)
330         {
331             FreeLibrary(NotificationDll->hInstance);
332         }
333 
334         ListEntry = ListEntry->Flink;
335 
336         RemoveEntryList(&NotificationDll->ListEntry);
337 
338         RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
339     }
340 }
341 
342 /* EOF */
343