https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a0bef1998e07c8d75db26eaa5696bbb9a81c596e

commit a0bef1998e07c8d75db26eaa5696bbb9a81c596e
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Wed May 3 07:45:35 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Wed May 3 07:45:35 2023 +0900

    [KBSWITCH] Rely on GetKeyboardLayoutList for getting list (#5263)
    
    - Use GetKeyboardLayoutList to get the keyboard list instead of using 
Preload registry key.
    - Get the special IDs from registry to handle special HKLs in newly-added 
LoadSpecialIds function.
    - Add GetKLIDFromHKL, GetHKLFromLayoutNum, UpdateLayoutList, and 
GetKLIDFromLayoutNum helper functions.
    CORE-13145, CORE-10667, CORE-18924
---
 base/applications/kbswitch/kbswitch.c | 400 ++++++++++++++++++----------------
 1 file changed, 218 insertions(+), 182 deletions(-)

diff --git a/base/applications/kbswitch/kbswitch.c 
b/base/applications/kbswitch/kbswitch.c
index 984e2801bc3..bc9e698774a 100644
--- a/base/applications/kbswitch/kbswitch.c
+++ b/base/applications/kbswitch/kbswitch.c
@@ -26,6 +26,13 @@
  * won't be generated in Vista+.
  */
 
+#define IME_MASK        (0xE0000000UL)
+#define SPECIAL_MASK    (0xF0000000UL)
+
+#define IS_IME_HKL(hKL)             ((((ULONG_PTR)(hKL)) & 0xF0000000) == 
IME_MASK)
+#define IS_SPECIAL_HKL(hKL)         ((((ULONG_PTR)(hKL)) & 0xF0000000) == 
SPECIAL_MASK)
+#define SPECIALIDFROMHKL(hKL)       ((WORD)(HIWORD(hKL) & 0x0FFF))
+
 #define WM_NOTIFYICONMSG (WM_USER + 248)
 
 PKBSWITCHSETHOOKS    KbSwitchSetHooks    = NULL;
@@ -35,52 +42,158 @@ UINT ShellHookMessage = 0;
 HINSTANCE hInst;
 HANDLE    hProcessHeap;
 HMODULE   g_hHookDLL = NULL;
-ULONG     ulCurrentLayoutNum = 1;
+INT       g_nCurrentLayoutNum = 1;
 HICON     g_hTrayIcon = NULL;
 HWND      g_hwndLastActive = NULL;
+INT       g_cKLs = 0;
+HKL       g_ahKLs[64];
 
-static BOOL
-GetLayoutID(LPCTSTR szLayoutNum, LPTSTR szLCID, SIZE_T LCIDLength)
+typedef struct
 {
-    DWORD dwBufLen, dwRes;
-    HKEY hKey;
-    TCHAR szTempLCID[CCH_LAYOUT_ID + 1];
+    DWORD dwLayoutId;
+    HKL hKL;
+    TCHAR szKLID[CCH_LAYOUT_ID + 1];
+} SPECIAL_ID, *PSPECIAL_ID;
+
+SPECIAL_ID g_SpecialIds[80];
+INT g_cSpecialIds = 0;
 
-    /* Get the Layout ID */
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0, 
KEY_QUERY_VALUE,
-                     &hKey) == ERROR_SUCCESS)
+static VOID LoadSpecialIds(VOID)
+{
+    TCHAR szKLID[KL_NAMELENGTH], szLayoutId[16];
+    DWORD dwSize, dwIndex;
+    HKEY hKey, hLayoutKey;
+
+    g_cSpecialIds = 0;
+
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                     TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts"),
+                     0, KEY_READ, &hKey) != ERROR_SUCCESS)
     {
-        dwBufLen = sizeof(szTempLCID);
-        dwRes = RegQueryValueEx(hKey, szLayoutNum, NULL, NULL, 
(LPBYTE)szTempLCID, &dwBufLen);
-        if (dwRes != ERROR_SUCCESS)
+        return;
+    }
+
+    for (dwIndex = 0; dwIndex < 1000; ++dwIndex)
+    {
+        dwSize = ARRAYSIZE(szKLID);
+        if (RegEnumKeyEx(hKey, dwIndex, szKLID, &dwSize, NULL, NULL, NULL, 
NULL) != ERROR_SUCCESS)
+            break;
+
+        if (RegOpenKeyEx(hKey, szKLID, 0, KEY_READ, &hLayoutKey) != 
ERROR_SUCCESS)
+            continue;
+
+        dwSize = sizeof(szLayoutId);
+        if (RegQueryValueEx(hLayoutKey, TEXT("Layout Id"), NULL, NULL,
+                            (LPBYTE)szLayoutId, &dwSize) == ERROR_SUCCESS)
         {
-            RegCloseKey(hKey);
-            return FALSE;
+            DWORD dwKLID = _tcstoul(szKLID, NULL, 16);
+            WORD wLangId = LOWORD(dwKLID), wLayoutId = 
LOWORD(_tcstoul(szLayoutId, NULL, 16));
+            HKL hKL = (HKL)(LONG_PTR)(SPECIAL_MASK | MAKELONG(wLangId, 
wLayoutId));
+
+            /* Add a special ID */
+            g_SpecialIds[g_cSpecialIds].dwLayoutId = wLayoutId;
+            g_SpecialIds[g_cSpecialIds].hKL = hKL;
+            StringCchCopy(g_SpecialIds[g_cSpecialIds].szKLID,
+                          ARRAYSIZE(g_SpecialIds[g_cSpecialIds].szKLID), 
szKLID);
+            ++g_cSpecialIds;
         }
 
-        RegCloseKey(hKey);
+        RegCloseKey(hLayoutKey);
+
+        if (g_cSpecialIds >= ARRAYSIZE(g_SpecialIds))
+        {
+            OutputDebugStringA("g_SpecialIds is full!");
+            break;
+        }
+    }
+
+    RegCloseKey(hKey);
+}
+
+static VOID
+GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
+{
+    szKLID[0] = 0;
+
+    if (IS_IME_HKL(hKL))
+    {
+        StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), 
(DWORD)(DWORD_PTR)hKL);
+        return;
     }
 
-    /* Look for a substitute of this layout */
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Substitutes"), 0,
-                     KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+    if (IS_SPECIAL_HKL(hKL))
     {
-        dwBufLen = sizeof(szTempLCID);
-        if (RegQueryValueEx(hKey, szTempLCID, NULL, NULL, (LPBYTE)szLCID, 
&dwBufLen) != ERROR_SUCCESS)
+        INT i;
+        for (i = 0; i < g_cSpecialIds; ++i)
         {
-            /* No substitute found, then use the old LCID */
-            StringCchCopy(szLCID, LCIDLength, szTempLCID);
+            if (g_SpecialIds[i].hKL == hKL)
+            {
+                StringCchCopy(szKLID, KLIDLength, g_SpecialIds[i].szKLID);
+                return;
+            }
         }
+    }
+    else
+    {
+        StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), LOWORD(hKL));
+    }
+}
 
-        RegCloseKey(hKey);
+static VOID UpdateLayoutList(HKL hKL OPTIONAL)
+{
+    INT iKL;
+
+    if (!hKL)
+    {
+        if (0 <= (g_nCurrentLayoutNum - 1) && (g_nCurrentLayoutNum - 1) < 
g_cKLs)
+        {
+            hKL = g_ahKLs[g_nCurrentLayoutNum - 1];
+        }
+        else
+        {
+            HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : 
GetForegroundWindow());
+            DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
+            hKL = GetKeyboardLayout(dwTID);
+        }
+    }
+
+    g_cKLs = GetKeyboardLayoutList(ARRAYSIZE(g_ahKLs), g_ahKLs);
+
+    g_nCurrentLayoutNum = -1;
+    for (iKL = 0; iKL < g_cKLs; ++iKL)
+    {
+        if (g_ahKLs[iKL] == hKL)
+        {
+            g_nCurrentLayoutNum = iKL + 1;
+            break;
+        }
+    }
+
+    if (g_nCurrentLayoutNum == -1 && g_cKLs < ARRAYSIZE(g_ahKLs))
+    {
+        g_nCurrentLayoutNum = g_cKLs;
+        g_ahKLs[g_cKLs++] = hKL;
+    }
+}
+
+static HKL GetHKLFromLayoutNum(INT nLayoutNum)
+{
+    if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs)
+    {
+        return g_ahKLs[nLayoutNum - 1];
     }
     else
     {
-        /* Substitutes key couldn't be opened, so use the old LCID */
-        StringCchCopy(szLCID, LCIDLength, szTempLCID);
+        HWND hwndTarget = (g_hwndLastActive ? g_hwndLastActive : 
GetForegroundWindow());
+        DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
+        return GetKeyboardLayout(dwTID);
     }
+}
 
-    return TRUE;
+static VOID
+GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
+{
+    GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength);
 }
 
 static BOOL
@@ -95,21 +208,19 @@ GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, 
LPCTSTR FileName)
 }
 
 static BOOL
-GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T NameLength)
+GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
 {
     HKEY hKey;
     HRESULT hr;
     DWORD dwBufLen;
-    TCHAR szBuf[MAX_PATH];
-    TCHAR szLCID[CCH_LAYOUT_ID + 1];
+    TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
 
-    if (!GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID)))
-        return FALSE;
+    GetKLIDFromLayoutNum(nLayoutNum, szKLID, ARRAYSIZE(szKLID));
 
     StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
-                    _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts\\%s"), szLCID);
+                    _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts\\%s"), szKLID);
 
-    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != 
ERROR_SUCCESS)
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_READ, &hKey) != 
ERROR_SUCCESS)
         return FALSE;
 
     /* Use "Layout Display Name" value as an entry name if possible */
@@ -123,17 +234,17 @@ GetLayoutName(LPCTSTR szLayoutNum, LPTSTR szName, SIZE_T 
NameLength)
     /* Otherwise, use "Layout Text" value as an entry name */
     dwBufLen = NameLength * sizeof(TCHAR);
     if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
-                        (LPBYTE)szName, &dwBufLen) != ERROR_SUCCESS)
+                        (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
     {
         RegCloseKey(hKey);
-        return FALSE;
+        return TRUE;
     }
 
     RegCloseKey(hKey);
-    return TRUE;
+    return FALSE;
 }
 
-static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szLCID)
+static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
 {
     HKEY hKey;
     DWORD dwBufLen;
@@ -141,19 +252,17 @@ static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T 
cchImeFile, LPCTSTR szLCID)
 
     szImeFile[0] = UNICODE_NULL;
 
-    if (_tcslen(szLCID) != CCH_LAYOUT_ID)
+    if (_tcslen(szKLID) != CCH_LAYOUT_ID)
         return FALSE; /* Invalid LCID */
 
-    if (szLCID[0] != TEXT('E') && szLCID[0] != TEXT('e'))
+    if (szKLID[0] != TEXT('E') && szKLID[0] != TEXT('e'))
         return FALSE; /* Not an IME HKL */
 
     StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
-                    _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts\\%s"), szLCID);
+                    _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard 
Layouts\\%s"), szKLID);
 
     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, KEY_QUERY_VALUE, &hKey) != 
ERROR_SUCCESS)
-    {
         return FALSE;
-    }
 
     dwBufLen = cchImeFile * sizeof(TCHAR);
     if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
@@ -223,7 +332,7 @@ static HBITMAP BitmapFromIcon(HICON hIcon)
 }
 
 static HICON
-CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
+CreateTrayIcon(LPTSTR szKLID, LPCTSTR szImeFile OPTIONAL)
 {
     LANGID LangID;
     TCHAR szBuf[4];
@@ -245,7 +354,7 @@ CreateTrayIcon(LPTSTR szLCID, LPCTSTR szImeFile OPTIONAL)
     }
 
     /* Getting "EN", "FR", etc. from English, French, ... */
-    LangID = LANGIDFROMLCID(_tcstoul(szLCID, NULL, 16));
+    LangID = LANGIDFROMLCID(_tcstoul(szKLID, NULL, 16));
     if (GetLocaleInfo(LangID,
                       LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
                       szBuf,
@@ -323,15 +432,14 @@ static VOID
 AddTrayIcon(HWND hwnd)
 {
     NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | 
NIF_TIP };
-    TCHAR szLCID[CCH_LAYOUT_ID + 1], szName[MAX_PATH];
-    TCHAR szImeFile[80];
+    TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
 
-    GetLayoutID(_T("1"), szLCID, ARRAYSIZE(szLCID));
-    GetLayoutName(_T("1"), szName, ARRAYSIZE(szName));
-    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
+    GetKLIDFromLayoutNum(g_nCurrentLayoutNum, szKLID, ARRAYSIZE(szKLID));
+    GetLayoutName(g_nCurrentLayoutNum, szName, ARRAYSIZE(szName));
+    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
 
     tnid.uCallbackMessage = WM_NOTIFYICONMSG;
-    tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
+    tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
     StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
 
     Shell_NotifyIcon(NIM_ADD, &tnid);
@@ -355,15 +463,15 @@ DeleteTrayIcon(HWND hwnd)
 }
 
 static VOID
-UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
+UpdateTrayIcon(HWND hwnd, LPTSTR szKLID, LPTSTR szName)
 {
     NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | 
NIF_TIP };
     TCHAR szImeFile[80];
 
-    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
+    GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
 
     tnid.uCallbackMessage = WM_NOTIFYICONMSG;
-    tnid.hIcon = CreateTrayIcon(szLCID, szImeFile);
+    tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
     StringCchCopy(tnid.szTip, ARRAYSIZE(tnid.szTip), szName);
 
     Shell_NotifyIcon(NIM_MODIFY, &tnid);
@@ -373,12 +481,6 @@ UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
     g_hTrayIcon = tnid.hIcon;
 }
 
-static VOID
-GetLayoutIDByHkl(HKL hKl, LPTSTR szLayoutID, SIZE_T LayoutIDLength)
-{
-    StringCchPrintf(szLayoutID, LayoutIDLength, _T("%08lx"), 
(DWORD)(DWORD_PTR)(hKl));
-}
-
 static BOOL CALLBACK
 EnumWindowsProc(HWND hwnd, LPARAM lParam)
 {
@@ -390,25 +492,24 @@ static VOID
 ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL 
bNoActivate)
 {
     HKL hKl;
-    TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLCID[CCH_LAYOUT_ID + 1], 
szLangName[MAX_PATH];
+    TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
     LANGID LangID;
 
     /* The layout number starts from one. Zero is invalid */
     if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
         return;
 
-    _ultot(uLayoutNum, szLayoutNum, 10);
-    GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
-    LangID = (LANGID)_tcstoul(szLCID, NULL, 16);
+    GetKLIDFromLayoutNum(uLayoutNum, szKLID, ARRAYSIZE(szKLID));
+    LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
 
     /* Switch to the new keyboard layout */
     GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
-    UpdateTrayIcon(hwnd, szLCID, szLangName);
+    UpdateTrayIcon(hwnd, szKLID, szLangName);
 
     if (hwndTarget && !bNoActivate)
         SetForegroundWindow(hwndTarget);
 
-    hKl = LoadKeyboardLayout(szLCID, KLF_ACTIVATE);
+    hKl = LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
     if (hKl)
         ActivateKeyboardLayout(hKl, KLF_SETFORPROCESS);
 
@@ -423,95 +524,45 @@ ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND 
hwndTarget OPTIONAL, BOOL bNoAc
         EnumWindows(EnumWindowsProc, (LPARAM) hKl);
     }
 
-    ulCurrentLayoutNum = uLayoutNum;
+    g_nCurrentLayoutNum = uLayoutNum;
 }
 
 static HMENU
 BuildLeftPopupMenu(VOID)
 {
     HMENU hMenu = CreatePopupMenu();
-    HKEY hKey;
-    DWORD dwIndex, dwSize;
-    TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szName[MAX_PATH];
-    TCHAR szLCID[CCH_LAYOUT_ID + 1], szImeFile[80];
+    TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
     HICON hIcon;
     MENUITEMINFO mii = { sizeof(mii) };
+    INT iKL;
 
-    /* Add the keyboard layouts to the popup menu */
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0,
-                     KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+    for (iKL = 0; iKL < g_cKLs; ++iKL)
     {
-        for (dwIndex = 0; ; dwIndex++)
-        {
-            dwSize = sizeof(szLayoutNum);
-            if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL,
-                             NULL, NULL) != ERROR_SUCCESS)
-            {
-                break;
-            }
+        GetKLIDFromHKL(g_ahKLs[iKL], szKLID, ARRAYSIZE(szKLID));
+        GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
 
-            GetLayoutID(szLayoutNum, szLCID, ARRAYSIZE(szLCID));
-            GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szLCID);
+        if (!GetLayoutName(iKL + 1, szName, ARRAYSIZE(szName)))
+            continue;
 
-            if (!GetLayoutName(szLayoutNum, szName, ARRAYSIZE(szName)))
-                continue;
-
-            mii.fMask       = MIIM_ID | MIIM_STRING;
-            mii.wID         = _ttoi(szLayoutNum);
-            mii.dwTypeData  = szName;
-
-            hIcon = CreateTrayIcon(szLCID, szImeFile);
-            if (hIcon)
-            {
-                mii.hbmpItem = BitmapFromIcon(hIcon);
-                if (mii.hbmpItem)
-                    mii.fMask |= MIIM_BITMAP;
-            }
-
-            InsertMenuItem(hMenu, -1, TRUE, &mii);
-            DestroyIcon(hIcon);
-        }
-
-        CheckMenuItem(hMenu, ulCurrentLayoutNum, MF_CHECKED);
-
-        RegCloseKey(hKey);
-    }
-
-    return hMenu;
-}
-
-static ULONG
-GetMaxLayoutNum(VOID)
-{
-    HKEY hKey;
-    ULONG dwIndex, dwSize, uLayoutNum, uMaxLayoutNum = 0;
-    TCHAR szLayoutNum[CCH_ULONG_DEC + 1], szLayoutID[CCH_LAYOUT_ID + 1];
+        mii.fMask       = MIIM_ID | MIIM_STRING;
+        mii.wID         = iKL + 1;
+        mii.dwTypeData  = szName;
 
-    /* Get the maximum layout number in the Preload key */
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Keyboard Layout\\Preload"), 0,
-                     KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
-    {
-        for (dwIndex = 0; ; dwIndex++)
+        hIcon = CreateTrayIcon(szKLID, szImeFile);
+        if (hIcon)
         {
-            dwSize = sizeof(szLayoutNum);
-            if (RegEnumValue(hKey, dwIndex, szLayoutNum, &dwSize, NULL, NULL,
-                             NULL, NULL) != ERROR_SUCCESS)
-            {
-                break;
-            }
-
-            if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
-            {
-                uLayoutNum = _ttoi(szLayoutNum);
-                if (uMaxLayoutNum < uLayoutNum)
-                    uMaxLayoutNum = uLayoutNum;
-            }
+            mii.hbmpItem = BitmapFromIcon(hIcon);
+            if (mii.hbmpItem)
+                mii.fMask |= MIIM_BITMAP;
         }
 
-        RegCloseKey(hKey);
+        InsertMenuItem(hMenu, -1, TRUE, &mii);
+        DestroyIcon(hIcon);
     }
 
-    return uMaxLayoutNum;
+    CheckMenuItem(hMenu, g_nCurrentLayoutNum, MF_CHECKED);
+
+    return hMenu;
 }
 
 BOOL
@@ -549,37 +600,36 @@ DeleteHooks(VOID)
     }
 }
 
-ULONG
-GetNextLayout(VOID)
+static UINT GetLayoutNum(HKL hKL)
 {
-    TCHAR szLayoutNum[3 + 1], szLayoutID[CCH_LAYOUT_ID + 1];
-    ULONG uLayoutNum, uMaxNum = GetMaxLayoutNum();
+    INT iKL;
 
-    for (uLayoutNum = ulCurrentLayoutNum + 1; ; ++uLayoutNum)
+    for (iKL = 0; iKL < g_cKLs; ++iKL)
     {
-        if (uLayoutNum > uMaxNum)
-            uLayoutNum = 1;
-        if (uLayoutNum == ulCurrentLayoutNum)
-            break;
-
-        _ultot(uLayoutNum, szLayoutNum, 10);
-        if (GetLayoutID(szLayoutNum, szLayoutID, ARRAYSIZE(szLayoutID)))
-            return uLayoutNum;
+        if (g_ahKLs[iKL] == hKL)
+            return iKL + 1;
     }
 
-    return ulCurrentLayoutNum;
+    return 0;
+}
+
+ULONG
+GetNextLayout(VOID)
+{
+    return (g_nCurrentLayoutNum % g_cKLs) + 1;
 }
 
 UINT
-UpdateLanguageDisplay(HWND hwnd, HKL hKl)
+UpdateLanguageDisplay(HWND hwnd, HKL hKL)
 {
-    TCHAR szLCID[MAX_PATH], szLangName[MAX_PATH];
+    TCHAR szKLID[MAX_PATH], szLangName[MAX_PATH];
     LANGID LangID;
 
-    GetLayoutIDByHkl(hKl, szLCID, ARRAYSIZE(szLCID));
-    LangID = (LANGID)_tcstoul(szLCID, NULL, 16);
+    GetKLIDFromHKL(hKL, szKLID, ARRAYSIZE(szKLID));
+    LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
     GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
-    UpdateTrayIcon(hwnd, szLCID, szLangName);
+    UpdateTrayIcon(hwnd, szKLID, szLangName);
+    g_nCurrentLayoutNum = GetLayoutNum(hKL);
 
     return 0;
 }
@@ -611,21 +661,6 @@ UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
     return 0;
 }
 
-static UINT GetCurLayoutNum(HKL hKL)
-{
-    UINT i, nCount;
-    HKL ahKL[256];
-
-    nCount = GetKeyboardLayoutList(ARRAYSIZE(ahKL), ahKL);
-    for (i = 0; i < nCount; ++i)
-    {
-        if (ahKL[i] == hKL)
-            return i + 1;
-    }
-
-    return 0;
-}
-
 static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
 {
     TCHAR szClass[64];
@@ -641,8 +676,7 @@ static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
         return FALSE; /* Special window */
     }
 
-    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
-              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't work yet */
+    /* FIXME: CONWND needs special handling */
     if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
     {
         HKL hKL = GetKeyboardLayout(0);
@@ -671,15 +705,19 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
                 return -1;
             }
 
+            LoadSpecialIds();
+
+            UpdateLayoutList(NULL);
             AddTrayIcon(hwnd);
 
-            ActivateLayout(hwnd, ulCurrentLayoutNum, NULL, TRUE);
+            ActivateLayout(hwnd, g_nCurrentLayoutNum, NULL, TRUE);
             s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
             break;
         }
 
         case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
         {
+            UpdateLayoutList((HKL)lParam);
             UpdateLanguageDisplay(hwnd, (HKL)lParam);
             break;
         }
@@ -757,8 +795,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
                     if (hwndTarget == NULL)
                         hwndTarget = g_hwndLastActive;
 
-                    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
-                              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't 
work yet */
+                    /* FIXME: CONWND needs special handling */
                     if (hwndTarget &&
                         GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) 
&&
                         _tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
@@ -772,19 +809,17 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
                     {
                         dwThreadID = GetWindowThreadProcessId(hwndTarget, 
NULL);
                         hKL = GetKeyboardLayout(dwThreadID);
-                        uNum = GetCurLayoutNum(hKL);
+                        uNum = GetLayoutNum(hKL);
                         if (uNum != 0)
-                            ulCurrentLayoutNum = uNum;
+                            g_nCurrentLayoutNum = uNum;
                     }
 
                     ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
 
-                    /* FIXME: CONWND is multithreaded but KLF_SETFORPROCESS and
-                              DefWindowProc.WM_INPUTLANGCHANGEREQUEST won't 
work yet */
+                    /* FIXME: CONWND needs special handling */
                     if (bCONWND)
-                    {
-                        ActivateLayout(hwnd, ulCurrentLayoutNum, 
hwndTargetSave, TRUE);
-                    }
+                        ActivateLayout(hwnd, g_nCurrentLayoutNum, 
hwndTargetSave, TRUE);
+
                     break;
                 }
 
@@ -826,6 +861,7 @@ WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM 
lParam)
         {
             if (Message == s_uTaskbarRestart)
             {
+                UpdateLayoutList(NULL);
                 AddTrayIcon(hwnd);
                 break;
             }

Reply via email to