1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT: ReactOS International Control Panel
3*c2c66affSColin Finck * FILE: dll/cpl/intl/kblayouts.c
4*c2c66affSColin Finck * PURPOSE: Functions for manipulation with keyboard layouts
5*c2c66affSColin Finck * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
6*c2c66affSColin Finck */
7*c2c66affSColin Finck
8*c2c66affSColin Finck #include "intl.h"
9*c2c66affSColin Finck
10*c2c66affSColin Finck /* Character Count of a layout ID like "00000409" */
11*c2c66affSColin Finck #define CCH_LAYOUT_ID 8
12*c2c66affSColin Finck
13*c2c66affSColin Finck /* Maximum Character Count of a ULONG in decimal */
14*c2c66affSColin Finck #define CCH_ULONG_DEC 10
15*c2c66affSColin Finck
16*c2c66affSColin Finck
17*c2c66affSColin Finck /* szLayoutID like 00000409, szLangID like 00000409 */
18*c2c66affSColin Finck static BOOL
IsLayoutExists(PWSTR szLayoutID,PWSTR szLangID)19*c2c66affSColin Finck IsLayoutExists(PWSTR szLayoutID, PWSTR szLangID)
20*c2c66affSColin Finck {
21*c2c66affSColin Finck HKEY hKey, hSubKey;
22*c2c66affSColin Finck WCHAR szPreload[CCH_LAYOUT_ID + 1], szLayoutNum[3 + 1],
23*c2c66affSColin Finck szTmp[CCH_LAYOUT_ID + 1], szOldLangID[CCH_LAYOUT_ID + 1];
24*c2c66affSColin Finck DWORD dwIndex = 0, dwType, dwSize;
25*c2c66affSColin Finck BOOL IsLangExists = FALSE;
26*c2c66affSColin Finck LANGID langid;
27*c2c66affSColin Finck
28*c2c66affSColin Finck if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload",
29*c2c66affSColin Finck 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
30*c2c66affSColin Finck {
31*c2c66affSColin Finck dwSize = sizeof(szLayoutNum);
32*c2c66affSColin Finck
33*c2c66affSColin Finck while (RegEnumValueW(hKey, dwIndex, szLayoutNum, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
34*c2c66affSColin Finck {
35*c2c66affSColin Finck dwSize = sizeof(szPreload);
36*c2c66affSColin Finck if (RegQueryValueExW(hKey, szLayoutNum, NULL, NULL, (LPBYTE)szPreload, &dwSize) != ERROR_SUCCESS)
37*c2c66affSColin Finck {
38*c2c66affSColin Finck RegCloseKey(hKey);
39*c2c66affSColin Finck return FALSE;
40*c2c66affSColin Finck }
41*c2c66affSColin Finck
42*c2c66affSColin Finck langid = (LANGID)wcstoul(szPreload, NULL, 16);
43*c2c66affSColin Finck GetLocaleInfoW(langid, LOCALE_ILANGUAGE, szTmp, sizeof(szTmp) / sizeof(WCHAR));
44*c2c66affSColin Finck wsprintf(szOldLangID, L"0000%s", szTmp);
45*c2c66affSColin Finck
46*c2c66affSColin Finck if (wcscmp(szOldLangID, szLangID) == 0)
47*c2c66affSColin Finck IsLangExists = TRUE;
48*c2c66affSColin Finck else
49*c2c66affSColin Finck IsLangExists = FALSE;
50*c2c66affSColin Finck
51*c2c66affSColin Finck if (szPreload[0] == 'd')
52*c2c66affSColin Finck {
53*c2c66affSColin Finck if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes",
54*c2c66affSColin Finck 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
55*c2c66affSColin Finck {
56*c2c66affSColin Finck dwSize = sizeof(szTmp);
57*c2c66affSColin Finck RegQueryValueExW(hSubKey, szPreload, NULL, NULL, (LPBYTE)szTmp, &dwSize);
58*c2c66affSColin Finck
59*c2c66affSColin Finck if ((wcscmp(szTmp, szLayoutID) == 0)&&(IsLangExists))
60*c2c66affSColin Finck {
61*c2c66affSColin Finck RegCloseKey(hSubKey);
62*c2c66affSColin Finck RegCloseKey(hKey);
63*c2c66affSColin Finck return TRUE;
64*c2c66affSColin Finck }
65*c2c66affSColin Finck }
66*c2c66affSColin Finck }
67*c2c66affSColin Finck else
68*c2c66affSColin Finck {
69*c2c66affSColin Finck if ((wcscmp(szPreload, szLayoutID) == 0) && (IsLangExists))
70*c2c66affSColin Finck {
71*c2c66affSColin Finck RegCloseKey(hKey);
72*c2c66affSColin Finck return TRUE;
73*c2c66affSColin Finck }
74*c2c66affSColin Finck }
75*c2c66affSColin Finck
76*c2c66affSColin Finck IsLangExists = FALSE;
77*c2c66affSColin Finck dwSize = sizeof(szLayoutNum);
78*c2c66affSColin Finck dwIndex++;
79*c2c66affSColin Finck }
80*c2c66affSColin Finck
81*c2c66affSColin Finck RegCloseKey(hKey);
82*c2c66affSColin Finck }
83*c2c66affSColin Finck
84*c2c66affSColin Finck return FALSE;
85*c2c66affSColin Finck }
86*c2c66affSColin Finck
87*c2c66affSColin Finck static INT
GetLayoutCount(PWSTR szLang)88*c2c66affSColin Finck GetLayoutCount(PWSTR szLang)
89*c2c66affSColin Finck {
90*c2c66affSColin Finck HKEY hKey;
91*c2c66affSColin Finck WCHAR szLayoutID[3 + 1], szPreload[CCH_LAYOUT_ID + 1], szLOLang[MAX_PATH];
92*c2c66affSColin Finck DWORD dwIndex = 0, dwType, dwSize;
93*c2c66affSColin Finck UINT Count = 0, i, j;
94*c2c66affSColin Finck
95*c2c66affSColin Finck if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload",
96*c2c66affSColin Finck 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
97*c2c66affSColin Finck {
98*c2c66affSColin Finck dwSize = sizeof(szLayoutID);
99*c2c66affSColin Finck
100*c2c66affSColin Finck while (RegEnumValue(hKey, dwIndex, szLayoutID, &dwSize, NULL, &dwType, NULL, NULL) == ERROR_SUCCESS)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck dwSize = sizeof(szPreload);
103*c2c66affSColin Finck RegQueryValueExW(hKey, szLayoutID, NULL, NULL, (LPBYTE)szPreload, &dwSize);
104*c2c66affSColin Finck
105*c2c66affSColin Finck for (i = 4, j = 0; i < wcslen(szPreload)+1; i++, j++)
106*c2c66affSColin Finck szLOLang[j] = szPreload[i];
107*c2c66affSColin Finck
108*c2c66affSColin Finck if (wcscmp(szLOLang, szLang) == 0) Count += 1;
109*c2c66affSColin Finck
110*c2c66affSColin Finck dwSize = sizeof(szLayoutID);
111*c2c66affSColin Finck dwIndex++;
112*c2c66affSColin Finck }
113*c2c66affSColin Finck
114*c2c66affSColin Finck RegCloseKey(hKey);
115*c2c66affSColin Finck }
116*c2c66affSColin Finck
117*c2c66affSColin Finck return Count;
118*c2c66affSColin Finck }
119*c2c66affSColin Finck
120*c2c66affSColin Finck /* szLayoutID like 00000409, szLangID like 00000409 */
121*c2c66affSColin Finck static BOOL
AddNewLayout(PWSTR szLayoutID,PWSTR szLangID)122*c2c66affSColin Finck AddNewLayout(PWSTR szLayoutID, PWSTR szLangID)
123*c2c66affSColin Finck {
124*c2c66affSColin Finck WCHAR NewLayout[CCH_ULONG_DEC + 1], Lang[MAX_PATH],
125*c2c66affSColin Finck LangID[CCH_LAYOUT_ID + 1], SubPath[CCH_LAYOUT_ID + 1];
126*c2c66affSColin Finck HKEY hKey, hSubKey;
127*c2c66affSColin Finck DWORD cValues;
128*c2c66affSColin Finck LCID lcid;
129*c2c66affSColin Finck
130*c2c66affSColin Finck if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
131*c2c66affSColin Finck {
132*c2c66affSColin Finck if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &cValues, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
133*c2c66affSColin Finck {
134*c2c66affSColin Finck _ultow(cValues + 1, NewLayout, 10);
135*c2c66affSColin Finck
136*c2c66affSColin Finck lcid = wcstoul(szLangID, NULL, 16);
137*c2c66affSColin Finck
138*c2c66affSColin Finck GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Lang, sizeof(Lang) / sizeof(WCHAR));
139*c2c66affSColin Finck wsprintf(LangID, L"0000%s", Lang);
140*c2c66affSColin Finck
141*c2c66affSColin Finck if (IsLayoutExists(szLayoutID, LangID))
142*c2c66affSColin Finck {
143*c2c66affSColin Finck RegCloseKey(hKey);
144*c2c66affSColin Finck return FALSE;
145*c2c66affSColin Finck }
146*c2c66affSColin Finck
147*c2c66affSColin Finck if (GetLayoutCount(Lang) >= 1)
148*c2c66affSColin Finck {
149*c2c66affSColin Finck wsprintf(SubPath, L"d%03d%s", GetLayoutCount(Lang), Lang);
150*c2c66affSColin Finck }
151*c2c66affSColin Finck else if ((wcscmp(LangID, szLayoutID) != 0) && (GetLayoutCount(Lang) == 0))
152*c2c66affSColin Finck {
153*c2c66affSColin Finck wsprintf(SubPath, L"d%03d%s", 0, Lang);
154*c2c66affSColin Finck }
155*c2c66affSColin Finck else SubPath[0] = L'\0';
156*c2c66affSColin Finck
157*c2c66affSColin Finck if (wcslen(SubPath) != 0)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0, NULL,
160*c2c66affSColin Finck REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
161*c2c66affSColin Finck NULL, &hSubKey, NULL) == ERROR_SUCCESS)
162*c2c66affSColin Finck {
163*c2c66affSColin Finck if (RegSetValueExW(hSubKey, SubPath, 0, REG_SZ, (LPBYTE)szLayoutID,
164*c2c66affSColin Finck (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(WCHAR))) != ERROR_SUCCESS)
165*c2c66affSColin Finck {
166*c2c66affSColin Finck RegCloseKey(hSubKey);
167*c2c66affSColin Finck RegCloseKey(hKey);
168*c2c66affSColin Finck return FALSE;
169*c2c66affSColin Finck }
170*c2c66affSColin Finck RegCloseKey(hSubKey);
171*c2c66affSColin Finck }
172*c2c66affSColin Finck lstrcpy(szLayoutID, SubPath);
173*c2c66affSColin Finck }
174*c2c66affSColin Finck
175*c2c66affSColin Finck RegSetValueExW(hKey,
176*c2c66affSColin Finck NewLayout,
177*c2c66affSColin Finck 0,
178*c2c66affSColin Finck REG_SZ,
179*c2c66affSColin Finck (LPBYTE)szLayoutID,
180*c2c66affSColin Finck (DWORD)((CCH_LAYOUT_ID + 1) * sizeof(WCHAR)));
181*c2c66affSColin Finck }
182*c2c66affSColin Finck RegCloseKey(hKey);
183*c2c66affSColin Finck }
184*c2c66affSColin Finck
185*c2c66affSColin Finck return TRUE;
186*c2c66affSColin Finck }
187*c2c66affSColin Finck
188*c2c66affSColin Finck VOID
AddNewKbLayoutsByLcid(LCID Lcid)189*c2c66affSColin Finck AddNewKbLayoutsByLcid(LCID Lcid)
190*c2c66affSColin Finck {
191*c2c66affSColin Finck HINF hIntlInf;
192*c2c66affSColin Finck WCHAR szLang[CCH_LAYOUT_ID + 1], szLangID[CCH_LAYOUT_ID + 1];
193*c2c66affSColin Finck WCHAR szLangStr[MAX_STR_SIZE], szLayoutStr[MAX_STR_SIZE], szStr[MAX_STR_SIZE];
194*c2c66affSColin Finck INFCONTEXT InfContext;
195*c2c66affSColin Finck LONG Count;
196*c2c66affSColin Finck DWORD FieldCount, Index;
197*c2c66affSColin Finck
198*c2c66affSColin Finck GetLocaleInfoW(MAKELCID(Lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, szLang, sizeof(szLang) / sizeof(WCHAR));
199*c2c66affSColin Finck wsprintf(szLangID, L"0000%s", szLang);
200*c2c66affSColin Finck
201*c2c66affSColin Finck hIntlInf = SetupOpenInfFileW(L"intl.inf", NULL, INF_STYLE_WIN4, NULL);
202*c2c66affSColin Finck
203*c2c66affSColin Finck if (hIntlInf == INVALID_HANDLE_VALUE)
204*c2c66affSColin Finck return;
205*c2c66affSColin Finck
206*c2c66affSColin Finck if (!SetupOpenAppendInfFile(NULL, hIntlInf, NULL))
207*c2c66affSColin Finck {
208*c2c66affSColin Finck SetupCloseInfFile(hIntlInf);
209*c2c66affSColin Finck hIntlInf = NULL;
210*c2c66affSColin Finck return;
211*c2c66affSColin Finck }
212*c2c66affSColin Finck
213*c2c66affSColin Finck Count = SetupGetLineCount(hIntlInf, L"Locales");
214*c2c66affSColin Finck if (Count <= 0) return;
215*c2c66affSColin Finck
216*c2c66affSColin Finck if (SetupFindFirstLine(hIntlInf, L"Locales", szLangID, &InfContext))
217*c2c66affSColin Finck {
218*c2c66affSColin Finck FieldCount = SetupGetFieldCount(&InfContext);
219*c2c66affSColin Finck
220*c2c66affSColin Finck if (FieldCount != 0)
221*c2c66affSColin Finck {
222*c2c66affSColin Finck for (Index = 5; Index <= FieldCount; Index++)
223*c2c66affSColin Finck {
224*c2c66affSColin Finck if (SetupGetStringField(&InfContext, Index, szStr, MAX_STR_SIZE, NULL))
225*c2c66affSColin Finck {
226*c2c66affSColin Finck INT i, j;
227*c2c66affSColin Finck
228*c2c66affSColin Finck if (wcslen(szStr) != 13) continue;
229*c2c66affSColin Finck
230*c2c66affSColin Finck wsprintf(szLangStr, L"0000%s", szStr);
231*c2c66affSColin Finck szLangStr[8] = L'\0';
232*c2c66affSColin Finck
233*c2c66affSColin Finck for (i = 5, j = 0; i <= wcslen(szStr); i++, j++)
234*c2c66affSColin Finck szLayoutStr[j] = szStr[i];
235*c2c66affSColin Finck
236*c2c66affSColin Finck AddNewLayout(szLayoutStr, szLangStr);
237*c2c66affSColin Finck }
238*c2c66affSColin Finck }
239*c2c66affSColin Finck }
240*c2c66affSColin Finck }
241*c2c66affSColin Finck SetupCloseInfFile(hIntlInf);
242*c2c66affSColin Finck }
243