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

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Sat Aug 2 02:38:01 CEST 2008


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/include/window.h?rev=35022&r1=35021&r2=35022&view=diff
==============================================================================
--- 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/ntuser/event.c?rev=35022&r1=35021&r2=35022&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] 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/ntuser/hook.c?rev=35022&r1=35021&r2=35022&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] 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/ntuser/window.c?rev=35022&r1=35021&r2=35022&view=diff
==============================================================================
--- 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)
    {



More information about the Ros-diffs mailing list