xref: /reactos/win32ss/user/user32/windows/hook.c (revision a89844f7)
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