mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[Win32k]
- 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
This commit is contained in:
parent
5d164caee1
commit
f9da00bc86
4 changed files with 111 additions and 44 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue