cfe2a82c6f5398d8277625321b847ad841aa7da8
[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 WPARAM wParam = 0;
571 LPARAM lParam = 0;
572 LRESULT Result = 0;
573 BOOL Hit = FALSE;
574
575 Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
576
577 switch(Common->HookId)
578 {
579 case WH_CBT:
580 {
581 //ERR("WH_CBT: Code %d\n", Common->Code);
582 switch(Common->Code)
583 {
584 case HCBT_CREATEWND:
585 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
586 ((PCHAR) Common + Common->lParam);
587 RtlCopyMemory(&Csw, &CbtCreatewndExtra->Cs, sizeof(CREATESTRUCTW));
588 CbtCreatewndw.lpcs = &Csw;
589 CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
590 wParam = Common->wParam;
591 lParam = (LPARAM) &CbtCreatewndw;
592 //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass);
593 break;
594 case HCBT_CLICKSKIPPED:
595 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
596 lParam = (LPARAM) pMHook;
597 break;
598 case HCBT_MOVESIZE:
599 prl = (PRECTL)((PCHAR) Common + Common->lParam);
600 lParam = (LPARAM) prl;
601 break;
602 case HCBT_ACTIVATE:
603 pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
604 lParam = (LPARAM) pcbtas;
605 break;
606 case HCBT_KEYSKIPPED: /* The rest SEH support */
607 case HCBT_MINMAX:
608 case HCBT_SETFOCUS:
609 case HCBT_SYSCOMMAND:
610 case HCBT_DESTROYWND:
611 case HCBT_QS:
612 wParam = Common->wParam;
613 lParam = Common->lParam;
614 break;
615 default:
616 ERR("HCBT_ not supported = %d\n", Common->Code);
617 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
618 }
619
620 if (Common->Proc)
621 {
622 _SEH2_TRY
623 {
624 Result = Common->Proc(Common->Code, wParam, lParam);
625 }
626 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
627 {
628 Hit = TRUE;
629 }
630 _SEH2_END;
631 }
632 else
633 {
634 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
635 }
636 switch(Common->Code)
637 {
638 case HCBT_CREATEWND:
639 CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter;
640 CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
641 CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
642 CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
643 CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
644 break;
645 }
646 break;
647 }
648 case WH_KEYBOARD_LL:
649 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
650 pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
651 RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT));
652 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData);
653 break;
654 case WH_MOUSE_LL:
655 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
656 pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
657 RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
658 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
659 break;
660 case WH_MOUSE: /* SEH support */
661 pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
662 _SEH2_TRY
663 {
664 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
665 }
666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
667 {
668 Hit = TRUE;
669 }
670 _SEH2_END;
671 break;
672 case WH_CALLWNDPROC:
673 // ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
674 pCWP = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
675 RtlCopyMemory(pCWP, (PCHAR) Common + Common->lParam, sizeof(CWPSTRUCT));
676 /* If more memory is reserved, then lParam is a pointer.
677 * Size of the buffer is stocked in the lParam member, and its content
678 * is at the end of the argument buffer */
679 if(ArgumentLength > (sizeof(CWPSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
680 {
681 RtlCopyMemory((PCHAR)pCWP + sizeof(CWPSTRUCT),
682 (PCHAR)Common + Common->lParam + sizeof(CWPSTRUCT),
683 pCWP->lParam);
684 pCWP->lParam = (LPARAM)((PCHAR)pCWP + sizeof(CWPSTRUCT));
685 }
686 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWP);
687 HeapFree(GetProcessHeap(), 0, pCWP);
688 break;
689 case WH_CALLWNDPROCRET:
690 /* Almost the same as WH_CALLWNDPROC */
691 pCWPR = HeapAlloc(GetProcessHeap(), 0, ArgumentLength - sizeof(HOOKPROC_CALLBACK_ARGUMENTS));
692 RtlCopyMemory(pCWPR, (PCHAR) Common + Common->lParam, sizeof(CWPRETSTRUCT));
693 if(ArgumentLength > (sizeof(CWPRETSTRUCT) + sizeof(HOOKPROC_CALLBACK_ARGUMENTS)))
694 {
695 RtlCopyMemory((PCHAR)pCWPR + sizeof(CWPRETSTRUCT),
696 (PCHAR)Common + Common->lParam + sizeof(CWPRETSTRUCT),
697 pCWPR->lParam);
698 pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
699 }
700 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
701 HeapFree(GetProcessHeap(), 0, pCWPR);
702 break;
703 case WH_MSGFILTER: /* All SEH support */
704 case WH_SYSMSGFILTER:
705 case WH_GETMESSAGE:
706 pMsg = (PMSG)((PCHAR) Common + Common->lParam);
707 pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG));
708 RtlCopyMemory(pcMsg, pMsg, sizeof(MSG));
709 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
710 _SEH2_TRY
711 {
712 Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pcMsg);
713 }
714 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
715 {
716 Hit = TRUE;
717 }
718 _SEH2_END;
719 if (!Hit && Common->HookId == WH_GETMESSAGE)
720 RtlCopyMemory(pMsg, pcMsg, sizeof(MSG));
721 HeapFree( GetProcessHeap(), 0, pcMsg );
722 break;
723 case WH_KEYBOARD:
724 case WH_SHELL:
725 Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
726 break;
727 case WH_FOREGROUNDIDLE: /* <-- SEH support */
728 _SEH2_TRY
729 {
730 Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
731 }
732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
733 {
734 Hit = TRUE;
735 }
736 _SEH2_END;
737 break;
738 default:
739 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
740 }
741 if (Hit)
742 {
743 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Common->Proc);
744 }
745 return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
746 }
747
748 NTSTATUS WINAPI
749 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
750 {
751 PEVENTPROC_CALLBACK_ARGUMENTS Common;
752
753 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
754
755 Common->Proc(Common->hook,
756 Common->event,
757 Common->hwnd,
758 Common->idObject,
759 Common->idChild,
760 Common->dwEventThread,
761 Common->dwmsEventTime);
762
763 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
764 }
765
766
767