604d7ac9629fa7ba47970dc2e471203f48c817fa
[reactos.git] / boot / freeldr / freeldr / custom.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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 /* INCLUDES *******************************************************************/
21
22 #include <freeldr.h>
23
24 /* GLOBALS ********************************************************************/
25
26 #ifdef _M_IX86
27
28 const CHAR BootSectorFilePrompt[] = "Enter the boot sector file path.\n\nExamples:\n\\BOOTSECT.DOS\n/boot/bootsect.dos";
29 const CHAR LinuxKernelPrompt[] = "Enter the Linux kernel image path.\n\nExamples:\n/vmlinuz\n/boot/vmlinuz-2.4.18";
30 const CHAR LinuxInitrdPrompt[] = "Enter the initrd image path.\n\nExamples:\n/initrd.gz\n/boot/root.img.gz\n\nLeave blank for no initial ram disk.";
31 const CHAR LinuxCommandLinePrompt[] = "Enter the Linux kernel command line.\n\nExamples:\nroot=/dev/hda1\nroot=/dev/fd0 read-only\nroot=/dev/sdb1 init=/sbin/init";
32
33 #endif // _M_IX86
34
35 const CHAR BootDrivePrompt[] = "Enter the boot drive.\n\nExamples:\nfd0 - first floppy drive\nhd0 - first hard drive\nhd1 - second hard drive\ncd0 - first CD-ROM drive.\n\nBIOS drive numbers may also be used:\n0 - first floppy drive\n0x80 - first hard drive\n0x81 - second hard drive";
36 const CHAR BootPartitionPrompt[] = "Enter the boot partition.\n\nEnter 0 for the active (bootable) partition.";
37 const CHAR ARCPathPrompt[] = "Enter the boot ARC path.\n\nExamples:\nmulti(0)disk(0)rdisk(0)partition(1)\nmulti(0)disk(0)fdisk(0)";
38 const CHAR ReactOSSystemPathPrompt[] = "Enter the path to your ReactOS system directory.\n\nExamples:\n\\REACTOS\n\\ROS";
39 const CHAR ReactOSOptionsPrompt[] = "Enter the options you want passed to the kernel.\n\nExamples:\n/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200\n/FASTDETECT /SOS /NOGUIBOOT\n/BASEVIDEO /MAXMEM=64\n/KERNEL=NTKRNLMP.EXE /HAL=HALMPS.DLL";
40 const CHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup.";
41
42 /* FUNCTIONS ******************************************************************/
43
44 #ifdef HAS_OPTION_MENU_CUSTOM_BOOT
45
46 VOID OptionMenuCustomBoot(VOID)
47 {
48 PCSTR CustomBootMenuList[] = {
49 #ifdef _M_IX86
50 "Disk",
51 "Partition",
52 "Boot Sector File",
53 "Linux",
54 #endif
55 "ReactOS",
56 "ReactOS Setup"
57 };
58 ULONG SelectedMenuItem;
59 OperatingSystemItem OperatingSystem;
60
61 if (!UiDisplayMenu("Please choose a boot method:", NULL,
62 FALSE,
63 CustomBootMenuList,
64 RTL_NUMBER_OF(CustomBootMenuList),
65 0, -1,
66 &SelectedMenuItem,
67 TRUE,
68 NULL, NULL))
69 {
70 /* The user pressed ESC */
71 return;
72 }
73
74 /* Initialize a new custom OS entry */
75 OperatingSystem.SectionId = 0;
76 switch (SelectedMenuItem)
77 {
78 #ifdef _M_IX86
79 case 0: // Disk
80 EditCustomBootDisk(&OperatingSystem);
81 break;
82 case 1: // Partition
83 EditCustomBootPartition(&OperatingSystem);
84 break;
85 case 2: // Boot Sector File
86 EditCustomBootSectorFile(&OperatingSystem);
87 break;
88 case 3: // Linux
89 EditCustomBootLinux(&OperatingSystem);
90 break;
91 case 4: // ReactOS
92 EditCustomBootReactOS(&OperatingSystem, FALSE);
93 break;
94 case 5: // ReactOS Setup
95 EditCustomBootReactOS(&OperatingSystem, TRUE);
96 break;
97 #else
98 case 0: // ReactOS
99 EditCustomBootReactOS(&OperatingSystem, FALSE);
100 break;
101 case 1: // ReactOS Setup
102 EditCustomBootReactOS(&OperatingSystem, TRUE);
103 break;
104 #endif
105 }
106
107 /* And boot it */
108 if (OperatingSystem.SectionId != 0)
109 {
110 UiMessageBox(CustomBootPrompt);
111 LoadOperatingSystem(&OperatingSystem);
112 }
113 }
114
115 #endif // HAS_OPTION_MENU_CUSTOM_BOOT
116
117 #ifdef _M_IX86
118
119 VOID
120 EditCustomBootDisk(
121 IN OUT OperatingSystemItem* OperatingSystem)
122 {
123 TIMEINFO* TimeInfo;
124 ULONG_PTR SectionId = OperatingSystem->SectionId;
125 CHAR SectionName[100];
126 /* This construct is a trick for saving some stack space */
127 union
128 {
129 struct
130 {
131 CHAR Guard1;
132 CHAR Drive[20];
133 CHAR Guard2;
134 };
135 CHAR ArcPath[200];
136 } BootStrings;
137
138 RtlZeroMemory(SectionName, sizeof(SectionName));
139 RtlZeroMemory(&BootStrings, sizeof(BootStrings));
140
141 if (SectionId != 0)
142 {
143 /* Load the settings */
144
145 /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
146 *BootStrings.ArcPath = ANSI_NULL;
147 IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
148 if (!*BootStrings.ArcPath)
149 {
150 /* We don't, retrieve the boot drive value instead */
151 IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
152 }
153 }
154
155 if (!*BootStrings.ArcPath)
156 {
157 if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
158 return;
159 }
160 if (!*BootStrings.Drive)
161 {
162 if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
163 return;
164 }
165
166 /* Modify the settings values and return if we were in edit mode */
167 if (SectionId != 0)
168 {
169 /* Modify the BootPath if we have one */
170 if (*BootStrings.ArcPath)
171 {
172 IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
173 }
174 else if (*BootStrings.Drive)
175 {
176 /* Otherwise, modify the BootDrive */
177 IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
178 }
179 return;
180 }
181
182 /* Generate a unique section name */
183 TimeInfo = ArcGetTime();
184 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
185 "CustomBootDisk%u%u%u%u%u%u",
186 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
187 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
188
189 /* Add the section */
190 if (!IniAddSection(SectionName, &SectionId))
191 return;
192
193 /* Add the BootType */
194 if (!IniAddSettingValueToSection(SectionId, "BootType", "Drive"))
195 return;
196
197 /* Add the BootPath if we have one */
198 if (*BootStrings.ArcPath)
199 {
200 if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
201 return;
202 }
203 else if (*BootStrings.Drive)
204 {
205 /* Otherwise, add the BootDrive */
206 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
207 return;
208 }
209
210 OperatingSystem->SectionId = SectionId;
211 OperatingSystem->LoadIdentifier = NULL;
212 }
213
214 VOID
215 EditCustomBootPartition(
216 IN OUT OperatingSystemItem* OperatingSystem)
217 {
218 TIMEINFO* TimeInfo;
219 ULONG_PTR SectionId = OperatingSystem->SectionId;
220 CHAR SectionName[100];
221 /* This construct is a trick for saving some stack space */
222 union
223 {
224 struct
225 {
226 CHAR Guard1;
227 CHAR Drive[20];
228 CHAR Partition[20];
229 CHAR Guard2;
230 };
231 CHAR ArcPath[200];
232 } BootStrings;
233
234 RtlZeroMemory(SectionName, sizeof(SectionName));
235 RtlZeroMemory(&BootStrings, sizeof(BootStrings));
236
237 if (SectionId != 0)
238 {
239 /* Load the settings */
240
241 /*
242 * Check whether we have a "BootPath" value (takes precedence
243 * over both "BootDrive" and "BootPartition").
244 */
245 *BootStrings.ArcPath = ANSI_NULL;
246 IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
247 if (!*BootStrings.ArcPath)
248 {
249 /* We don't, retrieve the boot drive and partition values instead */
250 IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
251 IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
252 }
253 }
254
255 if (!*BootStrings.ArcPath)
256 {
257 if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
258 return;
259
260 if (*BootStrings.Drive)
261 {
262 if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
263 return;
264 }
265 }
266 if (!*BootStrings.Drive)
267 {
268 if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
269 return;
270 }
271
272 /* Modify the settings values and return if we were in edit mode */
273 if (SectionId != 0)
274 {
275 /* Modify the BootPath if we have one */
276 if (*BootStrings.ArcPath)
277 {
278 IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
279 }
280 else if (*BootStrings.Drive)
281 {
282 /* Otherwise, modify the BootDrive and BootPartition */
283 IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
284 IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
285 }
286 return;
287 }
288
289 /* Generate a unique section name */
290 TimeInfo = ArcGetTime();
291 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
292 "CustomBootPartition%u%u%u%u%u%u",
293 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
294 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
295
296 /* Add the section */
297 if (!IniAddSection(SectionName, &SectionId))
298 return;
299
300 /* Add the BootType */
301 if (!IniAddSettingValueToSection(SectionId, "BootType", "Partition"))
302 return;
303
304 /* Add the BootPath if we have one */
305 if (*BootStrings.ArcPath)
306 {
307 if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
308 return;
309 }
310 else if (*BootStrings.Drive)
311 {
312 /* Otherwise, add the BootDrive and BootPartition */
313 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
314 return;
315
316 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
317 return;
318 }
319
320 OperatingSystem->SectionId = SectionId;
321 OperatingSystem->LoadIdentifier = NULL;
322 }
323
324 VOID
325 EditCustomBootSectorFile(
326 IN OUT OperatingSystemItem* OperatingSystem)
327 {
328 TIMEINFO* TimeInfo;
329 ULONG_PTR SectionId = OperatingSystem->SectionId;
330 CHAR SectionName[100];
331 /* This construct is a trick for saving some stack space */
332 union
333 {
334 struct
335 {
336 CHAR Guard1;
337 CHAR Drive[20];
338 CHAR Partition[20];
339 CHAR Guard2;
340 };
341 CHAR ArcPath[200];
342 } BootStrings;
343 CHAR BootSectorFileString[200];
344
345 RtlZeroMemory(SectionName, sizeof(SectionName));
346 RtlZeroMemory(&BootStrings, sizeof(BootStrings));
347 RtlZeroMemory(BootSectorFileString, sizeof(BootSectorFileString));
348
349 if (SectionId != 0)
350 {
351 /* Load the settings */
352
353 /*
354 * Check whether we have a "BootPath" value (takes precedence
355 * over both "BootDrive" and "BootPartition").
356 */
357 *BootStrings.ArcPath = ANSI_NULL;
358 IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
359 if (!*BootStrings.ArcPath)
360 {
361 /* We don't, retrieve the boot drive and partition values instead */
362 IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
363 IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
364 }
365
366 IniReadSettingByName(SectionId, "BootSectorFile", BootSectorFileString, sizeof(BootSectorFileString));
367 }
368
369 if (!*BootStrings.ArcPath)
370 {
371 if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
372 return;
373
374 if (*BootStrings.Drive)
375 {
376 if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
377 return;
378 }
379 }
380 if (!*BootStrings.Drive)
381 {
382 if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
383 return;
384 }
385
386 if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, sizeof(BootSectorFileString)))
387 return;
388
389 /* Modify the settings values and return if we were in edit mode */
390 if (SectionId != 0)
391 {
392 /* Modify the BootPath if we have one */
393 if (*BootStrings.ArcPath)
394 {
395 IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
396 }
397 else if (*BootStrings.Drive)
398 {
399 /* Otherwise, modify the BootDrive and BootPartition */
400 IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
401 IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
402 }
403 else
404 {
405 /*
406 * Otherwise, zero out all values: BootSectorFile will be
407 * relative to the default system partition.
408 */
409 IniModifySettingValue(SectionId, "BootPath", "");
410 IniModifySettingValue(SectionId, "BootDrive", "");
411 IniModifySettingValue(SectionId, "BootPartition", "");
412 }
413
414 IniModifySettingValue(SectionId, "BootSectorFile", BootSectorFileString);
415 return;
416 }
417
418 /* Generate a unique section name */
419 TimeInfo = ArcGetTime();
420 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
421 "CustomBootSectorFile%u%u%u%u%u%u",
422 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
423 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
424
425 /* Add the section */
426 if (!IniAddSection(SectionName, &SectionId))
427 return;
428
429 /* Add the BootType */
430 if (!IniAddSettingValueToSection(SectionId, "BootType", "BootSector"))
431 return;
432
433 /* Add the BootPath if we have one */
434 if (*BootStrings.ArcPath)
435 {
436 if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
437 return;
438 }
439 else if (*BootStrings.Drive)
440 {
441 /* Otherwise, add the BootDrive and BootPartition */
442 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
443 return;
444
445 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
446 return;
447 }
448
449 /* Add the BootSectorFile */
450 if (!IniAddSettingValueToSection(SectionId, "BootSectorFile", BootSectorFileString))
451 return;
452
453 OperatingSystem->SectionId = SectionId;
454 OperatingSystem->LoadIdentifier = NULL;
455 }
456
457 VOID
458 EditCustomBootLinux(
459 IN OUT OperatingSystemItem* OperatingSystem)
460 {
461 TIMEINFO* TimeInfo;
462 ULONG_PTR SectionId = OperatingSystem->SectionId;
463 CHAR SectionName[100];
464 /* This construct is a trick for saving some stack space */
465 union
466 {
467 struct
468 {
469 CHAR Guard1;
470 CHAR Drive[20];
471 CHAR Partition[20];
472 CHAR Guard2;
473 };
474 CHAR ArcPath[200];
475 } BootStrings;
476 CHAR LinuxKernelString[200];
477 CHAR LinuxInitrdString[200];
478 CHAR LinuxCommandLineString[200];
479
480 RtlZeroMemory(SectionName, sizeof(SectionName));
481 RtlZeroMemory(&BootStrings, sizeof(BootStrings));
482 RtlZeroMemory(LinuxKernelString, sizeof(LinuxKernelString));
483 RtlZeroMemory(LinuxInitrdString, sizeof(LinuxInitrdString));
484 RtlZeroMemory(LinuxCommandLineString, sizeof(LinuxCommandLineString));
485
486 if (SectionId != 0)
487 {
488 /* Load the settings */
489
490 /*
491 * Check whether we have a "BootPath" value (takes precedence
492 * over both "BootDrive" and "BootPartition").
493 */
494 *BootStrings.ArcPath = ANSI_NULL;
495 IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
496 if (!*BootStrings.ArcPath)
497 {
498 /* We don't, retrieve the boot drive and partition values instead */
499 IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
500 IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
501 }
502
503 IniReadSettingByName(SectionId, "Kernel", LinuxKernelString, sizeof(LinuxKernelString));
504 IniReadSettingByName(SectionId, "Initrd", LinuxInitrdString, sizeof(LinuxInitrdString));
505 IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLineString, sizeof(LinuxCommandLineString));
506 }
507
508 if (!*BootStrings.ArcPath)
509 {
510 if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
511 return;
512
513 if (*BootStrings.Drive)
514 {
515 if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
516 return;
517 }
518 }
519 if (!*BootStrings.Drive)
520 {
521 if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
522 return;
523 }
524
525 if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, sizeof(LinuxKernelString)))
526 return;
527
528 if (!UiEditBox(LinuxInitrdPrompt, LinuxInitrdString, sizeof(LinuxInitrdString)))
529 return;
530
531 if (!UiEditBox(LinuxCommandLinePrompt, LinuxCommandLineString, sizeof(LinuxCommandLineString)))
532 return;
533
534 /* Modify the settings values and return if we were in edit mode */
535 if (SectionId != 0)
536 {
537 /* Modify the BootPath if we have one */
538 if (*BootStrings.ArcPath)
539 {
540 IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
541 }
542 else if (*BootStrings.Drive)
543 {
544 /* Otherwise, modify the BootDrive and BootPartition */
545 IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
546 IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
547 }
548 else
549 {
550 /*
551 * Otherwise, zero out all values: BootSectorFile will be
552 * relative to the default system partition.
553 */
554 IniModifySettingValue(SectionId, "BootPath", "");
555 IniModifySettingValue(SectionId, "BootDrive", "");
556 IniModifySettingValue(SectionId, "BootPartition", "");
557 }
558
559 IniModifySettingValue(SectionId, "Kernel", LinuxKernelString);
560 IniModifySettingValue(SectionId, "Initrd", LinuxInitrdString);
561 IniModifySettingValue(SectionId, "CommandLine", LinuxCommandLineString);
562 return;
563 }
564
565 /* Generate a unique section name */
566 TimeInfo = ArcGetTime();
567 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
568 "CustomLinux%u%u%u%u%u%u",
569 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
570 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
571
572 /* Add the section */
573 if (!IniAddSection(SectionName, &SectionId))
574 return;
575
576 /* Add the BootType */
577 if (!IniAddSettingValueToSection(SectionId, "BootType", "Linux"))
578 return;
579
580 /* Add the BootPath if we have one */
581 if (*BootStrings.ArcPath)
582 {
583 if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
584 return;
585 }
586 else if (*BootStrings.Drive)
587 {
588 /* Otherwise, add the BootDrive and BootPartition */
589 if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
590 return;
591
592 if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
593 return;
594 }
595
596 /* Add the Kernel */
597 if (!IniAddSettingValueToSection(SectionId, "Kernel", LinuxKernelString))
598 return;
599
600 /* Add the Initrd */
601 if (*LinuxInitrdString)
602 {
603 if (!IniAddSettingValueToSection(SectionId, "Initrd", LinuxInitrdString))
604 return;
605 }
606
607 /* Add the CommandLine */
608 if (!IniAddSettingValueToSection(SectionId, "CommandLine", LinuxCommandLineString))
609 return;
610
611 OperatingSystem->SectionId = SectionId;
612 OperatingSystem->LoadIdentifier = "Custom Linux Setup";
613 }
614
615 #endif // _M_IX86
616
617 VOID
618 EditCustomBootReactOS(
619 IN OUT OperatingSystemItem* OperatingSystem,
620 IN BOOLEAN IsSetup)
621 {
622 TIMEINFO* TimeInfo;
623 ULONG_PTR SectionId = OperatingSystem->SectionId;
624 CHAR SectionName[100];
625 CHAR BootDriveString[20];
626 CHAR BootPartitionString[20];
627 CHAR ReactOSSystemPath[200];
628 CHAR ReactOSARCPath[200];
629 CHAR ReactOSOptions[200];
630
631 RtlZeroMemory(SectionName, sizeof(SectionName));
632 RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
633 RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
634 RtlZeroMemory(ReactOSSystemPath, sizeof(ReactOSSystemPath));
635 RtlZeroMemory(ReactOSARCPath, sizeof(ReactOSARCPath));
636 RtlZeroMemory(ReactOSOptions, sizeof(ReactOSOptions));
637
638 if (SectionId != 0)
639 {
640 /* Load the settings */
641 IniReadSettingByName(SectionId, "SystemPath", ReactOSARCPath, sizeof(ReactOSARCPath));
642 IniReadSettingByName(SectionId, "Options", ReactOSOptions, sizeof(ReactOSOptions));
643 }
644
645 if (SectionId == 0)
646 {
647 if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
648 return;
649
650 if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
651 return;
652
653 if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, sizeof(ReactOSSystemPath)))
654 return;
655 }
656 else
657 {
658 if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSARCPath, sizeof(ReactOSARCPath)))
659 return;
660 }
661
662 if (!UiEditBox(ReactOSOptionsPrompt, ReactOSOptions, sizeof(ReactOSOptions)))
663 return;
664
665 /* Modify the settings values and return if we were in edit mode */
666 if (SectionId != 0)
667 {
668 IniModifySettingValue(SectionId, "SystemPath", ReactOSARCPath);
669 IniModifySettingValue(SectionId, "Options", ReactOSOptions);
670 return;
671 }
672
673 /* Generate a unique section name */
674 TimeInfo = ArcGetTime();
675 RtlStringCbPrintfA(SectionName, sizeof(SectionName),
676 "CustomReactOS%u%u%u%u%u%u",
677 TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
678 TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
679
680 /* Add the section */
681 if (!IniAddSection(SectionName, &SectionId))
682 return;
683
684 /* Add the BootType */
685 if (!IniAddSettingValueToSection(SectionId, "BootType", IsSetup ? "ReactOSSetup" : "Windows2003"))
686 return;
687
688 /* Construct the ReactOS ARC system path */
689 ConstructArcPath(ReactOSARCPath, ReactOSSystemPath, DriveMapGetBiosDriveNumber(BootDriveString), atoi(BootPartitionString));
690
691 /* Add the system path */
692 if (!IniAddSettingValueToSection(SectionId, "SystemPath", ReactOSARCPath))
693 return;
694
695 /* Add the CommandLine */
696 if (!IniAddSettingValueToSection(SectionId, "Options", ReactOSOptions))
697 return;
698
699 OperatingSystem->SectionId = SectionId;
700 OperatingSystem->LoadIdentifier = NULL;
701 }
702
703 #ifdef HAS_OPTION_MENU_REBOOT
704
705 VOID OptionMenuReboot(VOID)
706 {
707 UiMessageBox("The system will now reboot.");
708 Reboot();
709 }
710
711 #endif // HAS_OPTION_MENU_REBOOT