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
GetMaskFromEvent(DWORD Event)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
IntSetWindowsHook(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId,BOOL bAnsi)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
IntNotifyWinEvent(DWORD event,HWND hwnd,LONG idObject,LONG idChild,DWORD flags)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
CallMsgFilterA(LPMSG lpMsg,int nCode)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
CallMsgFilterW(LPMSG lpMsg,int nCode)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
CallNextHookEx(HHOOK Hook,int Code,WPARAM wParam,LPARAM lParam)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
SetWindowsHookW(int idHook,HOOKPROC lpfn)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
SetWindowsHookA(int idHook,HOOKPROC lpfn)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
DeregisterShellHookWindow(HWND hWnd)295 DeregisterShellHookWindow(HWND hWnd)
296 {
297 return NtUserxDeregisterShellHookWindow(hWnd);
298 }
299
300 /*
301 * @unimplemented
302 */
303 BOOL
304 WINAPI
RegisterShellHookWindow(HWND hWnd)305 RegisterShellHookWindow(HWND hWnd)
306 {
307 return NtUserxRegisterShellHookWindow(hWnd);
308 }
309
310 /*
311 * @implemented
312 */
313 BOOL
314 WINAPI
UnhookWindowsHook(int nCode,HOOKPROC pfnFilterProc)315 UnhookWindowsHook ( int nCode, HOOKPROC pfnFilterProc )
316 {
317 return NtUserxUnhookWindowsHook(nCode, pfnFilterProc);
318 }
319
320 /*
321 * @implemented
322 */
323 VOID
324 WINAPI
NotifyWinEvent(DWORD event,HWND hwnd,LONG idObject,LONG idChild)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
SetWinEventHook(UINT eventMin,UINT eventMax,HMODULE hmodWinEventProc,WINEVENTPROC pfnWinEventProc,DWORD idProcess,DWORD idThread,UINT dwFlags)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
IsWinEventHookInstalled(DWORD event)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
SetWindowsHookExA(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId)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
SetWindowsHookExW(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId)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
ClientLoadLibrary(PUNICODE_STRING pstrLibName,PUNICODE_STRING pstrInitFunc,BOOL bUnload,BOOL bApiHook)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
User32CallClientLoadLibraryFromKernel(PVOID Arguments,ULONG ArgumentLength)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
User32CallHookProcFromKernel(PVOID Arguments,ULONG ArgumentLength)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 hwnd %p msg %d\n",Common->Code,Common->wParam,pCWP->hwnd,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(CWPRETSTRUCT));
735 //ERR("WH_CALLWNDPROCRET: Code %d, wParam %d hwnd %p msg %d\n",Common->Code,Common->wParam,pCWPRT->hwnd,pCWPRT->message);
736 if ( Common->lParamSize )
737 {
738 pCWPR->lParam = (LPARAM)((PCHAR)pCWPR + sizeof(CWPRETSTRUCT));
739 RtlCopyMemory( (PCHAR)pCWPR + sizeof(CWPRETSTRUCT), &pcwprs->Extra, Common->lParamSize );
740 }
741 Result = Proc(Common->Code, Common->wParam, (LPARAM) pCWPR);
742 HeapFree(GetProcessHeap(), 0, pCWPR);
743 }
744 break;
745 case WH_MSGFILTER: /* All SEH support */
746 case WH_SYSMSGFILTER:
747 case WH_GETMESSAGE:
748 pMsg = (PMSG)((PCHAR) Common + Common->lParam);
749 pcMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MSG));
750 RtlCopyMemory(pcMsg, pMsg, sizeof(MSG));
751 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
752 _SEH2_TRY
753 {
754 Result = Proc(Common->Code, Common->wParam, (LPARAM) pcMsg);
755 }
756 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
757 {
758 Hit = TRUE;
759 }
760 _SEH2_END;
761 if (!Hit && Common->HookId == WH_GETMESSAGE)
762 RtlCopyMemory(pMsg, pcMsg, sizeof(MSG));
763 HeapFree( GetProcessHeap(), 0, pcMsg );
764 break;
765 case WH_KEYBOARD:
766 case WH_SHELL:
767 Result = Proc(Common->Code, Common->wParam, Common->lParam);
768 break;
769 case WH_FOREGROUNDIDLE: /* <-- SEH support */
770 _SEH2_TRY
771 {
772 Result = Proc(Common->Code, Common->wParam, Common->lParam);
773 }
774 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
775 {
776 Hit = TRUE;
777 }
778 _SEH2_END;
779 break;
780 default:
781 if (Loaded) FreeLibrary(mod);
782 ERR("WH_ not supported = %d\n", Common->HookId);
783 return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
784 }
785 if (Hit)
786 {
787 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Proc);
788 Status = STATUS_UNSUCCESSFUL;
789 }
790 if (Loaded) FreeLibrary(mod);
791 Common->Result = Result;
792 return ZwCallbackReturn(Arguments, ArgumentLength, Status);
793 }
794
795 NTSTATUS WINAPI
User32CallEventProcFromKernel(PVOID Arguments,ULONG ArgumentLength)796 User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
797 {
798 PEVENTPROC_CALLBACK_ARGUMENTS Common;
799 WINEVENTPROC Proc;
800 WCHAR module[MAX_PATH];
801 DWORD len;
802 HMODULE mod = NULL;
803 BOOL Loaded = FALSE;
804
805 Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments;
806
807 Proc = Common->Proc;
808
809 if (Common->offPfn && Common->Mod)
810 { // Validate the module again.
811 if (!(len = GetModuleFileNameW((HINSTANCE)Common->Mod, module, MAX_PATH)) || len >= MAX_PATH)
812 {
813 ERR("Error check for module!\n");
814 Common->Mod = 0;
815 }
816
817 if (Common->Mod && !(mod = GetModuleHandleW(module)))
818 {
819 TRACE("Reloading Event Module.\n");
820 if (!(mod = LoadLibraryExW(module, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)))
821 {
822 ERR("Failed to load Event Module.\n");
823 }
824 else
825 {
826 Loaded = TRUE; // Free it only when loaded.
827 }
828 }
829
830 if (mod)
831 {
832 TRACE("Loading Event Module. %S\n",module);
833 Proc = (WINEVENTPROC)((char *)mod + Common->offPfn);
834 }
835 }
836
837 Proc(Common->hook,
838 Common->event,
839 Common->hwnd,
840 Common->idObject,
841 Common->idChild,
842 Common->dwEventThread,
843 Common->dwmsEventTime);
844
845 if (Loaded) FreeLibrary(mod);
846
847 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
848 }
849
850
851
852