当前位置: 首页 > news >正文

win32k!ProcessKeyboardInputWorker函数和win32k!xxxProcessKeyEvent函数分析键盘扫描码和vk码

win32k!ProcessKeyboardInputWorker函数和win32k!xxxProcessKeyEvent函数分析键盘扫描码和vk码

Breakpoint 4 hit
eax=f75d698c ebx=e1418ab8 ecx=f75d0036 edx=ffffffa5 esi=00008000 edi=00000000
eip=bf8e8675 esp=f75d6970 ebp=f75d69a4 iopl=0         nv up ei pl zr na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000246
win32k!xxxProcessKeyEvent:
bf8e8675 55              push    ebp
1: kd> kc
 #
00 win32k!xxxProcessKeyEvent
01 win32k!ProcessKeyboardInputWorker
02 win32k!ProcessKeyboardInput
03 win32k!InputApc
04 nt!KiDeliverApc
05 nt!KiSwapThread
06 nt!KeWaitForMultipleObjects
07 win32k!RawInputThread
08 win32k!xxxCreateSystemThreads
09 win32k!NtUserCallOneParam
0a nt!_KiSystemService
0b SharedUserData!SystemCallStub
0c winsrv!NtUserCallOneParam
1: kd> dv
             pke = 0xf75d698c
ExtraInformation = 0
       bInjected = 0n0
              Vk = 0x8c ''
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKE *)0xf75d698c)
((win32k!tagKE *)0xf75d698c)                 : 0xf75d698c [Type: tagKE *]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x7c07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0x36 [Type: unsigned short]
    [+0x004] dwTime           : 0xffffffff [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]

1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!_KEYBOARD_INPUT_DATA *)0xf75d6998))
(*((win32k!_KEYBOARD_INPUT_DATA *)0xf75d6998))                 [Type: _KEYBOARD_INPUT_DATA]
    [+0x000] UnitId           : 0x0 [Type: unsigned short]
    [+0x002] MakeCode         : 0x7 [Type: unsigned short]
    [+0x004] Flags            : 0x0 [Type: unsigned short]
    [+0x006] Reserved         : 0x0 [Type: unsigned short]
    [+0x008] ExtraInformation : 0x0 [Type: unsigned long]

1: kd> g
Breakpoint 1 hit
eax=00000036 ebx=00008000 ecx=ffecf791 edx=00000000 esi=f75d698c edi=00004000
eip=bf8e7974 esp=f75d6940 ebp=f75d696c iopl=0         nv up ei pl zr na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000246
win32k!xxxKeyEvent:
bf8e7974 55              push    ebp
1: kd> dv
      usFlaggedVk = 0x36
        wScanCode = 7
             time = 0xffecf791
        ExtraInfo = 0
          hDevice = 0x00010063
             pkei = 0xf75d6998
        bInjected = 0n0
      fSASHandled = 0n16384
          message = 8
    fsReserveKeys = 0
fMakeAltUpASysKey = 0n0
               Vk = 0x74 't'
   tlpwndActivate = struct _TL
       ptiCurrent = 0x00008000
           fBreak = 0n-144873108
     usExtraStuff = 0
        bAnsiHook = 0n48
              msg = 0x698c
             kbds = struct tagKBDLLHOOKSTRUCT
      fsModifiers = 0xf75d698c
      fsModifiers = 0x30
           wParam = 0
1: kd> kc
 #
00 win32k!xxxKeyEvent
01 win32k!xxxProcessKeyEvent
02 win32k!ProcessKeyboardInputWorker
03 win32k!ProcessKeyboardInput
04 win32k!InputApc
05 nt!KiDeliverApc
06 nt!KiSwapThread
07 nt!KeWaitForMultipleObjects
08 win32k!RawInputThread
09 win32k!xxxCreateSystemThreads
0a win32k!NtUserCallOneParam
0b nt!_KiSystemService
0c SharedUserData!SystemCallStub
0d winsrv!NtUserCallOneParam

第二部分:


VOID ProcessKeyboardInput(PDEVICEINFO 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();
}

