⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
STDCALL
NtUserDragDetect(
   HWND hWnd,
   LONG x,
   LONG y)
{
   UNIMPLEMENTED
   return 0;
}

BOOL FASTCALL
IntBlockInput(PW32THREAD W32Thread, BOOL BlockIt)
{
   PW32THREAD OldBlock;
   ASSERT(W32Thread);

   if(!W32Thread->Desktop || (W32Thread->IsExiting && BlockIt))
   {
      /*
       * fail blocking if exiting the thread
       */

      return FALSE;
   }

   /*
    * FIXME - check access rights of the window station
    *         e.g. services running in the service window station cannot block input
    */
   if(!ThreadHasInputAccess(W32Thread) ||
         !IntIsActiveDesktop(W32Thread->Desktop))
   {
      SetLastWin32Error(ERROR_ACCESS_DENIED);
      return FALSE;
   }

   ASSERT(W32Thread->Desktop);
   OldBlock = W32Thread->Desktop->BlockInputThread;
   if(OldBlock)
   {
      if(OldBlock != W32Thread)
      {
         SetLastWin32Error(ERROR_ACCESS_DENIED);
         return FALSE;
      }
      W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
      return OldBlock == NULL;
   }

   W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
   return OldBlock == NULL;
}

BOOL
STDCALL
NtUserBlockInput(
   BOOL BlockIt)
{
   DECLARE_RETURN(BOOLEAN);

   DPRINT("Enter NtUserBlockInput\n");
   UserEnterExclusive();

   RETURN( IntBlockInput(PsGetCurrentThreadWin32Thread(), BlockIt));

CLEANUP:
   DPRINT("Leave NtUserBlockInput, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

BOOL FASTCALL
IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
{
   PSYSTEM_CURSORINFO CurInfo;
   BOOL res;

   CurInfo = IntGetSysCursorInfo(WinStaObject);
   res = CurInfo->SwapButtons;
   CurInfo->SwapButtons = Swap;
   return res;
}

BOOL FASTCALL
IntMouseInput(MOUSEINPUT *mi)
{
   const UINT SwapBtnMsg[2][2] =
      {
         {
            WM_LBUTTONDOWN, WM_RBUTTONDOWN
         },
         {WM_LBUTTONUP, WM_RBUTTONUP}
      };
   const WPARAM SwapBtn[2] =
      {
         MK_LBUTTON, MK_RBUTTON
      };
   POINT MousePos = {0}, OrgPos;
   PSYSTEM_CURSORINFO CurInfo;
   PWINSTATION_OBJECT WinSta;
   BOOL DoMove, SwapButtons;
   MSG Msg;
   HBITMAP hBitmap;
   BITMAPOBJ *BitmapObj;
   SURFOBJ *SurfObj;
   PDC dc;
   PWINDOW_OBJECT DesktopWindow;

#if 1

   HDC hDC;

   /* FIXME - get the screen dc from the window station or desktop */
   if(!(hDC = IntGetScreenDC()))
   {
      return FALSE;
   }
#endif

   ASSERT(mi);
#if 0

   WinSta = PsGetCurrentProcessWin32Process()->WindowStation;
#else
   /* FIXME - ugly hack but as long as we're using this dumb callback from the
   mouse class driver, we can't access the window station from the calling
   process */
   WinSta = InputWindowStation;
#endif

   ASSERT(WinSta);

   CurInfo = IntGetSysCursorInfo(WinSta);

   if(!mi->time)
   {
      LARGE_INTEGER LargeTickCount;
      KeQueryTickCount(&LargeTickCount);
      mi->time = MsqCalculateMessageTime(&LargeTickCount);
   }

   SwapButtons = CurInfo->SwapButtons;
   DoMove = FALSE;

   IntGetCursorLocation(WinSta, &MousePos);
   OrgPos.x = MousePos.x;
   OrgPos.y = MousePos.y;

   if(mi->dwFlags & MOUSEEVENTF_MOVE)
   {
      if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
      {
         MousePos.x = mi->dx;
         MousePos.y = mi->dy;
      }
      else
      {
         MousePos.x += mi->dx;
         MousePos.y += mi->dy;
      }

      DesktopWindow = IntGetWindowObject(WinSta->ActiveDesktop->DesktopWindow);

      if (DesktopWindow)
      {
         if(MousePos.x >= DesktopWindow->ClientRect.right)
            MousePos.x = DesktopWindow->ClientRect.right - 1;
         if(MousePos.y >= DesktopWindow->ClientRect.bottom)
            MousePos.y = DesktopWindow->ClientRect.bottom - 1;
         ObmDereferenceObject(DesktopWindow);
      }

      if(MousePos.x < 0)
         MousePos.x = 0;
      if(MousePos.y < 0)
         MousePos.y = 0;

      if(CurInfo->CursorClipInfo.IsClipped)
      {
         /* The mouse cursor needs to be clipped */

         if(MousePos.x >= (LONG)CurInfo->CursorClipInfo.Right)
            MousePos.x = (LONG)CurInfo->CursorClipInfo.Right;
         if(MousePos.x < (LONG)CurInfo->CursorClipInfo.Left)
            MousePos.x = (LONG)CurInfo->CursorClipInfo.Left;
         if(MousePos.y >= (LONG)CurInfo->CursorClipInfo.Bottom)
            MousePos.y = (LONG)CurInfo->CursorClipInfo.Bottom;
         if(MousePos.y < (LONG)CurInfo->CursorClipInfo.Top)
            MousePos.y = (LONG)CurInfo->CursorClipInfo.Top;
      }

      DoMove = (MousePos.x != OrgPos.x || MousePos.y != OrgPos.y);
   }

   if (DoMove)
   {
      dc = DC_LockDc(hDC);
      if (dc)
      {
         hBitmap = dc->w.hBitmap;
         DC_UnlockDc(dc);

         BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
         if (BitmapObj)
         {
            SurfObj = &BitmapObj->SurfObj;

            IntEngMovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude));
            /* Only now, update the info in the GDIDEVICE, so EngMovePointer can
            * use the old values to move the pointer image */
            GDIDEV(SurfObj)->Pointer.Pos.x = MousePos.x;
            GDIDEV(SurfObj)->Pointer.Pos.y = MousePos.y;

            BITMAPOBJ_UnlockBitmap(BitmapObj);
         }
      }
   }

   /*
    * Insert the messages into the system queue
    */

   Msg.wParam = CurInfo->ButtonsDown;
   Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
   Msg.pt = MousePos;
   if(DoMove)
   {
      Msg.message = WM_MOUSEMOVE;
      MsqInsertSystemMessage(&Msg);
   }

   Msg.message = 0;
   if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
   {
      gQueueKeyStateTable[VK_LBUTTON] |= 0xc0;
      Msg.message = SwapBtnMsg[0][SwapButtons];
      CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
      MsqInsertSystemMessage(&Msg);
   }
   else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
   {
      gQueueKeyStateTable[VK_LBUTTON] &= ~0x80;
      Msg.message = SwapBtnMsg[1][SwapButtons];
      CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
      MsqInsertSystemMessage(&Msg);
   }
   if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
   {
      gQueueKeyStateTable[VK_MBUTTON] |= 0xc0;
      Msg.message = WM_MBUTTONDOWN;
      CurInfo->ButtonsDown |= MK_MBUTTON;
      MsqInsertSystemMessage(&Msg);
   }
   else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
   {
      gQueueKeyStateTable[VK_MBUTTON] &= ~0x80;
      Msg.message = WM_MBUTTONUP;
      CurInfo->ButtonsDown &= ~MK_MBUTTON;
      MsqInsertSystemMessage(&Msg);
   }
   if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
   {
      gQueueKeyStateTable[VK_RBUTTON] |= 0xc0;
      Msg.message = SwapBtnMsg[0][!SwapButtons];
      CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
      MsqInsertSystemMessage(&Msg);
   }
   else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
   {
      gQueueKeyStateTable[VK_RBUTTON] &= ~0x80;
      Msg.message = SwapBtnMsg[1][!SwapButtons];
      CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
      MsqInsertSystemMessage(&Msg);
   }

   if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
         (mi->dwFlags & MOUSEEVENTF_WHEEL))
   {
      /* fail because both types of events use the mouseData field */
      return FALSE;
   }

   if(mi->dwFlags & MOUSEEVENTF_XDOWN)
   {
      Msg.message = WM_XBUTTONDOWN;
      if(mi->mouseData & XBUTTON1)
      {
         gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0;
         Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
         CurInfo->ButtonsDown |= XBUTTON1;
         MsqInsertSystemMessage(&Msg);
      }
      if(mi->mouseData & XBUTTON2)
      {
         gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0;
         Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
         CurInfo->ButtonsDown |= XBUTTON2;
         MsqInsertSystemMessage(&Msg);
      }
   }
   else if(mi->dwFlags & MOUSEEVENTF_XUP)
   {
      Msg.message = WM_XBUTTONUP;
      if(mi->mouseData & XBUTTON1)
      {
         gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80;
         Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
         CurInfo->ButtonsDown &= ~XBUTTON1;
         MsqInsertSystemMessage(&Msg);
      }
      if(mi->mouseData & XBUTTON2)
      {
         gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80;
         Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
         CurInfo->ButtonsDown &= ~XBUTTON2;
         MsqInsertSystemMessage(&Msg);
      }
   }
   if(mi->dwFlags & MOUSEEVENTF_WHEEL)
   {
      Msg.message = WM_MOUSEWHEEL;
      Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
      MsqInsertSystemMessage(&Msg);
   }

   return TRUE;
}

