[ros-diffs] [jimtabor] 34988: - 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.

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Fri Aug 1 01:48:35 CEST 2008


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/include/hook.h?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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/include/msgqueue.h?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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/ntuser/event.c?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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/ntuser/hook.c?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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/ntuser/message.c?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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/ntuser/msgqueue.c?rev=34988&r1=34987&r2=34988&view=diff
==============================================================================
--- 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;



More information about the Ros-diffs mailing list