diff --git a/reactos/win32ss/user/ntuser/input.c b/reactos/win32ss/user/ntuser/input.c index 58dbe704ff9..b34f256646e 100644 --- a/reactos/win32ss/user/ntuser/input.c +++ b/reactos/win32ss/user/ntuser/input.c @@ -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; + BOOL Hit = FALSE; + PATTACHINFO *ppai; - if (!gpai) return FALSE; - - 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; + 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 (!Hit) return STATUS_INVALID_PARAMETER; + + ASSERT(ptiFrom->pqAttach); + + ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount); + + /* 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; - } while (pai); - - if (!pai) return FALSE; - - if (paiprev) paiprev->paiNext = pai->paiNext; - else if (!pai->paiNext) gpai = NULL; - - ExFreePoolWithTag(pai, USERTAG_ATTACHINFO); - ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p\n",ptiFrom,ptiTo); + } + 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; } /* diff --git a/reactos/win32ss/user/ntuser/input.h b/reactos/win32ss/user/ntuser/input.h index a7456b01d71..3bb95670c00 100644 --- a/reactos/win32ss/user/ntuser/input.h +++ b/reactos/win32ss/user/ntuser/input.h @@ -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) diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index 6772e5eeadf..0e64b5cb5a1 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -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) { diff --git a/reactos/win32ss/user/ntuser/ntstubs.c b/reactos/win32ss/user/ntuser/ntstubs.c index f2eab323e1f..17418c8aa5d 100644 --- a/reactos/win32ss/user/ntuser/ntstubs.c +++ b/reactos/win32ss/user/ntuser/ntstubs.c @@ -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; }