win32k!xxxSkipSysMsg函数分析之WM_KEYUP消息0Xc0070001的由来和WM_KEYUP消息的31位和30位的含义==非常重要
第一部分:
* 0x80000000 is set if up, clear if down
* 0x40000000 is previous up/down state of key
第二部分:
win32k!xxxInternalToUnicode函数分析之WM_KEYDOWN和WM_KEYUP的返回值的不同
https://chenghao.blog.csdn.net/article/details/154705786
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
pti = PtiCurrent();
if ((pti->pMenuState != NULL) &&
(HW(pti->pMenuState->pGlobalPopupMenu->spwndPopupMenu) ==
pmsg->hwnd)) {
uiTMFlags |= TM_INMENUMODE;
} else {
uiTMFlags &= ~TM_INMENUMODE;
}
/*
* Don't change the contents of the passed in structure.
*/
lParam = pmsg->lParam;
/*
* For backward compatibility, mask the virtual key value.
*/
uVirKey = LOWORD(pmsg->wParam);
cChar = xxxInternalToUnicode(uVirKey, // virtual key code
HIWORD(lParam), // scan code, make/break bit
pti->pq->afKeyState,
awch, sizeof(awch)/sizeof(awch[0]),
uiTMFlags, &dwKeyFlags, NULL);
lParam |= (dwKeyFlags & ALTNUMPAD_BIT);
int xxxInternalToUnicode(
IN UINT uVirtKey,
IN UINT uScanCode,
CONST IN PBYTE pfvk,
OUT PWCHAR awchChars,
IN INT cChar,
IN UINT uiTMFlags,
OUT PDWORD pdwKeyFlags,
IN HKL hkl)
{
WORD wModBits;
WORD nShift;
WCHAR *pUniChar;
PVK_TO_WCHARS1 pVK;
PVK_TO_WCHAR_TABLE pVKT;
static WORD NumpadChar;
static WORD VKLastDown;
static BYTE ConvMode; // 0 == NUMPADCONV_OEMCP
PTHREADINFO ptiCurrent = PtiCurrentShared();
PKL pkl;
PKBDTABLES pKbdTbl;
PLIGATURE1 pLigature;
*pdwKeyFlags = (uScanCode & KBDBREAK);
if (*pdwKeyFlags & KBDBREAK) { // break code processing,表示是WM_KEYUP
第三部分:
1: kd> kc
#
00 win32k!xxxSkipSysMsg
01 win32k!xxxScanSysQueue
02 win32k!xxxRealInternalGetMessage
03 win32k!NtUserPeekMessage
04 nt!_KiSystemService
05 SharedUserData!SystemCallStub
06 USER32!NtUserPeekMessage
07 USER32!PeekMessageW
08 USER32!DialogBox2
09 USER32!InternalDialogBox
0a USER32!DialogBoxIndirectParamAorW
0b USER32!DialogBoxParamW
0c USER32!DialogBoxParamW_wrapper
0d winlogon!Fusion_DialogBoxParam
0e winlogon!TimeoutDialogBoxParam
0f winlogon!WlxDialogBoxParam
10 MSGINA!WlxWkstaLockedSAS
11 winlogon!DoLockWksta
12 winlogon!DoScreenSaver
13 winlogon!LoggedonDlgProc
14 winlogon!RootDlgProc
15 USER32!InternalCallWinProc
16 USER32!UserCallDlgProcCheckWow
17 USER32!DefDlgProcWorker
18 USER32!DefDlgProcW
19 USER32!InternalCallWinProc
1a USER32!UserCallWinProcCheckWow
1b USER32!DispatchMessageWorker
1c USER32!DispatchMessageW
1d USER32!IsDialogMessageW
1e USER32!DialogBox2
1f USER32!InternalDialogBox
20 USER32!DialogBoxIndirectParamAorW
21 USER32!DialogBoxParamW
22 USER32!DialogBoxParamW_wrapper
23 winlogon!Fusion_DialogBoxParam
24 winlogon!TimeoutDialogBoxParam
25 winlogon!WlxDialogBoxParam
26 winlogon!BlockWaitForUserAction
27 winlogon!MainLoop
28 winlogon!WinMain
29 winlogon!WinMainCRTStartup
1: kd> dv
pti = 0xe1404c50
pqmsg = 0xf75c6bc4
fDown = 0n-1082094230
pqmsgT = 0xbf808d6a
vk = 0x00 ''
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQMSG *)0xf75c6bc4)
((win32k!tagQMSG *)0xf75c6bc4) : 0xf75c6bc4 [Type: tagQMSG *]
[+0x000] pqmsgNext : 0x0 [Type: tagQMSG *]
[+0x004] pqmsgPrev : 0x0 [Type: tagQMSG *]
[+0x008] msg : {msg=0x101 wp=0x36 lp=0x70001} [Type: tagMSG]
[+0x024] ExtraInfo : 0 [Type: long]
[+0x028] dwQEvent : 0x0 [Type: unsigned long]
[+0x02c] pti : 0xe1404c50 [Type: tagTHREADINFO *]
1: kd> !thread
THREAD 897f2020 Cid 01c8.01cc Teb: 7ffde000 Win32Thread: e1404c50 RUNNING on processor 1
IRP List:
89590158: (0006,0094) Flags: 00000800 Mdl: 00000000
Not impersonating
DeviceMap e10003d8
Owning Process 89413020 Image: winlogon.exe
Attached Process N/A Image: N/A
Wait Start TickCount 274798196 Ticks: 3 (0:00:00:00.046)
Context Switch Count 3506 IdealProcessor: 1 LargeStack
UserTime 00:00:15.687
KernelTime 00:00:32.078
Stack Init f75c7000 Current f75c6bdc Base f75c7000 Limit f75c2000 Call 00000000
Priority 15 BasePriority 15 PriorityDecrement 0 IoPriority 0 PagePriority 0
ChildEBP RetAddr Args to Child
f75c6a9c bf80af08 e1404c50 f75c6bc4 bf9ea2a4 win32k!xxxSkipSysMsg (FPO: [Non-Fpo]) (CONV: stdcall) [d:srv03rtmwindowscore
tuserkernelinput.c @ 3352]
f75c6c40 bf8ad571 e1404c50 f75c6d04 00000000 win32k!xxxScanSysQueue+0x18a0 (FPO: [Non-Fpo]) (CONV: stdcall) [d:srv03rtmwindowscore
tuserkernelinput.c @ 5153]
f75c6cd8 bf89b537 f75c6d04 00000000 00000000 win32k!xxxRealInternalGetMessage+0x3c3 (FPO: [Non-Fpo]) (CONV: stdcall) [d:srv03rtmwindowscore
tuserkernelinput.c @ 636]
f75c6d3c 80afbcb2 0006f8f8 00000000 00000000 win32k!NtUserPeekMessage+0x7d (FPO: [Non-Fpo]) (CONV: stdcall) [d:srv03rtmwindowscore
tuserkernel
tstubs.c @ 5734]
f75c6d3c 7ffe0304 0006f8f8 00000000 00000000 nt!_KiSystemService+0x13f (FPO: [0,3] TrapFrame @ f75c6d64) (CONV: cdecl) [d:srv03rtmase
toskei386 rap.asm @ 1328]
/*
* Delete this message from the input queue. Make sure pqmsgT isn't
* 1: this could happen if an app unhooked a journal record hook
* during a callback from xxxScanSysQueue.
*/
if (pqmsgT != PQMSG_PLAYBACK) {
/*
* There are cases when idSysPeek points to a different message
* than the one we are trying to remove. This can happen if
* two threads enters in xxxScanSysQueue, sets the idSysPeek and
* after this their queues got redistributed. The first thread
* will have the idSysPeek preserved but the second one has to
* search the queue for its message. – ask CLupu
*/
if (!EqualMsg(pqmsgT, pqmsg)) {
PQMSG pqmsgS;
#if DBG
if (IsDbgTagEnabled(DBGTAG_SysPeek)) {
gnSysPeekSearch++;
}
#endif
TAGMSG0(DBGTAG_SysPeek | RIP_THERESMORE, “Different message than idSysPeek
“);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “pqmsg = %#p idSysPeek = %#p”, pqmsg, pqmsgT);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “pti = %#p pti = %#p”, pqmsg->pti, pqmsgT->pti);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “msg = %08lx msg = %08lx”, pqmsg->msg.message, pqmsgT->msg.message);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “hwnd = %#p hwnd = %#p”, pqmsg->msg.hwnd, pqmsgT->msg.hwnd);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “wParam = %#p wParam = %#p”, pqmsg->msg.wParam, pqmsgT->msg.wParam);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “lParam = %#p lParam = %#p”, pqmsg->msg.lParam, pqmsgT->msg.lParam);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “time = %08lx time = %08lx”, pqmsg->msg.time, pqmsgT->msg.time);
TAGMSG2(DBGTAG_SysPeek | RIP_NONAME | RIP_THERESMORE, “Extra = %08lx Extra = %08lx”, pqmsg->ExtraInfo, pqmsgT->ExtraInfo);
TAGMSG1(DBGTAG_SysPeek | RIP_NONAME, ”
pqmsgT = %#p”, pqmsgT);
/*
* Begin to search for this message
*/
pqmsgS = pti->pq->mlInput.pqmsgRead;
while (pqmsgS != NULL) {
if (EqualMsg(pqmsgS, pqmsg)) {
TAGMSG2(DBGTAG_SysPeek | RIP_THERESMORE,
“Deleting pqmsg %#p, pti %#p”,
pqmsgS, pqmsgS->pti);
TAGMSG4(DBGTAG_SysPeek | RIP_NONAME,
“m %04lx, w %#p, l %#p, t %lx”,
pqmsgS->msg.message, pqmsgS->msg.hwnd,
pqmsgS->msg.lParam, pqmsgS->msg.time);
pqmsgT = pqmsgS;
break;
}
pqmsgS = pqmsgS->pqmsgNext;
}
if (pqmsgS == NULL) {
TAGMSG0(DBGTAG_SysPeek, “Didn't find a matching message. No message removed.”);
return;
}
}
BOOL EqualMsg(PQMSG pqmsg1, PQMSG pqmsg2)
{
if (pqmsg1->msg.hwnd != pqmsg2->msg.hwnd ||
pqmsg1->msg.message != pqmsg2->msg.message)
return FALSE;
/*
* This might be a coalesced WM_MOUSEMOVE
*/
if (pqmsg1->msg.message == WM_MOUSEMOVE)
return TRUE;
if (pqmsg1->pti != pqmsg2->pti ||
pqmsg1->msg.time != pqmsg2->msg.time)
return FALSE;
return TRUE;
}
1: kd> dv
pti = 0xe1404c50
pqmsg = 0xf75c6bc4
fDown = 0n-512778072
pqmsgT = 0xe16fa0a8
vk = 0xe1 ''
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQMSG *)0xf75c6bc4)
((win32k!tagQMSG *)0xf75c6bc4) : 0xf75c6bc4 [Type: tagQMSG *]
[+0x000] pqmsgNext : 0x0 [Type: tagQMSG *]
[+0x004] pqmsgPrev : 0x0 [Type: tagQMSG *]
[+0x008] msg : {msg=0x101 wp=0x36 lp=0x70001} [Type: tagMSG]
[+0x024] ExtraInfo : 0 [Type: long]
[+0x028] dwQEvent : 0x0 [Type: unsigned long]
[+0x02c] pti : 0xe1404c50 [Type: tagTHREADINFO *]
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQMSG *)0xe16fa0a8)
((win32k!tagQMSG *)0xe16fa0a8) : 0xe16fa0a8 [Type: tagQMSG *]
[+0x000] pqmsgNext : 0x0 [Type: tagQMSG *]
[+0x004] pqmsgPrev : 0x0 [Type: tagQMSG *]
[+0x008] msg : {msg=0x101 wp=0x36 lp=0x70001} [Type: tagMSG]
[+0x024] ExtraInfo : 0 [Type: long]
[+0x028] dwQEvent : 0x0 [Type: unsigned long]
[+0x02c] pti : 0xe1404c50 [Type: tagTHREADINFO *]
DelQEntry(&pti->pq->mlInput, pqmsgT);
1: kd> dx -id 0,0,89413020 -r1 (*((win32k!tagMLIST *)0xe1630530))
(*((win32k!tagMLIST *)0xe1630530)) [Type: tagMLIST]
[+0x000] pqmsgRead : 0xe16fa0a8 [Type: tagQMSG *]
[+0x004] pqmsgWriteLast : 0xe16fa0a8 [Type: tagQMSG *]
[+0x008] cMsgs : 0x1 [Type: unsigned long]
1: kd> dv
pti = 0xe1404c50
pqmsg = 0xf75c6bc4
fDown = 0n-512778072
pqmsgT = 0xe16fa0a8
vk = 0xe1 ''
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQ *)0xe1630530)
((win32k!tagQ *)0xe1630530) : 0xe1630530 [Type: tagQ *]
[+0x000] mlInput [Type: tagMLIST]
1: kd> dx -id 0,0,89413020 -r1 (*((win32k!tagMLIST *)0xe1630530))
(*((win32k!tagMLIST *)0xe1630530)) [Type: tagMLIST]
[+0x000] pqmsgRead : 0xe16fa0a8 [Type: tagQMSG *]
[+0x004] pqmsgWriteLast : 0xe16fa0a8 [Type: tagQMSG *]
[+0x008] cMsgs : 0x1 [Type: unsigned long]
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQMSG *)0xe16fa0a8)
((win32k!tagQMSG *)0xe16fa0a8) : 0xe16fa0a8 [Type: tagQMSG *]
[+0x000] pqmsgNext : 0x0 [Type: tagQMSG *]
[+0x004] pqmsgPrev : 0x0 [Type: tagQMSG *]
[+0x008] msg : {msg=0x101 wp=0x36 lp=0x70001} [Type: tagMSG]
[+0x024] ExtraInfo : 0 [Type: long]
[+0x028] dwQEvent : 0x0 [Type: unsigned long]
[+0x02c] pti : 0xe1404c50 [Type: tagTHREADINFO *]
VOID DelQEntry(
PMLIST pml,
PQMSG pqmsg)
{
DebugValidateMLISTandQMSG(pml, pqmsg);
UserAssert((int)pml->cMsgs > 0);
UserAssert(pml->pqmsgRead);
UserAssert(pml->pqmsgWriteLast);
/*
* Unlink this pqmsg from the message list.
*/
if (pqmsg->pqmsgPrev != NULL)
pqmsg->pqmsgPrev->pqmsgNext = pqmsg->pqmsgNext;
if (pqmsg->pqmsgNext != NULL)
pqmsg->pqmsgNext->pqmsgPrev = pqmsg->pqmsgPrev;
/*
* Update the read/write pointers if necessary.
*/
if (pml->pqmsgRead == pqmsg)
pml->pqmsgRead = pqmsg->pqmsgNext;
if (pml->pqmsgWriteLast == pqmsg)
pml->pqmsgWriteLast = pqmsg->pqmsgPrev;
/*
* Adjust the message count and free the message structure.
*/
pml->cMsgs–;
ExFreeToPagedLookasideList(QEntryLookaside, pqmsg);
DebugValidateMLIST(pml);
}
1: kd> dx -id 0,0,89413020 -r1 (*((win32k!tagMLIST *)0xe1630530))
(*((win32k!tagMLIST *)0xe1630530)) [Type: tagMLIST]
[+0x000] pqmsgRead : 0x0 [Type: tagQMSG *]
[+0x004] pqmsgWriteLast : 0x0 [Type: tagQMSG *]
[+0x008] cMsgs : 0x0 [Type: unsigned long]
switch (pqmsg->msg.message) {
case WM_KEYUP:
case WM_SYSKEYUP:
fDown = FALSE;
/*
* Fall through.
*/
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
vk = LOBYTE(LOWORD(pqmsg->msg.wParam));
break;
vk = 0x36 '6'
} else {
UpdateKeyState(pti->pq, vk, fDown);
}
}
1: kd> t
eax=e1404c50 ebx=00000000 ecx=00000000 edx=f75c6bc4 esi=bf9ea2a4 edi=bf9eb174
eip=bf80921a esp=f75c6a7c ebp=f75c6a9c 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!xxxSkipSysMsg+0x4b0:
bf80921a e811010000 call win32k!UpdateKeyState (bf809330)
1: kd> t
eax=e1404c50 ebx=00000000 ecx=00000000 edx=f75c6bc4 esi=bf9ea2a4 edi=bf9eb174
eip=bf809330 esp=f75c6a78 ebp=f75c6a9c 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!UpdateKeyState:
bf809330 55 push ebp
1: kd> dv
pq = 0xe1630530
vk = 0x36
fDown = 0n0
1: kd> dx -id 0,0,89413020 -r1 ((win32k!tagQ *)0xe1630530)
((win32k!tagQ *)0xe1630530) : 0xe1630530 [Type: tagQ *]
[+0x000] mlInput [Type: tagMLIST]
[+0x00c] ptiSysLock : 0xe1404c50 [Type: tagTHREADINFO *]
[+0x010] idSysLock : 0xe16fa0a8 [Type: unsigned long]
[+0x014] idSysPeek : 0x0 [Type: unsigned long]
[+0x018] ptiMouse : 0xe1404c50 [Type: tagTHREADINFO *]
[+0x01c] ptiKeyboard : 0xe1404c50 [Type: tagTHREADINFO *]
[+0x020] spwndCapture : 0x0 [Type: tagWND *]
[+0x024] spwndFocus : 0xbc6449ac [Type: tagWND *]
[+0x028] spwndActive : 0xbc644124 [Type: tagWND *]
[+0x02c] spwndActivePrev : 0x0 [Type: tagWND *]
[+0x030] codeCapture : 0x1 [Type: unsigned int]
[+0x034] msgDblClk : 0x201 [Type: unsigned int]
[+0x038] xbtnDblClk : 0x0 [Type: unsigned short]
[+0x03c] timeDblClk : 0xffe598d9 [Type: unsigned long]
[+0x040] hwndDblClk : 0xc00d6 [Type: HWND__ *]
[+0x044] ptDblClk : {x=464 y=375} [Type: tagPOINT]
[+0x04c] afKeyRecentDown [Type: unsigned char [32]]
[+0x06c] afKeyState [Type: unsigned char [64]]
[+0x0ac] caret [Type: tagCARET]
[+0x0e4] spcurCurrent : 0x0 [Type: tagCURSOR *]
[+0x0e8] iCursorLevel : 0 [Type: int]
[+0x0ec] QF_flags : 0x140 [Type: unsigned long]
[+0x0f0] cThreads : 0x1 [Type: unsigned short]
[+0x0f2] cLockCount : 0x0 [Type: unsigned short]
[+0x0f4] msgJournal : 0x0 [Type: unsigned int]
[+0x0f8] ExtraInfo : 0 [Type: long]
1: kd> dx -id 0,0,89413020 -r1 (*((win32k!unsigned char (*)[64])0xe163059c))
(*((win32k!unsigned char (*)[64])0xe163059c)) [Type: unsigned char [64]]
[0] : 0x8 [Type: unsigned char]
[1] : 0x0 [Type: unsigned char]
[2] : 0x8 [Type: unsigned char]
[3] : 0x0 [Type: unsigned char]
[4] : 0x8 [Type: unsigned char]
[5] : 0x0 [Type: unsigned char]
[6] : 0x0 [Type: unsigned char]
[7] : 0x0 [Type: unsigned char]
[8] : 0x0 [Type: unsigned char]
[9] : 0x0 [Type: unsigned char]
[10] : 0x0 [Type: unsigned char]
[11] : 0x20 [Type: unsigned char]
[12] : 0x0 [Type: unsigned char]
[13] : 0x3a [Type: unsigned char]
0011 0110
0011 01
0n13
0011 1010
0010 1010
0x2a
1: kd> dx -id 0,0,89413020 -r1 (*((win32k!unsigned char (*)[64])0xe163059c))
(*((win32k!unsigned char (*)[64])0xe163059c)) [Type: unsigned char [64]]
[0] : 0x8 [Type: unsigned char]
[1] : 0x0 [Type: unsigned char]
[2] : 0x8 [Type: unsigned char]
[3] : 0x0 [Type: unsigned char]
[4] : 0x8 [Type: unsigned char]
[5] : 0x0 [Type: unsigned char]
[6] : 0x0 [Type: unsigned char]
[7] : 0x0 [Type: unsigned char]
[8] : 0x0 [Type: unsigned char]
[9] : 0x0 [Type: unsigned char]
[10] : 0x0 [Type: unsigned char]
[11] : 0x20 [Type: unsigned char]
[12] : 0x0 [Type: unsigned char]
[13] : 0x2a [Type: unsigned char]
/*
* Get the previous up/down state of the key here since
* SkipSysMsg() sets the key state table and destroys
* the previous state info.
*/由于SkipSysMsg()函数会设置按键状态表并销毁之前的状态信息,因此需要在此处获取按键的上一次按下/释放状态
fPrevDown = FALSE;
if (TestKeyStateDown(ptiCurrent->pq, wParam))
fPrevDown = TRUE; //fPrevDown=true这里被赋值为TRUE
/*
* Eat the message from the input queue and set the keystate
* table.
*/
PATHTAKEN3(0x20);
if (fRemove) {
xxxSkipSysMsg(ptiCurrent, &qmsg);
}
/*
* This gets us the LOWORD of lParam, the repeat count,
* the bit in the hi byte indicating whether this is an extended
* key, and the scan code. We also need to re-get the wParam in
* case xxxSkipSysMsg called a hook which modified the message.
* AfterDark's password protection does this.
*/
lParam = qmsg.msg.lParam;
wParam = qmsg.msg.wParam;
/*
* Indicate if it was previously down.
*/
if (fPrevDown)
lParam |= 0x40000000; // KF_REPEAT //关键代码
1: kd> dv lParam
lParam = 0n1074200577
1: kd> ?0n1074200577
Evaluate expression: 1074200577 = 40070001
/*
* Set the transition bit.
*/
switch (message) {
case WM_KEYUP:
case WM_SYSKEYUP:
lParam |= 0x80000000; // KF_UP
break;
}
1: kd> dv lParam
lParam = 0n-1073283071
1: kd> ?0n-1073283071
Evaluate expression: -1073283071 = c0070001
/*
* Set the alt key down bit.
*/
if (TestKeyStateDown(ptiCurrent->pq, VK_MENU)) {
lParam |= 0x20000000; // KF_ALTDOWN
}
/*
* Set the menu state flag.
*/
if (IsMenuStarted(ptiCurrent)) {
lParam |= 0x10000000; // KF_MENUMODE
}
/*
* Set the dialog state flag.
*/
if (ptiCurrent->pq->QF_flags & QF_DIALOGACTIVE) {
lParam |= 0x08000000; // KF_DLGMODE
}
/*
* 0x80000000 is set if up, clear if down
* 0x40000000 is previous up/down state of key
* 0x20000000 is whether the alt key is down
* 0x10000000 is whether currently in menumode.
* 0x08000000 is whether in dialog mode
* 0x04000000 is not used
* 0x02000000 is not used
* 0x01000000 is whether this is an extended keyboard key
*
* Low word is repeat count, low byte hiword is scan code,
* hi byte hiword is all these bits.
*/