3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
21 * PROJECT: ReactOS user32.dll
22 * FILE: dll/win32/user32/windows/hook.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 09-05-2001 CSH Created
29 /* INCLUDES ******************************************************************/
33 #include <wine/debug.h>
35 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
37 typedef struct _NOTIFYEVENT
43 } NOTIFYEVENT
, *PNOTIFYEVENT
;
45 /* PRIVATE FUNCTIONS *********************************************************/
50 GetMaskFromEvent(DWORD Event
)
54 if ( Event
> EVENT_OBJECT_STATECHANGE
)
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
;
62 if ( Event
== EVENT_OBJECT_STATECHANGE
) return SRV_EVENT_STATECHANGE
;
64 Ret
= SRV_EVENT_RUNNING
;
66 if ( Event
< EVENT_SYSTEM_MENUSTART
) return SRV_EVENT_CREATE
;
68 if ( Event
<= EVENT_SYSTEM_MENUPOPUPEND
)
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
;
91 WCHAR ModuleName
[MAX_PATH
];
92 UNICODE_STRING USModuleName
;
96 if (0 == GetModuleFileNameW(hMod
, ModuleName
, MAX_PATH
))
100 RtlInitUnicodeString(&USModuleName
, ModuleName
);
104 RtlInitUnicodeString(&USModuleName
, NULL
);
107 return NtUserSetWindowsHookEx(hMod
, &USModuleName
, dwThreadId
, idHook
, lpfn
, bAnsi
);
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.
127 ne
.idObject
= idObject
;
128 ne
.idChild
= idChild
;
130 if (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
))
131 NtUserxNotifyWinEvent(hwnd
, &ne
);
134 /* FUNCTIONS *****************************************************************/
158 if ( NtCurrentTeb()->Win32ThreadInfo
&&
159 (ISITHOOKED(WH_MSGFILTER
) || ISITHOOKED(WH_SYSMSGFILTER
)) )
161 if ( lpMsg
->message
& ~WM_MAXIMUM
)
163 SetLastError(ERROR_INVALID_PARAMETER
);
166 RtlCopyMemory(&Msg
, lpMsg
, sizeof(MSG
));
167 return NtUserCallMsgFilter( &Msg
, nCode
);
183 if ( NtCurrentTeb()->Win32ThreadInfo
&&
184 (ISITHOOKED(WH_MSGFILTER
) || ISITHOOKED(WH_SYSMSGFILTER
)) )
186 if ( lpMsg
->message
& ~WM_MAXIMUM
)
188 SetLastError(ERROR_INVALID_PARAMETER
);
191 RtlCopyMemory(&Msg
, lpMsg
, sizeof(MSG
));
192 return NtUserCallMsgFilter( &Msg
, nCode
);
204 HHOOK Hook
, // Windows NT/XP/2003: Ignored.
209 PCLIENTINFO ClientInfo
;
211 PHOOK pHook
, phkNext
;
216 ClientInfo
= GetWin32ClientInfo();
218 if (!ClientInfo
->phkCurrent
) return 0;
220 pHook
= DesktopPtrToUser(ClientInfo
->phkCurrent
);
222 if (!pHook
->phkNext
) return 0; // Nothing to do....
224 phkNext
= DesktopPtrToUser(pHook
->phkNext
);
226 if ( phkNext
->HookId
== WH_CALLWNDPROC
||
227 phkNext
->HookId
== WH_CALLWNDPROCRET
)
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
;
236 if (phkNext
->HookId
== WH_CALLWNDPROC
)
238 PCWPSTRUCT pCWP
= (PCWPSTRUCT
)lParam
;
240 NtUserMessageCall( pCWP
->hwnd
,
250 PCWPRETSTRUCT pCWPR
= (PCWPRETSTRUCT
)lParam
;
252 ClientInfo
->dwHookData
= pCWPR
->lResult
;
254 NtUserMessageCall( pCWPR
->hwnd
,
262 ClientInfo
->CI_flags
^= ((ClientInfo
->CI_flags
^ Flags
) & CI_CURTHPRHOOK
);
263 ClientInfo
->dwHookData
= Save
;
266 lResult
= NtUserCallNextHookEx(Code
, wParam
, lParam
, pHook
->Ansi
);
277 SetWindowsHookW(int idHook
, HOOKPROC lpfn
)
279 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
280 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, FALSE
);
281 // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
289 SetWindowsHookA(int idHook
, HOOKPROC lpfn
)
291 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
292 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, TRUE
);
293 // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
301 DeregisterShellHookWindow(HWND hWnd
)
303 return NtUserxDeregisterShellHookWindow(hWnd
);
311 RegisterShellHookWindow(HWND hWnd
)
313 return NtUserxRegisterShellHookWindow(hWnd
);
321 UnhookWindowsHook ( int nCode
, HOOKPROC pfnFilterProc
)
323 return NtUserxUnhookWindowsHook(nCode
, pfnFilterProc
);
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
);
353 HMODULE hmodWinEventProc
,
354 WINEVENTPROC pfnWinEventProc
,
360 WCHAR ModuleName
[MAX_PATH
];
361 UNICODE_STRING USModuleName
;
363 if ((hmodWinEventProc
!= NULL
) && (dwFlags
& WINEVENT_INCONTEXT
))
365 if (0 == GetModuleFileNameW(hmodWinEventProc
, ModuleName
, MAX_PATH
))
369 RtlInitUnicodeString(&USModuleName
, ModuleName
);
373 RtlInitUnicodeString(&USModuleName
, NULL
);
376 return NtUserSetWinEventHook(eventMin
,
391 IsWinEventHookInstalled(
394 if ((PTHREADINFO
)NtCurrentTeb()->Win32ThreadInfo
)
396 return (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
)) != 0;
412 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, TRUE
);
427 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, FALSE
);
431 User32CallHookProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
433 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
435 CBT_CREATEWNDW CbtCreatewndw
;
436 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
437 KBDLLHOOKSTRUCT KeyboardLlData
, *pKeyboardLlData
;
438 MSLLHOOKSTRUCT MouseLlData
, *pMouseLlData
;
440 PMOUSEHOOKSTRUCT pMHook
;
441 CWPSTRUCT CWP
, *pCWP
;
442 CWPRETSTRUCT CWPR
, *pCWPR
;
444 LPCBTACTIVATESTRUCT pcbtas
;
450 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Arguments
;
452 switch(Common
->HookId
)
456 //ERR("WH_CBT: Code %d\n", Common->Code);
460 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
)
461 ((PCHAR
) Common
+ Common
->lParam
);
462 RtlCopyMemory(&Csw
, &CbtCreatewndExtra
->Cs
, sizeof(CREATESTRUCTW
));
463 CbtCreatewndw
.lpcs
= &Csw
;
464 CbtCreatewndw
.hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
465 wParam
= Common
->wParam
;
466 lParam
= (LPARAM
) &CbtCreatewndw
;
467 //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass);
469 case HCBT_CLICKSKIPPED
:
470 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
471 lParam
= (LPARAM
) pMHook
;
474 prl
= (PRECTL
)((PCHAR
) Common
+ Common
->lParam
);
475 lParam
= (LPARAM
) prl
;
478 pcbtas
= (LPCBTACTIVATESTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
479 lParam
= (LPARAM
) pcbtas
;
481 case HCBT_KEYSKIPPED
: /* The rest SEH support */
484 case HCBT_SYSCOMMAND
:
485 case HCBT_DESTROYWND
:
487 wParam
= Common
->wParam
;
488 lParam
= Common
->lParam
;
491 ERR("HCBT_ not supported = %d\n", Common
->Code
);
492 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
499 Result
= Common
->Proc(Common
->Code
, wParam
, lParam
);
501 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
509 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common
,Common
->Proc
);
514 CbtCreatewndExtra
->WndInsertAfter
= CbtCreatewndw
.hwndInsertAfter
;
515 CbtCreatewndExtra
->Cs
.x
= CbtCreatewndw
.lpcs
->x
;
516 CbtCreatewndExtra
->Cs
.y
= CbtCreatewndw
.lpcs
->y
;
517 CbtCreatewndExtra
->Cs
.cx
= CbtCreatewndw
.lpcs
->cx
;
518 CbtCreatewndExtra
->Cs
.cy
= CbtCreatewndw
.lpcs
->cy
;
524 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
525 pKeyboardLlData
= (PKBDLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
526 RtlCopyMemory(&KeyboardLlData
, pKeyboardLlData
, sizeof(KBDLLHOOKSTRUCT
));
527 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &KeyboardLlData
);
530 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
531 pMouseLlData
= (PMSLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
532 RtlCopyMemory(&MouseLlData
, pMouseLlData
, sizeof(MSLLHOOKSTRUCT
));
533 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &MouseLlData
);
535 case WH_MOUSE
: /* SEH support */
536 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
539 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) pMHook
);
541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
548 // ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
549 pCWP
= (PCWPSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
550 RtlCopyMemory(&CWP
, pCWP
, sizeof(CWPSTRUCT
));
551 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWP
);
553 case WH_CALLWNDPROCRET
:
554 pCWPR
= (PCWPRETSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
555 RtlCopyMemory(&CWPR
, pCWPR
, sizeof(CWPRETSTRUCT
));
556 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWPR
);
558 case WH_MSGFILTER
: /* All SEH support */
559 case WH_SYSMSGFILTER
:
561 pMsg
= (PMSG
)((PCHAR
) Common
+ Common
->lParam
);
562 pcMsg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MSG
));
563 RtlCopyMemory(pcMsg
, pMsg
, sizeof(MSG
));
564 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
567 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) pcMsg
);
569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
574 if (!Hit
&& Common
->HookId
== WH_GETMESSAGE
)
575 RtlCopyMemory(pMsg
, pcMsg
, sizeof(MSG
));
576 HeapFree( GetProcessHeap(), 0, pcMsg
);
580 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, Common
->lParam
);
582 case WH_FOREGROUNDIDLE
: /* <-- SEH support */
585 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, Common
->lParam
);
587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
594 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
598 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common
->HookId
,Common
->Code
,Common
->Proc
);
600 return ZwCallbackReturn(&Result
, sizeof(LRESULT
), STATUS_SUCCESS
);
604 User32CallEventProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
606 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
608 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Arguments
;
610 Common
->Proc(Common
->hook
,
615 Common
->dwEventThread
,
616 Common
->dwmsEventTime
);
618 return ZwCallbackReturn(NULL
, 0, STATUS_SUCCESS
);