ReactOS 0.4.15-dev-6052-g2626c72
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 {
148 if (0 <= (g_nCurrentLayoutNum - 1) && (g_nCurrentLayoutNum - 1) < g_cKLs)
149 {
150 hKL = g_ahKLs[g_nCurrentLayoutNum - 1];
151 }
152 else
153 {
155 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
156 hKL = GetKeyboardLayout(dwTID);
157 }
158 }
159
161
163 for (iKL = 0; iKL < g_cKLs; ++iKL)
164 {
165 if (g_ahKLs[iKL] == hKL)
166 {
167 g_nCurrentLayoutNum = iKL + 1;
168 break;
169 }
170 }
171
173 {
175 g_ahKLs[g_cKLs++] = hKL;
176 }
177}
178
179static HKL GetHKLFromLayoutNum(INT nLayoutNum)
180{
181 if (0 <= (nLayoutNum - 1) && (nLayoutNum - 1) < g_cKLs)
182 {
183 return g_ahKLs[nLayoutNum - 1];
184 }
185 else
186 {
188 DWORD dwTID = GetWindowThreadProcessId(hwndTarget, NULL);
189 return GetKeyboardLayout(dwTID);
190 }
191}
192
193static VOID
194GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
195{
196 GetKLIDFromHKL(GetHKLFromLayoutNum(nLayoutNum), szKLID, KLIDLength);
197}
198
199static BOOL
201{
202 if (!GetSystemDirectory(szPath, cchPath))
203 return FALSE;
204
205 StringCchCat(szPath, cchPath, TEXT("\\"));
206 StringCchCat(szPath, cchPath, FileName);
207 return TRUE;
208}
209
210static BOOL
211GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
212{
213 HKEY hKey;
214 HRESULT hr;
216 TCHAR szBuf[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1];
217
218 GetKLIDFromLayoutNum(nLayoutNum, szKLID, ARRAYSIZE(szKLID));
219
220 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
221 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
222
224 return FALSE;
225
226 /* Use "Layout Display Name" value as an entry name if possible */
227 hr = SHLoadRegUIString(hKey, _T("Layout Display Name"), szName, NameLength);
228 if (SUCCEEDED(hr))
229 {
231 return TRUE;
232 }
233
234 /* Otherwise, use "Layout Text" value as an entry name */
235 dwBufLen = NameLength * sizeof(TCHAR);
236 if (RegQueryValueEx(hKey, _T("Layout Text"), NULL, NULL,
238 {
240 return TRUE;
241 }
242
244 return FALSE;
245}
246
247static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
248{
249 HKEY hKey;
251 TCHAR szBuf[MAX_PATH];
252
253 szImeFile[0] = UNICODE_NULL;
254
255 if (_tcslen(szKLID) != CCH_LAYOUT_ID)
256 return FALSE; /* Invalid LCID */
257
258 if (szKLID[0] != TEXT('E') && szKLID[0] != TEXT('e'))
259 return FALSE; /* Not an IME HKL */
260
261 StringCchPrintf(szBuf, ARRAYSIZE(szBuf),
262 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s"), szKLID);
263
265 return FALSE;
266
267 dwBufLen = cchImeFile * sizeof(TCHAR);
268 if (RegQueryValueEx(hKey, _T("IME File"), NULL, NULL,
269 (LPBYTE)szImeFile, &dwBufLen) != ERROR_SUCCESS)
270 {
271 szImeFile[0] = UNICODE_NULL;
272 }
273
275
276 return (szImeFile[0] != UNICODE_NULL);
277}
278
279typedef struct tagLOAD_ICON
280{
284
285static BOOL CALLBACK
288 LPCTSTR lpszType,
289 LPTSTR lpszName,
291{
292 PLOAD_ICON pLoadIcon = (PLOAD_ICON)lParam;
293 pLoadIcon->hIcon = (HICON)LoadImage(hModule, lpszName, IMAGE_ICON,
294 pLoadIcon->cxIcon, pLoadIcon->cyIcon,
296 if (pLoadIcon->hIcon)
297 return FALSE; /* Stop enumeration */
298 return TRUE;
299}
300
301static HICON FakeExtractIcon(LPCTSTR szIconPath, INT cxIcon, INT cyIcon)
302{
303 LOAD_ICON LoadIcon = { cxIcon, cyIcon, NULL };
304 HMODULE hImeDLL = LoadLibraryEx(szIconPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
305 if (hImeDLL)
306 {
308 FreeLibrary(hImeDLL);
309 }
310 return LoadIcon.hIcon;
311}
312
314{
315 HDC hdcScreen = GetDC(NULL);
316 HDC hdc = CreateCompatibleDC(hdcScreen);
319 HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
320 HGDIOBJ hbmOld;
321
322 if (hbm != NULL)
323 {
324 hbmOld = SelectObject(hdc, hbm);
325 DrawIconEx(hdc, 0, 0, hIcon, cxIcon, cyIcon, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
326 SelectObject(hdc, hbmOld);
327 }
328
329 DeleteDC(hdc);
330 ReleaseDC(NULL, hdcScreen);
331 return hbm;
332}
333
334static HICON
336{
338 TCHAR szBuf[4];
339 HDC hdcScreen, hdc;
340 HBITMAP hbmColor, hbmMono, hBmpOld;
341 HFONT hFont, hFontOld;
342 LOGFONT lf;
343 RECT rect;
345 HICON hIcon;
349
350 if (szImeFile && szImeFile[0])
351 {
353 return FakeExtractIcon(szPath, cxIcon, cyIcon);
354 }
355
356 /* Getting "EN", "FR", etc. from English, French, ... */
357 LangID = LANGIDFROMLCID(_tcstoul(szKLID, NULL, 16));
360 szBuf,
361 ARRAYSIZE(szBuf)) == 0)
362 {
363 szBuf[0] = szBuf[1] = _T('?');
364 }
365 szBuf[2] = 0; /* Truncate the identifier to two characters: "ENG" --> "EN" etc. */
366
367 /* Create hdc, hbmColor and hbmMono */
368 hdcScreen = GetDC(NULL);
369 hdc = CreateCompatibleDC(hdcScreen);
370 hbmColor = CreateCompatibleBitmap(hdcScreen, cxIcon, cyIcon);
371 ReleaseDC(NULL, hdcScreen);
372 hbmMono = CreateBitmap(cxIcon, cyIcon, 1, 1, NULL);
373
374 /* Checking NULL */
375 if (!hdc || !hbmColor || !hbmMono)
376 {
377 if (hbmMono)
378 DeleteObject(hbmMono);
379 if (hbmColor)
380 DeleteObject(hbmColor);
381 if (hdc)
382 DeleteDC(hdc);
383 return NULL;
384 }
385
386 /* Create a font */
387 hFont = NULL;
388 if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
389 {
390 /* Override the current size with something manageable */
391 lf.lfHeight = -11;
392 lf.lfWidth = 0;
394 }
395 if (!hFont)
397
398 SetRect(&rect, 0, 0, cxIcon, cyIcon);
399
400 /* Draw hbmColor */
401 hBmpOld = SelectObject(hdc, hbmColor);
403 FillRect(hdc, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
404 hFontOld = SelectObject(hdc, hFont);
408 SelectObject(hdc, hFontOld);
409
410 /* Fill hbmMono with black */
411 SelectObject(hdc, hbmMono);
412 PatBlt(hdc, 0, 0, cxIcon, cyIcon, BLACKNESS);
413 SelectObject(hdc, hBmpOld);
414
415 /* Create an icon from hbmColor and hbmMono */
418 IconInfo.hbmColor = hbmColor;
419 IconInfo.hbmMask = hbmMono;
421
422 /* Clean up */
424 DeleteObject(hbmMono);
425 DeleteObject(hbmColor);
426 DeleteDC(hdc);
427
428 return hIcon;
429}
430
431static VOID
433{
434 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
435 TCHAR szKLID[CCH_LAYOUT_ID + 1], szName[MAX_PATH], szImeFile[80];
436
439 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
440
442 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
444
446
447 if (g_hTrayIcon)
449 g_hTrayIcon = tnid.hIcon;
450}
451
452static VOID
454{
455 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1 };
457
458 if (g_hTrayIcon)
459 {
462 }
463}
464
465static VOID
467{
468 NOTIFYICONDATA tnid = { sizeof(tnid), hwnd, 1, NIF_ICON | NIF_MESSAGE | NIF_TIP };
469 TCHAR szImeFile[80];
470
471 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
472
474 tnid.hIcon = CreateTrayIcon(szKLID, szImeFile);
476
478
479 if (g_hTrayIcon)
481 g_hTrayIcon = tnid.hIcon;
482}
483
484static BOOL CALLBACK
486{
487 PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_SYSCHARSET, lParam);
488 return TRUE;
489}
490
491static VOID
492ActivateLayout(HWND hwnd, ULONG uLayoutNum, HWND hwndTarget OPTIONAL, BOOL bNoActivate)
493{
494 HKL hKl;
495 TCHAR szKLID[CCH_LAYOUT_ID + 1], szLangName[MAX_PATH];
497
498 /* The layout number starts from one. Zero is invalid */
499 if (uLayoutNum == 0 || uLayoutNum > 0xFF) /* Invalid */
500 return;
501
502 GetKLIDFromLayoutNum(uLayoutNum, szKLID, ARRAYSIZE(szKLID));
503 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
504
505 /* Switch to the new keyboard layout */
506 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
507 UpdateTrayIcon(hwnd, szKLID, szLangName);
508
509 if (hwndTarget && !bNoActivate)
510 SetForegroundWindow(hwndTarget);
511
512 hKl = LoadKeyboardLayout(szKLID, KLF_ACTIVATE);
513 if (hKl)
515
516 /* Post WM_INPUTLANGCHANGEREQUEST */
517 if (hwndTarget)
518 {
519 PostMessage(hwndTarget, WM_INPUTLANGCHANGEREQUEST,
520 INPUTLANGCHANGE_SYSCHARSET, (LPARAM)hKl);
521 }
522 else
523 {
525 }
526
527 g_nCurrentLayoutNum = uLayoutNum;
528}
529
530static HMENU
532{
533 HMENU hMenu = CreatePopupMenu();
534 TCHAR szName[MAX_PATH], szKLID[CCH_LAYOUT_ID + 1], szImeFile[80];
535 HICON hIcon;
536 MENUITEMINFO mii = { sizeof(mii) };
537 INT iKL;
538
539 for (iKL = 0; iKL < g_cKLs; ++iKL)
540 {
541 GetKLIDFromHKL(g_ahKLs[iKL], szKLID, ARRAYSIZE(szKLID));
542 GetImeFile(szImeFile, ARRAYSIZE(szImeFile), szKLID);
543
544 if (!GetLayoutName(iKL + 1, szName, ARRAYSIZE(szName)))
545 continue;
546
547 mii.fMask = MIIM_ID | MIIM_STRING;
548 mii.wID = iKL + 1;
549 mii.dwTypeData = szName;
550
551 hIcon = CreateTrayIcon(szKLID, szImeFile);
552 if (hIcon)
553 {
554 mii.hbmpItem = BitmapFromIcon(hIcon);
555 if (mii.hbmpItem)
556 mii.fMask |= MIIM_BITMAP;
557 }
558
559 InsertMenuItem(hMenu, -1, TRUE, &mii);
561 }
562
564
565 return hMenu;
566}
567
568BOOL
570{
571 g_hHookDLL = LoadLibrary(_T("kbsdll.dll"));
572 if (!g_hHookDLL)
573 {
574 return FALSE;
575 }
576
579
581 {
582 return FALSE;
583 }
584
585 return KbSwitchSetHooks();
586}
587
588VOID
590{
592 {
595 }
596 if (g_hHookDLL)
597 {
600 }
601}
602
604{
605 INT iKL;
606
607 for (iKL = 0; iKL < g_cKLs; ++iKL)
608 {
609 if (g_ahKLs[iKL] == hKL)
610 return iKL + 1;
611 }
612
613 return 0;
614}
615
616ULONG
618{
619 return (g_nCurrentLayoutNum % g_cKLs) + 1;
620}
621
622UINT
624{
625 TCHAR szKLID[MAX_PATH], szLangName[MAX_PATH];
627
628 GetKLIDFromHKL(hKL, szKLID, ARRAYSIZE(szKLID));
629 LangID = (LANGID)_tcstoul(szKLID, NULL, 16);
630 GetLocaleInfo(LangID, LOCALE_SLANGUAGE, szLangName, ARRAYSIZE(szLangName));
631 UpdateTrayIcon(hwnd, szKLID, szLangName);
633
634 return 0;
635}
636
637HWND
639{
640 TCHAR szClass[64];
641 HWND hwndIME;
642 HWND hwndTarget = hwndFore;
643 if (hwndTarget == NULL)
644 hwndTarget = GetForegroundWindow();
645
646 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass));
647 if (_tcsicmp(szClass, szKbSwitcherName) == 0)
648 hwndTarget = g_hwndLastActive;
649
650 hwndIME = ImmGetDefaultIMEWnd(hwndTarget);
651 return (hwndIME ? hwndIME : hwndTarget);
652}
653
654UINT
656{
657 DWORD dwThreadID = GetWindowThreadProcessId(GetTargetWindow(hwndFore), NULL);
658 HKL hKL = GetKeyboardLayout(dwThreadID);
660
661 return 0;
662}
663
665{
666 TCHAR szClass[64];
667
668 hwndFore = GetAncestor(hwndFore, GA_ROOT);
669
670 if (!IsWindowVisible(hwndFore) || !GetClassName(hwndFore, szClass, ARRAYSIZE(szClass)))
671 return FALSE;
672
673 if (_tcsicmp(szClass, szKbSwitcherName) == 0 ||
674 _tcsicmp(szClass, TEXT("Shell_TrayWnd")) == 0)
675 {
676 return FALSE; /* Special window */
677 }
678
679 /* FIXME: CONWND needs special handling */
680 if (_tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
681 {
682 HKL hKL = GetKeyboardLayout(0);
684 }
685
686 g_hwndLastActive = hwndFore;
687 return TRUE;
688}
689
692{
693 static HMENU s_hMenu = NULL, s_hRightPopupMenu = NULL;
694 static UINT s_uTaskbarRestart;
695 POINT pt;
696 HMENU hLeftPopupMenu;
697
698 switch (Message)
699 {
700 case WM_CREATE:
701 {
702 if (!SetHooks())
703 {
704 MessageBox(NULL, TEXT("SetHooks failed."), NULL, MB_ICONERROR);
705 return -1;
706 }
707
709
712
714 s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
715 break;
716 }
717
718 case WM_LANG_CHANGED: /* Comes from kbsdll.dll and this module */
719 {
722 break;
723 }
724
725 case WM_WINDOW_ACTIVATE: /* Comes from kbsdll.dll and this module */
726 {
727 HWND hwndFore = GetForegroundWindow();
728 if (RememberLastActive(hwnd, hwndFore))
729 return UpdateLanguageDisplayCurrent(hwnd, hwndFore);
730 break;
731 }
732
733 case WM_NOTIFYICONMSG:
734 {
735 switch (lParam)
736 {
737 case WM_RBUTTONUP:
738 case WM_LBUTTONUP:
739 {
742
743 if (lParam == WM_LBUTTONUP)
744 {
745 /* Rebuild the left popup menu on every click to take care of keyboard layout changes */
746 hLeftPopupMenu = BuildLeftPopupMenu();
747 TrackPopupMenu(hLeftPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
748 DestroyMenu(hLeftPopupMenu);
749 }
750 else
751 {
752 if (!s_hRightPopupMenu)
753 {
755 s_hRightPopupMenu = GetSubMenu(s_hMenu, 0);
756 }
757 TrackPopupMenu(s_hRightPopupMenu, 0, pt.x, pt.y, 0, hwnd, NULL);
758 }
759
760 PostMessage(hwnd, WM_NULL, 0, 0);
761 break;
762 }
763 }
764 break;
765 }
766
767 case WM_COMMAND:
768 switch (LOWORD(wParam))
769 {
770 case ID_EXIT:
771 {
772 PostMessage(hwnd, WM_CLOSE, 0, 0);
773 break;
774 }
775
776 case ID_PREFERENCES:
777 {
779 TEXT("control.exe"), TEXT("input.dll"),
781 if (ret <= 32)
782 MessageBox(hwnd, _T("Can't start input.dll"), NULL, MB_ICONERROR);
783 break;
784 }
785
786 case ID_NEXTLAYOUT:
787 {
788 HWND hwndTarget = (HWND)lParam, hwndTargetSave = NULL;
789 DWORD dwThreadID;
790 HKL hKL;
791 UINT uNum;
792 TCHAR szClass[64];
793 BOOL bCONWND = FALSE;
794
795 if (hwndTarget == NULL)
796 hwndTarget = g_hwndLastActive;
797
798 /* FIXME: CONWND needs special handling */
799 if (hwndTarget &&
800 GetClassName(hwndTarget, szClass, ARRAYSIZE(szClass)) &&
801 _tcsicmp(szClass, TEXT("ConsoleWindowClass")) == 0)
802 {
803 bCONWND = TRUE;
804 hwndTargetSave = hwndTarget;
805 hwndTarget = NULL;
806 }
807
808 if (hwndTarget)
809 {
810 dwThreadID = GetWindowThreadProcessId(hwndTarget, NULL);
811 hKL = GetKeyboardLayout(dwThreadID);
812 uNum = GetLayoutNum(hKL);
813 if (uNum != 0)
814 g_nCurrentLayoutNum = uNum;
815 }
816
817 ActivateLayout(hwnd, GetNextLayout(), hwndTarget, TRUE);
818
819 /* FIXME: CONWND needs special handling */
820 if (bCONWND)
821 ActivateLayout(hwnd, g_nCurrentLayoutNum, hwndTargetSave, TRUE);
822
823 break;
824 }
825
826 default:
827 {
828 if (1 <= LOWORD(wParam) && LOWORD(wParam) <= 1000)
829 {
831 {
833 }
835 }
836 break;
837 }
838 }
839 break;
840
841 case WM_SETTINGCHANGE:
842 {
843 if (wParam == SPI_SETNONCLIENTMETRICS)
844 {
846 break;
847 }
848 }
849 break;
850
851 case WM_DESTROY:
852 {
853 DeleteHooks();
854 DestroyMenu(s_hMenu);
857 break;
858 }
859
860 default:
861 {
862 if (Message == s_uTaskbarRestart)
863 {
866 break;
867 }
868 else if (Message == ShellHookMessage)
869 {
870 if (wParam == HSHELL_LANGUAGE)
872 else if (wParam == HSHELL_WINDOWACTIVATED)
874
875 break;
876 }
878 }
879 }
880
881 return 0;
882}
883
885_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
886{
888 MSG msg;
890 HWND hwnd;
891
892 switch (GetUserDefaultUILanguage())
893 {
896 break;
897 default:
898 break;
899 }
900
902 if (!hMutex)
903 return 1;
904
906 {
908 return 1;
909 }
910
913
914 ZeroMemory(&WndClass, sizeof(WndClass));
915 WndClass.lpfnWndProc = WndProc;
916 WndClass.hInstance = hInstance;
917 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
918 WndClass.lpszClassName = szKbSwitcherName;
919 if (!RegisterClass(&WndClass))
920 {
922 return 1;
923 }
924
928
929 while (GetMessage(&msg, NULL, 0, 0))
930 {
933 }
934
936 return 0;
937}
#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:47
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:2417
#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:485
static VOID LoadSpecialIds(VOID)
Definition: kbswitch.c:61
static HBITMAP BitmapFromIcon(HICON hIcon)
Definition: kbswitch.c:313
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:466
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:301
static BOOL GetLayoutName(INT nLayoutNum, LPTSTR szName, SIZE_T NameLength)
Definition: kbswitch.c:211
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:603
SPECIAL_ID g_SpecialIds[80]
Definition: kbswitch.c:58
static HICON CreateTrayIcon(LPTSTR szKLID, LPCTSTR szImeFile OPTIONAL)
Definition: kbswitch.c:335
static HKL GetHKLFromLayoutNum(INT nLayoutNum)
Definition: kbswitch.c:179
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
Definition: kbswitch.c:691
static HMENU BuildLeftPopupMenu(VOID)
Definition: kbswitch.c:531
#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:664
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:492
ULONG GetNextLayout(VOID)
Definition: kbswitch.c:617
static BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LPARAM lParam)
Definition: kbswitch.c:286
HWND g_hwndLastActive
Definition: kbswitch.c:47
VOID DeleteHooks(VOID)
Definition: kbswitch.c:589
static VOID GetKLIDFromLayoutNum(INT nLayoutNum, LPTSTR szKLID, SIZE_T KLIDLength)
Definition: kbswitch.c:194
INT g_cKLs
Definition: kbswitch.c:48
UINT UpdateLanguageDisplay(HWND hwnd, HKL hKL)
Definition: kbswitch.c:623
static BOOL GetImeFile(LPTSTR szImeFile, SIZE_T cchImeFile, LPCTSTR szKLID)
Definition: kbswitch.c:247
HICON g_hTrayIcon
Definition: kbswitch.c:46
UINT UpdateLanguageDisplayCurrent(HWND hwnd, HWND hwndFore)
Definition: kbswitch.c:655
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:569
static BOOL GetSystemLibraryPath(LPTSTR szPath, SIZE_T cchPath, LPCTSTR FileName)
Definition: kbswitch.c:200
HANDLE hProcessHeap
Definition: kbswitch.c:43
static VOID AddTrayIcon(HWND hwnd)
Definition: kbswitch.c:432
#define SPECIAL_MASK
Definition: kbswitch.c:30
static VOID DeleteTrayIcon(HWND hwnd)
Definition: kbswitch.c:453
HWND GetTargetWindow(HWND hwndFore)
Definition: kbswitch.c:638
#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:810
#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:60
HICON hIcon
Definition: msconfig.c:44
UINT_PTR HKL
Definition: msctf.idl:104
__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:3115
BOOL fIcon
Definition: winuser.h:3113
DWORD xHotspot
Definition: winuser.h:3114
HBITMAP hbmColor
Definition: winuser.h:3117
HBITMAP hbmMask
Definition: winuser.h:3116
UINT uCallbackMessage
Definition: shellapi.h:228
CHAR szTip[128]
Definition: shellapi.h:234
HICON hIcon
Definition: kbswitch.c:282
LPSTR dwTypeData
Definition: winuser.h:3241
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
int32_t INT_PTR
Definition: typedefs.h:64
WORD LANGID
Definition: typedefs.h:81
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:1720
#define ZeroMemory
Definition: winbase.h:1670
#define GetSystemDirectory
Definition: winbase.h:3713
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
#define LoadLibraryEx
Definition: winbase.h:3734
#define LoadLibrary
Definition: winbase.h:3733
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:342
#define CreateMutex
Definition: winbase.h:3627
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
#define EnumResourceNames
Definition: winbase.h:3643
_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:764
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:846
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define WM_CLOSE
Definition: winuser.h:1611
#define MIIM_STRING
Definition: winuser.h:722
HICON WINAPI CreateIconIndirect(_In_ PICONINFO)
Definition: cursoricon.c:2550
#define GA_ROOT
Definition: winuser.h:2779
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define MIIM_ID
Definition: winuser.h:717
#define COLOR_MENU
Definition: winuser.h:911
#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:1598
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
#define GetClassName
Definition: winuser.h:5773
#define KLF_ACTIVATE
Definition: winuser.h:111
BOOL WINAPI RegisterShellHookWindow(_In_ HWND)
#define COLOR_HIGHLIGHT
Definition: winuser.h:920
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define DT_SINGLELINE
Definition: winuser.h:540
#define WM_COMMAND
Definition: winuser.h:1730
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define IDC_ARROW
Definition: winuser.h:682
BOOL WINAPI GetCursorPos(_Out_ LPPOINT)
Definition: cursoricon.c:2639
#define WM_RBUTTONUP
Definition: winuser.h:1770
#define InsertMenuItem
Definition: winuser.h:5794
#define SM_CYSMICON
Definition: winuser.h:1007
#define MF_CHECKED
Definition: winuser.h:132
#define LoadKeyboardLayout
Definition: winuser.h:5806
#define SPI_GETICONTITLELOGFONT
Definition: winuser.h:1370
DWORD WINAPI CheckMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
#define DrawText
Definition: winuser.h:5761
#define CreateWindow
Definition: winuser.h:5744
#define HWND_DESKTOP
Definition: winuser.h:1199
#define MB_ICONERROR
Definition: winuser.h:781
#define WM_SETTINGCHANGE
Definition: winuser.h:1619
#define GetMessage
Definition: winuser.h:5780
#define SM_CXSMICON
Definition: winuser.h:1006
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
#define RegisterWindowMessage
Definition: winuser.h:5830
UINT WINAPI GetKeyboardLayoutList(_In_ int nBuff, _Out_writes_to_opt_(nBuff, return) HKL FAR *lpList)
#define MIIM_BITMAP
Definition: winuser.h:723
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:1997
#define LoadIcon
Definition: winuser.h:5803
#define WM_NULL
Definition: winuser.h:1597
#define LoadCursor
Definition: winuser.h:5802
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:921
HDC WINAPI GetDC(_In_opt_ HWND)
#define LoadMenu
Definition: winuser.h:5807
#define WM_LBUTTONUP
Definition: winuser.h:1767
#define DT_VCENTER
Definition: winuser.h:543
#define PostMessage
Definition: winuser.h:5822
#define LoadImage
Definition: winuser.h:5805
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define MessageBox
Definition: winuser.h:5812
#define LR_DEFAULTCOLOR
Definition: winuser.h:1081
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define RegisterClass
Definition: winuser.h:5826
#define WM_DESTROY
Definition: winuser.h:1599
#define DispatchMessage
Definition: winuser.h:5755
HKL WINAPI ActivateKeyboardLayout(_In_ HKL, _In_ UINT)
#define SystemParametersInfo
Definition: winuser.h:5848
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:2022
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