* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: General input functions
- * FILE: subsystems/win32/win32k/ntuser/input.c
+ * FILE: win32ss/user/ntuser/input.c
* PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Rafal Harabien (rafalh@reactos.org)
*/
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
- 0,
+ OBJ_KERNEL_HANDLE,
NULL,
NULL);
* Reads data from input devices and supports win32 timers
*/
VOID NTAPI
-RawInputThreadMain()
+RawInputThreadMain(VOID)
{
NTSTATUS MouStatus = STATUS_UNSUCCESSFUL, KbdStatus = STATUS_UNSUCCESSFUL, Status;
IO_STATUS_BLOCK MouIosb, KbdIosb;
PFILE_OBJECT pKbdDevice = NULL, pMouDevice = NULL;
LARGE_INTEGER ByteOffset;
//LARGE_INTEGER WaitTimeout;
- PVOID WaitObjects[3], pSignaledObject = NULL;
- ULONG cWaitObjects = 0, cMaxWaitObjects = 1;
+ PVOID WaitObjects[4], pSignaledObject = NULL;
+ KWAIT_BLOCK WaitBlockArray[RTL_NUMBER_OF(WaitObjects)];
+ ULONG cWaitObjects = 0, cMaxWaitObjects = 2;
MOUSE_INPUT_DATA MouseInput;
KEYBOARD_INPUT_DATA KeyInput;
+ PVOID ShutdownEvent;
+ HWINSTA hWinSta;
ByteOffset.QuadPart = (LONGLONG)0;
//WaitTimeout.QuadPart = (LONGLONG)(-10000000);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
+ Status = ObOpenObjectByPointer(InputWindowStation,
+ 0,
+ NULL,
+ MAXIMUM_ALLOWED,
+ ExWindowStationObjectType,
+ UserMode,
+ (PHANDLE)&hWinSta);
+ if (NT_SUCCESS(Status))
+ {
+ UserSetProcessWindowStation(hWinSta);
+ }
+ else
+ {
+ ASSERT(FALSE);
+ /* Failed to open the interactive winsta! What now? */
+ }
+
UserEnterExclusive();
StartTheTimers();
UserLeave();
- for(;;)
+ NT_ASSERT(ghMouseDevice == NULL);
+ NT_ASSERT(ghKeyboardDevice == NULL);
+
+ PoRequestShutdownEvent(&ShutdownEvent);
+ for (;;)
{
if (!ghMouseDevice)
{
UserEnterExclusive();
// Register the Window hotkey.
UserRegisterHotKey(PWND_BOTTOM, IDHK_WINKEY, MOD_WIN, 0);
+ // Register the Window Snap hotkey.
+ UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_LEFT, MOD_WIN, VK_LEFT);
+ UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_RIGHT, MOD_WIN, VK_RIGHT);
+ UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_UP, MOD_WIN, VK_UP);
+ UserRegisterHotKey(PWND_BOTTOM, IDHK_SNAP_DOWN, MOD_WIN, VK_DOWN);
// Register the debug hotkeys.
StartDebugHotKeys();
UserLeave();
/* Reset WaitHandles array */
cWaitObjects = 0;
+ WaitObjects[cWaitObjects++] = ShutdownEvent;
WaitObjects[cWaitObjects++] = MasterTimer;
if (ghMouseDevice)
KernelMode,
TRUE,
NULL,//&WaitTimeout,
- NULL);
+ WaitBlockArray);
if ((Status >= STATUS_WAIT_0) &&
(Status < (STATUS_WAIT_0 + (LONG)cWaitObjects)))
pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
/* Check if it is mouse or keyboard and update status */
- if (pSignaledObject == &pMouDevice->Event)
+ if ((MouStatus == STATUS_PENDING) &&
+ (pSignaledObject == &pMouDevice->Event))
+ {
MouStatus = MouIosb.Status;
- else if (pSignaledObject == &pKbdDevice->Event)
+ }
+ else if ((KbdStatus == STATUS_PENDING) &&
+ (pSignaledObject == &pKbdDevice->Event))
+ {
KbdStatus = KbdIosb.Status;
+ }
else if (pSignaledObject == MasterTimer)
{
ProcessTimers();
}
+ else if (pSignaledObject == ShutdownEvent)
+ {
+ break;
+ }
else ASSERT(FALSE);
}
}
else if (KbdStatus != STATUS_PENDING)
ERR("Failed to read from keyboard: %x.\n", KbdStatus);
}
- ERR("Raw Input Thread Exit!\n");
-}
-
-/*
- * CreateSystemThreads
- *
- * Called form dedicated thread in CSRSS. RIT is started in context of this
- * thread because it needs valid Win32 process with TEB initialized
- */
-DWORD NTAPI
-CreateSystemThreads(UINT Type)
-{
- UserLeave();
- switch (Type)
+ if (ghMouseDevice)
{
- case 0: RawInputThreadMain(); break;
- case 1: DesktopThreadMain(); break;
- default: ERR("Wrong type: %x\n", Type);
+ (void)ZwCancelIoFile(ghMouseDevice, &MouIosb);
+ ObCloseHandle(ghMouseDevice, KernelMode);
+ ObDereferenceObject(pMouDevice);
+ ghMouseDevice = NULL;
}
- UserEnterShared();
+ if (ghKeyboardDevice)
+ {
+ (void)ZwCancelIoFile(ghKeyboardDevice, &KbdIosb);
+ ObCloseHandle(ghKeyboardDevice, KernelMode);
+ ObDereferenceObject(pKbdDevice);
+ ghKeyboardDevice = NULL;
+ }
- return 0;
+ ERR("Raw Input Thread Exit!\n");
}
/*
do
{
if (!gpai) return TRUE;
-
+
pai = gpai; // Bottom of the list.
do
break;
}
pai = pai->paiNext;
-
+
} while (pai);
if (!pai && !ptiFrom && !ptiTo) break;
{
MSG msg;
PATTACHINFO pai;
+ PCURICON_OBJECT CurIcon;
/* Can not be the same thread. */
if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
- // FIXME: conditions?
- if (ptiTo->MessageQueue == gpqForeground)
- {
- ERR("ptiTo is Foreground\n");
- }
- else
- {
- ERR("ptiTo NOT Foreground\n");
- }
-
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;
+ RtlCopyMemory(&ptiTo->MessageQueue->CaretInfo,
+ &ptiFrom->MessageQueue->CaretInfo,
+ sizeof(ptiTo->MessageQueue->CaretInfo));
IntSetFocusMessageQueue(NULL);
IntSetFocusMessageQueue(ptiTo->MessageQueue);
gptiForeground = ptiTo;
else
{
ERR("ptiFrom NOT Foreground\n");
+ if ( ptiTo->MessageQueue->spwndActive == 0 )
+ ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
+ if ( ptiTo->MessageQueue->spwndFocus == 0 )
+ ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
}
+ CurIcon = ptiFrom->MessageQueue->CursorObject;
+
MsqDestroyMessageQueue(ptiFrom);
+ if (CurIcon)
+ {
+ // Could be global. Keep it above the water line!
+ UserReferenceObject(CurIcon);
+ }
+
+ if (CurIcon && UserObjectInDestroy(UserHMGetHandle(CurIcon)))
+ {
+ UserDereferenceObject(CurIcon);
+ CurIcon = NULL;
+ }
+
ptiFrom->MessageQueue = ptiTo->MessageQueue;
+ // Pass cursor From if To is null. Pass test_SetCursor parent_id == current pti ID.
+ if (CurIcon && ptiTo->MessageQueue->CursorObject == NULL)
+ {
+ ERR("ptiTo receiving ptiFrom Cursor\n");
+ ptiTo->MessageQueue->CursorObject = CurIcon;
+ }
+
ptiFrom->MessageQueue->cThreads++;
- ERR("ptiTo S Share count %d\n", ptiFrom->MessageQueue->cThreads);
+ ERR("ptiTo S Share count %u\n", ptiFrom->MessageQueue->cThreads);
IntReferenceMessageQueue(ptiTo->MessageQueue);
}
}
if (!Hit) return STATUS_INVALID_PARAMETER;
-
+
ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
-
+
if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
{
+ PWND spwndActive = ptiTo->MessageQueue->spwndActive;
+ PWND spwndFocus = ptiTo->MessageQueue->spwndFocus;
+
if (gptiForeground == ptiFrom)
{
ERR("ptiTo is now pti FG.\n");
gptiForeground = ptiTo;
}
ptiTo->MessageQueue->cThreads--;
- ERR("ptiTo E Share count %d\n", ptiTo->MessageQueue->cThreads);
+ ERR("ptiTo E Share count %u\n", ptiTo->MessageQueue->cThreads);
ASSERT(ptiTo->MessageQueue->cThreads >= 1);
IntDereferenceMessageQueue(ptiTo->MessageQueue);
ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
+ if (spwndActive)
+ {
+ if (spwndActive->head.pti == ptiFrom)
+ {
+ ptiFrom->MessageQueue->spwndActive = spwndActive;
+ ptiTo->MessageQueue->spwndActive = 0;
+ }
+ }
+ if (spwndFocus)
+ {
+ if (spwndFocus->head.pti == ptiFrom)
+ {
+ ptiFrom->MessageQueue->spwndFocus = spwndFocus;
+ ptiTo->MessageQueue->spwndFocus = 0;
+ }
+ }
ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
}
else
*/
RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
+ ptiTo->MessageQueue->msgDblClk.message = 0;
+
/* Generate mouse move message */
msg.message = WM_MOUSEMOVE;
msg.wParam = UserGetMouseButtonsState();
BOOL Ret = FALSE;
UserEnterExclusive();
- ERR("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
+ TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
- pti = IntTID2PTI((HANDLE)idAttach);
- ptiTo = IntTID2PTI((HANDLE)idAttachTo);
+ pti = IntTID2PTI(UlongToHandle(idAttach));
+ ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
if ( !pti || !ptiTo )
{
- ERR("AttachThreadInput pti or ptiTo NULL.\n");
+ TRACE("AttachThreadInput pti or ptiTo NULL.\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
goto Exit;
}
Status = UserAttachThreadInput( pti, ptiTo, fAttach);
if (!NT_SUCCESS(Status))
{
- ERR("AttachThreadInput Error Status 0x%x. \n",Status);
+ TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
EngSetLastError(RtlNtStatusToDosError(Status));
}
else Ret = TRUE;
Exit:
- ERR("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
+ TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
UserLeave();
return Ret;
}