ReactOS 0.4.15-dev-7788-g1ad9096
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#include <imm32_undoc.h>
15
16/*
17 * This program kbswitch is a mimic of Win2k's internat.exe.
18 * However, there are some differences.
19 *
20 * Comparing with WinNT4 ActivateKeyboardLayout, WinXP ActivateKeyboardLayout has
21 * process boundary, so we cannot activate the IME keyboard layout from the outer process.
22 * It needs special care.
23 *
24 * We use global hook by our kbsdll.dll, to watch the shell and the windows.
25 *
26 * It might not work correctly on Vista+ because keyboard layout change notification
27 * won't be generated in Vista+.
28 */
29
30#define WM_NOTIFYICONMSG (WM_USER + 248)
31
35
44
45typedef struct
46{
49 TCHAR szKLID[CCH_LAYOUT_ID + 1];
51
54
56{
57 TCHAR szKLID[KL_NAMELENGTH], szLayoutId[16];
58 DWORD dwSize, dwIndex;
59 HKEY hKey, hLayoutKey;
60
61 g_cSpecialIds = 0;
62
64 TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"),
66 {
67 return;
68 }
69
70 for (dwIndex = 0; dwIndex < 1000; ++dwIndex)
71 {
72 dwSize = ARRAYSIZE(szKLID);
73 if (RegEnumKeyEx(hKey, dwIndex, szKLID, &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
74 break;
75
76 if (RegOpenKeyEx(hKey, szKLID, 0, KEY_READ, &hLayoutKey) != ERROR_SUCCESS)
77 continue;
78
79 dwSize = sizeof(szLayoutId);
80 if (RegQueryValueEx(hLayoutKey, TEXT("Layout Id"), NULL, NULL,
81 (LPBYTE)szLayoutId, &dwSize) == ERROR_SUCCESS)
82 {
83 DWORD dwKLID = _tcstoul(szKLID, NULL, 16);
84 WORD wLangId = LOWORD(dwKLID), wLayoutId = LOWORD(_tcstoul(szLayoutId, NULL, 16));
85 HKL hKL = (HKL)(LONG_PTR)(SPECIAL_MASK | MAKELONG(wLangId, wLayoutId));
86
87 /* Add a special ID */
91 ARRAYSIZE(g_SpecialIds[g_cSpecialIds].szKLID), szKLID);
93 }
94
95 RegCloseKey(hLayoutKey);
96
98 {
99 OutputDebugStringA("g_SpecialIds is full!");
100 break;
101 }
102 }
103
105}
106
107static VOID
108GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
109{
110 szKLID[0] = 0;
111
112 if (IS_IME_HKL(hKL))
113 {
114 StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), (DWORD)(DWORD_PTR)hKL);
115 return;
116 }
117
118 if (IS_SPECIAL_HKL(hKL))
119 {
120 INT i;
121 for (i = 0; i < g_cSpecialIds; ++i)
122 {
123 if (g_SpecialIds[i].hKL == hKL)
124 {
125 StringCchCopy(szKLID, KLIDLength, g_SpecialIds[i].szKLID);
126 return;
127 }
128 }
129 }
130 else
131 {
132 StringCchPrintf(szKLID, KLIDLength, _T("%08lx"), LOWORD(hKL));
133 }
134}
135
137{
138 INT iKL;
139
140 if (!hKL)
141 {
143 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
144 hKL = GetKeyboardLayout(dwTID);
145 }
146
148
150 for (iKL = 0; iKL < g_cKLs; ++iKL)
151 {
152 if (g_ahKLs[iKL] == hKL)
153 {
154 g_nCurrentLayoutNum = iKL + 1;
155 break;
156 }
157 }
158
160 {
162 g_ahKLs[g_cKLs++] = hKL;
163 }
164}
165
166static HKL GetHKLFromLayoutNum(INT nLayoutNum)
167{
168 if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs)
169 {
170 return g_ahKLs[nLayoutNum - 1];
171 }
172 else
173 {
175 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
176 return GetKeyboardLayout(dwTID);
177 }
178}
179
180static VOID
181GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
182{
183 GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength);
184}
185
186static BOOL
188{
189 if (!GetSystemDirectory(szPath, cchPath))
190 return FALSE;
191
192 StringCchCat(szPath, cchPath, TEXT("\\"));
193 StringCchCat(szPath, cchPath, FileName);
194 return TRUE;
195}
196
197static BOOL
198GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
199{
200 HKEY hKey;
201 HRESULT hr;
203 TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
204
205 GetKLIDFromLayoutNum(nLayoutNum, szKLID, ARRAYSIZE(szKLID));
206
207 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
208 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
209
211 return FALSE;
212
213 /* Use "Layout Display Name" value as an entry name if possible */
214 hr = SHLoadRegUIString(hKey, _T("Layout Display Name"), szName, NameLength);
215 if (SUCCEEDED(hr))
216 {
218 return TRUE;
219 }
220
221 /* Otherwise, use "Layout Text" value as an entry name */
222 dwBufLen = NameLength * sizeof(TCHAR);
223 if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
225 {
227 return TRUE;
228 }
229
231 return FALSE;
232}
233
234static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
235{
236 HKEY hKey;
238 TCHAR szBuf[MAX_PATH];
239
240 szImeFile[0] = UNICODE_NULL;
241
242 if (_tcslen(szKLID) != CCH_LAYOUT_ID)
243 return FALSE; /* Invalid LCID */
244
245 if (szKLID[0] != TEXT('E') && szKLID[0] != TEXT('e'))
246 return FALSE; /* Not an IME HKL */
247
248 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
249 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
250
252 return FALSE;
253
254 dwBufLen = cchImeFile * sizeof(TCHAR);
255 if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
256 (LPBYTE)szImeFile, &dwBufLen) != ERROR_SUCCESS)
257 {
258 szImeFile[0] = UNICODE_NULL;
259 }
260
262
263 return (szImeFile[0] != UNICODE_NULL);
264}
265
266typedef struct tagLOAD_ICON
267{
271
272static BOOL CALLBACK
275 LPCTSTR lpszType,
276 LPTSTR lpszName,
278{
279 PLOAD_ICON pLoadIcon = (PLOAD_ICON)lParam;
280 pLoadIcon->hIcon = (HICON)LoadImage(hModule, lpszName, IMAGE_ICON,
281 pLoadIcon->cxIcon, pLoadIcon->cyIcon,
283 if (pLoadIcon->hIcon)
284 return FALSE; /* Stop enumeration */
285 return TRUE;
286}
287
288static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
289{
290 LOAD_ICON LoadIcon = { cxIcon, cyIcon, NULL };
291 HMODULE hImeDLL = LoadLibraryEx(szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
292 if (hImeDLL)
293 {
295 FreeLibrary(hImeDLL);
296 }
297 return LoadIcon.hIcon;
298}
299
301{
302 HDC hdcScreen = GetDC(NULL);
303 HDC hdc = CreateCompatibleDC(hdcScreen);
306 HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
307 HGDIOBJ hbmOld;
308
309 if (hbm != NULL)
310 {
311 hbmOld = SelectObject(hdc, hbm);
312 DrawIconEx(hdc, 0, 0, hIcon, cxIcon, cyIcon, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
313 SelectObject(hdc, hbmOld);
314 }
315
316 DeleteDC(hdc);
317 ReleaseDC(NULL, hdcScreen);
318 return hbm;
319}
320
321static HICON
323{
325 TCHAR szBuf[4];
326 HDC hdcScreen, hdc;
327 HBITMAP hbmColor, hbmMono, hBmpOld;
328 HFONT hFont, hFontOld;
329 LOGFONT lf;
330 RECT rect;
332 HICON hIcon;
336
337 if (szImeFile && szImeFile[0])
338 {
340 return FakeExtractIcon(szPath, cxIcon, cyIcon);
341 }
342
343 /* Getting "EN", "FR", etc. from English, French, ... */
344 LangID = LANGIDFROMLCID(_tcstoul(szKLID, NULL, 16));
347 szBuf,
348 ARRAYSIZE(szBuf)) == 0)
349 {
350 szBuf[0] = szBuf[1] = _T('?');
351 }
352 szBuf[2] = 0; /* Truncate the identifier to two characters: "ENG" --> "EN" etc. */
353
354 /* Create hdc, hbmColor and hbmMono */
355 hdcScreen = GetDC(NULL);
356 hdc = CreateCompatibleDC(hdcScreen);
357 hbmColor = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
358 ReleaseDC(NULL, hdcScreen);
359 hbmMono = CreateBitmap(cxIcon, cyIcon, 1, 1, NULL);
360
361 /* Checking NULL */
362 if (!hdc || !hbmColor || !hbmMono)
363 {
364 if (hbmMono)
365 DeleteObject(hbmMono);
366 if (hbmColor)
367 DeleteObject(hbmColor);
368 if (hdc)
369 DeleteDC(hdc);
370 return NULL;
371 }
372
373 /* Create a font */
374 hFont = NULL;
375 if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
376 {
377 /* Override the current size with something manageable */
378 lf.lfHeight = -11;
379 lf.lfWidth = 0;
381 }
382 if (!hFont)
384
385 SetRect(&rect, 0, 0, cxIcon, cyIcon);
386
387 /* Draw hbmColor */
388 hBmpOld = SelectObject(hdc, hbmColor);
390 FillRect(hdc, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
391 hFontOld = SelectObject(hdc, hFont);
395 SelectObject(hdc, hFontOld);
396
397 /* Fill hbmMono with black */
398 SelectObject(hdc, hbmMono);
399 PatBlt(hdc, 0, 0, cxIcon, cyIcon, BLACKNESS);
400 SelectObject(hdc, hBmpOld);
401
402 /* Create an icon from hbmColor and hbmMono */
405 IconInfo.hbmColor = hbmColor;
406 IconInfo.hbmMask = hbmMono;
408
409 /* Clean up */
411 DeleteObject(hbmMono);
412 DeleteObject(hbmColor);
413 DeleteDC(hdc);
414
415 return hIcon;
416}
417
418static VOID
420{
421 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
422 TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
423
426 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
427
429 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
431
433
434 if (g_hTrayIcon)
436 g_hTrayIcon = tnid.hIcon;
437}
438
439static VOID
441{
442 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1 };
444
445 if (g_hTrayIcon)
446 {
449 }
450}
451
452static VOID
454{
455 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
456 TCHAR szImeFile[80];
457
458 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
459
461 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
463
465
466 if (g_hTrayIcon)
468 g_hTrayIcon = tnid.hIcon;
469}
470
471static BOOL CALLBACK
473{
474 PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, lParam);
475 return TRUE;
476}
477
478static VOID
479ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
480{
481 HKL hKl;
482 TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
484
485 /* The layout number starts from one. Zero is invalid */
486 if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
487 return;
488
489 GetKLIDFromLayoutNum(uLayoutNum, szKLID, ARRAYSIZE(szKLID));
490 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
491
492 /* Switch to the new keyboard layout */
493 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
494 UpdateTrayIcon(hwnd, szKLID, szLangName);
495
496 if (hwndTarget && !bNoActivate)
497 SetForegroundWindow(hwndTarget);
498
499 hKl = LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
500 if (hKl)
502
503 /* Post WM_INPUTLANGCHANGEREQUEST */
504 if (hwndTarget)
505 {
506 PostMessage(hwndTarget, WM_INPUTLANGCHANGEREQUEST,
507 INPUTLANGCHANGE_SYSCHARSET, (LPARAM)hKl);
508 }
509 else
510 {
512 }
513
514 g_nCurrentLayoutNum = uLayoutNum;
515}
516
517static HMENU
519{
520 HMENU hMenu = CreatePopupMenu();
521 TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
522 HICON hIcon;
523 MENUITEMINFO mii = { sizeof(mii) };
524 INT iKL;
525
526 for (iKL = 0; iKL < g_cKLs; ++iKL)
527 {
528 GetKLIDFromHKL(g_ahKLs[iKL], szKLID, ARRAYSIZE(szKLID));
529 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
530
531 if (!GetLayoutName(iKL + 1, szName, ARRAYSIZE(szName)))
532 continue;
533
534 mii.fMask = MIIM_ID | MIIM_STRING;
535 mii.wID = iKL + 1;
536 mii.dwTypeData = szName;
537
538 hIcon = CreateTrayIcon(szKLID, szImeFile);
539 if (hIcon)
540 {
541 mii.hbmpItem = BitmapFromIcon(hIcon);
542 if (mii.hbmpItem)
543 mii.fMask |= MIIM_BITMAP;
544 }
545
546 InsertMenuItem(hMenu, -1, TRUE, &mii);
548 }
549
551
552 return hMenu;
553}
554
555BOOL
557{
558 g_hHookDLL = LoadLibrary(_T("kbsdll.dll"));
559 if (!g_hHookDLL)
560 {
561 return FALSE;
562 }
563
566
568 {
569 return FALSE;
570 }
571
572 return KbSwitchSetHooks();
573}
574
575VOID
577{
579 {
582 }
583 if (g_hHookDLL)
584 {
587 }
588}
589
591{
592 INT iKL;
593
594 for (iKL = 0; iKL < g_cKLs; ++iKL)
595 {
596 if (g_ahKLs[iKL] == hKL)
597 return iKL + 1;
598 }
599
600 return 0;
601}
602
603ULONG
605{
606 return (g_nCurrentLayoutNum % g_cKLs) + 1;
607}
608
609UINT
611{
612 TCHAR szKLID[MAX_PATH], szLangName[MAX_PATH];
614
615 GetKLIDFromHKL(hKL, szKLID, ARRAYSIZE(szKLID));
616 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
617 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
618 UpdateTrayIcon(hwnd, szKLID, szLangName);
620
621 return 0;
622}
623
624HWND
626{
627 TCHAR szClass[64];
628 HWND hwndIME;
629 HWND hwndTarget = hwndFore;
630 if (hwndTarget == NULL)
631 hwndTarget = GetForegroundWindow();
632
633 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass));
634 if (_tcsicmp(szClass, szKbSwitcherName) == 0)
635 hwndTarget = g_hwndLastActive;
636
637 hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
638 return (hwndIME ? hwndIME : hwndTarget);
639}
640
641UINT
643{
644 DWORD dwThreadID = GetWindowThreadProcessId(GetTargetWindow(hwndFore), NULL);
645 HKL hKL = GetKeyboardLayout(dwThreadID);
647
648 return 0;
649}
650
652{
653 TCHAR szClass[64];
654
655 hwndFore = GetAncestor(hwndFore, GA_ROOT);
656
657 if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, ARRAYSIZE(szClass)))
658 return FALSE;
659
660 if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
661 _tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
662 {
663 return FALSE; /* Special window */
664 }
665
666 /* FIXME: CONWND needs special handling */
667 if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
668 {
669 HKL hKL = GetKeyboardLayout(0);
671 }
672
673 g_hwndLastActive = hwndFore;
674 return TRUE;
675}
676
679{
680 static HMENU s_hMenu = NULL, s_hRightPopupMenu = NULL;
681 static UINT s_uTaskbarRestart;
682 POINT pt;
683 HMENU hLeftPopupMenu;
684
685 switch (Message)
686 {
687 case WM_CREATE:
688 {
689 if (!SetHooks())
690 {
691 MessageBox(NULL, TEXT("SetHooks failed."), NULL, MB_ICONERROR);
692 return -1;
693 }
694
696
699
701 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
702 break;
703 }
704
705 case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
706 {
709 break;
710 }
711
712 case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
713 {
714 HWND hwndFore = GetForegroundWindow();
715 if (RememberLastActive(hwnd, hwndFore))
716 return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
717 break;
718 }
719
720 case WM_NOTIFYICONMSG:
721 {
722 switch (lParam)
723 {
724 case WM_RBUTTONUP:
725 case WM_LBUTTONUP:
726 {
728
731
732 if (lParam == WM_LBUTTONUP)
733 {
734 /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
735 hLeftPopupMenu = BuildLeftPopupMenu();
736 TrackPopupMenu(hLeftPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
737 DestroyMenu(hLeftPopupMenu);
738 }
739 else
740 {
741 if (!s_hRightPopupMenu)
742 {
744 s_hRightPopupMenu = GetSubMenu(s_hMenu, 0);
745 }
746 TrackPopupMenu(s_hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
747 }
748
749 PostMessage(hwnd, WM_NULL, 0, 0);
750 break;
751 }
752 }
753 break;
754 }
755
756 case WM_COMMAND:
757 switch (LOWORD(wParam))
758 {
759 case ID_EXIT:
760 {
761 PostMessage(hwnd, WM_CLOSE, 0, 0);
762 break;
763 }
764
765 case ID_PREFERENCES:
766 {
768 TEXT("control.exe"), TEXT("input.dll"),
770 if (ret <= 32)
771 MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_ICONERROR);
772 break;
773 }
774
775 case ID_NEXTLAYOUT:
776 {
777 HWND hwndTarget = (HWND)lParam, hwndTargetSave = NULL;
778 DWORD dwThreadID;
779 HKL hKL;
780 UINT uNum;
781 TCHAR szClass[64];
782 BOOL bCONWND = FALSE;
783
784 if (hwndTarget == NULL)
785 hwndTarget = g_hwndLastActive;
786
787 /* FIXME: CONWND needs special handling */
788 if (hwndTarget &&
789 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
790 _tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
791 {
792 bCONWND = TRUE;
793 hwndTargetSave = hwndTarget;
794 hwndTarget = NULL;
795 }
796
797 if (hwndTarget)
798 {
799 dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
800 hKL = GetKeyboardLayout(dwThreadID);
801 uNum = GetLayoutNum(hKL);
802 if (uNum != 0)
803 g_nCurrentLayoutNum = uNum;
804 }
805
806 ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
807
808 /* FIXME: CONWND needs special handling */
809 if (bCONWND)
810 ActivateLayout(hwnd, g_nCurrentLayoutNum, hwndTargetSave, TRUE);
811
812 break;
813 }
814
815 default:
816 {
817 if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
818 {
820 {
822 }
824 }
825 break;
826 }
827 }
828 break;
829
830 case WM_SETTINGCHANGE:
831 {
832 if (wParam == SPI_SETNONCLIENTMETRICS)
833 {
835 break;
836 }
837 }
838 break;
839
840 case WM_DESTROY:
841 {
842 DeleteHooks();
843 DestroyMenu(s_hMenu);
846 break;
847 }
848
849 default:
850 {
851 if (Message == s_uTaskbarRestart)
852 {
855 break;
856 }
857 else if (Message == ShellHookMessage)
858 {
859 if (wParam == HSHELL_LANGUAGE)
861 else if (wParam == HSHELL_WINDOWACTIVATED)
863
864 break;
865 }
867 }
868 }
869
870 return 0;
871}
872
874_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
875{
877 MSG msg;
879 HWND hwnd;
880
881 switch (GetUserDefaultUILanguage())
882 {
885 break;
886 default:
887 break;
888 }
889
891 if (!hMutex)
892 return 1;
893
895 {
897 return 1;
898 }
899
902
903 ZeroMemory(&WndClass, sizeof(WndClass));
904 WndClass.lpfnWndProc = WndProc;
905 WndClass.hInstance = hInstance;
906 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
907 WndClass.lpszClassName = szKbSwitcherName;
908 if (!RegisterClass(&WndClass))
909 {
911 return 1;
912 }
913
917
918 while (GetMessage(&msg, NULL, 0, 0))
919 {
922 }
923
925 return 0;
926}
#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 SPECIAL_MASK
Definition: debug.h:13
#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 IS_SPECIAL_HKL(hKL)
Definition: imm32_undoc.h:21
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:20
#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:472
static VOID LoadSpecialIds(VOID)
Definition: kbswitch.c:55
static HBITMAP BitmapFromIcon(HICON hIcon)
Definition: kbswitch.c:300
UINT ShellHookMessage
Definition: kbswitch.c:34
PKBSWITCHSETHOOKS KbSwitchSetHooks
Definition: kbswitch.c:32
struct tagLOAD_ICON LOAD_ICON
static VOID UpdateTrayIcon(HWND hwnd, LPTSTR szKLID, LPTSTR szName)
Definition: kbswitch.c:453
struct SPECIAL_ID * PSPECIAL_ID
INT g_cSpecialIds
Definition: kbswitch.c:53
static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
Definition: kbswitch.c:288
static BOOL GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
Definition: kbswitch.c:198
HINSTANCE hInst
Definition: kbswitch.c:36
static VOID GetKLIDFromHKL(HKL hKL, LPTSTR szKLID, SIZE_T KLIDLength)
Definition: kbswitch.c:108
static UINT GetLayoutNum(HKL hKL)
Definition: kbswitch.c:590
SPECIAL_ID g_SpecialIds[80]
Definition: kbswitch.c:52
static HICON CreateTrayIcon(LPTSTR szKLID, LPCTSTR szImeFile OPTIONAL)
Definition: kbswitch.c:322
static HKL GetHKLFromLayoutNum(INT nLayoutNum)
Definition: kbswitch.c:166
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
Definition: kbswitch.c:678
static HMENU BuildLeftPopupMenu(VOID)
Definition: kbswitch.c:518
HKL g_ahKLs[64]
Definition: kbswitch.c:43
static BOOL RememberLastActive(HWND hwnd, HWND hwndFore)
Definition: kbswitch.c:651
PKBSWITCHDELETEHOOKS KbSwitchDeleteHooks
Definition: kbswitch.c:33
static VOID UpdateLayoutList(HKL hKL OPTIONAL)
Definition: kbswitch.c:136
static VOID ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
Definition: kbswitch.c:479
ULONG GetNextLayout(VOID)
Definition: kbswitch.c:604
static BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LPARAM lParam)
Definition: kbswitch.c:273
HWND g_hwndLastActive
Definition: kbswitch.c:41
VOID DeleteHooks(VOID)
Definition: kbswitch.c:576
static VOID GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
Definition: kbswitch.c:181
INT g_cKLs
Definition: kbswitch.c:42
UINT UpdateLanguageDisplay(HWND hwnd, HKL hKL)
Definition: kbswitch.c:610
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
Definition: kbswitch.c:234
HICON g_hTrayIcon
Definition: kbswitch.c:40
UINT UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
Definition: kbswitch.c:642
HMODULE g_hHookDLL
Definition: kbswitch.c:38
INT g_nCurrentLayoutNum
Definition: kbswitch.c:39
#define WM_NOTIFYICONMSG
Definition: kbswitch.c:30
struct tagLOAD_ICON * PLOAD_ICON
BOOL SetHooks(VOID)
Definition: kbswitch.c:556
static BOOL GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
Definition: kbswitch.c:187
HANDLE hProcessHeap
Definition: kbswitch.c:37
static VOID AddTrayIcon(HWND hwnd)
Definition: kbswitch.c:419
static VOID DeleteTrayIcon(HWND hwnd)
Definition: kbswitch.c:440
HWND GetTargetWindow(HWND hwndFore)
Definition: kbswitch.c:625
#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:47
HKL hKL
Definition: kbswitch.c:48
DWORD yHotspot
Definition: winuser.h:3125
BOOL fIcon
Definition: winuser.h:3123
DWORD xHotspot
Definition: winuser.h:3124
HBITMAP hbmColor
Definition: winuser.h:3127
HBITMAP hbmMask
Definition: winuser.h:3126
UINT uCallbackMessage
Definition: shellapi.h:228
CHAR szTip[128]
Definition: shellapi.h:234
HICON hIcon
Definition: kbswitch.c:269
LPSTR dwTypeData
Definition: winuser.h:3251
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:770
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:1621
#define MIIM_STRING
Definition: winuser.h:727
HICON WINAPI CreateIconIndirect(_In_ PICONINFO)
Definition: cursoricon.c:2581
#define GA_ROOT
Definition: winuser.h:2789
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define MIIM_ID
Definition: winuser.h:722
#define COLOR_MENU
Definition: winuser.h:917
#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:1608
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
#define GetClassName
Definition: winuser.h:5783
#define KLF_ACTIVATE
Definition: winuser.h:111
BOOL WINAPI RegisterShellHookWindow(_In_ HWND)
#define COLOR_HIGHLIGHT
Definition: winuser.h:926
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define WM_COMMAND
Definition: winuser.h:1740
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define IDC_ARROW
Definition: winuser.h:687
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2670
#define WM_RBUTTONUP
Definition: winuser.h:1780
#define InsertMenuItem
Definition: winuser.h:5804
#define SM_CYSMICON
Definition: winuser.h:1013
#define MF_CHECKED
Definition: winuser.h:132
#define LoadKeyboardLayout
Definition: winuser.h:5816
#define SPI_GETICONTITLELOGFONT
Definition: winuser.h:1380
DWORD WINAPI CheckMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
#define DrawText
Definition: winuser.h:5771
#define CreateWindow
Definition: winuser.h:5754
#define HWND_DESKTOP
Definition: winuser.h:1209
#define MB_ICONERROR
Definition: winuser.h:787
#define WM_SETTINGCHANGE
Definition: winuser.h:1629
#define GetMessage
Definition: winuser.h:5790
#define SM_CXSMICON
Definition: winuser.h:1012
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
#define RegisterWindowMessage
Definition: winuser.h:5840
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:2028
#define LoadIcon
Definition: winuser.h:5813
#define WM_NULL
Definition: winuser.h:1607
#define LoadCursor
Definition: winuser.h:5812
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:927
HDC WINAPI GetDC(_In_opt_ HWND)
#define LoadMenu
Definition: winuser.h:5817
#define WM_LBUTTONUP
Definition: winuser.h:1777
#define DT_VCENTER
Definition: winuser.h:543
#define PostMessage
Definition: winuser.h:5832
#define LoadImage
Definition: winuser.h:5815
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define MessageBox
Definition: winuser.h:5822
#define LR_DEFAULTCOLOR
Definition: winuser.h:1087
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define RegisterClass
Definition: winuser.h:5836
#define WM_DESTROY
Definition: winuser.h:1609
#define DispatchMessage
Definition: winuser.h:5765
HKL WINAPI ActivateKeyboardLayout(_In_ HKL, _In_ UINT)
#define SystemParametersInfo
Definition: winuser.h:5858
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:2053
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