[CMAKE]
[reactos.git] / subsystems / win32 / win32k / ntuser / event.c
index 20a9b97..cdc2092 100644 (file)
@@ -1,5 +1,12 @@
+/*
+ * COPYRIGHT:         See COPYING in the top level directory
+ * PROJECT:           ReactOS kernel
+ * PURPOSE:           Window event handlers
+ * FILE:              subsystems/win32/win32k/ntuser/event.c
+ * PROGRAMER:         James Tabor (james.tabor@rectos.org)
+ */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -62,28 +69,28 @@ IntSetSrvEventMask( UINT EventMin, UINT EventMax)
           (event >= EVENT_CONSOLE_CARET && event <= EVENT_CONSOLE_END_APPLICATION) ||
           (event >= EVENT_OBJECT_CREATE && event <= EVENT_OBJECT_ACCELERATORCHANGE))
       {
-         gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+         gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
       }
       if (event > EVENT_SYSTEM_MINIMIZEEND && event < EVENT_CONSOLE_CARET)
       {
           event = EVENT_CONSOLE_CARET-1;
-          gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+          gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
       }
       if (event > EVENT_CONSOLE_END_APPLICATION && event < EVENT_OBJECT_CREATE )
       {
           event = EVENT_OBJECT_CREATE-1;
-          gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+          gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
       }
       if (event > EVENT_OBJECT_ACCELERATORCHANGE && event < EVENT_MAX)
       {
           event = EVENT_MAX-1;
-          gpsi->SrvEventActivity |= GetMaskFromEvent(event);
+          gpsi->dwInstalledEventHooks |= GetMaskFromEvent(event);
           break;
-      }      
+      }
    }
-   if (!gpsi->SrvEventActivity)
-      gpsi->SrvEventActivity |= SRV_EVENT_RUNNING; // Set something.
-   DPRINT("SetSrvEventMask 2 : %x\n", gpsi->SrvEventActivity);
+   if (!gpsi->dwInstalledEventHooks)
+      gpsi->dwInstalledEventHooks |= SRV_EVENT_RUNNING; // Set something.
+   DPRINT("SetSrvEventMask 2 : %x\n", gpsi->dwInstalledEventHooks);
 }
 
 static
