1 /* 2 * ReactOS kernel 3 * Copyright (C) 2008 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS text-mode setup 22 * FILE: base/setup/usetup/mui.c 23 * PURPOSE: Text-mode setup 24 * PROGRAMMER: 25 */ 26 27 /* INCLUDES *****************************************************************/ 28 29 #include "precomp.h" 30 #include "mui.h" 31 #include "muifonts.h" 32 #include "muilanguages.h" 33 #include "registry.h" 34 35 #define NDEBUG 36 #include <debug.h> 37 38 39 /* FUNCTIONS ****************************************************************/ 40 41 static 42 ULONG 43 FindLanguageIndex( 44 IN PCWSTR LanguageId) 45 { 46 ULONG lngIndex = 0; 47 48 if (LanguageId == NULL) 49 { 50 /* Default to en-US */ 51 // return 0; // FIXME!! 52 LanguageId = L"00000409"; 53 } 54 55 while (MUILanguageList[lngIndex].LanguageID != NULL) 56 { 57 if (_wcsicmp(MUILanguageList[lngIndex].LanguageID, LanguageId) == 0) 58 { 59 return lngIndex; 60 } 61 62 lngIndex++; 63 } 64 65 return 0; 66 } 67 68 BOOLEAN 69 IsLanguageAvailable( 70 IN PCWSTR LanguageId) 71 { 72 ULONG lngIndex = 0; 73 74 while (MUILanguageList[lngIndex].LanguageID != NULL) 75 { 76 if (_wcsicmp(MUILanguageList[lngIndex].LanguageID, LanguageId) == 0) 77 return TRUE; 78 79 lngIndex++; 80 } 81 82 return FALSE; 83 } 84 85 86 PCWSTR 87 MUIDefaultKeyboardLayout( 88 IN PCWSTR LanguageId) 89 { 90 ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0); 91 return MUILanguageList[lngIndex].MuiLayouts[0].LayoutID; 92 } 93 94 PCWSTR 95 MUIGetOEMCodePage( 96 IN PCWSTR LanguageId) 97 { 98 ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0); 99 return MUILanguageList[lngIndex].OEMCPage; 100 } 101 102 PCWSTR 103 MUIGetGeoID( 104 IN PCWSTR LanguageId) 105 { 106 ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0); 107 return MUILanguageList[lngIndex].GeoID; 108 } 109 110 const MUI_LAYOUTS* 111 MUIGetLayoutsList( 112 IN PCWSTR LanguageId) 113 { 114 ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0); 115 return MUILanguageList[lngIndex].MuiLayouts; 116 } 117 118 119 static 120 BOOLEAN 121 AddHotkeySettings( 122 IN PCWSTR Hotkey, 123 IN PCWSTR LangHotkey, 124 IN PCWSTR LayoutHotkey) 125 { 126 OBJECT_ATTRIBUTES ObjectAttributes; 127 UNICODE_STRING KeyName; 128 UNICODE_STRING ValueName; 129 HANDLE KeyHandle; 130 ULONG Disposition; 131 NTSTATUS Status; 132 133 RtlInitUnicodeString(&KeyName, 134 L".DEFAULT\\Keyboard Layout\\Toggle"); 135 InitializeObjectAttributes(&ObjectAttributes, 136 &KeyName, 137 OBJ_CASE_INSENSITIVE, 138 GetRootKeyByPredefKey(HKEY_USERS, NULL), 139 NULL); 140 141 Status = NtCreateKey(&KeyHandle, 142 KEY_SET_VALUE, 143 &ObjectAttributes, 144 0, 145 NULL, 146 REG_OPTION_NON_VOLATILE, 147 &Disposition); 148 if (!NT_SUCCESS(Status)) 149 { 150 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); 151 return FALSE; 152 } 153 154 RtlInitUnicodeString(&ValueName, 155 L"Hotkey"); 156 157 Status = NtSetValueKey(KeyHandle, 158 &ValueName, 159 0, 160 REG_SZ, 161 (PVOID)Hotkey, 162 (1 + 1) * sizeof(WCHAR)); 163 if (!NT_SUCCESS(Status)) 164 { 165 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 166 NtClose(KeyHandle); 167 return FALSE; 168 } 169 170 RtlInitUnicodeString(&ValueName, 171 L"Language Hotkey"); 172 173 Status = NtSetValueKey(KeyHandle, 174 &ValueName, 175 0, 176 REG_SZ, 177 (PVOID)LangHotkey, 178 (1 + 1) * sizeof(WCHAR)); 179 if (!NT_SUCCESS(Status)) 180 { 181 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 182 NtClose(KeyHandle); 183 return FALSE; 184 } 185 186 RtlInitUnicodeString(&ValueName, 187 L"Layout Hotkey"); 188 189 Status = NtSetValueKey(KeyHandle, 190 &ValueName, 191 0, 192 REG_SZ, 193 (PVOID)LayoutHotkey, 194 (1 + 1) * sizeof(WCHAR)); 195 if (!NT_SUCCESS(Status)) 196 { 197 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 198 NtClose(KeyHandle); 199 return FALSE; 200 } 201 202 NtClose(KeyHandle); 203 return TRUE; 204 } 205 206 BOOLEAN 207 AddKbLayoutsToRegistry( 208 IN const MUI_LAYOUTS *MuiLayouts) 209 { 210 OBJECT_ATTRIBUTES ObjectAttributes; 211 UNICODE_STRING KeyName; 212 UNICODE_STRING ValueName; 213 HANDLE KeyHandle; 214 HANDLE SubKeyHandle; 215 NTSTATUS Status; 216 ULONG Disposition; 217 ULONG uIndex = 0; 218 ULONG uCount = 0; 219 WCHAR szKeyName[48] = L".DEFAULT\\Keyboard Layout"; 220 WCHAR szValueName[3 + 1]; 221 WCHAR szLangID[8 + 1]; 222 223 // Open the keyboard layout key 224 RtlInitUnicodeString(&KeyName, szKeyName); 225 InitializeObjectAttributes(&ObjectAttributes, 226 &KeyName, 227 OBJ_CASE_INSENSITIVE, 228 GetRootKeyByPredefKey(HKEY_USERS, NULL), 229 NULL); 230 231 Status = NtCreateKey(&KeyHandle, 232 KEY_CREATE_SUB_KEY, 233 &ObjectAttributes, 234 0, 235 NULL, 236 REG_OPTION_NON_VOLATILE, 237 &Disposition); 238 if (!NT_SUCCESS(Status)) 239 { 240 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); 241 return FALSE; 242 } 243 244 NtClose(KeyHandle); 245 246 KeyName.MaximumLength = sizeof(szKeyName); 247 Status = RtlAppendUnicodeToString(&KeyName, L"\\Preload"); 248 249 if (!NT_SUCCESS(Status)) 250 { 251 DPRINT1("RtlAppend failed! (%lx)\n", Status); 252 DPRINT1("String is %wZ\n", &KeyName); 253 return FALSE; 254 } 255 256 InitializeObjectAttributes(&ObjectAttributes, 257 &KeyName, 258 OBJ_CASE_INSENSITIVE, 259 GetRootKeyByPredefKey(HKEY_USERS, NULL), 260 NULL); 261 262 Status = NtCreateKey(&KeyHandle, 263 KEY_SET_VALUE, 264 &ObjectAttributes, 265 0, 266 NULL, 267 REG_OPTION_NON_VOLATILE, 268 &Disposition); 269 if (!NT_SUCCESS(Status)) 270 { 271 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); 272 return FALSE; 273 } 274 275 RtlInitUnicodeString(&KeyName, L".DEFAULT\\Keyboard Layout\\Substitutes"); 276 InitializeObjectAttributes(&ObjectAttributes, 277 &KeyName, 278 OBJ_CASE_INSENSITIVE, 279 GetRootKeyByPredefKey(HKEY_USERS, NULL), 280 NULL); 281 282 Status = NtCreateKey(&SubKeyHandle, 283 KEY_SET_VALUE, 284 &ObjectAttributes, 285 0, 286 NULL, 287 REG_OPTION_NON_VOLATILE, 288 &Disposition); 289 if (!NT_SUCCESS(Status)) 290 { 291 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); 292 NtClose(SubKeyHandle); 293 NtClose(KeyHandle); 294 return FALSE; 295 } 296 297 while (MuiLayouts[uIndex].LangID != NULL) 298 { 299 if (uIndex > 19) break; 300 301 RtlStringCchPrintfW(szValueName, ARRAYSIZE(szValueName), L"%u", uIndex + 1); 302 RtlInitUnicodeString(&ValueName, szValueName); 303 304 RtlStringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"0000%s", MuiLayouts[uIndex].LangID); 305 306 if (_wcsicmp(szLangID, MuiLayouts[uIndex].LayoutID) == 0) 307 { 308 Status = NtSetValueKey(KeyHandle, 309 &ValueName, 310 0, 311 REG_SZ, 312 (PVOID)MuiLayouts[uIndex].LayoutID, 313 (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR)); 314 if (!NT_SUCCESS(Status)) 315 { 316 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex); 317 NtClose(SubKeyHandle); 318 NtClose(KeyHandle); 319 return FALSE; 320 } 321 } 322 else 323 { 324 RtlStringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"d%03lu%s", uCount, MuiLayouts[uIndex].LangID); 325 Status = NtSetValueKey(KeyHandle, 326 &ValueName, 327 0, 328 REG_SZ, 329 (PVOID)szLangID, 330 (wcslen(szLangID)+1) * sizeof(WCHAR)); 331 if (!NT_SUCCESS(Status)) 332 { 333 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex); 334 NtClose(SubKeyHandle); 335 NtClose(KeyHandle); 336 return FALSE; 337 } 338 339 RtlInitUnicodeString(&ValueName, szLangID); 340 341 Status = NtSetValueKey(SubKeyHandle, 342 &ValueName, 343 0, 344 REG_SZ, 345 (PVOID)MuiLayouts[uIndex].LayoutID, 346 (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR)); 347 if (!NT_SUCCESS(Status)) 348 { 349 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %u)\n", Status, uIndex); 350 NtClose(SubKeyHandle); 351 NtClose(KeyHandle); 352 return FALSE; 353 } 354 355 uCount++; 356 } 357 358 uIndex++; 359 } 360 361 if (uIndex > 1) 362 AddHotkeySettings(L"2", L"2", L"1"); 363 else 364 AddHotkeySettings(L"3", L"3", L"3"); 365 366 NtClose(SubKeyHandle); 367 NtClose(KeyHandle); 368 return TRUE; 369 } 370 371 BOOLEAN 372 AddKeyboardLayouts( 373 IN PCWSTR LanguageId) 374 { 375 ULONG lngIndex = 0; 376 377 while (MUILanguageList[lngIndex].LanguageID != NULL) 378 { 379 if (_wcsicmp(MUILanguageList[lngIndex].LanguageID, LanguageId) == 0) 380 { 381 return AddKbLayoutsToRegistry(MUILanguageList[lngIndex].MuiLayouts); 382 } 383 384 lngIndex++; 385 } 386 387 return FALSE; 388 } 389 390 static 391 BOOLEAN 392 AddCodepageToRegistry( 393 IN PCWSTR ACPage, 394 IN PCWSTR OEMCPage, 395 IN PCWSTR MACCPage) 396 { 397 OBJECT_ATTRIBUTES ObjectAttributes; 398 UNICODE_STRING KeyName; 399 UNICODE_STRING ValueName; 400 HANDLE KeyHandle; 401 NTSTATUS Status; 402 403 // Open the nls codepage key 404 RtlInitUnicodeString(&KeyName, 405 L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage"); 406 InitializeObjectAttributes(&ObjectAttributes, 407 &KeyName, 408 OBJ_CASE_INSENSITIVE, 409 GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL), 410 NULL); 411 Status = NtOpenKey(&KeyHandle, 412 KEY_WRITE, 413 &ObjectAttributes); 414 if (!NT_SUCCESS(Status)) 415 { 416 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); 417 return FALSE; 418 } 419 420 // Set ANSI codepage 421 RtlInitUnicodeString(&ValueName, L"ACP"); 422 Status = NtSetValueKey(KeyHandle, 423 &ValueName, 424 0, 425 REG_SZ, 426 (PVOID)ACPage, 427 (wcslen(ACPage)+1) * sizeof(WCHAR)); 428 if (!NT_SUCCESS(Status)) 429 { 430 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 431 NtClose(KeyHandle); 432 return FALSE; 433 } 434 435 // Set OEM codepage 436 RtlInitUnicodeString(&ValueName, L"OEMCP"); 437 Status = NtSetValueKey(KeyHandle, 438 &ValueName, 439 0, 440 REG_SZ, 441 (PVOID)OEMCPage, 442 (wcslen(OEMCPage)+1) * sizeof(WCHAR)); 443 if (!NT_SUCCESS(Status)) 444 { 445 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 446 NtClose(KeyHandle); 447 return FALSE; 448 } 449 450 // Set MAC codepage 451 RtlInitUnicodeString(&ValueName, L"MACCP"); 452 Status = NtSetValueKey(KeyHandle, 453 &ValueName, 454 0, 455 REG_SZ, 456 (PVOID)MACCPage, 457 (wcslen(MACCPage)+1) * sizeof(WCHAR)); 458 if (!NT_SUCCESS(Status)) 459 { 460 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); 461 NtClose(KeyHandle); 462 return FALSE; 463 } 464 465 NtClose(KeyHandle); 466 467 return TRUE; 468 } 469 470 static 471 BOOLEAN 472 AddFontsSettingsToRegistry( 473 IN const MUI_SUBFONT * MuiSubFonts) 474 { 475 OBJECT_ATTRIBUTES ObjectAttributes; 476 UNICODE_STRING KeyName; 477 UNICODE_STRING ValueName; 478 HANDLE KeyHandle; 479 NTSTATUS Status; 480 ULONG uIndex = 0; 481 482 RtlInitUnicodeString(&KeyName, 483 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"); 484 InitializeObjectAttributes(&ObjectAttributes, 485 &KeyName, 486 OBJ_CASE_INSENSITIVE, 487 GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL), 488 NULL); 489 Status = NtOpenKey(&KeyHandle, 490 KEY_WRITE, 491 &ObjectAttributes); 492 if (!NT_SUCCESS(Status)) 493 { 494 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status); 495 return FALSE; 496 } 497 498 while (MuiSubFonts[uIndex].FontName != NULL) 499 { 500 RtlInitUnicodeString(&ValueName, MuiSubFonts[uIndex].FontName); 501 Status = NtSetValueKey(KeyHandle, 502 &ValueName, 503 0, 504 REG_SZ, 505 (PVOID)MuiSubFonts[uIndex].SubFontName, 506 (wcslen(MuiSubFonts[uIndex].SubFontName)+1) * sizeof(WCHAR)); 507 if (!NT_SUCCESS(Status)) 508 { 509 DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex); 510 NtClose(KeyHandle); 511 return FALSE; 512 } 513 514 uIndex++; 515 } 516 517 NtClose(KeyHandle); 518 519 return TRUE; 520 } 521 522 BOOLEAN 523 AddCodePage( 524 IN PCWSTR LanguageId) 525 { 526 ULONG lngIndex = 0; 527 528 while (MUILanguageList[lngIndex].LanguageID != NULL) 529 { 530 if (_wcsicmp(MUILanguageList[lngIndex].LanguageID, LanguageId) == 0) 531 { 532 if (AddCodepageToRegistry(MUILanguageList[lngIndex].ACPage, 533 MUILanguageList[lngIndex].OEMCPage, 534 MUILanguageList[lngIndex].MACCPage) && 535 AddFontsSettingsToRegistry(MUILanguageList[lngIndex].MuiSubFonts)) 536 { 537 return TRUE; 538 } 539 else 540 { 541 return FALSE; 542 } 543 } 544 545 lngIndex++; 546 } 547 548 return FALSE; 549 } 550 551 /* EOF */ 552