[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / keyboard.c
index dcc915f..70e9054 100644 (file)
@@ -12,9 +12,9 @@
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /*
  * COPYRIGHT:        See COPYING in the top level directory
 
 /* INCLUDES ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 
 #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
@@ -43,7 +42,9 @@
 /* Key States */
 #define KS_DOWN_MASK     0xc0
 #define KS_DOWN_BIT      0x80
-#define KS_LOCK_BIT    0x01
+#define KS_LOCK_BIT      0x01
+/* Scan Codes */
+#define SC_KEY_UP        0x8000
 /* lParam bits */
 #define LP_EXT_BIT       (1<<24)
 /* From kbdxx.c -- Key changes with numlock */
@@ -53,8 +54,6 @@
 BYTE gQueueKeyStateTable[256];
 
 
-PKBDRVFILE KBLList = NULL; // Keyboard layout list.
-
 
 /* FUNCTIONS *****************************************************************/
 
@@ -72,15 +71,15 @@ NTSTATUS FASTCALL InitKeyboardImpl(VOID)
 static UINT DontDistinguishShifts( UINT ret )
 {
    if( ret == VK_LSHIFT || ret == VK_RSHIFT )
-      ret = VK_LSHIFT;
+      ret = VK_SHIFT;
    if( ret == VK_LCONTROL || ret == VK_RCONTROL )
-      ret = VK_LCONTROL;
+      ret = VK_CONTROL;
    if( ret == VK_LMENU || ret == VK_RMENU )
-      ret = VK_LMENU;
+      ret = VK_MENU;
    return ret;
 }
 
-static VOID STDCALL SetKeyState(DWORD key, DWORD vk, DWORD ext, BOOL down)
+static VOID APIENTRY SetKeyState(DWORD key, DWORD vk, DWORD ext, BOOL down)
 {
    ASSERT(vk <= 0xff);
 
@@ -91,12 +90,12 @@ static VOID STDCALL SetKeyState(DWORD key, DWORD vk, DWORD ext, BOOL down)
          gQueueKeyStateTable[vk] ^= KS_LOCK_BIT;
    }
 
-   if (ext && vk == VK_LSHIFT)
-      vk = VK_RSHIFT;
-   if (ext && vk == VK_LCONTROL)
-      vk = VK_RCONTROL;
-   if (ext && vk == VK_LMENU)
-      vk = VK_RMENU;
+   if (vk == VK_SHIFT)
+      vk = ext ? VK_RSHIFT : VK_LSHIFT;
+   if (vk == VK_CONTROL)
+      vk = ext ? VK_RCONTROL : VK_LCONTROL;
+   if (vk == VK_MENU)
+      vk = ext ? VK_RMENU : VK_LMENU;
 
    if (down)
       gQueueKeyStateTable[vk] |= KS_DOWN_BIT;
@@ -199,18 +198,27 @@ static DWORD ModBits( PKBDTABLES pkKT, PBYTE KeyState )
          KS_DOWN_BIT)
       ModBits |= GetShiftBit( pkKT, VK_SHIFT );
 
+   if (KeysSet( pkKT, KeyState, VK_SHIFT, 0 ) &
+         KS_DOWN_BIT)
+      ModBits |= GetShiftBit( pkKT, VK_SHIFT );
+
    if (KeysSet( pkKT, KeyState, VK_LCONTROL, VK_RCONTROL ) &
          KS_DOWN_BIT )
       ModBits |= GetShiftBit( pkKT, VK_CONTROL );
 
+   if (KeysSet( pkKT, KeyState, VK_CONTROL, 0 ) &
+         KS_DOWN_BIT )
+      ModBits |= GetShiftBit( pkKT, VK_CONTROL );
+
    if (KeysSet( pkKT, KeyState, VK_LMENU, VK_RMENU ) &
          KS_DOWN_BIT )
       ModBits |= GetShiftBit( pkKT, VK_MENU );
 
    /* Handle Alt+Gr */
-   if (KeysSet( pkKT, KeyState, VK_RMENU, 0 ) &
-         KS_DOWN_BIT )
-      ModBits |= GetShiftBit( pkKT, VK_CONTROL );
+   if (pkKT->fLocalFlags & 0x1) 
+      if (KeysSet( pkKT, KeyState, VK_RMENU, 0 ) &
+            KS_DOWN_BIT)
+         ModBits |= GetShiftBit( pkKT, VK_CONTROL );
 
    /* Deal with VK_CAPITAL */
    if (KeysSet( pkKT, KeyState, VK_CAPITAL, 0 ) & KS_LOCK_BIT)
@@ -251,6 +259,7 @@ static BOOL TryToTranslateChar(WORD wVirtKey,
    {
       return FALSE;
    }
+
    for (nMod = 0; keyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
    {
       vtwTbl = &keyLayout->pVkToWcharTable[nMod];
@@ -266,13 +275,12 @@ static BOOL TryToTranslateChar(WORD wVirtKey,
 
             if( CapsMod >= keyLayout->pVkToWcharTable[nMod].nModifications )
             {
-               DWORD MaxBit = 1;
-               while( MaxBit <
-                      keyLayout->pVkToWcharTable[nMod].nModifications )
-                  MaxBit <<= 1;
+               return FALSE;
+            }
 
-               CapsMod &= MaxBit - 1; /* Guarantee that CapsMod lies
-                        in bounds. */
+            if( vkPtr->wch[CapsMod] == WCH_NONE )
+            {
+               return FALSE;
             }
 
             *pbDead = vkPtr->wch[CapsMod] == WCH_DEAD;
@@ -289,7 +297,7 @@ static BOOL TryToTranslateChar(WORD wVirtKey,
                if( vkPtr->VirtualKey != 0xff )
                {
                   DPRINT( "Found dead key with no trailer in the table.\n" );
-                  DPRINT( "VK: %04x, ADDR: %08x\n", wVirtKey, (int)vkPtr );
+                  DPRINT( "VK: %04x, ADDR: %p\n", wVirtKey, vkPtr );
                   return FALSE;
                }
                *pwcTranslatedChar = vkPtr->wch[CapsMod];
@@ -303,7 +311,7 @@ static BOOL TryToTranslateChar(WORD wVirtKey,
 }
 
 static
-int STDCALL
+int APIENTRY
 ToUnicodeInner(UINT wVirtKey,
                UINT wScanCode,
                PBYTE lpKeyState,
@@ -356,10 +364,10 @@ DWORD FASTCALL UserGetKeyState(DWORD key)
 }
 
 
-DWORD
-STDCALL
+SHORT
+APIENTRY
 NtUserGetKeyState(
-   DWORD key)
+   INT key)
 {
    DECLARE_RETURN(DWORD);
 
@@ -391,17 +399,17 @@ DWORD FASTCALL UserGetAsyncKeyState(DWORD key)
 
 
 
-DWORD
-STDCALL
+SHORT
+APIENTRY
 NtUserGetAsyncKeyState(
-   DWORD key)
+   INT key)
 {
-   DECLARE_RETURN(DWORD);
+   DECLARE_RETURN(SHORT);
 
    DPRINT("Enter NtUserGetAsyncKeyState\n");
    UserEnterExclusive();
 
-   RETURN(UserGetAsyncKeyState(key));
+   RETURN((SHORT)UserGetAsyncKeyState(key));
 
 CLEANUP:
    DPRINT("Leave NtUserGetAsyncKeyState, ret=%i\n",_ret_);
@@ -411,305 +419,11 @@ CLEANUP:
 
 
 
-int STDCALL ToUnicodeEx( UINT wVirtKey,
-                         UINT wScanCode,
-                         PBYTE lpKeyState,
-                         LPWSTR pwszBuff,
-                         int cchBuff,
-                         UINT wFlags,
-                         HKL dwhkl )
-{
-   int ToUnicodeResult = 0;
-
-   if (0 == (lpKeyState[wVirtKey] & KS_DOWN_BIT))
-   {
-      ToUnicodeResult = 0;
-   }
-   else
-   {
-      ToUnicodeResult = ToUnicodeInner( wVirtKey,
-                                        wScanCode,
-                                        lpKeyState,
-                                        pwszBuff,
-                                        cchBuff,
-                                        wFlags,
-                                        PsGetCurrentThreadWin32Thread() ?
-                                        PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0 );
-   }
-
-   return ToUnicodeResult;
-}
-
-int STDCALL ToUnicode( UINT wVirtKey,
-                       UINT wScanCode,
-                       PBYTE lpKeyState,
-                       LPWSTR pwszBuff,
-                       int cchBuff,
-                       UINT wFlags )
-{
-   return ToUnicodeEx( wVirtKey,
-                       wScanCode,
-                       gQueueKeyStateTable,
-                       pwszBuff,
-                       cchBuff,
-                       wFlags,
-                       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,
-                       HKL dwhkl)
+                       UINT flags)
 {
+   PTHREADINFO pti;
    static INT dead_char = 0;
    LONG UState = 0;
    WCHAR wp[2] = { 0 };
@@ -718,19 +432,31 @@ IntTranslateKbdMessage(LPMSG lpMsg,
    BOOL Result = FALSE;
    DWORD ScanCode = 0;
 
-
-   keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
+   pti = PsGetCurrentThreadWin32Thread();
+   keyLayout = pti->KeyboardLayout->KBTables;
    if( !keyLayout )
       return FALSE;
 
+   if (lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST)
+      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);
+   NewMsg.pt = gpsi->ptCursor;
+
+    switch (lpMsg->wParam)
+    {
+    case VK_PACKET:
+        NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
+        NewMsg.hwnd = lpMsg->hwnd;
+        NewMsg.wParam = HIWORD(lpMsg->lParam);
+        NewMsg.lParam = LOWORD(lpMsg->lParam);
+        MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY);
+        return TRUE;
+    }
+
+   ScanCode = (lpMsg->lParam >> 16) & 0xff;
 
    UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff,
                            gQueueKeyStateTable, wp, 2, 0,
@@ -766,14 +492,14 @@ IntTranslateKbdMessage(LPMSG lpMsg,
          NewMsg.wParam = dead_char;
          NewMsg.lParam = lpMsg->lParam;
          dead_char = 0;
-         MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
+         MsqPostMessage(pti->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);
+      MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY);
       Result = TRUE;
    }
    else if (UState == -1)
@@ -784,7 +510,7 @@ IntTranslateKbdMessage(LPMSG lpMsg,
       NewMsg.wParam = wp[0];
       NewMsg.lParam = lpMsg->lParam;
       dead_char = wp[0];
-      MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
+      MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY);
       Result = TRUE;
    }
 
@@ -792,16 +518,16 @@ IntTranslateKbdMessage(LPMSG lpMsg,
 }
 
 DWORD
-STDCALL
+APIENTRY
 NtUserGetKeyboardState(
    LPBYTE lpKeyState)
 {
    BOOL Result = TRUE;
    DECLARE_RETURN(DWORD);
-   
+
    DPRINT("Enter NtUserGetKeyboardState\n");
    UserEnterShared();
-   
+
    if (lpKeyState)
    {
       if(!NT_SUCCESS(MmCopyToCaller(lpKeyState, gQueueKeyStateTable, 256)))
@@ -809,20 +535,20 @@ NtUserGetKeyboardState(
    }
 
    RETURN(Result);
-   
+
 CLEANUP:
    DPRINT("Leave NtUserGetKeyboardState, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
-DWORD
-STDCALL
+BOOL
+APIENTRY
 NtUserSetKeyboardState(LPBYTE lpKeyState)
 {
    BOOL Result = TRUE;
    DECLARE_RETURN(DWORD);
-   
+
    DPRINT("Enter NtUserSetKeyboardState\n");
    UserEnterExclusive();
 
@@ -831,7 +557,7 @@ NtUserSetKeyboardState(LPBYTE lpKeyState)
       if(! NT_SUCCESS(MmCopyFromCaller(gQueueKeyStateTable, lpKeyState, 256)))
          Result = FALSE;
    }
-   
+
    RETURN(Result);
 
 CLEANUP:
@@ -916,11 +642,11 @@ static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout )
    switch( Type )
    {
       case 0:
-         if( Code == VK_RSHIFT )
+         if( Code == VK_SHIFT )
             Code = VK_LSHIFT;
-         if( Code == VK_RMENU )
+         if( Code == VK_MENU )
             Code = VK_LMENU;
-         if( Code == VK_RCONTROL )
+         if( Code == VK_CONTROL )
             Code = VK_LCONTROL;
          ret = VkToScan( Code, FALSE, keyLayout );
          break;
@@ -951,31 +677,33 @@ static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout )
 }
 
 UINT
-STDCALL
+APIENTRY
 NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl )
 {
+   PTHREADINFO pti;
    PKBDTABLES keyLayout;
    DECLARE_RETURN(UINT);
-   
+
    DPRINT("Enter NtUserMapVirtualKeyEx\n");
    UserEnterExclusive();
-   
-   keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
+
+   pti = PsGetCurrentThreadWin32Thread();
+   keyLayout = pti ? pti->KeyboardLayout->KBTables : 0;
 
    if( !keyLayout )
       RETURN(0);
 
    RETURN(IntMapVirtualKeyEx( Code, Type, keyLayout ));
-   
+
 CLEANUP:
    DPRINT("Leave NtUserMapVirtualKeyEx, ret=%i\n",_ret_);
    UserLeave();
-   END_CLEANUP;   
+   END_CLEANUP;
 }
 
 
 int
-STDCALL
+APIENTRY
 NtUserToUnicodeEx(
    UINT wVirtKey,
    UINT wScanCode,
@@ -985,14 +713,20 @@ NtUserToUnicodeEx(
    UINT wFlags,
    HKL dwhkl )
 {
+   PTHREADINFO pti;
    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...
+   UserEnterShared();//fixme: this syscall doesnt seem to need any locking...
 
+   /* Key up? */
+   if (wScanCode & SC_KEY_UP)
+   {
+      RETURN(0);
+   }
 
    if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
                                     lpKeyState,
@@ -1001,31 +735,37 @@ NtUserToUnicodeEx(
       DPRINT1( "Couldn't copy key state from caller.\n" );
       RETURN(0);
    }
-   OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING);
-   if( !OutPwszBuff )
+   
+   /* Virtual code is correct? */
+   if (wVirtKey < 0x100)
    {
-      DPRINT1( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
-      RETURN(0);
+      OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING);
+      if( !OutPwszBuff )
+      {
+         DPRINT1( "ExAllocatePoolWithTag(%d) failed\n", sizeof(WCHAR) * cchBuff);
+         RETURN(0);
+      }
+      RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );
+
+      pti = PsGetCurrentThreadWin32Thread();
+      ret = ToUnicodeInner( wVirtKey,
+                            wScanCode,
+                            KeyStateBuf,
+                            OutPwszBuff,
+                            cchBuff,
+                            wFlags,
+                            pti ? pti->KeyboardLayout->KBTables : 0 );
+
+      MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff);
+      ExFreePoolWithTag(OutPwszBuff, TAG_STRING);
    }
-   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;   
+   END_CLEANUP;
 }
 
 static int W32kSimpleToupper( int ch )
@@ -1036,9 +776,10 @@ static int W32kSimpleToupper( int ch )
 }
 
 DWORD
-STDCALL
+APIENTRY
 NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
 {
+   PTHREADINFO pti;
    int i;
    DWORD ret = 0;
    UINT CareVk = 0;
@@ -1048,12 +789,12 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
    PKBDTABLES keyLayout;
    VSC_LPWSTR *KeyNames;
    DECLARE_RETURN(DWORD);
-   
+
    DPRINT("Enter NtUserGetKeyNameText\n");
    UserEnterShared();
-   
-   keyLayout = PsGetCurrentThreadWin32Thread() ?
-      PsGetCurrentThreadWin32Thread()->KeyboardLayout : 0;
+
+   pti = PsGetCurrentThreadWin32Thread();
+   keyLayout = pti ? pti->KeyboardLayout->KBTables : 0;
 
    if( !keyLayout || nSize < 1 )
       RETURN(0);
@@ -1061,12 +802,22 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
    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;
+      switch (VkCode)
+      {
+          case VK_RSHIFT:
+              ScanCode |= 0x100;
+          case VK_LSHIFT:
+             VkCode = VK_SHIFT;
+             break;
+          case VK_LCONTROL:
+          case VK_RCONTROL:
+             VkCode = VK_CONTROL;
+             break;
+          case VK_LMENU:
+          case VK_RMENU:
+             VkCode = VK_MENU;
+             break;
+      }
    }
    else
    {
@@ -1116,7 +867,7 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
    }
 
    RETURN(ret);
-   
+
 CLEANUP:
    DPRINT("Leave NtUserGetKeyNameText, ret=%i\n",_ret_);
    UserLeave();
@@ -1247,101 +998,6 @@ 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
@@ -1363,45 +1019,39 @@ 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.
  */
 DWORD
-STDCALL
+APIENTRY
 NtUserVkKeyScanEx(
-   DWORD wChar,
-   DWORD KeyboardLayout,
-   DWORD Unknown2)
+   WCHAR wChar,
+   HKL hKeyboardLayout,
+   BOOL UsehKL ) // TRUE from KeyboardLayout, FALSE from pkbl = (THREADINFO)->KeyboardLayout
 {
-/* 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;
+   PKBL pkbl = NULL;
+   DWORD CapsMod = 0, CapsState = 0, Ret = -1;
 
-   if(!KeyboardLayout)
-      return -1;
-   KeyLayout = (PKBDTABLES) KeyboardLayout;
+   DPRINT("NtUserVkKeyScanEx() wChar %d, KbdLayout 0x%p\n", wChar, hKeyboardLayout);
+   UserEnterShared();
+
+   if (UsehKL)
+   {
+      if ( !hKeyboardLayout || !(pkbl = UserHklToKbl(hKeyboardLayout)))
+      goto Exit;
+   }
+   else // From VkKeyScanAW it is FALSE so KeyboardLayout is white noise.
+   {
+     pkbl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
+   }   
+
+   KeyLayout = pkbl->KBTables;
 
    for (nMod = 0; KeyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
    {
@@ -1424,13 +1074,16 @@ NtUserVkKeyScanEx(
                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));
+               Ret = ((CapsMod << 8)|(vkPtr->VirtualKey & 0xff));
+               goto Exit;
             }
          }
          vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + size_this_entry);
       }
    }
-   return -1;
+Exit:
+   UserLeave();
+   return Ret;
 }