reverting 25758 : for follow reason

1. it cause regress of loading keyboard layout from the regsiter when reatcos booting. 
2. it does not follow windows implement 
3. it does not using ntoskrnl for it is ntoskrnl that handling the keyboard not the win32k.
4. it does not using right protoype for some syscall
5. some syscall does not working like windows. it mess it up instead. 
6. Do not implement own design on public api and syscall

svn path=/trunk/; revision=25763
This commit is contained in:
Magnus Olsen 2007-02-10 14:52:46 +00:00
parent 516fc1cc74
commit 1bbe7c2674
13 changed files with 686 additions and 526 deletions

View file

@ -241,10 +241,13 @@ VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
{
INT len;
PTCHAR pBuf;
CONSOLE_SCREEN_BUFFER_INFO csbi;
TCHAR szOut[OUTPUT_BUFFER_SIZE];
DWORD dwWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
#ifdef _UNICODE
INT WideLen;
PCHAR pBuf;
#endif
/* used to count number of lines since last pause */
static int LineCount = 0;
@ -266,8 +269,7 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
/* rest LineCount and return if no string have been given */
if (szFormat == NULL)
return 0;
//get the size of the visual screen that can be printed too
if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
{
@ -287,37 +289,48 @@ INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHa
}
len = _vstprintf (szOut, szFormat, arg_ptr);
pBuf = szOut;
#ifdef _UNICODE
pBuf = malloc(len + 1);
#endif
for(i = 0; i < len; i++)
{
// search 'end of string' '\n' or 'end of screen line'
for(; (i < len) && (pBuf[i] != _T('\n') && (CharSL<ScreenCol)) ; i++)
for(; (i < len) && (szOut[i] != _T('\n') && (CharSL<ScreenCol)) ; i++)
CharSL++;
WriteFile (GetStdHandle (nStdHandle),&pBuf[i-CharSL],sizeof(CHAR)*(CharSL+1),&dwWritten,NULL);
LineCount++;
CharSL=0;
#ifdef _UNICODE
WideLen = WideCharToMultiByte( OutputCodePage, 0, &szOut[i-CharSL], CharSL + 1, pBuf, CharSL + 1, NULL, NULL);
WriteFile (GetStdHandle (nStdHandle),pBuf,WideLen,&dwWritten,NULL);
#else
WriteFile (GetStdHandle (nStdHandle),&szOut[i-CharSL],sizeof(CHAR)*(CharSL+1),&dwWritten,NULL);
#endif
LineCount++;
if(LineCount >= ScreenLines)
{
if(_tcsnicmp(&pBuf[i], _T("\n"), 2)!=0)
if(_tcsnicmp(&szOut[i], _T("\n"), 2)!=0)
WriteFile (GetStdHandle (nStdHandle),_T("\n"),sizeof(CHAR),&dwWritten,NULL);
if(PagePrompt() != PROMPT_YES)
{
return 1;
break;
}
//reset the number of lines being printed
LineCount = 0;
CharSL=0;
}
CharSL=0;
}
#ifdef _UNICODE
free(pBuf);
#endif
if (i < len) //!= PROMPT_YES
return 1;
return 0;
}

View file

@ -1,7 +1,7 @@
LIBRARY user32.dll
EXPORTS
ActivateKeyboardLayout@8=NtUserActivateKeyboardLayout@8
ActivateKeyboardLayout@8
AdjustWindowRect@12
AdjustWindowRectEx@16
AlignRects@16
@ -295,7 +295,7 @@ GetKeyNameTextA@12
GetKeyNameTextW@12
GetKeyState@4
GetKeyboardLayout@4
GetKeyboardLayoutList@8=NtUserGetKeyboardLayoutList@8
GetKeyboardLayoutList@8
GetKeyboardLayoutNameA@4
GetKeyboardLayoutNameW@4
GetKeyboardState@4

View file

