Author: jimtabor
Date: Fri Aug 1 19:38:01 2008
New Revision: 35022
URL:
http://svn.reactos.org/svn/reactos?rev=35022&view=rev
Log:
- Implemented NotifyWinEvent, SetWinEventHook and UnhookWinEvent.
- I only enables test_winevents(), test_set_hook() and all related with wine Msg tests.
The test takes a while to run due to the IsWinEventHookInstalled check. I optimized our
mask set to take this into account. The results are, the test is slow and our code is
fast.
- We pass all Event and Local Hook tests. Will research the problem with global hooks and
finish it up.
Modified:
trunk/reactos/subsystems/win32/win32k/include/window.h
trunk/reactos/subsystems/win32/win32k/ntuser/event.c
trunk/reactos/subsystems/win32/win32k/ntuser/hook.c
trunk/reactos/subsystems/win32/win32k/ntuser/window.c
Modified: trunk/reactos/subsystems/win32/win32k/include/window.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/window.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/window.h [iso-8859-1] Fri Aug 1
19:38:01 2008
@@ -167,6 +167,8 @@
LRESULT FASTCALL
IntDefWindowProc( PWINDOW_OBJECT Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL
Ansi);
+VOID FASTCALL IntNotifyWinEvent(DWORD, PWINDOW_OBJECT, LONG, LONG);
+
#endif /* _WIN32K_WINDOW_H */
/* EOF */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/event.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/event.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/event.c [iso-8859-1] Fri Aug 1 19:38:01
2008
@@ -4,9 +4,14 @@
#define NDEBUG
#include <debug.h>
+typedef struct _EVENTPACK
+{
+ PEVENTHOOK pEH;
+ LONG idObject;
+ LONG idChild;
+} EVENTPACK, *PEVENTPACK;
+
static PEVENTTABLE GlobalEvents = NULL;
-static ULONG EventSys[EVENT_SYSTEM_MINIMIZEEND+1] = {0};
-static ULONG EventObj[( EVENT_OBJECT_ACCELERATORCHANGE - EVENT_OBJECT_CREATE) +1] = {0};
/* PRIVATE FUNCTIONS *********************************************************/
@@ -47,92 +52,38 @@
static
VOID
FASTCALL
-IntEventUpCount(ULONG eventMin, ULONG eventMax)
-{
- INT i, Min, Max;
-
- if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <=
EVENT_SYSTEM_MINIMIZEEND)
- {
- for (i = eventMin; i < eventMax; i++)
- {
- gpsi->SrvEventActivity |= GetMaskFromEvent(i);
- EventSys[i]++;
- }
- }
- if ( eventMin >= EVENT_OBJECT_CREATE && eventMax <=
EVENT_OBJECT_ACCELERATORCHANGE)
- {
- for (i = eventMin; i < eventMax; i++)
- {
- gpsi->SrvEventActivity |= GetMaskFromEvent(i);
- EventObj[i - EVENT_OBJECT_CREATE]++;
- }
- }
- if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <=
EVENT_OBJECT_ACCELERATORCHANGE)
- {
- Max = EVENT_SYSTEM_MINIMIZEEND;
- for (i = eventMin; i < Max; i++)
- {
- gpsi->SrvEventActivity |= GetMaskFromEvent(i);
- EventSys[i]++;
- }
- Min = EVENT_OBJECT_CREATE;
- for (i = Min; i < eventMax; i++)
- {
- gpsi->SrvEventActivity |= GetMaskFromEvent(i);
- EventObj[i - EVENT_OBJECT_CREATE]++;
- }
- }
-}
-
-static
-VOID
-FASTCALL
-IntEventDownCount(ULONG eventMin, ULONG eventMax)
-{
- INT i, Min, Max;
-
- if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <=
EVENT_SYSTEM_MINIMIZEEND)
- {
- for (i = eventMin; i < eventMax; i++)
- {
- EventSys[i]--;
- if (!EventSys[i]) gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
- }
- }
- if ( eventMin >= EVENT_OBJECT_CREATE && eventMax <=
EVENT_OBJECT_ACCELERATORCHANGE)
- {
- for (i = eventMin; i < eventMax; i++)
- {
- EventObj[i - EVENT_OBJECT_CREATE]--;
- if (!EventObj[i - EVENT_OBJECT_CREATE])
- gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
- }
- }
- if ( eventMin >= EVENT_SYSTEM_SOUND && eventMax <=
EVENT_OBJECT_ACCELERATORCHANGE)
- {
- Max = EVENT_SYSTEM_MINIMIZEEND;
- for (i = eventMin; i < Max; i++)
- {
- EventSys[i]--;
- if (!EventSys[i]) gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
- }
- Min = EVENT_OBJECT_CREATE;
- for (i = Min; i < eventMax; i++)
- {
- EventObj[i - EVENT_OBJECT_CREATE]--;
- if (!EventObj[i - EVENT_OBJECT_CREATE])
- gpsi->SrvEventActivity &= ~GetMaskFromEvent(i);
- }
- }
-}
-
-
-static
-DWORD
-FASTCALL
-TimeStamp(VOID)
-{
- return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated *
SharedUserData->TickCountMultiplier / 16777216);
+IntSetSrvEventMask( UINT EventMin, UINT EventMax)
+{
+ UINT event;
+ DPRINT("SetSrvEventMask 1\n");
+ for ( event = EventMin; event <= EventMax; event++)
+ {
+ if ((event >= EVENT_SYSTEM_SOUND && event <=
EVENT_SYSTEM_MINIMIZEEND) ||
+ (event >= EVENT_CONSOLE_CARET && event <=
EVENT_CONSOLE_END_APPLICATION) ||
+ (event >= EVENT_OBJECT_CREATE && event <=
EVENT_OBJECT_ACCELERATORCHANGE))
+ {
+ gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ }
+ if (event > EVENT_SYSTEM_MINIMIZEEND && event < EVENT_CONSOLE_CARET)
+ {
+ event = EVENT_CONSOLE_CARET-1;
+ gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ }
+ if (event > EVENT_CONSOLE_END_APPLICATION && event <
EVENT_OBJECT_CREATE )
+ {
+ event = EVENT_OBJECT_CREATE-1;
+ gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ }
+ if (event > EVENT_OBJECT_ACCELERATORCHANGE && event < EVENT_MAX)
+ {
+ event = EVENT_MAX-1;
+ gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+ break;
+ }
+ }
+ if (!gpsi->SrvEventActivity)
+ gpsi->SrvEventActivity |= SRV_EVENT_RUNNING; // Set something.
+ DPRINT("SetSrvEventMask 2 : %x\n", gpsi->SrvEventActivity);
}
static
@@ -146,14 +97,19 @@
{
NTSTATUS Status;
ULONG_PTR uResult;
+ EVENTPACK EP;
+
+ EP.pEH = pEH;
+ EP.idObject = idObject;
+ EP.idChild = idChild;
/* FIXME should get timeout from
* HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
Status =
co_MsqSendMessage(((PW32THREAD)pEH->Thread->Tcb.Win32Thread)->MessageQueue,
hwnd,
event,
- idObject,
- idChild,
+ 0,
+ (LPARAM)&EP,
5000,
TRUE,
MSQ_ISEVENT,
@@ -162,6 +118,7 @@
return NT_SUCCESS(Status) ? uResult : 0;
}
+
static
BOOL
FASTCALL
@@ -171,6 +128,7 @@
{
RemoveEntryList(&pEH->Chain);
GlobalEvents->Counts--;
+ if (!GlobalEvents->Counts) gpsi->SrvEventActivity = 0;
UserDeleteObject(pEH->Self, otEvent);
return TRUE;
}
@@ -186,30 +144,73 @@
LONG idObject,
LONG idChild)
{
-
- PEVENTHOOK pEH = UserHeapAlloc(sizeof(EVENTHOOK));
-
- if ((gpsi->SrvEventActivity & GetMaskFromEvent(event))) return 0; // No events
to run.
-
-
- if ((pEH->Thread != PsGetCurrentThread()) && (pEH->Thread != NULL))
- {
- // Post it in message queue.
- return IntCallLowLevelEvent(pEH, event, hwnd, idObject, idChild);
- }
-
-
- LRESULT Result = co_IntCallEventProc(pEH->Self,
- event,
- hwnd,
- idObject,
- idChild,
- (DWORD)(NtCurrentTeb()->Cid).UniqueThread,
- TimeStamp(),
- pEH->Proc);
+ PEVENTHOOK pEH;
+ LRESULT Result;
+ PEVENTPACK pEP = (PEVENTPACK)idChild;
+
+ pEH = pEP->pEH;
+
+ Result = co_IntCallEventProc( pEH->Self,
+ event,
+ hwnd,
+ pEP->idObject,
+ pEP->idChild,
+ (DWORD)(NtCurrentTeb()->Cid).UniqueThread,
+ (DWORD)EngGetTickCount(),
+ pEH->Proc);
return Result;
}
+VOID
+FASTCALL
+IntNotifyWinEvent(
+ DWORD Event,
+ PWINDOW_OBJECT Window,
+ LONG idObject,
+ LONG idChild)
+{
+ PEVENTHOOK pEH;
+ LRESULT Result;
+
+ if (!GlobalEvents->Counts) return;
+
+ pEH = (PEVENTHOOK)GlobalEvents->Events.Flink;
+
+ do
+ {
+ UserReferenceObject(pEH);
+ // Must be inside the event window.
+ if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
+ {
+ if ((pEH->Thread != PsGetCurrentThread()) && (pEH->Thread !=
NULL))
+ { // if all process || all thread || other thread same process
+ if (!(pEH->idProcess) || !(pEH->idThread) ||
+ ((DWORD)(NtCurrentTeb()->Cid).UniqueProcess == pEH->idProcess))
+ {
+ Result = IntCallLowLevelEvent(pEH, Event, Window->hSelf, idObject,
idChild);
+ }
+ }// if ^skip own thread && ((Pid && CPid == Pid && ^skip
own process) || all process)
+ else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
+ ( ((pEH->idProcess &&
+ (DWORD)(NtCurrentTeb()->Cid).UniqueProcess == pEH->idProcess)
&&
+ !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
+ !pEH->idProcess ) )
+ {
+ Result = co_IntCallEventProc( pEH->Self,
+ Event,
+ Window->hSelf,
+ idObject,
+ idChild,
+ (DWORD)(NtCurrentTeb()->Cid).UniqueThread,
+ (DWORD)EngGetTickCount(),
+ pEH->Proc);
+ }
+ }
+ UserDereferenceObject(pEH);
+
+ pEH = (PEVENTHOOK)pEH->Chain.Flink;
+ } while (pEH != (PEVENTHOOK)&GlobalEvents->Events.Flink);
+}
VOID
STDCALL
@@ -219,8 +220,22 @@
LONG idObject,
LONG idChild)
{
+ PWINDOW_OBJECT Window = NULL;
+ USER_REFERENCE_ENTRY Ref;
UserEnterExclusive();
- UNIMPLEMENTED
+
+ /* Validate input */
+ if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window =
UserGetWindowObject(hWnd)))
+ {
+ return;
+ }
+
+ if (gpsi->SrvEventActivity & GetMaskFromEvent(Event))
+ {
+ UserRefObjectCo(Window, &Ref);
+ IntNotifyWinEvent( Event, Window, idObject, idChild);
+ UserDerefObjectCo(Window);
+ }
UserLeave();
}
@@ -241,10 +256,9 @@
UNICODE_STRING ModuleName;
NTSTATUS Status;
HANDLE Handle;
+ PETHREAD Thread = NULL;
UserEnterExclusive();
-
- DPRINT1("WARNING! Use at your own risk! Function is UNIMPLEMENTED!\n");
if ( !GlobalEvents )
{
@@ -253,6 +267,34 @@
InitializeListHead(&GlobalEvents->Events);
}
+ if (eventMin > eventMax)
+ {
+ SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
+ goto SetEventExit;
+ }
+
+ if (!lpfnWinEventProc)
+ {
+ SetLastWin32Error(ERROR_INVALID_FILTER_PROC);
+ goto SetEventExit;
+ }
+
+ if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc)
+ {
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+ goto SetEventExit;
+ }
+
+ if (idThread)
+ {
+ Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_THREAD_ID);
+ goto SetEventExit;
+ }
+ }
+
pEH = UserCreateObject(gHandleTable, &Handle, otEvent, sizeof(EVENTHOOK));
if (pEH)
{
@@ -260,7 +302,10 @@
GlobalEvents->Counts++;
pEH->Self = Handle;
- pEH->Thread = PsGetCurrentThread();
+ if (Thread)
+ pEH->Thread = Thread;
+ else
+ pEH->Thread = PsGetCurrentThread();
pEH->eventMin = eventMin;
pEH->eventMax = eventMax;
pEH->idProcess = idProcess;
@@ -268,21 +313,13 @@
pEH->Ansi = FALSE;
pEH->Flags = dwflags;
- if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc)
- {
- SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
- goto SetEventExit;
- }
-
- if (eventMin > eventMax)
- {
- SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
- goto SetEventExit;
- }
if (NULL != hmodWinEventProc)
{
- Status = MmCopyFromCaller(&ModuleName, puString, sizeof(UNICODE_STRING));
+ Status = MmCopyFromCaller(&ModuleName,
+ puString,
+ sizeof(UNICODE_STRING));
+
if (! NT_SUCCESS(Status))
{
UserDereferenceObject(pEH);
@@ -290,9 +327,11 @@
SetLastNtError(Status);
goto SetEventExit;
}
+
pEH->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
ModuleName.MaximumLength,
TAG_HOOK);
+
if (NULL == pEH->ModuleName.Buffer)
{
UserDereferenceObject(pEH);
@@ -300,10 +339,13 @@
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
goto SetEventExit;
}
+
pEH->ModuleName.MaximumLength = ModuleName.MaximumLength;
+
Status = MmCopyFromCaller(pEH->ModuleName.Buffer,
ModuleName.Buffer,
ModuleName.MaximumLength);
+
if (! NT_SUCCESS(Status))
{
ExFreePool(pEH->ModuleName.Buffer);
@@ -312,24 +354,23 @@
SetLastNtError(Status);
goto SetEventExit;
}
+
pEH->ModuleName.Length = ModuleName.Length;
+
pEH->Proc = (void *)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
}
else
pEH->Proc = lpfnWinEventProc;
Ret = Handle;
- /*
- Now we are good, set the Events and counts.
- */
- IntEventUpCount(eventMin, eventMax);
+ IntSetSrvEventMask( eventMin, eventMax);
}
SetEventExit:
+ if (Thread) ObDereferenceObject(Thread);
UserLeave();
return Ret;
}
-
BOOL
STDCALL
@@ -341,12 +382,9 @@
UserEnterExclusive();
- DPRINT1("WARNING! Use at your own risk! Function is UNIMPLEMENTED!\n");
-
pEH = (PEVENTHOOK)UserGetObject(gHandleTable, hWinEventHook, otEvent);
if (pEH)
{
- IntEventDownCount(pEH->eventMin, pEH->eventMax);
Ret = IntRemoveEvent(pEH);
}
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/hook.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/hook.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/hook.c [iso-8859-1] Fri Aug 1 19:38:01
2008
@@ -974,9 +974,15 @@
DPRINT("Enter NtUserSetWindowsHookEx\n");
UserEnterExclusive();
- if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId || NULL == HookProc)
+ if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( NULL);
+ }
+
+ if (!HookProc)
+ {
+ SetLastWin32Error(ERROR_INVALID_FILTER_PROC);
RETURN( NULL);
}
@@ -1029,7 +1035,7 @@
}
else if (NULL == Mod)
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
RETURN( NULL);
}
else
@@ -1039,10 +1045,7 @@
Global = TRUE;
}
- /* We only (partially) support local WH_CBT hooks and
- * WH_KEYBOARD_LL, WH_MOUSE_LL and WH_GETMESSAGE hooks for now
- */
- if (Global ||
+ if ( Global ||
WH_DEBUG == HookId ||
WH_JOURNALPLAYBACK == HookId ||
WH_JOURNALRECORD == HookId)
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Fri Aug 1 19:38:01
2008
@@ -2059,7 +2059,7 @@
RETURN((HWND)0);
}
#if 0
- Result = co_EVENT_CallEvents(EVENT_OBJECT_CREATE, Window->hSelf, OBJID_WINDOW, 0);
+ Result = IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0);
if (Result == (LRESULT)-1)
{