7b4629bb5ad18145b2e95549800cec10e9a10ae1
[reactos.git] / base / setup / usetup / bootsup.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: base/setup/usetup/bootsup.c
5 * PURPOSE: Bootloader support functions
6 * PROGRAMMER: Eric Kohl
7 */
8
9 #include "usetup.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 #define SECTORSIZE 512
15
16 #include <pshpack1.h>
17 typedef struct _FAT_BOOTSECTOR
18 {
19 UCHAR JumpBoot[3]; // Jump instruction to boot code
20 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
21 USHORT BytesPerSector; // Bytes per sector
22 UCHAR SectorsPerCluster; // Number of sectors in a cluster
23 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
24 UCHAR NumberOfFats; // Number of FAT tables
25 USHORT RootDirEntries; // Number of root directory entries (fat12/16)
26 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
27 UCHAR MediaDescriptor; // Media descriptor byte
28 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
29 USHORT SectorsPerTrack; // Number of sectors in a track
30 USHORT NumberOfHeads; // Number of heads on the disk
31 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
32 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
33 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
34 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
35 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
36 ULONG VolumeSerialNumber; // Volume serial number
37 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
38 CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
39
40 UCHAR BootCodeAndData[448]; // The remainder of the boot sector
41
42 USHORT BootSectorMagic; // 0xAA55
43
44 } FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
45
46 typedef struct _FAT32_BOOTSECTOR
47 {
48 UCHAR JumpBoot[3]; // Jump instruction to boot code
49 CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
50 USHORT BytesPerSector; // Bytes per sector
51 UCHAR SectorsPerCluster; // Number of sectors in a cluster
52 USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
53 UCHAR NumberOfFats; // Number of FAT tables
54 USHORT RootDirEntries; // Number of root directory entries (fat12/16)
55 USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
56 UCHAR MediaDescriptor; // Media descriptor byte
57 USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
58 USHORT SectorsPerTrack; // Number of sectors in a track
59 USHORT NumberOfHeads; // Number of heads on the disk
60 ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
61 ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
62 ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
63 USHORT ExtendedFlags; // Extended flags (fat32)
64 USHORT FileSystemVersion; // File system version (fat32)
65 ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32)
66 USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
67 USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
68 UCHAR Reserved[12]; // Reserved for future expansion
69 UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
70 UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
71 UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
72 ULONG VolumeSerialNumber; // Volume serial number
73 CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
74 CHAR FileSystemType[8]; // Always set to the string "FAT32 "
75
76 UCHAR BootCodeAndData[420]; // The remainder of the boot sector
77
78 USHORT BootSectorMagic; // 0xAA55
79
80 } FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
81
82 typedef struct _EXT2_BOOTSECTOR
83 {
84 // The EXT2 bootsector is completely user-specific.
85 // No FS data is stored there.
86 UCHAR Fill[1024];
87 } EXT2_BOOTSECTOR, *PEXT2_BOOTSECTOR;
88
89 // TODO: Add more bootsector structures!
90
91 #include <poppack.h>
92
93 extern PPARTLIST PartitionList;
94
95 /* FUNCTIONS ****************************************************************/
96
97
98 static
99 VOID
100 CreateCommonFreeLoaderSections(
101 PINICACHE IniCache)
102 {
103 PINICACHESECTION IniSection;
104
105 /* Create "FREELOADER" section */
106 IniSection = IniCacheAppendSection(IniCache, L"FREELOADER");
107
108 #if DBG
109 if (IsUnattendedSetup)
110 {
111 /* DefaultOS=ReactOS */
112 IniCacheInsertKey(IniSection,
113 NULL,
114 INSERT_LAST,
115 L"DefaultOS",
116 #ifndef _WINKD_
117 L"ReactOS_KdSerial");
118 #else
119 L"ReactOS_Debug");
120 #endif
121 }
122 else
123 #endif
124 {
125 /* DefaultOS=ReactOS */
126 IniCacheInsertKey(IniSection,
127 NULL,
128 INSERT_LAST,
129 L"DefaultOS",
130 L"ReactOS");
131 }
132
133 #if DBG
134 if (IsUnattendedSetup)
135 #endif
136 {
137 /* Timeout=0 for unattended or non debug*/
138 IniCacheInsertKey(IniSection,
139 NULL,
140 INSERT_LAST,
141 L"TimeOut",
142 L"0");
143 }
144 #if DBG
145 else
146 {
147 /* Timeout=0 or 10 */
148 IniCacheInsertKey(IniSection,
149 NULL,
150 INSERT_LAST,
151 L"TimeOut",
152 L"10");
153 }
154 #endif
155
156 /* Create "Display" section */
157 IniSection = IniCacheAppendSection(IniCache, L"Display");
158
159 /* TitleText=ReactOS Boot Manager */
160 IniCacheInsertKey(IniSection,
161 NULL,
162 INSERT_LAST,
163 L"TitleText",
164 L"ReactOS Boot Manager");
165
166 /* StatusBarColor=Cyan */
167 IniCacheInsertKey(IniSection,
168 NULL,
169 INSERT_LAST,
170 L"StatusBarColor",
171 L"Cyan");
172
173 /* StatusBarTextColor=Black */
174 IniCacheInsertKey(IniSection,
175 NULL,
176 INSERT_LAST,
177 L"StatusBarTextColor",
178 L"Black");
179
180 /* BackdropTextColor=White */
181 IniCacheInsertKey(IniSection,
182 NULL,
183 INSERT_LAST,
184 L"BackdropTextColor",
185 L"White");
186
187 /* BackdropColor=Blue */
188 IniCacheInsertKey(IniSection,
189 NULL,
190 INSERT_LAST,
191 L"BackdropColor",
192 L"Blue");
193
194 /* BackdropFillStyle=Medium */
195 IniCacheInsertKey(IniSection,
196 NULL,
197 INSERT_LAST,
198 L"BackdropFillStyle",
199 L"Medium");
200
201 /* TitleBoxTextColor=White */
202 IniCacheInsertKey(IniSection,
203 NULL,
204 INSERT_LAST,
205 L"TitleBoxTextColor",
206 L"White");
207
208 /* TitleBoxColor=Red */
209 IniCacheInsertKey(IniSection,
210 NULL,
211 INSERT_LAST,
212 L"TitleBoxColor",
213 L"Red");
214
215 /* MessageBoxTextColor=White */
216 IniCacheInsertKey(IniSection,
217 NULL,
218 INSERT_LAST,
219 L"MessageBoxTextColor",
220 L"White");
221
222 /* MessageBoxColor=Blue */
223 IniCacheInsertKey(IniSection,
224 NULL,
225 INSERT_LAST,
226 L"MessageBoxColor",
227 L"Blue");
228
229 /* MenuTextColor=White */
230 IniCacheInsertKey(IniSection,
231 NULL,
232 INSERT_LAST,
233 L"MenuTextColor",
234 L"Gray");
235
236 /* MenuColor=Blue */
237 IniCacheInsertKey(IniSection,
238 NULL,
239 INSERT_LAST,
240 L"MenuColor",
241 L"Black");
242
243 /* TextColor=Yellow */
244 IniCacheInsertKey(IniSection,
245 NULL,
246 INSERT_LAST,
247 L"TextColor",
248 L"Gray");
249
250 /* SelectedTextColor=Black */
251 IniCacheInsertKey(IniSection,
252 NULL,
253 INSERT_LAST,
254 L"SelectedTextColor",
255 L"Black");
256
257 /* SelectedColor=Gray */
258 IniCacheInsertKey(IniSection,
259 NULL,
260 INSERT_LAST,
261 L"SelectedColor",
262 L"Gray");
263
264 /* SelectedColor=Gray */
265 IniCacheInsertKey(IniSection,
266 NULL,
267 INSERT_LAST,
268 L"ShowTime",
269 L"No");
270
271 /* SelectedColor=Gray */
272 IniCacheInsertKey(IniSection,
273 NULL,
274 INSERT_LAST,
275 L"MenuBox",
276 L"No");
277
278 /* SelectedColor=Gray */
279 IniCacheInsertKey(IniSection,
280 NULL,
281 INSERT_LAST,
282 L"CenterMenu",
283 L"No");
284
285 /* SelectedColor=Gray */
286 IniCacheInsertKey(IniSection,
287 NULL,
288 INSERT_LAST,
289 L"MinimalUI",
290 L"Yes");
291
292 /* SelectedColor=Gray */
293 IniCacheInsertKey(IniSection,
294 NULL,
295 INSERT_LAST,
296 L"TimeText",
297 L"Seconds until highlighted choice will be started automatically: ");
298 }
299
300 static
301 NTSTATUS
302 CreateNTOSEntry(
303 PINICACHE IniCache,
304 PINICACHESECTION OSSection,
305 PWCHAR Section,
306 PWCHAR Description,
307 PWCHAR BootType,
308 PWCHAR ArcPath,
309 PWCHAR Options)
310 {
311 PINICACHESECTION IniSection;
312
313 /* Insert entry into "Operating Systems" section */
314 IniCacheInsertKey(OSSection,
315 NULL,
316 INSERT_LAST,
317 Section,
318 Description);
319
320 /* Create new section */
321 IniSection = IniCacheAppendSection(IniCache, Section);
322
323 /* BootType= */
324 IniCacheInsertKey(IniSection,
325 NULL,
326 INSERT_LAST,
327 L"BootType",
328 BootType);
329
330 /* SystemPath= */
331 IniCacheInsertKey(IniSection,
332 NULL,
333 INSERT_LAST,
334 L"SystemPath",
335 ArcPath);
336
337 /* Options= */
338 IniCacheInsertKey(IniSection,
339 NULL,
340 INSERT_LAST,
341 L"Options",
342 Options);
343
344 return STATUS_SUCCESS;
345 }
346
347 static
348 VOID
349 CreateFreeLoaderReactOSEntries(
350 PINICACHE IniCache,
351 PWCHAR ArcPath)
352 {
353 PINICACHESECTION IniSection;
354
355 /* Create "Operating Systems" section */
356 IniSection = IniCacheAppendSection(IniCache, L"Operating Systems");
357
358 /* ReactOS */
359 CreateNTOSEntry(IniCache, IniSection,
360 L"ReactOS", L"\"ReactOS\"",
361 L"Windows2003", ArcPath,
362 L"");
363
364 /* ReactOS_Debug */
365 CreateNTOSEntry(IniCache, IniSection,
366 L"ReactOS_Debug", L"\"ReactOS (Debug)\"",
367 L"Windows2003", ArcPath,
368 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS");
369 #ifdef _WINKD_
370 /* ReactOS_VBoxDebug */
371 CreateNTOSEntry(IniCache, IniSection,
372 L"ReactOS_VBoxDebug", L"\"ReactOS (VBoxDebug)\"",
373 L"Windows2003", ArcPath,
374 L"/DEBUG /DEBUGPORT=VBOX /SOS");
375 #endif
376 #if DBG
377 #ifndef _WINKD_
378 /* ReactOS_KdSerial */
379 CreateNTOSEntry(IniCache, IniSection,
380 L"ReactOS_KdSerial", L"\"ReactOS (RosDbg)\"",
381 L"Windows2003", ArcPath,
382 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /KDSERIAL");
383 #endif
384
385 /* ReactOS_Screen */
386 CreateNTOSEntry(IniCache, IniSection,
387 L"ReactOS_Screen", L"\"ReactOS (Screen)\"",
388 L"Windows2003", ArcPath,
389 L"/DEBUG /DEBUGPORT=SCREEN /SOS");
390
391 /* ReactOS_LogFile */
392 CreateNTOSEntry(IniCache, IniSection,
393 L"ReactOS_LogFile", L"\"ReactOS (Log file)\"",
394 L"Windows2003", ArcPath,
395 L"/DEBUG /DEBUGPORT=FILE /SOS");
396
397 /* ReactOS_Ram */
398 CreateNTOSEntry(IniCache, IniSection,
399 L"ReactOS_Ram", L"\"ReactOS (RAM Disk)\"",
400 L"Windows2003", L"ramdisk(0)\\ReactOS",
401 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /RDPATH=reactos.img /RDIMAGEOFFSET=32256");
402
403 /* ReactOS_EMS */
404 CreateNTOSEntry(IniCache, IniSection,
405 L"ReactOS_EMS", L"\"ReactOS (Emergency Management Services)\"",
406 L"Windows2003", ArcPath,
407 L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS /redirect=com2 /redirectbaudrate=115200");
408 #endif
409 }
410
411 static
412 NTSTATUS
413 CreateFreeLoaderIniForReactOS(
414 PWCHAR IniPath,
415 PWCHAR ArcPath)
416 {
417 PINICACHE IniCache;
418
419 /* Initialize the INI file */
420 IniCache = IniCacheCreate();
421
422 /* Create the common FreeLdr sections */
423 CreateCommonFreeLoaderSections(IniCache);
424
425 /* Add the ReactOS entries */
426 CreateFreeLoaderReactOSEntries(IniCache, ArcPath);
427
428 /* Save the INI file */
429 IniCacheSave(IniCache, IniPath);
430 IniCacheDestroy(IniCache);
431
432 return STATUS_SUCCESS;
433 }
434
435 static
436 NTSTATUS
437 CreateFreeLoaderIniForReactOSAndBootSector(
438 PWCHAR IniPath,
439 PWCHAR ArcPath,
440 PWCHAR Section,
441 PWCHAR Description,
442 PWCHAR BootDrive,
443 PWCHAR BootPartition,
444 PWCHAR BootSector)
445 {
446 PINICACHE IniCache;
447 PINICACHESECTION IniSection;
448
449 /* Initialize the INI file */
450 IniCache = IniCacheCreate();
451
452 /* Create the common FreeLdr sections */
453 CreateCommonFreeLoaderSections(IniCache);
454
455 /* Add the ReactOS entries */
456 CreateFreeLoaderReactOSEntries(IniCache, ArcPath);
457
458 /* Get "Operating Systems" section */
459 IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
460
461 /* Insert entry into "Operating Systems" section */
462 IniCacheInsertKey(IniSection,
463 NULL,
464 INSERT_LAST,
465 Section,
466 Description);
467
468 /* Create new section */
469 IniSection = IniCacheAppendSection(IniCache, Section);
470
471 /* BootType=BootSector */
472 IniCacheInsertKey(IniSection,
473 NULL,
474 INSERT_LAST,
475 L"BootType",
476 L"BootSector");
477
478 /* BootDrive= */
479 IniCacheInsertKey(IniSection,
480 NULL,
481 INSERT_LAST,
482 L"BootDrive",
483 BootDrive);
484
485 /* BootPartition= */
486 IniCacheInsertKey(IniSection,
487 NULL,
488 INSERT_LAST,
489 L"BootPartition",
490 BootPartition);
491
492 /* BootSector= */
493 IniCacheInsertKey(IniSection,
494 NULL,
495 INSERT_LAST,
496 L"BootSectorFile",
497 BootSector);
498
499 /* Save the INI file */
500 IniCacheSave(IniCache, IniPath);
501 IniCacheDestroy(IniCache);
502
503 return STATUS_SUCCESS;
504 }
505
506 static
507 NTSTATUS
508 UpdateFreeLoaderIni(
509 PWCHAR IniPath,
510 PWCHAR ArcPath)
511 {
512 NTSTATUS Status;
513 PINICACHE IniCache;
514 PINICACHESECTION IniSection;
515 PINICACHESECTION OsIniSection;
516 WCHAR SectionName[80];
517 WCHAR OsName[80];
518 WCHAR SystemPath[200];
519 WCHAR SectionName2[200];
520 PWCHAR KeyData;
521 ULONG i,j;
522
523 Status = IniCacheLoad(&IniCache, IniPath, FALSE);
524 if (!NT_SUCCESS(Status))
525 return Status;
526
527 /* Get "Operating Systems" section */
528 IniSection = IniCacheGetSection(IniCache, L"Operating Systems");
529 if (IniSection == NULL)
530 {
531 IniCacheDestroy(IniCache);
532 return STATUS_UNSUCCESSFUL;
533 }
534
535 /* Find an existing usable or an unused section name */
536 i = 1;
537 wcscpy(SectionName, L"ReactOS");
538 wcscpy(OsName, L"\"ReactOS\"");
539 while(TRUE)
540 {
541 Status = IniCacheGetKey(IniSection, SectionName, &KeyData);
542 if (!NT_SUCCESS(Status))
543 break;
544
545 /* Get operation system section */
546 if (KeyData[0] == '"')
547 {
548 wcscpy(SectionName2, &KeyData[1]);
549 j = wcslen(SectionName2);
550 if (j > 0)
551 {
552 SectionName2[j-1] = 0;
553 }
554 }
555 else
556 {
557 wcscpy(SectionName2, KeyData);
558 }
559
560 /* Search for an existing ReactOS entry */
561 OsIniSection = IniCacheGetSection(IniCache, SectionName2);
562 if (OsIniSection != NULL)
563 {
564 BOOLEAN UseExistingEntry = TRUE;
565
566 /* Check for boot type "Windows2003" */
567 Status = IniCacheGetKey(OsIniSection, L"BootType", &KeyData);
568 if (NT_SUCCESS(Status))
569 {
570 if ((KeyData == NULL) ||
571 ( (_wcsicmp(KeyData, L"Windows2003") != 0) &&
572 (_wcsicmp(KeyData, L"\"Windows2003\"") != 0) ))
573 {
574 /* This is not a ReactOS entry */
575 UseExistingEntry = FALSE;
576 }
577 }
578 else
579 {
580 UseExistingEntry = FALSE;
581 }
582
583 if (UseExistingEntry)
584 {
585 /* BootType is Windows2003. Now check SystemPath. */
586 Status = IniCacheGetKey(OsIniSection, L"SystemPath", &KeyData);
587 if (NT_SUCCESS(Status))
588 {
589 swprintf(SystemPath, L"\"%s\"", ArcPath);
590 if ((KeyData == NULL) ||
591 ( (_wcsicmp(KeyData, ArcPath) != 0) &&
592 (_wcsicmp(KeyData, SystemPath) != 0) ))
593 {
594 /* This entry is a ReactOS entry, but the SystemRoot
595 does not match the one we are looking for. */
596 UseExistingEntry = FALSE;
597 }
598 }
599 else
600 {
601 UseExistingEntry = FALSE;
602 }
603 }
604
605 if (UseExistingEntry)
606 {
607 IniCacheDestroy(IniCache);
608 return STATUS_SUCCESS;
609 }
610 }
611
612 swprintf(SectionName, L"ReactOS_%lu", i);
613 swprintf(OsName, L"\"ReactOS %lu\"", i);
614 i++;
615 }
616
617 /* Create a new "ReactOS" entry */
618 CreateNTOSEntry(IniCache, IniSection,
619 SectionName, OsName,
620 L"Windows2003", ArcPath,
621 L"");
622
623 IniCacheSave(IniCache, IniPath);
624 IniCacheDestroy(IniCache);
625
626 return STATUS_SUCCESS;
627 }
628
629 BOOLEAN
630 IsThereAValidBootSector(PWSTR RootPath)
631 {
632 /*
633 * We first demand that the bootsector has a valid signature at its end.
634 * We then check the first 3 bytes (as a ULONG) of the bootsector for a
635 * potential "valid" instruction (the BIOS starts execution of the bootsector
636 * at its beginning). Currently this criterium is that this ULONG must be
637 * non-zero. If both these tests pass, then the bootsector is valid; otherwise
638 * it is invalid and certainly needs to be overwritten.
639 */
640 BOOLEAN IsValid = FALSE;
641 NTSTATUS Status;
642 UNICODE_STRING Name;
643 OBJECT_ATTRIBUTES ObjectAttributes;
644 IO_STATUS_BLOCK IoStatusBlock;
645 HANDLE FileHandle;
646 LARGE_INTEGER FileOffset;
647 PUCHAR BootSector;
648 ULONG Instruction;
649
650 /* Allocate buffer for bootsector */
651 BootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
652 if (BootSector == NULL)
653 return FALSE; // STATUS_INSUFFICIENT_RESOURCES;
654
655 /* Read current boot sector into buffer */
656 RtlInitUnicodeString(&Name, RootPath);
657
658 InitializeObjectAttributes(&ObjectAttributes,
659 &Name,
660 OBJ_CASE_INSENSITIVE,
661 NULL,
662 NULL);
663
664 Status = NtOpenFile(&FileHandle,
665 GENERIC_READ | SYNCHRONIZE,
666 &ObjectAttributes,
667 &IoStatusBlock,
668 0,
669 FILE_SYNCHRONOUS_IO_NONALERT);
670 if (!NT_SUCCESS(Status))
671 goto Quit;
672
673 RtlZeroMemory(BootSector, SECTORSIZE);
674
675 FileOffset.QuadPart = 0ULL;
676 Status = NtReadFile(FileHandle,
677 NULL,
678 NULL,
679 NULL,
680 &IoStatusBlock,
681 BootSector,
682 SECTORSIZE,
683 &FileOffset,
684 NULL);
685 NtClose(FileHandle);
686 if (!NT_SUCCESS(Status))
687 goto Quit;
688
689 /* Check the instruction; we use a ULONG to read three bytes */
690 Instruction = (*(PULONG)BootSector) & 0x00FFFFFF;
691 IsValid = (Instruction != 0x00000000);
692
693 /* Check the bootsector signature */
694 IsValid &= (*(PUSHORT)(BootSector + 0x1fe) == 0xaa55);
695
696 Quit:
697 /* Free the boot sector */
698 RtlFreeHeap(ProcessHeap, 0, BootSector);
699 return IsValid; // Status;
700 }
701
702 NTSTATUS
703 SaveBootSector(
704 PWSTR RootPath,
705 PWSTR DstPath,
706 ULONG Length)
707 {
708 NTSTATUS Status;
709 UNICODE_STRING Name;
710 OBJECT_ATTRIBUTES ObjectAttributes;
711 IO_STATUS_BLOCK IoStatusBlock;
712 HANDLE FileHandle;
713 LARGE_INTEGER FileOffset;
714 PUCHAR BootSector;
715
716 /* Allocate buffer for bootsector */
717 BootSector = RtlAllocateHeap(ProcessHeap, 0, Length);
718 if (BootSector == NULL)
719 return STATUS_INSUFFICIENT_RESOURCES;
720
721 /* Read current boot sector into buffer */
722 RtlInitUnicodeString(&Name, RootPath);
723
724 InitializeObjectAttributes(&ObjectAttributes,
725 &Name,
726 OBJ_CASE_INSENSITIVE,
727 NULL,
728 NULL);
729
730 Status = NtOpenFile(&FileHandle,
731 GENERIC_READ | SYNCHRONIZE,
732 &ObjectAttributes,
733 &IoStatusBlock,
734 0,
735 FILE_SYNCHRONOUS_IO_NONALERT);
736 if (!NT_SUCCESS(Status))
737 {
738 RtlFreeHeap(ProcessHeap, 0, BootSector);
739 return Status;
740 }
741
742 FileOffset.QuadPart = 0ULL;
743 Status = NtReadFile(FileHandle,
744 NULL,
745 NULL,
746 NULL,
747 &IoStatusBlock,
748 BootSector,
749 Length,
750 &FileOffset,
751 NULL);
752 NtClose(FileHandle);
753 if (!NT_SUCCESS(Status))
754 {
755 RtlFreeHeap(ProcessHeap, 0, BootSector);
756 return Status;
757 }
758
759 /* Write bootsector to DstPath */
760 RtlInitUnicodeString(&Name, DstPath);
761
762 InitializeObjectAttributes(&ObjectAttributes,
763 &Name,
764 0,
765 NULL,
766 NULL);
767
768 Status = NtCreateFile(&FileHandle,
769 GENERIC_WRITE | SYNCHRONIZE,
770 &ObjectAttributes,
771 &IoStatusBlock,
772 NULL,
773 FILE_ATTRIBUTE_NORMAL,
774 0,
775 FILE_SUPERSEDE,
776 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
777 NULL,
778 0);
779 if (!NT_SUCCESS(Status))
780 {
781 RtlFreeHeap(ProcessHeap, 0, BootSector);
782 return Status;
783 }
784
785 Status = NtWriteFile(FileHandle,
786 NULL,
787 NULL,
788 NULL,
789 &IoStatusBlock,
790 BootSector,
791 Length,
792 NULL,
793 NULL);
794 NtClose(FileHandle);
795
796 /* Free the boot sector */
797 RtlFreeHeap(ProcessHeap, 0, BootSector);
798
799 return Status;
800 }
801
802 static
803 NTSTATUS
804 InstallFat16BootCodeToFile(
805 PWSTR SrcPath,
806 PWSTR DstPath,
807 PWSTR RootPath)
808 {
809 NTSTATUS Status;
810 UNICODE_STRING Name;
811 OBJECT_ATTRIBUTES ObjectAttributes;
812 IO_STATUS_BLOCK IoStatusBlock;
813 HANDLE FileHandle;
814 LARGE_INTEGER FileOffset;
815 PFAT_BOOTSECTOR OrigBootSector;
816 PFAT_BOOTSECTOR NewBootSector;
817
818 /* Allocate buffer for original bootsector */
819 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
820 if (OrigBootSector == NULL)
821 return STATUS_INSUFFICIENT_RESOURCES;
822
823 /* Read current boot sector into buffer */
824 RtlInitUnicodeString(&Name, RootPath);
825
826 InitializeObjectAttributes(&ObjectAttributes,
827 &Name,
828 OBJ_CASE_INSENSITIVE,
829 NULL,
830 NULL);
831
832 Status = NtOpenFile(&FileHandle,
833 GENERIC_READ | SYNCHRONIZE,
834 &ObjectAttributes,
835 &IoStatusBlock,
836 0,
837 FILE_SYNCHRONOUS_IO_NONALERT);
838 if (!NT_SUCCESS(Status))
839 {
840 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
841 return Status;
842 }
843
844 FileOffset.QuadPart = 0ULL;
845 Status = NtReadFile(FileHandle,
846 NULL,
847 NULL,
848 NULL,
849 &IoStatusBlock,
850 OrigBootSector,
851 SECTORSIZE,
852 &FileOffset,
853 NULL);
854 NtClose(FileHandle);
855 if (!NT_SUCCESS(Status))
856 {
857 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
858 return Status;
859 }
860
861 /* Allocate buffer for new bootsector */
862 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
863 if (NewBootSector == NULL)
864 {
865 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
866 return STATUS_INSUFFICIENT_RESOURCES;
867 }
868
869 /* Read new bootsector from SrcPath */
870 RtlInitUnicodeString(&Name, SrcPath);
871
872 InitializeObjectAttributes(&ObjectAttributes,
873 &Name,
874 OBJ_CASE_INSENSITIVE,
875 NULL,
876 NULL);
877
878 Status = NtOpenFile(&FileHandle,
879 GENERIC_READ | SYNCHRONIZE,
880 &ObjectAttributes,
881 &IoStatusBlock,
882 0,
883 FILE_SYNCHRONOUS_IO_NONALERT);
884 if (!NT_SUCCESS(Status))
885 {
886 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
887 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
888 return Status;
889 }
890
891 FileOffset.QuadPart = 0ULL;
892 Status = NtReadFile(FileHandle,
893 NULL,
894 NULL,
895 NULL,
896 &IoStatusBlock,
897 NewBootSector,
898 SECTORSIZE,
899 &FileOffset,
900 NULL);
901 NtClose(FileHandle);
902 if (!NT_SUCCESS(Status))
903 {
904 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
905 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
906 return Status;
907 }
908
909 /* Adjust bootsector (copy a part of the FAT BPB) */
910 memcpy(&NewBootSector->OemName,
911 &OrigBootSector->OemName,
912 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
913 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
914
915 /* Free the original boot sector */
916 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
917
918 /* Write new bootsector to DstPath */
919 RtlInitUnicodeString(&Name, DstPath);
920
921 InitializeObjectAttributes(&ObjectAttributes,
922 &Name,
923 0,
924 NULL,
925 NULL);
926
927 Status = NtCreateFile(&FileHandle,
928 GENERIC_WRITE | SYNCHRONIZE,
929 &ObjectAttributes,
930 &IoStatusBlock,
931 NULL,
932 FILE_ATTRIBUTE_NORMAL,
933 0,
934 FILE_OVERWRITE_IF,
935 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
936 NULL,
937 0);
938 if (!NT_SUCCESS(Status))
939 {
940 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
941 return Status;
942 }
943
944 FileOffset.QuadPart = 0ULL;
945 Status = NtWriteFile(FileHandle,
946 NULL,
947 NULL,
948 NULL,
949 &IoStatusBlock,
950 NewBootSector,
951 SECTORSIZE,
952 NULL,
953 NULL);
954 NtClose(FileHandle);
955
956 /* Free the new boot sector */
957 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
958
959 return Status;
960 }
961
962 static
963 NTSTATUS
964 InstallFat32BootCodeToFile(
965 PWSTR SrcPath,
966 PWSTR DstPath,
967 PWSTR RootPath)
968 {
969 NTSTATUS Status;
970 UNICODE_STRING Name;
971 OBJECT_ATTRIBUTES ObjectAttributes;
972 IO_STATUS_BLOCK IoStatusBlock;
973 HANDLE FileHandle;
974 LARGE_INTEGER FileOffset;
975 PFAT32_BOOTSECTOR OrigBootSector;
976 PFAT32_BOOTSECTOR NewBootSector;
977
978 /* Allocate buffer for original bootsector */
979 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
980 if (OrigBootSector == NULL)
981 return STATUS_INSUFFICIENT_RESOURCES;
982
983 /* Read current boot sector into buffer */
984 RtlInitUnicodeString(&Name, RootPath);
985
986 InitializeObjectAttributes(&ObjectAttributes,
987 &Name,
988 OBJ_CASE_INSENSITIVE,
989 NULL,
990 NULL);
991
992 Status = NtOpenFile(&FileHandle,
993 GENERIC_READ | SYNCHRONIZE,
994 &ObjectAttributes,
995 &IoStatusBlock,
996 0,
997 FILE_SYNCHRONOUS_IO_NONALERT);
998 if (!NT_SUCCESS(Status))
999 {
1000 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1001 return Status;
1002 }
1003
1004 FileOffset.QuadPart = 0ULL;
1005 Status = NtReadFile(FileHandle,
1006 NULL,
1007 NULL,
1008 NULL,
1009 &IoStatusBlock,
1010 OrigBootSector,
1011 SECTORSIZE,
1012 NULL,
1013 NULL);
1014 NtClose(FileHandle);
1015 if (!NT_SUCCESS(Status))
1016 {
1017 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1018 return Status;
1019 }
1020
1021 /* Allocate buffer for new bootsector (2 sectors) */
1022 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1023 if (NewBootSector == NULL)
1024 {
1025 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1026 return STATUS_INSUFFICIENT_RESOURCES;
1027 }
1028
1029 /* Read new bootsector from SrcPath */
1030 RtlInitUnicodeString(&Name, SrcPath);
1031
1032 InitializeObjectAttributes(&ObjectAttributes,
1033 &Name,
1034 OBJ_CASE_INSENSITIVE,
1035 NULL,
1036 NULL);
1037
1038 Status = NtOpenFile(&FileHandle,
1039 GENERIC_READ | SYNCHRONIZE,
1040 &ObjectAttributes,
1041 &IoStatusBlock,
1042 0,
1043 FILE_SYNCHRONOUS_IO_NONALERT);
1044 if (!NT_SUCCESS(Status))
1045 {
1046 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1047 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1048 return Status;
1049 }
1050
1051 Status = NtReadFile(FileHandle,
1052 NULL,
1053 NULL,
1054 NULL,
1055 &IoStatusBlock,
1056 NewBootSector,
1057 2 * SECTORSIZE,
1058 NULL,
1059 NULL);
1060 NtClose(FileHandle);
1061 if (!NT_SUCCESS(Status))
1062 {
1063 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1064 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1065 return Status;
1066 }
1067
1068 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1069 memcpy(&NewBootSector->OemName,
1070 &OrigBootSector->OemName,
1071 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1072 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1073
1074 /* Disable the backup boot sector */
1075 NewBootSector->BackupBootSector = 0;
1076
1077 /* Free the original boot sector */
1078 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1079
1080 /* Write the first sector of the new bootcode to DstPath */
1081 RtlInitUnicodeString(&Name, DstPath);
1082
1083 InitializeObjectAttributes(&ObjectAttributes,
1084 &Name,
1085 0,
1086 NULL,
1087 NULL);
1088
1089 Status = NtCreateFile(&FileHandle,
1090 GENERIC_WRITE | SYNCHRONIZE,
1091 &ObjectAttributes,
1092 &IoStatusBlock,
1093 NULL,
1094 FILE_ATTRIBUTE_NORMAL,
1095 0,
1096 FILE_SUPERSEDE,
1097 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1098 NULL,
1099 0);
1100 if (!NT_SUCCESS(Status))
1101 {
1102 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1103 return Status;
1104 }
1105
1106 FileOffset.QuadPart = 0ULL;
1107 Status = NtWriteFile(FileHandle,
1108 NULL,
1109 NULL,
1110 NULL,
1111 &IoStatusBlock,
1112 NewBootSector,
1113 SECTORSIZE,
1114 NULL,
1115 NULL);
1116 NtClose(FileHandle);
1117 if (!NT_SUCCESS(Status))
1118 {
1119 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1120 return Status;
1121 }
1122
1123 /* Write the second sector of the new bootcode to boot disk sector 14 */
1124 RtlInitUnicodeString(&Name, RootPath);
1125
1126 InitializeObjectAttributes(&ObjectAttributes,
1127 &Name,
1128 0,
1129 NULL,
1130 NULL);
1131
1132 Status = NtOpenFile(&FileHandle,
1133 GENERIC_WRITE | SYNCHRONIZE,
1134 &ObjectAttributes,
1135 &IoStatusBlock,
1136 0,
1137 FILE_SYNCHRONOUS_IO_NONALERT);
1138 if (!NT_SUCCESS(Status))
1139 {
1140 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1141 return Status;
1142 }
1143
1144 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1145 Status = NtWriteFile(FileHandle,
1146 NULL,
1147 NULL,
1148 NULL,
1149 &IoStatusBlock,
1150 ((PUCHAR)NewBootSector + SECTORSIZE),
1151 SECTORSIZE,
1152 &FileOffset,
1153 NULL);
1154 if (!NT_SUCCESS(Status))
1155 {
1156 }
1157 NtClose(FileHandle);
1158
1159 /* Free the new boot sector */
1160 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1161
1162 return Status;
1163 }
1164
1165
1166 NTSTATUS
1167 InstallMbrBootCodeToDisk(
1168 PWSTR SrcPath,
1169 PWSTR RootPath)
1170 {
1171 NTSTATUS Status;
1172 UNICODE_STRING Name;
1173 OBJECT_ATTRIBUTES ObjectAttributes;
1174 IO_STATUS_BLOCK IoStatusBlock;
1175 HANDLE FileHandle;
1176 LARGE_INTEGER FileOffset;
1177 PPARTITION_SECTOR OrigBootSector;
1178 PPARTITION_SECTOR NewBootSector;
1179
1180 /* Allocate buffer for original bootsector */
1181 OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1182 0,
1183 sizeof(PARTITION_SECTOR));
1184 if (OrigBootSector == NULL)
1185 return STATUS_INSUFFICIENT_RESOURCES;
1186
1187 /* Read current boot sector into buffer */
1188 RtlInitUnicodeString(&Name,
1189 RootPath);
1190
1191 InitializeObjectAttributes(&ObjectAttributes,
1192 &Name,
1193 OBJ_CASE_INSENSITIVE,
1194 NULL,
1195 NULL);
1196
1197 Status = NtOpenFile(&FileHandle,
1198 GENERIC_READ | SYNCHRONIZE,
1199 &ObjectAttributes,
1200 &IoStatusBlock,
1201 0,
1202 FILE_SYNCHRONOUS_IO_NONALERT);
1203 if (!NT_SUCCESS(Status))
1204 {
1205 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1206 return Status;
1207 }
1208
1209 FileOffset.QuadPart = 0ULL;
1210 Status = NtReadFile(FileHandle,
1211 NULL,
1212 NULL,
1213 NULL,
1214 &IoStatusBlock,
1215 OrigBootSector,
1216 sizeof(PARTITION_SECTOR),
1217 &FileOffset,
1218 NULL);
1219 NtClose(FileHandle);
1220 if (!NT_SUCCESS(Status))
1221 {
1222 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1223 return Status;
1224 }
1225
1226 /* Allocate buffer for new bootsector */
1227 NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1228 0,
1229 sizeof(PARTITION_SECTOR));
1230 if (NewBootSector == NULL)
1231 {
1232 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1233 return STATUS_INSUFFICIENT_RESOURCES;
1234 }
1235
1236 /* Read new bootsector from SrcPath */
1237 RtlInitUnicodeString(&Name, SrcPath);
1238
1239 InitializeObjectAttributes(&ObjectAttributes,
1240 &Name,
1241 OBJ_CASE_INSENSITIVE,
1242 NULL,
1243 NULL);
1244
1245 Status = NtOpenFile(&FileHandle,
1246 GENERIC_READ | SYNCHRONIZE,
1247 &ObjectAttributes,
1248 &IoStatusBlock,
1249 0,
1250 FILE_SYNCHRONOUS_IO_NONALERT);
1251 if (!NT_SUCCESS(Status))
1252 {
1253 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1254 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1255 return Status;
1256 }
1257
1258 Status = NtReadFile(FileHandle,
1259 NULL,
1260 NULL,
1261 NULL,
1262 &IoStatusBlock,
1263 NewBootSector,
1264 sizeof(PARTITION_SECTOR),
1265 NULL,
1266 NULL);
1267 NtClose(FileHandle);
1268 if (!NT_SUCCESS(Status))
1269 {
1270 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1271 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1272 return Status;
1273 }
1274
1275 /* Copy partition table from old MBR to new */
1276 RtlCopyMemory(&NewBootSector->Signature,
1277 &OrigBootSector->Signature,
1278 sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */);
1279
1280 /* Free the original boot sector */
1281 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1282
1283 /* Write new bootsector to RootPath */
1284 RtlInitUnicodeString(&Name, RootPath);
1285
1286 InitializeObjectAttributes(&ObjectAttributes,
1287 &Name,
1288 0,
1289 NULL,
1290 NULL);
1291
1292 Status = NtOpenFile(&FileHandle,
1293 GENERIC_WRITE | SYNCHRONIZE,
1294 &ObjectAttributes,
1295 &IoStatusBlock,
1296 0,
1297 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1298 if (!NT_SUCCESS(Status))
1299 {
1300 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1301 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1302 return Status;
1303 }
1304
1305 FileOffset.QuadPart = 0ULL;
1306 Status = NtWriteFile(FileHandle,
1307 NULL,
1308 NULL,
1309 NULL,
1310 &IoStatusBlock,
1311 NewBootSector,
1312 sizeof(PARTITION_SECTOR),
1313 &FileOffset,
1314 NULL);
1315 NtClose(FileHandle);
1316
1317 /* Free the new boot sector */
1318 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1319
1320 return Status;
1321 }
1322
1323 static
1324 NTSTATUS
1325 InstallFat12BootCodeToFloppy(
1326 PWSTR SrcPath,
1327 PWSTR RootPath)
1328 {
1329 NTSTATUS Status;
1330 UNICODE_STRING Name;
1331 OBJECT_ATTRIBUTES ObjectAttributes;
1332 IO_STATUS_BLOCK IoStatusBlock;
1333 HANDLE FileHandle;
1334 LARGE_INTEGER FileOffset;
1335 PFAT_BOOTSECTOR OrigBootSector;
1336 PFAT_BOOTSECTOR NewBootSector;
1337
1338 /* Allocate buffer for original bootsector */
1339 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1340 if (OrigBootSector == NULL)
1341 return STATUS_INSUFFICIENT_RESOURCES;
1342
1343 /* Read current boot sector into buffer */
1344 RtlInitUnicodeString(&Name, RootPath);
1345
1346 InitializeObjectAttributes(&ObjectAttributes,
1347 &Name,
1348 OBJ_CASE_INSENSITIVE,
1349 NULL,
1350 NULL);
1351
1352 Status = NtOpenFile(&FileHandle,
1353 GENERIC_READ | SYNCHRONIZE,
1354 &ObjectAttributes,
1355 &IoStatusBlock,
1356 0,
1357 FILE_SYNCHRONOUS_IO_NONALERT);
1358 if (!NT_SUCCESS(Status))
1359 {
1360 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1361 return Status;
1362 }
1363
1364 FileOffset.QuadPart = 0ULL;
1365 Status = NtReadFile(FileHandle,
1366 NULL,
1367 NULL,
1368 NULL,
1369 &IoStatusBlock,
1370 OrigBootSector,
1371 SECTORSIZE,
1372 &FileOffset,
1373 NULL);
1374 NtClose(FileHandle);
1375 if (!NT_SUCCESS(Status))
1376 {
1377 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1378 return Status;
1379 }
1380
1381 /* Allocate buffer for new bootsector */
1382 NewBootSector = RtlAllocateHeap(ProcessHeap,
1383 0,
1384 SECTORSIZE);
1385 if (NewBootSector == NULL)
1386 {
1387 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1388 return STATUS_INSUFFICIENT_RESOURCES;
1389 }
1390
1391 /* Read new bootsector from SrcPath */
1392 RtlInitUnicodeString(&Name, SrcPath);
1393
1394 InitializeObjectAttributes(&ObjectAttributes,
1395 &Name,
1396 OBJ_CASE_INSENSITIVE,
1397 NULL,
1398 NULL);
1399
1400 Status = NtOpenFile(&FileHandle,
1401 GENERIC_READ | SYNCHRONIZE,
1402 &ObjectAttributes,
1403 &IoStatusBlock,
1404 0,
1405 FILE_SYNCHRONOUS_IO_NONALERT);
1406 if (!NT_SUCCESS(Status))
1407 {
1408 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1409 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1410 return Status;
1411 }
1412
1413 Status = NtReadFile(FileHandle,
1414 NULL,
1415 NULL,
1416 NULL,
1417 &IoStatusBlock,
1418 NewBootSector,
1419 SECTORSIZE,
1420 NULL,
1421 NULL);
1422 NtClose(FileHandle);
1423 if (!NT_SUCCESS(Status))
1424 {
1425 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1426 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1427 return Status;
1428 }
1429
1430 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1431 memcpy(&NewBootSector->OemName,
1432 &OrigBootSector->OemName,
1433 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1434 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1435
1436 /* Free the original boot sector */
1437 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1438
1439 /* Write new bootsector to RootPath */
1440 RtlInitUnicodeString(&Name, RootPath);
1441
1442 InitializeObjectAttributes(&ObjectAttributes,
1443 &Name,
1444 0,
1445 NULL,
1446 NULL);
1447
1448 Status = NtOpenFile(&FileHandle,
1449 GENERIC_WRITE | SYNCHRONIZE,
1450 &ObjectAttributes,
1451 &IoStatusBlock,
1452 0,
1453 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1454 if (!NT_SUCCESS(Status))
1455 {
1456 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1457 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1458 return Status;
1459 }
1460
1461 FileOffset.QuadPart = 0ULL;
1462 Status = NtWriteFile(FileHandle,
1463 NULL,
1464 NULL,
1465 NULL,
1466 &IoStatusBlock,
1467 NewBootSector,
1468 SECTORSIZE,
1469 &FileOffset,
1470 NULL);
1471 NtClose(FileHandle);
1472
1473 /* Free the new boot sector */
1474 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1475
1476 return Status;
1477 }
1478
1479 static
1480 NTSTATUS
1481 InstallFat16BootCodeToDisk(
1482 PWSTR SrcPath,
1483 PWSTR RootPath)
1484 {
1485 NTSTATUS Status;
1486 UNICODE_STRING Name;
1487 OBJECT_ATTRIBUTES ObjectAttributes;
1488 IO_STATUS_BLOCK IoStatusBlock;
1489 HANDLE FileHandle;
1490 LARGE_INTEGER FileOffset;
1491 PFAT_BOOTSECTOR OrigBootSector;
1492 PFAT_BOOTSECTOR NewBootSector;
1493
1494 /* Allocate buffer for original bootsector */
1495 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1496 if (OrigBootSector == NULL)
1497 return STATUS_INSUFFICIENT_RESOURCES;
1498
1499 /* Read current boot sector into buffer */
1500 RtlInitUnicodeString(&Name, RootPath);
1501
1502 InitializeObjectAttributes(&ObjectAttributes,
1503 &Name,
1504 OBJ_CASE_INSENSITIVE,
1505 NULL,
1506 NULL);
1507
1508 Status = NtOpenFile(&FileHandle,
1509 GENERIC_READ | SYNCHRONIZE,
1510 &ObjectAttributes,
1511 &IoStatusBlock,
1512 0,
1513 FILE_SYNCHRONOUS_IO_NONALERT);
1514 if (!NT_SUCCESS(Status))
1515 {
1516 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1517 return Status;
1518 }
1519
1520 FileOffset.QuadPart = 0ULL;
1521 Status = NtReadFile(FileHandle,
1522 NULL,
1523 NULL,
1524 NULL,
1525 &IoStatusBlock,
1526 OrigBootSector,
1527 SECTORSIZE,
1528 &FileOffset,
1529 NULL);
1530 NtClose(FileHandle);
1531 if (!NT_SUCCESS(Status))
1532 {
1533 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1534 return Status;
1535 }
1536
1537 /* Allocate buffer for new bootsector */
1538 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1539 if (NewBootSector == NULL)
1540 {
1541 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1542 return STATUS_INSUFFICIENT_RESOURCES;
1543 }
1544
1545 /* Read new bootsector from SrcPath */
1546 RtlInitUnicodeString(&Name, SrcPath);
1547
1548 InitializeObjectAttributes(&ObjectAttributes,
1549 &Name,
1550 OBJ_CASE_INSENSITIVE,
1551 NULL,
1552 NULL);
1553
1554 Status = NtOpenFile(&FileHandle,
1555 GENERIC_READ | SYNCHRONIZE,
1556 &ObjectAttributes,
1557 &IoStatusBlock,
1558 0,
1559 FILE_SYNCHRONOUS_IO_NONALERT);
1560 if (!NT_SUCCESS(Status))
1561 {
1562 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1563 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1564 return Status;
1565 }
1566
1567 Status = NtReadFile(FileHandle,
1568 NULL,
1569 NULL,
1570 NULL,
1571 &IoStatusBlock,
1572 NewBootSector,
1573 SECTORSIZE,
1574 NULL,
1575 NULL);
1576 NtClose(FileHandle);
1577 if (!NT_SUCCESS(Status))
1578 {
1579 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1580 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1581 return Status;
1582 }
1583
1584 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1585 memcpy(&NewBootSector->OemName,
1586 &OrigBootSector->OemName,
1587 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1588 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1589
1590 /* Free the original boot sector */
1591 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1592
1593 /* Write new bootsector to RootPath */
1594 RtlInitUnicodeString(&Name, RootPath);
1595
1596 InitializeObjectAttributes(&ObjectAttributes,
1597 &Name,
1598 0,
1599 NULL,
1600 NULL);
1601
1602 Status = NtOpenFile(&FileHandle,
1603 GENERIC_WRITE | SYNCHRONIZE,
1604 &ObjectAttributes,
1605 &IoStatusBlock,
1606 0,
1607 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1608 if (!NT_SUCCESS(Status))
1609 {
1610 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1611 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1612 return Status;
1613 }
1614
1615 FileOffset.QuadPart = 0ULL;
1616 Status = NtWriteFile(FileHandle,
1617 NULL,
1618 NULL,
1619 NULL,
1620 &IoStatusBlock,
1621 NewBootSector,
1622 SECTORSIZE,
1623 &FileOffset,
1624 NULL);
1625 NtClose(FileHandle);
1626
1627 /* Free the new boot sector */
1628 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1629
1630 return Status;
1631 }
1632
1633 static
1634 NTSTATUS
1635 InstallFat32BootCodeToDisk(
1636 PWSTR SrcPath,
1637 PWSTR RootPath)
1638 {
1639 NTSTATUS Status;
1640 UNICODE_STRING Name;
1641 OBJECT_ATTRIBUTES ObjectAttributes;
1642 IO_STATUS_BLOCK IoStatusBlock;
1643 HANDLE FileHandle;
1644 LARGE_INTEGER FileOffset;
1645 PFAT32_BOOTSECTOR OrigBootSector;
1646 PFAT32_BOOTSECTOR NewBootSector;
1647 USHORT BackupBootSector;
1648
1649 /* Allocate buffer for original bootsector */
1650 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1651 if (OrigBootSector == NULL)
1652 return STATUS_INSUFFICIENT_RESOURCES;
1653
1654 /* Read current boot sector into buffer */
1655 RtlInitUnicodeString(&Name, RootPath);
1656
1657 InitializeObjectAttributes(&ObjectAttributes,
1658 &Name,
1659 OBJ_CASE_INSENSITIVE,
1660 NULL,
1661 NULL);
1662
1663 Status = NtOpenFile(&FileHandle,
1664 GENERIC_READ | SYNCHRONIZE,
1665 &ObjectAttributes,
1666 &IoStatusBlock,
1667 0,
1668 FILE_SYNCHRONOUS_IO_NONALERT);
1669 if (!NT_SUCCESS(Status))
1670 {
1671 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1672 return Status;
1673 }
1674
1675 FileOffset.QuadPart = 0ULL;
1676 Status = NtReadFile(FileHandle,
1677 NULL,
1678 NULL,
1679 NULL,
1680 &IoStatusBlock,
1681 OrigBootSector,
1682 SECTORSIZE,
1683 &FileOffset,
1684 NULL);
1685 NtClose(FileHandle);
1686 if (!NT_SUCCESS(Status))
1687 {
1688 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1689 return Status;
1690 }
1691
1692
1693 /* Allocate buffer for new bootsector (2 sectors) */
1694 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1695 if (NewBootSector == NULL)
1696 {
1697 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1698 return STATUS_INSUFFICIENT_RESOURCES;
1699 }
1700
1701 /* Read new bootsector from SrcPath */
1702 RtlInitUnicodeString(&Name, SrcPath);
1703
1704 InitializeObjectAttributes(&ObjectAttributes,
1705 &Name,
1706 OBJ_CASE_INSENSITIVE,
1707 NULL,
1708 NULL);
1709
1710 Status = NtOpenFile(&FileHandle,
1711 GENERIC_READ | SYNCHRONIZE,
1712 &ObjectAttributes,
1713 &IoStatusBlock,
1714 0,
1715 FILE_SYNCHRONOUS_IO_NONALERT);
1716 if (!NT_SUCCESS(Status))
1717 {
1718 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1719 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1720 return Status;
1721 }
1722
1723 Status = NtReadFile(FileHandle,
1724 NULL,
1725 NULL,
1726 NULL,
1727 &IoStatusBlock,
1728 NewBootSector,
1729 2 * SECTORSIZE,
1730 NULL,
1731 NULL);
1732 NtClose(FileHandle);
1733 if (!NT_SUCCESS(Status))
1734 {
1735 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1736 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1737 return Status;
1738 }
1739
1740 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1741 memcpy(&NewBootSector->OemName,
1742 &OrigBootSector->OemName,
1743 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1744 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1745
1746 /* Get the location of the backup boot sector */
1747 BackupBootSector = OrigBootSector->BackupBootSector;
1748
1749 /* Free the original boot sector */
1750 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1751
1752 /* Write the first sector of the new bootcode to DstPath */
1753 RtlInitUnicodeString(&Name, RootPath);
1754
1755 InitializeObjectAttributes(&ObjectAttributes,
1756 &Name,
1757 0,
1758 NULL,
1759 NULL);
1760
1761 Status = NtOpenFile(&FileHandle,
1762 GENERIC_WRITE | SYNCHRONIZE,
1763 &ObjectAttributes,
1764 &IoStatusBlock,
1765 0,
1766 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1767 if (!NT_SUCCESS(Status))
1768 {
1769 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1770 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1771 return Status;
1772 }
1773
1774 /* Write sector 0 */
1775 FileOffset.QuadPart = 0ULL;
1776 Status = NtWriteFile(FileHandle,
1777 NULL,
1778 NULL,
1779 NULL,
1780 &IoStatusBlock,
1781 NewBootSector,
1782 SECTORSIZE,
1783 &FileOffset,
1784 NULL);
1785 if (!NT_SUCCESS(Status))
1786 {
1787 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1788 NtClose(FileHandle);
1789 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1790 return Status;
1791 }
1792
1793 /* Write backup boot sector */
1794 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1795 {
1796 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1797 Status = NtWriteFile(FileHandle,
1798 NULL,
1799 NULL,
1800 NULL,
1801 &IoStatusBlock,
1802 NewBootSector,
1803 SECTORSIZE,
1804 &FileOffset,
1805 NULL);
1806 if (!NT_SUCCESS(Status))
1807 {
1808 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1809 NtClose(FileHandle);
1810 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1811 return Status;
1812 }
1813 }
1814
1815 /* Write sector 14 */
1816 FileOffset.QuadPart = 14 * SECTORSIZE;
1817 Status = NtWriteFile(FileHandle,
1818 NULL,
1819 NULL,
1820 NULL,
1821 &IoStatusBlock,
1822 ((PUCHAR)NewBootSector + SECTORSIZE),
1823 SECTORSIZE,
1824 &FileOffset,
1825 NULL);
1826 if (!NT_SUCCESS(Status))
1827 {
1828 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1829 }
1830 NtClose(FileHandle);
1831
1832 /* Free the new boot sector */
1833 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1834
1835 return Status;
1836 }
1837
1838 static
1839 NTSTATUS
1840 InstallExt2BootCodeToDisk(
1841 PWSTR SrcPath,
1842 PWSTR RootPath)
1843 {
1844 NTSTATUS Status;
1845 UNICODE_STRING Name;
1846 OBJECT_ATTRIBUTES ObjectAttributes;
1847 IO_STATUS_BLOCK IoStatusBlock;
1848 HANDLE FileHandle;
1849 LARGE_INTEGER FileOffset;
1850 // PEXT2_BOOTSECTOR OrigBootSector;
1851 PEXT2_BOOTSECTOR NewBootSector;
1852 // USHORT BackupBootSector;
1853
1854 #if 0
1855 /* Allocate buffer for original bootsector */
1856 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1857 if (OrigBootSector == NULL)
1858 return STATUS_INSUFFICIENT_RESOURCES;
1859
1860 /* Read current boot sector into buffer */
1861 RtlInitUnicodeString(&Name, RootPath);
1862
1863 InitializeObjectAttributes(&ObjectAttributes,
1864 &Name,
1865 OBJ_CASE_INSENSITIVE,
1866 NULL,
1867 NULL);
1868
1869 Status = NtOpenFile(&FileHandle,
1870 GENERIC_READ | SYNCHRONIZE,
1871 &ObjectAttributes,
1872 &IoStatusBlock,
1873 0,
1874 FILE_SYNCHRONOUS_IO_NONALERT);
1875 if (!NT_SUCCESS(Status))
1876 {
1877 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1878 return Status;
1879 }
1880
1881 FileOffset.QuadPart = 0ULL;
1882 Status = NtReadFile(FileHandle,
1883 NULL,
1884 NULL,
1885 NULL,
1886 &IoStatusBlock,
1887 OrigBootSector,
1888 SECTORSIZE,
1889 &FileOffset,
1890 NULL);
1891 NtClose(FileHandle);
1892 if (!NT_SUCCESS(Status))
1893 {
1894 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1895 return Status;
1896 }
1897 #endif
1898
1899 /* Allocate buffer for new bootsector */
1900 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(EXT2_BOOTSECTOR));
1901 if (NewBootSector == NULL)
1902 {
1903 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1904 return STATUS_INSUFFICIENT_RESOURCES;
1905 }
1906
1907 /* Read new bootsector from SrcPath */
1908 RtlInitUnicodeString(&Name, SrcPath);
1909
1910 InitializeObjectAttributes(&ObjectAttributes,
1911 &Name,
1912 OBJ_CASE_INSENSITIVE,
1913 NULL,
1914 NULL);
1915
1916 Status = NtOpenFile(&FileHandle,
1917 GENERIC_READ | SYNCHRONIZE,
1918 &ObjectAttributes,
1919 &IoStatusBlock,
1920 0,
1921 FILE_SYNCHRONOUS_IO_NONALERT);
1922 if (!NT_SUCCESS(Status))
1923 {
1924 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1925 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1926 return Status;
1927 }
1928
1929 Status = NtReadFile(FileHandle,
1930 NULL,
1931 NULL,
1932 NULL,
1933 &IoStatusBlock,
1934 NewBootSector,
1935 sizeof(EXT2_BOOTSECTOR),
1936 NULL,
1937 NULL);
1938 NtClose(FileHandle);
1939 if (!NT_SUCCESS(Status))
1940 {
1941 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1942 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1943 return Status;
1944 }
1945
1946 #if 0
1947 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1948 memcpy(&NewBootSector->OemName,
1949 &OrigBootSector->OemName,
1950 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1951 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1952
1953 NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
1954
1955 /* Get the location of the backup boot sector */
1956 BackupBootSector = OrigBootSector->BackupBootSector;
1957
1958 /* Free the original boot sector */
1959 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1960 #endif
1961
1962 /* Write new bootsector to RootPath */
1963 RtlInitUnicodeString(&Name, RootPath);
1964
1965 InitializeObjectAttributes(&ObjectAttributes,
1966 &Name,
1967 0,
1968 NULL,
1969 NULL);
1970
1971 Status = NtOpenFile(&FileHandle,
1972 GENERIC_WRITE | SYNCHRONIZE,
1973 &ObjectAttributes,
1974 &IoStatusBlock,
1975 0,
1976 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1977 if (!NT_SUCCESS(Status))
1978 {
1979 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1980 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1981 return Status;
1982 }
1983
1984 /* Write sector 0 */
1985 FileOffset.QuadPart = 0ULL;
1986 Status = NtWriteFile(FileHandle,
1987 NULL,
1988 NULL,
1989 NULL,
1990 &IoStatusBlock,
1991 NewBootSector,
1992 sizeof(EXT2_BOOTSECTOR),
1993 &FileOffset,
1994 NULL);
1995 #if 0
1996 if (!NT_SUCCESS(Status))
1997 {
1998 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1999 NtClose(FileHandle);
2000 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2001 return Status;
2002 }
2003
2004 /* Write backup boot sector */
2005 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
2006 {
2007 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
2008 Status = NtWriteFile(FileHandle,
2009 NULL,
2010 NULL,
2011 NULL,
2012 &IoStatusBlock,
2013 NewBootSector,
2014 SECTORSIZE,
2015 &FileOffset,
2016 NULL);
2017 if (!NT_SUCCESS(Status))
2018 {
2019 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2020 NtClose(FileHandle);
2021 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2022 return Status;
2023 }
2024 }
2025
2026 /* Write sector 14 */
2027 FileOffset.QuadPart = 14 * SECTORSIZE;
2028 Status = NtWriteFile(FileHandle,
2029 NULL,
2030 NULL,
2031 NULL,
2032 &IoStatusBlock,
2033 ((PUCHAR)NewBootSector + SECTORSIZE),
2034 SECTORSIZE,
2035 &FileOffset,
2036 NULL);
2037 if (!NT_SUCCESS(Status))
2038 {
2039 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2040 }
2041 #endif
2042 NtClose(FileHandle);
2043
2044 /* Free the new boot sector */
2045 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2046
2047 return Status;
2048 }
2049
2050 static
2051 NTSTATUS
2052 UnprotectBootIni(
2053 PWSTR FileName,
2054 PULONG Attributes)
2055 {
2056 NTSTATUS Status;
2057 UNICODE_STRING Name;
2058 OBJECT_ATTRIBUTES ObjectAttributes;
2059 IO_STATUS_BLOCK IoStatusBlock;
2060 FILE_BASIC_INFORMATION FileInfo;
2061 HANDLE FileHandle;
2062
2063 RtlInitUnicodeString(&Name, FileName);
2064
2065 InitializeObjectAttributes(&ObjectAttributes,
2066 &Name,
2067 OBJ_CASE_INSENSITIVE,
2068 NULL,
2069 NULL);
2070
2071 Status = NtOpenFile(&FileHandle,
2072 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2073 &ObjectAttributes,
2074 &IoStatusBlock,
2075 0,
2076 FILE_SYNCHRONOUS_IO_NONALERT);
2077 if (Status == STATUS_NO_SUCH_FILE)
2078 {
2079 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2080 *Attributes = 0;
2081 return STATUS_SUCCESS;
2082 }
2083 if (!NT_SUCCESS(Status))
2084 {
2085 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2086 return Status;
2087 }
2088
2089 Status = NtQueryInformationFile(FileHandle,
2090 &IoStatusBlock,
2091 &FileInfo,
2092 sizeof(FILE_BASIC_INFORMATION),
2093 FileBasicInformation);
2094 if (!NT_SUCCESS(Status))
2095 {
2096 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2097 NtClose(FileHandle);
2098 return Status;
2099 }
2100
2101 *Attributes = FileInfo.FileAttributes;
2102
2103 /* Delete attributes SYSTEM, HIDDEN and READONLY */
2104 FileInfo.FileAttributes = FileInfo.FileAttributes &
2105 ~(FILE_ATTRIBUTE_SYSTEM |
2106 FILE_ATTRIBUTE_HIDDEN |
2107 FILE_ATTRIBUTE_READONLY);
2108
2109 Status = NtSetInformationFile(FileHandle,
2110 &IoStatusBlock,
2111 &FileInfo,
2112 sizeof(FILE_BASIC_INFORMATION),
2113 FileBasicInformation);
2114 if (!NT_SUCCESS(Status))
2115 {
2116 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2117 }
2118
2119 NtClose(FileHandle);
2120 return Status;
2121 }
2122
2123 static
2124 NTSTATUS
2125 ProtectBootIni(
2126 PWSTR FileName,
2127 ULONG Attributes)
2128 {
2129 NTSTATUS Status;
2130 UNICODE_STRING Name;
2131 OBJECT_ATTRIBUTES ObjectAttributes;
2132 IO_STATUS_BLOCK IoStatusBlock;
2133 FILE_BASIC_INFORMATION FileInfo;
2134 HANDLE FileHandle;
2135
2136 RtlInitUnicodeString(&Name, FileName);
2137
2138 InitializeObjectAttributes(&ObjectAttributes,
2139 &Name,
2140 OBJ_CASE_INSENSITIVE,
2141 NULL,
2142 NULL);
2143
2144 Status = NtOpenFile(&FileHandle,
2145 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2146 &ObjectAttributes,
2147 &IoStatusBlock,
2148 0,
2149 FILE_SYNCHRONOUS_IO_NONALERT);
2150 if (!NT_SUCCESS(Status))
2151 {
2152 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2153 return Status;
2154 }
2155
2156 Status = NtQueryInformationFile(FileHandle,
2157 &IoStatusBlock,
2158 &FileInfo,
2159 sizeof(FILE_BASIC_INFORMATION),
2160 FileBasicInformation);
2161 if (!NT_SUCCESS(Status))
2162 {
2163 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2164 NtClose(FileHandle);
2165 return Status;
2166 }
2167
2168 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
2169
2170 Status = NtSetInformationFile(FileHandle,
2171 &IoStatusBlock,
2172 &FileInfo,
2173 sizeof(FILE_BASIC_INFORMATION),
2174 FileBasicInformation);
2175 if (!NT_SUCCESS(Status))
2176 {
2177 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2178 }
2179
2180 NtClose(FileHandle);
2181 return Status;
2182 }
2183
2184 static
2185 NTSTATUS
2186 UpdateBootIni(
2187 PWSTR BootIniPath,
2188 PWSTR EntryName,
2189 PWSTR EntryValue)
2190 {
2191 NTSTATUS Status;
2192 PINICACHE Cache = NULL;
2193 PINICACHESECTION Section = NULL;
2194 ULONG FileAttribute;
2195 PWCHAR OldValue = NULL;
2196
2197 Status = IniCacheLoad(&Cache, BootIniPath, FALSE);
2198 if (!NT_SUCCESS(Status))
2199 {
2200 return Status;
2201 }
2202
2203 Section = IniCacheGetSection(Cache,
2204 L"operating systems");
2205 if (Section == NULL)
2206 {
2207 IniCacheDestroy(Cache);
2208 return STATUS_UNSUCCESSFUL;
2209 }
2210
2211 /* Check - maybe record already exists */
2212 Status = IniCacheGetKey(Section, EntryName, &OldValue);
2213
2214 /* If either key was not found, or contains something else - add new one */
2215 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
2216 {
2217 IniCacheInsertKey(Section,
2218 NULL,
2219 INSERT_LAST,
2220 EntryName,
2221 EntryValue);
2222 }
2223
2224 Status = UnprotectBootIni(BootIniPath,
2225 &FileAttribute);
2226 if (!NT_SUCCESS(Status))
2227 {
2228 IniCacheDestroy(Cache);
2229 return Status;
2230 }
2231
2232 Status = IniCacheSave(Cache, BootIniPath);
2233 if (!NT_SUCCESS(Status))
2234 {
2235 IniCacheDestroy(Cache);
2236 return Status;
2237 }
2238
2239 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
2240 Status = ProtectBootIni(BootIniPath, FileAttribute);
2241
2242 IniCacheDestroy(Cache);
2243
2244 return Status;
2245 }
2246
2247 static
2248 NTSTATUS
2249 InstallFatBootcodeToPartition(
2250 PUNICODE_STRING SystemRootPath,
2251 PUNICODE_STRING SourceRootPath,
2252 PUNICODE_STRING DestinationArcPath,
2253 UCHAR PartitionType)
2254 {
2255 #ifdef __REACTOS__
2256 NTSTATUS Status;
2257 BOOLEAN DoesFreeLdrExist;
2258 WCHAR SrcPath[MAX_PATH];
2259 WCHAR DstPath[MAX_PATH];
2260
2261 /* FAT or FAT32 partition */
2262 DPRINT("System path: '%wZ'\n", SystemRootPath);
2263
2264 /* Copy FreeLoader to the system partition */
2265 wcscpy(SrcPath, SourceRootPath->Buffer);
2266 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2267 wcscpy(DstPath, SystemRootPath->Buffer);
2268 wcscat(DstPath, L"\\freeldr.sys");
2269
2270 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2271 Status = SetupCopyFile(SrcPath, DstPath);
2272 if (!NT_SUCCESS(Status))
2273 {
2274 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2275 return Status;
2276 }
2277
2278 /* Prepare for possibly copying 'freeldr.ini' */
2279 wcscpy(DstPath, SystemRootPath->Buffer);
2280 wcscat(DstPath, L"\\freeldr.ini");
2281
2282 DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
2283 if (DoesFreeLdrExist)
2284 {
2285 /* Update existing 'freeldr.ini' */
2286 DPRINT1("Update existing 'freeldr.ini'\n");
2287
2288 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2289 if (!NT_SUCCESS(Status))
2290 {
2291 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2292 return Status;
2293 }
2294 }
2295
2296 /* Check for NT and other bootloaders */
2297
2298 // FIXME: Check for Vista+ bootloader!
2299 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
2300 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
2301 {
2302 /* Search root directory for 'ntldr' and 'boot.ini' */
2303 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2304
2305 /* Create or update 'freeldr.ini' */
2306 if (DoesFreeLdrExist == FALSE)
2307 {
2308 /* Create new 'freeldr.ini' */
2309 DPRINT1("Create new 'freeldr.ini'\n");
2310 // wcscpy(DstPath, SystemRootPath->Buffer);
2311 // wcscat(DstPath, L"\\freeldr.ini");
2312
2313 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2314 if (!NT_SUCCESS(Status))
2315 {
2316 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2317 return Status;
2318 }
2319
2320 /* Install new bootcode into a file */
2321 wcscpy(DstPath, SystemRootPath->Buffer);
2322 wcscat(DstPath, L"\\bootsect.ros");
2323
2324 if (PartitionType == PARTITION_FAT32 ||
2325 PartitionType == PARTITION_FAT32_XINT13)
2326 {
2327 /* Install FAT32 bootcode */
2328 wcscpy(SrcPath, SourceRootPath->Buffer);
2329 wcscat(SrcPath, L"\\loader\\fat32.bin");
2330
2331 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2332 Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
2333 SystemRootPath->Buffer);
2334 if (!NT_SUCCESS(Status))
2335 {
2336 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2337 return Status;
2338 }
2339 }
2340 else
2341 {
2342 /* Install FAT16 bootcode */
2343 wcscpy(SrcPath, SourceRootPath->Buffer);
2344 wcscat(SrcPath, L"\\loader\\fat.bin");
2345
2346 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2347 Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
2348 SystemRootPath->Buffer);
2349 if (!NT_SUCCESS(Status))
2350 {
2351 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2352 return Status;
2353 }
2354 }
2355 }
2356
2357 /* Update 'boot.ini' */
2358 wcscpy(DstPath, SystemRootPath->Buffer);
2359 wcscat(DstPath, L"\\boot.ini");
2360
2361 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2362 Status = UpdateBootIni(DstPath,
2363 L"C:\\bootsect.ros",
2364 L"\"ReactOS\"");
2365 if (!NT_SUCCESS(Status))
2366 {
2367 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2368 return Status;
2369 }
2370 }
2371 else
2372 {
2373 /* Non-NT bootloaders: install our own bootloader */
2374
2375 PWCHAR Section;
2376 PWCHAR Description;
2377 PWCHAR BootDrive;
2378 PWCHAR BootPartition;
2379 PWCHAR BootSector;
2380 PWCHAR BootSectorFileName;
2381
2382 if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
2383 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
2384 {
2385 /* Search for root directory for 'io.sys' and 'msdos.sys' */
2386 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2387
2388 Section = L"DOS";
2389 Description = L"\"DOS/Windows\"";
2390 BootDrive = L"hd0";
2391 BootPartition = L"1";
2392 BootSector = L"BOOTSECT.DOS";
2393
2394 BootSectorFileName = L"\\bootsect.dos";
2395 }
2396 else
2397 if (DoesFileExist(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
2398 {
2399 /* Search for root directory for 'kernel.sys' */
2400 DPRINT1("Found FreeDOS boot loader\n");
2401
2402 Section = L"DOS";
2403 Description = L"\"FreeDOS\"";
2404 BootDrive = L"hd0";
2405 BootPartition = L"1";
2406 BootSector = L"BOOTSECT.DOS";
2407
2408 BootSectorFileName = L"\\bootsect.dos";
2409 }
2410 else
2411 {
2412 /* No or unknown boot loader */
2413 DPRINT1("No or unknown boot loader found\n");
2414
2415 Section = L"Unknown";
2416 Description = L"\"Unknown Operating System\"";
2417 BootDrive = L"hd0";
2418 BootPartition = L"1";
2419 BootSector = L"BOOTSECT.OLD";
2420
2421 BootSectorFileName = L"\\bootsect.old";
2422 }
2423
2424 /* Create or update 'freeldr.ini' */
2425 if (DoesFreeLdrExist == FALSE)
2426 {
2427 /* Create new 'freeldr.ini' */
2428 DPRINT1("Create new 'freeldr.ini'\n");
2429 // wcscpy(DstPath, SystemRootPath->Buffer);
2430 // wcscat(DstPath, L"\\freeldr.ini");
2431
2432 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2433 {
2434 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2435 DstPath, DestinationArcPath->Buffer,
2436 Section, Description,
2437 BootDrive, BootPartition, BootSector);
2438 if (!NT_SUCCESS(Status))
2439 {
2440 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2441 return Status;
2442 }
2443
2444 /* Save current bootsector */
2445 wcscpy(DstPath, SystemRootPath->Buffer);
2446 wcscat(DstPath, BootSectorFileName);
2447
2448 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2449 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
2450 if (!NT_SUCCESS(Status))
2451 {
2452 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2453 return Status;
2454 }
2455 }
2456 else
2457 {
2458 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2459 if (!NT_SUCCESS(Status))
2460 {
2461 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2462 return Status;
2463 }
2464 }
2465
2466 /* Install new bootsector on the disk */
2467 if (PartitionType == PARTITION_FAT32 ||
2468 PartitionType == PARTITION_FAT32_XINT13)
2469 {
2470 /* Install FAT32 bootcode */
2471 wcscpy(SrcPath, SourceRootPath->Buffer);
2472 wcscat(SrcPath, L"\\loader\\fat32.bin");
2473
2474 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2475 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2476 if (!NT_SUCCESS(Status))
2477 {
2478 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2479 return Status;
2480 }
2481 }
2482 else
2483 {
2484 /* Install FAT16 bootcode */
2485 wcscpy(SrcPath, SourceRootPath->Buffer);
2486 wcscat(SrcPath, L"\\loader\\fat.bin");
2487
2488 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2489 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2490 if (!NT_SUCCESS(Status))
2491 {
2492 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2493 return Status;
2494 }
2495 }
2496 }
2497 }
2498
2499 return STATUS_SUCCESS;
2500 #else
2501 return STATUS_NOT_IMPLEMENTED;
2502 #endif
2503 }
2504
2505 static
2506 NTSTATUS
2507 InstallExt2BootcodeToPartition(
2508 PUNICODE_STRING SystemRootPath,
2509 PUNICODE_STRING SourceRootPath,
2510 PUNICODE_STRING DestinationArcPath,
2511 UCHAR PartitionType)
2512 {
2513 #ifdef __REACTOS__
2514 NTSTATUS Status;
2515 BOOLEAN DoesFreeLdrExist;
2516 WCHAR SrcPath[MAX_PATH];
2517 WCHAR DstPath[MAX_PATH];
2518
2519 /* EXT2 partition */
2520 DPRINT("System path: '%wZ'\n", SystemRootPath);
2521
2522 /* Copy FreeLoader to the system partition */
2523 wcscpy(SrcPath, SourceRootPath->Buffer);
2524 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2525 wcscpy(DstPath, SystemRootPath->Buffer);
2526 wcscat(DstPath, L"\\freeldr.sys");
2527
2528 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2529 Status = SetupCopyFile(SrcPath, DstPath);
2530 if (!NT_SUCCESS(Status))
2531 {
2532 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2533 return Status;
2534 }
2535
2536 /* Prepare for possibly copying 'freeldr.ini' */
2537 wcscpy(DstPath, SystemRootPath->Buffer);
2538 wcscat(DstPath, L"\\freeldr.ini");
2539
2540 DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
2541 if (DoesFreeLdrExist)
2542 {
2543 /* Update existing 'freeldr.ini' */
2544 DPRINT1("Update existing 'freeldr.ini'\n");
2545
2546 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2547 if (!NT_SUCCESS(Status))
2548 {
2549 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2550 return Status;
2551 }
2552 }
2553
2554 /* Check for *nix bootloaders */
2555
2556 /* Create or update 'freeldr.ini' */
2557 if (DoesFreeLdrExist == FALSE)
2558 {
2559 /* Create new 'freeldr.ini' */
2560 DPRINT1("Create new 'freeldr.ini'\n");
2561 wcscpy(DstPath, SystemRootPath->Buffer);
2562 wcscat(DstPath, L"\\freeldr.ini");
2563
2564 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2565 DPRINT1("*nix or unknown boot loader found\n");
2566
2567 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2568 {
2569 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2570 DstPath, DestinationArcPath->Buffer,
2571 L"Linux", L"\"Linux\"",
2572 L"hd0", L"1", L"BOOTSECT.OLD");
2573 if (!NT_SUCCESS(Status))
2574 {
2575 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2576 return Status;
2577 }
2578
2579 /* Save current bootsector */
2580 wcscpy(DstPath, SystemRootPath->Buffer);
2581 wcscat(DstPath, L"\\bootsect.old");
2582
2583 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2584 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(EXT2_BOOTSECTOR));
2585 if (!NT_SUCCESS(Status))
2586 {
2587 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2588 return Status;
2589 }
2590 }
2591 else
2592 {
2593 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2594 if (!NT_SUCCESS(Status))
2595 {
2596 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2597 return Status;
2598 }
2599 }
2600
2601 /* Install new bootsector on the disk */
2602 // if (PartitionType == PARTITION_EXT2)
2603 {
2604 /* Install EXT2 bootcode */
2605 wcscpy(SrcPath, SourceRootPath->Buffer);
2606 wcscat(SrcPath, L"\\loader\\ext2.bin");
2607
2608 DPRINT1("Install EXT2 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2609 Status = InstallExt2BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2610 if (!NT_SUCCESS(Status))
2611 {
2612 DPRINT1("InstallExt2BootCodeToDisk() failed (Status %lx)\n", Status);
2613 return Status;
2614 }
2615 }
2616 }
2617
2618 return STATUS_SUCCESS;
2619 #else
2620 return STATUS_NOT_IMPLEMENTED;
2621 #endif
2622 }
2623
2624
2625 NTSTATUS
2626 InstallVBRToPartition(
2627 PUNICODE_STRING SystemRootPath,
2628 PUNICODE_STRING SourceRootPath,
2629 PUNICODE_STRING DestinationArcPath,
2630 UCHAR PartitionType)
2631 {
2632 switch (PartitionType)
2633 {
2634 case PARTITION_FAT_12:
2635 case PARTITION_FAT_16:
2636 case PARTITION_HUGE:
2637 case PARTITION_XINT13:
2638 case PARTITION_FAT32:
2639 case PARTITION_FAT32_XINT13:
2640 {
2641 return InstallFatBootcodeToPartition(SystemRootPath,
2642 SourceRootPath,
2643 DestinationArcPath,
2644 PartitionType);
2645 }
2646
2647 case PARTITION_EXT2:
2648 {
2649 return InstallExt2BootcodeToPartition(SystemRootPath,
2650 SourceRootPath,
2651 DestinationArcPath,
2652 PartitionType);
2653 }
2654
2655 case PARTITION_IFS:
2656 break;
2657
2658 default:
2659 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
2660 break;
2661 }
2662
2663 return STATUS_UNSUCCESSFUL;
2664 }
2665
2666
2667 NTSTATUS
2668 InstallFatBootcodeToFloppy(
2669 PUNICODE_STRING SourceRootPath,
2670 PUNICODE_STRING DestinationArcPath)
2671 {
2672 #ifdef __REACTOS__
2673 NTSTATUS Status;
2674 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0");
2675 WCHAR SrcPath[MAX_PATH];
2676 WCHAR DstPath[MAX_PATH];
2677
2678 /* Format the floppy first */
2679 Status = VfatFormat(&FloppyDevice,
2680 FMIFS_FLOPPY,
2681 NULL,
2682 TRUE,
2683 0,
2684 NULL);
2685 if (!NT_SUCCESS(Status))
2686 {
2687 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2688 return Status;
2689 }
2690
2691 /* Copy FreeLoader to the boot partition */
2692 wcscpy(SrcPath, SourceRootPath->Buffer);
2693 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2694
2695 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2696
2697 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2698 Status = SetupCopyFile(SrcPath, DstPath);
2699 if (!NT_SUCCESS(Status))
2700 {
2701 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2702 return Status;
2703 }
2704
2705 /* Create new 'freeldr.ini' */
2706 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2707
2708 DPRINT("Create new 'freeldr.ini'\n");
2709 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2710 if (!NT_SUCCESS(Status))
2711 {
2712 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2713 return Status;
2714 }
2715
2716 /* Install FAT12/16 boosector */
2717 wcscpy(SrcPath, SourceRootPath->Buffer);
2718 wcscat(SrcPath, L"\\loader\\fat.bin");
2719
2720 wcscpy(DstPath, L"\\Device\\Floppy0");
2721
2722 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2723 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2724 if (!NT_SUCCESS(Status))
2725 {
2726 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2727 return Status;
2728 }
2729
2730 return STATUS_SUCCESS;
2731 #else
2732 return STATUS_NOT_IMPLEMENTED;
2733 #endif
2734 }
2735
2736 /* EOF */