[INPUT.CPL]
[reactos.git] / reactos / dll / cpl / input / layout_list.c
1 /*
2 * PROJECT: input.dll
3 * FILE: dll/cpl/input/layout_list.c
4 * PURPOSE: input.dll
5 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
6 */
7
8 #include "layout_list.h"
9
10
11 static LAYOUT_LIST_NODE *_LayoutList = NULL;
12
13
14 static LAYOUT_LIST_NODE*
15 LayoutList_AppendNode(DWORD dwId, DWORD dwSpecialId, const WCHAR *pszName)
16 {
17 LAYOUT_LIST_NODE *pCurrent;
18 LAYOUT_LIST_NODE *pNew;
19
20 if (pszName == NULL)
21 return NULL;
22
23 pCurrent = _LayoutList;
24
25 pNew = (LAYOUT_LIST_NODE*)malloc(sizeof(LAYOUT_LIST_NODE));
26 if (pNew == NULL)
27 return NULL;
28
29 ZeroMemory(pNew, sizeof(LAYOUT_LIST_NODE));
30
31 pNew->pszName = _wcsdup(pszName);
32 if (pNew->pszName == NULL)
33 {
34 free(pNew);
35 return NULL;
36 }
37
38 pNew->dwId = dwId;
39 pNew->dwSpecialId = dwSpecialId;
40
41 if (pCurrent == NULL)
42 {
43 _LayoutList = pNew;
44 }
45 else
46 {
47 while (pCurrent->pNext != NULL)
48 {
49 pCurrent = pCurrent->pNext;
50 }
51
52 pNew->pPrev = pCurrent;
53 pCurrent->pNext = pNew;
54 }
55
56 return pNew;
57 }
58
59
60 VOID
61 LayoutList_Destroy(VOID)
62 {
63 LAYOUT_LIST_NODE *pCurrent;
64
65 if (_LayoutList == NULL)
66 return;
67
68 pCurrent = _LayoutList;
69
70 while (pCurrent != NULL)
71 {
72 LAYOUT_LIST_NODE *pNext = pCurrent->pNext;
73
74 free(pCurrent->pszName);
75 free(pCurrent);
76
77 pCurrent = pNext;
78 }
79
80 _LayoutList = NULL;
81 }
82
83
84 VOID
85 LayoutList_Create(VOID)
86 {
87 WCHAR szSystemDirectory[MAX_PATH];
88 WCHAR szLayoutId[MAX_PATH];
89 DWORD dwIndex = 0;
90 DWORD dwSize;
91 HKEY hKey;
92
93 if (!GetSystemDirectoryW(szSystemDirectory, ARRAYSIZE(szSystemDirectory)))
94 {
95 return;
96 }
97
98 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
99 L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts",
100 0,
101 KEY_ENUMERATE_SUB_KEYS,
102 &hKey) != ERROR_SUCCESS)
103 {
104 return;
105 }
106
107 dwSize = ARRAYSIZE(szLayoutId);
108
109 while (RegEnumKeyExW(hKey, dwIndex, szLayoutId, &dwSize,
110 NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
111 {
112 HKEY hLayoutKey;
113
114 if (RegOpenKeyExW(hKey,
115 szLayoutId,
116 0,
117 KEY_QUERY_VALUE,
118 &hLayoutKey) == ERROR_SUCCESS)
119 {
120 WCHAR szBuffer[MAX_PATH];
121
122 dwSize = sizeof(szBuffer);
123
124 if (RegQueryValueExW(hLayoutKey,
125 L"Layout File",
126 NULL, NULL,
127 (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS)
128 {
129 WCHAR szFilePath[MAX_PATH];
130
131 StringCchPrintfW(szFilePath, ARRAYSIZE(szFilePath),
132 L"%s\\%s", szSystemDirectory, szBuffer);
133
134 if (GetFileAttributesW(szFilePath) != INVALID_FILE_ATTRIBUTES)
135 {
136 DWORD dwSpecialId = 0;
137
138 dwSize = sizeof(szBuffer);
139
140 if (RegQueryValueExW(hLayoutKey,
141 L"Layout Id",
142 NULL, NULL,
143 (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS)
144 {
145 dwSpecialId = DWORDfromString(szBuffer);
146 }
147
148 dwSize = sizeof(szBuffer);
149
150 if (RegQueryValueExW(hLayoutKey,
151 L"Layout Display Name",
152 NULL, NULL,
153 (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS &&
154 szBuffer[0] == L'@')
155 {
156 WCHAR *pBuffer;
157 WCHAR *pIndex;
158
159 /* Move to the position after the character "@" */
160 pBuffer = szBuffer + 1;
161
162 /* Get a pointer to the beginning ",-" */
163 pIndex = wcsstr(pBuffer, L",-");
164
165 if (pIndex != NULL)
166 {
167 WCHAR szPath[MAX_PATH];
168 INT iIndex;
169
170 /* Convert the number in the string after the ",-" */
171 iIndex = _wtoi(pIndex + 2);
172
173 pIndex[0] = 0;
174
175 if (ExpandEnvironmentStringsW(pBuffer, szPath, ARRAYSIZE(szPath)) != 0)
176 {
177 HANDLE hHandle;
178
179 hHandle = LoadLibraryW(szPath);
180 if (hHandle != NULL)
181 {
182 INT iLength = LoadStringW(hHandle, iIndex, szBuffer, ARRAYSIZE(szBuffer));
183
184 FreeLibrary(hHandle);
185
186 if (iLength != 0)
187 {
188 DWORD dwLayoutId = DWORDfromString(szLayoutId);
189
190 LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer);
191 }
192 else
193 {
194 goto NotTranslated;
195 }
196 }
197 else
198 {
199 goto NotTranslated;
200 }
201 }
202 else
203 {
204 goto NotTranslated;
205 }
206 }
207 else
208 {
209 goto NotTranslated;
210 }
211 }
212 else
213 {
214 NotTranslated:
215 dwSize = sizeof(szBuffer);
216
217 if (RegQueryValueExW(hLayoutKey,
218 L"Layout Text",
219 NULL, NULL,
220 (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS)
221 {
222 DWORD dwLayoutId = DWORDfromString(szLayoutId);
223
224 LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer);
225 }
226 }
227 }
228 }
229
230 RegCloseKey(hLayoutKey);
231 }
232
233 dwSize = ARRAYSIZE(szLayoutId);
234 ++dwIndex;
235 }
236
237 RegCloseKey(hKey);
238 }
239
240
241 LAYOUT_LIST_NODE*
242 LayoutList_GetByHkl(HKL hkl)
243 {
244 LAYOUT_LIST_NODE *pCurrent;
245
246 if ((HIWORD(hkl) & 0xF000) == 0xF000)
247 {
248 DWORD dwSpecialId = (HIWORD(hkl) & 0x0FFF);
249
250 for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext)
251 {
252 if (dwSpecialId == pCurrent->dwSpecialId)
253 {
254 return pCurrent;
255 }
256 }
257 }
258 else
259 {
260 for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext)
261 {
262 if (HIWORD(hkl) == LOWORD(pCurrent->dwId))
263 {
264 return pCurrent;
265 }
266 }
267 }
268
269 return NULL;
270 }
271
272
273 LAYOUT_LIST_NODE*
274 LayoutList_GetFirst(VOID)
275 {
276 return _LayoutList;
277 }