From 76dd22c3e52f06b45125366e1ea76f91562e493e Mon Sep 17 00:00:00 2001 From: James Tabor Date: Thu, 17 Apr 2008 01:48:34 +0000 Subject: [PATCH] Adding support for Event hooks. Start using the server info structure and pass the pointer to the user with kernel to user correction. svn path=/trunk/; revision=32993 --- reactos/dll/win32/user32/misc/dllmain.c | 4 + reactos/dll/win32/user32/windows/hook.c | 28 +++- reactos/include/reactos/win32k/callback.h | 22 +++- reactos/include/reactos/win32k/ntuser.h | 4 +- .../win32/win32k/include/callback.h | 10 ++ .../subsystems/win32/win32k/include/hook.h | 20 +++ .../subsystems/win32/win32k/ntuser/callback.c | 65 +++++++++ .../subsystems/win32/win32k/ntuser/event.c | 124 ++++++++++++++++++ reactos/subsystems/win32/win32k/ntuser/hook.c | 85 +----------- .../subsystems/win32/win32k/ntuser/ntstubs.c | 13 -- .../subsystems/win32/win32k/ntuser/window.c | 4 +- reactos/subsystems/win32/win32k/win32k.rbuild | 1 + 12 files changed, 275 insertions(+), 105 deletions(-) create mode 100644 reactos/subsystems/win32/win32k/ntuser/event.c diff --git a/reactos/dll/win32/user32/misc/dllmain.c b/reactos/dll/win32/user32/misc/dllmain.c index 1682c8e667b..63c10d8bc60 100644 --- a/reactos/dll/win32/user32/misc/dllmain.c +++ b/reactos/dll/win32/user32/misc/dllmain.c @@ -8,6 +8,7 @@ PUSER_HANDLE_TABLE gHandleTable = NULL; PUSER_HANDLE_ENTRY gHandleEntries = NULL; PW32PROCESSINFO g_pi = NULL; /* User Mode Pointer */ PW32PROCESSINFO g_kpi = NULL; /* Kernel Mode Pointer */ +PSERVERINFO g_psi = NULL; PW32PROCESSINFO GetW32ProcessInfo(VOID); @@ -56,9 +57,12 @@ Init(VOID) (PVOID)User32SetupDefaultCursors; NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_HOOKPROC] = (PVOID)User32CallHookProcFromKernel; + NtCurrentTeb()->ProcessEnvironmentBlock->KernelCallbackTable[USER32_CALLBACK_EVENTPROC] = + (PVOID)User32CallEventProcFromKernel; g_pi = GetW32ProcessInfo(); g_kpi = SharedPtrToKernel(g_pi); + g_psi = SharedPtrToUser(g_pi->psi); gHandleTable = SharedPtrToUser(g_pi->UserHandleTable); gHandleEntries = SharedPtrToUser(gHandleTable->handles); diff --git a/reactos/dll/win32/user32/windows/hook.c b/reactos/dll/win32/user32/windows/hook.c index f1ddbd0465a..227223fedf7 100644 --- a/reactos/dll/win32/user32/windows/hook.c +++ b/reactos/dll/win32/user32/windows/hook.c @@ -33,8 +33,7 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(user32); - -DWORD Bogus_SrvEventActivity = 0; // Fixme, need to ref to share data. +extern PSERVERINFO g_psi; /* PRIVATE FUNCTIONS *********************************************************/ @@ -263,7 +262,7 @@ NotifyWinEvent( // "Servers call NotifyWinEvent to announce the event to the system after the // event has occurred; they must never notify the system of an event before // the event has occurred." msdn on NotifyWinEvent. - if (Bogus_SrvEventActivity & GetMaskFromEvent(event)) // Check to see. + if (g_psi->SrvEventActivity & GetMaskFromEvent(event)) // Check to see. NtUserNotifyWinEvent(event, hwnd, idObject, idChild); } @@ -318,7 +317,7 @@ IsWinEventHookInstalled( { if ((PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo) { - return (Bogus_SrvEventActivity & GetMaskFromEvent(event)) != 0; + return (g_psi->SrvEventActivity & GetMaskFromEvent(event)) != 0; } return FALSE; } @@ -454,3 +453,24 @@ User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength) return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); } + +NTSTATUS STDCALL +User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PEVENTPROC_CALLBACK_ARGUMENTS Common; + + Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Arguments; + + Common->Proc(Common->hook, + Common->event, + Common->hwnd, + Common->idObject, + Common->idChild, + Common->dwEventThread, + Common->dwmsEventTime); + + return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS); +} + + + diff --git a/reactos/include/reactos/win32k/callback.h b/reactos/include/reactos/win32k/callback.h index a3d63400409..903a457bab7 100644 --- a/reactos/include/reactos/win32k/callback.h +++ b/reactos/include/reactos/win32k/callback.h @@ -6,7 +6,8 @@ #define USER32_CALLBACK_LOADSYSMENUTEMPLATE (2) #define USER32_CALLBACK_LOADDEFAULTCURSORS (3) #define USER32_CALLBACK_HOOKPROC (4) -#define USER32_CALLBACK_MAXIMUM (4) +#define USER32_CALLBACK_EVENTPROC (5) +#define USER32_CALLBACK_MAXIMUM (5) typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS { @@ -50,6 +51,23 @@ typedef struct _HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS /* WCHAR szClass[] */ } HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS, *PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS; +typedef VOID (*WINEVENTPROC)(HWINEVENTHOOK,DWORD,HWND,LONG,LONG,DWORD,DWORD); + +typedef struct _EVENTPROC_CALLBACK_ARGUMENTS +{ + HWINEVENTHOOK hook; + DWORD event; + HWND hwnd; + LONG idObject; + LONG idChild; + DWORD dwEventThread; + DWORD dwmsEventTime; + WINEVENTPROC Proc; + BOOLEAN Ansi; + UINT ModuleNameLength; + WCHAR ModuleName[1]; +} EVENTPROC_CALLBACK_ARGUMENTS, *PEVENTPROC_CALLBACK_ARGUMENTS; + NTSTATUS STDCALL User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength); NTSTATUS STDCALL @@ -60,5 +78,7 @@ NTSTATUS STDCALL User32SetupDefaultCursors(PVOID Arguments, ULONG ArgumentLength); NTSTATUS STDCALL User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32CallEventProcFromKernel(PVOID Arguments, ULONG ArgumentLength); #endif /* __INCLUDE_USER32_CALLBACK_H */ diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index b6701758342..4dd7f32f768 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -1679,7 +1679,7 @@ NtUserNotifyProcessCreate( DWORD dwUnknown3, DWORD dwUnknown4); -DWORD +VOID NTAPI NtUserNotifyWinEvent( DWORD Event, @@ -2345,7 +2345,7 @@ NTAPI NtUserUnhookWindowsHookEx( HHOOK Hook); -DWORD +BOOL NTAPI NtUserUnhookWinEvent( HWINEVENTHOOK hWinEventHook); diff --git a/reactos/subsystems/win32/win32k/include/callback.h b/reactos/subsystems/win32/win32k/include/callback.h index 99ac6ebfd7f..f9ca3cc15c8 100644 --- a/reactos/subsystems/win32/win32k/include/callback.h +++ b/reactos/subsystems/win32/win32k/include/callback.h @@ -35,6 +35,16 @@ co_IntCallHookProc(INT HookId, BOOLEAN Ansi, PUNICODE_STRING ModuleName); +LRESULT STDCALL +co_IntCallEventProc(HWINEVENTHOOK hook, + DWORD event, + HWND hwnd, + LONG idObject, + LONG idChild, + DWORD dwEventThread, + DWORD dwmsEventTime, + WINEVENTPROC Proc); + VOID FASTCALL IntCleanupThreadCallbacks(PW32THREAD W32Thread); diff --git a/reactos/subsystems/win32/win32k/include/hook.h b/reactos/subsystems/win32/win32k/include/hook.h index 1c160e0d768..2eb0aca6cf9 100644 --- a/reactos/subsystems/win32/win32k/include/hook.h +++ b/reactos/subsystems/win32/win32k/include/hook.h @@ -23,7 +23,27 @@ typedef struct tagHOOKTABLE UINT Counts[NB_HOOKS]; /* use counts for each hook chain */ } HOOKTABLE, *PHOOKTABLE; +typedef struct tagEVENTHOOK +{ + LIST_ENTRY Chain; /* Event chain entry */ + HWINEVENTHOOK Self; /* user handle for this event */ + PETHREAD Thread; /* Thread owning the event */ + UINT eventMin; + UINT eventMax; + WINEVENTPROC Proc; /* Event function */ + BOOLEAN Ansi; /* Is it an Ansi event? */ + ULONG Flags; /* Some internal flags */ + UNICODE_STRING ModuleName; /* Module name for global events */ +} EVENTHOOK, *PEVENTHOOK; + +typedef struct tagEVENTTABLE +{ + LIST_ENTRY Events; + UINT Counts; +} EVENTTABLE, *PEVENTTABLE; + LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam); +LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, LONG, LONG); VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread); PHOOK FASTCALL IntGetHookObject(HHOOK); diff --git a/reactos/subsystems/win32/win32k/ntuser/callback.c b/reactos/subsystems/win32/win32k/ntuser/callback.c index 0ee8fd9ed26..335d909075a 100644 --- a/reactos/subsystems/win32/win32k/ntuser/callback.c +++ b/reactos/subsystems/win32/win32k/ntuser/callback.c @@ -465,4 +465,69 @@ co_IntCallHookProc(INT HookId, return Result; } +LRESULT +STDCALL +co_IntCallEventProc(HWINEVENTHOOK hook, + DWORD event, + HWND hWnd, + LONG idObject, + LONG idChild, + DWORD dwEventThread, + DWORD dwmsEventTime, + WINEVENTPROC Proc) +{ + LRESULT Result; + NTSTATUS Status; + PEVENTPROC_CALLBACK_ARGUMENTS Common; + ULONG ArgumentLength, ResultLength; + PVOID Argument, ResultPointer, pWnd; + + ArgumentLength = sizeof(EVENTPROC_CALLBACK_ARGUMENTS); + + Argument = IntCbAllocateMemory(ArgumentLength); + if (NULL == Argument) + { + DPRINT1("EventProc callback failed: out of memory\n"); + return 0; + } + Common = (PEVENTPROC_CALLBACK_ARGUMENTS) Argument; + Common->hook = hook; + Common->event = event; + Common->hwnd = hWnd; + Common->idObject = idObject; + Common->idChild = idChild; + Common->dwEventThread = dwEventThread; + Common->dwmsEventTime = dwmsEventTime; + Common->Proc = Proc; + + ResultPointer = NULL; + ResultLength = sizeof(LRESULT); + + IntSetTebWndCallback (&hWnd, &pWnd); + + UserLeaveCo(); + + Status = KeUserModeCallback(USER32_CALLBACK_EVENTPROC, + Argument, + ArgumentLength, + &ResultPointer, + &ResultLength); + + /* Simulate old behaviour: copy into our local buffer */ + Result = *(LRESULT*)ResultPointer; + + UserEnterCo(); + + IntRestoreTebWndCallback (hWnd, pWnd); + + IntCbFreeMemory(Argument); + + if (!NT_SUCCESS(Status)) + { + return 0; + } + + return Result; +} + /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/event.c b/reactos/subsystems/win32/win32k/ntuser/event.c new file mode 100644 index 00000000000..76c34f6a193 --- /dev/null +++ b/reactos/subsystems/win32/win32k/ntuser/event.c @@ -0,0 +1,124 @@ + +#include + +#define NDEBUG +#include + +extern PSERVERINFO gpsi; +//static PEVENTTABLE GlobalEvents; + + +/* PRIVATE FUNCTIONS *********************************************************/ + +static +DWORD +FASTCALL +GetMaskFromEvent(DWORD Event) +{ + DWORD Ret = 0; + + if ( Event > EVENT_OBJECT_STATECHANGE ) + { + if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE; + if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE; + if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE; + return SRV_EVENT_CREATE; + } + + if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE; + + Ret = SRV_EVENT_RUNNING; + + if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE; + + if ( Event <= EVENT_SYSTEM_MENUPOPUPEND ) + { + Ret = SRV_EVENT_MENU; + } + else + { + if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE; + if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION; + if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE; + } + return Ret; +} + + +static +DWORD +FASTCALL +TimeStamp(VOID) +{ + return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated * SharedUserData->TickCountMultiplier / 16777216); +} + +/* FUNCTIONS *****************************************************************/ + +LRESULT +FASTCALL +co_EVENT_CallEvents( DWORD event, + HWND hwnd, + LONG idObject, + LONG idChild) +{ + + PEVENTHOOK peh = UserHeapAlloc(sizeof(EVENTHOOK)); + + if ((gpsi->SrvEventActivity & GetMaskFromEvent(event))) return 0; // No events to run. + + LRESULT Result = co_IntCallEventProc(peh->Self, + event, + hwnd, + idObject, + idChild, + (DWORD)(NtCurrentTeb()->Cid).UniqueThread, + TimeStamp(), + peh->Proc); + return Result; +} + + +VOID +STDCALL +NtUserNotifyWinEvent( + DWORD Event, + HWND hWnd, + LONG idObject, + LONG idChild) +{ + UNIMPLEMENTED +} + +HWINEVENTHOOK +STDCALL +NtUserSetWinEventHook( + UINT eventMin, + UINT eventMax, + HMODULE hmodWinEventProc, + PUNICODE_STRING puString, + WINEVENTPROC lpfnWinEventProc, + DWORD idProcess, + DWORD idThread, + UINT dwflags) +{ + gpsi->SrvEventActivity |= GetMaskFromEvent(eventMin); + gpsi->SrvEventActivity &= ~GetMaskFromEvent(eventMin); + + UNIMPLEMENTED + + return 0; +} + + +BOOL +STDCALL +NtUserUnhookWinEvent( + HWINEVENTHOOK hWinEventHook) +{ + UNIMPLEMENTED + + return FALSE; +} + +/* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/hook.c b/reactos/subsystems/win32/win32k/ntuser/hook.c index 315ca644237..11ef68e8df5 100644 --- a/reactos/subsystems/win32/win32k/ntuser/hook.c +++ b/reactos/subsystems/win32/win32k/ntuser/hook.c @@ -1,26 +1,8 @@ -/* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PURPOSE: Window hooks - * FILE: subsys/win32k/ntuser/hook.c + * FILE: subsystem/win32/win32k/ntuser/hook.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) * REVISION HISTORY: * 06-06-2001 CSH Created @@ -37,44 +19,10 @@ #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1)) static PHOOKTABLE GlobalHooks; -DWORD Bogus_SrvEventActivity = 0; /* PRIVATE FUNCTIONS *********************************************************/ -static -DWORD -FASTCALL -GetMaskFromEvent(DWORD Event) -{ - DWORD Ret = 0; - - if ( Event > EVENT_OBJECT_STATECHANGE ) - { - if ( Event == EVENT_OBJECT_LOCATIONCHANGE ) return SRV_EVENT_LOCATIONCHANGE; - if ( Event == EVENT_OBJECT_NAMECHANGE ) return SRV_EVENT_NAMECHANGE; - if ( Event == EVENT_OBJECT_VALUECHANGE ) return SRV_EVENT_VALUECHANGE; - return SRV_EVENT_CREATE; - } - - if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE; - - Ret = SRV_EVENT_RUNNING; - - if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE; - - if ( Event <= EVENT_SYSTEM_MENUPOPUPEND ) - { - Ret = SRV_EVENT_MENU; - } - else - { - if ( Event <= EVENT_CONSOLE_CARET-1 ) return SRV_EVENT_CREATE; - if ( Event <= EVENT_CONSOLE_END_APPLICATION ) return SRV_EVENT_END_APPLICATION; - if ( Event != EVENT_OBJECT_FOCUS ) return SRV_EVENT_CREATE; - } - return Ret; -} /* create a new hook table */ static PHOOKTABLE @@ -734,25 +682,6 @@ CLEANUP: END_CLEANUP; } -HWINEVENTHOOK -STDCALL -NtUserSetWinEventHook( - UINT eventMin, - UINT eventMax, - HMODULE hmodWinEventProc, - PUNICODE_STRING puString, - WINEVENTPROC lpfnWinEventProc, - DWORD idProcess, - DWORD idThread, - UINT dwflags) -{ - - Bogus_SrvEventActivity |= GetMaskFromEvent(eventMin); // Fake it out for now. - Bogus_SrvEventActivity &= ~GetMaskFromEvent(eventMin); - UNIMPLEMENTED - - return 0; -} BOOL STDCALL @@ -801,15 +730,5 @@ CLEANUP: UserLeave(); END_CLEANUP; } - -DWORD -STDCALL -NtUserUnhookWinEvent( - HWINEVENTHOOK hWinEventHook) -{ - UNIMPLEMENTED - - return 0; -} - + /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c index f6f0795ab65..1d1d1a85532 100644 --- a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c +++ b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c @@ -426,19 +426,6 @@ NtUserNotifyIMEStatus( return 0; } -DWORD -STDCALL -NtUserNotifyWinEvent( - DWORD Event, - HWND hWnd, - LONG idObject, - LONG idChild) -{ - UNIMPLEMENTED - - return 0; -} - DWORD STDCALL NtUserQueryUserCounters( diff --git a/reactos/subsystems/win32/win32k/ntuser/window.c b/reactos/subsystems/win32/win32k/ntuser/window.c index aeed20652a2..7c3b3bc6e59 100644 --- a/reactos/subsystems/win32/win32k/ntuser/window.c +++ b/reactos/subsystems/win32/win32k/ntuser/window.c @@ -2056,7 +2056,7 @@ AllocErr: IntUnlinkWindow(Window); RETURN((HWND)0); } -#if 0 + Result = co_EVENT_CallEvents(EVENT_OBJECT_CREATE, Window->hSelf, OBJID_WINDOW, 0); if (Result == (LRESULT)-1) @@ -2065,7 +2065,7 @@ AllocErr: DPRINT1("IntCreateWindowEx(): event CREATE hook failed. No cleanup performed!\n"); RETURN((HWND)0); } -#endif + /* Send move and size messages. */ if (!(Window->Flags & WINDOWOBJECT_NEED_SIZE)) { diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index 6994b362fde..611e2e079df 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -112,6 +112,7 @@ csr.c cursoricon.c desktop.c + event.c focus.c guicheck.c hook.c