1: kd> dt DEVICEINFO e1418a48
win32k!DEVICEINFO
   +0x000 head             : _HEAD
   +0x008 pNext            : 0xe167f428 tagDEVICEINFO
   +0x00c type             : 0x1 ''
   +0x00d bFlags           : 0x2 ''
   +0x00e usActions        : 0
   +0x010 nRetryRead       : 0 ''
   +0x014 ustrName         : _UNICODE_STRING "\??\ACPI#PNP0303#4&5289e18&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
   +0x01c handle           : 0x0000022c Void
   +0x020 NotificationEntry : 0xe1416e58 Void
   +0x024 pkeHidChangeCompleted : 0x896049e8 _KEVENT
   +0x028 iosb             : _IO_STATUS_BLOCK
   +0x030 ReadStatus       : 0n0
   +0x034 OpenerProcess    : 0x000001b0 Void
   +0x038 OpenStatus       : 0n0
   +0x03c AttrStatus       : 0n0
   +0x040 timeStartRead    : 0xffecf8d9
   +0x044 timeEndRead      : 0xffecf8da
   +0x048 nReadsOutstanding : 0n0
   +0x04c mouse            : tagMOUSE_DEVICE_INFO
   +0x04c keyboard         : tagKEYBOARD_DEVICE_INFO
   +0x04c hid              : tagHID_DEVICE_INFO
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!_IO_STATUS_BLOCK *)0xe1418a70))
(*((win32k!_IO_STATUS_BLOCK *)0xe1418a70))                 [Type: _IO_STATUS_BLOCK]
    [+0x000] Status           : 0 [Type: long]
    [+0x000] Pointer          : 0x0 [Type: void *]
    [+0x004] Information      : 0xc [Type: unsigned long]
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKEYBOARD_DEVICE_INFO *)0xe1418a94))
(*((win32k!tagKEYBOARD_DEVICE_INFO *)0xe1418a94))                 [Type: tagKEYBOARD_DEVICE_INFO]
    [+0x000] Attr             [Type: _KEYBOARD_ATTRIBUTES]
    [+0x01c] IdEx             [Type: _KEYBOARD_ID_EX]
    [+0x024] Data             [Type: _KEYBOARD_INPUT_DATA [10]]
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!_KEYBOARD_INPUT_DATA (*)[10])0xe1418ab8))
(*((win32k!_KEYBOARD_INPUT_DATA (*)[10])0xe1418ab8))                 [Type: _KEYBOARD_INPUT_DATA [10]]
    [0]              [Type: _KEYBOARD_INPUT_DATA]
    [1]              [Type: _KEYBOARD_INPUT_DATA]
    [2]              [Type: _KEYBOARD_INPUT_DATA]
    [3]              [Type: _KEYBOARD_INPUT_DATA]
    [4]              [Type: _KEYBOARD_INPUT_DATA]
    [5]              [Type: _KEYBOARD_INPUT_DATA]
    [6]              [Type: _KEYBOARD_INPUT_DATA]
    [7]              [Type: _KEYBOARD_INPUT_DATA]
    [8]              [Type: _KEYBOARD_INPUT_DATA]
    [9]              [Type: _KEYBOARD_INPUT_DATA]

1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*0
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 7
   +0x004 Flags            : 1
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*1
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*2
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*3
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*4
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*5
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x5b
   +0x004 Flags            : 2
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*6
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x5b
   +0x004 Flags            : 3
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*7
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 1
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*8
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*9
   +0x000 UnitId           : 0
   +0x002 MakeCode         : 0x1d
   +0x004 Flags            : 0
   +0x006 Reserved         : 0
   +0x008 ExtraInformation : 0
1: kd> dt win32k!_KEYBOARD_INPUT_DATA  0xe1418ab8+c*a
   +0x000 UnitId           : 0x620
   +0x002 MakeCode         : 0xc05
   +0x004 Flags            : 0x7355
   +0x006 Reserved         : 0x6b74
   +0x008 ExtraInformation : 0xbf8a7688

第三部分:

Breakpoint 6 hit
eax=e1418ab8 ebx=e1418ab8 ecx=80ae2d98 edx=bfa6fd2c esi=e1418a48 edi=e1418ac4
eip=bf8e9575 esp=f75d69a8 ebp=f75d69c4 iopl=0         nv up ei ng nz na po cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000283
win32k!ProcessKeyboardInputWorker:
bf8e9575 55              push    ebp
1: kd> kc
 #
00 win32k!ProcessKeyboardInputWorker
01 win32k!ProcessKeyboardInput
02 win32k!InputApc
03 nt!KiDeliverApc
04 nt!KiSwapThread
05 nt!KeWaitForMultipleObjects
06 win32k!RawInputThread
07 win32k!xxxCreateSystemThreads
08 win32k!NtUserCallOneParam
09 nt!_KiSystemService
0a SharedUserData!SystemCallStub
0b winsrv!NtUserCallOneParam

1: kd> dv
           pkei = 0xe1418ab8
    pDeviceInfo = 0xe1418a48
  fProcessRemap = 0n1

1: kd> dx -id 0,0,8960a020 -r1 ((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)
((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)                 : 0xe1418ab8 [Type: _KEYBOARD_INPUT_DATA *]
    [+0x000] UnitId           : 0x0 [Type: unsigned short]
    [+0x002] MakeCode         : 0x7 [Type: unsigned short]
    [+0x004] Flags            : 0x1 [Type: unsigned short]
    [+0x006] Reserved         : 0x0 [Type: unsigned short]
    [+0x008] ExtraInformation : 0x0 [Type: unsigned long]

//
// Define the keyboard input data Flags.
//

#define KEY_MAKE  0
#define KEY_BREAK 1
#define KEY_E0    2
#define KEY_E1    4
#define KEY_TERMSRV_SET_LED 8
#define KEY_TERMSRV_SHADOW  0x10
#define KEY_TERMSRV_VKPACKET 0x20

#ifdef GENERIC_INPUT
    /*
     * Set the device handle and raw data
     */
    ke.hDevice = PtoH(pDeviceInfo);
    UserAssert(pkei);
    ke.data = *pkei;
#endif


1: kd> dv
           pkei = 0xe1418ab8
    pDeviceInfo = 0xe1418a48
  fProcessRemap = 0n1
             Vk = 0xe1 ''
        bPrefix = 0xb8 ''
             ke = struct tagKE
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKE *)0xf75d698c))
(*((win32k!tagKE *)0xf75d698c))                 [Type: tagKE]
    [+0x000] bScanCode        : 0xb8 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8ab8 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0xe141 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!_KEYBOARD_INPUT_DATA *)0xf75d6998))
(*((win32k!_KEYBOARD_INPUT_DATA *)0xf75d6998))                 [Type: _KEYBOARD_INPUT_DATA]
    [+0x000] UnitId           : 0x0 [Type: unsigned short]
    [+0x002] MakeCode         : 0x7 [Type: unsigned short]
    [+0x004] Flags            : 0x1 [Type: unsigned short]
    [+0x006] Reserved         : 0x0 [Type: unsigned short]
    [+0x008] ExtraInformation : 0x0 [Type: unsigned long]


1: kd> x win32k!gSetLedReceived
bfa70240          win32k!gSetLedReceived = 0


//
// Define the keyboard indicators.
//

#define KEYBOARD_LED_INJECTED     0x8000 //Used by Terminal Server
#define KEYBOARD_SHADOW           0x4000 //Used by Terminal Server
//#if defined(FE_SB) || defined(WINDOWS_FE) || defined(DBCS)
#define KEYBOARD_KANA_LOCK_ON     8 // Japanese keyboard
//#endif // defined(FE_SB) || defined(WINDOWS_FE) || defined(DBCS)
#define KEYBOARD_CAPS_LOCK_ON     4
#define KEYBOARD_NUM_LOCK_ON      2
#define KEYBOARD_SCROLL_LOCK_ON   1

第四部分:

ProcessKeys:
        if (pkei->Flags & KEY_E0) {
            bPrefix = 0xE0;
        } else if (pkei->Flags & KEY_E1) {
            bPrefix = 0xE1;
        } else {
            bPrefix = 0;
        }


//
// Define the keyboard input data Flags.
//

#define KEY_MAKE  0
#define KEY_BREAK 1

#define KEY_E0    2
#define KEY_E1    4
#define KEY_TERMSRV_SET_LED 8
#define KEY_TERMSRV_SHADOW  0x10
#define KEY_TERMSRV_VKPACKET 0x20


1: kd> dx -id 0,0,8960a020 -r1 ((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)
((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)                 : 0xe1418ab8 [Type: _KEYBOARD_INPUT_DATA *]
    [+0x000] UnitId           : 0x0 [Type: unsigned short]
    [+0x002] MakeCode         : 0x7 [Type: unsigned short]
    [+0x004] Flags            : 0x1 [Type: unsigned short]
    [+0x006] Reserved         : 0x0 [Type: unsigned short]
    [+0x008] ExtraInformation : 0x0 [Type: unsigned long]


        if (pkei->MakeCode == 0xFF) {
            /*
             * Kbd overrun (kbd hardware and/or keyboard driver) : Beep!
             * (some DELL keyboards send 0xFF if keys are hit hard enough,
             * presumably due to keybounce)
             */
            LeaveCrit();
            UserBeep(440, 125);
            EnterCrit();
            return;
        }            //可以删除,提高运行速度。


             * 键盘溢出(键盘硬件和/或键盘驱动程序):哔!
             
*(如果按键力度足够大,某些DELL键盘会发送0xFF,
            
 * 推测是由于按键反弹)


1: kd> dv
           pkei = 0xe1418a00
    pDeviceInfo = 0xe1418a48
  fProcessRemap = 0n1
             Vk = 0xe1 ''
        bPrefix = 0x00 ''
             ke = struct tagKE
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKE *)0xf75d698c))
(*((win32k!tagKE *)0xf75d698c))                 [Type: tagKE]
    [+0x000] bScanCode        : 0xb8 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8ab8 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0xe141 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]

        ke.bScanCode = (BYTE)(pkei->MakeCode & 0x7F);    //关键一步:


