[Win32k]
authorJames Tabor <james.tabor@reactos.org>
Sat, 18 Aug 2012 22:13:38 +0000 (22:13 +0000)
committerJames Tabor <james.tabor@reactos.org>
Sat, 18 Aug 2012 22:13:38 +0000 (22:13 +0000)
- AttachThreadInput, this should fix the crash. Original crash patch by Giannis Adamopoulos. See bug 7225.
- WARNING: This code should be turned off until the restructuring is finished. Please read bug 7225!

svn path=/trunk/; revision=57103

reactos/win32ss/user/ntuser/input.c
reactos/win32ss/user/ntuser/input.h
reactos/win32ss/user/ntuser/main.c
reactos/win32ss/user/ntuser/ntstubs.c

index 58dbe70..b34f256 100644 (file)
@@ -17,6 +17,7 @@ PTHREADINFO ptiKeyboard;
 PTHREADINFO ptiMouse;
 PKTIMER MasterTimer = NULL;
 PATTACHINFO gpai = NULL;
+INT paiCount = 0;
 HANDLE ghKeyboardDevice;
 
 static DWORD LastInputTick = 0;
@@ -414,20 +415,20 @@ IsThreadAttach(PTHREADINFO ptiTo)
     return pai->pti1;
 }
 
-BOOL FASTCALL
+NTSTATUS FASTCALL
 UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
 {
     MSG msg;
     PATTACHINFO pai;
 
     /* Can not be the same thread. */
-    if (ptiFrom == ptiTo) return FALSE;
+    if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
 
     /* Do not attach to system threads or between different desktops. */
     if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
-            ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
-            ptiFrom->rpdesk != ptiTo->rpdesk)
-        return FALSE;
+        ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
+        ptiFrom->rpdesk != ptiTo->rpdesk)
+        return STATUS_ACCESS_DENIED;
 
     /* MSDN Note:
        Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
@@ -437,20 +438,34 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
     if (fAttach)
     {
         pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
-        if (!pai) return FALSE;
+        if (!pai) return STATUS_NO_MEMORY;
 
         pai->paiNext = gpai;
         pai->pti1 = ptiFrom;
         pai->pti2 = ptiTo;
         gpai = pai;
-        ERR("Attach Allocated! ptiFrom 0x%p  ptiTo 0x%p\n",ptiFrom,ptiTo);
+        paiCount++;
+        ERR("Attach Allocated! ptiFrom 0x%p  ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
+
+        if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
+        {
+           ERR("Attach Threads are already associated!\n");
+        }
 
         ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
-        ptiFrom->pqAttach = ptiFrom->MessageQueue;
+
+        /* Keep the original queue in pqAttach (ie do not trash it in a second attachment) */
+        if (ptiFrom->pqAttach == NULL)
+           ptiFrom->pqAttach = ptiFrom->MessageQueue;
         ptiFrom->MessageQueue = ptiTo->MessageQueue;
+
+        ptiFrom->MessageQueue->cThreads++;
+        ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
+
         // FIXME: conditions?
         if (ptiFrom->pqAttach == gpqForeground)
         {
+           ERR("ptiFrom is Foreground\n");
         ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive;
         ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus;
         ptiFrom->MessageQueue->CursorObject = ptiFrom->pqAttach->CursorObject;
@@ -458,31 +473,71 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
         ptiFrom->MessageQueue->QF_flags ^= ((ptiFrom->MessageQueue->QF_flags ^ ptiFrom->pqAttach->QF_flags) & QF_CAPTURELOCKED);
         ptiFrom->MessageQueue->CaretInfo = ptiFrom->pqAttach->CaretInfo;
         }
+        else
+        {
+           ERR("ptiFrom NOT Foreground\n");
+        }
+        if (ptiTo->MessageQueue == gpqForeground)
+        {
+           ERR("ptiTo is Foreground\n");
+        }
+        else
+        {
+           ERR("ptiTo NOT Foreground\n");
+        }
     }
     else /* If clear, unlink and free it. */
     {
-        PATTACHINFO paiprev = NULL;
-
-        if (!gpai) return FALSE;
+        BOOL Hit = FALSE;
+        PATTACHINFO *ppai;
 
-        pai = gpai;
+        if (!gpai) return STATUS_INVALID_PARAMETER;
 
         /* Search list and free if found or return false. */
-        do
+        ppai = &gpai;
+        while (*ppai != NULL)
         {
-            if (pai->pti2 == ptiTo && pai->pti1 == ptiFrom) break;
-            paiprev = pai;
-            pai = pai->paiNext;
-        } while (pai);
+           if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
+           {
+              pai = *ppai;
+              /* Remove it from the list */
+              *ppai = (*ppai)->paiNext;
+              ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
+              paiCount--;
+              Hit = TRUE;
+              break;
+           }
+           ppai = &((*ppai)->paiNext);
+        }
 
