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