[WINLOGON] Load the notification dlls on demand
[reactos.git] / base / system / winlogon / notify.c
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 */