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 BOOL bSfcNotification;
47 } NOTIFICATION_ITEM, *PNOTIFICATION_ITEM;
48
49
50 static LIST_ENTRY NotificationDllListHead;
51
52
53 /* FUNCTIONS *****************************************************************/
54
55 static
56 VOID
AddSfcNotification(VOID)57 AddSfcNotification(VOID)
58 {
59 WCHAR szSfcFileName[MAX_PATH];
60 PNOTIFICATION_ITEM NotificationDll;
61 DWORD dwError = ERROR_SUCCESS;
62
63 ExpandEnvironmentStringsW(L"%windir%\\system32\\sfc.dll",
64 szSfcFileName,
65 ARRAYSIZE(szSfcFileName));
66
67 NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
68 HEAP_ZERO_MEMORY,
69 sizeof(NOTIFICATION_ITEM));
70 if (NotificationDll == NULL)
71 {
72 dwError = ERROR_OUTOFMEMORY;
73 goto done;
74 }
75
76 NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(),
77 HEAP_ZERO_MEMORY,
78 (wcslen(szSfcFileName) + 1) * sizeof(WCHAR));
79 if (NotificationDll->pszDllName == NULL)
80 {
81 dwError = ERROR_OUTOFMEMORY;
82 goto done;
83 }
84
85 wcscpy(NotificationDll->pszDllName, szSfcFileName);
86
87 NotificationDll->bEnabled = TRUE;
88 NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
89 NotificationDll->bSfcNotification = TRUE;
90
91 InsertHeadList(&NotificationDllListHead,
92 &NotificationDll->ListEntry);
93
94 done:
95 if (dwError != ERROR_SUCCESS)
96 {
97 if (NotificationDll != NULL)
98 {
99 if (NotificationDll->pszDllName != NULL)
100 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
101
102 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
103 }
104 }
105 }
106
107 static
108 VOID
AddNotificationDll(HKEY hNotifyKey,PWSTR pszKeyName)109 AddNotificationDll(
110 HKEY hNotifyKey,
111 PWSTR pszKeyName)
112 {
113 HKEY hDllKey = NULL;
114 PNOTIFICATION_ITEM NotificationDll = NULL;
115 DWORD dwSize, dwType;
116 DWORD dwError;
117
118 TRACE("AddNotificationDll(%p %S)\n", hNotifyKey, pszKeyName);
119
120 dwError = RegOpenKeyExW(hNotifyKey,
121 pszKeyName,
122 0,
123 KEY_READ,
124 &hDllKey);
125 if (dwError != ERROR_SUCCESS)
126 return;
127
128 NotificationDll = RtlAllocateHeap(RtlGetProcessHeap(),
129 HEAP_ZERO_MEMORY,
130 sizeof(NOTIFICATION_ITEM));
131 if (NotificationDll == NULL)
132 {
133 dwError = ERROR_OUTOFMEMORY;
134 goto done;
135 }
136
137 NotificationDll->pszKeyName = RtlAllocateHeap(RtlGetProcessHeap(),
138 HEAP_ZERO_MEMORY,
139 (wcslen(pszKeyName) + 1) * sizeof(WCHAR));
140 if (NotificationDll->pszKeyName == NULL)
141 {
142 dwError = ERROR_OUTOFMEMORY;
143 goto done;
144 }
145
146 wcscpy(NotificationDll->pszKeyName, pszKeyName);
147
148 dwSize = 0;
149 RegQueryValueExW(hDllKey,
150 L"DllName",
151 NULL,
152 &dwType,
153 NULL,
154 &dwSize);
155 if (dwSize == 0)
156 {
157 dwError = ERROR_FILE_NOT_FOUND;
158 goto done;
159 }
160
161 NotificationDll->pszDllName = RtlAllocateHeap(RtlGetProcessHeap(),
162 HEAP_ZERO_MEMORY,
163 dwSize);
164 if (NotificationDll->pszDllName == NULL)
165 {
166 dwError = ERROR_OUTOFMEMORY;
167 goto done;
168 }
169
170 dwError = RegQueryValueExW(hDllKey,
171 L"DllName",
172 NULL,
173 &dwType,
174 (PBYTE)NotificationDll->pszDllName,
175 &dwSize);
176 if (dwError != ERROR_SUCCESS)
177 goto done;
178
179 NotificationDll->bEnabled = TRUE;
180 NotificationDll->dwMaxWait = 30; /* FIXME: ??? */
181
182 dwSize = sizeof(BOOL);
183 RegQueryValueExW(hDllKey,
184 L"Asynchronous",
185 NULL,
186 &dwType,
187 (PBYTE)&NotificationDll->bAsynchronous,
188 &dwSize);
189
190 dwSize = sizeof(BOOL);
191 RegQueryValueExW(hDllKey,
192 L"Enabled",
193 NULL,
194 &dwType,
195 (PBYTE)&NotificationDll->bEnabled,
196 &dwSize);
197
198 dwSize = sizeof(BOOL);
199 RegQueryValueExW(hDllKey,
200 L"Impersonate",
201 NULL,
202 &dwType,
203 (PBYTE)&NotificationDll->bImpersonate,
204 &dwSize);
205
206 dwSize = sizeof(BOOL);
207 RegQueryValueExW(hDllKey,
208 L"Safe",
209 NULL,
210 &dwType,
211 (PBYTE)&NotificationDll->bSafe,
212 &dwSize);
213
214 dwSize = sizeof(BOOL);
215 RegQueryValueExW(hDllKey,
216 L"SmartCardLogonNotify",
217 NULL,
218 &dwType,
219 (PBYTE)&NotificationDll->bSmartCardLogon,
220 &dwSize);
221
222 dwSize = sizeof(DWORD);
223 RegQueryValueExW(hDllKey,
224 L"MaxWait",
225 NULL,
226 &dwType,
227 (PBYTE)&NotificationDll->dwMaxWait,
228 &dwSize);
229
230 InsertHeadList(&NotificationDllListHead,
231 &NotificationDll->ListEntry);
232
233 done:
234 if (dwError != ERROR_SUCCESS)
235 {
236 if (NotificationDll != NULL)
237 {
238 if (NotificationDll->pszKeyName != NULL)
239 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
240
241 if (NotificationDll->pszDllName != NULL)
242 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
243
244 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
245 }
246 }
247
248 RegCloseKey(hDllKey);
249 }
250
251
252 BOOL
InitNotifications(VOID)253 InitNotifications(VOID)
254 {
255 HKEY hNotifyKey = NULL;
256 LONG lError;
257 DWORD dwIndex;
258 WCHAR szKeyName[80];
259 DWORD dwKeyName;
260
261 TRACE("InitNotifications()\n");
262
263 InitializeListHead(&NotificationDllListHead);
264
265 AddSfcNotification();
266
267 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
268 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
269 0,
270 KEY_READ | KEY_ENUMERATE_SUB_KEYS,
271 &hNotifyKey);
272 if (lError != ERROR_SUCCESS)
273 {
274 TRACE("RegOpenKeyExW()\n");
275 return TRUE;
276 }
277
278 dwIndex = 0;
279 for(;;)
280 {
281 dwKeyName = ARRAYSIZE(szKeyName);
282 lError = RegEnumKeyExW(hNotifyKey,
283 dwIndex,
284 szKeyName,
285 &dwKeyName,
286 NULL,
287 NULL,
288 NULL,
289 NULL);
290 if (lError != ERROR_SUCCESS)
291 break;
292
293 TRACE("Notification DLL: %S\n", szKeyName);
294 AddNotificationDll(hNotifyKey, szKeyName);
295
296 dwIndex++;
297 }
298
299 RegCloseKey(hNotifyKey);
300
301 TRACE("InitNotifications() done\n");
302
303 return TRUE;
304 }
305
306
307 static
308 VOID
CallNotificationDll(HKEY hNotifyKey,PNOTIFICATION_ITEM NotificationDll,NOTIFICATION_TYPE Type,PWLX_NOTIFICATION_INFO pInfo)309 CallNotificationDll(
310 HKEY hNotifyKey,
311 PNOTIFICATION_ITEM NotificationDll,
312 NOTIFICATION_TYPE Type,
313 PWLX_NOTIFICATION_INFO pInfo)
314 {
315 HMODULE hModule;
316 CHAR szFuncBuffer[128];
317 DWORD dwError = ERROR_SUCCESS;
318 PWLX_NOTIFY_HANDLER pNotifyHandler;
319
320 if (NotificationDll->bSfcNotification)
321 {
322 switch (Type)
323 {
324 case LogonHandler:
325 strcpy(szFuncBuffer, "SfcWLEventLogon");
326 break;
327
328 case LogoffHandler:
329 strcpy(szFuncBuffer, "SfcWLEventLogoff");
330 break;
331
332 default:
333 return;
334 }
335 }
336 else
337 {
338 HKEY hDllKey;
339 DWORD dwSize;
340 DWORD dwType;
341
342 dwError = RegOpenKeyExW(hNotifyKey,
343 NotificationDll->pszKeyName,
344 0,
345 KEY_READ,
346 &hDllKey);
347 if (dwError != ERROR_SUCCESS)
348 {
349 TRACE("RegOpenKeyExW()\n");
350 return;
351 }
352
353 dwSize = sizeof(szFuncBuffer);
354 dwError = RegQueryValueExA(hDllKey,
355 FuncNames[Type],
356 NULL,
357 &dwType,
358 (PBYTE)szFuncBuffer,
359 &dwSize);
360
361 RegCloseKey(hDllKey);
362 }
363
364 if (dwError != ERROR_SUCCESS)
365 return;
366
367 hModule = LoadLibraryW(NotificationDll->pszDllName);
368 if (!hModule)
369 return;
370
371 pNotifyHandler = (PWLX_NOTIFY_HANDLER)GetProcAddress(hModule, szFuncBuffer);
372
373 _SEH2_TRY
374 {
375 if (pNotifyHandler)
376 pNotifyHandler(pInfo);
377 }
378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
379 {
380 ERR("WL: Exception while running notification %S!%s, Status 0x%08lx\n",
381 NotificationDll->pszDllName, szFuncBuffer, _SEH2_GetExceptionCode());
382 }
383 _SEH2_END;
384
385 FreeLibrary(hModule);
386 }
387
388
389 VOID
CallNotificationDlls(PWLSESSION pSession,NOTIFICATION_TYPE Type)390 CallNotificationDlls(
391 PWLSESSION pSession,
392 NOTIFICATION_TYPE Type)
393 {
394 PLIST_ENTRY ListEntry;
395 PNOTIFICATION_ITEM NotificationDll;
396 WLX_NOTIFICATION_INFO Info;
397 HKEY hNotifyKey = NULL;
398 DWORD dwError;
399
400 TRACE("CallNotificationDlls()\n");
401
402 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
403 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify",
404 0,
405 KEY_READ | KEY_ENUMERATE_SUB_KEYS,
406 &hNotifyKey);
407 if (dwError != ERROR_SUCCESS)
408 {
409 TRACE("RegOpenKeyExW()\n");
410 return;
411 }
412
413 Info.Size = sizeof(WLX_NOTIFICATION_INFO);
414
415 switch (Type)
416 {
417 case LogoffHandler:
418 case ShutdownHandler:
419 Info.Flags = 3;
420 break;
421
422 default:
423 Info.Flags = 0;
424 break;
425 }
426
427 Info.UserName = NULL; //UserName;
428 Info.Domain = NULL; //Domain;
429 Info.WindowStation = pSession->InteractiveWindowStationName;
430 Info.hToken = pSession->UserToken;
431
432 switch (Type)
433 {
434 case LogonHandler:
435 case StartShellHandler:
436 Info.hDesktop = pSession->ApplicationDesktop;
437 break;
438
439 case StartScreenSaverHandler:
440 Info.hDesktop = pSession->ApplicationDesktop;
441 break;
442
443 default:
444 Info.hDesktop = pSession->WinlogonDesktop;
445 break;
446 }
447
448 Info.pStatusCallback = NULL;
449
450 ListEntry = NotificationDllListHead.Flink;
451 while (ListEntry != &NotificationDllListHead)
452 {
453 TRACE("ListEntry %p\n", ListEntry);
454
455 NotificationDll = CONTAINING_RECORD(ListEntry,
456 NOTIFICATION_ITEM,
457 ListEntry);
458 TRACE("NotificationDll: %p\n", NotificationDll);
459 if (NotificationDll != NULL && NotificationDll->bEnabled)
460 CallNotificationDll(hNotifyKey, NotificationDll, Type, &Info);
461
462 ListEntry = ListEntry->Flink;
463 }
464
465 RegCloseKey(hNotifyKey);
466 }
467
468
469 VOID
CleanupNotifications(VOID)470 CleanupNotifications(VOID)
471 {
472 PLIST_ENTRY ListEntry;
473 PNOTIFICATION_ITEM NotificationDll;
474
475 ListEntry = NotificationDllListHead.Flink;
476 while (ListEntry != &NotificationDllListHead)
477 {
478 NotificationDll = CONTAINING_RECORD(ListEntry,
479 NOTIFICATION_ITEM,
480 ListEntry);
481 if (NotificationDll != NULL)
482 {
483 if (NotificationDll->pszKeyName != NULL)
484 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName);
485
486 if (NotificationDll->pszDllName != NULL)
487 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName);
488 }
489
490 ListEntry = ListEntry->Flink;
491
492 RemoveEntryList(&NotificationDll->ListEntry);
493
494 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll);
495 }
496 }
497
498 /* EOF */
499