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: lib/user32/windows/input.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 NtUserCallHwndParam(hwnd
, (DWORD
)&ne
, HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT
);
134 /* FUNCTIONS *****************************************************************/
158 if (NtCurrentTeb()->Win32ThreadInfo
&& IsThreadHooked(GetWin32ClientInfo()))
160 if ( lpMsg
->message
& ~WM_MAXIMUM
)
162 SetLastError(ERROR_INVALID_PARAMETER
);
165 RtlCopyMemory(&Msg
, lpMsg
, sizeof(MSG
));
166 return NtUserCallMsgFilter( &Msg
, nCode
);
182 if (NtCurrentTeb()->Win32ThreadInfo
&& IsThreadHooked(GetWin32ClientInfo()))
184 if ( lpMsg
->message
& ~WM_MAXIMUM
)
186 SetLastError(ERROR_INVALID_PARAMETER
);
189 RtlCopyMemory(&Msg
, lpMsg
, sizeof(MSG
));
190 return NtUserCallMsgFilter( &Msg
, nCode
);
202 HHOOK Hook
, // Windows NT/XP/2003: Ignored.
207 PCLIENTINFO ClientInfo
;
209 PHOOK pHook
, phkNext
;
214 ClientInfo
= GetWin32ClientInfo();
216 if (!ClientInfo
->phkCurrent
) return 0;
218 pHook
= DesktopPtrToUser(ClientInfo
->phkCurrent
);
220 if (!pHook
->phkNext
) return 0; // Nothing to do....
222 phkNext
= DesktopPtrToUser(pHook
->phkNext
);
224 if ( phkNext
->HookId
== WH_CALLWNDPROC
||
225 phkNext
->HookId
== WH_CALLWNDPROCRET
)
227 Save
= ClientInfo
->dwHookData
;
228 Flags
= ClientInfo
->CI_flags
& CI_CURTHPRHOOK
;
229 // wParam: If the message was sent by the current thread/process, it is
230 // nonzero; otherwise, it is zero.
231 if (wParam
) ClientInfo
->CI_flags
|= CI_CURTHPRHOOK
;
232 else ClientInfo
->CI_flags
&= ~CI_CURTHPRHOOK
;
234 if (phkNext
->HookId
== WH_CALLWNDPROC
)
236 PCWPSTRUCT pCWP
= (PCWPSTRUCT
)lParam
;
238 NtUserMessageCall( pCWP
->hwnd
,
248 PCWPRETSTRUCT pCWPR
= (PCWPRETSTRUCT
)lParam
;
250 ClientInfo
->dwHookData
= pCWPR
->lResult
;
252 NtUserMessageCall( pCWPR
->hwnd
,
260 ClientInfo
->CI_flags
^= ((ClientInfo
->CI_flags
^ Flags
) & CI_CURTHPRHOOK
);
261 ClientInfo
->dwHookData
= Save
;
264 lResult
= NtUserCallNextHookEx(Code
, wParam
, lParam
, pHook
->Ansi
);
275 SetWindowsHookW(int idHook
, HOOKPROC lpfn
)
277 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
278 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, FALSE
);
279 // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
287 SetWindowsHookA(int idHook
, HOOKPROC lpfn
)
289 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
290 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, TRUE
);
291 // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
299 DeregisterShellHookWindow(HWND hWnd
)
301 return NtUserCallHwnd(hWnd
, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW
);
309 RegisterShellHookWindow(HWND hWnd
)
311 return NtUserCallHwnd(hWnd
, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW
);
319 UnhookWindowsHook ( int nCode
, HOOKPROC pfnFilterProc
)
321 return NtUserCallTwoParam(nCode
, (DWORD_PTR
)pfnFilterProc
, TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK
);
336 // "Servers call NotifyWinEvent to announce the event to the system after the
337 // event has occurred; they must never notify the system of an event before
338 // the event has occurred." msdn on NotifyWinEvent.
339 if (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
)) // Check to see.
340 NtUserNotifyWinEvent(event
, hwnd
, idObject
, idChild
);
351 HMODULE hmodWinEventProc
,
352 WINEVENTPROC pfnWinEventProc
,
358 WCHAR ModuleName
[MAX_PATH
];
359 UNICODE_STRING USModuleName
;
361 if ((hmodWinEventProc
!= NULL
) && (dwFlags
& WINEVENT_INCONTEXT
))
363 if (0 == GetModuleFileNameW(hmodWinEventProc
, ModuleName
, MAX_PATH
))
367 RtlInitUnicodeString(&USModuleName
, ModuleName
);
371 RtlInitUnicodeString(&USModuleName
, NULL
);
374 return NtUserSetWinEventHook(eventMin
,
389 IsWinEventHookInstalled(
392 if ((PTHREADINFO
)NtCurrentTeb()->Win32ThreadInfo
)
394 return (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
)) != 0;
410 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, TRUE
);
425 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, FALSE
);
429 User32CallHookProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
431 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
433 CBT_CREATEWNDW CbtCreatewndw
;
434 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
435 KBDLLHOOKSTRUCT KeyboardLlData
, *pKeyboardLlData
;
436 MSLLHOOKSTRUCT MouseLlData
, *pMouseLlData
;
438 PMOUSEHOOKSTRUCT pMHook
;
439 CWPSTRUCT CWP
, *pCWP
;
440 CWPRETSTRUCT CWPR
, *pCWPR
;
442 LPCBTACTIVATESTRUCT pcbtas
;
448 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Arguments
;
450 switch(Common
->HookId
)
454 //ERR("WH_CBT: Code %d\n", Common->Code);
458 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
)
459 ((PCHAR
) Common
+ Common
->lParam
);
460 RtlCopyMemory(&Csw
, &CbtCreatewndExtra
->Cs
, sizeof(CREATESTRUCTW
));
461 CbtCreatewndw
.lpcs
= &Csw
;
462 CbtCreatewndw
.hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
463 wParam
= Common
->wParam
;
464 lParam
= (LPARAM
) &CbtCreatewndw
;
465 //ERR("HCBT_CREATEWND: hWnd 0x%x Name 0x%x Class 0x%x\n", Common->wParam, Csw.lpszName, Csw.lpszClass);
467 case HCBT_CLICKSKIPPED
:
468 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
469 lParam
= (LPARAM
) pMHook
;
472 prl
= (PRECTL
)((PCHAR
) Common
+ Common
->lParam
);
473 lParam
= (LPARAM
) prl
;
476 pcbtas
= (LPCBTACTIVATESTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
477 lParam
= (LPARAM
) pcbtas
;
479 case HCBT_KEYSKIPPED
: /* The rest SEH support */
482 case HCBT_SYSCOMMAND
:
483 case HCBT_DESTROYWND
:
485 wParam
= Common
->wParam
;
486 lParam
= Common
->lParam
;
489 ERR("HCBT_ not supported = %d\n", Common
->Code
);
490 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
497 Result
= Common
->Proc(Common
->Code
, wParam
, lParam
);
499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
507 ERR("Null Proc! Common = 0x%x, Proc = 0x%x\n",Common
,Common
->Proc
);
512 CbtCreatewndExtra
->WndInsertAfter
= CbtCreatewndw
.hwndInsertAfter
;
513 CbtCreatewndExtra
->Cs
.x
= CbtCreatewndw
.lpcs
->x
;
514 CbtCreatewndExtra
->Cs
.y
= CbtCreatewndw
.lpcs
->y
;
515 CbtCreatewndExtra
->Cs
.cx
= CbtCreatewndw
.lpcs
->cx
;
516 CbtCreatewndExtra
->Cs
.cy
= CbtCreatewndw
.lpcs
->cy
;
522 //ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
523 pKeyboardLlData
= (PKBDLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
524 RtlCopyMemory(&KeyboardLlData
, pKeyboardLlData
, sizeof(KBDLLHOOKSTRUCT
));
525 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &KeyboardLlData
);
528 //ERR("WH_MOUSE_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
529 pMouseLlData
= (PMSLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
530 RtlCopyMemory(&MouseLlData
, pMouseLlData
, sizeof(MSLLHOOKSTRUCT
));
531 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &MouseLlData
);
533 case WH_MOUSE
: /* SEH support */
534 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
537 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) pMHook
);
539 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
546 // ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
547 pCWP
= (PCWPSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
548 RtlCopyMemory(&CWP
, pCWP
, sizeof(CWPSTRUCT
));
549 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWP
);
551 case WH_CALLWNDPROCRET
:
552 pCWPR
= (PCWPRETSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
553 RtlCopyMemory(&CWPR
, pCWPR
, sizeof(CWPRETSTRUCT
));
554 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWPR
);
556 case WH_MSGFILTER
: /* All SEH support */
557 case WH_SYSMSGFILTER
:
559 pMsg
= (PMSG
)((PCHAR
) Common
+ Common
->lParam
);
560 pcMsg
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MSG
));
561 RtlCopyMemory(pcMsg
, pMsg
, sizeof(MSG
));
562 // ERR("pMsg %d pcMsg %d\n",pMsg->message, pcMsg->message);
565 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) pcMsg
);
567 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
572 if (!Hit
&& Common
->HookId
== WH_GETMESSAGE
)
573 RtlCopyMemory(pMsg
, pcMsg
, sizeof(MSG
));
574 HeapFree( GetProcessHeap(), 0, pcMsg
);
578 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, Common
->lParam
);
580 case WH_FOREGROUNDIDLE
: /* <-- SEH support */
583 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, Common
->lParam
);
585 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
592 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
596 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common
->HookId
,Common
->Code
,Common
->Proc
);
598 return ZwCallbackReturn(&Result
, sizeof(LRESULT
), STATUS_SUCCESS
);
602 User32CallEventProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
604 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
606 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Arguments
;
608 Common
->Proc(Common
->hook
,
613 Common
->dwEventThread
,
614 Common
->dwmsEventTime
);
616 return ZwCallbackReturn(NULL
, 0, STATUS_SUCCESS
);