Added NLS-file loader.
[reactos.git] / freeldr / freeldr / reactos / reactos.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <freeldr.h>
22 #include <asmcode.h>
23 #include <reactos.h>
24 #include <rtl.h>
25 #include <fs.h>
26 #include <ui.h>
27 #include <multiboot.h>
28 #include <mm.h>
29 #include <parseini.h>
30
31 #include "registry.h"
32 #include "hwdetect.h"
33
34
35 #define NDEBUG
36
37
38 static BOOL
39 LoadKernel(PCHAR szFileName, int nPos)
40 {
41 PFILE FilePointer;
42 PCHAR szShortName;
43 char szBuffer[256];
44
45 szShortName = strrchr(szFileName, '\\');
46 if (szShortName == NULL)
47 szShortName = szFileName;
48 else
49 szShortName = szShortName + 1;
50
51 FilePointer = OpenFile(szFileName);
52 if (FilePointer == NULL)
53 {
54 strcat(szBuffer, szShortName);
55 strcat(szBuffer, " not found.");
56 MessageBox(szBuffer);
57 return(FALSE);
58 }
59
60 /*
61 * Update the status bar with the current file
62 */
63 strcpy(szBuffer, " Reading ");
64 strcat(szBuffer, szShortName);
65 DrawStatusText(szBuffer);
66
67 /*
68 * Load the kernel
69 */
70 MultiBootLoadKernel(FilePointer);
71
72 DrawProgressBar(nPos);
73
74 return(TRUE);
75 }
76
77
78 static BOOL
79 LoadDriver(PCHAR szFileName, int nPos)
80 {
81 PFILE FilePointer;
82 char value[256];
83 char *p;
84
85 FilePointer = OpenFile(szFileName);
86 if (FilePointer == NULL)
87 {
88 strcat(value, szFileName);
89 strcat(value, " not found.");
90 MessageBox(value);
91 return(FALSE);
92 }
93
94 /*
95 * Update the status bar with the current file
96 */
97 strcpy(value, " Reading ");
98 p = strrchr(szFileName, '\\');
99 if (p == NULL)
100 strcat(value, szFileName);
101 else
102 strcat(value, p + 1);
103 DrawStatusText(value);
104
105 /*
106 * Load the driver
107 */
108 MultiBootLoadModule(FilePointer, szFileName, NULL);
109
110 DrawProgressBar(nPos);
111
112 return(TRUE);
113 }
114
115
116 static BOOL
117 LoadNlsFile(PCHAR szFileName, PCHAR szModuleName)
118 {
119 PFILE FilePointer;
120 char value[256];
121 char *p;
122
123 FilePointer = OpenFile(szFileName);
124 if (FilePointer == NULL)
125 {
126 strcat(value, szFileName);
127 strcat(value, " not found.");
128 MessageBox(value);
129 return(FALSE);
130 }
131
132 /*
133 * Update the status bar with the current file
134 */
135 strcpy(value, " Reading ");
136 p = strrchr(szFileName, '\\');
137 if (p == NULL)
138 strcat(value, szFileName);
139 else
140 strcat(value, p + 1);
141 DrawStatusText(value);
142
143 /*
144 * Load the driver
145 */
146 MultiBootLoadModule(FilePointer, szModuleName, NULL);
147
148 return(TRUE);
149 }
150
151
152 static VOID
153 LoadBootDrivers(PCHAR szSystemRoot, int nPos)
154 {
155 LONG rc = 0;
156 HKEY hGroupKey, hServiceKey, hDriverKey;
157 char ValueBuffer[256];
158 char ServiceName[256];
159 ULONG BufferSize;
160 ULONG Index;
161 char *s, *p;
162 char GroupName[256];
163 ULONG len;
164 BOOL done;
165
166 ULONG ValueSize;
167 ULONG ValueType;
168 ULONG StartValue;
169 UCHAR DriverGroup[256];
170 ULONG DriverGroupSize;
171
172 UCHAR ImagePath[256];
173
174 /* get 'service group order' key */
175 rc = RegOpenKey(NULL,
176 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
177 &hGroupKey);
178 // printf("RegOpenKey(): rc %d\n", (int)rc);
179 if (rc != ERROR_SUCCESS)
180 return;
181
182 /* enumerate drivers */
183 rc = RegOpenKey(NULL,
184 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
185 &hServiceKey);
186 // printf("RegOpenKey(): rc %d\n", (int)rc);
187 if (rc != ERROR_SUCCESS)
188 return;
189
190 // printf("hKey: %x\n", (int)hKey);
191
192 BufferSize = 256;
193 rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)ValueBuffer, &BufferSize);
194 // printf("RegQueryValue(): rc %d\n", (int)rc);
195 if (rc != ERROR_SUCCESS)
196 return;
197
198
199 // printf("BufferSize: %d \n", (int)BufferSize);
200
201 // printf("ValueBuffer: '%s' \n", ValueBuffer);
202
203 done = FALSE;
204 s = ValueBuffer;
205 do
206 {
207 p = strchr(s, ';');
208 if (p != NULL)
209 {
210 len = p - s;
211 memcpy(GroupName, s, len);
212 GroupName[len] = 0;
213 s = p + 1;
214 }
215 else
216 {
217 strcpy(GroupName, s);
218 done = TRUE;
219 }
220 // printf("Driver group: '%s'\n", GroupName);
221
222 /* enumerate all drivers */
223 Index = 0;
224 while (TRUE)
225 {
226 ValueSize = 256;
227 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
228 // printf("RegEnumKey(): rc %d\n", (int)rc);
229 if (rc == ERROR_NO_MORE_ITEMS)
230 break;
231 if (rc != ERROR_SUCCESS)
232 return;
233 // printf("Service %d: '%s'\n", (int)Index, ServiceName);
234
235 /* open driver Key */
236 rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
237
238 ValueSize = sizeof(ULONG);
239 rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
240 // printf(" Start: %x \n", (int)StartValue);
241
242 DriverGroupSize = 256;
243 rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
244 // printf(" Group: %s \n", DriverGroup);
245
246 if ((StartValue == 0) && (stricmp(DriverGroup, GroupName) == 0))
247 {
248 ValueSize = 256;
249 rc = RegQueryValue(hDriverKey,
250 "ImagePathName",
251 NULL,
252 (PUCHAR)ImagePath,
253 &ValueSize);
254 if (rc != ERROR_SUCCESS)
255 {
256 // printf(" ImagePath: not found\n");
257 strcpy(ImagePath, szSystemRoot);
258 strcat(ImagePath, "system32\\drivers\\");
259 strcat(ImagePath, ServiceName);
260 strcat(ImagePath, ".sys");
261 }
262 else
263 {
264 // printf(" ImagePath: '%s'\n", ImagePath);
265 }
266 // printf(" Loading driver: '%s'\n", ImagePath);
267
268 if (nPos < 100)
269 nPos += 5;
270
271 LoadDriver(ImagePath, nPos);
272 }
273 Index++;
274 }
275 }
276 while(done == FALSE);
277 }
278
279
280 static BOOL
281 LoadNlsFiles(PCHAR szSystemRoot)
282 {
283 LONG rc = ERROR_SUCCESS;
284 HKEY hKey;
285 char szIdBuffer[80];
286 char szNameBuffer[80];
287 char szFileName[256];
288 ULONG BufferSize;
289
290 /* open the codepage key */
291 rc = RegOpenKey(NULL,
292 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
293 &hKey);
294 if (rc != ERROR_SUCCESS)
295 return(FALSE);
296
297
298 /* get ANSI codepage */
299 BufferSize = 80;
300 rc = RegQueryValue(hKey, "ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
301 if (rc != ERROR_SUCCESS)
302 return(FALSE);
303
304 BufferSize = 80;
305 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
306 if (rc != ERROR_SUCCESS)
307 return(FALSE);
308
309
310 /* load ANSI codepage table */
311 strcpy(szFileName, szSystemRoot);
312 strcat(szFileName, "system32\\");
313 strcat(szFileName, szNameBuffer);
314 if (!LoadNlsFile(szFileName, "ANSI.NLS"))
315 return(FALSE);
316
317
318 /* get OEM codepage */
319 BufferSize = 80;
320 rc = RegQueryValue(hKey, "OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
321 if (rc != ERROR_SUCCESS)
322 return(FALSE);
323
324 BufferSize = 80;
325 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
326 if (rc != ERROR_SUCCESS)
327 return(FALSE);
328
329 /* load OEM codepage table */
330 strcpy(szFileName, szSystemRoot);
331 strcat(szFileName, "system32\\");
332 strcat(szFileName, szNameBuffer);
333 if (!LoadNlsFile(szFileName, "OEM.NLS"))
334 return(FALSE);
335
336
337 /* open the language key */
338 rc = RegOpenKey(NULL,
339 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
340 &hKey);
341 if (rc != ERROR_SUCCESS)
342 return(FALSE);
343
344
345 /* get the Unicode case table */
346 BufferSize = 80;
347 rc = RegQueryValue(hKey, "Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
348 if (rc != ERROR_SUCCESS)
349 return(FALSE);
350
351 BufferSize = 80;
352 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
353 if (rc != ERROR_SUCCESS)
354 return(FALSE);
355
356 /* load Unicode case table */
357 strcpy(szFileName, szSystemRoot);
358 strcat(szFileName, "system32\\");
359 strcat(szFileName, szNameBuffer);
360 if (!LoadNlsFile(szFileName, "UNICASE.NLS"))
361 return(FALSE);
362
363 return(TRUE);
364 }
365
366
367 void LoadAndBootReactOS(PUCHAR OperatingSystemName)
368 {
369 PFILE FilePointer;
370 char name[1024];
371 char value[1024];
372 char szFileName[1024];
373 char szBootPath[256];
374 // int i;
375 // int nNumDriverFiles=0;
376 // int nNumFilesLoaded=0;
377 char MsgBuffer[256];
378 ULONG SectionId;
379
380 char* Base;
381 ULONG Size;
382
383 //
384 // Open the operating system section
385 // specified in the .ini file
386 //
387 if (!OpenSection(OperatingSystemName, &SectionId))
388 {
389 sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
390 MessageBox(MsgBuffer);
391 return;
392 }
393
394 /*
395 * Setup multiboot information structure
396 */
397 mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
398 mb_info.mem_lower = GetConventionalMemorySize();
399 mb_info.mem_upper = GetExtendedMemorySize();
400 mb_info.boot_device = 0xffffffff;
401 mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
402 mb_info.mods_count = 0;
403 mb_info.mods_addr = (unsigned long)multiboot_modules;
404 mb_info.mmap_length = GetBiosMemoryMap(&multiboot_memory_map);
405 if (mb_info.mmap_length)
406 {
407 mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
408 mb_info.flags |= MB_INFO_FLAG_MEMORY_MAP;
409 //printf("memory map length: %d\n", mb_info.mmap_length);
410 //printf("dumping memory map:\n");
411 //for (i=0; i<(mb_info.mmap_length / 4); i++)
412 //{
413 // printf("0x%x\n", ((unsigned long *)&multiboot_memory_map)[i]);
414 //}
415 //getch();
416 }
417 //printf("low_mem = %d\n", mb_info.mem_lower);
418 //printf("high_mem = %d\n", mb_info.mem_upper);
419 //getch();
420
421 /*
422 * Make sure the system path is set in the .ini file
423 */
424 if (!ReadSectionSettingByName(SectionId, "SystemPath", value, 1024))
425 {
426 MessageBox("System path not specified for selected operating system.");
427 return;
428 }
429
430 /*
431 * Verify system path
432 */
433 if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
434 {
435 sprintf(MsgBuffer,"Invalid system path: '%s'", value);
436 MessageBox(MsgBuffer);
437 return;
438 }
439
440 /* set boot drive and partition */
441 ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
442 ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
443
444 /* copy ARC path into kernel command line */
445 strcpy(multiboot_kernel_cmdline, value);
446
447 /*
448 * Read the optional kernel parameters (if any)
449 */
450 if (ReadSectionSettingByName(SectionId, "Options", value, 1024))
451 {
452 strcat(multiboot_kernel_cmdline, " ");
453 strcat(multiboot_kernel_cmdline, value);
454 }
455
456 /* append a backslash */
457 if ((strlen(szBootPath)==0) ||
458 szBootPath[strlen(szBootPath)] != '\\')
459 strcat(szBootPath, "\\");
460
461 #ifndef NDEBUG
462 sprintf(MsgBuffer,"SystemRoot: '%s'", szBootPath);
463 MessageBox(MsgBuffer);
464 #endif
465
466 DrawBackdrop();
467
468 DrawStatusText(" Loading...");
469 DrawProgressBar(0);
470
471 /*
472 * Try to open boot drive
473 */
474 if (!OpenDiskDrive(BootDrive, BootPartition))
475 {
476 MessageBox("Failed to open boot drive.");
477 return;
478 }
479
480 /*
481 * Find the kernel image name
482 * and try to load the kernel off the disk
483 */
484 if(ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
485 {
486 /*
487 * Set the name and
488 */
489 if (value[0] == '\\')
490 {
491 strcpy(szFileName, value);
492 }
493 else
494 {
495 strcpy(szFileName, szBootPath);
496 strcat(szFileName, "SYSTEM32\\");
497 strcat(szFileName, value);
498 }
499 }
500 else
501 {
502 strcpy(value, "NTOSKRNL.EXE");
503 strcpy(szFileName, szBootPath);
504 strcat(szFileName, "SYSTEM32\\");
505 strcat(szFileName, value);
506 }
507
508 if (!LoadKernel(szFileName, 5))
509 return;
510
511 /*
512 * Find the HAL image name
513 * and try to load the kernel off the disk
514 */
515 if(ReadSectionSettingByName(SectionId, "Hal", value, 1024))
516 {
517 /*
518 * Set the name and
519 */
520 if (value[0] == '\\')
521 {
522 strcpy(szFileName, value);
523 }
524 else
525 {
526 strcpy(szFileName, szBootPath);
527 strcat(szFileName, "SYSTEM32\\");
528 strcat(szFileName, value);
529 }
530 }
531 else
532 {
533 strcpy(value, "HAL.DLL");
534 strcpy(szFileName, szBootPath);
535 strcat(szFileName, "SYSTEM32\\");
536 strcat(szFileName, value);
537 }
538
539 if (!LoadDriver(szFileName, 10))
540 return;
541
542 /*
543 * Find the System hive image name
544 * and try to load it off the disk
545 */
546 if(ReadSectionSettingByName(SectionId, "SystemHive", value, 1024))
547 {
548 /*
549 * Set the name and
550 */
551 if (value[0] == '\\')
552 {
553 strcpy(szFileName, value);
554 }
555 else
556 {
557 strcpy(szFileName, szBootPath);
558 strcat(szFileName, "SYSTEM32\\CONFIG\\");
559 strcat(szFileName, value);
560 }
561 }
562 else
563 {
564 strcpy(value, "SYSTEM.HIV");
565 strcpy(szFileName, szBootPath);
566 strcat(szFileName, "SYSTEM32\\CONFIG\\");
567 strcat(szFileName, value);
568 }
569
570 #ifndef NDEBUG
571 sprintf(MsgBuffer,"SystemHive: '%s'", szFileName);
572 MessageBox(MsgBuffer);
573 #endif
574
575 FilePointer = OpenFile(szFileName);
576 if (FilePointer == NULL)
577 {
578 strcat(value, " not found.");
579 MessageBox(value);
580 return;
581 }
582
583 /*
584 * Update the status bar with the current file
585 */
586 strcpy(name, " Reading ");
587 strcat(name, value);
588 while (strlen(name) < 80)
589 strcat(name, " ");
590 DrawStatusText(name);
591
592 /*
593 * Load the system hive
594 */
595 Base = MultiBootLoadModule(FilePointer, szFileName, &Size);
596 RegInitializeRegistry();
597 RegImportHive(Base, Size);
598
599 DrawProgressBar(15);
600
601 #ifndef NDEBUG
602 sprintf(MsgBuffer,"SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size);
603 MessageBox(MsgBuffer);
604 #endif
605
606 /*
607 * retrieve hardware information and create the hardware hive
608 */
609 DetectHardware();
610 // Base = MultiBootCreateModule(HARDWARE.HIV);
611 // RegExportHive("\\Registry\\Machine\\HARDWARE", Base, &Size);
612 // MultiBootCloseModule(Base, Size);
613
614 DrawProgressBar(20);
615
616 /*
617 * load NLS files
618 */
619 if (!LoadNlsFiles(szBootPath))
620 {
621 MessageBox("Failed to load NLS files\n");
622 return;
623 }
624
625 DrawProgressBar(25);
626
627 /*
628 * load boot drivers
629 */
630 LoadBootDrivers(szBootPath, 25);
631
632
633 /*
634 * Clear the screen and redraw the backdrop and status bar
635 */
636 DrawBackdrop();
637 DrawStatusText(" Press any key to boot");
638
639 /*
640 * Wait for user
641 */
642 strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
643 strcat(name, OperatingSystemName);
644 strcat(name, ".");
645 //MessageBox(name);
646
647 RestoreScreen(ScreenBuffer);
648
649 /*
650 * Now boot the kernel
651 */
652 stop_floppy();
653 boot_reactos();
654 }
655