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 = 80 * sizeof(WCHAR); 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 HKEY hDllKey = NULL; 316 HMODULE hModule = NULL; 317 CHAR szFuncBuffer[128]; 318 DWORD dwSize; 319 DWORD dwType; 320 DWORD dwError = ERROR_SUCCESS; 321 PWLX_NOTIFY_HANDLER pNotifyHandler; 322 323 if (NotificationDll->bSfcNotification) 324 { 325 switch (Type) 326 { 327 case LogonHandler: 328 strcpy(szFuncBuffer, "SfcWLEventLogon"); 329 break; 330 331 case LogoffHandler: 332 strcpy(szFuncBuffer, "SfcWLEventLogoff"); 333 break; 334 335 default: 336 return; 337 } 338 } 339 else 340 { 341 dwError = RegOpenKeyExW(hNotifyKey, 342 NotificationDll->pszKeyName, 343 0, 344 KEY_READ, 345 &hDllKey); 346 if (dwError != ERROR_SUCCESS) 347 { 348 TRACE("RegOpenKeyExW()\n"); 349 return; 350 } 351 352 dwSize = sizeof(szFuncBuffer); 353 dwError = RegQueryValueExA(hDllKey, 354 FuncNames[Type], 355 NULL, 356 &dwType, 357 (PBYTE)szFuncBuffer, 358 &dwSize); 359 } 360 361 if (dwError == ERROR_SUCCESS) 362 { 363 hModule = LoadLibraryW(NotificationDll->pszDllName); 364 if (hModule != NULL) 365 { 366 pNotifyHandler = (PWLX_NOTIFY_HANDLER)GetProcAddress(hModule, szFuncBuffer); 367 if (pNotifyHandler != NULL) 368 pNotifyHandler(pInfo); 369 370 FreeLibrary(hModule); 371 } 372 } 373 374 if (hDllKey != NULL) 375 RegCloseKey(hDllKey); 376 } 377 378 379 VOID 380 CallNotificationDlls( 381 PWLSESSION pSession, 382 NOTIFICATION_TYPE Type) 383 { 384 PLIST_ENTRY ListEntry; 385 PNOTIFICATION_ITEM NotificationDll; 386 WLX_NOTIFICATION_INFO Info; 387 HKEY hNotifyKey = NULL; 388 DWORD dwError; 389 390 TRACE("CallNotificationDlls()\n"); 391 392 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 393 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify", 394 0, 395 KEY_READ | KEY_ENUMERATE_SUB_KEYS, 396 &hNotifyKey); 397 if (dwError != ERROR_SUCCESS) 398 { 399 TRACE("RegOpenKeyExW()\n"); 400 return; 401 } 402 403 Info.Size = sizeof(WLX_NOTIFICATION_INFO); 404 405 switch (Type) 406 { 407 case LogoffHandler: 408 case ShutdownHandler: 409 Info.Flags = 3; 410 break; 411 412 default: 413 Info.Flags = 0; 414 break; 415 } 416 417 Info.UserName = NULL; //UserName; 418 Info.Domain = NULL; //Domain; 419 Info.WindowStation = pSession->InteractiveWindowStationName; 420 Info.hToken = pSession->UserToken; 421 422 switch (Type) 423 { 424 case LogonHandler: 425 case StartShellHandler: 426 Info.hDesktop = pSession->ApplicationDesktop; 427 break; 428 429 case StartScreenSaverHandler: 430 Info.hDesktop = pSession->ApplicationDesktop; 431 break; 432 433 default: 434 Info.hDesktop = pSession->WinlogonDesktop; 435 break; 436 } 437 438 Info.pStatusCallback = NULL; 439 440 ListEntry = NotificationDllListHead.Flink; 441 while (ListEntry != &NotificationDllListHead) 442 { 443 TRACE("ListEntry %p\n", ListEntry); 444 445 NotificationDll = CONTAINING_RECORD(ListEntry, 446 NOTIFICATION_ITEM, 447 ListEntry); 448 TRACE("NotificationDll: %p\n", NotificationDll); 449 if (NotificationDll != NULL && NotificationDll->bEnabled) 450 CallNotificationDll(hNotifyKey, NotificationDll, Type, &Info); 451 452 ListEntry = ListEntry->Flink; 453 } 454 455 RegCloseKey(hNotifyKey); 456 } 457 458 459 VOID 460 CleanupNotifications(VOID) 461 { 462 PLIST_ENTRY ListEntry; 463 PNOTIFICATION_ITEM NotificationDll; 464 465 ListEntry = NotificationDllListHead.Flink; 466 while (ListEntry != &NotificationDllListHead) 467 { 468 NotificationDll = CONTAINING_RECORD(ListEntry, 469 NOTIFICATION_ITEM, 470 ListEntry); 471 if (NotificationDll != NULL) 472 { 473 if (NotificationDll->pszKeyName != NULL) 474 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszKeyName); 475 476 if (NotificationDll->pszDllName != NULL) 477 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll->pszDllName); 478 } 479 480 ListEntry = ListEntry->Flink; 481 482 RemoveEntryList(&NotificationDll->ListEntry); 483 484 RtlFreeHeap(RtlGetProcessHeap(), 0, NotificationDll); 485 } 486 } 487 488 /* EOF */ 489