1 /* 2 * ReactOS kernel 3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 /* 20 * 21 * PROJECT: ReactOS user32.dll 22 * FILE: win32ss/user/user32/windows/hook.c 23 * PURPOSE: Hooks 24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 25 * UPDATE HISTORY: 26 * 09-05-2001 CSH Created 27 */ 28 29 #include <user32.h> 30 31 WINE_DEFAULT_DEBUG_CHANNEL(user32); 32 33 typedef struct _NOTIFYEVENT 34 { 35 DWORD event; 36 LONG idObject; 37 LONG idChild; 38 DWORD flags; 39 } NOTIFYEVENT, *PNOTIFYEVENT; 40 41 /* PRIVATE FUNCTIONS *********************************************************/ 42 43 static 44 DWORD 45 FASTCALL 46 GetMaskFromEvent(DWORD Event) 47 { 48 DWORD Ret = 0; 49 50 if ( Event > EVENT_OBJECT_STATECHANGE ) 51 { 52 if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE; 53 if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE; 54 if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE; 55 return SRV_EVENT_CREATE; 56 } 57 58 if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE; 59 60 Ret = SRV_EVENT_RUNNING; 61 62 if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE; 63 64 if ( Event <= EVENT_SYSTEM_MENUPOPUPEND ) 65 { 66 Ret = SRV_EVENT_MENU; 67 } 68 else 69 { 70 if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE; 71 if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION; 72 if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE; 73 } 74 return Ret; 75 } 76 77 static 78 HHOOK 79 FASTCALL 80 IntSetWindowsHook( 81 int idHook, 82 HOOKPROC lpfn, 83 HINSTANCE hMod, 84 DWORD dwThreadId, 85 BOOL bAnsi) 86 { 87 WCHAR ModuleName[MAX_PATH]; 88 UNICODE_STRING USModuleName; 89 90 if (NULL != hMod) 91 { 92 if (0 == GetModuleFileNameW(hMod, ModuleName, MAX_PATH)) 93 { 94 return NULL; 95 } 96 RtlInitUnicodeString(&USModuleName, ModuleName); 97 } 98 else 99 { 100 RtlInitUnicodeString(&USModuleName, NULL); 101 } 102 103 return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi); 104 } 105 106 /* 107 Since ReactOS uses User32 as the main message source this was needed. 108 Base on the funny rules from the wine tests it left it with this option. 109 8^( 110 */ 111 VOID 112 FASTCALL 113 IntNotifyWinEvent( 114 DWORD event, 115 HWND hwnd, 116 LONG idObject, 117 LONG idChild, 118 DWORD flags 119 ) 120 { 121 NOTIFYEVENT ne; 122 ne.event = event; 123 ne.idObject = idObject; 124 ne.idChild = idChild; 125 ne.flags = flags; 126 if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) 127 NtUserxNotifyWinEvent(hwnd, &ne); 128 } 129 130 /* FUNCTIONS *****************************************************************/ 131 132 #if 0 133 BOOL 134 WINAPI 135 CallMsgFilter( 136 LPMSG lpMsg, 137 int nCode) 138 { 139 UNIMPLEMENTED; 140 return FALSE; 141 } 142 #endif 143 144 /* 145 * @implemented 146 */ 147 BOOL 148 WINAPI 149 CallMsgFilterA( 150 LPMSG lpMsg, 151 int nCode) 152 { 153 MSG Msg; 154 if ( NtCurrentTeb()->Win32ThreadInfo && 155 (ISITHOOKED(WH_MSGFILTER) || ISITHOOKED(WH_SYSMSGFILTER)) ) 156 { 157 if ( lpMsg->message & ~WM_MAXIMUM ) 158 { 159 SetLastError(ERROR_INVALID_PARAMETER); 160 return FALSE; 161 } 162 RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); 163 return NtUserCallMsgFilter( &Msg, nCode); 164 } 165 return FALSE; 166 } 167 168 169 /* 170 * @implemented 171 */ 172 BOOL 173 WINAPI 174 CallMsgFilterW( 175 LPMSG lpMsg, 176 int nCode) 177 { 178 MSG Msg; 179 if ( NtCurrentTeb()->Win32ThreadInfo && 180 (ISITHOOKED(WH_MSGFILTER) || ISITHOOKED(WH_SYSMSGFILTER)) ) 181 { 182 if ( lpMsg->message & ~WM_MAXIMUM ) 183 { 184 SetLastError(ERROR_INVALID_PARAMETER); 185 return FALSE; 186 } 187 RtlCopyMemory(&Msg, lpMsg, sizeof(MSG)); 188 return NtUserCallMsgFilter( &Msg, nCode); 189 } 190 return FALSE; 191 } 192 193 194 /* 195 * @implemented 196 */ 197 LRESULT 198 WINAPI 199 CallNextHookEx( 200 HHOOK Hook, // Windows NT/XP/2003: Ignored. 201 int Code, 202 WPARAM wParam, 203 LPARAM lParam) 204 { 205 PCLIENTINFO ClientInfo; 206 DWORD Flags, Save; 207 PHOOK pHook, phkNext; 208 LRESULT lResult = 0; 209 210 ClientInfo = GetWin32ClientInfo(); 211 212 if (!ClientInfo->phkCurrent) return 0; 213 214 pHook = DesktopPtrToUser(ClientInfo->phkCurrent); 215 216 if (!pHook->phkNext) return 0; // Nothing to do.... 217 218 phkNext = DesktopPtrToUser(pHook->phkNext); 219 220 if ( phkNext->HookId == WH_CALLWNDPROC || 221 phkNext->HookId == WH_CALLWNDPROCRET) 222 { 223 Save = ClientInfo->dwHookData; 224 Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK; 225 // wParam: If the message was sent by the current thread/process, it is 226 // nonzero; otherwise, it is zero. 227 if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK; 228 else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK; 229 230 if (phkNext->HookId == WH_CALLWNDPROC) 231 { 232 PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam; 233 234 NtUserMessageCall( pCWP->hwnd, 235 pCWP->message, 236 pCWP->wParam, 237 pCWP->lParam, 238 (ULONG_PTR)&lResult, 239 FNID_CALLWNDPROC, 240 phkNext->Ansi); 241 } 242 else 243 { 244 PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam; 245 246 ClientInfo->dwHookData = pCWPR->lResult; 247 248 NtUserMessageCall( pCWPR->hwnd, 249 pCWPR->message, 250 pCWPR->wParam, 251 pCWPR->lParam, 252 (ULONG_PTR)&lResult, 253 FNID_CALLWNDPROCRET, 254 phkNext->Ansi); 255 } 256 ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK); 257 ClientInfo->dwHookData = Save; 258 } 259 else 260 lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi); 261 262 return lResult; 263 } 264 265 266 /* 267 * @implemented 268 */ 269 HHOOK 270 WINAPI 271 SetWindowsHookW(int idHook, HOOKPROC lpfn) 272 { 273 DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread); 274 return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE); 275 // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE); 276 } 277 278 /* 279 * @implemented 280 */ 281 HHOOK 282 WINAPI 283 SetWindowsHookA(int idHook, HOOKPROC lpfn) 284 { 285 DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread); 286 return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE); 287 // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE); 288 } 289 290 /* 291 * @unimplemented 292 */ 293 BOOL 294 WINAPI 295 DeregisterShellHookWindow(HWND hWnd) 296 { 297 return NtUserxDeregisterShellHookWindow(hWnd); 298 } 299 300 /* 301 * @unimplemented 302 */ 303 BOOL 304 WINAPI 305 RegisterShellHookWindow(HWND hWnd) 306 { 307 return NtUserxRegisterShellHookWindow(hWnd); 308 } 309 310 /* 311 * @implemented 312 */ 313 BOOL 314 WINAPI 315 UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc ) 316 { 317 return NtUserxUnhookWindowsHook(nCode, pfnFilterProc); 318 } 319 320 /* 321 * @implemented 322 */ 323 VOID 324 WINAPI 325 NotifyWinEvent( 326 DWORD event, 327 HWND hwnd, 328 LONG idObject, 329 LONG idChild 330 ) 331 { 332 // "Servers call NotifyWinEvent to announce the event to the system after the 333 // event has occurred; they must never notify the system of an event before 334 // the event has occurred." msdn on NotifyWinEvent. 335 if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) // Check to see. 336 NtUserNotifyWinEvent(event, hwnd, idObject, idChild); 337 } 338 339 /* 340 * @implemented 341 */ 342 HWINEVENTHOOK 343 WINAPI 344 SetWinEventHook( 345 UINT eventMin, 346 UINT eventMax, 347 HMODULE hmodWinEventProc, 348 WINEVENTPROC pfnWinEventProc, 349 DWORD idProcess, 350 DWORD idThread, 351 UINT dwFlags 352 ) 353 { 354 WCHAR ModuleName[MAX_PATH]; 355 UNICODE_STRING USModuleName; 356 PUNICODE_STRING pusmodName; 357 358 RtlInitUnicodeString(&USModuleName, NULL); 359 360 if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT)) 361 { 362 if (0 == GetModuleFileNameW(hmodWinEventProc, ModuleName, MAX_PATH)) 363 { 364 return NULL; 365 } 366 RtlInitUnicodeString(&USModuleName, ModuleName); 367 pusmodName = &USModuleName; 368 } 369 else 370 { 371 pusmodName = NULL; 372 } 373 374 return NtUserSetWinEventHook(eventMin, 375 eventMax, 376 hmodWinEventProc, 377 pusmodName, 378 pfnWinEventProc, 379 idProcess, 380 idThread, 381 dwFlags); 382 } 383 384 /* 385 * @implemented 386 */ 387 BOOL 388 WINAPI 389 IsWinEventHookInstalled( 390 DWORD event) 391 { 392 if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo) 393 { 394 return (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) != 0; 395 } 396 return FALSE; 397 } 398 399 /* 400 * @implemented 401 */ 402 HHOOK 403 WINAPI 404 SetWindowsHookExA( 405 int idHook, 406 HOOKPROC lpfn, 407 HINSTANCE hMod, 408 DWORD dwThreadId) 409 { 410 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE); 411 } 412 413 414 /* 415 * @implemented 416 */ 417 HHOOK 418 WINAPI 419 SetWindowsHookExW( 420 int idHook, 421 HOOKPROC lpfn, 422 HINSTANCE hMod, 423 DWORD dwThreadId) 424 { 425 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE); 426 } 427 428 static 429 BOOL 430 ClientLoadLibrary( 431 PUNICODE_STRING pstrLibName, 432 PUNICODE_STRING pstrInitFunc, 433 BOOL bUnload, 434 BOOL bApiHook) 435 { 436 HINSTANCE hLibrary; 437 PVOID pInitFunction; 438 NTSTATUS Status; 439 ANSI_STRING InitFuncName; 440 BOOL bResult = FALSE; 441 442 TRACE("ClientLoadLibrary: pid: %d, strLibraryName: %S, " 443 "strInitFuncName: %S, bUnload: %d, bApiHook:%d\n", 444 GetCurrentProcessId(), 445 pstrLibName->Buffer, 446 pstrInitFunc->Buffer, 447 bUnload, 448 bApiHook); 449 450 /* Check if we have to load the module */ 451 if (bUnload == FALSE) 452 { 453 ASSERT(pstrLibName->Buffer != NULL); 454 455 /* Load it */ 456 hLibrary = LoadLibrary(pstrLibName->Buffer); 457 if (hLibrary == 0) 458 { 459 return FALSE; 460 } 461 462 if (!bApiHook) 463 { 464 /* There is nothing more to do for a global hook*/ 465 return TRUE; 466 } 467 468 /* Initialize the user api hook */ 469 ASSERT(pstrInitFunc->Buffer); 470 Status = RtlUnicodeStringToAnsiString(&InitFuncName, 471 pstrInitFunc, 472 TRUE); 473 if (!NT_SUCCESS(Status)) 474 { 475 FreeLibrary(hLibrary); 476 return FALSE; 477 } 478 479 /* Get the address of the initialization routine */ 480 pInitFunction = GetProcAddress(hLibrary, InitFuncName.Buffer); 481 if (pInitFunction) 482 { 483 /* Call the initialization routine */ 484 bResult = InitUserApiHook(hLibrary, (USERAPIHOOKPROC)pInitFunction); 485 } 486 487 RtlFreeAnsiString(&InitFuncName); 488 489 /* In case of error unload the library */ 490 if (bResult == FALSE) 491 { 492 FreeLibrary(hLibrary); 493 } 494 } 495 else 496 { 497 /* Cleanup user api hook before unloading */ 498 if (bApiHook) 499 { 500 hLibrary = ghmodUserApiHook; 501 bResult = ClearUserApiHook(ghmodUserApiHook); 502 503 /* Check if we can we unload it now */ 504 if (!bResult) 505 { 506 /* Return success because we are going to free 507 the library in EndUserApiHook*/ 508 return TRUE; 509 } 510 } 511 else 512 { 513 /* Get the library handle from the name */ 514 hLibrary = GetModuleHandle(pstrLibName->Buffer); 515 if (hLibrary == NULL) 516 { 517 return FALSE; 518 } 519 } 520 521 bResult = FreeLibrary(hLibrary); 522 } 523 524 return bResult; 525 } 526 527 NTSTATUS WINAPI 528 User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength) 529 { 530 BOOL bResult; 531 PCLIENT_LOAD_LIBRARY_ARGUMENTS Argument; 532 533 /* Retireve the callback parameters */ 534 Argument = (PCLIENT_LOAD_LIBRARY_ARGUMENTS)Arguments; 535 if(Argument->strLibraryName.Buffer != NULL) 536 { 537 Argument->strLibraryName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strLibraryName.Buffer + (ULONG_PTR)Argument); 538 } 539 if(Argument->strInitFuncName.Buffer != NULL) 540 { 541 Argument->strInitFuncName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strInitFuncName.Buffer + (ULONG_PTR)Argument); 542 } 543 544 /* Call the implementation of the callback */ 545 bResult = ClientLoadLibrary(&Argument->strLibraryName, 546 &Argument->strInitFuncName, 547 Argument->Unload, 548 Argument->ApiHook); 549 550 return ZwCallbackReturn(&bResult, sizeof(HINSTANCE), STATUS_SUCCESS); 551 } 552 553 NTSTATUS WINAPI 554 User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) 555 { 556 PHOOKPROC_CALLBACK_ARGUMENTS Common; 557 CREATESTRUCTW *pCsw = NULL; 558 CBT_CREATEWNDW *pCbtCreatewndw = NULL; 559 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL; 560 KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData; 561 MSLLHOOKSTRUCT MouseLlData, *pMouseLlData; 562 MSG *pcMsg, *pMsg; 563 PMOUSEHOOKSTRUCT pMHook; 564 CWPSTRUCT *pCWP; 565 CWPRETSTRUCT *pCWPR; 566 PRECTL prl; 567 LPCBTACTIVATESTRUCT pcbtas; 568 HOOKPROC Proc; 569 WPARAM wParam = 0; 570 LPARAM lParam = 0; 571 LRESULT Result = 0; 572 BOOL Hit = FALSE, Loaded = FALSE; 573 HMODULE mod = NULL; 574 NTSTATUS Status = STATUS_SUCCESS; 575 576 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments; 577 578 Proc = Common->Proc; 579 // HookProc Justin Case module is from another process. 580 if (Common->offPfn && Common->Mod) 581 { 582 if (!(mod = GetModuleHandleW((LPCWSTR)Common->ModuleName))) 583 { 584 TRACE("Reloading Hook Module.\n"); 585 if (!(mod = LoadLibraryExW((LPCWSTR)Common->ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH))) 586 { 587 ERR("Failed to load Hook Module.\n"); 588 } 589 else 590 { 591 Loaded = TRUE; // Free it only when loaded. 592 } 593 } 594 if (mod) 595 { 596 TRACE("Loading Hook Module. %S\n",Common->ModuleName); 597 Proc = (HOOKPROC)((char *)mod + Common->offPfn); 598 } 599 } 600 601 switch(Common->HookId) 602 { 603 case WH_CBT: 604 { 605 //ERR("WH_CBT: Code %d\n", Common->Code); 606 switch(Common->Code) 607 { 608 case HCBT_CREATEWND: 609 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) 610 ((PCHAR) Common + Common->lParam); 611 612 pCbtCreatewndw = (CBT_CREATEWNDW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CBT_CREATEWNDW)); 613 RtlCopyMemory(pCbtCreatewndw, CbtCreatewndExtra, sizeof(CBT_CREATEWNDW)); 614 615 pCsw = (CREATESTRUCTW*)HeapAlloc(GetProcessHeap(), 0, sizeof(CREATESTRUCTW)); 616 RtlCopyMemory(pCsw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); 617 618 pCbtCreatewndw->lpcs = pCsw; 619 pCbtCreatewndw->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; 620 wParam = Common->wParam; 621 lParam = (LPARAM) pCbtCreatewndw; 622 //ERR("HCBT_CREATEWND: hWnd %p Csw %p Name %p Class %p\n", Common->wParam, pCsw, pCsw->lpszName, pCsw->lpszClass); 623 break; 624 case HCBT_CLICKSKIPPED: 625 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); 626 lParam = (LPARAM) pMHook; 627 wParam = Common->wParam; 628 break; 629 case HCBT_MOVESIZE: 630 prl = (PRECTL)((PCHAR) Common + Common->lParam); 631 lParam = (LPARAM) prl; 632 wParam = Common->wParam; 633 break; 634 case HCBT_ACTIVATE: 635 //ERR("HCBT_ACTIVATE: hwnd %p\n",Common->wParam); 636 pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam); 637 lParam = (LPARAM) pcbtas; 638 wParam = Common->wParam; 639 break; 640 case HCBT_KEYSKIPPED: /* The rest SEH support */ 641 case HCBT_MINMAX: 642 case HCBT_SETFOCUS: 643 case HCBT_SYSCOMMAND: 644 case HCBT_DESTROYWND: 645 case HCBT_QS: 646 wParam = Common->wParam; 647 lParam = Common->lParam; 648 break; 649 default: 650 if (Loaded) FreeLibrary(mod); 651 ERR("HCBT_ not supported = %d\n", Common->Code); 652 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED); 653 } 654 655 if (Proc) 656 { 657 _SEH2_TRY 658 { 659 Result = Proc(Common->Code, wParam, lParam); 660 } 661 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 662 { 663 Hit = TRUE; 664 } 665 _SEH2_END; 666 } 667 else 668 { 669 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Proc); 670 } 671 switch(Common->Code) 672 { 673 case HCBT_CREATEWND: 674 CbtCreatewndExtra->WndInsertAfter = pCbtCreatewndw->hwndInsertAfter; 675 CbtCreatewndExtra->Cs.x = pCbtCreatewndw->lpcs->x; 676 CbtCreatewndExtra->Cs.y = pCbtCreatewndw->lpcs->y; 677 CbtCreatewndExtra->Cs.cx = pCbtCreatewndw->lpcs->cx; 678 CbtCreatewndExtra->Cs.cy = pCbtCreatewndw->lpcs->cy; 679 HeapFree(GetProcessHeap(), 0, pCsw); 680 HeapFree(GetProcessHeap(), 0, pCbtCreatewndw); 681 break; 682 } 683 break; 684 } 685 case WH_KEYBOARD_LL: 686 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); 687 pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); 688 RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT)); 689 Result = Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData); 690 break; 691 case WH_MOUSE_LL: 692 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); 693 pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); 694 RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT)); 695 Result = Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData); 696 break; 697 case WH_MOUSE: /* SEH support */ 698 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); 699 _SEH2_TRY 700 { 701 Result = Proc(Common->Code, Common->wParam, (LPARAM) pMHook); 702 } 703 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 704 { 705 Hit = TRUE; 706 } 707 _SEH2_END; 708 break; 709 case WH_CALLWNDPROC: 710 { 711 PCWP_Struct pcwps = (PCWP_Struct)Common; 712 CWPSTRUCT *pCWPT = &pcwps->cwps; 713 pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT)); 714 RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT)); 715 // ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message); 716 /* If more memory is reserved, then lParam is a pointer. 717 * Size of the buffer is stocked in the lParam member, and its content 718 * is at the end of the argument buffer */ 719 if ( Common->lParamSize ) 720 { 721 pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT)); 722 RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize ); 723 } 724 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP); 725 HeapFree(GetProcessHeap(), 0, pCWP); 726 } 727 break; 728 case WH_CALLWNDPROCRET: 729 /* Almost the same as WH_CALLWNDPROC */ 730 { 731 PCWPR_Struct pcwprs = (PCWPR_Struct)Common; 732 CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs; 733 pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT)); 734 RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT)); 735 if ( Common->lParamSize ) 736 { 737 pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT)); 738 RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize ); 739 } 740 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR); 741 HeapFree(GetProcessHeap(), 0, pCWPR); 742 } 743 break; 744 case WH_MSGFILTER: /* All SEH support */ 745 case WH_SYSMSGFILTER: 746 case WH_GETMESSAGE: 747 pMsg = (PMSG)((PCHAR) Common + Common->lParam); 748 pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG)); 749 RtlCopyMemory(pcMsg, pMsg, sizeof(MSG)); 750 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message); 751 _SEH2_TRY 752 { 753 Result = Proc(Common->Code, Common->wParam, (LPARAM) pcMsg); 754 } 755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 756 { 757 Hit = TRUE; 758 } 759 _SEH2_END; 760 if (!Hit && Common->HookId == WH_GETMESSAGE) 761 RtlCopyMemory(pMsg, pcMsg, sizeof(MSG)); 762 HeapFree( GetProcessHeap(), 0, pcMsg ); 763 break; 764 case WH_KEYBOARD: 765 case WH_SHELL: 766 Result = Proc(Common->Code, Common->wParam, Common->lParam); 767 break; 768 case WH_FOREGROUNDIDLE: /* <-- SEH support */ 769 _SEH2_TRY 770 { 771 Result = Proc(Common->Code, Common->wParam, Common->lParam); 772 } 773 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 774 { 775 Hit = TRUE; 776 } 777 _SEH2_END; 778 break; 779 default: 780 if (Loaded) FreeLibrary(mod); 781 ERR("WH_ not supported = %d\n", Common->HookId); 782 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED); 783 } 784 if (Hit) 785 { 786 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Proc); 787 Status = STATUS_UNSUCCESSFUL; 788 } 789 if (Loaded) FreeLibrary(mod); 790 Common->Result = Result; 791 return ZwCallbackReturn(Arguments, ArgumentLength, Status); 792 } 793 794 NTSTATUS WINAPI 795 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength) 796 { 797 PEVENTPROC_CALLBACK_ARGUMENTS Common; 798 WINEVENTPROC Proc; 799 WCHAR module[MAX_PATH]; 800 DWORD len; 801 HMODULE mod = NULL; 802 BOOL Loaded = FALSE; 803 804 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments; 805 806 Proc = Common->Proc; 807 808 if (Common->offPfn && Common->Mod) 809 { // Validate the module again. 810 if (!(len = GetModuleFileNameW((HINSTANCE)Common->Mod, module, MAX_PATH)) || len >= MAX_PATH) 811 { 812 ERR("Error check for module!\n"); 813 Common->Mod = 0; 814 } 815 816 if (Common->Mod && !(mod = GetModuleHandleW(module))) 817 { 818 TRACE("Reloading Event Module.\n"); 819 if (!(mod = LoadLibraryExW(module, NULL, LOAD_WITH_ALTERED_SEARCH_PATH))) 820 { 821 ERR("Failed to load Event Module.\n"); 822 } 823 else 824 { 825 Loaded = TRUE; // Free it only when loaded. 826 } 827 } 828 829 if (mod) 830 { 831 TRACE("Loading Event Module. %S\n",module); 832 Proc = (WINEVENTPROC)((char *)mod + Common->offPfn); 833 } 834 } 835 836 Proc(Common->hook, 837 Common->event, 838 Common->hwnd, 839 Common->idObject, 840 Common->idChild, 841 Common->dwEventThread, 842 Common->dwmsEventTime); 843 844 if (Loaded) FreeLibrary(mod); 845 846 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS); 847 } 848 849 850 851