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