- Add back and fix useful dprint.
[reactos.git] / reactos / subsys / win32k / ntuser / keyboard.c
index 218ef1b..99653e3 100644 (file)
@@ -16,8 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: keyboard.c,v 1.14 2003/11/07 19:58:43 arty Exp $
- *
+/*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Messages
 
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <win32k/win32k.h>
-#include <internal/safe.h>
-#include <internal/kbd.h>
-#include <include/guicheck.h>
-#include <include/msgqueue.h>
-#include <include/window.h>
-#include <include/class.h>
-#include <include/error.h>
-#include <include/object.h>
-#include <include/winsta.h>
+#include <w32k.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
+#define MOD_BITS_MASK 0x3fffffff
+#define MOD_KCTRL     0x02
+/* Key States */
+#define KS_DOWN_MASK     0xc0
+#define KS_DOWN_BIT      0x80
+#define KS_LOCK_BIT    0x01
+/* lParam bits */
+#define LP_EXT_BIT       (1<<24)
+/* From kbdxx.c -- Key changes with numlock */
+#define KNUMP         0x400
+
+/* Lock the keyboard state to prevent unusual concurrent access */
+FAST_MUTEX QueueStateLock;
 
 BYTE QueueKeyStateTable[256];
 
-/* arty -- These should be phased out for the general kbdxx.dll tables */
-
-struct accent_char
-{
-    BYTE ac_accent;
-    BYTE ac_char;
-    BYTE ac_result;
-};
+#define IntLockQueueState \
+  ExAcquireFastMutex(&QueueStateLock)
 
-static const struct accent_char accent_chars[] =
-{
-/* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */
-    {'`', 'A', '\300'},  {'`', 'a', '\340'},
-    {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
-    {'^', 'A', '\302'},  {'^', 'a', '\342'},
-    {'~', 'A', '\303'},  {'~', 'a', '\343'},
-    {'"', 'A', '\304'},  {'"', 'a', '\344'},
-    {'O', 'A', '\305'},  {'o', 'a', '\345'},
-    {'0', 'A', '\305'},  {'0', 'a', '\345'},
-    {'A', 'A', '\305'},  {'a', 'a', '\345'},
-    {'A', 'E', '\306'},  {'a', 'e', '\346'},
-    {',', 'C', '\307'},  {',', 'c', '\347'},
-    {'`', 'E', '\310'},  {'`', 'e', '\350'},
-    {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
-    {'^', 'E', '\312'},  {'^', 'e', '\352'},
-    {'"', 'E', '\313'},  {'"', 'e', '\353'},
-    {'`', 'I', '\314'},  {'`', 'i', '\354'},
-    {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
-    {'^', 'I', '\316'},  {'^', 'i', '\356'},
-    {'"', 'I', '\317'},  {'"', 'i', '\357'},
-    {'-', 'D', '\320'},  {'-', 'd', '\360'},
-    {'~', 'N', '\321'},  {'~', 'n', '\361'},
-    {'`', 'O', '\322'},  {'`', 'o', '\362'},
-    {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
-    {'^', 'O', '\324'},  {'^', 'o', '\364'},
-    {'~', 'O', '\325'},  {'~', 'o', '\365'},
-    {'"', 'O', '\326'},  {'"', 'o', '\366'},
-    {'/', 'O', '\330'},  {'/', 'o', '\370'},
-    {'`', 'U', '\331'},  {'`', 'u', '\371'},
-    {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
-    {'^', 'U', '\333'},  {'^', 'u', '\373'},
-    {'"', 'U', '\334'},  {'"', 'u', '\374'},
-    {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
-    {'T', 'H', '\336'},  {'t', 'h', '\376'},
-    {'s', 's', '\337'},  {'"', 'y', '\377'},
-    {'s', 'z', '\337'},  {'i', 'j', '\377'},
-       /* iso-8859-2 uses this */
-    {'<', 'L', '\245'},  {'<', 'l', '\265'},   /* caron */
-    {'<', 'S', '\251'},  {'<', 's', '\271'},
-    {'<', 'T', '\253'},  {'<', 't', '\273'},
-    {'<', 'Z', '\256'},  {'<', 'z', '\276'},
-    {'<', 'C', '\310'},  {'<', 'c', '\350'},
-    {'<', 'E', '\314'},  {'<', 'e', '\354'},
-    {'<', 'D', '\317'},  {'<', 'd', '\357'},
-    {'<', 'N', '\322'},  {'<', 'n', '\362'},
-    {'<', 'R', '\330'},  {'<', 'r', '\370'},
-    {';', 'A', '\241'},  {';', 'a', '\261'},   /* ogonek */
-    {';', 'E', '\312'},  {';', 'e', '\332'},
-    {'\'', 'Z', '\254'}, {'\'', 'z', '\274'},  /* acute */
-    {'\'', 'R', '\300'}, {'\'', 'r', '\340'},
-    {'\'', 'L', '\305'}, {'\'', 'l', '\345'},
-    {'\'', 'C', '\306'}, {'\'', 'c', '\346'},
-    {'\'', 'N', '\321'}, {'\'', 'n', '\361'},
-/*  collision whith S, from iso-8859-9 !!! */
-    {',', 'S', '\252'},  {',', 's', '\272'},   /* cedilla */
-    {',', 'T', '\336'},  {',', 't', '\376'},
-    {'.', 'Z', '\257'},  {'.', 'z', '\277'},   /* dot above */
-    {'/', 'L', '\243'},  {'/', 'l', '\263'},   /* slash */
-    {'/', 'D', '\320'},  {'/', 'd', '\360'},
-    {'(', 'A', '\303'},  {'(', 'a', '\343'},   /* breve */
-    {'\275', 'O', '\325'}, {'\275', 'o', '\365'},      /* double acute */
-    {'\275', 'U', '\334'}, {'\275', 'u', '\374'},
-    {'0', 'U', '\332'},  {'0', 'u', '\372'},   /* ring above */
-       /* iso-8859-3 uses this */
-    {'/', 'H', '\241'},  {'/', 'h', '\261'},   /* slash */
-    {'>', 'H', '\246'},  {'>', 'h', '\266'},   /* circumflex */
-    {'>', 'J', '\254'},  {'>', 'j', '\274'},
-    {'>', 'C', '\306'},  {'>', 'c', '\346'},
-    {'>', 'G', '\330'},  {'>', 'g', '\370'},
-    {'>', 'S', '\336'},  {'>', 's', '\376'},
-/*  collision whith G( from iso-8859-9 !!!   */
-    {'(', 'G', '\253'},  {'(', 'g', '\273'},   /* breve */
-    {'(', 'U', '\335'},  {'(', 'u', '\375'},
-/*  collision whith I. from iso-8859-3 !!!   */
-    {'.', 'I', '\251'},  {'.', 'i', '\271'},   /* dot above */
-    {'.', 'C', '\305'},  {'.', 'c', '\345'},
-    {'.', 'G', '\325'},  {'.', 'g', '\365'},
-       /* iso-8859-4 uses this */
-    {',', 'R', '\243'},  {',', 'r', '\263'},   /* cedilla */
-    {',', 'L', '\246'},  {',', 'l', '\266'},
-    {',', 'G', '\253'},  {',', 'g', '\273'},
-    {',', 'N', '\321'},  {',', 'n', '\361'},
-    {',', 'K', '\323'},  {',', 'k', '\363'},
-    {'~', 'I', '\245'},  {'~', 'i', '\265'},   /* tilde */
-    {'-', 'E', '\252'},  {'-', 'e', '\272'},   /* macron */
-    {'-', 'A', '\300'},  {'-', 'a', '\340'},
-    {'-', 'I', '\317'},  {'-', 'i', '\357'},
-    {'-', 'O', '\322'},  {'-', 'o', '\362'},
-    {'-', 'U', '\336'},  {'-', 'u', '\376'},
-    {'/', 'T', '\254'},  {'/', 't', '\274'},   /* slash */
-    {'.', 'E', '\314'},  {'.', 'e', '\344'},   /* dot above */
-    {';', 'I', '\307'},  {';', 'i', '\347'},   /* ogonek */
-    {';', 'U', '\331'},  {';', 'u', '\371'},
-       /* iso-8859-9 uses this */
-       /* iso-8859-9 has really bad choosen G( S, and I. as they collide
-        * whith the same letters on other iso-8859-x (that is they are on
-        * different places :-( ), if you use turkish uncomment these and
-        * comment out the lines in iso-8859-2 and iso-8859-3 sections
-        * FIXME: should be dynamic according to chosen language
-        *        if/when Wine has turkish support.  
-        */ 
-/*  collision whith G( from iso-8859-3 !!!   */
-/*  {'(', 'G', '\320'},  {'(', 'g', '\360'}, */        /* breve */
-/*  collision whith S, from iso-8859-2 !!! */
-/*  {',', 'S', '\336'},  {',', 's', '\376'}, */        /* cedilla */
-/*  collision whith I. from iso-8859-3 !!!   */
-/*  {'.', 'I', '\335'},  {'.', 'i', '\375'}, */        /* dot above */
-};
+#define IntUnLockQueueState \
+  ExReleaseFastMutex(&QueueStateLock)
 
 /* FUNCTIONS *****************************************************************/
 
+/* Initialization -- Right now, just zero the key state and init the lock */
+NTSTATUS FASTCALL InitKeyboardImpl(VOID) {
+  ExInitializeFastMutex(&QueueStateLock);
+  RtlZeroMemory(&QueueKeyStateTable,0x100);
+  return STATUS_SUCCESS;
+}
+
 /*** Statics used by TranslateMessage ***/
 
+/*** Shift state code was out of hand, sorry. --- arty */
+
 static UINT DontDistinguishShifts( UINT ret ) {
-    if( ret == VK_LSHIFT || ret == VK_RSHIFT ) ret = VK_SHIFT;
-    if( ret == VK_LCONTROL || ret == VK_RCONTROL ) ret = VK_CONTROL;
-    if( ret == VK_LMENU || ret == VK_RMENU ) ret = VK_MENU;
+    if( ret == VK_LSHIFT || ret == VK_RSHIFT ) ret = VK_LSHIFT;
+    if( ret == VK_LCONTROL || ret == VK_RCONTROL ) ret = VK_LCONTROL;
+    if( ret == VK_LMENU || ret == VK_RMENU ) ret = VK_LMENU;
     return ret;
 }
 
-static VOID STDCALL SetKeyState(DWORD key, BOOL down) {
-  QueueKeyStateTable[key] = down ? 0x80 : 0;
+static VOID STDCALL SetKeyState(DWORD key, DWORD vk, DWORD ext, BOOL down) {
+  ASSERT(vk <= 0xff);
+
+  /* Special handling for toggles like numpad and caps lock */
+  if (vk == VK_CAPITAL || vk == VK_NUMLOCK) {
+    if (down) QueueKeyStateTable[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 (down)
+    QueueKeyStateTable[vk] |= KS_DOWN_BIT;
+  else
+    QueueKeyStateTable[vk] &= ~KS_DOWN_MASK;
+
+  if (vk == VK_LSHIFT || vk == VK_RSHIFT) {
+    if ((QueueKeyStateTable[VK_LSHIFT] & KS_DOWN_BIT) ||
+        (QueueKeyStateTable[VK_RSHIFT] & KS_DOWN_BIT)) {
+      QueueKeyStateTable[VK_SHIFT] |= KS_DOWN_BIT;
+    } else {
+      QueueKeyStateTable[VK_SHIFT] &= ~KS_DOWN_MASK;
+    }
+  }
+
+  if (vk == VK_LCONTROL || vk == VK_RCONTROL) {
+    if ((QueueKeyStateTable[VK_LCONTROL] & KS_DOWN_BIT) ||
+        (QueueKeyStateTable[VK_RCONTROL] & KS_DOWN_BIT)) {
+      QueueKeyStateTable[VK_CONTROL] |= KS_DOWN_BIT;
+    } else {
+      QueueKeyStateTable[VK_CONTROL] &= ~KS_DOWN_MASK;
+    }
+  }
+
+  if (vk == VK_LMENU || vk == VK_RMENU) {
+    if ((QueueKeyStateTable[VK_LMENU] & KS_DOWN_BIT) ||
+        (QueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT)) {
+      QueueKeyStateTable[VK_MENU] |= KS_DOWN_BIT;
+    } else {
+      QueueKeyStateTable[VK_MENU] &= ~KS_DOWN_MASK;
+    }
+  }
 }
 
 VOID DumpKeyState( PBYTE KeyState ) {
@@ -192,61 +138,68 @@ VOID DumpKeyState( PBYTE KeyState ) {
   DbgPrint( "};\n" );
 }
 
-static BYTE KeysSet( PKBDTABLES pkKT, PBYTE KeyState, 
-                    int Mod, int FakeModLeft, int FakeModRight ) {
-  int i;
-
+static BYTE KeysSet( PKBDTABLES pkKT, PBYTE KeyState,
+                    int FakeModLeft, int FakeModRight ) {
   if( !KeyState || !pkKT ) return 0;
 
-  for( i = 0; i < pkKT->bMaxVSCtoVK; i++ ) {
-    if( KeyState[i] & 0xC0 &&
-       ((pkKT->pusVSCtoVK[i] & 0xff) == Mod ||
-        (pkKT->pusVSCtoVK[i] & 0xff) == FakeModLeft ||
-        (pkKT->pusVSCtoVK[i] & 0xff) == FakeModRight ) ) {
-      return KeyState[i];
-    }
-  }
+  /* Search special codes first */
+  if( FakeModLeft && KeyState[FakeModLeft] )
+      return KeyState[FakeModLeft];
+  else if( FakeModRight && KeyState[FakeModRight] )
+      return KeyState[FakeModRight];
 
   return 0;
 }
 
-static DWORD ModBits( PKBDTABLES pkKT, PBYTE KeyState ) {
+/* Search the keyboard layout modifiers table for the shift bit.  I don't
+ * want to count on the shift bit not moving, because it can be specified
+ * in the layout */
+
+static DWORD FASTCALL GetShiftBit( PKBDTABLES pkKT, DWORD Vk ) {
   int i;
+
+  for( i = 0; pkKT->pCharModifiers->pVkToBit[i].Vk; i++ )
+    if( pkKT->pCharModifiers->pVkToBit[i].Vk == Vk )
+      return pkKT->pCharModifiers->pVkToBit[i].ModBits;
+
+  return 0;
+}
+
+static DWORD ModBits( PKBDTABLES pkKT, PBYTE KeyState ) {
   DWORD ModBits = 0;
-  BYTE Mask;
 
   if( !KeyState ) return 0;
 
   /* DumpKeyState( KeyState ); */
 
-  for( i = 0; pkKT->pCharModifiers->pVkToBit[i].Vk; i++ ) {
-    int Vk = pkKT->pCharModifiers->pVkToBit[i].Vk;
-    switch(Vk)
-      {
-        case VK_SHIFT:
-         Mask = KeysSet( pkKT, KeyState, Vk, VK_LSHIFT, VK_RSHIFT );
-          if (Mask & 0xc0)
-           ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
-         break;
-        case VK_CONTROL:
-         Mask = KeysSet( pkKT, KeyState, Vk, VK_LCONTROL, VK_RCONTROL );
-          if (Mask & 0xc0)
-           ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
-         break;
-        case VK_MENU:
-         Mask = KeysSet( pkKT, KeyState, Vk, VK_LMENU, VK_RMENU );
-          if (Mask & 0xc0)
-           ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
-          if (Mask & 0x40)
-            ModBits |= 0x02 /* KCTRL */;
-         break;
-       default:
-         Mask = KeysSet( pkKT, KeyState, Vk, 0, 0 );
-          if (Mask & 0x80)
-           ModBits |= pkKT->pCharModifiers->pVkToBit[i].ModBits;
-         break;
-      }
-  }
+  if (KeysSet( pkKT, KeyState, VK_LSHIFT, VK_RSHIFT ) &
+      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_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 );
+
+      /* Deal with VK_CAPITAL */
+  if (KeysSet( pkKT, KeyState, VK_CAPITAL, 0 ) & KS_LOCK_BIT)
+    {
+      ModBits |= CAPITAL_BIT;
+    }
+
+  /* Deal with VK_NUMLOCK */
+  if (KeysSet( pkKT, KeyState, VK_NUMLOCK, 0 ) & KS_LOCK_BIT)
+    {
+      ModBits |= NUMLOCK_BIT;
+    }
 
   DPRINT( "Current Mod Bits: %x\n", ModBits );
 
@@ -258,47 +211,64 @@ static BOOL TryToTranslateChar(WORD wVirtKey,
                               PBOOL pbDead,
                               PBOOL pbLigature,
                               PWCHAR pwcTranslatedChar,
-                              PKBDTABLES keyLayout ) 
+                              PKBDTABLES keyLayout )
 {
   PVK_TO_WCHAR_TABLE vtwTbl;
   PVK_TO_WCHARS10 vkPtr;
   size_t size_this_entry;
-  int nMod, shift;
+  int nMod;
+  DWORD CapsMod = 0, CapsState = 0;
 
-  DPRINT ( "TryToTranslate: %04x %x\n", wVirtKey, ModBits ); 
+  CapsState = ModBits & ~MOD_BITS_MASK;
+  ModBits = ModBits & MOD_BITS_MASK;
+
+  DPRINT ( "TryToTranslate: %04x %x\n", wVirtKey, ModBits );
 
   if (ModBits > keyLayout->pCharModifiers->wMaxModBits)
     {
       return FALSE;
     }
-  shift = keyLayout->pCharModifiers->ModNumber[ModBits];
-
   for (nMod = 0; keyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
     {
-      if (shift >= keyLayout->pVkToWcharTable[nMod].nModifications)
-        {
-         continue;
-       }
       vtwTbl = &keyLayout->pVkToWcharTable[nMod];
       size_this_entry = vtwTbl->cbSize;
       vkPtr = (PVK_TO_WCHARS10)((BYTE *)vtwTbl->pVkToWchars);
       while(vkPtr->VirtualKey)
         {
-          if( wVirtKey == vkPtr->VirtualKey ) 
+          if( wVirtKey == (vkPtr->VirtualKey & 0xff) )
            {
-             *pbDead = vkPtr->wch[shift] == WCH_DEAD;
-             *pbLigature = vkPtr->wch[shift] == WCH_LGTR;
-             *pwcTranslatedChar = vkPtr->wch[shift];
-             if( *pbDead ) 
+              CapsMod = keyLayout->pCharModifiers->ModNumber
+                  [ModBits ^
+                   ((CapsState & CAPITAL_BIT) ? vkPtr->Attributes : 0)];
+
+             if( CapsMod > keyLayout->pVkToWcharTable[nMod].nModifications ) {
+                 DWORD MaxBit = 1;
+                 while( MaxBit <
+                        keyLayout->pVkToWcharTable[nMod].nModifications )
+                     MaxBit <<= 1;
+
+                 CapsMod &= MaxBit - 1; /* Guarantee that CapsMod lies
+                                           in bounds. */
+             }
+
+             *pbDead = vkPtr->wch[CapsMod] == WCH_DEAD;
+             *pbLigature = vkPtr->wch[CapsMod] == WCH_LGTR;
+             *pwcTranslatedChar = vkPtr->wch[CapsMod];
+
+             DPRINT("%d %04x: CapsMod %08x CapsState %08x Char %04x\n",
+                      nMod, wVirtKey,
+                      CapsMod, CapsState, *pwcTranslatedChar);
+
+             if( *pbDead )
                {
                   vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + size_this_entry);
-                 if( vkPtr->VirtualKey != 0xff ) 
+                 if( vkPtr->VirtualKey != 0xff )
                    {
                      DPRINT( "Found dead key with no trailer in the table.\n" );
                      DPRINT( "VK: %04x, ADDR: %08x\n", wVirtKey, (int)vkPtr );
                      return FALSE;
                    }
-                 *pwcTranslatedChar = vkPtr->wch[shift];
+                 *pwcTranslatedChar = vkPtr->wch[CapsMod];
                }
                return TRUE;
            }
@@ -328,16 +298,15 @@ ToUnicodeInner(UINT wVirtKey,
                          ModBits( pkKT, lpKeyState ),
                          &bDead,
                          &bLigature,
-                         &wcTranslatedChar, 
-                         pkKT ) ) 
+                         &wcTranslatedChar,
+                         pkKT ) )
     {
-      if( bLigature ) 
+      if( bLigature )
         {
          DPRINT("Not handling ligature (yet)\n" );
          return 0;
         }
 
-      /* DbgPrint( "Trans: %04x\n", wcTranslatedChar ); */
       if( cchBuff > 0 ) pwszBuff[0] = wcTranslatedChar;
 
       return bDead ? -1 : 1;
@@ -351,17 +320,35 @@ STDCALL
 NtUserGetKeyState(
   DWORD key)
 {
-  DWORD ret;
+  DWORD ret = 0;
 
+  IntLockQueueState;
   if( key < 0x100 ) {
-    ret = ((DWORD)(QueueKeyStateTable[key] & 0x80) << 8 ) |
-      (QueueKeyStateTable[key] & 0x80) |
-      (QueueKeyStateTable[key] & 0x01);
-    return ret;
+    ret = ((DWORD)(QueueKeyStateTable[key] & KS_DOWN_BIT) << 8 ) |
+      (QueueKeyStateTable[key] & KS_LOCK_BIT);
   }
-  return 0;
+  IntUnLockQueueState;
+  return ret;
 }
 
+DWORD
+STDCALL
+NtUserGetAsyncKeyState(
+  DWORD key)
+{
+  DWORD ret = 0;
+
+  IntLockQueueState;
+  if( key < 0x100 ) {
+    ret = ((DWORD)(QueueKeyStateTable[key] & KS_DOWN_BIT) << 8 ) |
+      (QueueKeyStateTable[key] & KS_LOCK_BIT);
+  }
+  IntUnLockQueueState;
+  return ret;
+}
+
+
+
 int STDCALL ToUnicodeEx( UINT wVirtKey,
                         UINT wScanCode,
                         PBYTE lpKeyState,
@@ -369,14 +356,27 @@ int STDCALL ToUnicodeEx( UINT wVirtKey,
                         int cchBuff,
                         UINT wFlags,
                         HKL dwhkl ) {
-  return ToUnicodeInner( wVirtKey,
-                        wScanCode,
-                        lpKeyState,
-                        pwszBuff,
-                        cchBuff,
-                        wFlags,
-                        PsGetWin32Thread() ? 
-                        PsGetWin32Thread()->KeyboardLayout : 0 );
+  int ToUnicodeResult = 0;
+
+  if (0 == (lpKeyState[wVirtKey] & KS_DOWN_BIT))
+    {
+      ToUnicodeResult = 0;
+    }
+  else
+    {
+      IntLockQueueState;
+      ToUnicodeResult = ToUnicodeInner( wVirtKey,
+                                       wScanCode,
+                                       lpKeyState,
+                                       pwszBuff,
+                                       cchBuff,
+                                       wFlags,
+                                       PsGetWin32Thread() ?
+                                       PsGetWin32Thread()->KeyboardLayout : 0 );
+      IntUnLockQueueState;
+    }
+
+  return ToUnicodeResult;
 }
 
 int STDCALL ToUnicode( UINT wVirtKey,
@@ -394,7 +394,7 @@ int STDCALL ToUnicode( UINT wVirtKey,
                      0 );
 }
 
-/* 
+/*
  * Utility to copy and append two unicode strings.
  *
  * IN OUT PUNICODE_STRING ResultFirst -> First string and result
@@ -405,29 +405,30 @@ int STDCALL ToUnicode( UINT wVirtKey,
  * Returns NTSTATUS.
  */
 
-static NTSTATUS ReallyAppendUnicodeString(PUNICODE_STRING ResultFirst,
-                                         PUNICODE_STRING Second,
-                                         BOOL Deallocate) {
-  NTSTATUS Status;
-  PWSTR new_string = 
-    ExAllocatePool(PagedPool,
-                  (ResultFirst->Length + Second->Length + sizeof(WCHAR)));
-  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;
+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;
 }
 
 /*
@@ -440,66 +441,66 @@ static NTSTATUS ReallyAppendUnicodeString(PUNICODE_STRING ResultFirst,
  * Returns NTSTATUS
  */
 
-static NTSTATUS 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;
-  }
+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);
+    Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
+                            0,
+                            0,
+                            &ResLength);
 
-  if( Status != STATUS_BUFFER_TOO_SMALL ) {
-    NtClose(KeyHandle);
-    return Status;
-  }
+    if( Status != STATUS_BUFFER_TOO_SMALL ) {
+       NtClose(KeyHandle);
+       return Status;
+    }
 
-  ResLength += sizeof( *KeyValuePartialInfo );
-  KeyValuePartialInfo = 
-    ExAllocatePool(PagedPool, ResLength);
-  Length = ResLength;
+    ResLength += sizeof( *KeyValuePartialInfo );
+    KeyValuePartialInfo =
+       ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
+    Length = ResLength;
 
-  if( !KeyValuePartialInfo ) {
-    NtClose(KeyHandle);
-    return STATUS_NO_MEMORY;
-  }
+    if( !KeyValuePartialInfo ) {
+       NtClose(KeyHandle);
+       return STATUS_NO_MEMORY;
+    }
 
-  Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
-                          (PVOID)KeyValuePartialInfo,
-                          Length,
-                          &ResLength);
+    Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
+                            (PVOID)KeyValuePartialInfo,
+                            Length,
+                            &ResLength);
 
-  if( !NT_SUCCESS(Status) ) {
-    NtClose(KeyHandle);
-    ExFreePool(KeyValuePartialInfo);
-    return Status;
-  }
+    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"");
-  ReallyAppendUnicodeString(ReturnedValue,&Temp,FALSE);
+    Temp.Length = Temp.MaximumLength = KeyValuePartialInfo->DataLength;
+    Temp.Buffer = (PWCHAR)KeyValuePartialInfo->Data;
 
-  ExFreePool(KeyValuePartialInfo);
-  NtClose(KeyHandle);
+    /* At this point, KeyValuePartialInfo->Data contains the key data */
+    RtlInitUnicodeString(ReturnedValue,L"");
+    AppendUnicodeString(ReturnedValue,&Temp,FALSE);
 
-  return Status;
+    ExFreePool(KeyValuePartialInfo);
+    NtClose(KeyHandle);
+
+    return Status;
 }
 
 typedef PVOID (*KbdLayerDescriptor)(VOID);
@@ -508,14 +509,15 @@ NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
                                        DWORD flags,
                                        PVOID *func_addr);
 
-void InitKbdLayout( PVOID *pkKeyboardLayout ) {
-  UNICODE_STRING KeyName;
-  UNICODE_STRING ValueName;
+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;
@@ -525,79 +527,75 @@ void InitKbdLayout( PVOID *pkKeyboardLayout ) {
   #define XX_STATUS(x) if (!NT_SUCCESS(Status = (x))) continue;
 
   do {
-    RtlInitUnicodeString(&KeyName,
-                        L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
-                        L"\\Control\\Nls\\Locale");
-    RtlInitUnicodeString(&ValueName,
-                        L"(Default)");
-       
-    DPRINT("KeyName = %wZ, ValueName = %wZ\n", &KeyName, &ValueName);
-
-    Status = ReadRegistryValue(&KeyName,&ValueName,&DefaultLocale);
-    
-    if( !NT_SUCCESS(Status) ) {
-      DbgPrint( "Could not get default locale (%08x).\n", Status );
-    } else {
-      DPRINT( "DefaultLocale = %wZ\n", &DefaultLocale );
+    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\\");
 
-      ReallyAppendUnicodeString(&LayoutKeyName,&DefaultLocale,FALSE);
+      AppendUnicodeString(&LayoutKeyName,&DefaultLocale,FALSE);
 
-      RtlFreeUnicodeString(&DefaultLocale);
       RtlInitUnicodeString(&LayoutValueName,L"Layout File");
 
       Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);
       RtlInitUnicodeString(&FullLayoutPath,SYSTEMROOT_DIR);
 
       if( !NT_SUCCESS(Status) ) {
-       DbgPrint("Got default locale but not layout file. (%08x)\n",
+       DPRINT1("Got default locale but not layout file. (%08lx)\n",
                 Status);
-       RtlFreeUnicodeString(&LayoutFile);
       } else {
        DPRINT("Read registry and got %wZ\n", &LayoutFile);
-    
+
        RtlFreeUnicodeString(&LayoutKeyName);
 
-       ReallyAppendUnicodeString(&FullLayoutPath,&LayoutFile,FALSE);
+       AppendUnicodeString(&FullLayoutPath,&LayoutFile,FALSE);
 
        DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);
 
        RtlFreeUnicodeString(&LayoutFile);
 
-       KeyboardLayoutWSTR = ExAllocatePool(PagedPool,
-                                           (FullLayoutPath.Length + 1) * 
-                                           sizeof(WCHAR));
+       KeyboardLayoutWSTR =
+         ExAllocatePoolWithTag(PagedPool,
+                               FullLayoutPath.Length + sizeof(WCHAR),
+                               TAG_STRING);
 
        if( !KeyboardLayoutWSTR ) {
-         DbgPrint("Couldn't allocate a string for the keyboard layout name.\n");
+         DPRINT1("Couldn't allocate a string for the keyboard layout name.\n");
          RtlFreeUnicodeString(&FullLayoutPath);
          return;
        }
        memcpy(KeyboardLayoutWSTR,FullLayoutPath.Buffer,
-              (FullLayoutPath.Length + 1) * sizeof(WCHAR));
-       KeyboardLayoutWSTR[FullLayoutPath.Length] = 0;
+              FullLayoutPath.Length + sizeof(WCHAR));
+       KeyboardLayoutWSTR[FullLayoutPath.Length / sizeof(WCHAR)] = 0;
 
        kbModule = EngLoadImage(KeyboardLayoutWSTR);
        DPRINT( "Load Keyboard Layout: %S\n", KeyboardLayoutWSTR );
 
         if( !kbModule )
-         DbgPrint( "Load Keyboard Layout: No %wZ\n", &FullLayoutPath );
-      }
+         DPRINT1( "Load Keyboard Layout: No %wZ\n", &FullLayoutPath );
 
-      RtlFreeUnicodeString(&FullLayoutPath);
+       RtlFreeUnicodeString(&FullLayoutPath);
+      }
     }
 
     if( !kbModule )
     {
-      DbgPrint("Trying to load US Keyboard Layout\n");
+      DPRINT1("Trying to load US Keyboard Layout\n");
       kbModule = EngLoadImage(L"\\SystemRoot\\system32\\kbdus.dll");
-      
+
       if (!kbModule)
       {
-        DbgPrint("Failed to load any Keyboard Layout\n");
+        DPRINT1("Failed to load any Keyboard Layout\n");
         return;
            }
     }
@@ -608,14 +606,14 @@ void InitKbdLayout( PVOID *pkKeyboardLayout ) {
                           &kbdProcedureName,
                           0,
                           (PVOID*)&layerDescGetFn);
-    
+
     if( layerDescGetFn ) {
       *pkKeyboardLayout = layerDescGetFn();
     }
   } while (FALSE);
 
   if( !*pkKeyboardLayout ) {
-    DbgPrint("Failed to load the keyboard layout.\n");
+    DPRINT1("Failed to load the keyboard layout.\n");
   }
 
 #undef XX_STATUS
@@ -627,96 +625,92 @@ PKBDTABLES W32kGetDefaultKeyLayout() {
   return pkKeyboardLayout;
 }
 
-BOOL STDCALL
-NtUserTranslateMessage(LPMSG lpMsg,
-                      HKL dwhkl) /* Used to pass the kbd layout */
+BOOL FASTCALL
+IntTranslateKbdMessage(LPMSG lpMsg,
+                       HKL dwhkl)
 {
   static INT dead_char = 0;
-  UINT ScanCode = 0;
   LONG UState = 0;
   WCHAR wp[2] = { 0 };
   MSG NewMsg = { 0 };
-  MSG InMsg = { 0 };
-  PUSER_MESSAGE UMsg;
   PKBDTABLES keyLayout;
+  BOOL Result = FALSE;
+  DWORD ScanCode = 0;
 
-  if( !NT_SUCCESS(MmCopyFromCaller(&InMsg, lpMsg, sizeof(InMsg))) ) {
-    return FALSE;
-  }
 
   keyLayout = PsGetWin32Thread()->KeyboardLayout;
-  if( !keyLayout ) return 0;
+  if( !keyLayout )
+    return FALSE;
 
-  ScanCode = (InMsg.lParam >> 16) & 0xff;
+  if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
+    return FALSE;
 
-  if (InMsg.message != WM_KEYDOWN && InMsg.message != WM_SYSKEYDOWN)
-    {
-      if (InMsg.message == WM_KEYUP) {
-       SetKeyState( ScanCode, FALSE ); /* Release key */
-      }
-      return(FALSE);
-    }
+  ScanCode = (lpMsg->lParam >> 16) & 0xff;
 
-  SetKeyState( ScanCode, TRUE ); /* Strike key */
+  IntLockQueueState;
 
-  /* Pass 2: Get Unicode Character */
-  UState = ToUnicodeInner(InMsg.wParam, HIWORD(InMsg.lParam) & 0xff,
-                         QueueKeyStateTable, wp, 2, 0, 
+  /* All messages have to contain the cursor point. */
+  IntGetCursorLocation(PsGetWin32Thread()->Desktop->WindowStation,
+                       &NewMsg.pt);
+
+  UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff,
+                         QueueKeyStateTable, wp, 2, 0,
                          keyLayout );
 
   if (UState == 1)
     {
-      NewMsg.message = (InMsg.message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
+      NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
       if (dead_char)
         {
          ULONG i;
-         
-         if (wp[0] == ' ') wp[0] =  dead_char;
-         if (dead_char == 0xa2) dead_char = '(';
-         else if (dead_char == 0xa8) dead_char = '"';
-         else if (dead_char == 0xb2) dead_char = ';';
-         else if (dead_char == 0xb4) dead_char = '\'';
-         else if (dead_char == 0xb7) dead_char = '<';
-         else if (dead_char == 0xb8) dead_char = ',';
-         else if (dead_char == 0xff) dead_char = '.';
-         for (i = 0; i < sizeof(accent_chars)/sizeof(accent_chars[0]); i++)
+         WCHAR first, second;
+         DPRINT("PREVIOUS DEAD CHAR: %c\n", dead_char);
+
+         for( i = 0; keyLayout->pDeadKey[i].dwBoth; i++ )
            {
-             if ((accent_chars[i].ac_accent == dead_char) &&
-                 (accent_chars[i].ac_char == wp[0]))
-                {
-                 wp[0] = accent_chars[i].ac_result;
-                 break;
-                }
+             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;
+               }
            }
-             dead_char = 0;
-        }
-      NewMsg.hwnd = InMsg.hwnd;
+
+         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(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
+       }
+
+      NewMsg.hwnd = lpMsg->hwnd;
       NewMsg.wParam = wp[0];
-      NewMsg.lParam = InMsg.lParam;
-      UMsg = MsqCreateMessage(&NewMsg);
-      DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], InMsg.lParam );
-      MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
-      return(TRUE);
+      NewMsg.lParam = lpMsg->lParam;
+      DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
+      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
+      Result = TRUE;
     }
   else if (UState == -1)
     {
-      NewMsg.message = 
-       (InMsg.message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
-      NewMsg.hwnd = InMsg.hwnd;
+      NewMsg.message =
+       (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
+      NewMsg.hwnd = lpMsg->hwnd;
       NewMsg.wParam = wp[0];
-      NewMsg.lParam = InMsg.lParam;
+      NewMsg.lParam = lpMsg->lParam;
       dead_char = wp[0];
-      UMsg = MsqCreateMessage(&NewMsg);
-      MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg);
-      return(TRUE);
+      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
+      Result = TRUE;
     }
-  return(FALSE);
-}
 
-HWND STDCALL
-NtUserSetFocus(HWND hWnd)
-{
-  return IntSetFocusWindow(hWnd);
+  IntUnLockQueueState;
+  return Result;
 }
 
 DWORD
@@ -724,11 +718,15 @@ STDCALL
 NtUserGetKeyboardState(
   LPBYTE lpKeyState)
 {
+  BOOL Result = TRUE;
+
+  IntLockQueueState;
   if (lpKeyState) {
        if(!NT_SUCCESS(MmCopyToCaller(lpKeyState, QueueKeyStateTable, 256)))
-               return FALSE;
+         Result = FALSE;
   }
-  return TRUE;
+  IntUnLockQueueState;
+  return Result;
 }
 
 DWORD
@@ -736,11 +734,16 @@ STDCALL
 NtUserSetKeyboardState(
   LPBYTE lpKeyState)
 {
-       if (lpKeyState) {
-               if(! NT_SUCCESS(MmCopyFromCaller(QueueKeyStateTable, lpKeyState, 256)))
-                       return FALSE;
-       }
-    return TRUE;
+  BOOL Result = TRUE;
+
+ IntLockQueueState;
+  if (lpKeyState) {
+    if(! NT_SUCCESS(MmCopyFromCaller(QueueKeyStateTable, lpKeyState, 256)))
+      Result = FALSE;
+  }
+  IntUnLockQueueState;
+
+  return Result;
 }
 
 static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT ) {
@@ -754,15 +757,20 @@ static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT ) {
 }
 
 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 ) 
+      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 ) 
+      if( pkKT->pVSCtoVK_E1[i].Vsc == Code )
        return pkKT->pVSCtoVK_E1[i].Vk & 0xff;
     }
 
@@ -792,13 +800,8 @@ UINT ScanToVk( UINT Code, BOOL ExtKey, PKBDTABLES pkKT ) {
  * @implemented
  */
 
-UINT
-STDCALL
-NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
+static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout ) {
   UINT ret = 0;
-  PKBDTABLES keyLayout = PsGetWin32Thread()->KeyboardLayout;
-
-  if( !keyLayout ) return 0;
 
   switch( Type ) {
   case 0:
@@ -809,9 +812,9 @@ NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
     break;
 
   case 1:
-    ret = 
+    ret =
       DontDistinguishShifts
-      (NtUserMapVirtualKeyEx( Code, 3, keyboardId, dwhkl ) );
+      (IntMapVirtualKeyEx( Code, 3, keyLayout ) );
     break;
 
   case 2: {
@@ -823,6 +826,7 @@ NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
   } break;
 
   case 3:
+
     ret = ScanToVk( Code, FALSE, keyLayout );
     break;
   }
@@ -830,6 +834,17 @@ NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
   return ret;
 }
 
+UINT
+STDCALL
+NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) {
+  PKBDTABLES keyLayout = PsGetWin32Thread() ?
+    PsGetWin32Thread()->KeyboardLayout : 0;
+
+  if( !keyLayout ) return 0;
+
+  return IntMapVirtualKeyEx( Code, Type, keyLayout );
+}
+
 
 int
 STDCALL
@@ -844,17 +859,17 @@ NtUserToUnicodeEx(
   BYTE KeyStateBuf[0x100];
   PWCHAR OutPwszBuff = 0;
   int ret = 0;
-  
+
 
   if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
                                   lpKeyState,
                                   sizeof(KeyStateBuf))) ) {
-    DbgPrint( "Couldn't copy key state from caller.\n" );
+    DPRINT1( "Couldn't copy key state from caller.\n" );
     return 0;
   }
-  OutPwszBuff = ExAllocatePool(NonPagedPool,sizeof(WCHAR) * cchBuff);
+  OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING);
   if( !OutPwszBuff ) {
-    DbgPrint( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
+    DPRINT1( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
     return 0;
   }
   RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );
@@ -865,7 +880,7 @@ NtUserToUnicodeEx(
                     OutPwszBuff,
                     cchBuff,
                     wFlags,
-                    dwhkl );  
+                    dwhkl );
 
   MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff);
   ExFreePool(OutPwszBuff);
@@ -887,8 +902,8 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
   UINT VkCode = 0;
   UINT ScanCode = (lParam >> 16) & 0xff;
   BOOL ExtKey = lParam & (1<<24) ? TRUE : FALSE;
-  PKBDTABLES keyLayout = 
-    PsGetWin32Thread() ? 
+  PKBDTABLES keyLayout =
+    PsGetWin32Thread() ?
     PsGetWin32Thread()->KeyboardLayout : 0;
 
   if( !keyLayout || nSize < 1 ) return 0;
@@ -907,12 +922,12 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
 
   VSC_LPWSTR *KeyNames = 0;
 
-  if( CareVk != VkCode ) 
+  if( CareVk != VkCode )
     ScanCode = VkToScan( VkCode, ExtKey, keyLayout );
-  
-  if( ExtKey ) 
+
+  if( ExtKey )
     KeyNames = keyLayout->pKeyNamesExt;
-  else 
+  else
     KeyNames = keyLayout->pKeyNames;
 
   for( i = 0; KeyNames[i].pwsz; i++ ) {
@@ -920,8 +935,8 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
       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, 
+      if( NT_SUCCESS( MmCopyToCaller( lpString,
+                                     KeyNames[i].pwsz,
                                      StrMax * sizeof(WCHAR) ) ) &&
          NT_SUCCESS( MmCopyToCaller( lpString + StrMax,
                                      &null_wc,
@@ -935,7 +950,7 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
   if( ret == 0 ) {
     WCHAR UCName[2];
 
-    UCName[0] = W32kSimpleToupper(NtUserMapVirtualKeyEx( VkCode, 2, 0, 0 ));
+    UCName[0] = W32kSimpleToupper(IntMapVirtualKeyEx( VkCode, 2, keyLayout ));
     UCName[1] = 0;
     ret = 1;
 
@@ -952,12 +967,209 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) {
  */
 
 VOID FASTCALL W32kKeyProcessMessage(LPMSG Msg, PKBDTABLES KeyboardLayout) {
-  if( !KeyboardLayout || !Msg) return;
-  if( Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
-      Msg->message != WM_KEYUP   && Msg->message != WM_SYSKEYUP ) {
-    return;
+  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 } };
+
+  if( !KeyboardLayout || !Msg ||
+      (Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
+       Msg->message != WM_KEYUP   && Msg->message != WM_SYSKEYUP) )
+    {
+      return;
+    }
+
+  IntLockQueueState;
+
+  /* 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,QueueKeyStateTable);
+
+  /* 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( ScanCode >= KeyboardLayout->bMaxVSCtoVK )
+    RawVk = 0;
+  else
+    RawVk = KeyboardLayout->pusVSCtoVK[ScanCode];
+
+  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( QueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT ) {
+      if( Msg->message == WM_SYSKEYDOWN ) Msg->message = WM_KEYDOWN;
+      else Msg->message = WM_KEYUP;
   }
-  Msg->wParam = NtUserMapVirtualKeyEx( (Msg->lParam >> 16) & 0xff, 1, 0, 0 );
+
+  IntUnLockQueueState;
+}
+
+DWORD
+STDCALL
+NtUserGetKeyboardLayoutList(
+  DWORD Items,
+  DWORD pHklBuff)
+{
+  UNIMPLEMENTED
+
+  return 0;
 }
 
+DWORD
+STDCALL
+NtUserGetKeyboardLayoutName(
+  DWORD lpszName)
+{
+  UNIMPLEMENTED
+
+  return 0;
+}
+
+HKL
+STDCALL
+NtUserGetKeyboardLayout(
+  DWORD dwThreadId)
+{
+  NTSTATUS Status;
+  PETHREAD Thread;
+  PW32THREAD W32Thread;
+  PKBDTABLES layout;
+
+  if (!dwThreadId)
+     W32Thread = PsGetWin32Thread();
+  else 
+  {
+     Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+     if(!NT_SUCCESS(Status))
+       {
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return 0;
+       }
+     W32Thread = Thread->Tcb.Win32Thread;
+  }
+  layout = W32Thread->KeyboardLayout;
+  if(!layout) return 0;
+  return (HKL)layout;
+}
+    
+  
+DWORD
+STDCALL
+NtUserGetKeyboardType(
+  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)
+{
+  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 */