1: kd> dv
           pkei = 0xe1418a00
    pDeviceInfo = 0xe1418a48
  fProcessRemap = 0n1
             Vk = 0xe1 ''
        bPrefix = 0x00 ''
             ke = struct tagKE
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKE *)0xf75d698c))
(*((win32k!tagKE *)0xf75d698c))                 [Type: tagKE]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0xe141 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]

        if (fProcessRemap && (gpScancodeMap || gpFlexMap)) {    条件不满足


1: kd> x win32k!gpFlexMap
bfa6eda4          win32k!gpFlexMap = 0x00000000
1: kd> x win32k!gpScancodeMap
bfa71418          win32k!gpScancodeMap = 0x00000000


        gbVKLastDown = Vk = VKFromVSC(&ke, bPrefix, gafRawKeyState);


/*****************************************************************************\
* VKFromVSC
*
* This function is called from KeyEvent() after each call to VSCFromSC.  The
* keyboard input data passed in is translated to a virtual key code.
* This translation is dependent upon the currently depressed modifier keys.
*
* For instance, scan codes representing the number pad keys may be
* translated into VK_NUMPAD codes or cursor movement codes depending
* upon the state of NumLock and the modifier keys.


 每次调用VSCFromSC后,都会从KeyEvent()函数中调用此函数。传入的键盘输入数据会被转换为虚拟键码。
这种转换取决于当前按下的修饰键。
 
例如,根据NumLock和修饰键的状态,代表数字键盘按键的扫描码可能会被翻译为VK_NUMPAD码或光标移动码。

第四部分:

1: kd> x win32k!gptiForeground
bfa71ab0          win32k!gptiForeground = 0xe1404c50
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagTHREADINFO *)0xe1404c50)
((win32k!tagTHREADINFO *)0xe1404c50)                 : 0xe1404c50 [Type: tagTHREADINFO *]
    [+0x000] pEThread         : 0x897f2020 [Type: _ETHREAD *]
    [+0x004] RefCount         : 0x1 [Type: unsigned long]
    [+0x008] ptlW32           : 0x0 [Type: _TL *]
    [+0x00c] pgdiDcattr       : 0x5e0570 [Type: void *]
    [+0x010] pgdiBrushAttr    : 0x0 [Type: void *]
    [+0x014] pUMPDObjs        : 0x0 [Type: void *]
    [+0x018] pUMPDHeap        : 0x0 [Type: void *]
    [+0x01c] pUMPDObj         : 0x0 [Type: void *]
    [+0x020] GdiTmpAllocList  [Type: _LIST_ENTRY]
    [+0x028] ptl              : 0x0 [Type: _TL *]
    [+0x02c] ppi              : 0xe1619070 [Type: tagPROCESSINFO *]
    [+0x030] pq               : 0xe1630530 [Type: tagQ *]
    [+0x034] spklActive       : 0xe13e6bb8 [Type: tagKL *]
    [+0x038] pcti             : 0xbc643b04 [Type: tagCLIENTTHREADINFO *]
    [+0x03c] rpdesk           : 0x894da378 [Type: tagDESKTOP *]
    [+0x040] pDeskInfo        : 0xbc640c9c [Type: tagDESKTOPINFO *]
    [+0x044] ulClientDelta    : 0xbbe70000 [Type: unsigned long]
    [+0x048] pClientInfo      : 0x7ffde6cc [Type: tagCLIENTINFO *]
    [+0x04c] TIF_flags        : 0x1100000 [Type: unsigned long]
    [+0x050] pstrAppName      : 0x0 [Type: _UNICODE_STRING *]
    [+0x054] psmsSent         : 0x0 [Type: tagSMS *]
    [+0x058] psmsCurrent      : 0x0 [Type: tagSMS *]
    [+0x05c] psmsReceiveList  : 0x0 [Type: tagSMS *]
    [+0x060] timeLast         : -1247250 [Type: long]
    [+0x064] idLast           : 0xe16fa0a8 [Type: unsigned long]
    [+0x068] exitCode         : 0 [Type: int]
    [+0x06c] hdesk            : 0x2a4 [Type: HDESK__ *]
    [+0x070] cPaintsReady     : 0 [Type: int]
    [+0x074] cTimersReady     : 0x0 [Type: unsigned int]
    [+0x078] pMenuState       : 0x0 [Type: tagMENUSTATE *]
    [+0x07c] ptdb             : 0x0 [Type: tagTDB *]
    [+0x07c] pwinsta          : 0x0 [Type: tagWINDOWSTATION *]
    [+0x080] psiiList         : 0x0 [Type: tagSVR_INSTANCE_INFO *]
    [+0x084] dwExpWinVer      : 0x400 [Type: unsigned long]
    [+0x088] dwCompatFlags    : 0x0 [Type: unsigned long]
    [+0x08c] dwCompatFlags2   : 0x0 [Type: unsigned long]
    [+0x090] pqAttach         : 0x0 [Type: tagQ *]
    [+0x094] ptiSibling       : 0x0 [Type: tagTHREADINFO *]
    [+0x098] pmsd             : 0x0 [Type: _MOVESIZEDATA *]
    [+0x09c] fsHooks          : 0x108 [Type: unsigned long]
    [+0x0a0] sphkCurrent      : 0x0 [Type: tagHOOK *]
    [+0x0a4] pSBTrack         : 0x0 [Type: tagSBTRACK *]
    [+0x0a8] hEventQueueClient : 0xcc [Type: void *]
    [+0x0ac] pEventQueueServer : 0x894e9610 [Type: _KEVENT *]
    [+0x0b0] PtiLink          [Type: _LIST_ENTRY]
    [+0x0b8] iCursorLevel     : 0 [Type: int]
    [+0x0bc] ptLast           : {x=363 y=627} [Type: tagPOINT]
    [+0x0c4] spwndDefaultIme  : 0x0 [Type: tagWND *]
    [+0x0c8] spDefaultImc     : 0x0 [Type: tagIMC *]
    [+0x0cc] hklPrev          : 0x0 [Type: HKL__ *]
    [+0x0d0] cEnterCount      : 0 [Type: int]
    [+0x0d4] mlPost           [Type: tagMLIST]
    [+0x0e0] fsChangeBitsRemoved : 0x0 [Type: unsigned short]
    [+0x0e2] wchInjected      : 0x0 [Type: unsigned short]
    [+0x0e4] fsReserveKeys    : 0x0 [Type: unsigned long]
    [+0x0e8] apEvent          : 0x0 [Type: _KEVENT * *]
    [+0x0ec] amdesk           : 0xf01ff [Type: unsigned long]
    [+0x0f0] cWindows         : 0x12 [Type: unsigned int]
    [+0x0f4] cVisWindows      : 0x1 [Type: unsigned int]
    [+0x0f8] aphkStart        [Type: tagHOOK * [16]]
    [+0x138] cti              [Type: tagCLIENTTHREADINFO]
    [+0x14c] hPrevHidData     : 0x0 [Type: void *]
    [+0x150] cNestedCalls     : 0x1 [Type: unsigned int]
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKL *)0xe13e6bb8)
((win32k!tagKL *)0xe13e6bb8)                 : 0xe13e6bb8 [Type: tagKL *]
    [+0x000] head             [Type: _HEAD]
    [+0x008] pklNext          : 0xe13e6bb8 [Type: tagKL *]
    [+0x00c] pklPrev          : 0xe13e6bb8 [Type: tagKL *]
    [+0x010] dwKL_Flags       : 0x0 [Type: unsigned long]
    [+0x014] hkl              : 0x4090409 [Type: HKL__ *]
    [+0x018] spkf             : 0xe166c5d8 [Type: tagKBDFILE *]
    [+0x01c] spkfPrimary      : 0xe166c5d8 [Type: tagKBDFILE *]
    [+0x020] dwFontSigs       : 0x3f01ff [Type: unsigned long]
    [+0x024] iBaseCharset     : 0x0 [Type: unsigned int]
    [+0x028] CodePage         : 0x4e4 [Type: unsigned short]
    [+0x02a] wchDiacritic     : 0x0 [Type: unsigned short]
    [+0x02c] piiex            : 0x0 [Type: tagIMEINFOEX *]
    [+0x030] uNumTbl          : 0x0 [Type: unsigned int]
    [+0x034] pspkfExtra       : 0x0 [Type: tagKBDFILE * *]
    [+0x038] dwLastKbdType    : 0x0 [Type: unsigned long]
    [+0x03c] dwLastKbdSubType : 0x0 [Type: unsigned long]
    [+0x040] dwKLID           : 0x409 [Type: unsigned long]
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKBDFILE *)0xe166c5d8)
((win32k!tagKBDFILE *)0xe166c5d8)                 : 0xe166c5d8 [Type: tagKBDFILE *]
    [+0x000] head             [Type: _HEAD]
    [+0x008] pkfNext          : 0x0 [Type: tagKBDFILE *]
    [+0x00c] hBase            : 0xe16ef018 [Type: void *]
    [+0x010] pKbdTbl          : 0xe16ef9b0 [Type: tagKbdLayer *]
    [+0x014] Size             : 0xaa7 [Type: unsigned long]
    [+0x018] pKbdNlsTbl       : 0x0 [Type: tagKbdNlsLayer *]
    [+0x01c] awchDllName      [Type: unsigned short [32]]
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKbdLayer *)0xe16ef9b0)
((win32k!tagKbdLayer *)0xe16ef9b0)                 : 0xe16ef9b0 [Type: tagKbdLayer *]
    [+0x000] pCharModifiers   : 0xe16ef1c4 [Type: MODIFIERS *]
    [+0x004] pVkToWcharTable  : 0xe16ef394 [Type: _VK_TO_WCHAR_TABLE *]
    [+0x008] pDeadKey         : 0x0 [Type: DEADKEY *]
    [+0x00c] pKeyNames        : 0xe16ef5e8 [Type: VSC_LPWSTR *]
    [+0x010] pKeyNamesExt     : 0xe16ef8f8 [Type: VSC_LPWSTR *]
    [+0x014] pKeyNamesDead    : 0x0 [Type: unsigned short * *]
    [+0x018] pusVSCtoVK       : 0xe16ef018 : 0xff [Type: unsigned short *]
    [+0x01c] bMaxVSCtoVK      : 0x7f [Type: unsigned char]
    [+0x020] pVSCtoVK_E0      : 0xe16ef118 [Type: _VSC_VK *]
    [+0x024] pVSCtoVK_E1      : 0xe16ef1b4 [Type: _VSC_VK *]
    [+0x028] fLocaleFlags     : 0x10000 [Type: unsigned long]
    [+0x02c] nLgMax           : 0x0 [Type: unsigned char]
    [+0x02d] cbLgEntry        : 0x0 [Type: unsigned char]
    [+0x030] pLigature        : 0x0 [Type: _LIGATURE1 *]
    [+0x034] dwType           : 0x0 [Type: unsigned long]
    [+0x038] dwSubType        : 0x0 [Type: unsigned long]
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!unsigned short *)0xe16ef018)
((win32k!unsigned short *)0xe16ef018)                 : 0xe16ef018 : 0xff [Type: unsigned short *]
    0xff [Type: unsigned short]
1: kd> db 0xe16ef018
e16ef018  ff 00 1b 00 31 00 32 00-33 00 34 00 35 00 36 00  ....1.2.3.4.5.6.
e16ef028  37 00 38 00 39 00 30 00-bd 00 bb 00 08 00 09 00  7.8.9.0.........
e16ef038  51 00 57 00 45 00 52 00-54 00 59 00 55 00 49 00  Q.W.E.R.T.Y.U.I.
e16ef048  4f 00 50 00 db 00 dd 00-0d 00 a2 00 41 00 53 00  O.P.........A.S.
e16ef058  44 00 46 00 47 00 48 00-4a 00 4b 00 4c 00 ba 00  D.F.G.H.J.K.L...
e16ef068  de 00 c0 00 a0 00 dc 00-5a 00 58 00 43 00 56 00  ........Z.X.C.V.
e16ef078  42 00 4e 00 4d 00 bc 00-be 00 bf 00 a1 01 6a 02  B.N.M.........j.
e16ef088  a4 00 20 00 14 00 70 00-71 00 72 00 73 00 74 00  .. ...p.q.r.s.t.
1: kd> db 0xe16ef018+80
e16ef098  75 00 76 00 77 00 78 00-79 00 90 03 91 02 24 0c  u.v.w.x.y.....$.
e16ef0a8  26 0c 21 0c 6d 00 25 0c-0c 0c 27 0c 6b 00 23 0c  &.!.m.%...'.k.#.
e16ef0b8  28 0c 22 0c 2d 0c 2e 0c-2c 00 ff 00 e2 00 7a 00  (.".-...,.....z.
e16ef0c8  7b 00 0c 00 ee 00 f1 00-ea 00 f9 00 f5 00 f3 00  {...............
e16ef0d8  ff 00 ff 00 fb 00 2f 00-7c 00 7d 00 7e 00 7f 00  ....../.|.}.~...
e16ef0e8  80 00 81 00 82 00 83 00-84 00 85 00 86 00 ed 00  ................
e16ef0f8  ff 00 e9 00 ff 00 c1 00-ff 00 ff 00 87 00 ff 00  ................
e16ef108  ff 00 ff 00 ff 00 eb 00-09 00 ff 00 c2 00 00 00  ................


ff 00 1b 00 31 00 32 00-33 00 34 00 35 00 36 00
37 00 38 00 39 00 30 00-bd 00 bb 00 08 00 09 00
51 00 57 00 45 00 52 00-54 00 59 00 55 00 49 00
4f 00 50 00 db 00 dd 00-0d 00 a2 00 41 00 53 00
44 00 46 00 47 00 48 00-4a 00 4b 00 4c 00 ba 00
de 00 c0 00 a0 00 dc 00-5a 00 58 00 43 00 56 00
42 00 4e 00 4d 00 bc 00-be 00 bf 00 a1 01 6a 02
a4 00 20 00 14 00 70 00-71 00 72 00 73 00 74 00
75 00 76 00 77 00 78 00-79 00 90 03 91 02 24 0c
26 0c 21 0c 6d 00 25 0c-0c 0c 27 0c 6b 00 23 0c
28 0c 22 0c 2d 0c 2e 0c-2c 00 ff 00 e2 00 7a 00
7b 00 0c 00 ee 00 f1 00-ea 00 f9 00 f5 00 f3 00
ff 00 ff 00 fb 00 2f 00-7c 00 7d 00 7e 00 7f 00
80 00 81 00 82 00 83 00-84 00 85 00 86 00 ed 00
ff 00 e9 00 ff 00 c1 00-ff 00 ff 00 87 00 ff 00
ff 00 ff 00 ff 00 eb 00-09 00 ff 00 c2 00 00 00

#define VK_UNKNOWN        0xFF

    /*
     * Initialize as an unknown VK (unrecognised scancode)
     */
    pke->usFlaggedVk = usVKey = VK_UNKNOWN;

1: kd> dv
            pke = 0xf75d698c
        bPrefix = 0x00 ''
     afKeyState = 0xbfa70f20 ""
       fVkPause = 0n0
         usVKey = 7
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKE *)0xf75d698c)
((win32k!tagKE *)0xf75d698c)                 : 0xf75d698c [Type: tagKE *]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0xff [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]


        if (gptiForeground->spklActive) {
            pKbdTbl = gptiForeground->spklActive->spkf->pKbdTbl;


            usVKey = pKbdTbl->pusVSCtoVK[pke->bScanCode];    关键一步:    eax=00000036

            usVKey = pKbdTbl->pusVSCtoVK[pke->bScanCode];


1: kd> p
eax=00000036 ebx=f75d698c ecx=00000007 edx=00000200 esi=bfa05c0c edi=bfa05c3c
eip=bf890311 esp=f75d695c ebp=f75d696c iopl=0         nv up ei ng nz ac pe cy
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000297
win32k!VKFromVSC+0xc1:
bf890311 6685c0          test    ax,ax

    pke->usFlaggedVk = usVKey;
    return (BYTE)usVKey;
}

