Partially fixed up tree after merge from HEAD. More to do.
[reactos.git] / reactos / boot / freeldr / freeldr / windows / wlregistry.c
1 /*
2 * PROJECT: EFI Windows Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: freeldr/winldr/wlregistry.c
5 * PURPOSE: Registry support functions
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 /* INCLUDES ***************************************************************/
10
11 #include <freeldr.h>
12
13 #ifdef _M_PPC
14 #include <of.h>
15 #include <mmu.h>
16 #endif
17
18 #define NDEBUG
19 #include <debug.h>
20
21 BOOLEAN
22 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
23 IN LPCSTR DirectoryPath,
24 IN LPCSTR AnsiFileName,
25 IN LPCSTR OemFileName,
26 IN LPCSTR LanguageFileName);
27
28
29 /* FUNCTIONS **************************************************************/
30
31 BOOLEAN
32 WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
33 IN LPCSTR DirectoryPath,
34 IN LPCSTR HiveName)
35 {
36 PFILE FileHandle;
37 CHAR FullHiveName[256];
38 BOOLEAN Status;
39 ULONG HiveFileSize;
40 ULONG_PTR HiveDataPhysical;
41 PVOID HiveDataVirtual;
42
43 /* Concatenate path and filename to get the full name */
44 strcpy(FullHiveName, DirectoryPath);
45 strcat(FullHiveName, HiveName);
46 //Print(L"Loading %s...\n", FullHiveName);
47 FileHandle = FsOpenFile(FullHiveName);
48
49 if (FileHandle == NULL)
50 {
51 UiMessageBox("Opening hive file failed!");
52 return FALSE;
53 }
54
55 /* Get the file length */
56 HiveFileSize = FsGetFileSize(FileHandle);
57
58 if (HiveFileSize == 0)
59 {
60 FsCloseFile(FileHandle);
61 UiMessageBox("Hive file has 0 size!");
62 return FALSE;
63 }
64
65 /* Round up the size to page boundary and alloc memory */
66 HiveDataPhysical = (ULONG_PTR)MmAllocateMemory(
67 MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT);
68
69 if (HiveDataPhysical == 0)
70 {
71 FsCloseFile(FileHandle);
72 UiMessageBox("Unable to alloc memory for a hive!");
73 return FALSE;
74 }
75
76 /* Convert address to virtual */
77 #ifdef _M_IX86
78 HiveDataVirtual = (PVOID)(KSEG0_BASE | HiveDataPhysical);
79 #elif defined(_M_PPC)
80 HiveDataVirtual = (PVOID)HiveDataPhysical;
81 #endif
82
83 /* Fill LoaderBlock's entries */
84 LoaderBlock->RegistryLength = HiveFileSize;
85 LoaderBlock->RegistryBase = HiveDataVirtual;
86
87 /* Finally read from file to the memory */
88 Status = FsReadFile(FileHandle, HiveFileSize, NULL, (PVOID)HiveDataPhysical);
89 FsCloseFile(FileHandle);
90 if (!Status)
91 {
92 UiMessageBox("Unable to read from hive file!");
93 return FALSE;
94 }
95
96 return TRUE;
97 }
98
99 // Queries registry for those three file names
100 BOOLEAN WinLdrGetNLSNames(LPSTR AnsiName,
101 LPSTR OemName,
102 LPSTR LangName)
103 {
104 LONG rc = ERROR_SUCCESS;
105 FRLDRHKEY hKey;
106 WCHAR szIdBuffer[80];
107 WCHAR NameBuffer[80];
108 ULONG BufferSize;
109
110 /* open the codepage key */
111 rc = RegOpenKey(NULL,
112 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
113 &hKey);
114 if (rc != ERROR_SUCCESS)
115 {
116 //strcpy(szErrorOut, "Couldn't open CodePage registry key");
117 return FALSE;
118 }
119
120 /* get ANSI codepage */
121 BufferSize = sizeof(szIdBuffer);
122 rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
123 if (rc != ERROR_SUCCESS)
124 {
125 //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
126 return FALSE;
127 }
128
129 BufferSize = sizeof(NameBuffer);
130 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
131 if (rc != ERROR_SUCCESS)
132 {
133 //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
134 return FALSE;
135 }
136 sprintf(AnsiName, "%S", NameBuffer);
137
138 /* get OEM codepage */
139 BufferSize = sizeof(szIdBuffer);
140 rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
141 if (rc != ERROR_SUCCESS)
142 {
143 //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
144 return FALSE;
145 }
146
147 BufferSize = sizeof(NameBuffer);
148 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
149 if (rc != ERROR_SUCCESS)
150 {
151 //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
152 return FALSE;
153 }
154 sprintf(OemName, "%S", NameBuffer);
155
156 /* open the language key */
157 rc = RegOpenKey(NULL,
158 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
159 &hKey);
160 if (rc != ERROR_SUCCESS)
161 {
162 //strcpy(szErrorOut, "Couldn't open Language registry key");
163 return FALSE;
164 }
165
166 /* get the Unicode case table */
167 BufferSize = sizeof(szIdBuffer);
168 rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
169 if (rc != ERROR_SUCCESS)
170 {
171 //strcpy(szErrorOut, "Couldn't get Language Default setting");
172 return FALSE;
173 }
174
175 BufferSize = sizeof(NameBuffer);
176 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
177 if (rc != ERROR_SUCCESS)
178 {
179 //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
180 return FALSE;
181 }
182 sprintf(LangName, "%S", NameBuffer);
183
184 return TRUE;
185 }
186
187 BOOLEAN WinLdrLoadAndScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
188 IN LPCSTR DirectoryPath)
189 {
190 CHAR SearchPath[1024];
191 CHAR AnsiName[256], OemName[256], LangName[256];
192 BOOLEAN Status;
193
194 // There is a simple logic here: try to load usual hive (system), if it
195 // fails, then give system.alt a try, and finally try a system.sav
196
197 // FIXME: For now we only try system
198 strcpy(SearchPath, DirectoryPath);
199 strcat(SearchPath, "SYSTEM32\\CONFIG\\");
200 Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");
201
202 // Fail if failed...
203 if (!Status)
204 return FALSE;
205
206 // Initialize in-memory registry
207 RegInitializeRegistry();
208
209 // Import what was loaded
210 Status = RegImportBinaryHive((PCHAR)VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
211 if (!Status)
212 {
213 UiMessageBox("Importing binary hive failed!");
214 return FALSE;
215 }
216
217 // Initialize the 'CurrentControlSet' link
218 if (RegInitCurrentControlSet(FALSE) != ERROR_SUCCESS)
219 {
220 UiMessageBox("Initializing CurrentControlSet link failed!");
221 return FALSE;
222 }
223
224 Status = WinLdrGetNLSNames(AnsiName, OemName, LangName);
225 if (!Status)
226 {
227 UiMessageBox("Getting NLS names from registry failed!");
228 return FALSE;
229 }
230
231 DbgPrint((DPRINT_WINDOWS, "NLS data %s %s %s\n", AnsiName, OemName, LangName));
232
233 /* Load NLS data, should be moved to WinLdrLoadAndScanSystemHive() */
234 strcpy(SearchPath, DirectoryPath);
235 strcat(SearchPath, "SYSTEM32\\");
236 Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
237 DbgPrint((DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status));
238
239 return TRUE;
240 }
241
242
243 /* PRIVATE FUNCTIONS ******************************************************/
244
245 BOOLEAN
246 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
247 IN LPCSTR DirectoryPath,
248 IN LPCSTR AnsiFileName,
249 IN LPCSTR OemFileName,
250 IN LPCSTR LanguageFileName)
251 {
252 CHAR FileName[255];
253 PFILE AnsiFileHandle;
254 PFILE OemFileHandle;
255 PFILE LanguageFileHandle;
256 ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
257 ULONG TotalSize;
258 ULONG_PTR NlsDataBase;
259 PVOID NlsVirtual;
260 BOOLEAN Status, AnsiEqualsOem = FALSE;
261
262 /* There may be a case, when OEM and ANSI page coincide */
263 if (!strcmp(AnsiFileName, OemFileName))
264 AnsiEqualsOem = TRUE;
265
266 /* Open file with ANSI and store its size */
267 //Print(L"Loading %s...\n", Filename);
268 strcpy(FileName, DirectoryPath);
269 strcat(FileName, AnsiFileName);
270 AnsiFileHandle = FsOpenFile(FileName);
271
272 if (AnsiFileHandle == NULL)
273 goto Failure;
274
275 AnsiFileSize = FsGetFileSize(AnsiFileHandle);
276 DbgPrint((DPRINT_WINDOWS, "AnsiFileSize: %d\n", AnsiFileSize));
277 FsCloseFile(AnsiFileHandle);
278
279 /* Open OEM file and store its length */
280 if (AnsiEqualsOem)
281 {
282 OemFileSize = 0;
283 }
284 else
285 {
286 //Print(L"Loading %s...\n", Filename);
287 strcpy(FileName, DirectoryPath);
288 strcat(FileName, OemFileName);
289 OemFileHandle = FsOpenFile(FileName);
290
291 if (OemFileHandle == NULL)
292 goto Failure;
293
294 OemFileSize = FsGetFileSize(OemFileHandle);
295 FsCloseFile(OemFileHandle);
296 }
297 DbgPrint((DPRINT_WINDOWS, "OemFileSize: %d\n", OemFileSize));
298
299 /* And finally open the language codepage file and store its length */
300 //Print(L"Loading %s...\n", Filename);
301 strcpy(FileName, DirectoryPath);
302 strcat(FileName, LanguageFileName);
303 LanguageFileHandle = FsOpenFile(FileName);
304
305 if (LanguageFileHandle == NULL)
306 goto Failure;
307
308 LanguageFileSize = FsGetFileSize(LanguageFileHandle);
309 FsCloseFile(LanguageFileHandle);
310 DbgPrint((DPRINT_WINDOWS, "LanguageFileSize: %d\n", LanguageFileSize));
311
312 /* Sum up all three length, having in mind that every one of them
313 must start at a page boundary => thus round up each file to a page */
314 TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
315 MM_SIZE_TO_PAGES(OemFileSize) +
316 MM_SIZE_TO_PAGES(LanguageFileSize);
317
318 NlsDataBase = (ULONG_PTR)MmAllocateMemory(TotalSize*MM_PAGE_SIZE);
319
320 if (NlsDataBase == 0)
321 goto Failure;
322
323 #ifdef _M_IX86
324 NlsVirtual = (PVOID)(KSEG0_BASE | NlsDataBase);
325 #elif defined(_M_PPC)
326 NlsVirtual = (PVOID)NlsDataBase;
327 #endif
328 LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
329 LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual +
330 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
331 LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual +
332 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
333 (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
334
335 /* Ansi and OEM data are the same - just set pointers to the same area */
336 if (AnsiEqualsOem)
337 LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
338
339
340 /* Now actually read the data into memory, starting with Ansi file */
341 strcpy(FileName, DirectoryPath);
342 strcat(FileName, AnsiFileName);
343 AnsiFileHandle = FsOpenFile(FileName);
344
345 if (AnsiFileHandle == NULL)
346 goto Failure;
347
348 Status = FsReadFile(AnsiFileHandle, AnsiFileSize, NULL, VaToPa(LoaderBlock->NlsData->AnsiCodePageData));
349
350 if (!Status)
351 goto Failure;
352
353 FsCloseFile(AnsiFileHandle);
354
355 /* OEM now, if it doesn't equal Ansi of course */
356 if (!AnsiEqualsOem)
357 {
358 strcpy(FileName, DirectoryPath);
359 strcat(FileName, OemFileName);
360 OemFileHandle = FsOpenFile(FileName);
361
362 if (OemFileHandle == NULL)
363 goto Failure;
364
365 Status = FsReadFile(OemFileHandle, OemFileSize, NULL, VaToPa(LoaderBlock->NlsData->OemCodePageData));
366
367 if (!Status)
368 goto Failure;
369
370 FsCloseFile(AnsiFileHandle);
371 }
372
373 /* finally the language file */
374 strcpy(FileName, DirectoryPath);
375 strcat(FileName, LanguageFileName);
376 LanguageFileHandle = FsOpenFile(FileName);
377
378 if (LanguageFileHandle == NULL)
379 goto Failure;
380
381 Status = FsReadFile(LanguageFileHandle, LanguageFileSize, NULL, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData));
382
383 if (!Status)
384 goto Failure;
385
386 FsCloseFile(LanguageFileHandle);
387
388 //
389 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
390 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
391 //
392 LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
393
394 /* Convert NlsTables address to VA */
395 LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
396
397 return TRUE;
398
399 Failure:
400 //UiMessageBox("Error reading NLS file %s\n", Filename);
401 UiMessageBox("Error reading NLS file!");
402 return FALSE;
403 }