78b1a37acb3d52cf4f29594a75d91428a65f3be6
[reactos.git] / win32ss / user / user32 / windows / hook.c
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