1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKE *)0xf75d698c)
((win32k!tagKE *)0xf75d698c)                 : 0xf75d698c [Type: tagKE *]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0x36 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]


返回到:

VOID ProcessKeyboardInputWorker(
    PKEYBOARD_INPUT_DATA pkei,
#ifdef GENERIC_INPUT
    PDEVICEINFO pDeviceInfo,
#endif
    BOOL fProcessRemap)
{


        if (pkei->Flags & KEY_BREAK) {
            ke.usFlaggedVk |= KBDBREAK;    //最重要的一步:加上KBDBREAK标志0x8000,说明是key_up
        }

参考:
1: kd> dv  pkei
           pkei = 0xe1418ab8
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)
((win32k!_KEYBOARD_INPUT_DATA *)0xe1418ab8)                 : 0xe1418ab8 [Type: _KEYBOARD_INPUT_DATA *]
    [+0x000] UnitId           : 0x0 [Type: unsigned short]
    [+0x002] MakeCode         : 0x7 [Type: unsigned short]
    [+0x004] Flags            : 0x1 [Type: unsigned short]
    [+0x006] Reserved         : 0x0 [Type: unsigned short]
    [+0x008] ExtraInformation : 0x0 [Type: unsigned long]
参考:

1: kd> p
eax=00000036 ebx=e1418ab8 ecx=00000007 edx=00000200 esi=00008000 edi=00000000
eip=bf8e96ae esp=f75d6980 ebp=f75d69a4 iopl=0         nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000206
win32k!ProcessKeyboardInputWorker+0x139:
bf8e96ae f6430401        test    byte ptr [ebx+4],1         ds:0023:e1418abc=01