@@ -96,29 +103,34 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
                         LONG idChild)
 {
    NTSTATUS Status;
-   ULONG_PTR uResult;
-   EVENTPACK EP;
+   PEVENTPACK pEP;
+   ULONG_PTR uResult = 0;
+
+   pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
+   if (!pEP) return 0;
 
-   EP.pEH = pEH;
-   EP.idObject = idObject;
-   EP.idChild = idChild;
+   pEP->pEH = pEH;
+   pEP->idObject = idObject;
+   pEP->idChild = idChild;
 
    /* FIXME should get timeout from
     * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-   Status = co_MsqSendMessage(((PTHREADINFO)pEH->Thread->Tcb.Win32Thread)->MessageQueue,
-                                           hwnd,
-                                          event,
-                                              0,
-                                    (LPARAM)&EP,
-                                           5000,
-                                           TRUE,
-                                    MSQ_ISEVENT,
-                                       &uResult);
-
+   Status = co_MsqSendMessage( pEH->head.pti->MessageQueue,
+                               hwnd,
+                               event,
+                               0,
+                              (LPARAM)pEP,
+                               300,
+                               TRUE,
+                               MSQ_ISEVENT,
+                              &uResult);
+   if (!NT_SUCCESS(Status))
+   { 
+      ExFreePoolWithTag(pEP, TAG_HOOK);
+   }
    return NT_SUCCESS(Status) ? uResult : 0;
 }
 
-
 static
 BOOL
 FASTCALL
@@ -126,23 +138,61 @@ IntRemoveEvent(PEVENTHOOK pEH)
 {
    if (pEH)
    {
+      DPRINT("IntRemoveEvent pEH 0x%x\n",pEH);
+      KeEnterCriticalRegion();
       RemoveEntryList(&pEH->Chain);
       GlobalEvents->Counts--;
-      if (!GlobalEvents->Counts) gpsi->SrvEventActivity = 0;
-      UserDeleteObject(pEH->Self, otEvent);
+      if (!GlobalEvents->Counts) gpsi->dwInstalledEventHooks = 0;
+      UserDeleteObject(UserHMGetHandle(pEH), otEvent);
+      KeLeaveCriticalRegion();
       return TRUE;
    }
    return FALSE;
 }
 
+VOID
+FASTCALL
+EVENT_DestroyThreadEvents(PETHREAD Thread)
+{
+   PTHREADINFO pti;
+   PEVENTHOOK pEH;
+   PLIST_ENTRY pLE;
+
+   pti = Thread->Tcb.Win32Thread;
+   if (!pti) return;
+
+   if (!GlobalEvents || !GlobalEvents->Counts) return;
+
+   pLE = GlobalEvents->Events.Flink;
+   if (IsListEmpty(pLE)) return;
+
+   pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+   do
+   {
+      if (IsListEmpty(pLE)) break;
+      if (!pEH) break;
+      pLE = pEH->Chain.Flink;
+      if (pEH->head.pti == pti)
+      {
+         IntRemoveEvent(pEH);
+      }
+      pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+   } while (pLE != &GlobalEvents->Events);
+
+   return;
+}
+
 /* FUNCTIONS *****************************************************************/
 
+//
+// Dispatch MsgQueue Event Call processor!
+//
 LRESULT
 FASTCALL
 co_EVENT_CallEvents( DWORD event,
-                       HWND hwnd, 
-                    UINT_PTR idObject,
-                    LONG_PTR idChild)
+                     HWND hwnd, 
+                     UINT_PTR idObject,
+                     LONG_PTR idChild)
 {
    PEVENTHOOK pEH;
    LRESULT Result;
@@ -150,14 +200,16 @@ co_EVENT_CallEvents( DWORD event,
 
    pEH = pEP->pEH;
    
-   Result = co_IntCallEventProc( pEH->Self,
-                                     event,
-                                      hwnd,
-                             pEP->idObject,
-                              pEP->idChild,
(DWORD)(NtCurrentTeb()->ClientId).UniqueThread,
-                  (DWORD)EngGetTickCount(),
+   Result = co_IntCallEventProc( UserHMGetHandle(pEH),
+                                 event,
+                                 hwnd,
+                                 pEP->idObject,
+                                 pEP->idChild,
                                PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+                                (DWORD)EngGetTickCount(),
                                  pEH->Proc);
+
+   ExFreePoolWithTag(pEP, TAG_HOOK);
    return Result;
 }
 
@@ -165,82 +217,109 @@ VOID
 FASTCALL
 IntNotifyWinEvent(
    DWORD Event,
-   PWINDOW_OBJECT Window,
+   PWND  pWnd,
    LONG  idObject,
-   LONG  idChild)
+   LONG  idChild,
+   DWORD flags)
 {
    PEVENTHOOK pEH;
-   LRESULT Result;
+   PLIST_ENTRY pLE;
+   PTHREADINFO pti, ptiCurrent;
 
-   if (!GlobalEvents->Counts) return;
+   DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd);
 
-   pEH = (PEVENTHOOK)GlobalEvents->Events.Flink;
+   if (!GlobalEvents || !GlobalEvents->Counts) return;
 
+   if (pWnd && pWnd->state & WNDS_DESTROYED) return;
+
+   ptiCurrent = PsGetCurrentThreadWin32Thread();
+
+   if (pWnd && flags & WEF_SETBYWNDPTI)
+      pti = pWnd->head.pti;
+   else
+      pti = ptiCurrent;
+
+   pLE = GlobalEvents->Events.Flink;
+   pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
    do
-   { 
+   {
+     if (!pEH) break;
      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) || 
-               (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)pEH->idProcess))
+// if all process || all thread || other thread same process
+// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
+        if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) &&
+             (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) &&
+             (!pEH->idThread  || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) &&
+             (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD)  || pEH->head.pti != pti) &&
+               pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks.
+        {
+           // Send message to the thread if pEH is not current.
+           if (pEH->head.pti != ptiCurrent)
            {
-              Result = IntCallLowLevelEvent(pEH, Event, Window->hSelf, idObject, idChild);
+              DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject);
+              IntCallLowLevelEvent( pEH,
+                                    Event,
+                                    UserHMGetHandle(pWnd),
+                                    idObject,
+                                    idChild);
            }
