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 */ 343