[WIN32K] Use KeStackAttachProcess
[reactos.git] / win32ss / user / ntuser / hook.c
index 3e6e942..792d195 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window hooks
- * FILE:             subsystems/win32/win32k/ntuser/hook.c
+ * FILE:             win32ss/user/ntuser/hook.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
  *                   James Tabor (james.tabor@rectos.org)
  *                   Rafal Harabien (rafalh@reactos.org)
@@ -92,7 +92,7 @@ IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook)
     PLIST_ENTRY ListEntry;
     PPROCESSINFO ppiCsr;
 
-    ERR("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
+    TRACE("IntHookModuleUnloaded: iHookID=%d\n", iHookID);
 
     ppiCsr = PsGetProcessWin32Process(gpepCSRSS);
 
@@ -103,7 +103,7 @@ IntHookModuleUnloaded(PDESKTOP pdesk, int iHookID, HHOOK hHook)
 
         /* FIXME: Do some more security checks here */
 
-        /* FIXME: The first check is a reactos specific hack for system threads */
+        /* FIXME: HACK: The first check is a reactos specific hack for system threads */
         if(!PsIsSystemProcess(ptiCurrent->ppi->peProcess) &&
            ptiCurrent->ppi != ppiCsr)
         {
@@ -222,7 +222,7 @@ UserUnregisterUserApiHook(VOID)
         return FALSE;
     }
 
-    ERR("UserUnregisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
+    TRACE("UserUnregisterUserApiHook. Server PID: %p\n", PsGetProcessId(pti->ppi->peProcess));
 
     /* Unregister the api hook */
     gpsi->dwSRVIFlags &= ~SRVINFO_APIHOOK;
@@ -318,13 +318,13 @@ co_IntCallLowLevelHook(PHOOK Hook,
 // Dispatch MsgQueue Hook Call processor!
 //
 LRESULT
-FASTCALL
+APIENTRY
 co_CallHook( INT HookId,
              INT Code,
              WPARAM wParam,
              LPARAM lParam)
 {
-    LRESULT Result;
+    LRESULT Result = 0;
     PHOOK phk;
     PHOOKPACK pHP = (PHOOKPACK)lParam;
 
@@ -335,14 +335,16 @@ co_CallHook( INT HookId,
     {
        case WH_JOURNALPLAYBACK:
        case WH_JOURNALRECORD:
-       case WH_KEYBOARD:
        case WH_KEYBOARD_LL:
        case WH_MOUSE_LL:
        case WH_MOUSE:
           lParam = (LPARAM)pHP->pHookStructs;
+       case WH_KEYBOARD:
           break;
     }
 
+    if (!UserObjectInDestroy(UserHMGetHandle(phk))) //// Fix CORE-10549.
+    {
     /* The odds are high for this to be a Global call. */
     Result = co_IntCallHookProc( HookId,
                                  Code,
@@ -353,7 +355,7 @@ co_CallHook( INT HookId,
                                  phk->offPfn,
                                  phk->Ansi,
                                 &phk->ModuleName);
-
+    }
     /* The odds so high, no one is waiting for the results. */
     if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK);
     ExFreePoolWithTag(pHP, TAG_HOOK);
@@ -362,7 +364,7 @@ co_CallHook( INT HookId,
 
 static
 LRESULT
-FASTCALL
+APIENTRY
 co_HOOK_CallHookNext( PHOOK Hook,
                       INT Code,
                       WPARAM wParam,
@@ -516,7 +518,7 @@ co_IntCallDebugHook(PHOOK Hook,
 
 static
 LRESULT
-FASTCALL
+APIENTRY
 co_UserCallNextHookEx(PHOOK Hook,
                     int Code,
                     WPARAM wParam,
@@ -721,7 +723,8 @@ co_UserCallNextHookEx(PHOOK Hook,
 
                             if (!IS_ATOM(pcbtcww->lpcs->lpszClass))
                             {
-                               ProbeForRead( pcbtcww->lpcs->lpszClass,
+                                _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL);
+                                ProbeForRead(pcbtcww->lpcs->lpszClass,
                                              sizeof(CHAR),
                                              1);
                             }
@@ -740,7 +743,8 @@ co_UserCallNextHookEx(PHOOK Hook,
 
                             if (!IS_ATOM(pcbtcww->lpcs->lpszClass))
                             {
-                               ProbeForRead( pcbtcww->lpcs->lpszClass,
+                                _Analysis_assume_(pcbtcww->lpcs->lpszClass != NULL);
+                                ProbeForRead(pcbtcww->lpcs->lpszClass,
                                              sizeof(WCHAR),
                                              1);
                             }
@@ -969,15 +973,16 @@ IntGetGlobalHookHandles(PDESKTOP pdo, int HookId)
       ++cHooks;
 
     pList = ExAllocatePoolWithTag(PagedPool, (cHooks + 1) * sizeof(HHOOK), TAG_HOOK);
-    if(!pList)
+    if (!pList)
     {
         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return NULL;
-}
+    }
 
     for (pElem = pLastHead->Flink; pElem != pLastHead; pElem = pElem->Flink)
-{
+    {
         pHook = CONTAINING_RECORD(pElem, HOOK, Chain);
+        NT_ASSERT(i < cHooks);
         pList[i++] = pHook->head.h;
     }
     pList[i] = NULL;
@@ -1032,45 +1037,59 @@ BOOLEAN
 IntRemoveHook(PVOID Object)
 {
     INT HookId;
-    PTHREADINFO pti;
+    PTHREADINFO ptiHook, pti;
     PDESKTOP pdo;
     PHOOK Hook = Object;
 
+    NT_ASSERT(UserIsEnteredExclusive());
+
     HookId = Hook->HookId;
+    pti = PsGetCurrentThreadWin32Thread();
 
     if (Hook->ptiHooked) // Local
     {
-       pti = Hook->ptiHooked;
+        ptiHook = Hook->ptiHooked;
 
-       IntFreeHook( Hook);
+        IntFreeHook(Hook);
 
-       if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) )
-       {
-          pti->fsHooks &= ~HOOKID_TO_FLAG(HookId);
-          _SEH2_TRY
-          {
-             pti->pClientInfo->fsHooks = pti->fsHooks;
-          }
-          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-          {
-              /* Do nothing */
-              (void)0;
-          }
-          _SEH2_END;
+        if (IsListEmpty(&ptiHook->aphkStart[HOOKID_TO_INDEX(HookId)]))
+        {
+            BOOL bOtherProcess;
+            KAPC_STATE ApcState;
+
+            ptiHook->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+            bOtherProcess = (ptiHook->ppi != pti->ppi);
+
+            if (bOtherProcess)
+                KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState);
+
+            _SEH2_TRY
+            {
+                ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Do nothing */
+                (void)0;
+            }
+            _SEH2_END;
+
+            if (bOtherProcess)
+                KeUnstackDetachProcess(&ApcState);
        }
     }
     else // Global
     {
-       IntFreeHook( Hook);
+        IntFreeHook(Hook);
 
-       pdo = IntGetActiveDesktop();
+        pdo = IntGetActiveDesktop();
 
-       if ( pdo &&
-            pdo->pDeskInfo &&
-            IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) )
-       {
-          pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
-       }
+        if (pdo &&
+             pdo->pDeskInfo &&
+             IsListEmpty(&pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]))
+        {
+            pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+        }
     }
 
     return TRUE;
@@ -1080,7 +1099,7 @@ IntRemoveHook(PVOID Object)
   Win32k Kernel Space Hook Caller.
  */
 LRESULT
-FASTCALL
+APIENTRY
 co_HOOK_CallHooks( INT HookId,
                    INT Code,
                    WPARAM wParam,
@@ -1150,6 +1169,8 @@ co_HOOK_CallHooks( INT HookId,
        }
 
        Hook = CONTAINING_RECORD(pLastHead->Flink, HOOK, Chain);
+       ObReferenceObject(pti->pEThread);
+       IntReferenceThreadInfo(pti);
        UserRefObjectCo(Hook, &Ref);
 
        ClientInfo = pti->pClientInfo;
@@ -1179,7 +1200,7 @@ co_HOOK_CallHooks( INT HookId,
                                     wParam,
                                     lParam,
                                     Hook->Proc,
-                                    Hook->ihmod, 
+                                    Hook->ihmod,
                                     Hook->offPfn,
                                     Hook->Ansi,
                                    &Hook->ModuleName);
@@ -1199,6 +1220,8 @@ co_HOOK_CallHooks( INT HookId,
        pti->sphkCurrent = SaveHook;
        Hook->phkNext = NULL;
        UserDerefObjectCo(Hook);
+       IntDereferenceThreadInfo(pti);
+       ObDereferenceObject(pti->pEThread);
     }
 
     if ( Global )
@@ -1224,7 +1247,6 @@ co_HOOK_CallHooks( INT HookId,
               ERR("Invalid hook!\n");
               continue;
           }
-          UserRefObjectCo(Hook, &Ref);
 
          /* Hook->Thread is null, we hax around this with Hook->head.pti. */
           ptiHook = Hook->head.pti;
@@ -1234,6 +1256,7 @@ co_HOOK_CallHooks( INT HookId,
              TRACE("Next Hook %p, %p\n", ptiHook->rpdesk, pdo);
              continue;
           }
+          UserRefObjectCo(Hook, &Ref);
 
           if (ptiHook != pti )
           {
@@ -1248,19 +1271,40 @@ co_HOOK_CallHooks( INT HookId,
                 TRACE("\nGlobal Hook posting to another Thread! %d\n",HookId );
                 Result = co_IntCallLowLevelHook(Hook, Code, wParam, lParam);
              }
+             else if (ptiHook->ppi == pti->ppi)
+             {
+                TRACE("\nGlobal Hook calling to another Thread! %d\n",HookId );
+                ObReferenceObject(ptiHook->pEThread);
+                IntReferenceThreadInfo(ptiHook);
+                Result = co_IntCallHookProc( HookId,
+                                             Code,
+                                             wParam,
+                                             lParam,
+                                             Hook->Proc,
+                                             Hook->ihmod,
+                                             Hook->offPfn,
+                                             Hook->Ansi,
+                                            &Hook->ModuleName);
+                IntDereferenceThreadInfo(ptiHook);
+                ObDereferenceObject(ptiHook->pEThread);
+             }
           }
           else
           { /* Make the direct call. */
-             TRACE("Local Hook calling to Thread! %d\n",HookId );
+             TRACE("Global going Local Hook calling to Thread! %d\n",HookId );
+             ObReferenceObject(pti->pEThread);
+             IntReferenceThreadInfo(pti);
              Result = co_IntCallHookProc( HookId,
                                           Code,
                                           wParam,
                                           lParam,
                                           Hook->Proc,
-                                          Hook->ihmod, 
+                                          Hook->ihmod,
                                           Hook->offPfn,
                                           Hook->Ansi,
                                          &Hook->ModuleName);
+             IntDereferenceThreadInfo(pti);
+             ObDereferenceObject(pti->pEThread);
           }
           UserDerefObjectCo(Hook);
        }
@@ -1294,12 +1338,14 @@ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
        {
           Hook = CONTAINING_RECORD(pElement, HOOK, Chain);
 
+          /* Get the next element now, we might free the hook in what follows */
+          pElement = Hook->Chain.Flink;
+
           if (Hook->Proc == pfnFilterProc)
           {
              if (Hook->head.pti == pti)
              {
                 IntRemoveHook(Hook);
-                UserDereferenceObject(Hook);
                 return TRUE;
              }
              else
@@ -1308,8 +1354,6 @@ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
                 return FALSE;
              }
           }
-
-          pElement = Hook->Chain.Flink;
        }
     }
     return FALSE;
@@ -1402,7 +1446,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
                         BOOL Ansi)
 {
     PWINSTATION_OBJECT WinStaObj;
-    PHOOK Hook;
+    PHOOK Hook = NULL;
     UNICODE_STRING ModuleName;
     NTSTATUS Status;
     HHOOK Handle;
@@ -1434,13 +1478,13 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
             HookId == WH_MOUSE_LL ||
             HookId == WH_SYSMSGFILTER)
        {
-           ERR("Local hook installing Global HookId: %d\n",HookId);
+           TRACE("Local hook installing Global HookId: %d\n",HookId);
            /* these can only be global */
            EngSetLastError(ERROR_GLOBAL_ONLY_HOOK);
            RETURN( NULL);
        }
 
-       if ( !(ptiHook = IntTID2PTI( (HANDLE)ThreadId )))
+       if ( !(ptiHook = IntTID2PTI( UlongToHandle(ThreadId) )))
        {
           ERR("Invalid thread id 0x%x\n", ThreadId);
           EngSetLastError(ERROR_INVALID_PARAMETER);
@@ -1507,9 +1551,10 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
     }
 
     Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation,
-                                             KernelMode,
+                                             UserMode,
                                              0,
-                                            &WinStaObj);
+                                            &WinStaObj,
+                                             0);
 
     if (!NT_SUCCESS(Status))
     {
@@ -1525,7 +1570,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
        RETURN( NULL);
     }
 
-    Hook->ihmod   = (INT)Mod; // Module Index from atom table, Do this for now.
+    Hook->ihmod   = (INT_PTR)Mod; // Module Index from atom table, Do this for now.
     Hook->HookId  = HookId;
     Hook->rpdesk  = ptiHook->rpdesk;
     Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
@@ -1558,7 +1603,9 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
           }
           else
           {
-             KeAttachProcess(&ptiHook->ppi->peProcess->Pcb);
+             KAPC_STATE ApcState;
+
+             KeStackAttachProcess(&ptiHook->ppi->peProcess->Pcb, &ApcState);
              _SEH2_TRY
              {
                 ptiHook->pClientInfo->fsHooks = ptiHook->fsHooks;
@@ -1569,7 +1616,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
                 ERR("Problem writing to Remote ClientInfo!\n");
              }
              _SEH2_END;
-             KeDetachProcess();
+             KeUnstackDetachProcess(&ApcState);
           }
        }
     }
@@ -1634,6 +1681,8 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
     RETURN( Handle);
 
 CLEANUP:
+    if (Hook)
+        UserDereferenceObject(Hook);
     TRACE("Leave NtUserSetWindowsHookEx, ret=%p\n", _ret_);
     UserLeave();
     END_CLEANUP;