6c20e0f613b75a4c29b18ec9bd96b19171596bd0
[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
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 */