📄 keyboard.c
字号:
return Result;
}
DWORD
STDCALL
NtUserGetKeyboardState(
LPBYTE lpKeyState)
{
BOOL Result = TRUE;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetKeyboardState\n");
UserEnterShared();
if (lpKeyState)
{
if(!NT_SUCCESS(MmCopyToCaller(lpKeyState, gQueueKeyStateTable, 256)))
Result = FALSE;
}
RETURN(Result);
CLEANUP:
DPRINT("Leave NtUserGetKeyboardState, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD
STDCALL
NtUserSetKeyboardState(LPBYTE lpKeyState)
{
BOOL Result = TRUE;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserSetKeyboardState\n");
UserEnterExclusive();
if (lpKeyState)
{
if(! NT_SUCCESS(MmCopyFromCaller(gQueueKeyStateTable, lpKeyState, 256)))
Result = FALSE;
}
RETURN(Result);
CLEANUP:
DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT )
{
int i;
for( i = 0; i < pkKT->bMaxVSCtoVK; i++ )
{
if( pkKT->pusVSCtoVK[i] == Code )
{
return i;
}
}
return 0;
}
UINT ScanToVk( UINT Code, BOOL ExtKey, PKBDTABLES pkKT )
{
if( !pkKT )
{
DPRINT("ScanToVk: No layout\n");
return 0;
}
if( ExtKey )
{
int i;
for( i = 0; pkKT->pVSCtoVK_E0[i].Vsc; i++ )
{
if( pkKT->pVSCtoVK_E0[i].Vsc == Code )
return pkKT->pVSCtoVK_E0[i].Vk & 0xff;
}
for( i = 0; pkKT->pVSCtoVK_E1[i].Vsc; i++ )
{
if( pkKT->pVSCtoVK_E1[i].Vsc == Code )
return pkKT->pVSCtoVK_E1[i].Vk & 0xff;
}
return 0;
}
else
{
if( Code >= pkKT->bMaxVSCtoVK )
{
return 0;
}
return pkKT->pusVSCtoVK[Code] & 0xff;
}
}
/*
* Map a virtual key code, or virtual scan code, to a scan code, key code,
* or unshifted unicode character.
*
* Code: See Below
* Type:
* 0 -- Code is a virtual key code that is converted into a virtual scan code
* that does not distinguish between left and right shift keys.
* 1 -- Code is a virtual scan code that is converted into a virtual key code
* that does not distinguish between left and right shift keys.
* 2 -- Code is a virtual key code that is converted into an unshifted unicode
* character.
* 3 -- Code is a virtual scan code that is converted into a virtual key code
* that distinguishes left and right shift keys.
* KeyLayout: Keyboard layout handle (currently, unused)
*
* @implemented
*/
static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout )
{
UINT ret = 0;
switch( Type )
{
case 0:
if( Code == VK_RSHIFT )
Code = VK_LSHIFT;
if( Code == VK_RMENU )
Code = VK_LMENU;
if( Code == VK_RCONTROL )
Code = VK_LCONTROL;
ret = VkToScan( Code, FALSE, keyLayout );
break;
case 1:
ret =
DontDistinguishShifts
(IntMapVirtualKeyEx( Code, 3, keyLayout ) );
break;
case 2:
{
WCHAR wp[2] = {0};
ret = VkToScan( Code, FALSE, keyLayout );
ToUnicodeInner( Code, ret, 0, wp, 2, 0, keyLayout );
ret = wp[0];
}
break;
case 3:
ret = ScanToVk( Code, FALSE, keyLayout );
break;
}
return ret;
}
UINT
STDCALL
NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl )
{
PKBDTABLES keyLayout;
DECLARE_RETURN(UINT);
DPRINT("Enter NtUserMapVirtualKeyEx\n");
UserEnterExclusive();
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
if( !keyLayout )
RETURN(0);
RETURN(IntMapVirtualKeyEx( Code, Type, keyLayout ));
CLEANUP:
DPRINT("Leave NtUserMapVirtualKeyEx, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
int
STDCALL
NtUserToUnicodeEx(
UINT wVirtKey,
UINT wScanCode,
PBYTE lpKeyState,
LPWSTR pwszBuff,
int cchBuff,
UINT wFlags,
HKL dwhkl )
{
BYTE KeyStateBuf[0x100];
PWCHAR OutPwszBuff = 0;
int ret = 0;
DECLARE_RETURN(int);
DPRINT("Enter NtUserSetKeyboardState\n");
UserEnterShared();//faxme: this syscall doesnt seem to need any locking...
if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
lpKeyState,
sizeof(KeyStateBuf))) )
{
DPRINT1( "Couldn't copy key state from caller.\n" );
RETURN(0);
}
OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING);
if( !OutPwszBuff )
{
DPRINT1( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
RETURN(0);
}
RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );
ret = ToUnicodeEx( wVirtKey,
wScanCode,
KeyStateBuf,
OutPwszBuff,
cchBuff,
wFlags,
dwhkl );
MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff);
ExFreePool(OutPwszBuff);
RETURN(ret);
CLEANUP:
DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static int W32kSimpleToupper( int ch )
{
if( ch >= 'a' && ch <= 'z' )
ch = ch - 'a' + 'A';
return ch;
}
DWORD
STDCALL
NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
{
int i;
DWORD ret = 0;
UINT CareVk = 0;
UINT VkCode = 0;
UINT ScanCode = (lParam >> 16) & 0xff;
BOOL ExtKey = lParam & (1<<24) ? TRUE : FALSE;
PKBDTABLES keyLayout;
VSC_LPWSTR *KeyNames;
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetKeyNameText\n");
UserEnterShared();
keyLayout = PsGetCurrentThreadWin32Thread() ?
PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
if( !keyLayout || nSize < 1 )
RETURN(0);
if( lParam & (1<<25) )
{
CareVk = VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
if( VkCode == VK_LSHIFT || VkCode == VK_RSHIFT )
VkCode = VK_LSHIFT;
if( VkCode == VK_LCONTROL || VkCode == VK_RCONTROL )
VkCode = VK_LCONTROL;
if( VkCode == VK_LMENU || VkCode == VK_RMENU )
VkCode = VK_LMENU;
}
else
{
VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
}
KeyNames = 0;
if( CareVk != VkCode )
ScanCode = VkToScan( VkCode, ExtKey, keyLayout );
if( ExtKey )
KeyNames = keyLayout->pKeyNamesExt;
else
KeyNames = keyLayout->pKeyNames;
for( i = 0; KeyNames[i].pwsz; i++ )
{
if( KeyNames[i].vsc == ScanCode )
{
UINT StrLen = wcslen(KeyNames[i].pwsz);
UINT StrMax = StrLen > (nSize - 1) ? (nSize - 1) : StrLen;
WCHAR null_wc = 0;
if( NT_SUCCESS( MmCopyToCaller( lpString,
KeyNames[i].pwsz,
StrMax * sizeof(WCHAR) ) ) &&
NT_SUCCESS( MmCopyToCaller( lpString + StrMax,
&null_wc,
sizeof( WCHAR ) ) ) )
{
ret = StrMax;
break;
}
}
}
if( ret == 0 )
{
WCHAR UCName[2];
UCName[0] = W32kSimpleToupper(IntMapVirtualKeyEx( VkCode, 2, keyLayout ));
UCName[1] = 0;
ret = 1;
if( !NT_SUCCESS(MmCopyToCaller( lpString, UCName, 2 * sizeof(WCHAR) )) )
RETURN(0);
}
RETURN(ret);
CLEANUP:
DPRINT("Leave NtUserGetKeyNameText, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* Filter this message according to the current key layout, setting wParam
* appropriately.
*/
VOID FASTCALL
W32kKeyProcessMessage(LPMSG Msg,
PKBDTABLES KeyboardLayout,
BYTE Prefix)
{
DWORD ScanCode = 0, ModifierBits = 0;
DWORD i = 0;
DWORD BaseMapping = 0;
DWORD RawVk = 0;
static WORD NumpadConversion[][2] =
{ { VK_DELETE, VK_DECIMAL },
{ VK_INSERT, VK_NUMPAD0 },
{ VK_END, VK_NUMPAD1 },
{ VK_DOWN, VK_NUMPAD2 },
{ VK_NEXT, VK_NUMPAD3 },
{ VK_LEFT, VK_NUMPAD4 },
{ VK_CLEAR, VK_NUMPAD5 },
{ VK_RIGHT, VK_NUMPAD6 },
{ VK_HOME, VK_NUMPAD7 },
{ VK_UP, VK_NUMPAD8 },
{ VK_PRIOR, VK_NUMPAD9 },
{ 0,0 } };
PVSC_VK VscVkTable = NULL;
if( !KeyboardLayout || !Msg ||
(Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
Msg->message != WM_KEYUP && Msg->message != WM_SYSKEYUP) )
{
return;
}
/* arty -- handle numpad -- On real windows, the actual key produced
* by the messaging layer is different based on the state of numlock. */
ModifierBits = ModBits(KeyboardLayout,gQueueKeyStateTable);
/* Get the raw scan code, so we can look up whether the key is a numpad
* key
*
* Shift and the LP_EXT_BIT cancel. */
ScanCode = (Msg->lParam >> 16) & 0xff;
BaseMapping = Msg->wParam =
IntMapVirtualKeyEx( ScanCode, 1, KeyboardLayout );
if( Prefix == 0 )
{
if( ScanCode >= KeyboardLayout->bMaxVSCtoVK )
RawVk = 0xff;
else
RawVk = KeyboardLayout->pusVSCtoVK[ScanCode];
}
else
{
if( Prefix == 0xE0 )
{
/* ignore shift codes */
if( ScanCode == 0x2A || ScanCode == 0x36 )
{
return;
}
VscVkTable = KeyboardLayout->pVSCtoVK_E0;
}
else if( Prefix == 0xE1 )
{
VscVkTable = KeyboardLayout->pVSCtoVK_E1;
}
RawVk = 0xff;
while (VscVkTable->Vsc)
{
if( VscVkTable->Vsc == ScanCode )
{
RawVk = VscVkTable->Vk;
}
VscVkTable++;
}
}
if ((ModifierBits & NUMLOCK_BIT) &&
!(ModifierBits & GetShiftBit(KeyboardLayout, VK_SHIFT)) &&
(RawVk & KNUMP) &&
!(Msg->lParam & LP_EXT_BIT))
{
/* The key in question is a numpad key. Search for a translation. */
for (i = 0; NumpadConversion[i][0]; i++)
{
if ((BaseMapping & 0xff) == NumpadConversion[i][0]) /* RawVk? */
{
Msg->wParam = NumpadConversion[i][1];
break;
}
}
}
DPRINT("Key: [%04x -> %04x]\n", BaseMapping, Msg->wParam);
/* Now that we have the VK, we can set the keymap appropriately
* This is a better place for this code, as it's guaranteed to be
* run, unlike translate message. */
if (Msg->message == WM_KEYDOWN || Msg->message == WM_SYSKEYDOWN)
{
SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT,
TRUE ); /* Strike key */
}
else if (Msg->message == WM_KEYUP || Msg->message == WM_SYSKEYUP)
{
SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT,
FALSE ); /* Release key */
}
/* We need to unset SYSKEYDOWN if the ALT key is an ALT+Gr */
if( gQueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT )
{
if( Msg->message == WM_SYSKEYDOWN )
Msg->message = WM_KEYDOWN;
else
Msg->message = WM_KEYUP;
}
}
DWORD FASTCALL
UserGetKeyboardType(
DWORD TypeFlag)
{
switch(TypeFlag)
{
case 0: /* Keyboard type */
return 4; /* AT-101 */
case 1: /* Keyboard Subtype */
return 0; /* There are no defined subtypes */
case 2: /* Number of F-keys */
return 12; /* We're doing an 101 for now, so return 12 F-keys */
default:
DPRINT1("Unknown type!\n");
return 0; /* The book says 0 here, so 0 */
}
}
/*
Based on TryToTranslateChar, instead of processing VirtualKey match,
look for wChar match.
*/
DWORD
STDCALL
NtUserVkKeyScanEx(
DWORD wChar,
DWORD KeyboardLayout,
DWORD Unknown2)
{
/* FAXME: currently, this routine doesnt seem to need any locking */
PKBDTABLES KeyLayout;
PVK_TO_WCHAR_TABLE vtwTbl;
PVK_TO_WCHARS10 vkPtr;
size_t size_this_entry;
int nMod;
DWORD CapsMod = 0, CapsState = 0;
if(!KeyboardLayout)
return -1;
KeyLayout = (PKBDTABLES) KeyboardLayout;
for (nMod = 0; KeyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
{
vtwTbl = &KeyLayout->pVkToWcharTable[nMod];
size_this_entry = vtwTbl->cbSize;
vkPtr = (PVK_TO_WCHARS10)((BYTE *)vtwTbl->pVkToWchars);
while(vkPtr->VirtualKey)
{
/*
0x01 Shift key
0x02 Ctrl key
0x04 Alt key
Should have only 8 valid possibilities. Including zero.
*/
for(CapsState = 0; CapsState < vtwTbl->nModifications; CapsState++)
{
if(vkPtr->wch[CapsState] == wChar)
{
CapsMod = KeyLayout->pCharModifiers->ModNumber[CapsState];
DPRINT("nMod %d wC %04x: CapsMod %08x CapsState %08x MaxModBits %08x\n",
nMod, wChar, CapsMod, CapsState, KeyLayout->pCharModifiers->wMaxModBits);
return ((CapsMod << 8)|(vkPtr->VirtualKey & 0xff));
}
}
vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + size_this_entry);
}
}
return -1;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -