📄 input.c
字号:
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 + -