2dafdd64c19a2a773e9c3a76268ac5e70981fb7e
[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 = DuplicateString(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 = sizeof(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 szPath[MAX_PATH];
157 WCHAR *pBuffer;
158 WCHAR *pIndex;
159 INT iIndex;
160
161 /* Move to the position after the character "@" */
162 pBuffer = szBuffer + 1;
163
164 /* Get a pointer to the beginning ",-" */
165 pIndex = wcsstr(pBuffer, L",-");
166
167 /* Convert the number in the string after the ",-" */
168 iIndex = _wtoi(pIndex + 2);
169
170 pIndex[0] = 0;
171
172 if (ExpandEnvironmentStringsW(pBuffer, szPath, ARRAYSIZE(szPath)) != 0)
173 {
174 HANDLE hHandle;
175
176 hHandle = LoadLibraryW(szPath);
177 if (hHandle != NULL)
178 {
179 INT iLength = LoadStringW(hHandle, iIndex, szBuffer, ARRAYSIZE(szBuffer));
180
181 FreeLibrary(hHandle);
182
183 if (iLength != 0)
184 {
185 DWORD dwLayoutId = DWORDfromString(szLayoutId);
186
187 LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer);
188 }
189 else
190 {
191 goto NotTranslated;
192 }
193 }
194 else
195 {
196 goto NotTranslated;
197 }
198 }
199 else
200 {
201 goto NotTranslated;
202 }
203 }
204 else
205 {
206 NotTranslated:
207 dwSize = sizeof(szBuffer);
208
209 if (RegQueryValueExW(hLayoutKey,
210 L"Layout Text",
211 NULL, NULL,
212 (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS)
213 {
214 DWORD dwLayoutId = DWORDfromString(szLayoutId);
215
216 LayoutList_AppendNode(dwLayoutId, dwSpecialId, szBuffer);
217 }
218 }
219 }
220 }
221
222 RegCloseKey(hLayoutKey);
223 }
224
225 dwSize = sizeof(szLayoutId);
226 ++dwIndex;
227 }
228
229 RegCloseKey(hKey);
230 }
231
232
233 LAYOUT_LIST_NODE*
234 LayoutList_GetByHkl(HKL hkl)
235 {
236 LAYOUT_LIST_NODE *pCurrent;
237
238 if ((HIWORD(hkl) & 0xF000) == 0xF000)
239 {
240 DWORD dwSpecialId = (HIWORD(hkl) & 0x0FFF);
241
242 for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext)
243 {
244 if (dwSpecialId == pCurrent->dwSpecialId)
245 {
246 return pCurrent;
247 }
248 }
249 }
250 else
251 {
252 for (pCurrent = _LayoutList; pCurrent != NULL; pCurrent = pCurrent->pNext)
253 {
254 if (HIWORD(hkl) == LOWORD(pCurrent->dwId))
255 {
256 return pCurrent;
257 }
258 }
259 }
260
261 return NULL;
262 }
263
264
265 LAYOUT_LIST_NODE*
266 LayoutList_GetFirst(VOID)
267 {
268 return _LayoutList;
269 }