return ret;
}
-PTHREADINFO FASTCALL
-IsThreadAttach(PTHREADINFO ptiTo)
+BOOL
+FASTCALL
+IsRemoveAttachThread(PTHREADINFO pti)
{
+ NTSTATUS Status;
PATTACHINFO pai;
+ BOOL Ret = TRUE;
+ PTHREADINFO ptiFrom = NULL, ptiTo = NULL;
- if (!gpai) return NULL;
-
- pai = gpai;
do
{
- if (pai->pti2 == ptiTo) break;
- pai = pai->paiNext;
- } while (pai);
-
- if (!pai) return NULL;
-
- // Return ptiFrom.
- return pai->pti1;
+ if (!gpai) return TRUE;
+
+ pai = gpai; // Bottom of the list.
+
+ do
+ {
+ if (pai->pti2 == pti)
+ {
+ ptiFrom = pai->pti1;
+ ptiTo = pti;
+ break;
+ }
+ if (pai->pti1 == pti)
+ {
+ ptiFrom = pti;
+ ptiTo = pai->pti2;
+ break;
+ }
+ pai = pai->paiNext;
+
+ } while (pai);
+
+ if (!pai && !ptiFrom && !ptiTo) break;
+
+ Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE);
+ if (!NT_SUCCESS(Status)) Ret = FALSE;
+
+ } while (Ret);
+
+ return Ret;
}
NTSTATUS FASTCALL
paiCount++;
ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
- if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
+ if (ptiTo->MessageQueue != ptiFrom->MessageQueue)
{
- ERR("Attach Threads are already associated!\n");
- }
- ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
+ ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
- /* 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;
+ // FIXME: conditions?
+ if (ptiTo->MessageQueue == gpqForeground)
+ {
+ ERR("ptiTo is Foreground\n");
+ }
+ else
+ {
+ ERR("ptiTo NOT Foreground\n");
+ }
- ptiFrom->MessageQueue->cThreads++;
- ERR("ptiTo S Share count %lu\n", ptiFrom->MessageQueue->cThreads);
+ if (ptiFrom->MessageQueue == gpqForeground)
+ {
+ ERR("ptiFrom is Foreground\n");
+ ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
+ ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
+ ptiTo->MessageQueue->CursorObject = ptiFrom->MessageQueue->CursorObject;
+ ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture;
+ ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED);
+ ptiTo->MessageQueue->CaretInfo = ptiFrom->MessageQueue->CaretInfo;
+ IntSetFocusMessageQueue(NULL);
+ IntSetFocusMessageQueue(ptiTo->MessageQueue);
+ gptiForeground = ptiTo;
+ }
+ else
+ {
+ ERR("ptiFrom NOT Foreground\n");
+ }
- // 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;
- ptiFrom->MessageQueue->spwndCapture = ptiFrom->pqAttach->spwndCapture;
- 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");
+ MsqDestroyMessageQueue(ptiFrom);
+
+ ptiFrom->MessageQueue = ptiTo->MessageQueue;
+
+ ptiFrom->MessageQueue->cThreads++;
+ ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
+
+ IntReferenceMessageQueue(ptiTo->MessageQueue);
}
else
{
- ERR("ptiTo NOT Foreground\n");
+ ERR("Attach Threads are already associated!\n");
}
}
else /* If clear, unlink and free it. */
}
if (!Hit) return STATUS_INVALID_PARAMETER;
-
- ASSERT(ptiFrom->pqAttach);
ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
+
+ if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
+ {
+ if (gptiForeground == ptiFrom)
+ {
+ ERR("ptiTo is now pti FG.\n");
+ // MessageQueue foreground is set so switch threads.
+ gptiForeground = ptiTo;
+ }
+ ptiTo->MessageQueue->cThreads--;
+ ERR("ptiTo E Share count %d\n", ptiTo->MessageQueue->cThreads);
+ ASSERT(ptiTo->MessageQueue->cThreads >= 1);
+
+ IntDereferenceMessageQueue(ptiTo->MessageQueue);
+
+ ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
- /* Search list and check if the thread is attached one more time */
- pai = gpai;
- while(pai)
+ ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
+ }
+ else
{
- /* If the thread is attached again , we are done */
- if (pai->pti1 == ptiFrom)
- {
- ptiFrom->MessageQueue->cThreads--;
- ERR("ptiTo L Share count %lu\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;
+ ERR("Detaching Threads are not associated!\n");
}
-
- ptiFrom->MessageQueue->cThreads--;
- ERR("ptiTo E Share count %lu\n", ptiFrom->MessageQueue->cThreads);
- ptiFrom->MessageQueue = ptiFrom->pqAttach;
- // FIXME: conditions?
- ptiFrom->MessageQueue->CursorObject = NULL;
- ptiFrom->MessageQueue->spwndActive = NULL;
- ptiFrom->MessageQueue->spwndFocus = NULL;
- ptiFrom->MessageQueue->spwndCapture = NULL;
- ptiFrom->pqAttach = NULL;
- ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
}
/* Note that key state, which can be ascertained by calls to the GetKeyState
or GetKeyboardState function, is reset after a call to AttachThreadInput.