📄 keyboard.c
字号:
UserEnterExclusive();
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 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 : 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
STDCALL
NtUserGetKeyboardLayoutList(
DWORD Items,
DWORD pHklBuff)
{
UNIMPLEMENTED
return 0;
}
BOOL
STDCALL
NtUserGetKeyboardLayoutName(
LPWSTR lpszName)
{
BOOL ret = FALSE;
LCID LocaleId;
WCHAR LocaleBuffer[16];
NTSTATUS Status;
UserEnterExclusive();
DPRINT("Enter NtUserGetKeyboardLayoutName\n");
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
if (NT_SUCCESS(Status))
{
swprintf(LocaleBuffer, L"%08lx", LocaleId);
DPRINT("LocaleId : %08lx\n",LocaleId);
_SEH_TRY
{
ProbeForWrite(lpszName, 16, 1);
RtlCopyMemory(lpszName,LocaleBuffer,16);
ret = TRUE;
}
_SEH_HANDLE
{
SetLastNtError(_SEH_GetExceptionCode());
ret = FALSE;
}
_SEH_END;
}
UserLeave();
return ret;
}
HKL FASTCALL
UserGetKeyboardLayout(
DWORD dwThreadId)
{
NTSTATUS Status;
PETHREAD Thread;
PW32THREAD W32Thread;
PKBDTABLES layout;
if (!dwThreadId)
W32Thread = PsGetCurrentThreadWin32Thread();
else
{
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);//fixme: deref thread
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
W32Thread = Thread->Tcb.Win32Thread; /* Wrong, but returning the pointer to
the table. */
}
layout = W32Thread->KeyboardLayout;
if(!layout)
return 0;
return (HKL)layout;
}
HKL
STDCALL
NtUserGetKeyboardLayout(
DWORD dwThreadId)
{
DECLARE_RETURN(HKL);
UserEnterShared();
DPRINT("Enter NtUserGetKeyboardLayout\n");
RETURN( UserGetKeyboardLayout(dwThreadId));
CLEANUP:
DPRINT("Leave NtUserGetKeyboardLayout, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
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 */
}
}
HKL
STDCALL
NtUserLoadKeyboardLayoutEx(
IN HANDLE Handle,
IN DWORD offTable,
IN HKL hKL,
IN PUNICODE_STRING puszKLID,
IN UINT KLayoutLangID,
IN UINT Flags)
{
UNIMPLEMENTED
return 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 + -