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