win32k!xxxKeyEvent函数里面的win32k!xxxDoHotKeyStuff如何确定是CAD键的到来的
win32k!xxxKeyEvent函数里面的win32k!xxxDoHotKeyStuff如何确定是CAD键的到来的
chenghao@chenghaodeiMac core % grep "StartDeviceRead" -nr|grep -v "inary"
./ntuser/kernel/pnp.c:1687:* StartDeviceRead
./ntuser/kernel/pnp.c:1702:PDEVICEINFO StartDeviceRead(
./ntuser/kernel/pnp.c:1762: TAGMSG1(DBGTAG_PNP, "StartDeviceRead: pDevInfo=%p has been closed on demand.", pDeviceInfo);
./ntuser/kernel/pnp.c:1767: TAGMSG1(DBGTAG_PNP, "StartDeviceRead: pDevInfo=%p, bFlags has been reset.", pDeviceInfo);
./ntuser/kernel/pnp.c:1876: RIPMSG2(RIP_WARNING, "StartDeviceRead %#p failed Status %#x",
./ntuser/kernel/pnp.c:2108: pDeviceInfoNext = StartDeviceRead(pDeviceInfo);
./ntuser/kernel/pnp.c:2122: pDeviceInfoNext = StartDeviceRead(pDeviceInfo);
./ntuser/kernel/pnp.c:2214: pDeviceInfoNext = StartDeviceRead(pDeviceInfo);
./ntuser/kernel/pnp.c:2248: pDeviceInfoNext = StartDeviceRead(pDeviceInfo);
./ntuser/kernel/userk.h:4520:PDEVICEINFO StartDeviceRead(PDEVICEINFO pDeviceInfo);
./ntuser/kernel/ntinput.c:651: * (see StartDeviceRead).
./ntuser/kernel/ntinput.c:2084: StartDeviceRead(pDeviceInfo);
./ntuser/kernel/ntinput.c:2091:* has been processed by USER, StartDeviceRead() is called again to request
./ntuser/kernel/ntinput.c:4347:* have been consumed, calls StartDeviceRead() to request more keyboard events.
VOID NTAPI InputApc(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved
)
{
PDEVICEINFO pDeviceInfo = (PDEVICEINFO)ApcContext;
UNREFERENCED_PARAMETER(Reserved);
/*
* Check if the RIT is being terminated.
* If we hit this assertion, the RIT was killed by someone inadvertently.
* Not much can be done if it once happens.
*/
UserAssert(gptiRit);
UserAssert((gptiRit->TIF_flags & TIF_INCLEANUP) == 0);
#ifdef DIAGNOSE_IO
pDeviceInfo->nReadsOutstanding--;
#endif
/*
* If this device needs freeing, abandon reading now and request the free.
* (Don't even process the input that we received in this APC)
*/
if (pDeviceInfo->usActions & GDIAF_FREEME) {
#ifdef GENERIC_INPUT
CheckCritOut();
EnterCrit();
#endif
EnterDeviceInfoListCrit();
pDeviceInfo->bFlags &= ~GDIF_READING;
FreeDeviceInfo(pDeviceInfo);
LeaveDeviceInfoListCrit();
#ifdef GENERIC_INPUT
LeaveCrit();
#endif
return;
}
if (NT_SUCCESS(IoStatusBlock->Status) && pDeviceInfo->handle) {
PDEVICE_TEMPLATE pDevTpl = &aDeviceTemplate[pDeviceInfo->type];
pDevTpl->DeviceRead(pDeviceInfo);
}
if (IsRemoteConnection()) {
PoSetSystemState(ES_SYSTEM_REQUIRED);
}
StartDeviceRead(pDeviceInfo);
}
DEVICE_TEMPLATE aDeviceTemplate[DEVICE_TYPE_MAX + 1] = {
// DEVICE_TYPE_MOUSE
{
sizeof(GENERIC_DEVICE_INFO)+sizeof(MOUSE_DEVICE_INFO), // cbDeviceInfo
&GUID_CLASS_MOUSE, // pClassGUID
PMAP_MOUCLASS_PARAMS, // uiRegistrySection
L"mouclass", // pwszClassName
DD_MOUSE_DEVICE_NAME_U L"0", // pwszDefDevName
DD_MOUSE_DEVICE_NAME_U L"Legacy0", // pwszLegacyDevName
IOCTL_MOUSE_QUERY_ATTRIBUTES, // IOCTL_Attr
FIELD_OFFSET(DEVICEINFO, mouse.Attr), // offAttr
sizeof((PDEVICEINFO)NULL)->mouse.Attr, // cbAttr
FIELD_OFFSET(DEVICEINFO, mouse.Data), // offData
sizeof((PDEVICEINFO)NULL)->mouse.Data, // cbData
ProcessMouseInput, // Reader routine
NULL // pkeHidChange
},
// DEVICE_TYPE_KEYBOARD
{
sizeof(GENERIC_DEVICE_INFO)+sizeof(KEYBOARD_DEVICE_INFO), // cbDeviceInfo
&GUID_CLASS_KEYBOARD, // pClassGUID
PMAP_KBDCLASS_PARAMS, // uiRegistrySection
L"kbdclass", // pwszClassName
DD_KEYBOARD_DEVICE_NAME_U L"0", // pwszDefDevName
DD_KEYBOARD_DEVICE_NAME_U L"Legacy0", // pwszLegacyDevName
IOCTL_KEYBOARD_QUERY_ATTRIBUTES, // IOCTL_Attr
FIELD_OFFSET(DEVICEINFO, keyboard.Attr), // offAttr
sizeof((PDEVICEINFO)NULL)->keyboard.Attr, // cbAttr
FIELD_OFFSET(DEVICEINFO, keyboard.Data), // offData
sizeof((PDEVICEINFO)NULL)->keyboard.Data, // cbData
ProcessKeyboardInput, // Reader routine
NULL // pkeHidChange
},
#ifdef GENERIC_INPUT
// DEVICE_TYPE_HID
{
sizeof(GENERIC_DEVICE_INFO)+sizeof(HID_DEVICE_INFO), // cbDeviceInfo
&GUID_CLASS_INPUT, // pClassGUID
0, // uiRegistrySection. LATER: add real one
L"hid", // pwszClassName
L"", // pwszDefDevName
L"", // pwszLegacyDevName
0, // IOCTL_ATTR
0, // offAttr
0, // cbAttr
0, // offData
0, // cbData
ProcessHidInput, // Reader routine
NULL, // pkeHidChange,
DT_HID, // dwFlags
},
#endif
// Add new input device type template here
};
PDEVICEINFO StartDeviceRead(
PDEVICEINFO pDeviceInfo)
{
/*
* Avoid to start reading NULL device handle.
* This happen when the DeviceNotify receives QUERY_REMOVE
* and the RIT finishes processing it, but RequestDeviceChange
* has not finished its wait.
*/
#ifdef GENERIC_INPUT
pDeviceInfo->ReadStatus = ZwReadFile(
pDeviceInfo->handle,
NULL, // hReadEvent
InputApc, // InputApc()
pDeviceInfo, // ApcContext
&pDeviceInfo->iosb,
pBuffer,
ulLengthToRead,
PZERO(LARGE_INTEGER), NULL);
#else
pDeviceInfo->ReadStatus = ZwReadFile(
pDeviceInfo->handle,
NULL, // hReadEvent
InputApc, // InputApc()
pDeviceInfo, // ApcContext
&pDeviceInfo->iosb,
(PVOID)((PBYTE)pDeviceInfo + pDevTpl->offData),
pDevTpl->cbData,
PZERO(LARGE_INTEGER), NULL);
#endif
VOID ProcessKeyboardInput(PDEVICEINFO pDeviceInfo)
{
PKEYBOARD_INPUT_DATA pkei;
PKEYBOARD_INPUT_DATA pkeiStart, pkeiEnd;
EnterCrit();
UserAssert(pDeviceInfo->type == DEVICE_TYPE_KEYBOARD);
UserAssert(pDeviceInfo->iosb.Information);
UserAssert(NT_SUCCESS(pDeviceInfo->iosb.Status));
/*
* Switch the keyboard layout table, if the current KL has multiple
* tables.
*/
if (gpKL && gpKL->uNumTbl > 0 &&
(gpKL->dwLastKbdType != GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo) ||
gpKL->dwLastKbdSubType != GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo))) {
SearchAndSetKbdTbl(pDeviceInfo,
GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo),
GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo));
/*
* Whether or not we found the match, cache the type/subtype so that
* we will not try to find the same type/subtype for a while.
*/
gpKL->dwLastKbdType = GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo);
gpKL->dwLastKbdSubType = GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo);
}
pkeiStart = pDeviceInfo->keyboard.Data;
pkeiEnd = (PKEYBOARD_INPUT_DATA)((PBYTE)pkeiStart + pDeviceInfo->iosb.Information);
for (pkei = pkeiStart; pkei < pkeiEnd; pkei++) {
ProcessKeyboardInputWorker(pkei,
#ifdef GENERIC_INPUT
pDeviceInfo,
#endif
TRUE);
}
LeaveCrit();
}
VOID ProcessKeyboardInputWorker(
PKEYBOARD_INPUT_DATA pkei,
#ifdef GENERIC_INPUT
PDEVICEINFO pDeviceInfo,
#endif
BOOL fProcessRemap)
{
//
// Keep track of real modifier key state. Conveniently, the values for
// VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU and
// VK_RMENU are contiguous. We'll construct a bit field to keep track
// of the current modifier key state. If a bit is set, the corresponding
// modifier key is down. The bit field has the following format:
//
// +---------------------------------------------------+
// | Right | Left | Right | Left | Right | Left |
// | Alt | Alt | Control | Control | Shift | Shift |
// +---------------------------------------------------+
// 5 4 3 2 1 0 Bit
//
// Add bit 7 -- VK_RWIN
// bit 6 -- VK_LWIN
switch (Vk) {
case VK_LSHIFT:
case VK_RSHIFT:
case VK_LCONTROL:
case VK_RCONTROL:
case VK_LMENU:
case VK_RMENU:
gCurrentModifierBit = 1 << (Vk & 0xf);
break;
case VK_LWIN:
gCurrentModifierBit = 0x40;
break;
case VK_RWIN:
gCurrentModifierBit = 0x80;
break;
default:
gCurrentModifierBit = 0;
}
if (gCurrentModifierBit) {
/*
* If this is a break of a modifier key then clear the bit value.
* Otherwise, set it.
*/
if (pkei->Flags & KEY_BREAK) {
gPhysModifierState &= ~gCurrentModifierBit;
} else {
gPhysModifierState |= gCurrentModifierBit;
}
}
if (!TEST_ACCF(ACCF_ACCESSENABLED)) {
xxxProcessKeyEvent(&ke, (ULONG_PTR)pkei->ExtraInformation,
pkei->Flags & KEY_TERMSRV_SHADOW ? TRUE : FALSE);
} else {
if ((gtmridAccessTimeOut != 0) && TEST_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON)) {
gtmridAccessTimeOut = InternalSetTimer(
NULL,
gtmridAccessTimeOut,
(UINT)gAccessTimeOut.iTimeOutMSec,
xxxAccessTimeOutTimer,
TMRF_RIT | TMRF_ONESHOT
);
}
if (AccessProceduresStream(&ke, pkei->ExtraInformation, 0)) {
xxxProcessKeyEvent(&ke, (ULONG_PTR)pkei->ExtraInformation,
pkei->Flags & KEY_TERMSRV_SHADOW ? TRUE : FALSE);
}
}
} else {
VOID xxxProcessKeyEvent(
PKE pke,
ULONG_PTR ExtraInformation,
BOOL bInjected)
{
} else {
if (KEOEMProcs(pke) && xxxKELocaleProcs(pke) && xxxKENLSProcs(pke,ExtraInformation)) {
xxxKeyEvent(pke->usFlaggedVk, pke->bScanCode,
pke->dwTime, ExtraInformation,
#ifdef GENERIC_INPUT
pke->hDevice,
&pke->data,
#endif
bInjected);
}
BOOL xxxDoHotKeyStuff(
UINT vk,
BOOL fBreak,
DWORD fsReserveKeys)
{
UINT fsModOnlyHotkey;
UINT fs;
PHOTKEY phk;
BOOL fCancel;
BOOL fEatDebugKeyBreak;
PWND pwnd;
BOOL bSAS;
CheckCritIn();
chenghao@chenghaodeiMac core % grep "xxxDoHotKeyStuff" -nr|grep -v "inary"
./kmode/win32k.prf:2615:xxxDoHotKeyStuff@12
./ntuser/kernel/userk.h:5164:BOOL xxxDoHotKeyStuff(UINT vk, BOOL fBreak, DWORD fsReserveKeys);
./ntuser/kernel/ntinput.c:2810: if (xxxDoHotKeyStuff(Vk, fBreak, fsReserveKeys)) {
./ntuser/kernel/hotkeys.c:462: * The below two states are used by xxxDoHotKeyStuff().
./ntuser/kernel/hotkeys.c:488:* xxxDoHotKeyStuff
./ntuser/kernel/hotkeys.c:514:BOOL xxxDoHotKeyStuff(
VOID xxxKeyEvent(
USHORT usFlaggedVk,
WORD wScanCode,
DWORD time,
ULONG_PTR ExtraInfo,
#ifdef GENERIC_INPUT
HANDLE hDevice,
PKEYBOARD_INPUT_DATA pkei,
#endif
BOOL bInjected)
{
/*
* Check for hotkeys.
*/
if (xxxDoHotKeyStuff(Vk, fBreak, fsReserveKeys)) {
/***************************************************************************\
* IsSAS
*
* Checks the physical state of keyboard modifiers that would effect SAS.
\***************************************************************************/
BOOL IsSAS(
BYTE vk,
UINT *pfsModifiers)
{
CheckCritIn();
if (gvkSAS != vk) {
return FALSE;
}
/*
* Special case for SAS - examine real physical modifier-key state!
*
* An evil daemon process can fool convincingly pretend to be winlogon
* by registering Alt+Del as a hotkey, and spinning another thread that
* continually calls keybd_event() to send the Ctrl key up: when the
* user types Ctrl+Alt+Del, only Alt+Del will be seen by the system,
* the evil daemon will get woken by WM_HOTKEY and can pretend to be
* winlogon. So look at gfsSASModifiersDown in this case, to see what keys
* were physically pressed.
* NOTE: If hotkeys are ever made to work under journal playback, make
* sure they don't affect the gfsSASModifiersDown! - IanJa.
*/
if (gfsSASModifiersDown == gfsSASModifiers) {
*pfsModifiers = gfsSASModifiersDown;
return TRUE;
}
return FALSE;
}
chenghao@chenghaodeiMac core % grep "gfsSASModifiersDown" -nr|grep -v "inary"
./ntuser/kdexts/userexts.c:11868: moveExpValue(&PhysModifiers, VAR(gfsSASModifiersDown));
./ntuser/kernel/globals.h:531:extern UINT gfsSASModifiersDown; // SAS modifiers really physically down
./ntuser/kernel/ntinput.c:2659: * Maintain gfsSASModifiersDown to indicate which of Ctrl/Shift/Alt
./ntuser/kernel/ntinput.c:2664: gfsSASModifiersDown &= ~VKTOMODIFIERS(Vk);
./ntuser/kernel/ntinput.c:2666: gfsSASModifiersDown |= VKTOMODIFIERS(Vk);
./ntuser/kernel/hotkeys.c:448: * winlogon. So look at gfsSASModifiersDown in this case, to see what keys
./ntuser/kernel/hotkeys.c:451: * sure they don't affect the gfsSASModifiersDown! - IanJa.
./ntuser/kernel/hotkeys.c:453: if (gfsSASModifiersDown == gfsSASModifiers) {
./ntuser/kernel/hotkeys.c:454: *pfsModifiers = gfsSASModifiersDown;
./ntuser/kernel/hotkeys.c:483: gfsSASModifiersDown = 0;
./ntuser/kernel/globals.c:648: * real physically pressed modifier keys (gfsSASModifiersDown).
./ntuser/kernel/globals.c:664:UINT gfsSASModifiersDown; // SAS modifiers really physically down
参考:
0: kd> kc
#
00 win32k!PostInputMessage
01 win32k!xxxKeyEvent
02 win32k!xxxProcessKeyEvent
03 win32k!ProcessKeyboardInputWorker
04 win32k!ProcessKeyboardInput
05 win32k!InputApc
06 nt!KiDeliverApc
07 nt!KiSwapThread
08 nt!KeWaitForMultipleObjects
09 win32k!RawInputThread
0a win32k!xxxCreateSystemThreads
0b win32k!NtUserCallOneParam
0c nt!_KiSystemService
0d SharedUserData!SystemCallStub
0: kd> kc
#
00 win32k!StoreQMessage
01 win32k!_PostMessage
02 win32k!xxxDoHotKeyStuff
03 win32k!xxxKeyEvent
04 win32k!xxxProcessKeyEvent
05 win32k!ProcessKeyboardInputWorker
06 win32k!ProcessKeyboardInput
07 win32k!InputApc
08 nt!KiDeliverApc
09 nt!KiSwapThread
0a nt!KeWaitForMultipleObjects
0b win32k!RawInputThread
0c win32k!xxxCreateSystemThreads
0d win32k!NtUserCallOneParam
0e nt!_KiSystemService
0f SharedUserData!SystemCallStub
10 winsrv!NtUserCallOneParam
参考:
VOID xxxKeyEvent(
USHORT usFlaggedVk,
WORD wScanCode,
DWORD time,
ULONG_PTR ExtraInfo,
#ifdef GENERIC_INPUT
HANDLE hDevice,
PKEYBOARD_INPUT_DATA pkei,
#endif
BOOL bInjected)
{
/*
* Maintain gfsSASModifiersDown to indicate which of Ctrl/Shift/Alt
* are really truly physically down
*/
if (!bInjected && ((wScanCode & SCANCODE_SIMULATED) == 0)) {
if (fBreak) {
gfsSASModifiersDown &= ~VKTOMODIFIERS(Vk);
} else {
gfsSASModifiersDown |= VKTOMODIFIERS(Vk);
}
}
#define VKTOMODIFIERS(Vk) ((((Vk) >= VK_SHIFT) && ((Vk) <= VK_MENU)) ? \
(MOD_SHIFT >> ((Vk) - VK_SHIFT)) : \
0)
../../public/sdk/inc/winuser.h:2975:#define MOD_SHIFT 0x0004
100
10 100
11 10
12 1
VK_SHIFT 10 16 Shift键
VK_CONTROL 11 17 Ctrl键
VK_MENU 12 18 Alt键
CTRL+ALT=0x3
gfsSASModifiersDown=0x3