1: kd> p
eax=00000036 ebx=e1418ab8 ecx=00000007 edx=00000200 esi=00008000 edi=00000000
eip=bf8e96b4 esp=f75d6980 ebp=f75d69a4 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000202
win32k!ProcessKeyboardInputWorker+0x13f:
bf8e96b4 660975ea        or      word ptr [ebp-16h],si    ss:0010:f75d698e=0036

1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKE *)0xf75d698c))
(*((win32k!tagKE *)0xf75d698c))                 [Type: tagKE]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0x36 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]

or上0x8000后:

1: kd> dv
           pkei = 0xe1418a00
    pDeviceInfo = 0x36418a48
  fProcessRemap = 0n1
             Vk = 0x36 '6'
        bPrefix = 0x00 ''
             ke = struct tagKE
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!tagKE *)0xf75d698c))
(*((win32k!tagKE *)0xf75d698c))                 [Type: tagKE]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0x8036 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]


        //
        // 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;
            }
        }

#define VK_LSHIFT       0xA0
#define VK_RSHIFT       0xA1
#define VK_LCONTROL     0xA2
#define VK_RCONTROL     0xA3
#define VK_LMENU        0xA4
#define VK_RMENU        0xA5


#define ACCF_ACCESSENABLED              0x00000100
#define TEST_ACCF(f)               TEST_FLAG(gdwPUDFlags, f)

1: kd> x win32k!gdwPUDFlags
bfa52fc0          win32k!gdwPUDFlags = 0x1684100

            if (AccessProceduresStream(&ke, pkei->ExtraInformation, 0)) {
                xxxProcessKeyEvent(&ke, (ULONG_PTR)pkei->ExtraInformation,
                    pkei->Flags & KEY_TERMSRV_SHADOW ? TRUE : FALSE);
            }

/***************************************************************************\
* AccessProceduresStream
*
* This function controls the order in which the access functions are called.
* All key events pass through this routine.  If an access function returns
* FALSE then none of the other access functions in the stream are called.
* This routine is called initially from KeyboardApcProcedure(), but then
* can be called any number of times by the access functions as they process
* the current key event or add more key events.
*
* Return value:
*   TRUE    All access functions returned TRUE, the key event can be
*           processed.
*   FALSE   An access function returned FALSE, the key event should be
*           discarded.
*
* History:
*   11 Feb 93 GregoryW   Created.
\***************************************************************************/
BOOL AccessProceduresStream(PKE pKeyEvent, ULONG ExtraInformation, int dwProcIndex)
{
    int index;

    CheckCritIn();
    for (index = dwProcIndex; index < ARRAY_SIZE(aAccessibilityProc); index++) {
        if (!aAccessibilityProc[index](pKeyEvent, ExtraInformation, index+1)) {
            return FALSE;
        }
    }

    return TRUE;
}


1: kd> x win32k!aAccessibilityProc
bfa03ac8          win32k!aAccessibilityProc = <function> *[5]
1: kd> dx -id 0,0,8960a020 -r1 (*((win32k!int (*(*)[5])(tagKE *,unsigned long,int))0xbfa03ac8))
(*((win32k!int (*(*)[5])(tagKE *,unsigned long,int))0xbfa03ac8))                 [Type: int (* [5])(tagKE *,unsigned long,int)]
    [0]              : 0xbf8ec264 [Type: int (*)(tagKE *,unsigned long,int)]
    [1]              : 0xbf8eb95f [Type: int (*)(tagKE *,unsigned long,int)]
    [2]              : 0xbf8ebc51 [Type: int (*)(tagKE *,unsigned long,int)]
    [3]              : 0xbf8ec324 [Type: int (*)(tagKE *,unsigned long,int)]
    [4]              : 0xbf8ec5aa [Type: int (*)(tagKE *,unsigned long,int)]
