[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: dll/win32/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 //GetConnected();
215
216 ClientInfo = GetWin32ClientInfo();
217
218 if (!ClientInfo->phkCurrent) return 0;
219
220 pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
221
222 if (!pHook->phkNext) return 0; // Nothing to do....
223
224 phkNext = DesktopPtrToUser(pHook->phkNext);
225
226 if ( phkNext->HookId == WH_CALLWNDPROC ||
227 phkNext->HookId == WH_CALLWNDPROCRET)
228 {
229 Save = ClientInfo->dwHookData;
230 Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
231 // wParam: If the message was sent by the current thread/process, it is
232 // nonzero; otherwise, it is zero.
233 if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
234 else ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
235
236 if (phkNext->HookId == WH_CALLWNDPROC)
237 {
238 PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
239
240 NtUserMessageCall( pCWP->hwnd,
241 pCWP->message,
242 pCWP->wParam,
243 pCWP->lParam,
244 (ULONG_PTR)&lResult,
245 FNID_CALLWNDPROC,
246 phkNext->Ansi);
247 }
248 else
249 {
250 PCWPRETSTRUCT pCWPR = (PCWPRETSTRUCT)lParam;
251
252 ClientInfo->dwHookData = pCWPR->lResult;
253
254 NtUserMessageCall( pCWPR->hwnd,
255 pCWPR->message,
256 pCWPR->wParam,
257 pCWPR->lParam,
258 (ULONG_PTR)&lResult,
259 FNID_CALLWNDPROCRET,
260 phkNext->Ansi);
261 }
262 ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
263 ClientInfo->dwHookData = Save;
264 }
265 else
266 lResult = NtUserCallNextHookEx(Code, wParam, lParam, pHook->Ansi);
267
268 return lResult;
269 }
270
271
272 /*
273 * @implemented
274 */
275 HHOOK
276 WINAPI
277 SetWindowsHookW(int idHook, HOOKPROC lpfn)
278 {
279 DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
280 return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE);
281 // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
282 }
283
284 /*
285 * @implemented
286 */
287 HHOOK
288 WINAPI
289 SetWindowsHookA(int idHook, HOOKPROC lpfn)
290 {
291 DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
292 return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE);
293 // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
294 }
295
296 /*
297 * @unimplemented
298 */
299 BOOL
300 WINAPI
301 DeregisterShellHookWindow(HWND hWnd)
302 {
303 return NtUserxDeregisterShellHookWindow(hWnd);
304 }
305
306 /*
307 * @unimplemented
308 */
309 BOOL
310 WINAPI
311 RegisterShellHookWindow(HWND hWnd)
312 {
313 return NtUserxRegisterShellHookWindow(hWnd);
314 }
315
316 /*
317 * @implemented
318 */
319 BOOL
320 WINAPI
321 UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc )
322 {
323 return NtUserxUnhookWindowsHook(nCode, pfnFilterProc);
324 }
325
326 /*
327 * @implemented
328 */
329 VOID
330 WINAPI
331 NotifyWinEvent(
332 DWORD event,
333 HWND hwnd,
334 LONG idObject,
335 LONG idChild
336 )
337 {
338 // "Servers call NotifyWinEvent to announce the event to the system after the
339 // event has occurred; they must never notify the system of an event before
340 // the event has occurred." msdn on NotifyWinEvent.
341 if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) // Check to see.
342 NtUserNotifyWinEvent(event, hwnd, idObject, idChild);
343 }
344
345 /*
346 * @implemented
347 */
348 HWINEVENTHOOK
349 WINAPI
350 SetWinEventHook(
351 UINT eventMin,
352 UINT eventMax,
353 HMODULE hmodWinEventProc,
354 WINEVENTPROC pfnWinEventProc,
355 DWORD idProcess,
356 DWORD idThread,
357 UINT dwFlags
358 )
359 {
360 WCHAR ModuleName[MAX_PATH];
361 UNICODE_STRING USModuleName;
362
363 if ((hmodWinEventProc != NULL) && (dwFlags & WINEVENT_INCONTEXT))
364 {
365 if (0 == GetModuleFileNameW(hmodWinEventProc, ModuleName, MAX_PATH))
366 {
367 return NULL;
368 }
369 RtlInitUnicodeString(&USModuleName, ModuleName);
370 }
371 else
372 {
373 RtlInitUnicodeString(&USModuleName, NULL);
374 }
375
376 return NtUserSetWinEventHook(eventMin,
377 eventMax,
378 hmodWinEventProc,
379 &USModuleName,
380 pfnWinEventProc,
381 idProcess,
382 idThread,
383 dwFlags);
384 }
385
386 /*
387 * @implemented
388 */
389 BOOL
390 WINAPI
391 IsWinEventHookInstalled(
392 DWORD event)
393 {
394 if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
395 {
396 return (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event)) != 0;
397 }
398 return FALSE;
399 }
400
401 /*
402 * @implemented
403 */
404 HHOOK
405 WINAPI
406 SetWindowsHookExA(
407 int idHook,
408 HOOKPROC lpfn,
409 HINSTANCE hMod,
410 DWORD dwThreadId)
411 {
412 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, TRUE);
413 }
414
415
416 /*
417 * @implemented
418 */
419 HHOOK
420 WINAPI
421 SetWindowsHookExW(
422 int idHook,
423 HOOKPROC lpfn,
424 HINSTANCE hMod,
425 DWORD dwThreadId)
426 {
427 return IntSetWindowsHook(idHook, lpfn, hMod, dwThreadId, FALSE);
428 }
429
430 static
431 BOOL
432 ClientLoadLibrary(
433 PUNICODE_STRING pstrLibName,
434 PUNICODE_STRING pstrInitFunc,
435 BOOL bUnload,
436 BOOL bApiHook)
437 {
438 HINSTANCE hLibrary;
439 PVOID pInitFunction;
440 NTSTATUS Status;
441 ANSI_STRING InitFuncName;
442 BOOL bResult = FALSE;
443
444 TRACE("ClientLoadLibrary: pid: %d, strLibraryName: %S, "
445 "strInitFuncName: %S, bUnload: %d, bApiHook:%d\n",
446 GetCurrentProcessId(),
447 pstrLibName->Buffer,
448 pstrInitFunc->Buffer,
449 bUnload,
450 bApiHook);
451
452 /* Check if we have to load the module */
453 if (bUnload == FALSE)
454 {
455 ASSERT(pstrLibName->Buffer != NULL);
456
457 /* Load it */
458 hLibrary = LoadLibrary(pstrLibName->Buffer);
459 if (hLibrary == 0)
460 {
461 return FALSE;
462 }
463
464 if (!bApiHook)
465 {
466 /* There is nothing more to do for a global hook*/
467 return TRUE;
468 }
469
470 /* Initialize the user api hook */
471 ASSERT(pstrInitFunc->Buffer);
472 Status = RtlUnicodeStringToAnsiString(&InitFuncName,
473 pstrInitFunc,
474 TRUE);
475 if (!NT_SUCCESS(Status))
476 {
477 FreeLibrary(hLibrary);
478 return FALSE;
479 }
480
481 /* Get the address of the initialization routine */
482 pInitFunction = GetProcAddress(hLibrary, InitFuncName.Buffer);
483 if (pInitFunction)
484 {
485 /* Call the initialization routine */
486 bResult = InitUserApiHook(hLibrary, (USERAPIHOOKPROC)pInitFunction);
487 }
488
489 RtlFreeAnsiString(&InitFuncName);
490
491 /* In case of error unload the library */
492 if (bResult == FALSE)
493 {
494 FreeLibrary(hLibrary);
495 }
496 }
497 else
498 {
499 /* Cleanup user api hook before unloading */
500 if (bApiHook)
501 {
502 hLibrary = ghmodUserApiHook;
503 bResult = ClearUserApiHook(ghmodUserApiHook);
504
505 /* Check if we can we unload it now */
506 if (!bResult)
507 {
508 /* Return success because we are going to free
509 the library in EndUserApiHook*/
510 return TRUE;
511 }
512 }
513 else
514 {
515 /* Get the library handle from the name */
516 hLibrary = GetModuleHandle(pstrLibName->Buffer);
517 if (hLibrary == NULL)
518 {
519 return FALSE;
520 }
521 }
522
523 bResult = FreeLibrary(hLibrary);
524 }
525
526 return bResult;
527 }
528
529 NTSTATUS WINAPI
530 User32CallClientLoadLibraryFromKernel(PVOID Arguments, ULONG ArgumentLength)
531 {
532 BOOL bResult;
533 PCLIENT_LOAD_LIBRARY_ARGUMENTS Argument;
534
535 /* Retireve the callback parameters */
536 Argument = (PCLIENT_LOAD_LIBRARY_ARGUMENTS)Arguments;
537 if(Argument->strLibraryName.Buffer != NULL)
538 {
539 Argument->strLibraryName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strLibraryName.Buffer + (ULONG_PTR)Argument);
540 }
541 if(Argument->strInitFuncName.Buffer != NULL)
542 {
543 Argument->strInitFuncName.Buffer = (PWCHAR)((ULONG_PTR)Argument->strInitFuncName.Buffer + (ULONG_PTR)Argument);
544 }
545
546 /* Call the implementation of the callback */
547 bResult = ClientLoadLibrary(&Argument->strLibraryName,
548 &Argument->strInitFuncName,
549 Argument->Unload,
550 Argument->ApiHook);
551
552 return ZwCallbackReturn(&bResult, sizeof(HINSTANCE), STATUS_SUCCESS);
553 }
554
555 NTSTATUS WINAPI
556 User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
557 {
558 PHOOKPROC_CALLBACK_ARGUMENTS Common;
559 CREATESTRUCTW Csw;
560 CBT_CREATEWNDW CbtCreatewndw;
561 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
562 KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData;
563 MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
564 MSG *pcMsg, *pMsg;
565 PMOUSEHOOKSTRUCT pMHook;
566 CWPSTRUCT *pCWP;
567 CWPRETSTRUCT *pCWPR;
568 PRECTL prl;
569 LPCBTACTIVATESTRUCT pcbtas;
570 HOOKPROC Proc;
571 WPARAM wParam = 0;
572 LPARAM lParam = 0;
573 LRESULT Result = 0;
574 BOOL Hit = FALSE;
575 HMODULE mod = NULL;
576
577 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
578
579 Proc = Common->Proc;
580 // HookProc Justin Case module is from another process.
581 if (Common->offPfn && Common->Mod)
582 {
583 if (!(mod = GetModuleHandleW((LPCWSTR)Common->ModuleName)))
584 {
585 TRACE("Reloading Hook Module.\n");
586 if (!(mod = LoadLibraryExW((LPCWSTR)Common->ModuleName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)))
587 {
588 ERR("Failed to load Hook Module.\n");
589 }
590 }
591 if (mod)
592 {
593 TRACE("Loading Hook Module.\n");
594 Proc = (HOOKPROC)((char *)mod + Common->offPfn);
595 }
596 }
597
598 switch(Common->HookId)
599 {
600 case WH_CBT:
601 {
602 //ERR("WH_CBT: Code %d\n", Common->Code);
603 switch(Common->Code)
604 {
605 case HCBT_CREATEWND:
606 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
607 ((PCHAR) Common + Common->lParam);
608 RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW));
609 CbtCreatewndw.lpcs = &Csw;
610 CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
611 wParam = Common->wParam;
612 lParam = (LPARAM) &CbtCreatewndw;
613 //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass);
614 break;
615 case HCBT_CLICKSKIPPED:
616 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
617 lParam = (LPARAM) pMHook;
618 break;
619 case HCBT_MOVESIZE:
620 prl = (PRECTL)((PCHAR) Common + Common->lParam);
621 lParam = (LPARAM) prl;
622 break;
623 case HCBT_ACTIVATE:
624 pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
625 lParam = (LPARAM) pcbtas;
626 break;
627 case HCBT_KEYSKIPPED: /* The rest SEH support */
628 case HCBT_MINMAX:
629 case HCBT_SETFOCUS:
630 case HCBT_SYSCOMMAND:
631 case HCBT_DESTROYWND:
632 case HCBT_QS:
633 wParam = Common->wParam;
634 lParam = Common->lParam;
635 break;
636 default:
637 if (mod) FreeLibrary(mod);
638 ERR("HCBT_ not supported = %d\n", Common->Code);
639 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
640 }
641
642 if (Proc)
643 {
644 _SEH2_TRY
645 {
646 Result = Proc(Common->Code, wParam, lParam);
647 }
648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
649 {
650 Hit = TRUE;
651 }
652 _SEH2_END;
653 }
654 else
655 {
656 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Proc);
657 }
658 switch(Common->Code)
659 {
660 case HCBT_CREATEWND:
661 CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
662 CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
663 CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
664 CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
665 CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
666 break;
667 }
668 break;
669 }
670 case WH_KEYBOARD_LL:
671 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
672 pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
673 RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT));
674 Result = Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData);
675 break;
676 case WH_MOUSE_LL:
677 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
678 pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
679 RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
680 Result = Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
681 break;
682 case WH_MOUSE: /* SEH support */
683 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
684 _SEH2_TRY
685 {
686 Result = Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
687 }
688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
689 {
690 Hit = TRUE;
691 }
692 _SEH2_END;
693 break;
694 case WH_CALLWNDPROC:
695 // ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
696 pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
697 RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
698 /* If more memory is reserved, then lParam is a pointer.
699 * Size of the buffer is stocked in the lParam member, and its content
700 * is at the end of the argument buffer */
701 if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
702 {
703 RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
704 (PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
705 pCWP->lParam);
706 pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
707 }
708 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
709 HeapFree(GetProcessHeap(), 0, pCWP);
710 break;
711 case WH_CALLWNDPROCRET:
712 /* Almost the same as WH_CALLWNDPROC */
713 pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
714 RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
715 if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
716 {
717 RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
718 (PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
719 pCWPR->lParam);
720 pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
721 }
722 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
723 HeapFree(GetProcessHeap(), 0, pCWPR);
724 break;
725 case WH_MSGFILTER: /* All SEH support */
726 case WH_SYSMSGFILTER:
727 case WH_GETMESSAGE:
728 pMsg = (PMSG)((PCHAR) Common + Common->lParam);
729 pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG));
730 RtlCopyMemory(pcMsg, pMsg, sizeof(MSG));
731 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
732 _SEH2_TRY
733 {
734 Result = Proc(Common->Code, Common->wParam, (LPARAM) pcMsg);
735 }
736 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
737 {
738 Hit = TRUE;
739 }
740 _SEH2_END;
741 if (!Hit && Common->HookId == WH_GETMESSAGE)
742 RtlCopyMemory(pMsg, pcMsg, sizeof(MSG));
743 HeapFree( GetProcessHeap(), 0, pcMsg );
744 break;
745 case WH_KEYBOARD:
746 case WH_SHELL:
747 Result = Proc(Common->Code, Common->wParam, Common->lParam);
748 break;
749 case WH_FOREGROUNDIDLE: /* <-- SEH support */
750 _SEH2_TRY
751 {
752 Result = Proc(Common->Code, Common->wParam, Common->lParam);
753 }
754 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
755 {
756 Hit = TRUE;
757 }
758 _SEH2_END;
759 break;
760 default:
761 if (mod) FreeLibrary(mod);
762 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
763 }
764 if (Hit)
765 {
766 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Proc);
767 }
768 if (mod) FreeLibrary(mod);
769 return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
770 }
771
772 NTSTATUS WINAPI
773 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
774 {
775 PEVENTPROC_CALLBACK_ARGUMENTS Common;
776
777 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
778
779 Common->Proc(Common->hook,
780 Common->event,
781 Common->hwnd,
782 Common->idObject,
783 Common->idChild,
784 Common->dwEventThread,
785 Common->dwmsEventTime);
786
787 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
788 }
789
790
791