a80a1810531082d8c25c535866d80fe28e22a056
[reactos.git] / reactos / base / setup / usetup / mui.c
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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/mui.c
23 * PURPOSE: Text-mode setup
24 * PROGRAMMER:
25 */
26
27 #include "usetup.h"
28 #include "errorcode.h"
29 #include "mui.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 #include "lang/bg-BG.h"
35 #include "lang/en-US.h"
36 #include "lang/de-DE.h"
37 #include "lang/el-GR.h"
38 #include "lang/es-ES.h"
39 #include "lang/fr-FR.h"
40 #include "lang/it-IT.h"
41 #include "lang/pl-PL.h"
42 #include "lang/ru-RU.h"
43 #include "lang/sk-SK.h"
44 #include "lang/sv-SE.h"
45 #include "lang/uk-UA.h"
46 #include "lang/lt-LT.h"
47
48 static const MUI_LANGUAGE LanguageList[] =
49 {
50 /* Lang ID, DefKbdLayout,ANSI CP, OEM CP, MAC CP, Language Name, page strgs,error strings */
51 {L"00000409", L"00000409", L"1252", L"437", L"10000", L"English", enUSPages, enUSErrorEntries, enUSStrings },
52 {L"00000402", L"00000402", L"1251", L"866", L"10007", L"Bulgarian", bgBGPages, bgBGErrorEntries, enUSStrings },
53 {L"00000403", L"00000403", L"1252", L"850", L"10000", L"Catalan", enUSPages, enUSErrorEntries, enUSStrings },
54 {L"00000804", L"00000804", L"936", L"936", L"10008", L"Chinese (PRC)", enUSPages, enUSErrorEntries, enUSStrings },
55 {L"00000406", L"00000406", L"1252", L"850", L"10000", L"Danish", enUSPages, enUSErrorEntries, enUSStrings },
56 {L"00000413", L"00000813", L"1252", L"850", L"10000", L"Dutch", enUSPages, enUSErrorEntries, enUSStrings },
57 {L"0000040B", L"0000040B", L"1252", L"850", L"10000", L"Finnish", enUSPages, enUSErrorEntries, enUSStrings },
58 {L"0000040C", L"0000040C", L"1252", L"850", L"10000", L"French", frFRPages, frFRErrorEntries, enUSStrings },
59 {L"00000407", L"00000407", L"1252", L"850", L"10000", L"German", deDEPages, deDEErrorEntries, deDEStrings },
60 {L"00000408", L"00000408", L"1253", L"737", L"10006", L"Greek", elGRPages, elGRErrorEntries, enUSStrings },
61 {L"0000040D", L"0000040D", L"1255", L"862", L"10005", L"Hebrew", enUSPages, enUSErrorEntries, enUSStrings },
62 {L"0000040E", L"0000040E", L"1250", L"852", L"10029", L"Hungarian", enUSPages, enUSErrorEntries, enUSStrings },
63 {L"00000410", L"00000410", L"1252", L"850", L"10000", L"Italian", itITPages, itITErrorEntries, enUSStrings },
64 {L"00000411", L"00000411", L"932", L"932", L"10001", L"Japanese", enUSPages, enUSErrorEntries, enUSStrings },
65 {L"00000412", L"00000412", L"949", L"949", L"10003", L"Korean", enUSPages, enUSErrorEntries, enUSStrings },
66 {L"00000427", L"00000427", L"1257", L"775", L"10029", L"Lithuanian", ltLTPages, ltLTErrorEntries, enUSStrings },
67 {L"00000414", L"00000414", L"1252", L"850", L"10000", L"Norwegian", enUSPages, enUSErrorEntries, enUSStrings },
68 {L"00000419", L"00000419", L"1251", L"866", L"10007", L"Russian", ruRUPages, ruRUErrorEntries, enUSStrings },
69 {L"0000041B", L"0000041B", L"1250", L"852", L"10029", L"Slovak", skSKPages, skSKErrorEntries, enUSStrings },
70 {L"0000040A", L"0000040A", L"1252", L"850", L"10000", L"Spanish", esESPages, esESErrorEntries, enUSStrings },
71 {L"00000415", L"00000415", L"1250", L"852", L"10029", L"Polish", plPLPages, plPLErrorEntries, enUSStrings },
72 {L"00000816", L"00000816", L"1252", L"850", L"10000", L"Portuguese", enUSPages, enUSErrorEntries, enUSStrings },
73 {L"0000041D", L"0000041D", L"1252", L"850", L"10000", L"Swedish", svSEPages, svSEErrorEntries, enUSStrings },
74 {L"0000041E", L"0000041E", L"874", L"874", L"10021", L"Thai", enUSPages, enUSErrorEntries, enUSStrings },
75 {L"0000041F", L"0000041F", L"1254", L"857", L"10081", L"Turkish", enUSPages, enUSErrorEntries, enUSStrings },
76 {L"00000422", L"00000422", L"1251", L"866", L"10017", L"Ukrainian", ukUAPages, ukUAErrorEntries, enUSStrings },
77 {NULL, NULL, NULL, NULL, NULL}
78 };
79
80 extern
81 VOID
82 PopupError(IN PCCH Text,
83 IN PCCH Status,
84 IN PINPUT_RECORD Ir,
85 IN ULONG WaitEvent);
86
87 static
88 const MUI_ENTRY *
89 FindMUIEntriesOfPage(IN ULONG PageNumber)
90 {
91 ULONG muiIndex = 0;
92 ULONG lngIndex = 0;
93 const MUI_PAGE * Pages = NULL;
94
95 do
96 {
97 /* First we search the language list till we find current selected language messages */
98 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
99 {
100 /* Get all available pages for this language */
101 Pages = LanguageList[lngIndex].MuiPages;
102
103 do
104 {
105 /* Get page messages */
106 if (Pages[muiIndex].Number == PageNumber)
107 return Pages[muiIndex].MuiEntry;
108
109 muiIndex++;
110 }
111 while (Pages[muiIndex].MuiEntry != NULL);
112 }
113
114 lngIndex++;
115 }
116 while (LanguageList[lngIndex].MuiPages != NULL);
117
118 return NULL;
119 }
120
121 static
122 const MUI_ERROR *
123 FindMUIErrorEntries(VOID)
124 {
125 ULONG lngIndex = 0;
126
127 do
128 {
129 /* First we search the language list till we find current selected language messages */
130 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
131 {
132 /* Get all available error messages for this language */
133 return LanguageList[lngIndex].MuiErrors;
134 }
135
136 lngIndex++;
137 }
138 while (LanguageList[lngIndex].MuiPages != NULL);
139
140 return NULL;
141 }
142
143 static
144 const MUI_STRING *
145 FindMUIStringEntries(VOID)
146 {
147 ULONG lngIndex = 0;
148
149 do
150 {
151 /* First we search the language list till we find current selected language messages */
152 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
153 {
154 /* Get all available strings for this language */
155 return LanguageList[lngIndex].MuiStrings;
156 }
157
158 lngIndex++;
159 }
160 while (LanguageList[lngIndex].MuiPages != NULL);
161
162 return NULL;
163 }
164
165 LPCWSTR
166 MUIDefaultKeyboardLayout(VOID)
167 {
168 ULONG lngIndex = 0;
169 do
170 {
171 /* First we search the language list till we find current selected language messages */
172 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
173 {
174 /* Return default keyboard layout */
175 return LanguageList[lngIndex].LanguageKeyboardLayoutID;
176 }
177
178 lngIndex++;
179 }
180 while (LanguageList[lngIndex].MuiPages != NULL);
181
182 return NULL;
183 }
184
185 VOID
186 MUIDisplayPage(IN ULONG page)
187 {
188 const MUI_ENTRY * entry;
189 int index;
190 int flags;
191
192 entry = FindMUIEntriesOfPage(page);
193 if (!entry)
194 {
195 PopupError("Error: Failed to find translated page",
196 NULL,
197 NULL,
198 POPUP_WAIT_NONE);
199 return;
200 }
201
202 index = 0;
203 do
204 {
205 flags = entry[index].Flags;
206 switch(flags)
207 {
208 case TEXT_NORMAL:
209 CONSOLE_SetTextXY(entry[index].X, entry[index].Y, entry[index].Buffer);
210 break;
211 case TEXT_HIGHLIGHT:
212 CONSOLE_SetHighlightedTextXY(entry[index].X, entry[index].Y, entry[index].Buffer);
213 break;
214 case TEXT_UNDERLINE:
215 CONSOLE_SetUnderlinedTextXY(entry[index].X, entry[index].Y, entry[index].Buffer);
216 break;
217 case TEXT_STATUS:
218 CONSOLE_SetStatusText(entry[index].Buffer);
219 break;
220 default:
221 break;
222 }
223 index++;
224 }
225 while (entry[index].Buffer != NULL);
226 }
227
228 VOID
229 MUIDisplayError(IN ULONG ErrorNum, OUT PINPUT_RECORD Ir, IN ULONG WaitEvent)
230 {
231 const MUI_ERROR * entry;
232
233 if (ErrorNum >= ERROR_LAST_ERROR_CODE)
234 {
235 PopupError("Invalid error number provided",
236 "Press ENTER to continue",
237 Ir,
238 POPUP_WAIT_ENTER);
239
240 return;
241 }
242
243 entry = FindMUIErrorEntries();
244 if (!entry)
245 {
246 PopupError("Error: Failed to find translated error message",
247 NULL,
248 NULL,
249 POPUP_WAIT_NONE);
250 return;
251 }
252
253 PopupError(entry[ErrorNum].ErrorText,
254 entry[ErrorNum].ErrorStatus,
255 Ir,
256 WaitEvent);
257 }
258
259 LPSTR
260 MUIGetString(ULONG Number)
261 {
262 ULONG i;
263 const MUI_STRING * entry;
264
265 entry = FindMUIStringEntries();
266 if (entry)
267 {
268 for (i = 0; entry[i].Number != 0; i++)
269 {
270 if (entry[i].Number == Number)
271 {
272 return entry[i].String;
273 }
274 }
275 }
276
277 PopupError("Error: Failed to find translated string",
278 NULL,
279 NULL,
280 POPUP_WAIT_NONE);
281
282 return "<nostring>";
283 }
284
285 static BOOLEAN
286 AddCodepageToRegistry(IN LPCWSTR ACPage, IN LPCWSTR OEMCPage, IN LPCWSTR MACCPage)
287 {
288 OBJECT_ATTRIBUTES ObjectAttributes;
289 UNICODE_STRING KeyName;
290 UNICODE_STRING ValueName;
291 HANDLE KeyHandle;
292 NTSTATUS Status;
293
294 // Open the nls codepage key
295 RtlInitUnicodeString(&KeyName,
296 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
297 InitializeObjectAttributes(&ObjectAttributes,
298 &KeyName,
299 OBJ_CASE_INSENSITIVE,
300 NULL,
301 NULL);
302 Status = NtOpenKey(&KeyHandle,
303 KEY_WRITE,
304 &ObjectAttributes);
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
308 return FALSE;
309 }
310
311 // Set ANSI codepage
312 RtlInitUnicodeString(&ValueName, L"ACP");
313 Status = NtSetValueKey(KeyHandle,
314 &ValueName,
315 0,
316 REG_SZ,
317 (PVOID)ACPage,
318 wcslen(ACPage) * sizeof(PWCHAR));
319 if (!NT_SUCCESS(Status))
320 {
321 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
322 NtClose(KeyHandle);
323 return FALSE;
324 }
325
326 // Set OEM codepage
327 RtlInitUnicodeString(&ValueName, L"OEMCP");
328 Status = NtSetValueKey(KeyHandle,
329 &ValueName,
330 0,
331 REG_SZ,
332 (PVOID)OEMCPage,
333 wcslen(OEMCPage) * sizeof(PWCHAR));
334 if (!NT_SUCCESS(Status))
335 {
336 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
337 NtClose(KeyHandle);
338 return FALSE;
339 }
340
341 // Set MAC codepage
342 RtlInitUnicodeString(&ValueName, L"MACCP");
343 Status = NtSetValueKey(KeyHandle,
344 &ValueName,
345 0,
346 REG_SZ,
347 (PVOID)MACCPage,
348 wcslen(MACCPage) * sizeof(PWCHAR));
349 if (!NT_SUCCESS(Status))
350 {
351 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
352 NtClose(KeyHandle);
353 return FALSE;
354 }
355
356 NtClose(KeyHandle);
357
358 return TRUE;
359 }
360
361 BOOLEAN
362 AddCodePage(VOID)
363 {
364 ULONG lngIndex = 0;
365 do
366 {
367 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
368 {
369 return AddCodepageToRegistry(LanguageList[lngIndex].ACPage,
370 LanguageList[lngIndex].OEMCPage,
371 LanguageList[lngIndex].MACCPage);
372 }
373
374 lngIndex++;
375 }
376 while (LanguageList[lngIndex].MuiPages != NULL);
377
378 return FALSE;
379 }
380
381 VOID
382 SetConsoleCodePage(VOID)
383 {
384 ULONG lngIndex = 0;
385 UINT wCodePage;
386
387 do
388 {
389 if (_wcsicmp(LanguageList[lngIndex].LanguageID , SelectedLanguageId) == 0)
390 {
391 wCodePage = (UINT) wcstoul(LanguageList[lngIndex].OEMCPage, NULL, 10);
392 SetConsoleOutputCP(wCodePage);
393 return;
394 }
395
396 lngIndex++;
397 }
398 while (LanguageList[lngIndex].MuiPages != NULL);
399 }
400
401 /* EOF */