1: kd> u bf8ec264
win32k!HighContrastHotKey [d:\srv03rtm\windows\core\ntuser\kernel\access.c @ 1788]:
bf8ec264 55              push    ebp
bf8ec265 8bec            mov     ebp,esp
bf8ec267 53              push    ebx
bf8ec268 e8b01afcff      call    win32k!_AssertCritIn (bf8add1d)
bf8ec26d 0fb6152014a7bf  movzx   edx,byte ptr [win32k!gLatchBits (bfa71420)]
bf8ec274 0fb60d2314a7bf  movzx   ecx,byte ptr [win32k!gPhysModifierState (bfa71423)]
bf8ec27b 8b4508          mov     eax,dword ptr [ebp+8]
bf8ec27e 8a5802          mov     bl,byte ptr [eax+2]
1: kd> u bf8eb95f
win32k!FilterKeys [d:\srv03rtm\windows\core\ntuser\kernel\access.c @ 480]:
bf8eb95f 55              push    ebp
bf8eb960 8bec            mov     ebp,esp
bf8eb962 53              push    ebx
bf8eb963 56              push    esi
bf8eb964 57              push    edi
bf8eb965 e8b323fcff      call    win32k!_AssertCritIn (bf8add1d)
bf8eb96a 8b7508          mov     esi,dword ptr [ebp+8]
bf8eb96d 8a4e02          mov     cl,byte ptr [esi+2]
1: kd> u bf8ebc51
win32k!xxxStickyKeys [d:\srv03rtm\windows\core\ntuser\kernel\access.c @ 724]:
bf8ebc51 55              push    ebp
bf8ebc52 8bec            mov     ebp,esp
bf8ebc54 51              push    ecx
bf8ebc55 a10814a7bf      mov     eax,dword ptr [win32k!grpdeskRitInput (bfa71408)]
bf8ebc5a 8b4010          mov     eax,dword ptr [eax+10h]
bf8ebc5d 8b400c          mov     eax,dword ptr [eax+0Ch]
bf8ebc60 53              push    ebx
bf8ebc61 56              push    esi
1: kd> u bf8ec324
win32k!MouseKeys [d:\srv03rtm\windows\core\ntuser\kernel\access.c @ 1857]:
bf8ec324 55              push    ebp
bf8ec325 8bec            mov     ebp,esp
bf8ec327 53              push    ebx
bf8ec328 56              push    esi
bf8ec329 e8ef19fcff      call    win32k!_AssertCritIn (bf8add1d)
bf8ec32e 0fb6052014a7bf  movzx   eax,byte ptr [win32k!gLatchBits (bfa71420)]
bf8ec335 8b4d08          mov     ecx,dword ptr [ebp+8]
bf8ec338 0fb6152314a7bf  movzx   edx,byte ptr [win32k!gPhysModifierState (bfa71423)]
1: kd> u bf8ec5aa
win32k!ToggleKeys [d:\srv03rtm\windows\core\ntuser\kernel\access.c @ 2167]:
bf8ec5aa 55              push    ebp
bf8ec5ab 8bec            mov     ebp,esp
bf8ec5ad 53              push    ebx
bf8ec5ae 56              push    esi
bf8ec5af 57              push    edi
bf8ec5b0 e86817fcff      call    win32k!_AssertCritIn (bf8add1d)
bf8ec5b5 8b4508          mov     eax,dword ptr [ebp+8]
bf8ec5b8 8a4802          mov     cl,byte ptr [eax+2]

1: kd> kc
 #
00 win32k!xxxProcessKeyEvent
01 win32k!ProcessKeyboardInputWorker
02 win32k!ProcessKeyboardInput
03 win32k!InputApc
04 nt!KiDeliverApc
05 nt!KiSwapThread
06 nt!KeWaitForMultipleObjects
07 win32k!RawInputThread
08 win32k!xxxCreateSystemThreads
09 win32k!NtUserCallOneParam
0a nt!_KiSystemService
0b SharedUserData!SystemCallStub
0c winsrv!NtUserCallOneParam
1: kd> dv
             pke = 0xf75d698c
ExtraInformation = 0
       bInjected = 0n0
              Vk = 0x8c ''
1: kd> dx -id 0,0,8960a020 -r1 ((win32k!tagKE *)0xf75d698c)
((win32k!tagKE *)0xf75d698c)                 : 0xf75d698c [Type: tagKE *]
    [+0x000] bScanCode        : 0x7 [Type: unsigned char]
    [+0x000] wchInjected      : 0x8a07 [Type: unsigned short]
    [+0x002] usFlaggedVk      : 0x8036 [Type: unsigned short]
    [+0x004] dwTime           : 0xf75d69a4 [Type: unsigned long]
    [+0x008] hDevice          : 0x10063 [Type: void *]
    [+0x00c] data             [Type: _KEYBOARD_INPUT_DATA]

http://www.dtcms.com/a/596693.html

相关文章:

  • k均值,密度聚类,层次聚类三种聚类底层逻辑的区别
  • 基于微信小程序的茶叶茶具销售和管理系统(源码+论文+部署+安装)
  • INT303 Big Data Analysis 大数据分析 Pt.8 聚类
  • 4-ARM-PEG-Biotin(2)/Silane(2),特性与制备方法解析
  • 【成功案例】朗迪锋助力高校实验室数智化升级
  • 【开题答辩实录分享】以《证劵数据可视化分析项目设计与实现》为例进行答辩实录分享
  • 可信计算、TPM
  • SAP HANA 发展历史:内存计算如何重塑企业级数据平台
  • 存算一体架构在空间计算中的应用
  • docker swarm集群搭建,对比k8s
  • 为什么网站需要维护需要网站建设
  • 25年05月架构甄选范文“论多模型数据源”,软考高级,系统架构设计师论文
  • 重庆做网站公司哪家比较好图片设计在线
  • Ubuntu 上使用 VSCode 调试 C++ (CMake 项目) 指南
  • opencv 学习: 07 使用迭代器 (iterator) 遍历像素
  • Two Sigma 面经分享|智商检测级别的面试,逻辑与细节缺一不可
  • 【STM32项目开源】STM32单片机物联网门禁控制系统
  • Ubuntu 系统部署 PostgreSQL 主从复制 + 流复制(Streaming Replication)完整操作指南
  • 福州企业网站推广定制wordpress国人模板
  • 场景落地绘就创新图景,人工智能迎来应用浪潮
  • 数据结构(20)
  • 线性代数 - 理解求解矩阵特征值的特征方程
  • Swift的逃逸闭包
  • ESP32基础-GPIO_LED进阶
  • AT指令连接onenet平台(mqtt协议)
  • 二分搜索中 `right = mid` 而非 `right = mid + 1` 的解释
  • 走进Linux的世界:进程优先级
  • 蛙蛙写作网站中国建设银行网站-个人客
  • jetson开机之前自启脚本sudo ifconfig 如何不需要输入密码
  • 环评登记表在哪个网站做php网站开发试题