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