xref: /reactos/dll/cpl/input/layout_list.c (revision c2c66aff)
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 }
278