📄 mouhid.cpp
字号:
}
ValidateHidMouse(pHidMouse);
switch(dwMsg) {
case HID_CLOSE_DEVICE:
// Free all of our resources.
WaitForSingleObject(pHidMouse->hThread, INFINITE);
CloseHandle(pHidMouse->hThread);
pHidMouse->hThread = NULL;
// Send ups for each button that is still down.
SetButtonFlags(&dwFlags, pHidMouse->puPrevUsages, pHidMouse->dwMaxUsages,
g_rgdwUsageToUpButton, dim(g_rgdwUsageToUpButton));
MouseEvent(dwFlags, 0, 0, 0);
FreeHidMouse(pHidMouse);
fRet = TRUE;
break;
default:
DEBUGMSG(ZONE_ERROR, (_T("%s: Unhandled message %u\r\n"), pszFname));
break;
};
EXIT:
return fRet;
}
#ifdef DEBUG
// Match function with typedef.
static LPHID_CLIENT_NOTIFICATIONS g_pfnDeviceNotifications = HIDDeviceNotifications;
#endif
// Allocate the usage lists for this mouse. The lists are allocated in
// a single block and then divided up.
static
BOOL
AllocateUsageLists(
PHID_MOUSE pHidMouse,
size_t cbUsages
)
{
SETFNAME(_T("AllocateUsageLists"));
BOOL fRet = FALSE;
size_t cbTotal;
PBYTE pbStart;
DWORD dwIdx;
PUSAGE *rgppUsages[] = {
&pHidMouse->puPrevUsages,
&pHidMouse->puCurrUsages,
&pHidMouse->puBreakUsages,
&pHidMouse->puMakeUsages
};
DEBUGCHK(pHidMouse != NULL);
// Allocate a block of memory for all the usage lists
cbTotal = cbUsages * dim(rgppUsages);
pbStart = (PBYTE) LocalAlloc(LPTR, cbTotal);
if (pbStart == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
// Divide the block.
for (dwIdx = 0; dwIdx < dim(rgppUsages); ++dwIdx) {
*rgppUsages[dwIdx] = (PUSAGE) (pbStart + (cbUsages * dwIdx));
}
fRet = TRUE;
EXIT:
return fRet;
}
// Find out if this mouse has a wheel or Z axis
static
void
DetermineWheelUsage(
PHID_MOUSE pHidMouse
)
{
static const USAGE rgWheelUsages[] = {
HID_USAGE_GENERIC_WHEEL,
HID_USAGE_GENERIC_Z,
};
NTSTATUS status;
HIDP_VALUE_CAPS hidpValueCaps;
USHORT cValueCaps;
DWORD dwIdx;
PREFAST_DEBUGCHK(pHidMouse != NULL);
for (dwIdx = 0; dwIdx < dim(rgWheelUsages); ++dwIdx)
{
USAGE usageCurr = rgWheelUsages[dwIdx];
cValueCaps = 1; // Only one structure to fill
status = HidP_GetSpecificValueCaps(
HidP_Input,
HID_USAGE_PAGE_GENERIC,
0,
usageCurr,
&hidpValueCaps,
&cValueCaps,
pHidMouse->phidpPreparsedData);
if (NT_SUCCESS(status)) {
// We found our wheel axis
pHidMouse->usageWheel = usageCurr;
break;
}
}
if (dwIdx == dim(rgWheelUsages)) {
// We did not find a wheel axis
pHidMouse->usageWheel = HAS_NO_WHEEL;
}
}
// Set the mouse_event button flags for this list of usages.
static
void
SetButtonFlags(
PDWORD pdwFlags,
PUSAGE pUsages,
DWORD dwMaxUsages,
const DWORD *pdwUsageMappings, // Array of usage->flags to use
DWORD cdwUsageMappings // Count of usage->flags mappings
)
{
DWORD dwIdx;
DEBUGCHK(pdwFlags != NULL);
PREFAST_DEBUGCHK(pUsages != NULL);
DEBUGCHK(pdwUsageMappings != NULL);
for (dwIdx = 0; dwIdx < dwMaxUsages; ++dwIdx) {
const USAGE usage = pUsages[dwIdx];
if (usage == 0) {
// No more set usages
break;
}
else if (usage < cdwUsageMappings) {
*pdwFlags |= pdwUsageMappings[usage];
}
// else this is a button we do not handle.
}
}
// Determine the movement on the axis defined by usage. Store it in pDelta.
static
NTSTATUS
GetAxisMovement(
PHID_MOUSE pHidMouse,
USAGE usage, // X, Y, Z, or Wheel
PCHAR pbHidPacket,
DWORD cbHidPacket,
PLONG pDelta
)
{
SETFNAME(_T("GetAxisMovement"));
NTSTATUS status;
PREFAST_DEBUGCHK(pHidMouse != NULL);
DEBUGCHK(pbHidPacket != NULL);
PREFAST_DEBUGCHK(pDelta != NULL);
status = HidP_GetScaledUsageValue(
HidP_Input,
HID_USAGE_PAGE_GENERIC,
0,
usage,
pDelta,
pHidMouse->phidpPreparsedData,
pbHidPacket,
cbHidPacket);
if (status == HIDP_STATUS_BAD_LOG_PHY_VALUES) {
// Bad physical max/min detected.
DEBUGMSG(ZONE_ERROR, (_T("%s: Bad physical max/min for mouse axis usage 0x%x\r\n"),
pszFname, usage));
*pDelta = 0;
}
return status;
}
// Take a report generated by the device and convert it to a mouse_event
static
void
ProcessMouseReport(
PHID_MOUSE pHidMouse,
PCHAR pbHidPacket,
DWORD cbHidPacket
)
{
SETFNAME(_T("ProcessMouseReport"));
NTSTATUS status;
ULONG uCurrUsages;
DWORD cbUsageList;
DWORD dwFlags;
LONG dx, dy, dz;
PREFAST_DEBUGCHK(pHidMouse != NULL);
DEBUGCHK(pbHidPacket != NULL);
DEBUGCHK(dim(g_rgdwUsageToDownButton) == dim(g_rgdwUsageToUpButton));
ValidateHidMouse(pHidMouse);
dwFlags = dx = dy = dz = 0;
uCurrUsages = pHidMouse->dwMaxUsages;
cbUsageList = uCurrUsages * sizeof(USAGE);
//
// Handle mouse buttons
//
// Get the usage list from this packet.
status = HidP_GetUsages(
HidP_Input,
HID_USAGE_PAGE_BUTTON,
0,
pHidMouse->puCurrUsages,
&uCurrUsages, // IN OUT parameter
pHidMouse->phidpPreparsedData,
pbHidPacket,
cbHidPacket);
if (NT_SUCCESS(status)) {
status = HidP_UsageListDifference(
pHidMouse->puPrevUsages,
pHidMouse->puCurrUsages,
pHidMouse->puBreakUsages,
pHidMouse->puMakeUsages,
pHidMouse->dwMaxUsages);
if (NT_SUCCESS(status)) {
// Determine which buttons went up and down.
SetButtonFlags(&dwFlags, pHidMouse->puBreakUsages, pHidMouse->dwMaxUsages,
g_rgdwUsageToUpButton, dim(g_rgdwUsageToUpButton));
SetButtonFlags(&dwFlags, pHidMouse->puMakeUsages, pHidMouse->dwMaxUsages,
g_rgdwUsageToDownButton, dim(g_rgdwUsageToDownButton));
}
}
// else maybe we do not have any buttons (HIDP_STATUS_USAGE_NOT_FOUND)
//
// Handle mouse axis movement
//
GetAxisMovement(pHidMouse, HID_USAGE_GENERIC_X, pbHidPacket, cbHidPacket, &dx);
GetAxisMovement(pHidMouse, HID_USAGE_GENERIC_Y, pbHidPacket, cbHidPacket, &dy);
if ((dx != 0) || (dy != 0)) {
dwFlags |= MOUSEEVENTF_MOVE;
}
if (pHidMouse->usageWheel != HAS_NO_WHEEL) {
GetAxisMovement(pHidMouse, pHidMouse->usageWheel, pbHidPacket, cbHidPacket, &dz);
if (dz != 0) {
dz *= WHEEL_DELTA;
dwFlags |= MOUSEEVENTF_WHEEL;
}
}
if (dwFlags) {
// Send this mouse event
MouseEvent(dwFlags, dx, dy, dz);
}
// Save the current usages.
memcpy(pHidMouse->puPrevUsages, pHidMouse->puCurrUsages, cbUsageList);
}
// Send the mouse event to GWES
static
void
MouseEvent(
DWORD dwFlags,
DWORD dx,
DWORD dy,
DWORD dwData
)
{
SETFNAME(_T("MouseEvent"));
BOOL fSendEventToSystem = TRUE;
DEBUGMSG(ZONE_USAGES, (_T("%s: HID: dx %4d, dy %4d, dwData %4d, flags 0x%04x\r\n"), pszFname,
dx, dy, dwData, dwFlags));
if (g_fUseMouseHook) {
// See if any mouse hook app, such as Transcriber wants the mouse event
fSendEventToSystem = !DriverMouseHook(dwFlags, dx, dy, dwData);
}
if (fSendEventToSystem) {
mouse_event(dwFlags, dx, dy, dwData, 0);
}
}
// Free the memory used by pHidKbd
void
FreeHidMouse(
PHID_MOUSE pHidMouse
)
{
PREFAST_DEBUGCHK(pHidMouse != NULL);
DEBUGCHK(pHidMouse->hThread == NULL); // We do not close the thread handle
if (pHidMouse->puPrevUsages != NULL) LocalFree(pHidMouse->puPrevUsages);
LocalFree(pHidMouse);
}
#ifdef DEBUG
// Validate a PHID_KBD structure
static
void
ValidateHidMouse(
PHID_MOUSE pHidMouse
)
{
DWORD cbUsageList;
PREFAST_DEBUGCHK(pHidMouse != NULL);
DEBUGCHK(pHidMouse->dwSig == HID_MOUSE_SIG);
DEBUGCHK(pHidMouse->hDevice != NULL);
DEBUGCHK(pHidMouse->pHidFuncs != NULL);
DEBUGCHK(pHidMouse->phidpPreparsedData != NULL);
DEBUGCHK(pHidMouse->hidpCaps.UsagePage == HID_USAGE_PAGE_GENERIC);
DEBUGCHK(pHidMouse->hidpCaps.Usage == HID_USAGE_GENERIC_MOUSE);
if (pHidMouse->fhThreadInited == TRUE) {
DEBUGCHK(pHidMouse->hThread != NULL);
}
cbUsageList = pHidMouse->dwMaxUsages * sizeof(*pHidMouse->puPrevUsages);
DEBUGCHK(pHidMouse->puPrevUsages != NULL);
DEBUGCHK(LocalSize(pHidMouse->puPrevUsages) >= cbUsageList * 4);
DEBUGCHK((DWORD) pHidMouse->puCurrUsages == ((DWORD) pHidMouse->puPrevUsages) + cbUsageList);
DEBUGCHK((DWORD) pHidMouse->puBreakUsages == ((DWORD) pHidMouse->puCurrUsages) + cbUsageList);
DEBUGCHK((DWORD) pHidMouse->puMakeUsages == ((DWORD) pHidMouse->puBreakUsages) + cbUsageList);
DEBUGCHK( (pHidMouse->usageWheel == HID_USAGE_GENERIC_WHEEL) ||
(pHidMouse->usageWheel == HID_USAGE_GENERIC_Z) ||
(pHidMouse->usageWheel == HAS_NO_WHEEL) );
}
#endif // DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -