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 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 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 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 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 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 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