-        if (!pai) return FALSE;
+        if (!Hit) return STATUS_INVALID_PARAMETER;
 
-        if (paiprev) paiprev->paiNext = pai->paiNext;
-        else if (!pai->paiNext) gpai = NULL;
+        ASSERT(ptiFrom->pqAttach);
+        ERR("Attach Free! ptiFrom 0x%p  ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
 
-        ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
-        ERR("Attach Free! ptiFrom 0x%p  ptiTo 0x%p\n",ptiFrom,ptiTo);
+        /* Search list and check if the thread is attached one more time */
+        pai = gpai;
+        while(pai)
+        {
+            /* If the thread is attached again , we are done */
+            if (pai->pti1 == ptiFrom) 
+            {
+                ptiFrom->MessageQueue->cThreads--;
+                ERR("ptiTo L Share count %d\n", ptiFrom->MessageQueue->cThreads);
+                /* Use the message queue of the last attachment */
+                ptiFrom->MessageQueue = pai->pti2->MessageQueue;
+                ptiFrom->MessageQueue->CursorObject = NULL;
+                ptiFrom->MessageQueue->spwndActive = NULL;
+                ptiFrom->MessageQueue->spwndFocus = NULL;
+                ptiFrom->MessageQueue->spwndCapture = NULL;
+                return STATUS_SUCCESS;
+            }
+            pai = pai->paiNext;
+        }
 
+        ptiFrom->MessageQueue->cThreads--;
+        ERR("ptiTo E Share count %d\n", ptiFrom->MessageQueue->cThreads);
         ptiFrom->MessageQueue = ptiFrom->pqAttach;
         // FIXME: conditions?
         ptiFrom->MessageQueue->CursorObject = NULL;
@@ -505,7 +560,7 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
     msg.pt = gpsi->ptCursor;
     co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
 
-    return TRUE;
+    return STATUS_SUCCESS;
 }
 
 /*
index a7456b0..3bb9567 100644 (file)
@@ -62,7 +62,7 @@ extern PATTACHINFO gpai;
 INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
 BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
 DWORD NTAPI CreateSystemThreads(UINT Type);
-BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
+NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
 PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO);
 VOID FASTCALL DoTheScreenSaver(VOID);
 #define ThreadHasInputAccess(W32Thread) (TRUE)
index 6772e5e..0e64b5c 100644 (file)
@@ -401,6 +401,28 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
     ppiCurrent = ptiCurrent->ppi;
     ASSERT(ppiCurrent);
 
+    // ptiTo
+    if (IsThreadAttach(ptiCurrent))
+    {
+       PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
+       TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
+       UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
+    }
+    
+    // ptiFrom
+    if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
+    {
+       PTHREADINFO ptiTo;
+       ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
+       TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
+       if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
+       else
+       {
+          // eThread maybe okay but Win32Thread already made NULL!
+          ERR_CH(UserThread,"Attached Thread ptiFrom did not switch due to ptiTo is NULL!\n");
+       }
+    }
+
     /* Decrement thread count and check if its 0 */
     ppiCurrent->cThreads--;
 
@@ -472,23 +494,6 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
         }
     }
 
-    // ptiTo
-    if (IsThreadAttach(ptiCurrent))
-    {
-       PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
-       TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
-       UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
-    }
-    
-    // ptiFrom
-    if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
-    {
-       PTHREADINFO ptiTo;
-       ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
-       TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
-       UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
-    }
-
     /* Free the message queue */
     if (ptiCurrent->MessageQueue)
     {
index f2eab32..17418c8 100644 (file)
@@ -34,6 +34,7 @@ NtUserAttachThreadInput(
   BOOL Ret = FALSE;
 
   UserEnterExclusive();
+  ERR("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
   Status = PsLookupThreadByThreadId((HANDLE)idAttach, &Thread);
   if (!NT_SUCCESS(Status))
   {
@@ -53,9 +54,15 @@ NtUserAttachThreadInput(
   ObDereferenceObject(Thread);
   ObDereferenceObject(ThreadTo);
 
-  Ret = UserAttachThreadInput( pti, ptiTo, fAttach);
+  Status = UserAttachThreadInput( pti, ptiTo, fAttach);
+  if (!NT_SUCCESS(Status))
+  {
+     EngSetLastError(RtlNtStatusToDosError(Status));
+  }
+  else Ret = TRUE;
 
 Exit:
+  ERR("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
   UserLeave();
   return Ret;
 }