-        }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
-        else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
-                   ( ((pEH->idProcess &&
-                     NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)pEH->idProcess) &&
-                     !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
-                     !pEH->idProcess ) )
-        {
-           Result = co_IntCallEventProc( pEH->Self,
-                                             Event,
-                                     Window->hSelf,
-                                          idObject,
-                                           idChild,
-             PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
-                          (DWORD)EngGetTickCount(),
-                                         pEH->Proc);
-        }
+           else
+           {
+              DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject);
+              co_IntCallEventProc( UserHMGetHandle(pEH),
+                                   Event,
+                                   UserHMGetHandle(pWnd),
+                                   idObject,
+                                   idChild,
+                                   PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+                                  (DWORD)EngGetTickCount(),
+                                   pEH->Proc);
+           }
+        }        
      }
      UserDereferenceObject(pEH);
-
-     pEH = (PEVENTHOOK)pEH->Chain.Flink;
-   } while (pEH != (PEVENTHOOK)&GlobalEvents->Events.Flink);
+     pLE = pEH->Chain.Flink;
+     pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+   } while (pLE != &GlobalEvents->Events);
 }            
 
 VOID
-STDCALL
+APIENTRY
 NtUserNotifyWinEvent(
    DWORD Event,
    HWND  hWnd,
    LONG  idObject,
    LONG  idChild)
 {
-   PWINDOW_OBJECT Window = NULL;
+   PWND Window = NULL;
    USER_REFERENCE_ENTRY Ref;
    UserEnterExclusive();
 
    /* Validate input */
-   if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
+   if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
    {
-      return;
-   }   
-   
-   if (gpsi->SrvEventActivity & GetMaskFromEvent(Event))
+     Window = UserGetWindowObject(hWnd);
+     if (!Window)
+     {
+       UserLeave();
+       return;
+     }
+   }
+
+   if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event))
    {
-      UserRefObjectCo(Window, &Ref);
-      IntNotifyWinEvent( Event, Window, idObject, idChild);
-      UserDerefObjectCo(Window);
+      if (Window) UserRefObjectCo(Window, &Ref);
+      IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
+      if (Window) UserDerefObjectCo(Window);
    }
    UserLeave();
 }
 
 HWINEVENTHOOK
-STDCALL
+APIENTRY
 NtUserSetWinEventHook(
    UINT eventMin,
    UINT eventMax,
@@ -253,16 +332,22 @@ NtUserSetWinEventHook(
 {
    PEVENTHOOK pEH;
    HWINEVENTHOOK Ret = NULL;
-   UNICODE_STRING ModuleName;
    NTSTATUS Status;
    HANDLE Handle;
    PETHREAD Thread = NULL;
 
+   DPRINT("NtUserSetWinEventHook hmod 0x%x, pfn 0x%x\n",hmodWinEventProc, lpfnWinEventProc);
+
    UserEnterExclusive();
 
    if ( !GlobalEvents )
    {
       GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK);
+      if (GlobalEvents == NULL)
+      {
+         SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+         goto SetEventExit;
+      }
       GlobalEvents->Counts = 0;      
       InitializeListHead(&GlobalEvents->Events);
    }
@@ -294,70 +379,31 @@ NtUserSetWinEventHook(
          goto SetEventExit;
       }
    }
-
-   pEH = UserCreateObject(gHandleTable, &Handle, otEvent, sizeof(EVENTHOOK));
+   // Creator, pti is set here.
+   pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK));
    if (pEH)
    {
       InsertTailList(&GlobalEvents->Events, &pEH->Chain);
       GlobalEvents->Counts++;
 
-      pEH->Self      = Handle;
-      if (Thread)
-         pEH->Thread = Thread;
-      else
-         pEH->Thread = PsGetCurrentThread();
+      UserHMGetHandle(pEH) = Handle;
       pEH->eventMin  = eventMin;
       pEH->eventMax  = eventMax;
-      pEH->idProcess = idProcess;
-      pEH->idThread  = idThread;
-      pEH->Ansi      = FALSE;
+      pEH->idProcess = idProcess; // These are cmp'ed
+      pEH->idThread  = idThread;  //  "
       pEH->Flags     = dwflags;
-
-
+    /*
+       If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
+       the atom index table where the hmod data is saved to be recalled later
+       if fSync set by WINEVENT_INCONTEXT.
+       If WINEVENT_OUTOFCONTEXT just use proc..
+       Do this instead....
+     */
       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);
+         pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
+         pEH->ihmod = (INT)hmodWinEventProc;
+         pEH->Proc = lpfnWinEventProc;
       }
       else
          pEH->Proc = lpfnWinEventProc;
@@ -375,7 +421,7 @@ SetEventExit:
 }
 
 BOOL
-STDCALL
+APIENTRY
 NtUserUnhookWinEvent(
    HWINEVENTHOOK hWinEventHook)
 {