[WIN32K:NTUSER]
[reactos.git] / reactos / win32ss / user / ntuser / input.c
index 9ac0603..22ac414 100644 (file)
@@ -100,7 +100,7 @@ OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceN
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &DeviceName,
-                               0,
+                               OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
 
@@ -125,17 +125,19 @@ OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceN
  * 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;
 
     ByteOffset.QuadPart = (LONGLONG)0;
     //WaitTimeout.QuadPart = (LONGLONG)(-10000000);
@@ -156,6 +158,7 @@ RawInputThreadMain()
     NT_ASSERT(ghMouseDevice == NULL);
     NT_ASSERT(ghKeyboardDevice == NULL);
 
+    PoRequestShutdownEvent(&ShutdownEvent);
     for (;;)
     {
         if (!ghMouseDevice)
@@ -189,6 +192,7 @@ RawInputThreadMain()
 
         /* Reset WaitHandles array */
         cWaitObjects = 0;
+        WaitObjects[cWaitObjects++] = ShutdownEvent;
         WaitObjects[cWaitObjects++] = MasterTimer;
 
         if (ghMouseDevice)
@@ -241,7 +245,7 @@ RawInputThreadMain()
                                               KernelMode,
                                               TRUE,
                                               NULL,//&WaitTimeout,
-                                              NULL);
+                                              WaitBlockArray);
 
             if ((Status >= STATUS_WAIT_0) &&
                 (Status < (STATUS_WAIT_0 + (LONG)cWaitObjects)))
@@ -264,6 +268,10 @@ RawInputThreadMain()
                 {
                     ProcessTimers();
                 }
+                else if (pSignaledObject == ShutdownEvent)
+                {
+                    break;
+                }
                 else ASSERT(FALSE);
             }
         }
@@ -302,6 +310,23 @@ RawInputThreadMain()
         else if (KbdStatus != STATUS_PENDING)
             ERR("Failed to read from keyboard: %x.\n", KbdStatus);
     }
+
+    if (ghMouseDevice)
+    {
+        (void)ZwCancelIoFile(ghMouseDevice, &MouIosb);
+        ObCloseHandle(ghMouseDevice, KernelMode);
+        ObDereferenceObject(pMouDevice);
+        ghMouseDevice = NULL;
+    }
+
+    if (ghKeyboardDevice)
+    {
+        (void)ZwCancelIoFile(ghKeyboardDevice, &KbdIosb);
+        ObCloseHandle(ghKeyboardDevice, KernelMode);
+        ObDereferenceObject(pKbdDevice);
+        ghKeyboardDevice = NULL;
+    }
+
     ERR("Raw Input Thread Exit!\n");
 }
 
@@ -492,16 +517,6 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
 
            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");
@@ -509,7 +524,9 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
               ptiTo->MessageQueue->spwndFocus   = ptiFrom->MessageQueue->spwndFocus;
               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;
@@ -517,14 +534,25 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
            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;
            }
 
@@ -533,8 +561,8 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
            // 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;
-              UserReferenceObject(CurIcon);
            }
 
            ptiFrom->MessageQueue->cThreads++;
@@ -577,6 +605,9 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
 
         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");
@@ -591,6 +622,22 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
 
            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
@@ -604,6 +651,8 @@ UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
      */
     RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
 
+    ptiTo->MessageQueue->msgDblClk.message = 0;
+
     /* Generate mouse move message */
     msg.message = WM_MOUSEMOVE;
     msg.wParam = UserGetMouseButtonsState();