mirror of
https://github.com/reactos/reactos.git
synced 2025-04-22 13:10:39 +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;
|
PTHREADINFO ptiMouse;
|
||||||
PKTIMER MasterTimer = NULL;
|
PKTIMER MasterTimer = NULL;
|
||||||
PATTACHINFO gpai = NULL;
|
PATTACHINFO gpai = NULL;
|
||||||
|
INT paiCount = 0;
|
||||||
HANDLE ghKeyboardDevice;
|
HANDLE ghKeyboardDevice;
|
||||||
|
|
||||||
static DWORD LastInputTick = 0;
|
static DWORD LastInputTick = 0;
|
||||||
|
@ -414,20 +415,20 @@ IsThreadAttach(PTHREADINFO ptiTo)
|
||||||
return pai->pti1;
|
return pai->pti1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL FASTCALL
|
NTSTATUS FASTCALL
|
||||||
UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
|
UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
PATTACHINFO pai;
|
PATTACHINFO pai;
|
||||||
|
|
||||||
/* Can not be the same thread. */
|
/* 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. */
|
/* Do not attach to system threads or between different desktops. */
|
||||||
if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
|
if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
|
||||||
ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
|
ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
|
||||||
ptiFrom->rpdesk != ptiTo->rpdesk)
|
ptiFrom->rpdesk != ptiTo->rpdesk)
|
||||||
return FALSE;
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
/* MSDN Note:
|
/* MSDN Note:
|
||||||
Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
|
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)
|
if (fAttach)
|
||||||
{
|
{
|
||||||
pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
|
pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
|
||||||
if (!pai) return FALSE;
|
if (!pai) return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
pai->paiNext = gpai;
|
pai->paiNext = gpai;
|
||||||
pai->pti1 = ptiFrom;
|
pai->pti1 = ptiFrom;
|
||||||
pai->pti2 = ptiTo;
|
pai->pti2 = ptiTo;
|
||||||
gpai = pai;
|
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;
|
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 = ptiTo->MessageQueue;
|
||||||
|
|
||||||
|
ptiFrom->MessageQueue->cThreads++;
|
||||||
|
ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
|
||||||
|
|
||||||
// FIXME: conditions?
|
// FIXME: conditions?
|
||||||
if (ptiFrom->pqAttach == gpqForeground)
|
if (ptiFrom->pqAttach == gpqForeground)
|
||||||
{
|
{
|
||||||
|
ERR("ptiFrom is Foreground\n");
|
||||||
ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive;
|
ptiFrom->MessageQueue->spwndActive = ptiFrom->pqAttach->spwndActive;
|
||||||
ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus;
|
ptiFrom->MessageQueue->spwndFocus = ptiFrom->pqAttach->spwndFocus;
|
||||||
ptiFrom->MessageQueue->CursorObject = ptiFrom->pqAttach->CursorObject;
|
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->QF_flags ^= ((ptiFrom->MessageQueue->QF_flags ^ ptiFrom->pqAttach->QF_flags) & QF_CAPTURELOCKED);
|
||||||
ptiFrom->MessageQueue->CaretInfo = ptiFrom->pqAttach->CaretInfo;
|
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. */
|
else /* If clear, unlink and free it. */
|
||||||
{
|
{
|
||||||
PATTACHINFO paiprev = NULL;
|
BOOL Hit = FALSE;
|
||||||
|
PATTACHINFO *ppai;
|
||||||
|
|
||||||
if (!gpai) return FALSE;
|
if (!gpai) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
pai = gpai;
|
|
||||||
|
|
||||||
/* Search list and free if found or return false. */
|
/* Search list and free if found or return false. */
|
||||||
do
|
ppai = &gpai;
|
||||||
|
while (*ppai != NULL)
|
||||||
{
|
{
|
||||||
if (pai->pti2 == ptiTo && pai->pti1 == ptiFrom) break;
|
if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
|
||||||
paiprev = pai;
|
{
|
||||||
|
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;
|
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;
|
ptiFrom->MessageQueue = ptiFrom->pqAttach;
|
||||||
// FIXME: conditions?
|
// FIXME: conditions?
|
||||||
ptiFrom->MessageQueue->CursorObject = NULL;
|
ptiFrom->MessageQueue->CursorObject = NULL;
|
||||||
|
@ -505,7 +560,7 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
|
||||||
msg.pt = gpsi->ptCursor;
|
msg.pt = gpsi->ptCursor;
|
||||||
co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
|
co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
|
||||||
|
|
||||||
return TRUE;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -62,7 +62,7 @@ extern PATTACHINFO gpai;
|
||||||
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
||||||
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
||||||
DWORD NTAPI CreateSystemThreads(UINT Type);
|
DWORD NTAPI CreateSystemThreads(UINT Type);
|
||||||
BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
||||||
PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO);
|
PTHREADINFO FASTCALL IsThreadAttach(PTHREADINFO);
|
||||||
VOID FASTCALL DoTheScreenSaver(VOID);
|
VOID FASTCALL DoTheScreenSaver(VOID);
|
||||||
#define ThreadHasInputAccess(W32Thread) (TRUE)
|
#define ThreadHasInputAccess(W32Thread) (TRUE)
|
||||||
|
|
|
@ -401,6 +401,28 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
|
||||||
ppiCurrent = ptiCurrent->ppi;
|
ppiCurrent = ptiCurrent->ppi;
|
||||||
ASSERT(ppiCurrent);
|
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 */
|
/* Decrement thread count and check if its 0 */
|
||||||
ppiCurrent->cThreads--;
|
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 */
|
/* Free the message queue */
|
||||||
if (ptiCurrent->MessageQueue)
|
if (ptiCurrent->MessageQueue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ NtUserAttachThreadInput(
|
||||||
BOOL Ret = FALSE;
|
BOOL Ret = FALSE;
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
ERR("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
|
||||||
Status = PsLookupThreadByThreadId((HANDLE)idAttach, &Thread);
|
Status = PsLookupThreadByThreadId((HANDLE)idAttach, &Thread);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -53,9 +54,15 @@ NtUserAttachThreadInput(
|
||||||
ObDereferenceObject(Thread);
|
ObDereferenceObject(Thread);
|
||||||
ObDereferenceObject(ThreadTo);
|
ObDereferenceObject(ThreadTo);
|
||||||
|
|
||||||
Ret = UserAttachThreadInput( pti, ptiTo, fAttach);
|
Status = UserAttachThreadInput( pti, ptiTo, fAttach);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
EngSetLastError(RtlNtStatusToDosError(Status));
|
||||||
|
}
|
||||||
|
else Ret = TRUE;
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
|
ERR("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
|
||||||
UserLeave();
|
UserLeave();
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue