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 *****************************************************************/
159 if (nCode
!= HCBT_CREATEWND
) ret
= NtUserCallMsgFilter((LPMSG
) lpMsg
, nCode
);
162 UNICODE_STRING usBuffer
;
163 CBT_CREATEWNDA
*cbtcwA
= (CBT_CREATEWNDA
*)lpMsg
->lParam
;
164 CBT_CREATEWNDW cbtcwW
;
168 Msg
.hwnd
= lpMsg
->hwnd
;
169 Msg
.message
= lpMsg
->message
;
170 Msg
.time
= lpMsg
->time
;
172 Msg
.wParam
= lpMsg
->wParam
;
175 cbtcwW
.hwndInsertAfter
= cbtcwA
->hwndInsertAfter
;
176 csW
= *(CREATESTRUCTW
*)cbtcwA
->lpcs
;
178 if (HIWORD(cbtcwA
->lpcs
->lpszName
))
180 RtlCreateUnicodeStringFromAsciiz(&usBuffer
,cbtcwA
->lpcs
->lpszName
);
181 csW
.lpszName
= usBuffer
.Buffer
;
183 if (HIWORD(cbtcwA
->lpcs
->lpszClass
))
185 RtlCreateUnicodeStringFromAsciiz(&usBuffer
,cbtcwA
->lpcs
->lpszClass
);
186 csW
.lpszClass
= usBuffer
.Buffer
;
188 Msg
.lParam
=(LPARAM
) &cbtcwW
;
190 ret
= NtUserCallMsgFilter((LPMSG
)&Msg
, nCode
);
192 lpMsg
->time
= Msg
.time
;
195 cbtcwA
->hwndInsertAfter
= cbtcwW
.hwndInsertAfter
;
196 if (HIWORD(csW
.lpszName
)) HeapFree( GetProcessHeap(), 0, (LPWSTR
)csW
.lpszName
);
197 if (HIWORD(csW
.lpszClass
)) HeapFree( GetProcessHeap(), 0, (LPWSTR
)csW
.lpszClass
);
212 return NtUserCallMsgFilter((LPMSG
) lpMsg
, nCode
);
222 HHOOK Hook
, // Windows NT/XP/2003: Ignored.
227 PCLIENTINFO ClientInfo
;
229 PHOOK pHook
, phkNext
;
234 ClientInfo
= GetWin32ClientInfo();
236 if (!ClientInfo
->phkCurrent
) return 0;
238 pHook
= DesktopPtrToUser(ClientInfo
->phkCurrent
);
240 if (!pHook
->phkNext
) return 0; // Nothing to do....
242 phkNext
= DesktopPtrToUser(pHook
->phkNext
);
244 if ( phkNext
->HookId
== WH_CALLWNDPROC
||
245 phkNext
->HookId
== WH_CALLWNDPROCRET
)
247 Save
= ClientInfo
->dwHookData
;
248 Flags
= ClientInfo
->CI_flags
& CI_CURTHPRHOOK
;
249 // wParam: If the message was sent by the current thread/process, it is
250 // nonzero; otherwise, it is zero.
251 if (wParam
) ClientInfo
->CI_flags
|= CI_CURTHPRHOOK
;
252 else ClientInfo
->CI_flags
&= ~CI_CURTHPRHOOK
;
254 if (phkNext
->HookId
== WH_CALLWNDPROC
)
256 PCWPSTRUCT pCWP
= (PCWPSTRUCT
)lParam
;
258 NtUserMessageCall( pCWP
->hwnd
,
268 PCWPRETSTRUCT pCWPR
= (PCWPRETSTRUCT
)lParam
;
270 ClientInfo
->dwHookData
= pCWPR
->lResult
;
272 NtUserMessageCall( pCWPR
->hwnd
,
280 ClientInfo
->CI_flags
^= ((ClientInfo
->CI_flags
^ Flags
) & CI_CURTHPRHOOK
);
281 ClientInfo
->dwHookData
= Save
;
284 lResult
= NtUserCallNextHookEx(Code
, wParam
, lParam
, pHook
->Ansi
);
295 SetWindowsHookW(int idHook
, HOOKPROC lpfn
)
297 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
298 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, FALSE
);
299 // return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
307 SetWindowsHookA(int idHook
, HOOKPROC lpfn
)
309 DWORD ThreadId
= PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
);
310 return IntSetWindowsHook(idHook
, lpfn
, NULL
, ThreadId
, TRUE
);
311 // return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
319 DeregisterShellHookWindow(HWND hWnd
)
321 return NtUserCallHwnd(hWnd
, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW
);
329 RegisterShellHookWindow(HWND hWnd
)
331 return NtUserCallHwnd(hWnd
, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW
);
339 UnhookWindowsHook ( int nCode
, HOOKPROC pfnFilterProc
)
341 return NtUserCallTwoParam(nCode
, (DWORD_PTR
)pfnFilterProc
, TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK
);
356 // "Servers call NotifyWinEvent to announce the event to the system after the
357 // event has occurred; they must never notify the system of an event before
358 // the event has occurred." msdn on NotifyWinEvent.
359 if (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
)) // Check to see.
360 NtUserNotifyWinEvent(event
, hwnd
, idObject
, idChild
);
371 HMODULE hmodWinEventProc
,
372 WINEVENTPROC pfnWinEventProc
,
378 WCHAR ModuleName
[MAX_PATH
];
379 UNICODE_STRING USModuleName
;
381 if ((hmodWinEventProc
!= NULL
) && (dwFlags
& WINEVENT_INCONTEXT
))
383 if (0 == GetModuleFileNameW(hmodWinEventProc
, ModuleName
, MAX_PATH
))
387 RtlInitUnicodeString(&USModuleName
, ModuleName
);
391 RtlInitUnicodeString(&USModuleName
, NULL
);
394 return NtUserSetWinEventHook(eventMin
,
409 IsWinEventHookInstalled(
412 if ((PTHREADINFO
)NtCurrentTeb()->Win32ThreadInfo
)
414 return (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(event
)) != 0;
430 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, TRUE
);
445 return IntSetWindowsHook(idHook
, lpfn
, hMod
, dwThreadId
, FALSE
);
449 User32CallHookProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
451 PHOOKPROC_CALLBACK_ARGUMENTS Common
;
453 CBT_CREATEWNDW CbtCreatewndw
;
454 PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra
= NULL
;
455 KBDLLHOOKSTRUCT KeyboardLlData
, *pKeyboardLlData
;
456 MSLLHOOKSTRUCT MouseLlData
, *pMouseLlData
;
458 PMOUSEHOOKSTRUCT pMHook
;
459 CWPSTRUCT CWP
, *pCWP
;
460 CWPRETSTRUCT CWPR
, *pCWPR
;
462 LPCBTACTIVATESTRUCT pcbtas
;
468 Common
= (PHOOKPROC_CALLBACK_ARGUMENTS
) Arguments
;
470 switch(Common
->HookId
)
477 CbtCreatewndExtra
= (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS
)
478 ((PCHAR
) Common
+ Common
->lParam
);
479 Csw
= CbtCreatewndExtra
->Cs
;
480 Csw
.lpszName
= CbtCreatewndExtra
->Cs
.lpszName
;
481 Csw
.lpszClass
= CbtCreatewndExtra
->Cs
.lpszClass
;
482 wParam
= Common
->wParam
;
483 CbtCreatewndw
.lpcs
= &Csw
;
484 CbtCreatewndw
.hwndInsertAfter
= CbtCreatewndExtra
->WndInsertAfter
;
485 lParam
= (LPARAM
) &CbtCreatewndw
;
487 case HCBT_CLICKSKIPPED
:
488 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
489 lParam
= (LPARAM
) pMHook
;
492 prl
= (PRECTL
)((PCHAR
) Common
+ Common
->lParam
);
493 lParam
= (LPARAM
) prl
;
496 pcbtas
= (LPCBTACTIVATESTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
497 lParam
= (LPARAM
) pcbtas
;
499 case HCBT_KEYSKIPPED
: /* The rest SEH support */
502 case HCBT_SYSCOMMAND
:
503 case HCBT_DESTROYWND
:
505 wParam
= Common
->wParam
;
506 lParam
= Common
->lParam
;
509 ERR("HCBT_ not supported = %d\n", Common
->Code
);
510 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
517 Result
= Common
->Proc(Common
->Code
, wParam
, lParam
);
519 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
527 ERR("Common = 0x%x, Proc = 0x%x\n",Common
,Common
->Proc
);
532 CbtCreatewndExtra
->WndInsertAfter
= CbtCreatewndw
.hwndInsertAfter
;
533 CbtCreatewndExtra
->Cs
.x
= CbtCreatewndw
.lpcs
->x
;
534 CbtCreatewndExtra
->Cs
.y
= CbtCreatewndw
.lpcs
->y
;
535 CbtCreatewndExtra
->Cs
.cx
= CbtCreatewndw
.lpcs
->cx
;
536 CbtCreatewndExtra
->Cs
.cy
= CbtCreatewndw
.lpcs
->cy
;
542 ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common
->Code
,Common
->wParam
);
543 pKeyboardLlData
= (PKBDLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
544 RtlCopyMemory(&KeyboardLlData
, pKeyboardLlData
, sizeof(KBDLLHOOKSTRUCT
));
545 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &KeyboardLlData
);
548 pMouseLlData
= (PMSLLHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
549 RtlCopyMemory(&MouseLlData
, pMouseLlData
, sizeof(MSLLHOOKSTRUCT
));
550 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &MouseLlData
);
552 case WH_MOUSE
: /* SEH support */
553 pMHook
= (PMOUSEHOOKSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
556 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) pMHook
);
558 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
565 ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common
->Code
,Common
->wParam
);
566 pCWP
= (PCWPSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
567 RtlCopyMemory(&CWP
, pCWP
, sizeof(CWPSTRUCT
));
568 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWP
);
570 case WH_CALLWNDPROCRET
:
571 pCWPR
= (PCWPRETSTRUCT
)((PCHAR
) Common
+ Common
->lParam
);
572 RtlCopyMemory(&CWPR
, pCWPR
, sizeof(CWPRETSTRUCT
));
573 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &CWPR
);
575 case WH_MSGFILTER
: /* All SEH support */
576 ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common
->Code
,Common
->wParam
);
577 case WH_SYSMSGFILTER
:
579 pMsg
= (PMSG
)((PCHAR
) Common
+ Common
->lParam
);
580 RtlCopyMemory(&Msg
, pMsg
, sizeof(MSG
));
583 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, (LPARAM
) &Msg
);
585 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
590 if (!Hit
&& Common
->HookId
== WH_GETMESSAGE
)
591 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
593 case WH_FOREGROUNDIDLE
: /* <-- SEH support */
598 Result
= Common
->Proc(Common
->Code
, Common
->wParam
, Common
->lParam
);
600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
607 return ZwCallbackReturn(NULL
, 0, STATUS_NOT_SUPPORTED
);
611 ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common
->HookId
,Common
->Code
,Common
->Proc
);
613 return ZwCallbackReturn(&Result
, sizeof(LRESULT
), STATUS_SUCCESS
);
617 User32CallEventProcFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
619 PEVENTPROC_CALLBACK_ARGUMENTS Common
;
621 Common
= (PEVENTPROC_CALLBACK_ARGUMENTS
) Arguments
;
623 Common
->Proc(Common
->hook
,
628 Common
->dwEventThread
,
629 Common
->dwmsEventTime
);
631 return ZwCallbackReturn(NULL
, 0, STATUS_SUCCESS
);