BOOL FASTCALL
IntKeyboardInput(KEYBDINPUT *ki)
{
   return FALSE;
}

UINT
STDCALL
NtUserSendInput(
   UINT nInputs,
   LPINPUT pInput,
   INT cbSize)
{
   PW32THREAD W32Thread;
   UINT cnt;
   DECLARE_RETURN(UINT);

   DPRINT("Enter NtUserSendInput\n");
   UserEnterExclusive();

   W32Thread = PsGetCurrentThreadWin32Thread();
   ASSERT(W32Thread);

   if(!W32Thread->Desktop)
   {
      RETURN( 0);
   }

   if(!nInputs || !pInput || (cbSize != sizeof(INPUT)))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      RETURN( 0);
   }

   /*
    * FIXME - check access rights of the window station
    *         e.g. services running in the service window station cannot block input
    */
   if(!ThreadHasInputAccess(W32Thread) ||
         !IntIsActiveDesktop(W32Thread->Desktop))
   {
      SetLastWin32Error(ERROR_ACCESS_DENIED);
      RETURN( 0);
   }

   cnt = 0;
   while(nInputs--)
   {
      INPUT SafeInput;
      NTSTATUS Status;

      Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
      if(!NT_SUCCESS(Status))
      {
         SetLastNtError(Status);
         RETURN( cnt);
      }

      switch(SafeInput.type)
      {
         case INPUT_MOUSE:
            if(IntMouseInput(&SafeInput.mi))
            {
               cnt++;
            }
            break;
         case INPUT_KEYBOARD:
            if(IntKeyboardInput(&SafeInput.ki))
            {
               cnt++;
            }
            break;
         case INPUT_HARDWARE:
            break;
#ifndef NDEBUG

         default:
            DPRINT1("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
            break;
#endif

      }
   }

   RETURN( cnt);

CLEANUP:
   DPRINT("Leave NtUserSendInput, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -