ReactOS 0.4.15-dev-7670-g69b08be
kbswitch.c
Go to the documentation of this file.
1/*
2 * PROJECT: Keyboard Layout Switcher
3 * FILE: base/applications/kbswitch/kbswitch.c
4 * PURPOSE: Switching Keyboard Layouts
5 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
6 * Colin Finck (mail@colinfinck.de)
7 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8 */
9
10#include "kbswitch.h"
11#include <shlobj.h>
12#include <shlwapi_undoc.h>
13#include <imm.h>
14
15/*
16 * This program kbswitch is a mimic of Win2k's internat.exe.
17 * However, there are some differences.
18 *
19 * Comparing with WinNT4 ActivateKeyboardLayout, WinXP ActivateKeyboardLayout has
20 * process boundary, so we cannot activate the IME keyboard layout from the outer process.
21 * It needs special care.
22 *
23 * We use global hook by our kbsdll.dll, to watch the shell and the windows.
24 *
25 * It might not work correctly on Vista+ because keyboard layout change notification
26 * won't be generated in Vista+.
27 */
28
29#define IME_MASK (0xE0000000UL)
30#define SPECIAL_MASK (0xF0000000UL)
31
32#define IS_IME_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == IME_MASK)
33#define IS_SPECIAL_HKL(hKL) ((((ULONG_PTR)(hKL)) & 0xF0000000) == SPECIAL_MASK)
34#define SPECIALIDFROMHKL(hKL) ((WORD)(HIWORD(hKL) & 0x0FFF))
35
36#define WM_NOTIFYICONMSG (WM_USER + 248)
37
41
50
51typedef struct
52{
55 TCHAR szKLID[CCH_LAYOUT_ID + 1];
57
60
62{
63 TCHAR szKLID[KL_NAMELENGTH], szLayoutId[16];
64 DWORD dwSize, dwIndex;
65 HKEY hKey, hLayoutKey;
66
67 g_cSpecialIds = 0;
68
70 TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"),
72 {
73 return;
74 }
75
76 for (dwIndex = 0; dwIndex < 1000; ++dwIndex)
77 {
78 dwSize = ARRAYSIZE(szKLID);
79 if (RegEnumKeyEx(hKey, dwIndex, szKLID, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
80 break;
81
82 if (RegOpenKeyEx(hKey, szKLID, 0, KEY_READ, &hLayoutKey) != ERROR_SUCCESS)
83 continue;
84
85 dwSize = sizeof(szLayoutId);
86 if (RegQueryValueEx(hLayoutKey, TEXT("Layout Id"), NULL, NULL,
87 (LPBYTE)szLayoutId, &dwSize) == ERROR_SUCCESS)
88 {
89 DWORD dwKLID = _tcstoul(szKLID, NULL, 16);
90 WORD wLangId = LOWORD(dwKLID), wLayoutId = LOWORD(_tcstoul(szLayoutId, NULL, 16));
91 HKL hKL = (HKL)(LONG_PTR)(SPECIAL_MASK | MAKELONG(wLangId, wLayoutId));
92
93 /* Add a special ID */
97 ARRAYSIZE(g_SpecialIds[g_cSpecialIds].szKLID), szKLID);
99 }
100
101 RegCloseKey(hLayoutKey);
102
104 {
105 OutputDebugStringA("g_SpecialIds is full!");
106 break;
107 }
108 }
109
111}
112
113static VOID
114GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
115{
116 szKLID[0] = 0;
117
118 if (IS_IME_HKL(hKL))
119 {
120 StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), (DWORD)(DWORD_PTR)hKL);
121 return;
122 }
123
124 if (IS_SPECIAL_HKL(hKL))
125 {
126 INT i;
127 for (i = 0; i < g_cSpecialIds; ++i)
128 {
129 if (g_SpecialIds[i].hKL == hKL)
130 {
131 StringCchCopy(szKLID, KLIDLength, g_SpecialIds[i].szKLID);
132 return;
133 }
134 }
135 }
136 else
137 {
138 StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), LOWORD(hKL));
139 }
140}
141
143{
144 INT iKL;
145
146 if (!hKL)
147 {
149 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
150 hKL = GetKeyboardLayout(dwTID);
151 }
152
154
156 for (iKL = 0; iKL < g_cKLs; ++iKL)
157 {
158 if (g_ahKLs[iKL] == hKL)
159 {
160 g_nCurrentLayoutNum = iKL + 1;
161 break;
162 }
163 }
164
166 {
168 g_ahKLs[g_cKLs++] = hKL;
169 }
170}
171
172static HKL GetHKLFromLayoutNum(INT nLayoutNum)
173{
174 if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs)
175 {
176 return g_ahKLs[nLayoutNum - 1];
177 }
178 else
179 {
181 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
182 return GetKeyboardLayout(dwTID);
183 }
184}
185
186static VOID
187GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
188{
189 GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength);
190}
191
192static BOOL
194{
195 if (!GetSystemDirectory(szPath, cchPath))
196 return FALSE;
197
198 StringCchCat(szPath, cchPath, TEXT("\\"));
199 StringCchCat(szPath, cchPath, FileName);
200 return TRUE;
201}
202
203static BOOL
204GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
205{
206 HKEY hKey;
207 HRESULT hr;
209 TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
210
211 GetKLIDFromLayoutNum(nLayoutNum, szKLID, ARRAYSIZE(szKLID));
212
213 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
214 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
215
217 return FALSE;
218
219 /* Use "Layout Display Name" value as an entry name if possible */
220 hr = SHLoadRegUIString(hKey, _T("Layout Display Name"), szName, NameLength);
221 if (SUCCEEDED(hr))
222 {
224 return TRUE;
225 }
226
227 /* Otherwise, use "Layout Text" value as an entry name */
228 dwBufLen = NameLength * sizeof(TCHAR);
229 if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
231 {
233 return TRUE;
234 }
235
237 return FALSE;
238}
239
240static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
241{
242 HKEY hKey;
244 TCHAR szBuf[MAX_PATH];
245
246 szImeFile[0] = UNICODE_NULL;
247
248 if (_tcslen(szKLID) != CCH_LAYOUT_ID)
249 return FALSE; /* Invalid LCID */
250
251 if (szKLID[0] != TEXT('E') && szKLID[0] != TEXT('e'))
252 return FALSE; /* Not an IME HKL */
253
254 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
255 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
256
258 return FALSE;
259
260 dwBufLen = cchImeFile * sizeof(TCHAR);
261 if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
262 (LPBYTE)szImeFile, &dwBufLen) != ERROR_SUCCESS)
263 {
264 szImeFile[0] = UNICODE_NULL;
265 }
266
268
269 return (szImeFile[0] != UNICODE_NULL);
270}
271
272typedef struct tagLOAD_ICON
273{
277
278static BOOL CALLBACK
281 LPCTSTR lpszType,
282 LPTSTR lpszName,
284{
285 PLOAD_ICON pLoadIcon = (PLOAD_ICON)lParam;
286 pLoadIcon->hIcon = (HICON)LoadImage(hModule, lpszName, IMAGE_ICON,
287 pLoadIcon->cxIcon, pLoadIcon->cyIcon,
289 if (pLoadIcon->hIcon)
290 return FALSE; /* Stop enumeration */
291 return TRUE;
292}
293
294static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
295{
296 LOAD_ICON LoadIcon = { cxIcon, cyIcon, NULL };
297 HMODULE hImeDLL = LoadLibraryEx(szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
298 if (hImeDLL)
299 {
301 FreeLibrary(hImeDLL);
302 }
303 return LoadIcon.hIcon;
304}
305
307{
308 HDC hdcScreen = GetDC(NULL);
309 HDC hdc = CreateCompatibleDC(hdcScreen);
312 HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
313 HGDIOBJ hbmOld;
314
315 if (hbm != NULL)
316 {
317 hbmOld = SelectObject(hdc, hbm);
318 DrawIconEx(hdc, 0, 0, hIcon, cxIcon, cyIcon, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
319 SelectObject(hdc, hbmOld);
320 }
321
322 DeleteDC(hdc);
323 ReleaseDC(NULL, hdcScreen);
324 return hbm;
325}
326
327static HICON
329{
331 TCHAR szBuf[4];
332 HDC hdcScreen, hdc;
333 HBITMAP hbmColor, hbmMono, hBmpOld;
334 HFONT hFont, hFontOld;
335 LOGFONT lf;
336 RECT rect;
338 HICON hIcon;
342
343 if (szImeFile && szImeFile[0])
344 {
346 return FakeExtractIcon(szPath, cxIcon, cyIcon);
347 }
348
349 /* Getting "EN", "FR", etc. from English, French, ... */
350 LangID = LANGIDFROMLCID(_tcstoul(szKLID, NULL, 16));
353 szBuf,
354 ARRAYSIZE(szBuf)) == 0)
355 {
356 szBuf[0] = szBuf[1] = _T('?');
357 }
358 szBuf[2] = 0; /* Truncate the identifier to two characters: "ENG" --> "EN" etc. */
359
360 /* Create hdc, hbmColor and hbmMono */
361 hdcScreen = GetDC(NULL);
362 hdc = CreateCompatibleDC(hdcScreen);
363 hbmColor = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
364 ReleaseDC(NULL, hdcScreen);
365 hbmMono = CreateBitmap(cxIcon, cyIcon, 1, 1, NULL);
366
367 /* Checking NULL */
368 if (!hdc || !hbmColor || !hbmMono)
369 {
370 if (hbmMono)
371 DeleteObject(hbmMono);
372 if (hbmColor)
373 DeleteObject(hbmColor);
374 if (hdc)
375 DeleteDC(hdc);
376 return NULL;
377 }
378
379 /* Create a font */
380 hFont = NULL;
381 if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
382 {
383 /* Override the current size with something manageable */
384 lf.lfHeight = -11;
385 lf.lfWidth = 0;
387 }
388 if (!hFont)
390
391 SetRect(&rect, 0, 0, cxIcon, cyIcon);
392
393 /* Draw hbmColor */
394 hBmpOld = SelectObject(hdc, hbmColor);
396 FillRect(hdc, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
397 hFontOld = SelectObject(hdc, hFont);
401 SelectObject(hdc, hFontOld);
402
403 /* Fill hbmMono with black */
404 SelectObject(hdc, hbmMono);
405 PatBlt(hdc, 0, 0, cxIcon, cyIcon, BLACKNESS);
406 SelectObject(hdc, hBmpOld);
407
408 /* Create an icon from hbmColor and hbmMono */
411 IconInfo.hbmColor = hbmColor;
412 IconInfo.hbmMask = hbmMono;
414
415 /* Clean up */
417 DeleteObject(hbmMono);
418 DeleteObject(hbmColor);
419 DeleteDC(hdc);
420
421 return hIcon;
422}
423
424static VOID
426{
427 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
428 TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
429
432 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
433
435 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
437
439
440 if (g_hTrayIcon)
442 g_hTrayIcon = tnid.hIcon;
443}
444
445static VOID
447{
448 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1 };
450
451 if (g_hTrayIcon)
452 {
455 }
456}
457
458static VOID
460{
461 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
462 TCHAR szImeFile[80];
463
464 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
465
467 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
469
471
472 if (g_hTrayIcon)
474 g_hTrayIcon = tnid.hIcon;
475}
476
477static BOOL CALLBACK
479{
480 PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, lParam);
481 return TRUE;
482}
483
484static VOID
485ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
486{
487 HKL hKl;
488 TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
490
491 /* The layout number starts from one. Zero is invalid */
492 if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
493 return;
494
495 GetKLIDFromLayoutNum(uLayoutNum, szKLID, ARRAYSIZE(szKLID));
496 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
497
498 /* Switch to the new keyboard layout */
499 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
500 UpdateTrayIcon(hwnd, szKLID, szLangName);
501
502 if (hwndTarget && !bNoActivate)
503 SetForegroundWindow(hwndTarget);
504
505 hKl = LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
506 if (hKl)
508
509 /* Post WM_INPUTLANGCHANGEREQUEST */
510 if (hwndTarget)
511 {
512 PostMessage(hwndTarget, WM_INPUTLANGCHANGEREQUEST,
513 INPUTLANGCHANGE_SYSCHARSET, (LPARAM)hKl);
514 }
515 else
516 {
518 }
519
520 g_nCurrentLayoutNum = uLayoutNum;
521}
522
523static HMENU
525{
526 HMENU hMenu = CreatePopupMenu();
527 TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
528 HICON hIcon;
529 MENUITEMINFO mii = { sizeof(mii) };
530 INT iKL;
531
532 for (iKL = 0; iKL < g_cKLs; ++iKL)
533 {
534 GetKLIDFromHKL(g_ahKLs[iKL], szKLID, ARRAYSIZE(szKLID));
535 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
536
537 if (!GetLayoutName(iKL + 1, szName, ARRAYSIZE(szName)))
538 continue;
539
540 mii.fMask = MIIM_ID | MIIM_STRING;
541 mii.wID = iKL + 1;
542 mii.dwTypeData = szName;
543
544 hIcon = CreateTrayIcon(szKLID, szImeFile);
545 if (hIcon)
546 {
547 mii.hbmpItem = BitmapFromIcon(hIcon);
548 if (mii.hbmpItem)
549 mii.fMask |= MIIM_BITMAP;
550 }
551
552 InsertMenuItem(hMenu, -1, TRUE, &mii);
554 }
555
557
558 return hMenu;
559}
560
561BOOL
563{
564 g_hHookDLL = LoadLibrary(_T("kbsdll.dll"));
565 if (!g_hHookDLL)
566 {
567 return FALSE;
568 }
569
572
574 {
575 return FALSE;
576 }
577
578 return KbSwitchSetHooks();
579}
580
581VOID
583{
585 {
588 }
589 if (g_hHookDLL)
590 {
593 }
594}
595
597{
598 INT iKL;
599
600 for (iKL = 0; iKL < g_cKLs; ++iKL)
601 {
602 if (g_ahKLs[iKL] == hKL)
603 return iKL + 1;
604 }
605
606 return 0;
607}
608
609ULONG
611{
612 return (g_nCurrentLayoutNum % g_cKLs) + 1;
613}
614
615UINT
617{
618 TCHAR szKLID[MAX_PATH], szLangName[MAX_PATH];
620
621 GetKLIDFromHKL(hKL, szKLID, ARRAYSIZE(szKLID));
622 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
623 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
624 UpdateTrayIcon(hwnd, szKLID, szLangName);
626
627 return 0;
628}
629
630HWND
632{
633 TCHAR szClass[64];
634 HWND hwndIME;
635 HWND hwndTarget = hwndFore;
636 if (hwndTarget == NULL)
637 hwndTarget = GetForegroundWindow();
638
639 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass));
640 if (_tcsicmp(szClass, szKbSwitcherName) == 0)
641 hwndTarget = g_hwndLastActive;
642
643 hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
644 return (hwndIME ? hwndIME : hwndTarget);
645}
646
647UINT
649{
650 DWORD dwThreadID = GetWindowThreadProcessId(GetTargetWindow(hwndFore), NULL);
651 HKL hKL = GetKeyboardLayout(dwThreadID);
653
654 return 0;
655}
656
658{
659 TCHAR szClass[64];
660
661 hwndFore = GetAncestor(hwndFore, GA_ROOT);
662
663 if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, ARRAYSIZE(szClass)))
664 return FALSE;
665
666 if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
667 _tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
668 {
669 return FALSE; /* Special window */
670 }
671
672 /* FIXME: CONWND needs special handling */
673 if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
674 {
675 HKL hKL = GetKeyboardLayout(0);
677 }
678
679 g_hwndLastActive = hwndFore;
680 return TRUE;
681}
682
685{
686 static HMENU s_hMenu = NULL, s_hRightPopupMenu = NULL;
687 static UINT s_uTaskbarRestart;
688 POINT pt;
689 HMENU hLeftPopupMenu;
690
691 switch (Message)
692 {
693 case WM_CREATE:
694 {
695 if (!SetHooks())
696 {
697 MessageBox(NULL, TEXT("SetHooks failed."), NULL, MB_ICONERROR);
698 return -1;
699 }
700
702
705
707 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
708 break;
709 }
710
711 case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
712 {
715 break;
716 }
717
718 case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
719 {
720 HWND hwndFore = GetForegroundWindow();
721 if (RememberLastActive(hwnd, hwndFore))
722 return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
723 break;
724 }
725
726 case WM_NOTIFYICONMSG:
727 {
728 switch (lParam)
729 {
730 case WM_RBUTTONUP:
731 case WM_LBUTTONUP:
732 {
734
737
738 if (lParam == WM_LBUTTONUP)
739 {
740 /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
741 hLeftPopupMenu = BuildLeftPopupMenu();
742 TrackPopupMenu(hLeftPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
743 DestroyMenu(hLeftPopupMenu);
744 }
745 else
746 {
747 if (!s_hRightPopupMenu)
748 {
750 s_hRightPopupMenu = GetSubMenu(s_hMenu, 0);
751 }
752 TrackPopupMenu(s_hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
753 }
754
755 PostMessage(hwnd, WM_NULL, 0, 0);
756 break;
757 }
758 }
759 break;
760 }
761
762 case WM_COMMAND:
763 switch (LOWORD(wParam))
764 {
765 case ID_EXIT:
766 {
767 PostMessage(hwnd, WM_CLOSE, 0, 0);
768 break;
769 }
770
771 case ID_PREFERENCES:
772 {
774 TEXT("control.exe"), TEXT("input.dll"),
776 if (ret <= 32)
777 MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_ICONERROR);
778 break;
779 }
780
781 case ID_NEXTLAYOUT:
782 {
783 HWND hwndTarget = (HWND)lParam, hwndTargetSave = NULL;
784 DWORD dwThreadID;
785 HKL hKL;
786 UINT uNum;
787 TCHAR szClass[64];
788 BOOL bCONWND = FALSE;
789
790 if (hwndTarget == NULL)
791 hwndTarget = g_hwndLastActive;
792
793 /* FIXME: CONWND needs special handling */
794 if (hwndTarget &&
795 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
796 _tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
797 {
798 bCONWND = TRUE;
799 hwndTargetSave = hwndTarget;
800 hwndTarget = NULL;
801 }
802
803 if (hwndTarget)
804 {
805 dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
806 hKL = GetKeyboardLayout(dwThreadID);
807 uNum = GetLayoutNum(hKL);
808 if (uNum != 0)
809 g_nCurrentLayoutNum = uNum;
810 }
811
812 ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
813
814 /* FIXME: CONWND needs special handling */
815 if (bCONWND)
816 ActivateLayout(hwnd, g_nCurrentLayoutNum, hwndTargetSave, TRUE);
817
818 break;
819 }
820
821 default:
822 {
823 if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
824 {
826 {
828 }
830 }
831 break;
832 }
833 }
834 break;
835
836 case WM_SETTINGCHANGE:
837 {
838 if (wParam == SPI_SETNONCLIENTMETRICS)
839 {
841 break;
842 }
843 }
844 break;
845
846 case WM_DESTROY:
847 {
848 DeleteHooks();
849 DestroyMenu(s_hMenu);
852 break;
853 }
854
855 default:
856 {
857 if (Message == s_uTaskbarRestart)
858 {
861 break;
862 }
863 else if (Message == ShellHookMessage)
864 {
865 if (wParam == HSHELL_LANGUAGE)
867 else if (wParam == HSHELL_WINDOWACTIVATED)
869
870 break;
871 }
873 }
874 }
875
876 return 0;
877}
878
880_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
881{
883 MSG msg;
885 HWND hwnd;
886
887 switch (GetUserDefaultUILanguage())
888 {
891 break;
892 default:
893 break;
894 }
895
897 if (!hMutex)
898 return 1;
899
901 {
903 return 1;
904 }
905
908
909 ZeroMemory(&WndClass, sizeof(WndClass));
910 WndClass.lpfnWndProc = WndProc;
911 WndClass.hInstance = hInstance;
912 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
913 WndClass.lpszClassName = szKbSwitcherName;
914 if (!RegisterClass(&WndClass))
915 {
917 return 1;
918 }
919
923
924 while (GetMessage(&msg, NULL, 0, 0))
925 {
928 }
929
931 return 0;
932}
#define msg(x)
Definition: auth_time.c:54
#define ID_NEXTLAYOUT
Definition: resource.h:12
#define ID_EXIT
Definition: resource.h:10
#define ID_PREFERENCES
Definition: resource.h:11
#define IDR_POPUP
Definition: resource.h:7
HFONT hFont
Definition: main.c:53
#define RegCloseKey(hKey)
Definition: registry.h:49
WCHAR WndClass[]
Definition: capicon.c:23
HINSTANCE hInstance
Definition: charmap.c:19
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
HMODULE hModule
Definition: animate.c:44
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
HANDLE HWND
Definition: compat.h:19
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
Definition: ime.c:890
static const WCHAR Message[]
Definition: register.c:74
#define pt(x, y)
Definition: drawing.c:79
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxAutoRegKey hKey
pKey DeleteObject()
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
Definition: ignoredbgout.c:18
#define _tcstoul
Definition: tchar.h:595
#define _tWinMain
Definition: tchar.h:498
_Out_opt_ PICONINFO IconInfo
Definition: ntuser.h:2294
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define TEXT(s)
Definition: k32.h:26
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
Definition: kbswitch.c:478
static VOID LoadSpecialIds(VOID)
Definition: kbswitch.c:61
static HBITMAP BitmapFromIcon(HICON hIcon)
Definition: kbswitch.c:306
UINT ShellHookMessage
Definition: kbswitch.c:40
PKBSWITCHSETHOOKS KbSwitchSetHooks
Definition: kbswitch.c:38
struct tagLOAD_ICON LOAD_ICON
static VOID UpdateTrayIcon(HWND hwnd, LPTSTR szKLID, LPTSTR szName)
Definition: kbswitch.c:459
struct SPECIAL_ID * PSPECIAL_ID
INT g_cSpecialIds
Definition: kbswitch.c:59
#define IS_SPECIAL_HKL(hKL)
Definition: kbswitch.c:33
static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
Definition: kbswitch.c:294
static BOOL GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
Definition: kbswitch.c:204
HINSTANCE hInst
Definition: kbswitch.c:42
static VOID GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
Definition: kbswitch.c:114
static UINT GetLayoutNum(HKL hKL)
Definition: kbswitch.c:596
SPECIAL_ID g_SpecialIds[80]
Definition: kbswitch.c:58
static HICON CreateTrayIcon(LPTSTR szKLID, LPCTSTR szImeFile OPTIONAL)
Definition: kbswitch.c:328
static HKL GetHKLFromLayoutNum(INT nLayoutNum)
Definition: kbswitch.c:172
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
Definition: kbswitch.c:684
static HMENU BuildLeftPopupMenu(VOID)
Definition: kbswitch.c:524
#define IS_IME_HKL(hKL)
Definition: kbswitch.c:32
HKL g_ahKLs[64]
Definition: kbswitch.c:49
static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
Definition: kbswitch.c:657
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks
Definition: kbswitch.c:39
static VOID UpdateLayoutList(HKL hKL OPTIONAL)
Definition: kbswitch.c:142
static VOID ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
Definition: kbswitch.c:485
ULONG GetNextLayout(VOID)
Definition: kbswitch.c:610
static BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LPARAM lParam)
Definition: kbswitch.c:279
HWND g_hwndLastActive
Definition: kbswitch.c:47
VOID DeleteHooks(VOID)
Definition: kbswitch.c:582
static VOID GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
Definition: kbswitch.c:187
INT g_cKLs
Definition: kbswitch.c:48
UINT UpdateLanguageDisplay(HWND hwnd, HKL hKL)
Definition: kbswitch.c:616
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
Definition: kbswitch.c:240
HICON g_hTrayIcon
Definition: kbswitch.c:46
UINT UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
Definition: kbswitch.c:648
HMODULE g_hHookDLL
Definition: kbswitch.c:44
INT g_nCurrentLayoutNum
Definition: kbswitch.c:45
#define WM_NOTIFYICONMSG
Definition: kbswitch.c:36
struct tagLOAD_ICON * PLOAD_ICON
BOOL SetHooks(VOID)
Definition: kbswitch.c:562
static BOOL GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
Definition: kbswitch.c:193
HANDLE hProcessHeap
Definition: kbswitch.c:43
static VOID AddTrayIcon(HWND hwnd)
Definition: kbswitch.c:425
#define SPECIAL_MASK
Definition: kbswitch.c:30
static VOID DeleteTrayIcon(HWND hwnd)
Definition: kbswitch.c:446
HWND GetTargetWindow(HWND hwndFore)
Definition: kbswitch.c:631
#define CCH_LAYOUT_ID
Definition: kbswitch.h:17
BOOL(WINAPI * PKBSWITCHSETHOOKS)(VOID)
Definition: kbswitch.h:26
#define WM_WINDOW_ACTIVATE
Definition: kbswitch.h:24
VOID(WINAPI * PKBSWITCHDELETEHOOKS)(VOID)
Definition: kbswitch.h:27
TCHAR szKbSwitcherName[]
Definition: kbswitch.h:29
#define WM_LANG_CHANGED
Definition: kbswitch.h:23
LANGID WINAPI GetUserDefaultUILanguage(void)
Definition: lang.c:816
USHORT LANGID
Definition: mui.h:9
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
LPCWSTR szPath
Definition: env.c:37
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
HDC hdc
Definition: main.c:9
HANDLE hMutex
Definition: mutex.c:11
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static HICON
Definition: imagelist.c:84
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
HICON hIcon
Definition: msconfig.c:44
UINT_PTR HKL
Definition: msctf.idl:143
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned int UINT
Definition: ndis.h:50
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define UNICODE_NULL
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
#define L(x)
Definition: ntvdm.h:50
#define LOWORD(l)
Definition: pedump.c:82
#define RT_GROUP_ICON
Definition: pedump.c:375
static const WCHAR szName[]
Definition: powrprof.c:45
#define DefWindowProc
Definition: ros2win.h:31
#define MAKELANGID(p, s)
Definition: nls.h:15
#define LANG_HEBREW
Definition: nls.h:67
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define ShellExecute
Definition: shellapi.h:690
#define NIM_DELETE
Definition: shellapi.h:93
#define NIM_MODIFY
Definition: shellapi.h:92
#define NIF_ICON
Definition: shellapi.h:103
#define NIF_MESSAGE
Definition: shellapi.h:102
#define NIM_ADD
Definition: shellapi.h:91
#define Shell_NotifyIcon
Definition: shellapi.h:688
#define NIF_TIP
Definition: shellapi.h:104
HRESULT hr
Definition: shlfolder.c:183
#define SHLoadRegUIString
& rect
Definition: startmenu.cpp:1413
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
#define StringCchCopy
Definition: strsafe.h:139
#define StringCchPrintf
Definition: strsafe.h:517
#define StringCchCat
Definition: strsafe.h:317
LONG lfHeight
Definition: dimm.idl:42
LONG lfWidth
Definition: dimm.idl:43
DWORD dwLayoutId
Definition: kbswitch.c:53
HKL hKL
Definition: kbswitch.c:54
DWORD yHotspot
Definition: winuser.h:3124
BOOL fIcon
Definition: winuser.h:3122
DWORD xHotspot
Definition: winuser.h:3123
HBITMAP hbmColor
Definition: winuser.h:3126
HBITMAP hbmMask
Definition: winuser.h:3125
UINT uCallbackMessage
Definition: shellapi.h:228
CHAR szTip[128]
Definition: shellapi.h:234
HICON hIcon
Definition: kbswitch.c:275
LPSTR dwTypeData
Definition: winuser.h:3250
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
unsigned char * LPBYTE
Definition: typedefs.h:53
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
uint32_t ULONG
Definition: typedefs.h:59
#define _T(x)
Definition: vfdio.h:22
int ret
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083
COLORREF WINAPI SetDCBrushColor(_In_ HDC hdc, _In_ COLORREF crColor)
Definition: dc.c:905
BOOL WINAPI SetProcessDefaultLayout(DWORD dwDefaultLayout)
Definition: window.c:1719
#define ZeroMemory
Definition: winbase.h:1712
#define GetSystemDirectory
Definition: winbase.h:3777
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LoadLibraryEx
Definition: winbase.h:3798
#define LoadLibrary
Definition: winbase.h:3797
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:342
#define CreateMutex
Definition: winbase.h:3691
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
#define EnumResourceNames
Definition: winbase.h:3707
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4246
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
#define BLACKNESS
Definition: wingdi.h:323
HGDIOBJ WINAPI GetStockObject(_In_ int)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
#define DEFAULT_GUI_FONT
Definition: wingdi.h:909
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
#define DI_NORMAL
Definition: wingdi.h:72
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define TRANSPARENT
Definition: wingdi.h:950
#define LAYOUT_RTL
Definition: wingdi.h:1371
BOOL WINAPI PatBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
BOOL WINAPI DeleteDC(_In_ HDC)
#define CreateFontIndirect
Definition: wingdi.h:4444
#define GetLocaleInfo
Definition: winnls.h:1186
#define LOCALE_SLANGUAGE
Definition: winnls.h:26
#define LOCALE_NOUSEROVERRIDE
Definition: winnls.h:19
#define LOCALE_SABBREVLANGNAME
Definition: winnls.h:28
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define RegOpenKeyEx
Definition: winreg.h:520
#define RegQueryValueEx
Definition: winreg.h:524
#define RegEnumKeyEx
Definition: winreg.h:510
#define SW_SHOWNORMAL
Definition: winuser.h:769
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
DWORD WINAPI GetSysColor(_In_ int)
BOOL WINAPI IsWindow(_In_opt_ HWND)
HMENU WINAPI CreatePopupMenu(void)
Definition: menu.c:838
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define WM_CLOSE
Definition: winuser.h:1620
#define MIIM_STRING
Definition: winuser.h:727
HICON WINAPI CreateIconIndirect(_In_ PICONINFO)
Definition: cursoricon.c:2564
#define GA_ROOT
Definition: winuser.h:2788
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define MIIM_ID
Definition: winuser.h:722
#define COLOR_MENU
Definition: winuser.h:916
#define KLF_SETFORPROCESS
Definition: winuser.h:117
#define DT_CENTER
Definition: winuser.h:527
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
#define KL_NAMELENGTH
Definition: winuser.h:122
#define IMAGE_ICON
Definition: winuser.h:212
#define WM_CREATE
Definition: winuser.h:1607
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
#define GetClassName
Definition: winuser.h:5782
#define KLF_ACTIVATE
Definition: winuser.h:111
BOOL WINAPI RegisterShellHookWindow(_In_ HWND)
#define COLOR_HIGHLIGHT
Definition: winuser.h:925
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define WM_COMMAND
Definition: winuser.h:1739
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define IDC_ARROW
Definition: winuser.h:687
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2653
#define WM_RBUTTONUP
Definition: winuser.h:1779
#define InsertMenuItem
Definition: winuser.h:5803
#define SM_CYSMICON
Definition: winuser.h:1012
#define MF_CHECKED
Definition: winuser.h:132
#define LoadKeyboardLayout
Definition: winuser.h:5815
#define SPI_GETICONTITLELOGFONT
Definition: winuser.h:1379
DWORD WINAPI CheckMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
#define DrawText
Definition: winuser.h:5770
#define CreateWindow
Definition: winuser.h:5753
#define HWND_DESKTOP
Definition: winuser.h:1208
#define MB_ICONERROR
Definition: winuser.h:786
#define WM_SETTINGCHANGE
Definition: winuser.h:1628
#define GetMessage
Definition: winuser.h:5789
#define SM_CXSMICON
Definition: winuser.h:1011
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
#define RegisterWindowMessage
Definition: winuser.h:5839
UINT WINAPI GetKeyboardLayoutList(_In_ int nBuff, _Out_writes_to_opt_(nBuff, return) HKL FAR *lpList)
#define MIIM_BITMAP
Definition: winuser.h:728
BOOL WINAPI DrawIconEx(_In_ HDC, _In_ int, _In_ int, _In_ HICON, _In_ int, _In_ int, _In_ UINT, _In_opt_ HBRUSH, _In_ UINT)
Definition: cursoricon.c:2011
#define LoadIcon
Definition: winuser.h:5812
#define WM_NULL
Definition: winuser.h:1606
#define LoadCursor
Definition: winuser.h:5811
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:926
HDC WINAPI GetDC(_In_opt_ HWND)
#define LoadMenu
Definition: winuser.h:5816
#define WM_LBUTTONUP
Definition: winuser.h:1776
#define DT_VCENTER
Definition: winuser.h:543
#define PostMessage
Definition: winuser.h:5831
#define LoadImage
Definition: winuser.h:5814
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define MessageBox
Definition: winuser.h:5821
#define LR_DEFAULTCOLOR
Definition: winuser.h:1086
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define RegisterClass
Definition: winuser.h:5835
#define WM_DESTROY
Definition: winuser.h:1608
#define DispatchMessage
Definition: winuser.h:5764
HKL WINAPI ActivateKeyboardLayout(_In_ HKL, _In_ UINT)
#define SystemParametersInfo
Definition: winuser.h:5857
BOOL WINAPI IsWindowVisible(_In_ HWND)
#define MAKEINTRESOURCE
Definition: winuser.h:591
int WINAPI GetSystemMetrics(_In_ int)
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2036
char TCHAR
Definition: xmlstorage.h:189
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define _tcslen
Definition: xmlstorage.h:198
#define _tcsicmp
Definition: xmlstorage.h:205