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 Csw; 558 CBT_CREATEWNDW CbtCreatewndw; 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 RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW)); 612 CbtCreatewndw.lpcs = &Csw; 613 CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter; 614 wParam = Common->wParam; 615 lParam = (LPARAM) &CbtCreatewndw; 616 //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass); 617 break; 618 case HCBT_CLICKSKIPPED: 619 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); 620 lParam = (LPARAM) pMHook; 621 wParam = Common->wParam; 622 break; 623 case HCBT_MOVESIZE: 624 prl = (PRECTL)((PCHAR) Common + Common->lParam); 625 lParam = (LPARAM) prl; 626 wParam = Common->wParam; 627 break; 628 case HCBT_ACTIVATE: 629 //ERR("HCBT_ACTIVATE: hwnd %p\n",Common->wParam); 630 pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam); 631 lParam = (LPARAM) pcbtas; 632 wParam = Common->wParam; 633 break; 634 case HCBT_KEYSKIPPED: /* The rest SEH support */ 635 case HCBT_MINMAX: 636 case HCBT_SETFOCUS: 637 case HCBT_SYSCOMMAND: 638 case HCBT_DESTROYWND: 639 case HCBT_QS: 640 wParam = Common->wParam; 641 lParam = Common->lParam; 642 break; 643 default: 644 if (Loaded) FreeLibrary(mod); 645 ERR("HCBT_ not supported = %d\n", Common->Code); 646 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED); 647 } 648 649 if (Proc) 650 { 651 _SEH2_TRY 652 { 653 Result = Proc(Common->Code, wParam, lParam); 654 } 655 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 656 { 657 Hit = TRUE; 658 } 659 _SEH2_END; 660 } 661 else 662 { 663 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Proc); 664 } 665 switch(Common->Code) 666 { 667 case HCBT_CREATEWND: 668 CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter; 669 CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x; 670 CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y; 671 CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx; 672 CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy; 673 break; 674 } 675 break; 676 } 677 case WH_KEYBOARD_LL: 678 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); 679 pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); 680 RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT)); 681 Result = Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData); 682 break; 683 case WH_MOUSE_LL: 684 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam); 685 pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam); 686 RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT)); 687 Result = Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData); 688 break; 689 case WH_MOUSE: /* SEH support */ 690 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam); 691 _SEH2_TRY 692 { 693 Result = Proc(Common->Code, Common->wParam, (LPARAM) pMHook); 694 } 695 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 696 { 697 Hit = TRUE; 698 } 699 _SEH2_END; 700 break; 701 case WH_CALLWNDPROC: 702 { 703 PCWP_Struct pcwps = (PCWP_Struct)Common; 704 CWPSTRUCT *pCWPT = &pcwps->cwps; 705 pCWP = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPSTRUCT)); 706 RtlCopyMemory(pCWP, pCWPT, sizeof(CWPSTRUCT)); 707 // ERR("WH_CALLWNDPROC: Code %d, wParam %d msg %d\n",Common->Code,Common->wParam,pCWP->message); 708 /* If more memory is reserved, then lParam is a pointer. 709 * Size of the buffer is stocked in the lParam member, and its content 710 * is at the end of the argument buffer */ 711 if ( Common->lParamSize ) 712 { 713 pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT)); 714 RtlCopyMemory( (PCHAR)pCWP + sizeof(CWPSTRUCT), &pcwps->Extra, Common->lParamSize ); 715 } 716 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP); 717 HeapFree(GetProcessHeap(), 0, pCWP); 718 } 719 break; 720 case WH_CALLWNDPROCRET: 721 /* Almost the same as WH_CALLWNDPROC */ 722 { 723 PCWPR_Struct pcwprs = (PCWPR_Struct)Common; 724 CWPRETSTRUCT *pCWPRT = &pcwprs->cwprs; 725 pCWPR = HeapAlloc(GetProcessHeap(), 0, Common->lParamSize + sizeof(CWPRETSTRUCT)); 726 RtlCopyMemory(pCWPR, pCWPRT, sizeof(CWPSTRUCT)); 727 if ( Common->lParamSize ) 728 { 729 pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT)); 730 RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize ); 731 } 732 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR); 733 HeapFree(GetProcessHeap(), 0, pCWPR); 734 } 735 break; 736 case WH_MSGFILTER: /* All SEH support */ 737 case WH_SYSMSGFILTER: 738 case WH_GETMESSAGE: 739 pMsg = (PMSG)((PCHAR) Common + Common->lParam); 740 pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG)); 741 RtlCopyMemory(pcMsg, pMsg, sizeof(MSG)); 742 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message); 743 _SEH2_TRY 744 { 745 Result = Proc(Common->Code, Common->wParam, (LPARAM) pcMsg); 746 } 747 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 748 { 749 Hit = TRUE; 750 } 751 _SEH2_END; 752 if (!Hit && Common->HookId == WH_GETMESSAGE) 753 RtlCopyMemory(pMsg, pcMsg, sizeof(MSG)); 754 HeapFree( GetProcessHeap(), 0, pcMsg ); 755 break; 756 case WH_KEYBOARD: 757 case WH_SHELL: 758 Result = Proc(Common->Code, Common->wParam, Common->lParam); 759 break; 760 case WH_FOREGROUNDIDLE: /* <-- SEH support */ 761 _SEH2_TRY 762 { 763 Result = Proc(Common->Code, Common->wParam, Common->lParam); 764 } 765 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 766 { 767 Hit = TRUE; 768 } 769 _SEH2_END; 770 break; 771 default: 772 if (Loaded) FreeLibrary(mod); 773 ERR("WH_ not supported = %d\n", Common->HookId); 774 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED); 775 } 776 if (Hit) 777 { 778 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Proc); 779 Status = STATUS_UNSUCCESSFUL; 780 } 781 if (Loaded) FreeLibrary(mod); 782 Common->Result = Result; 783 return ZwCallbackReturn(Arguments, ArgumentLength, Status); 784 } 785 786 NTSTATUS WINAPI 787 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength) 788 { 789 PEVENTPROC_CALLBACK_ARGUMENTS Common; 790 WINEVENTPROC Proc; 791 WCHAR module[MAX_PATH]; 792 DWORD len; 793 HMODULE mod = NULL; 794 BOOL Loaded = FALSE; 795 796 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments; 797 798 Proc = Common->Proc; 799 800 if (Common->offPfn && Common->Mod) 801 { // Validate the module again. 802 if (!(len = GetModuleFileNameW((HINSTANCE)Common->Mod, module, MAX_PATH)) || len >= MAX_PATH) 803 { 804 ERR("Error check for module!\n"); 805 Common->Mod = 0; 806 } 807 808 if (Common->Mod && !(mod = GetModuleHandleW(module))) 809 { 810 TRACE("Reloading Event Module.\n"); 811 if (!(mod = LoadLibraryExW(module, NULL, LOAD_WITH_ALTERED_SEARCH_PATH))) 812 { 813 ERR("Failed to load Event Module.\n"); 814 } 815 else 816 { 817 Loaded = TRUE; // Free it only when loaded. 818 } 819 } 820 821 if (mod) 822 { 823 TRACE("Loading Event Module. %S\n",module); 824 Proc = (WINEVENTPROC)((char *)mod + Common->offPfn); 825 } 826 } 827 828 Proc(Common->hook, 829 Common->event, 830 Common->hwnd, 831 Common->idObject, 832 Common->idChild, 833 Common->dwEventThread, 834 Common->dwmsEventTime); 835 836 if (Loaded) FreeLibrary(mod); 837 838 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS); 839 } 840 841 842 843