📄 keyboard.c
字号:
return STATUS_NO_MEMORY;
}
memcpy( new_string, ResultFirst->Buffer,
ResultFirst->Length );
memcpy( new_string + ResultFirst->Length / sizeof(WCHAR),
Second->Buffer,
Second->Length );
if( Deallocate )
RtlFreeUnicodeString(ResultFirst);
ResultFirst->Length += Second->Length;
ResultFirst->MaximumLength = ResultFirst->Length;
new_string[ResultFirst->Length / sizeof(WCHAR)] = 0;
Status = RtlCreateUnicodeString(ResultFirst,new_string) ?
STATUS_SUCCESS : STATUS_NO_MEMORY;
ExFreePool(new_string);
return Status;
}
/*
* Utility function to read a value from the registry more easily.
*
* IN PUNICODE_STRING KeyName -> Name of key to open
* IN PUNICODE_STRING ValueName -> Name of value to open
* OUT PUNICODE_STRING ReturnedValue -> String contained in registry
*
* Returns NTSTATUS
*/
static NTSTATUS NTAPI ReadRegistryValue( PUNICODE_STRING KeyName,
PUNICODE_STRING ValueName,
PUNICODE_STRING ReturnedValue )
{
NTSTATUS Status;
HANDLE KeyHandle;
OBJECT_ATTRIBUTES KeyAttributes;
PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
ULONG Length = 0;
ULONG ResLength = 0;
UNICODE_STRING Temp;
InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
if( !NT_SUCCESS(Status) )
{
return Status;
}
Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
0,
0,
&ResLength);
if( Status != STATUS_BUFFER_TOO_SMALL )
{
NtClose(KeyHandle);
return Status;
}
ResLength += sizeof( *KeyValuePartialInfo );
KeyValuePartialInfo =
ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
Length = ResLength;
if( !KeyValuePartialInfo )
{
NtClose(KeyHandle);
return STATUS_NO_MEMORY;
}
Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
(PVOID)KeyValuePartialInfo,
Length,
&ResLength);
if( !NT_SUCCESS(Status) )
{
NtClose(KeyHandle);
ExFreePool(KeyValuePartialInfo);
return Status;
}
Temp.Length = Temp.MaximumLength = KeyValuePartialInfo->DataLength;
Temp.Buffer = (PWCHAR)KeyValuePartialInfo->Data;
/* At this point, KeyValuePartialInfo->Data contains the key data */
RtlInitUnicodeString(ReturnedValue,L"");
AppendUnicodeString(ReturnedValue,&Temp,FALSE);
ExFreePool(KeyValuePartialInfo);
NtClose(KeyHandle);
return Status;
}
typedef PVOID (*KbdLayerDescriptor)(VOID);
NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
PANSI_STRING import_name,
DWORD flags,
PVOID *func_addr);
void InitKbdLayout( PVOID *pkKeyboardLayout )
{
WCHAR LocaleBuffer[16];
UNICODE_STRING LayoutKeyName;
UNICODE_STRING LayoutValueName;
UNICODE_STRING DefaultLocale;
UNICODE_STRING LayoutFile;
UNICODE_STRING FullLayoutPath;
LCID LocaleId;
PWCHAR KeyboardLayoutWSTR;
HMODULE kbModule = 0;
NTSTATUS Status;
ANSI_STRING kbdProcedureName;
KbdLayerDescriptor layerDescGetFn;
#define XX_STATUS(x) if (!NT_SUCCESS(Status = (x))) continue;
do
{
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get default locale (%08lx).\n", Status);
}
else
{
DPRINT("DefaultLocale = %lx\n", LocaleId);
swprintf(LocaleBuffer, L"%08lx", LocaleId);
DPRINT("DefaultLocale = %S\n", LocaleBuffer);
RtlInitUnicodeString(&DefaultLocale, LocaleBuffer);
RtlInitUnicodeString(&LayoutKeyName,
L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
L"\\Control\\KeyboardLayouts\\");
AppendUnicodeString(&LayoutKeyName,&DefaultLocale,FALSE);
RtlInitUnicodeString(&LayoutValueName,L"Layout File");
Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);
RtlFreeUnicodeString(&LayoutKeyName);
if( !NT_SUCCESS(Status) )
{
DPRINT1("Got default locale but not layout file. (%08lx)\n",
Status);
}
else
{
DPRINT("Read registry and got %wZ\n", &LayoutFile);
RtlInitUnicodeString(&FullLayoutPath,SYSTEMROOT_DIR);
AppendUnicodeString(&FullLayoutPath,&LayoutFile,FALSE);
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
RtlFreeUnicodeString(&LayoutFile);
KeyboardLayoutWSTR =
ExAllocatePoolWithTag(PagedPool,
FullLayoutPath.Length + sizeof(WCHAR),
TAG_STRING);
if( !KeyboardLayoutWSTR )
{
DPRINT1("Couldn't allocate a string for the keyboard layout name.\n");
RtlFreeUnicodeString(&FullLayoutPath);
return;
}
memcpy(KeyboardLayoutWSTR,FullLayoutPath.Buffer,
FullLayoutPath.Length);
KeyboardLayoutWSTR[FullLayoutPath.Length / sizeof(WCHAR)] = 0;
kbModule = EngLoadImage(KeyboardLayoutWSTR);
DPRINT( "Load Keyboard Layout: %S\n", KeyboardLayoutWSTR );
if( !kbModule )
DPRINT1( "Load Keyboard Layout: No %wZ\n", &FullLayoutPath );
ExFreePool(KeyboardLayoutWSTR);
RtlFreeUnicodeString(&FullLayoutPath);
}
}
if( !kbModule )
{
DPRINT1("Trying to load US Keyboard Layout\n");
kbModule = EngLoadImage(L"\\SystemRoot\\system32\\kbdus.dll");
if (!kbModule)
{
DPRINT1("Failed to load any Keyboard Layout\n");
return;
}
}
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
LdrGetProcedureAddress((PVOID)kbModule,
&kbdProcedureName,
0,
(PVOID*)&layerDescGetFn);
if( layerDescGetFn )
{
*pkKeyboardLayout = layerDescGetFn();
}
}
while (FALSE);
if( !*pkKeyboardLayout )
{
DPRINT1("Failed to load the keyboard layout.\n");
}
#undef XX_STATUS
}
PKBDTABLES W32kGetDefaultKeyLayout(VOID)
{
PKBDTABLES pkKeyboardLayout = 0;
InitKbdLayout( (PVOID) &pkKeyboardLayout );
return pkKeyboardLayout;
}
BOOL FASTCALL
IntTranslateKbdMessage(LPMSG lpMsg,
HKL dwhkl)
{
static INT dead_char = 0;
LONG UState = 0;
WCHAR wp[2] = { 0 };
MSG NewMsg = { 0 };
PKBDTABLES keyLayout;
BOOL Result = FALSE;
DWORD ScanCode = 0;
keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
if( !keyLayout )
return FALSE;
if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
return FALSE;
ScanCode = (lpMsg->lParam >> 16) & 0xff;
/* All messages have to contain the cursor point. */
IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop->WindowStation,
&NewMsg.pt);
UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff,
gQueueKeyStateTable, wp, 2, 0,
keyLayout );
if (UState == 1)
{
NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
if (dead_char)
{
ULONG i;
WCHAR first, second;
DPRINT("PREVIOUS DEAD CHAR: %c\n", dead_char);
for( i = 0; keyLayout->pDeadKey[i].dwBoth; i++ )
{
first = keyLayout->pDeadKey[i].dwBoth >> 16;
second = keyLayout->pDeadKey[i].dwBoth;
if (first == dead_char && second == wp[0])
{
wp[0] = keyLayout->pDeadKey[i].wchComposed;
dead_char = 0;
break;
}
}
DPRINT("FINAL CHAR: %c\n", wp[0]);
}
if (dead_char)
{
NewMsg.hwnd = lpMsg->hwnd;
NewMsg.wParam = dead_char;
NewMsg.lParam = lpMsg->lParam;
dead_char = 0;
MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
}
NewMsg.hwnd = lpMsg->hwnd;
NewMsg.wParam = wp[0];
NewMsg.lParam = lpMsg->lParam;
DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
Result = TRUE;
}
else if (UState == -1)
{
NewMsg.message =
(lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
NewMsg.hwnd = lpMsg->hwnd;
NewMsg.wParam = wp[0];
NewMsg.lParam = lpMsg->lParam;
dead_char = wp[0];
MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
Result = TRUE;
}
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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -