📄 conshid.cpp
字号:
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
//
#include "conshid.h"
#include <windev.h>
#include "Oemioctl.h"
#ifdef DEBUG
// Debug Zones
#define DBG_ERROR 0x0001
#define DBG_WARNING 0x0002
#define DBG_INIT 0x0004
#define DBG_FUNCTION 0x0008
#define DBG_USAGES 0x0010
DBGPARAM dpCurSettings = {
TEXT("ConsHid"), {
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Function"),
TEXT("Usages"), TEXT(""), TEXT(""), TEXT(""),
TEXT(""), TEXT(""), TEXT(""), TEXT(""),
TEXT(""), TEXT(""), TEXT(""), TEXT("") },
DBG_ERROR | DBG_WARNING };
static
void
ValidateHidConsumer(
PHID_CONSUMER pHidConsumer
);
#else
#define ValidateHidConsumer(ptr)
#endif // DEBUG
// MapVirtualKey(x, 3) converts scan codes to virtual keys
#define MAP_SC_TO_VK 3
// Describes an association from a Usage to an AT Scan Code
struct USAGE_TO_SC_ASSOCIATION {
USAGE usage;
UINT16 uiSc;
};
// Usage to Virtual Key table
static const USAGE_TO_SC_ASSOCIATION g_rgUsageToScAssn[] = {
{ HID_CONSUMER_SCAN_NEXT_TRACK, 0xE04D },
{ HID_CONSUMER_SCAN_PREVIOUS_TRACK, 0xE015 },
{ HID_CONSUMER_STOP, 0xE03B },
{ HID_CONSUMER_PLAY_PAUSE, 0xE034 },
{ HID_CONSUMER_VOLUME_MUTE, 0xE023 },
{ HID_CONSUMER_VOLUME_INCREMENT, 0xE032 },
{ HID_CONSUMER_VOLUME_DECREMENT, 0xE021 },
{ HID_CONSUMER_LAUNCH_CONFIGURATION, 0xE050 },
{ HID_CONSUMER_LAUNCH_EMAIL, 0xE048 },
{ HID_CONSUMER_LAUNCH_CALCULATOR, 0xE02B },
{ HID_CONSUMER_LAUNCH_BROWSER, 0xE040 },
{ HID_CONSUMER_APP_SEARCH, 0xE010 },
{ HID_CONSUMER_APP_HOME, 0xE03A },
{ HID_CONSUMER_APP_BACK, 0xE038 },
{ HID_CONSUMER_APP_FORWARD, 0xE030 },
{ HID_CONSUMER_APP_STOP, 0xE028 },
{ HID_CONSUMER_APP_REFRESH, 0xE020 },
{ HID_CONSUMER_APP_BOOKMARKS, 0xE018 },
};
DWORD
SendKeyboardUsages(
PUSAGE pUsages,
DWORD dwMaxUsages,
HIDP_KEYBOARD_DIRECTION keyEvent
);
void
KeyboardEvent(
UINT vk,
UINT sc,
DWORD dwFlags
);
void
ProcessConsumerReport(
PHID_CONSUMER pHidConsumer,
PCHAR pbHidPacket,
DWORD cbHidPacket
);
BOOL
AllocateUsageLists(
PHID_CONSUMER pHidConsumer,
size_t cbUsages
);
VOID
FreeHidConsumer(
PHID_CONSUMER pHidConsumer
);
// Dll entry function.
extern "C"
BOOL
DllEntry(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpReserved
)
{
SETFNAME(_T("CONSHID DllEntry"));
UNREFERENCED_PARAMETER(lpReserved);
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hDllHandle);
DEBUGMSG(ZONE_INIT, (_T("%s: Attach\r\n"), pszFname));
DisableThreadLibraryCalls((HMODULE) hDllHandle);
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (_T("%s: Detach\r\n"), pszFname));
break;
default:
break;
}
return TRUE ;
}
// Get interrupt reports from the device. Thread exits when the device has
// been removed.
static
DWORD
WINAPI
ConsumerThreadProc(
LPVOID lpParameter
)
{
SETFNAME(_T("ConsumerThreadProc"));
PHID_CONSUMER pHidConsumer = (PHID_CONSUMER) lpParameter;
BOOL fGWEReady = FALSE;
PCHAR pbHidPacket;
DWORD cbHidPacket;
DWORD cbBuffer;
DWORD dwErr;
DEBUGCHK(pHidConsumer != NULL);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
cbBuffer = pHidConsumer->hidpCaps.InputReportByteLength;
pbHidPacket = (PCHAR) LocalAlloc(LMEM_FIXED, cbBuffer);
if (pbHidPacket == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
while (TRUE)
{
ValidateHidConsumer(pHidConsumer);
// Get an interrupt report from the device.
dwErr = pHidConsumer->pHidFuncs->lpGetInterruptReport(
pHidConsumer->hDevice,
pbHidPacket,
cbBuffer,
&cbHidPacket,
NULL,
INFINITE);
// Make sure gwes is ready to accept keystrokes.
// Since USB is part of device.exe it can attempt to send keystrokes
// before gwes is present (if something is leaning on keyboard at poweron).
if (fGWEReady == FALSE) {
fGWEReady = IsAPIReady(SH_WMGR);
}
if (dwErr == ERROR_DEVICE_REMOVED) {
// Exit thread
break;
}
else if (fGWEReady == FALSE) {
// We cannot do anything with these keystrokes.
DEBUGMSG(ZONE_ERROR, (_T("%s: Discarding keyboard event, no GWES yet\n"),
pszFname));
continue;
}
else {
DEBUGCHK(dwErr == ERROR_SUCCESS);
ProcessConsumerReport(pHidConsumer, pbHidPacket, cbHidPacket);
}
}
EXIT:
if (pbHidPacket != NULL) LocalFree(pbHidPacket);
DEBUGMSG(ZONE_FUNCTION, (_T("%s: Exiting thread\r\n"), pszFname));
return 0;
}
// Entry point for the HID driver. Initializes the structures for this
// keyboard and starts the thread that will receive interrupt reports.
extern "C"
BOOL
HIDDeviceAttach(
HID_HANDLE hDevice,
PCHID_FUNCS pHidFuncs,
const HID_DRIVER_SETTINGS *pDriverSettings,
PHIDP_PREPARSED_DATA phidpPreparsedData,
PVOID *ppvNotifyParameter,
DWORD dwUnused
)
{
SETFNAME(_T("HIDDeviceAttach"));
BOOL fRet = FALSE;
size_t cbUsages;
PHID_CONSUMER pHidConsumer;
DEBUGCHK(hDevice != NULL);
DEBUGCHK(pHidFuncs != NULL);
DEBUGCHK(phidpPreparsedData != NULL);
DEBUGCHK(ppvNotifyParameter != NULL);
// Allocate this device's data structure and fill it.
pHidConsumer = (PHID_CONSUMER) LocalAlloc(LPTR, sizeof(HID_CONSUMER));
if (pHidConsumer == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("%s: LocalAlloc error:%d\r\n"), pszFname, GetLastError()));
goto EXIT;
}
pHidConsumer->dwSig = HID_CONSUMER_SIG;
pHidConsumer->hDevice = hDevice;
pHidConsumer->pHidFuncs = pHidFuncs;
pHidConsumer->phidpPreparsedData = phidpPreparsedData;
HidP_GetCaps(pHidConsumer->phidpPreparsedData, &pHidConsumer->hidpCaps);
// Get the total number of usages that can be returned in an input packet.
pHidConsumer->dwMaxUsages = HidP_MaxUsageListLength(HidP_Input,
HID_USAGE_PAGE_CONSUMER, phidpPreparsedData);
if (pHidConsumer->dwMaxUsages == 0) {
DEBUGMSG(ZONE_WARNING, (_T("%s: This collection does not have any ")
_T("understood usages and will be ignored\r\n"), pszFname));
goto EXIT;
}
cbUsages = pHidConsumer->dwMaxUsages * sizeof(*pHidConsumer->puPrevUsages);
if (AllocateUsageLists(pHidConsumer, cbUsages) == FALSE) {
goto EXIT;
}
// Create the thread that will receive reports from this device
pHidConsumer->hThread = CreateThread(NULL, 0, ConsumerThreadProc, pHidConsumer, 0, NULL);
if (pHidConsumer->hThread == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: Failed creating keyboard thread\r\n"),
pszFname));
goto EXIT;
}
else
{
ThreadInfo TI;
TI.ThreadHandle = pHidConsumer->hThread;
strcpy((char *)TI.ThreadName, "USB ConsumerThreadProc");
KernelIoControl(IOCTL_SET_THREAD, (LPVOID)&TI, sizeof(ThreadInfo), NULL, 0, NULL);
}
#ifdef DEBUG
pHidConsumer->fhThreadInited = TRUE;
#endif
*ppvNotifyParameter = pHidConsumer;
ValidateHidConsumer(pHidConsumer);
fRet = TRUE;
EXIT:
if ((fRet == FALSE) && (pHidConsumer != NULL)) {
FreeHidConsumer(pHidConsumer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -