Add preliminary support for keyboard layout APIs.

diff --git a/dlls/ttydrv/ttydrv.spec b/dlls/ttydrv/ttydrv.spec
index 9b75498..4f10c4c 100644
--- a/dlls/ttydrv/ttydrv.spec
+++ b/dlls/ttydrv/ttydrv.spec
@@ -35,10 +35,10 @@
 
 # USER driver
 
-@ cdecl VkKeyScan(long) TTYDRV_VkKeyScan
-@ cdecl MapVirtualKey(long long) TTYDRV_MapVirtualKey
-@ cdecl GetKeyNameText(long str long) TTYDRV_GetKeyNameText
-@ cdecl ToUnicode(long long ptr ptr long long) TTYDRV_ToUnicode
+@ cdecl VkKeyScanEx(long long) TTYDRV_VkKeyScanEx
+@ cdecl MapVirtualKeyEx(long long long) TTYDRV_MapVirtualKeyEx
+@ cdecl GetKeyNameText(long ptr long) TTYDRV_GetKeyNameText
+@ cdecl ToUnicodeEx(long long ptr ptr long long long) TTYDRV_ToUnicodeEx
 @ cdecl Beep() TTYDRV_Beep
 @ cdecl SetCursor(ptr) TTYDRV_SetCursor
 @ cdecl GetScreenSaveActive() TTYDRV_GetScreenSaveActive
diff --git a/dlls/ttydrv/user.c b/dlls/ttydrv/user.c
index 9c9afdb..fad2331 100644
--- a/dlls/ttydrv/user.c
+++ b/dlls/ttydrv/user.c
@@ -34,17 +34,17 @@
 struct tagCURSORICONINFO;
 
 /***********************************************************************
- *		VkKeyScan (TTYDRV.@)
+ *		VkKeyScanEx (TTYDRV.@)
  */
-WORD TTYDRV_VkKeyScan(CHAR cChar)
+SHORT TTYDRV_VkKeyScanEx(WCHAR cChar, HKL hkl)
 {
   return 0;
 }
 
 /***********************************************************************
- *		MapVirtualKey (TTYDRV.@)
+ *		MapVirtualKeyEx (TTYDRV.@)
  */
-UINT16 TTYDRV_MapVirtualKey(UINT16 wCode, UINT16 wMapType)
+UINT TTYDRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
 {
   return 0;
 }
@@ -52,7 +52,7 @@
 /***********************************************************************
  *		GetKeyNameText (TTYDRV.@)
  */
-INT16 TTYDRV_GetKeyNameText( LONG lParam, LPSTR lpBuffer, INT16 nSize )
+INT TTYDRV_GetKeyNameText( LONG lParam, LPWSTR lpBuffer, INT nSize )
 {
   if(lpBuffer && nSize)
     {
@@ -62,10 +62,10 @@
 }
 
 /***********************************************************************
- *		ToUnicode (TTYDRV.@)
+ *		ToUnicodeEx (TTYDRV.@)
  */
-INT TTYDRV_ToUnicode( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
-		      LPWSTR pwszBuff, int cchBuff, UINT flags )
+INT TTYDRV_ToUnicodeEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+		      LPWSTR pwszBuff, int cchBuff, UINT flags, HKL hkl )
 {
   return 0;
 }
diff --git a/dlls/user/user32.spec b/dlls/user/user32.spec
index 22c5705..ef3fe23 100644
--- a/dlls/user/user32.spec
+++ b/dlls/user/user32.spec
@@ -591,7 +591,7 @@
 @ stdcall UnhookWindowsHook(long ptr)
 @ stdcall UnhookWindowsHookEx(long)
 @ stdcall UnionRect(ptr ptr ptr)
-@ stub UnloadKeyboardLayout
+@ stdcall UnloadKeyboardLayout(long)
 @ stub UnlockWindowStation
 @ stdcall UnpackDDElParam(long long ptr ptr)
 @ stdcall UnregisterClassA(str long)
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 999c8b1..d8e5262 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -76,10 +76,16 @@
     }
 
     GET_USER_FUNC(InitKeyboard);
-    GET_USER_FUNC(VkKeyScan);
-    GET_USER_FUNC(MapVirtualKey);
+    GET_USER_FUNC(VkKeyScanEx);
+    GET_USER_FUNC(MapVirtualKeyEx);
     GET_USER_FUNC(GetKeyNameText);
-    GET_USER_FUNC(ToUnicode);
+    GET_USER_FUNC(ToUnicodeEx);
+    GET_USER_FUNC(GetKeyboardLayoutList);
+    GET_USER_FUNC(GetKeyboardLayout);
+    GET_USER_FUNC(GetKeyboardLayoutName);
+    GET_USER_FUNC(LoadKeyboardLayout);
+    GET_USER_FUNC(ActivateKeyboardLayout);
+    GET_USER_FUNC(UnloadKeyboardLayout);
     GET_USER_FUNC(Beep);
     GET_USER_FUNC(InitMouse);
     GET_USER_FUNC(SetCursor);
diff --git a/dlls/x11drv/Makefile.in b/dlls/x11drv/Makefile.in
index a083dfe..dc24c19 100644
--- a/dlls/x11drv/Makefile.in
+++ b/dlls/x11drv/Makefile.in
@@ -6,7 +6,7 @@
 MODULE    = x11drv.dll
 IMPORTS   = user32 gdi32 advapi32 kernel32 ntdll
 EXTRAINCL = @X_CFLAGS@
-EXTRALIBS = @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
+EXTRALIBS = $(LIBUNICODE) @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
 
 C_SRCS = \
 	$(TOPOBJDIR)/graphics/x11drv/bitblt.c \
diff --git a/dlls/x11drv/keyboard.c b/dlls/x11drv/keyboard.c
index 8a8b80f..1c1ce06 100644
--- a/dlls/x11drv/keyboard.c
+++ b/dlls/x11drv/keyboard.c
@@ -44,10 +44,12 @@
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
+#include "winuser.h"
 #include "wine/winuser16.h"
 #include "winnls.h"
 #include "win.h"
 #include "x11drv.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
@@ -115,6 +117,16 @@
    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
 };
 
+static const WORD main_key_vkey_qwerty_v2[MAIN_LEN] =
+{
+/* NOTE: this layout must concur with the scan codes layout above */
+   VK_OEM_5,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_PLUS,VK_OEM_4,
+   VK_Q,VK_W,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_6,VK_OEM_1,
+   VK_A,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_OEM_3,VK_OEM_7,VK_OEM_2,
+   VK_Z,VK_X,VK_C,VK_V,VK_B,VK_N,VK_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_MINUS,
+   VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
+};
+
 static const WORD main_key_vkey_qwertz[MAIN_LEN] =
 {
 /* NOTE: this layout must concur with the scan codes layout above */
@@ -738,68 +750,70 @@
 
 /*** Layout table. Add your keyboard mappings to this list */
 static const struct {
+    LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
+                 in the appropriate dlls/kernel/nls/.nls file */
     const char *comment;
     const char (*key)[MAIN_LEN][4];
     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
 } main_key_tab[]={
- {"United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
- {"British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
- {"Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
- {"Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
- {"Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
- {"Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
- {"United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
- {"Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
- {"Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
- {"Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
+ {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
+ {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
+ {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
+ {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
+ {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
+ {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
+ {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
+ {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
+ {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
+ {0x041e, "Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
 
- {NULL, NULL, NULL, NULL} /* sentinel */
+ {0, NULL, NULL, NULL, NULL} /* sentinel */
 };
 static unsigned kbd_layout=0; /* index into above table of layouts */
 
@@ -1487,26 +1501,148 @@
 
 
 /***********************************************************************
- *           X11DRV_MappingNotify
+ *		GetKeyboardLayoutList (X11DRV.@)
  */
-void X11DRV_MappingNotify( XMappingEvent *event )
+UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
 {
-    TSXRefreshKeyboardMapping(event);
-    X11DRV_InitKeyboard( pKeyStateTable );
+    INT i;
+
+    TRACE("%d, %p\n", size, hkl);
+
+    if (!size)
+    {
+        size = 4096; /* hope we will never have that many */
+        hkl = NULL;
+    }
+
+    for (i = 0; main_key_tab[i].comment && (i < size); i++)
+    {
+        if (hkl)
+            hkl[i] = (HKL)main_key_tab[i].lcid;
+    }
+    return i;
 }
 
 
 /***********************************************************************
- *		VkKeyScan (X11DRV.@)
+ *		GetKeyboardLayout (X11DRV.@)
  */
-WORD X11DRV_VkKeyScan(CHAR cChar)
+HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
+{
+    DWORD layout;
+    LANGID langid;
+
+    if (dwThreadid)
+        FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid);
+
+    layout = main_key_tab[kbd_layout].lcid;
+    /* 
+     * Microsoft Office expects this value to be something specific
+     * for Japanese and Korean Windows with an IME the value is 0xe001
+     * We should probibly 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 */
+
+    return (HKL)layout;
+}
+
+
+/***********************************************************************
+ *		GetKeyboardLayoutName (X11DRV.@)
+ */
+BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
+{
+    static const WCHAR formatW[] = {'%','0','8','l','x',0};
+    DWORD layout;
+    LANGID langid;
+
+    layout = main_key_tab[kbd_layout].lcid;
+    /* see comment above */
+    langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
+    if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
+        layout |= 0xe001 << 16; /* FIXME */
+
+    sprintfW(name, formatW, layout);
+    TRACE("returning %s\n", debugstr_w(name));
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *		LoadKeyboardLayout (X11DRV.@)
+ */
+HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
+{
+    FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+
+/***********************************************************************
+ *		UnloadKeyboardLayout (X11DRV.@)
+ */
+BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
+{
+    FIXME("%p: stub!\n", hkl);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *		ActivateKeyboardLayout (X11DRV.@)
+ */
+HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
+{
+    FIXME("%p, %04x: stub!\n", hkl, flags);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+
+/***********************************************************************
+ *           X11DRV_MappingNotify
+ */
+void X11DRV_MappingNotify( XMappingEvent *event )
+{
+    HWND hwnd;
+
+    TSXRefreshKeyboardMapping(event);
+    X11DRV_InitKeyboard( pKeyStateTable );
+
+    hwnd = GetFocus();
+    if (!hwnd) hwnd = GetActiveWindow();
+    PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
+                 0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
+}
+
+
+/***********************************************************************
+ *		VkKeyScanEx (X11DRV.@)
+ *
+ * Note: Windows ignores HKL parameter and uses current active layout instead
+ */
+SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
 {
     Display *display = thread_display();
     KeyCode keycode;
     KeySym keysym;
     int i, index;
+    CHAR cChar;
     SHORT ret;
 
+    if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
+    {
+        WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
+        return -1;
+    }
+
+    TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
+
     /* char->keysym (same for ANSI chars) */
     keysym = (unsigned char)cChar; /* (!) cChar is signed */
     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
@@ -1565,15 +1701,18 @@
 }
 
 /***********************************************************************
- *		MapVirtualKey (X11DRV.@)
+ *		MapVirtualKeyEx (X11DRV.@)
  */
-UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
+UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
 {
     Display *display = thread_display();
 
 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
 
-	TRACE("wCode=0x%x wMapType=%d ...\n", wCode,wMapType);
+    TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
+    if (hkl != X11DRV_GetKeyboardLayout(0))
+        FIXME("keyboard layout %p is not supported\n", hkl);
+
 	switch(wMapType) {
 		case 0:	{ /* vkey-code to scan-code */
 			/* let's do vkey -> keycode -> scan */
@@ -1667,7 +1806,7 @@
 /***********************************************************************
  *		GetKeyNameText (X11DRV.@)
  */
-INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
+INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
 {
   int vkey, ansi, scanCode;
   KeyCode keyc;
@@ -1679,7 +1818,7 @@
   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
 
   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
-  vkey = X11DRV_MapVirtualKey(scanCode, 1);
+  vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
 
   /*  handle "don't care" bit (0x02000000) */
   if (!(lParam & 0x02000000)) {
@@ -1701,7 +1840,7 @@
     }
   }
 
-  ansi = X11DRV_MapVirtualKey(vkey, 2);
+  ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
 
   /* first get the name of the "regular" keys which is the Upper case
@@ -1715,7 +1854,7 @@
       {
         if ((nSize >= 2) && lpBuffer)
 	{
-        *lpBuffer = toupper((char)ansi);
+          *lpBuffer = toupperW((WCHAR)ansi);
           *(lpBuffer+1) = 0;
           return 1;
         }
@@ -1747,7 +1886,8 @@
             scanCode, keyc, (int)keys, name);
       if (lpBuffer && nSize && name)
       {
-          lstrcpynA(lpBuffer, name, nSize);
+          MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
+          lpBuffer[nSize - 1] = 0;
           return 1;
       }
   }
@@ -1839,7 +1979,7 @@
 }
 
 /***********************************************************************
- *		ToUnicode (X11DRV.@)
+ *		ToUnicodeEx (X11DRV.@)
  *
  * The ToUnicode function translates the specified virtual-key code and keyboard
  * state to the corresponding Windows character or characters.
@@ -1856,8 +1996,8 @@
  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
  *
  */
-INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
-		     LPWSTR bufW, int bufW_size, UINT flags)
+INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+		     LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
 {
     Display *display = thread_display();
     XKeyEvent e;
@@ -1874,6 +2014,9 @@
         return 0;
     }
 
+    if (hkl != X11DRV_GetKeyboardLayout(0))
+        FIXME("keyboard layout %p is not supported\n", hkl);
+
     e.display = display;
     e.keycode = 0;
     e.state = 0;
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index c24c67d..e38f95d 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -63,10 +63,16 @@
 # USER driver
 
 @ cdecl InitKeyboard(ptr) X11DRV_InitKeyboard
-@ cdecl VkKeyScan(long) X11DRV_VkKeyScan
-@ cdecl MapVirtualKey(long long) X11DRV_MapVirtualKey
-@ cdecl GetKeyNameText(long str long) X11DRV_GetKeyNameText
-@ cdecl ToUnicode(long long ptr ptr long long) X11DRV_ToUnicode
+@ cdecl VkKeyScanEx(long long) X11DRV_VkKeyScanEx
+@ cdecl MapVirtualKeyEx(long long long) X11DRV_MapVirtualKeyEx
+@ cdecl GetKeyNameText(long ptr long) X11DRV_GetKeyNameText
+@ cdecl ToUnicodeEx(long long ptr ptr long long long) X11DRV_ToUnicodeEx
+@ cdecl GetKeyboardLayoutList(long ptr) X11DRV_GetKeyboardLayoutList
+@ cdecl GetKeyboardLayout(long) X11DRV_GetKeyboardLayout
+@ cdecl GetKeyboardLayoutName(ptr) X11DRV_GetKeyboardLayoutName
+@ cdecl LoadKeyboardLayout(wstr long) X11DRV_LoadKeyboardLayout
+@ cdecl ActivateKeyboardLayout(long long) X11DRV_ActivateKeyboardLayout
+@ cdecl UnloadKeyboardLayout(long) X11DRV_UnloadKeyboardLayout
 @ cdecl Beep() X11DRV_Beep
 @ cdecl InitMouse(ptr) X11DRV_InitMouse
 @ cdecl SetCursor(ptr) X11DRV_SetCursor
diff --git a/include/user.h b/include/user.h
index d8221ff..f87e0e3 100644
--- a/include/user.h
+++ b/include/user.h
@@ -72,10 +72,16 @@
 typedef struct tagUSER_DRIVER {
     /* keyboard functions */
     void   (*pInitKeyboard)(LPBYTE);
-    WORD   (*pVkKeyScan)(CHAR);
-    UINT   (*pMapVirtualKey)(UINT,UINT);
-    INT    (*pGetKeyNameText)(LONG,LPSTR,INT);
-    INT    (*pToUnicode)(UINT, UINT, LPBYTE, LPWSTR, int, UINT);
+    SHORT  (*pVkKeyScanEx)(WCHAR, HKL);
+    UINT   (*pMapVirtualKeyEx)(UINT, UINT, HKL);
+    INT    (*pGetKeyNameText)(LONG, LPWSTR, INT);
+    INT    (*pToUnicodeEx)(UINT, UINT, LPBYTE, LPWSTR, int, UINT, HKL);
+    UINT   (*pGetKeyboardLayoutList)(INT, HKL *);
+    HKL    (*pGetKeyboardLayout)(DWORD);
+    BOOL   (*pGetKeyboardLayoutName)(LPWSTR);
+    HKL    (*pLoadKeyboardLayout)(LPCWSTR, UINT);
+    HKL    (*pActivateKeyboardLayout)(HKL, UINT);
+    BOOL   (*pUnloadKeyboardLayout)(HKL);
     void   (*pBeep)(void);
     /* mouse functions */
     void   (*pInitMouse)(LPBYTE);
diff --git a/include/winuser.h b/include/winuser.h
index bc3d628..43684f9 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -3714,7 +3714,7 @@
 BOOL      WINAPI ExitWindowsEx(UINT,DWORD);
 BOOL      WINAPI GetIconInfo(HICON,PICONINFO);
 HKL       WINAPI GetKeyboardLayout(DWORD);
-INT       WINAPI GetKeyboardLayoutList(INT,HKL *);
+UINT      WINAPI GetKeyboardLayoutList(INT,HKL *);
 BOOL      WINAPI GetComboBoxInfo(HWND,PCOMBOBOXINFO);
 DWORD     WINAPI GetMenuContextHelpId(HMENU);
 UINT      WINAPI GetMenuDefaultItem(HMENU,UINT,UINT);
@@ -3767,9 +3767,11 @@
 WORD        WINAPI TileWindows (HWND, UINT, const LPRECT,
                                 UINT, const HWND *);
 INT         WINAPI ToUnicode(UINT,UINT,PBYTE,LPWSTR,int,UINT);
+INT         WINAPI ToUnicodeEx(UINT,UINT,LPBYTE,LPWSTR,int,UINT,HKL);
 BOOL      WINAPI TrackPopupMenuEx(HMENU,UINT,INT,INT,HWND,
                                     LPTPMPARAMS);
 BOOL        WINAPI UnhookWinEvent(HWINEVENTHOOK);
+BOOL        WINAPI UnloadKeyboardLayout(HKL);
 BOOL        WINAPI UnregisterDeviceNotification(HDEVNOTIFY);
 BOOL        WINAPI UnregisterHotKey(HWND,INT);
 DWORD       WINAPI WaitForInputIdle(HANDLE,DWORD);
@@ -4077,8 +4079,8 @@
 INT         WINAPI GetKeyNameTextA(LONG,LPSTR,INT);
 INT         WINAPI GetKeyNameTextW(LONG,LPWSTR,INT);
 #define     GetKeyNameText WINELIB_NAME_AW(GetKeyNameText)
-INT       WINAPI GetKeyboardLayoutNameA(LPSTR);
-INT       WINAPI GetKeyboardLayoutNameW(LPWSTR);
+BOOL        WINAPI GetKeyboardLayoutNameA(LPSTR);
+BOOL        WINAPI GetKeyboardLayoutNameW(LPWSTR);
 #define     GetKeyboardLayoutName WINELIB_NAME_AW(GetKeyboardLayoutName)
 SHORT       WINAPI GetKeyState(INT);
 HWND      WINAPI GetLastActivePopup(HWND);
@@ -4399,8 +4401,8 @@
 UINT        WINAPI UserRealizePalette(HDC);
 BOOL        WINAPI ValidateRect(HWND,const RECT*);
 BOOL        WINAPI ValidateRgn(HWND,HRGN);
-WORD        WINAPI VkKeyScanA(CHAR);
-WORD        WINAPI VkKeyScanW(WCHAR);
+SHORT       WINAPI VkKeyScanA(CHAR);
+SHORT       WINAPI VkKeyScanW(WCHAR);
 #define     VkKeyScan WINELIB_NAME_AW(VkKeyScan)
 WORD        WINAPI VkKeyScanExA(CHAR, HKL);
 WORD        WINAPI VkKeyScanExW(WCHAR, HKL);
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 774a5be..71dc3fa 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -859,6 +859,14 @@
 	}
 	break;
 
+    case WM_INPUTLANGCHANGEREQUEST:
+        /* notify about the switch only if it's really our current layout */
+        if ((HKL)lParam == GetKeyboardLayout(0))
+            result = SendMessageA( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
+        else
+            result = 0;
+        break;
+
     default:
         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
         break;
@@ -970,6 +978,14 @@
 	}
 	break;
 
+    case WM_INPUTLANGCHANGEREQUEST:
+        /* notify about the switch only if it's really our current layout */
+        if ((HKL)lParam == GetKeyboardLayout(0))
+            result = SendMessageW( hwnd, WM_INPUTLANGCHANGE, wParam, lParam );
+        else
+            result = 0;
+        break;
+
     default:
         result = DEFWND_DefWinProc( hwnd, msg, wParam, lParam );
         break;
diff --git a/windows/input.c b/windows/input.c
index 5ad72a6..ed845da 100644
--- a/windows/input.c
+++ b/windows/input.c
@@ -645,17 +645,22 @@
  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
  */
-WORD WINAPI VkKeyScanA(CHAR cChar)
+SHORT WINAPI VkKeyScanA(CHAR cChar)
 {
-    return USER_Driver.pVkKeyScan( cChar );
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return VkKeyScanW(wChar);
 }
 
 /******************************************************************************
  *		VkKeyScanW (USER32.@)
  */
-WORD WINAPI VkKeyScanW(WCHAR cChar)
+SHORT WINAPI VkKeyScanW(WCHAR cChar)
 {
-	return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
+    return VkKeyScanExW(cChar, GetKeyboardLayout(0));
 }
 
 /**********************************************************************
@@ -663,8 +668,12 @@
  */
 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
 {
-    /* FIXME: complete workaround this is */
-    return VkKeyScanA(cChar);
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return VkKeyScanExW(wChar, dwhkl);
 }
 
 /******************************************************************************
@@ -672,8 +681,9 @@
  */
 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
 {
-    /* FIXME: complete workaround this is */
-    return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
+    if (USER_Driver.pVkKeyScanEx)
+        return USER_Driver.pVkKeyScanEx(cChar, dwhkl);
+    return -1;
 }
 
 /******************************************************************************
@@ -701,7 +711,7 @@
  */
 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
 {
-    return USER_Driver.pMapVirtualKey( code, maptype );
+    return MapVirtualKeyExA( code, maptype, GetKeyboardLayout(0) );
 }
 
 /******************************************************************************
@@ -709,7 +719,7 @@
  */
 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
 {
-    return MapVirtualKeyA(code,maptype);
+    return MapVirtualKeyExW(code, maptype, GetKeyboardLayout(0));
 }
 
 /******************************************************************************
@@ -717,9 +727,7 @@
  */
 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
 {
-    if (hkl)
-    	FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
-    return MapVirtualKeyA(code,maptype);
+    return MapVirtualKeyExW(code, maptype, hkl);
 }
 
 /******************************************************************************
@@ -727,9 +735,11 @@
  */
 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
 {
-    if (hkl)
-    	FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
-    return MapVirtualKeyA(code,maptype);
+    TRACE_(keyboard)("(%d, %d, %p)\n", code, maptype, hkl);
+
+    if (USER_Driver.pMapVirtualKeyEx)
+        return USER_Driver.pMapVirtualKeyEx(code, maptype, hkl);
+    return 0;
 }
 
 /****************************************************************************
@@ -751,37 +761,37 @@
 /***********************************************************************
  *		GetKeyboardLayout (USER32.@)
  *
- * FIXME: - device handle for keyboard layout defaulted to
+ *        - device handle for keyboard layout defaulted to
  *          the language id. This is the way Windows default works.
  *        - the thread identifier (dwLayout) is also ignored.
  */
 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
 {
-        UINT layout;
-        layout = GetSystemDefaultLCID(); /* FIXME */
-        layout |= (layout<<16);          /* FIXME */
-        TRACE_(keyboard)("returning %08x\n",layout);
-        return (HKL)layout;
+    if (USER_Driver.pGetKeyboardLayout)
+        return USER_Driver.pGetKeyboardLayout(dwLayout);
+    return 0;
 }
 
 /****************************************************************************
  *		GetKeyboardLayoutNameA (USER32.@)
  */
-INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
+BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID)
 {
-        sprintf(pwszKLID, "%p",GetKeyboardLayout(0));
-        return 1;
+    WCHAR buf[KL_NAMELENGTH];
+
+    if (GetKeyboardLayoutNameW(buf))
+        return WideCharToMultiByte( CP_ACP, 0, buf, -1, pszKLID, KL_NAMELENGTH, NULL, NULL ) != 0;
+    return FALSE;
 }
 
 /****************************************************************************
  *		GetKeyboardLayoutNameW (USER32.@)
  */
-INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
+BOOL WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
 {
-        char buf[KL_NAMELENGTH];
-	int res = GetKeyboardLayoutNameA(buf);
-        MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
-	return res;
+    if (USER_Driver.pGetKeyboardLayoutName)
+        return USER_Driver.pGetKeyboardLayoutName(pwszKLID);
+    return FALSE;
 }
 
 /****************************************************************************
@@ -789,7 +799,18 @@
  */
 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
 {
-    return USER_Driver.pGetKeyNameText( lParam, lpBuffer, nSize );
+    WCHAR buf[256];
+    INT ret;
+
+    if (!GetKeyNameTextW(lParam, buf, 256))
+        return 0;
+    ret = WideCharToMultiByte(CP_ACP, 0, buf, -1, lpBuffer, nSize, NULL, NULL);
+    if (!ret && nSize)
+    {
+        ret = nSize - 1;
+        lpBuffer[ret] = 0;
+    }
+    return ret;
 }
 
 /****************************************************************************
@@ -797,15 +818,9 @@
  */
 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
 {
-	int res;
-	LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
-	if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
-	res = GetKeyNameTextA(lParam,buf,nSize);
-
-        if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
-            lpBuffer[nSize-1] = 0;
-	HeapFree( GetProcessHeap(), 0, buf );
-	return res;
+    if (USER_Driver.pGetKeyNameText)
+        return USER_Driver.pGetKeyNameText( lParam, lpBuffer, nSize );
+    return 0;
 }
 
 /****************************************************************************
@@ -814,7 +829,7 @@
 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
 		     LPWSTR lpwStr, int size, UINT flags)
 {
-    return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
+    return ToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, GetKeyboardLayout(0));
 }
 
 /****************************************************************************
@@ -823,24 +838,18 @@
 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
 		       LPWSTR lpwStr, int size, UINT flags, HKL hkl)
 {
-    /* FIXME: need true implementation */
-    return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
+    if (USER_Driver.pToUnicodeEx)
+        return USER_Driver.pToUnicodeEx(virtKey, scanCode, lpKeyState, lpwStr, size, flags, hkl);
+    return 0;
 }
 
 /****************************************************************************
  *		ToAscii (USER32.@)
  */
-INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
-                        LPWORD lpChar,UINT flags )
+INT WINAPI ToAscii( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
+                    LPWORD lpChar, UINT flags )
 {
-    WCHAR uni_chars[2];
-    INT ret, n_ret;
-
-    ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
-    if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
-    else n_ret = ret;
-    WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
-    return ret;
+    return ToAsciiEx(virtKey, scanCode, lpKeyState, lpChar, flags, GetKeyboardLayout(0));
 }
 
 /****************************************************************************
@@ -849,19 +858,25 @@
 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
                       LPWORD lpChar, UINT flags, HKL dwhkl )
 {
-    /* FIXME: need true implementation */
-    return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
+    WCHAR uni_chars[2];
+    INT ret, n_ret;
+
+    ret = ToUnicodeEx(virtKey, scanCode, lpKeyState, uni_chars, 2, flags, dwhkl);
+    if (ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
+    else n_ret = ret;
+    WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
+    return ret;
 }
 
 /**********************************************************************
  *		ActivateKeyboardLayout (USER32.@)
- *
- * Call ignored. WINE supports only system default keyboard layout.
  */
 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
 {
     TRACE_(keyboard)("(%p, %d)\n", hLayout, flags);
-    ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
+
+    if (USER_Driver.pActivateKeyboardLayout)
+        return USER_Driver.pActivateKeyboardLayout(hLayout, flags);
     return 0;
 }
 
@@ -869,21 +884,16 @@
 /***********************************************************************
  *		GetKeyboardLayoutList (USER32.@)
  *
- * FIXME: Supports only the system default language and layout and
- *          returns only 1 value.
- *
  * Return number of values available if either input parm is
  *  0, per MS documentation.
- *
  */
-INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
+UINT WINAPI GetKeyboardLayoutList(INT nBuff, HKL *layouts)
 {
-        TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
-        if (!nBuff || !layouts)
-            return 1;
-	if (layouts)
-		layouts[0] = GetKeyboardLayout(0);
-	return 1;
+    TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
+
+    if (USER_Driver.pGetKeyboardLayoutList)
+        return USER_Driver.pGetKeyboardLayoutList(nBuff, layouts);
+    return 0;
 }
 
 
@@ -905,13 +915,14 @@
 
 /***********************************************************************
  *		LoadKeyboardLayoutW (USER32.@)
- * Call ignored. WINE supports only system default keyboard layout.
  */
 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
 {
     TRACE_(keyboard)("(%s, %d)\n", debugstr_w(pwszKLID), Flags);
-    ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
-  return 0;
+
+    if (USER_Driver.pLoadKeyboardLayout)
+        return USER_Driver.pLoadKeyboardLayout(pwszKLID, Flags);
+    return 0;
 }
 
 /***********************************************************************
@@ -931,6 +942,18 @@
 }
 
 
+/***********************************************************************
+ *		UnloadKeyboardLayout (USER32.@)
+ */
+BOOL WINAPI UnloadKeyboardLayout(HKL hkl)
+{
+    TRACE_(keyboard)("(%p)\n", hkl);
+
+    if (USER_Driver.pUnloadKeyboardLayout)
+        return USER_Driver.pUnloadKeyboardLayout(hkl);
+    return 0;
+}
+
 typedef struct __TRACKINGLIST {
     TRACKMOUSEEVENT tme;
     POINT pos; /* center of hover rectangle */