@ -46,6 +46,218 @@ static UINT_PTR timer;
static const INT iTimerInterval = 50; /* msec for timer interval */
/* LOCALE FUNCTIONS **********************************************************/
/*
* 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 FASTCALL
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;
PWCHAR ReturnBuffer;
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 = LocalAlloc(LMEM_ZEROINIT, ResLength);
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);
LocalFree(KeyValuePartialInfo);
return Status;
}
/* At this point, KeyValuePartialInfo->Data contains the key data */
ReturnBuffer = LocalAlloc(0, KeyValuePartialInfo->DataLength);
if(!ReturnBuffer)
{
NtClose(KeyHandle);
LocalFree(KeyValuePartialInfo);
return STATUS_NO_MEMORY;
}
RtlCopyMemory(ReturnBuffer, KeyValuePartialInfo->Data, KeyValuePartialInfo->DataLength);
RtlInitUnicodeString(ReturnedValue, ReturnBuffer);
LocalFree(KeyValuePartialInfo);
NtClose(KeyHandle);
return Status;
}
static
HKL FASTCALL
IntLoadKeyboardLayout( LPCWSTR pwszKLID,
UINT Flags)
{
HANDLE Handle;
HINSTANCE KBModule = 0;
FARPROC pAddr = 0;
DWORD offTable = 0;
HKL hKL;
NTSTATUS Status;
WCHAR LocaleBuffer[16];
UNICODE_STRING LayoutKeyName;
UNICODE_STRING LayoutValueName;
UNICODE_STRING DefaultLocale;
UNICODE_STRING LayoutFile;
UNICODE_STRING FullLayoutPath;
LCID LocaleId;
ULONG_PTR layout;
LANGID langid;
WCHAR FullPathBuffer[MAX_PATH];
WCHAR LayoutKeyNameBuffer[128] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
L"\\Control\\KeyboardLayouts\\";
layout = (ULONG_PTR) wcstoul(pwszKLID, NULL, 16);
// LocaleId = GetSystemDefaultLCID();
LocaleId = (LCID) layout;
/* Create the HKL to be used by NtUserLoadKeyboardLayoutEx*/
/*
* Microsoft Office expects this value to be something specific
* for Japanese and Korean Windows with an IME the value is 0xe001
* We should probably check to see if an IME exists and if so then
* set this word properly.
*/
langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
layout |= 0xe001 << 16; /* FIXME */
else
layout |= layout << 16;
DPRINT("Input = %S, DefaultLocale = %lx\n", pwszKLID, LocaleId );
swprintf(LocaleBuffer, L"%08lx", LocaleId);
DPRINT("DefaultLocale = %S\n", LocaleBuffer);
RtlInitUnicodeString(&DefaultLocale, LocaleBuffer);
RtlInitUnicodeString(&LayoutKeyName, LayoutKeyNameBuffer);
LayoutKeyName.MaximumLength = sizeof(LayoutKeyNameBuffer);
RtlAppendUnicodeStringToString(&LayoutKeyName, &DefaultLocale);
DPRINT("LayoutKeyName=%wZ\n", &LayoutKeyName);
RtlInitUnicodeString(&LayoutValueName, L"Layout File");
Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to read registry value, %x\n", Status);
return NULL;
}
DPRINT("Read registry and got %wZ\n", &LayoutFile);
Status = GetSystemDirectory(FullPathBuffer, sizeof(FullPathBuffer));
if(Status == 0 || Status > sizeof(FullPathBuffer))
{
DPRINT1("GetSystemDirectory() failed! (%d)\n", GetLastError());
RtlFreeUnicodeString(&LayoutFile);
return NULL;
}
RtlInitUnicodeString(&FullLayoutPath, FullPathBuffer);
FullLayoutPath.MaximumLength = sizeof(FullPathBuffer);
if(FullLayoutPath.Length < FullLayoutPath.MaximumLength-1)
{
FullLayoutPath.Buffer[FullLayoutPath.Length/sizeof(WCHAR)] = '\\';
FullLayoutPath.Buffer[FullLayoutPath.Length/sizeof(WCHAR)+1] = 0;
FullLayoutPath.Length+=sizeof(WCHAR);
}
Status = RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile);
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
RtlFreeUnicodeString(&LayoutFile);
if(!NT_SUCCESS(Status))
{
DPRINT1("RtlAppendUnicodeStringToString() failed! (%x)\n", Status);
return NULL;
}
KBModule = LoadLibraryEx(FullPathBuffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if(!KBModule )
{
DPRINT1( "Failed to load %wZ, lasterror = %d\n", &FullLayoutPath, GetLastError() );
return NULL;
}
pAddr = GetProcAddress( KBModule, (LPCSTR) 1);
offTable = (DWORD) pAddr - (DWORD) KBModule; // Weeks to figure this out!
DPRINT( "Load Keyboard Module Offset: %x\n", offTable );
FreeLibrary(KBModule);
Handle = CreateFileW( FullPathBuffer,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
hKL = NtUserLoadKeyboardLayoutEx( Handle,
offTable,
(HKL) layout,
&DefaultLocale,
(UINT) layout,
Flags);
NtClose(Handle);
return hKL;
}
/* FUNCTIONS *****************************************************************/
@ -101,6 +313,18 @@ DragDetect(
}
/*
* @unimplemented
*/
HKL STDCALL
ActivateKeyboardLayout(HKL hkl,
UINT Flags)
{
UNIMPLEMENTED;
return (HKL)0;
}
/*
* @implemented
*/
@ -236,6 +460,18 @@ GetKeyState(int nVirtKey)
}
/*
* @unimplemented
*/
UINT STDCALL
GetKeyboardLayoutList(int nBuff,
HKL FAR *lpList)
{
UNIMPLEMENTED;
return 0;
}
/*
* @implemented
*/
@ -298,9 +534,15 @@ HKL STDCALL
LoadKeyboardLayoutA(LPCSTR pwszKLID,
UINT Flags)
{
return NtUserLoadKeyboardLayoutEx(
strtoul(pwszKLID, NULL, 16),
Flags);
HKL ret;
UNICODE_STRING pwszKLIDW;
if (pwszKLID) RtlCreateUnicodeStringFromAsciiz(&pwszKLIDW, pwszKLID);
else pwszKLIDW.Buffer = NULL;
ret = LoadKeyboardLayoutW(pwszKLIDW.Buffer, Flags);
RtlFreeUnicodeString(&pwszKLIDW);
return ret;
}
@ -311,11 +553,7 @@ HKL STDCALL
LoadKeyboardLayoutW(LPCWSTR pwszKLID,
UINT Flags)
{
// Look at revision 25596 to see how it's done in windows.
// We will do things our own way.
return NtUserLoadKeyboardLayoutEx(
wcstoul(pwszKLID, NULL, 16),
Flags);
return IntLoadKeyboardLayout( pwszKLID, Flags);
}

View file

@ -34,7 +34,9 @@
#include <ndk/ntndk.h>
#include <reactos/helper.h>
#define NDEBUG
//#define NDEBUG
#undef NDEBUG
#define DEBUG
#include <debug.h>
#define TAG_VIDEO_PORT TAG('V', 'I', 'D', 'P')

View file

@ -299,11 +299,11 @@ NTAPI
NtUserAcquireOrReleaseInputOwnership(
BOOLEAN Release);
HKL
DWORD
NTAPI
NtUserActivateKeyboardLayout(
HKL hKl,
ULONG Flags);
DWORD Unknown0,
DWORD Unknown1);
DWORD
NTAPI
@ -1008,11 +1008,11 @@ NTAPI
NtUserGetKeyboardLayout(
DWORD dwThreadid);
UINT
DWORD
NTAPI
NtUserGetKeyboardLayoutList(
INT nItems,
HKL *pHklBuff);
DWORD Unknown0,
DWORD Unknown1);
BOOL
NTAPI
@ -1219,7 +1219,11 @@ NtUserKillTimer
HKL
NTAPI
NtUserLoadKeyboardLayoutEx(
LCID LocaleId,
HANDLE Handle,
DWORD offTable,
HKL hKL,
PUNICODE_STRING puszKLID,
UINT KLayoutLangID,
UINT Flags);
BOOL

View file

@ -3,16 +3,19 @@
#include <internal/kbd.h>
typedef struct _KBDRVFILE
{
PSINGLE_LIST_ENTRY pkbdfChain;
WCHAR wcKBDF[9]; // used w GetKeyboardLayoutName same as wszKLID.
struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h
} KBDRVFILE, *PKBDRVFILE;
typedef struct _KBL
{
LIST_ENTRY List;
DWORD Flags;
WCHAR Name[9]; // used w GetKeyboardLayoutName same as wszKLID.
struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h
HANDLE hModule;
ULONG RefCount;
PLIST_ENTRY pklChain;
DWORD dwKBLFlags;
HKL hkl;
LCID lcid;
PKBDRVFILE pkbdf;
} KBL, *PKBL;
#define KBL_UNLOADED 0x20000000
@ -24,14 +27,12 @@ NTSTATUS FASTCALL
InitKeyboardImpl(VOID);
PUSER_MESSAGE_QUEUE W32kGetPrimitiveMessageQueue(VOID);
VOID W32kUnregisterPrimitiveMessageQueue(VOID);
PKBL W32kGetDefaultKeyLayout(VOID);
PKBDTABLES W32kGetDefaultKeyLayout(VOID);
VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyLayout, BYTE Prefix);
BOOL FASTCALL IntBlockInput(PW32THREAD W32Thread, BOOL BlockIt);
BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi);
BOOL FASTCALL IntKeyboardInput(KEYBDINPUT *ki);
BOOL UserInitDefaultKeyboardLayout();
#define ThreadHasInputAccess(W32Thread) \
(TRUE)

View file

@ -8,7 +8,7 @@ typedef struct _W32THREAD
struct _USER_MESSAGE_QUEUE* MessageQueue;
LIST_ENTRY WindowListHead;
LIST_ENTRY W32CallbackListHead;
struct _KBL* KeyboardLayout;
struct _KBDTABLES* KeyboardLayout;
struct _DESKTOP_OBJECT* Desktop;
HANDLE hDesktop;
DWORD MessagePumpHookValue;
@ -36,7 +36,7 @@ typedef struct _W32PROCESS
LIST_ENTRY PrivateFontListHead;
FAST_MUTEX DriverObjListLock;
LIST_ENTRY DriverObjListHead;
struct _KBL* KeyboardLayout;
struct _KBDTABLES* KeyboardLayout;
ULONG Flags;
LONG GDIObjects;
LONG UserObjects;

View file

@ -529,8 +529,8 @@ KeyboardThreadMain(PVOID StartContext)
KernelMode,
TRUE,
NULL);
DPRINT( "Keyboard Input Thread Starting...\n" );
/*
* Receive and process keyboard input.
*/
@ -754,7 +754,7 @@ KeyboardThreadMain(PVOID StartContext)
* keyboard layout in use.
*/
W32kKeyProcessMessage(&msg,
((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout->KBTables,
((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout,
KeyInput.Flags & KEY_E0 ? 0xE0 :
(KeyInput.Flags & KEY_E1 ? 0xE1 : 0));
@ -816,10 +816,8 @@ InitInputImpl(VOID)
}
/* Initialize the default keyboard layout */
if(!UserInitDefaultKeyboardLayout())
{
DPRINT1("Failed to initialize default keyboard layout!\n");
}
(VOID)W32kGetDefaultKeyLayout();
Status = PsCreateSystemThread(&MouseThreadHandle,
THREAD_ALL_ACCESS,

View file

@ -1,468 +0,0 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: subsystems/win32/win32k/ntuser/kbdlayout.c
* PURPOSE: Keyboard layout management
* COPYRIGHT: Copyright 2007 Saveliy Tretiakov
*
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
PKBL KBLList = NULL; // Keyboard layout list.
PKBL DefaultKL = NULL;
typedef PVOID (*KbdLayerDescriptor)(VOID);
NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
PANSI_STRING import_name,
DWORD flags,
PVOID *func_addr);
/* PRIVATE FUNCTIONS ******************************************************/
/*
* 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;
PWCHAR ReturnBuffer;
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;
}
/* At this point, KeyValuePartialInfo->Data contains the key data */
ReturnBuffer = ExAllocatePoolWithTag(PagedPool,
KeyValuePartialInfo->DataLength,
TAG_STRING);
if(!ReturnBuffer)
{
NtClose(KeyHandle);
ExFreePool(KeyValuePartialInfo);
return STATUS_NO_MEMORY;
}
RtlCopyMemory(ReturnBuffer,
KeyValuePartialInfo->Data,
KeyValuePartialInfo->DataLength);
RtlInitUnicodeString(ReturnedValue, ReturnBuffer);
ExFreePool(KeyValuePartialInfo);
NtClose(KeyHandle);
return Status;
}
static BOOL UserLoadKbdDll(WCHAR *wsKLID,
HANDLE *phModule,
PKBDTABLES *pKbdTables)
{
NTSTATUS Status;
KbdLayerDescriptor layerDescGetFn;
ANSI_STRING kbdProcedureName;
UNICODE_STRING LayoutKeyName;
UNICODE_STRING LayoutValueName;
UNICODE_STRING LayoutFile;
UNICODE_STRING FullLayoutPath;
UNICODE_STRING klid;
WCHAR LayoutPathBuffer[MAX_PATH] = L"\\SystemRoot\\System32\\";
WCHAR KeyNameBuffer[MAX_PATH] = L"\\REGISTRY\\Machine\\SYSTEM\\"
L"CurrentControlSet\\Control\\KeyboardLayouts\\";
RtlInitUnicodeString(&klid, wsKLID);
RtlInitUnicodeString(&LayoutValueName,L"Layout File");
RtlInitUnicodeString(&LayoutKeyName, KeyNameBuffer);
LayoutKeyName.MaximumLength = sizeof(KeyNameBuffer);
RtlAppendUnicodeStringToString(&LayoutKeyName, &klid);
Status = ReadRegistryValue(&LayoutKeyName, &LayoutValueName, &LayoutFile);
if(!NT_SUCCESS(Status))
{
DPRINT1("Can't get layout filename for %wZ. (%08lx)\n", klid, Status);
return FALSE;
}
DPRINT("Read registry and got %wZ\n", &LayoutFile);
RtlInitUnicodeString(&FullLayoutPath, LayoutPathBuffer);
FullLayoutPath.MaximumLength = sizeof(LayoutPathBuffer);
RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile);
DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
RtlFreeUnicodeString(&LayoutFile);
*phModule = EngLoadImage(FullLayoutPath.Buffer);
if(*phModule)
{
DPRINT("Loaded %wZ\n", &FullLayoutPath);
RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
LdrGetProcedureAddress((PVOID)*phModule,
&kbdProcedureName,
0,
(PVOID*)&layerDescGetFn);
if(layerDescGetFn)
{
*pKbdTables = layerDescGetFn();
}
else
{
DPRINT1("Error: %wZ has no KbdLayerDescriptor()\n", &FullLayoutPath);
}
if(!layerDescGetFn || !*pKbdTables)
{
DPRINT1("Failed to load the keyboard layout.\n");
EngUnloadImage(*phModule);
return FALSE;
}
}
else
{
DPRINT1("Failed to load dll %wZ\n", &FullLayoutPath);
return FALSE;
}
return TRUE;
}
static PKBL UserLoadDllAndCreateKbl(LCID LocaleId)
{
PKBL NewKbl;
ULONG hKl;
LANGID langid;
NewKbl = ExAllocatePool(PagedPool, sizeof(NewKbl));
if(!NewKbl)
{
DPRINT1("%s: Can't allocate memory!\n", __FUNCTION__);
return NULL;
}
swprintf(NewKbl->Name, L"%08lx", LocaleId);
if(!UserLoadKbdDll(NewKbl->Name, &NewKbl->hModule, &NewKbl->KBTables))
{
DPRINT1("%s: failed to load %x dll!\n", __FUNCTION__, LocaleId);
ExFreePool(NewKbl);
return NULL;
}
/* Microsoft Office expects this value to be something specific
* for Japanese and Korean Windows with an IME the value is 0xe001
* We should probably check to see if an IME exists and if so then
* set this word properly.
*/
langid = PRIMARYLANGID(LANGIDFROMLCID(LocaleId));
hKl = LocaleId;
if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
hKl |= 0xe001 << 16; /* FIXME */
else hKl |= hKl << 16;
NewKbl->hkl = (HKL) hKl;
NewKbl->lcid = LocaleId;
NewKbl->Flags = 0;
NewKbl->RefCount = 0;
return NewKbl;
}
BOOL UserInitDefaultKeyboardLayout()
{
LCID LocaleId;
NTSTATUS Status;
Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not get default locale (%08lx).\n", Status);
}
else
{
DPRINT("DefaultLocale = %08lx\n", LocaleId);
}
if(!NT_SUCCESS(Status) || !(DefaultKL = UserLoadDllAndCreateKbl(LocaleId)))
{
DPRINT1("Trying to load US Keyboard Layout.\n");
LocaleId = 0x409;
if(!(DefaultKL = UserLoadDllAndCreateKbl(LocaleId)))
{
DPRINT1("Failed to load any Keyboard Layout\n");
return FALSE;
}
}
InitializeListHead(&DefaultKL->List);
KBLList = DefaultKL;
return TRUE;
}
PKBL W32kGetDefaultKeyLayout(VOID)
{
return DefaultKL;
}
static PKBL UserHklToKbl(HKL hKl)
{
PKBL pKbl = KBLList;
do
{
if(pKbl->hkl == hKl) return pKbl;
pKbl = (PKBL) pKbl->List.Flink;
} while(pKbl != KBLList);
return NULL;
}
static PKBL UserActivateKbl(PW32THREAD Thread, PKBL pKbl)
{
PKBL Prev;
Prev = Thread->KeyboardLayout;
Prev->RefCount--;
Thread->KeyboardLayout = pKbl;
pKbl->RefCount++;
return Prev;
}
HKL FASTCALL
UserGetKeyboardLayout(
DWORD dwThreadId)
{
NTSTATUS Status;
PETHREAD Thread;
PW32THREAD W32Thread;
HKL Ret;
if(!dwThreadId)
{
W32Thread = PsGetCurrentThreadWin32Thread();
return W32Thread->KeyboardLayout->hkl;
}
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
W32Thread = PsGetThreadWin32Thread(Thread);
Ret = W32Thread->KeyboardLayout->hkl;
ObDereferenceObject(Thread);
return Ret;
}
/* EXPORTS *******************************************************************/
UINT
STDCALL
NtUserGetKeyboardLayoutList(
INT nItems,
HKL* pHklBuff)
{
UINT Ret = 0;
PKBL pKbl;
UserEnterShared();
pKbl = KBLList;
if(nItems == 0)
{
do
{
Ret++;
pKbl = (PKBL) pKbl->List.Flink;
} while(pKbl != KBLList);
}
else
{
_SEH_TRY
{
ProbeForWrite(pHklBuff, nItems*sizeof(HKL), 4);
while(Ret < nItems)
{
pHklBuff[Ret] = pKbl->hkl;
Ret++;
pKbl = (PKBL) pKbl->List.Flink;
if(pKbl == KBLList) break;
}
}
_SEH_HANDLE
{
SetLastNtError(_SEH_GetExceptionCode());
Ret = 0;
}
_SEH_END;
}
UserLeave();
return Ret;
}
BOOL
STDCALL
NtUserGetKeyboardLayoutName(
LPWSTR lpszName)
{
BOOL ret = FALSE;
PKBL pKbl;
UserEnterShared();
_SEH_TRY
{
ProbeForWrite(lpszName, 9*sizeof(WCHAR), 1);
pKbl = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
RtlCopyMemory(lpszName, pKbl->Name, 9*sizeof(WCHAR));
ret = TRUE;
}
_SEH_HANDLE
{
SetLastNtError(_SEH_GetExceptionCode());
ret = FALSE;
}
_SEH_END;
UserLeave();
return ret;
}
HKL
STDCALL
NtUserLoadKeyboardLayoutEx(
IN LCID LocaleId,
IN UINT Flags)
{
HKL Ret = NULL;
PKBL pKbl;
UserEnterExclusive();
pKbl = KBLList;
do
{
if(pKbl->lcid == LocaleId)
{
Ret = pKbl->hkl;
goto the_end;
}
pKbl = (PKBL) pKbl->List.Flink;
} while(pKbl != KBLList);
pKbl = UserLoadDllAndCreateKbl(LocaleId);
InsertTailList(&KBLList->List, &pKbl->List);
Ret = pKbl->hkl;
//FIXME: Respect Flags!
the_end:
UserLeave();
return Ret;
}
HKL
STDCALL
NtUserActivateKeyboardLayout(
HKL hKl,
ULONG Flags)
{
PKBL pKbl;
HKL Ret = NULL;
UserEnterExclusive();
pKbl = UserHklToKbl(hKl);
if(pKbl)
{
pKbl = UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl);
Ret = pKbl->hkl;
//FIXME: Respect flags!
}
UserLeave();
return Ret;
}
/* EOF */

View file

@ -33,7 +33,8 @@
#define NDEBUG
#include <debug.h>
/* Directory to load key layouts from */
#define SYSTEMROOT_DIR L"\\SystemRoot\\System32\\"
/* Lock modifiers */
#define CAPITAL_BIT 0x80000000
#define NUMLOCK_BIT 0x40000000
@ -52,6 +53,8 @@
BYTE gQueueKeyStateTable[256];
PKBDRVFILE KBLList = NULL; // Keyboard layout list.
/* FUNCTIONS *****************************************************************/
@ -431,7 +434,7 @@ int STDCALL ToUnicodeEx( UINT wVirtKey,
cchBuff,
wFlags,
PsGetCurrentThreadWin32Thread() ?
PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0 );
PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0 );
}
return ToUnicodeResult;
@ -453,6 +456,255 @@ int STDCALL ToUnicode( UINT wVirtKey,
0 );
}
/*
* Utility to copy and append two unicode strings.
*
* IN OUT PUNICODE_STRING ResultFirst -> First string and result
* IN PUNICODE_STRING Second -> Second string to append
* IN BOOL Deallocate -> TRUE: Deallocate First string before
* overwriting.
*
* Returns NTSTATUS.
*/
NTSTATUS NTAPI AppendUnicodeString(PUNICODE_STRING ResultFirst,
PUNICODE_STRING Second,
BOOL Deallocate)
{
NTSTATUS Status;
PWSTR new_string =
ExAllocatePoolWithTag(PagedPool,
(ResultFirst->Length + Second->Length + sizeof(WCHAR)),
TAG_STRING);
if( !new_string )
{
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,
@ -467,7 +719,7 @@ IntTranslateKbdMessage(LPMSG lpMsg,
DWORD ScanCode = 0;
keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables;
keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
if( !keyLayout )
return FALSE;
@ -708,7 +960,7 @@ NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl )
DPRINT("Enter NtUserMapVirtualKeyEx\n");
UserEnterExclusive();
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
if( !keyLayout )
RETURN(0);
@ -801,7 +1053,7 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
UserEnterShared();
keyLayout = PsGetCurrentThreadWin32Thread() ?
PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;
PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
if( !keyLayout || nSize < 1 )
RETURN(0);
@ -898,7 +1150,7 @@ W32kKeyProcessMessage(LPMSG Msg,
{ VK_UP, VK_NUMPAD8 },
{ VK_PRIOR, VK_NUMPAD9 },
{ 0,0 } };
PVSC_VK VscVkTable = NULL;
PVSC_VK VscVkTable = NULL;
if( !KeyboardLayout || !Msg ||
(Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
@ -995,6 +1247,101 @@ W32kKeyProcessMessage(LPMSG Msg,
}
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
@ -1016,6 +1363,22 @@ UserGetKeyboardType(
}
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.

View file

@ -13,6 +13,17 @@
#define NDEBUG
#include <debug.h>
DWORD
STDCALL
NtUserActivateKeyboardLayout(
DWORD Unknown0,
DWORD Unknown1)
{
UNIMPLEMENTED
return 0;
}
DWORD
STDCALL
NtUserAttachThreadInput(
@ -626,7 +637,6 @@ NtUserUnloadKeyboardLayout(
return 0;
}
DWORD
STDCALL
NtUserUpdateInputContext(

View file

@ -120,7 +120,6 @@
<file>hotkey.c</file>
<file>input.c</file>
<file>keyboard.c</file>
<file>kbdlayout.c</file>
<file>menu.c</file>
<file>message.c</file>
<file>metric.c</file>

View file

@ -428,7 +428,7 @@ NtUserInternalGetWindowText 3
NtUserIsClipboardFormatAvailable 1
NtUserKillSystemTimer 2
NtUserKillTimer 2
NtUserLoadKeyboardLayoutEx 2
NtUserLoadKeyboardLayoutEx 6
NtUserLockWindowStation 1
NtUserLockWindowUpdate 1
NtUserLockWorkStation 0