Author: jimtabor
Date: Thu Jul 31 18:48:35 2008
New Revision: 34988
URL:
http://svn.reactos.org/svn/reactos?rev=34988&view=rev
Log:
- Preliminary implementation of SetWinEventHook and UnhookWinEvent.
- Only wine cross test uses this and testing is not stable.
- Patches are welcome but all code is subject to change.
- All Hook code should be ready by Aug 4th.
Modified:
trunk/reactos/subsystems/win32/win32k/include/hook.h
trunk/reactos/subsystems/win32/win32k/include/msgqueue.h
trunk/reactos/subsystems/win32/win32k/ntuser/event.c
trunk/reactos/subsystems/win32/win32k/ntuser/hook.c
trunk/reactos/subsystems/win32/win32k/ntuser/message.c
trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
Modified: trunk/reactos/subsystems/win32/win32k/include/hook.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/hook.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/hook.h [iso-8859-1] Thu Jul 31 18:48:35
2008
@@ -33,6 +33,8 @@
PETHREAD Thread; /* Thread owning the event */
UINT eventMin;
UINT eventMax;
+ DWORD idProcess;
+ DWORD idThread;
WINEVENTPROC Proc; /* Event function */
BOOLEAN Ansi; /* Is it an Ansi event? */
ULONG Flags; /* Some internal flags */
Modified: trunk/reactos/subsystems/win32/win32k/include/msgqueue.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] Thu Jul 31
18:48:35 2008
@@ -4,6 +4,9 @@
#include "hook.h"
#define MSQ_HUNG 5000
+#define MSQ_NORMAL 0
+#define MSQ_ISHOOK 1
+#define MSQ_ISEVENT 2
typedef struct _USER_MESSAGE
{
@@ -25,7 +28,7 @@
ULONG_PTR CompletionCallbackContext;
/* entry in the dispatching list of the sender's message queue */
LIST_ENTRY DispatchingListEntry;
- BOOL HookMessage;
+ INT HookMessage;
} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE;
typedef struct _USER_SENT_MESSAGE_NOTIFY
@@ -121,7 +124,7 @@
NTSTATUS FASTCALL
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
- UINT uTimeout, BOOL Block, BOOL HookMessage,
+ UINT uTimeout, BOOL Block, INT HookMessage,
ULONG_PTR *uResult);
PUSER_MESSAGE FASTCALL
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
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] Thu Jul 31 18:48:35
2008
@@ -4,8 +4,9 @@
#define NDEBUG
#include <debug.h>
-//static PEVENTTABLE GlobalEvents;
-
+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 *********************************************************/
@@ -43,6 +44,88 @@
return Ret;
}
+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
@@ -50,6 +133,48 @@
TimeStamp(VOID)
{
return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated *
SharedUserData->TickCountMultiplier / 16777216);
+}
+
+static
+LRESULT
+FASTCALL
+IntCallLowLevelEvent( PEVENTHOOK pEH,
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild)
+{
+ NTSTATUS Status;
+ ULONG_PTR uResult;
+
+ /* 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,
+ 5000,
+ TRUE,
+ MSQ_ISEVENT,
+ &uResult);
+
+ return NT_SUCCESS(Status) ? uResult : 0;
+}
+
+static
+BOOL
+FASTCALL
+IntRemoveEvent(PEVENTHOOK pEH)
+{
+ if (pEH)
+ {
+ RemoveEntryList(&pEH->Chain);
+ GlobalEvents->Counts--;
+ UserDeleteObject(pEH->Self, otEvent);
+ return TRUE;
+ }
+ return FALSE;
}
/* FUNCTIONS *****************************************************************/
@@ -62,18 +187,26 @@
LONG idChild)
{
- PEVENTHOOK peh = UserHeapAlloc(sizeof(EVENTHOOK));
+ PEVENTHOOK pEH = UserHeapAlloc(sizeof(EVENTHOOK));
if ((gpsi->SrvEventActivity & GetMaskFromEvent(event))) return 0; // No events
to run.
- LRESULT Result = co_IntCallEventProc(peh->Self,
+
+ 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);
+ pEH->Proc);
return Result;
}
@@ -86,7 +219,9 @@
LONG idObject,
LONG idChild)
{
+ UserEnterExclusive();
UNIMPLEMENTED
+ UserLeave();
}
HWINEVENTHOOK
@@ -101,12 +236,98 @@
DWORD idThread,
UINT dwflags)
{
- gpsi->SrvEventActivity |= GetMaskFromEvent(eventMin);
- gpsi->SrvEventActivity &= ~GetMaskFromEvent(eventMin);
-
- UNIMPLEMENTED
-
- return 0;
+ PEVENTHOOK pEH;
+ HWINEVENTHOOK Ret = NULL;
+ UNICODE_STRING ModuleName;
+ NTSTATUS Status;
+ HANDLE Handle;
+
+ UserEnterExclusive();
+
+ DPRINT1("WARNING! Use at your own risk! Function is UNIMPLEMENTED!\n");
+
+ if ( !GlobalEvents )
+ {
+ GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK);
+ GlobalEvents->Counts = 0;
+ InitializeListHead(&GlobalEvents->Events);
+ }
+
+ pEH = UserCreateObject(gHandleTable, &Handle, otEvent, sizeof(EVENTHOOK));
+ if (pEH)
+ {
+ InsertTailList(&GlobalEvents->Events, &pEH->Chain);
+ GlobalEvents->Counts++;
+
+ pEH->Self = Handle;
+ pEH->Thread = PsGetCurrentThread();
+ pEH->eventMin = eventMin;
+ pEH->eventMax = eventMax;
+ pEH->idProcess = idProcess;
+ pEH->idThread = idThread;
+ 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));
+ if (! NT_SUCCESS(Status))
+ {
+ UserDereferenceObject(pEH);
+ IntRemoveEvent(pEH);
+ SetLastNtError(Status);
+ goto SetEventExit;
+ }
+ pEH->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ ModuleName.MaximumLength,
+ TAG_HOOK);
+ if (NULL == pEH->ModuleName.Buffer)
+ {
+ UserDereferenceObject(pEH);
+ IntRemoveEvent(pEH);
+ 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);
+ UserDereferenceObject(pEH);
+ IntRemoveEvent(pEH);
+ 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);
+ }
+
+SetEventExit:
+ UserLeave();
+ return Ret;
}
@@ -115,9 +336,22 @@
NtUserUnhookWinEvent(
HWINEVENTHOOK hWinEventHook)
{
- UNIMPLEMENTED
-
- return FALSE;
+ PEVENTHOOK pEH;
+ BOOL Ret = FALSE;
+
+ 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);
+ }
+
+ UserLeave();
+ return Ret;
}
/* EOF */
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] Thu Jul 31 18:48:35
2008
@@ -281,7 +281,7 @@
lParam,
5000,
TRUE,
- TRUE,
+ MSQ_ISHOOK,
&uResult);
return NT_SUCCESS(Status) ? uResult : 0;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Thu Jul 31
18:48:35 2008
@@ -1555,7 +1555,7 @@
lParam,
uTimeout,
(uFlags & SMTO_BLOCK),
- FALSE,
+ MSQ_NORMAL,
uResult);
}
while ((STATUS_TIMEOUT == Status) &&
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Thu Jul 31
18:48:35 2008
@@ -929,12 +929,19 @@
InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
&Message->ListEntry);
- if (Message->HookMessage)
+ if (Message->HookMessage == MSQ_ISHOOK)
{
Result = co_HOOK_CallHooks(Message->Msg.message,
(INT)(INT_PTR)Message->Msg.hwnd,
Message->Msg.wParam,
Message->Msg.lParam);
+ }
+ else if (Message->HookMessage == MSQ_ISEVENT)
+ {
+ Result = co_EVENT_CallEvents( Message->Msg.message,
+ Message->Msg.hwnd,
+ (LONG) Message->Msg.wParam,
+ (LONG) Message->Msg.lParam);
}
else
{
@@ -1090,7 +1097,7 @@
NTSTATUS FASTCALL
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
- UINT uTimeout, BOOL Block, BOOL HookMessage,
+ UINT uTimeout, BOOL Block, INT HookMessage,
ULONG_PTR *uResult)
{
PUSER_SENT_MESSAGE Message;