ReactOS  0.4.14-dev-114-gc8cbd56
mui.c
Go to the documentation of this file.
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
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
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
88  IN PCWSTR LanguageId)
89 {
90  ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0);
91  return MUILanguageList[lngIndex].MuiLayouts[0].LayoutID;
92 }
93 
94 PCWSTR
96  IN PCWSTR LanguageId)
97 {
98  ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0);
99  return MUILanguageList[lngIndex].OEMCPage;
100 }
101 
102 PCWSTR
104  IN PCWSTR LanguageId)
105 {
106  ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0);
107  return MUILanguageList[lngIndex].GeoID;
108 }
109 
110 const MUI_LAYOUTS*
112  IN PCWSTR LanguageId)
113 {
114  ULONG lngIndex = max(FindLanguageIndex(LanguageId), 0);
115  return MUILanguageList[lngIndex].MuiLayouts;
116 }
117 
118 
119 static
120 BOOLEAN
122  IN PCWSTR Hotkey,
123  IN PCWSTR LangHotkey,
124  IN PCWSTR LayoutHotkey)
125 {
132 
134  L".DEFAULT\\Keyboard Layout\\Toggle");
136  &KeyName,
139  NULL);
140 
144  0,
145  NULL,
147  &Disposition);
148  if (!NT_SUCCESS(Status))
149  {
150  DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
151  return FALSE;
152  }
153 
155  L"Hotkey");
156 
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);
167  return FALSE;
168  }
169 
171  L"Language Hotkey");
172 
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);
183  return FALSE;
184  }
185 
187  L"Layout Hotkey");
188 
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);
199  return FALSE;
200  }
201 
203  return TRUE;
204 }
205 
206 BOOLEAN
208  IN const MUI_LAYOUTS *MuiLayouts)
209 {
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);
226  &KeyName,
229  NULL);
230 
234  0,
235  NULL,
237  &Disposition);
238  if (!NT_SUCCESS(Status))
239  {
240  DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
241  return FALSE;
242  }
243 
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 
257  &KeyName,
260  NULL);
261 
265  0,
266  NULL,
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");
277  &KeyName,
280  NULL);
281 
285  0,
286  NULL,
288  &Disposition);
289  if (!NT_SUCCESS(Status))
290  {
291  DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
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  {
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);
319  return FALSE;
320  }
321  }
322  else
323  {
324  RtlStringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"d%03lu%s", uCount, MuiLayouts[uIndex].LangID);
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);
336  return FALSE;
337  }
338 
339  RtlInitUnicodeString(&ValueName, szLangID);
340 
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);
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 
368  return TRUE;
369 }
370 
371 BOOLEAN
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
393  IN PCWSTR ACPage,
394  IN PCWSTR OEMCPage,
395  IN PCWSTR MACCPage)
396 {
402 
403  // Open the nls codepage key
405  L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
407  &KeyName,
410  NULL);
412  KEY_WRITE,
414  if (!NT_SUCCESS(Status))
415  {
416  DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
417  return FALSE;
418  }
419 
420  // Set ANSI codepage
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);
432  return FALSE;
433  }
434 
435  // Set OEM codepage
436  RtlInitUnicodeString(&ValueName, L"OEMCP");
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);
447  return FALSE;
448  }
449 
450  // Set MAC codepage
451  RtlInitUnicodeString(&ValueName, L"MACCP");
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);
462  return FALSE;
463  }
464 
466 
467  return TRUE;
468 }
469 
470 static
471 BOOLEAN
473  IN const MUI_SUBFONT * MuiSubFonts)
474 {
480  ULONG uIndex = 0;
481 
483  L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
485  &KeyName,
488  NULL);
490  KEY_WRITE,
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);
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);
511  return FALSE;
512  }
513 
514  uIndex++;
515  }
516 
518 
519  return TRUE;
520 }
521 
522 BOOLEAN
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 */
#define HKEY_USERS
Definition: winreg.h:13
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4711
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
BOOLEAN AddKeyboardLayouts(IN PCWSTR LanguageId)
Definition: mui.c:372
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
PCWSTR GeoID
Definition: mui.h:22
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
Definition: mui.h:3
static BOOLEAN AddHotkeySettings(IN PCWSTR Hotkey, IN PCWSTR LangHotkey, IN PCWSTR LayoutHotkey)
Definition: mui.c:121
PCWSTR MUIGetOEMCodePage(IN PCWSTR LanguageId)
Definition: mui.c:95
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
static BOOLEAN AddFontsSettingsToRegistry(IN const MUI_SUBFONT *MuiSubFonts)
Definition: mui.c:472
PCWSTR OEMCPage
Definition: mui.h:19
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
PCWSTR MUIGetGeoID(IN PCWSTR LanguageId)
Definition: mui.c:103
PCWSTR MUIDefaultKeyboardLayout(IN PCWSTR LanguageId)
Definition: mui.c:87
unsigned char BOOLEAN
const MUI_LAYOUTS * MUIGetLayoutsList(IN PCWSTR LanguageId)
Definition: mui.c:111
smooth NULL
Definition: ftsmooth.c:416
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_WRITE
Definition: nt_native.h:1031
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static BOOLEAN AddCodepageToRegistry(IN PCWSTR ACPage, IN PCWSTR OEMCPage, IN PCWSTR MACCPage)
Definition: mui.c:392
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING _Out_ PNDIS_HANDLE SubKeyHandle
Definition: ndis.h:4723
const MUI_LAYOUTS * MuiLayouts
Definition: mui.h:24
static const WCHAR L[]
Definition: oid.c:1250
Status
Definition: gdiplustypes.h:24
HANDLE GetRootKeyByPredefKey(IN HANDLE KeyHandle, OUT PCWSTR *RootKeyMountPoint OPTIONAL)
Definition: registry.c:90
const MUI_LANGUAGE MUILanguageList[]
Definition: muilanguages.h:412
static ULONG FindLanguageIndex(IN PCWSTR LanguageId)
Definition: mui.c:43
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
BOOLEAN IsLanguageAvailable(IN PCWSTR LanguageId)
Definition: mui.c:69
BOOLEAN AddKbLayoutsToRegistry(IN const MUI_LAYOUTS *MuiLayouts)
Definition: mui.c:207
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
PCWSTR LayoutID
Definition: mui.h:12
BOOLEAN AddCodePage(IN PCWSTR LanguageId)
Definition: mui.c:523
Definition: mui.h:9
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22