[USETUP][ROSAPPS][EXT2LIB] NtReadFile() calls: Remove unused 'ByteOffset = 0', Use...
[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 Status = NtReadFile(FileHandle,
1005 NULL,
1006 NULL,
1007 NULL,
1008 &IoStatusBlock,
1009 OrigBootSector,
1010 SECTORSIZE,
1011 NULL,
1012 NULL);
1013 NtClose(FileHandle);
1014 if (!NT_SUCCESS(Status))
1015 {
1016 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1017 return Status;
1018 }
1019
1020 /* Allocate buffer for new bootsector (2 sectors) */
1021 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1022 if (NewBootSector == NULL)
1023 {
1024 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1025 return STATUS_INSUFFICIENT_RESOURCES;
1026 }
1027
1028 /* Read new bootsector from SrcPath */
1029 RtlInitUnicodeString(&Name, SrcPath);
1030
1031 InitializeObjectAttributes(&ObjectAttributes,
1032 &Name,
1033 OBJ_CASE_INSENSITIVE,
1034 NULL,
1035 NULL);
1036
1037 Status = NtOpenFile(&FileHandle,
1038 GENERIC_READ | SYNCHRONIZE,
1039 &ObjectAttributes,
1040 &IoStatusBlock,
1041 0,
1042 FILE_SYNCHRONOUS_IO_NONALERT);
1043 if (!NT_SUCCESS(Status))
1044 {
1045 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1046 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1047 return Status;
1048 }
1049
1050 Status = NtReadFile(FileHandle,
1051 NULL,
1052 NULL,
1053 NULL,
1054 &IoStatusBlock,
1055 NewBootSector,
1056 2 * SECTORSIZE,
1057 NULL,
1058 NULL);
1059 NtClose(FileHandle);
1060 if (!NT_SUCCESS(Status))
1061 {
1062 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1063 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1064 return Status;
1065 }
1066
1067 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1068 memcpy(&NewBootSector->OemName,
1069 &OrigBootSector->OemName,
1070 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1071 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1072
1073 /* Disable the backup boot sector */
1074 NewBootSector->BackupBootSector = 0;
1075
1076 /* Free the original boot sector */
1077 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1078
1079 /* Write the first sector of the new bootcode to DstPath */
1080 RtlInitUnicodeString(&Name, DstPath);
1081
1082 InitializeObjectAttributes(&ObjectAttributes,
1083 &Name,
1084 0,
1085 NULL,
1086 NULL);
1087
1088 Status = NtCreateFile(&FileHandle,
1089 GENERIC_WRITE | SYNCHRONIZE,
1090 &ObjectAttributes,
1091 &IoStatusBlock,
1092 NULL,
1093 FILE_ATTRIBUTE_NORMAL,
1094 0,
1095 FILE_SUPERSEDE,
1096 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
1097 NULL,
1098 0);
1099 if (!NT_SUCCESS(Status))
1100 {
1101 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1102 return Status;
1103 }
1104
1105 FileOffset.QuadPart = 0ULL;
1106 Status = NtWriteFile(FileHandle,
1107 NULL,
1108 NULL,
1109 NULL,
1110 &IoStatusBlock,
1111 NewBootSector,
1112 SECTORSIZE,
1113 NULL,
1114 NULL);
1115 NtClose(FileHandle);
1116 if (!NT_SUCCESS(Status))
1117 {
1118 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1119 return Status;
1120 }
1121
1122 /* Write the second sector of the new bootcode to boot disk sector 14 */
1123 RtlInitUnicodeString(&Name, RootPath);
1124
1125 InitializeObjectAttributes(&ObjectAttributes,
1126 &Name,
1127 0,
1128 NULL,
1129 NULL);
1130
1131 Status = NtOpenFile(&FileHandle,
1132 GENERIC_WRITE | SYNCHRONIZE,
1133 &ObjectAttributes,
1134 &IoStatusBlock,
1135 0,
1136 FILE_SYNCHRONOUS_IO_NONALERT);
1137 if (!NT_SUCCESS(Status))
1138 {
1139 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1140 return Status;
1141 }
1142
1143 FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
1144 Status = NtWriteFile(FileHandle,
1145 NULL,
1146 NULL,
1147 NULL,
1148 &IoStatusBlock,
1149 ((PUCHAR)NewBootSector + SECTORSIZE),
1150 SECTORSIZE,
1151 &FileOffset,
1152 NULL);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 }
1156 NtClose(FileHandle);
1157
1158 /* Free the new boot sector */
1159 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1160
1161 return Status;
1162 }
1163
1164
1165 NTSTATUS
1166 InstallMbrBootCodeToDisk(
1167 PWSTR SrcPath,
1168 PWSTR RootPath)
1169 {
1170 NTSTATUS Status;
1171 UNICODE_STRING Name;
1172 OBJECT_ATTRIBUTES ObjectAttributes;
1173 IO_STATUS_BLOCK IoStatusBlock;
1174 HANDLE FileHandle;
1175 LARGE_INTEGER FileOffset;
1176 PPARTITION_SECTOR OrigBootSector;
1177 PPARTITION_SECTOR NewBootSector;
1178
1179 /* Allocate buffer for original bootsector */
1180 OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1181 0,
1182 sizeof(PARTITION_SECTOR));
1183 if (OrigBootSector == NULL)
1184 return STATUS_INSUFFICIENT_RESOURCES;
1185
1186 /* Read current boot sector into buffer */
1187 RtlInitUnicodeString(&Name,
1188 RootPath);
1189
1190 InitializeObjectAttributes(&ObjectAttributes,
1191 &Name,
1192 OBJ_CASE_INSENSITIVE,
1193 NULL,
1194 NULL);
1195
1196 Status = NtOpenFile(&FileHandle,
1197 GENERIC_READ | SYNCHRONIZE,
1198 &ObjectAttributes,
1199 &IoStatusBlock,
1200 0,
1201 FILE_SYNCHRONOUS_IO_NONALERT);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1205 return Status;
1206 }
1207
1208 FileOffset.QuadPart = 0ULL;
1209 Status = NtReadFile(FileHandle,
1210 NULL,
1211 NULL,
1212 NULL,
1213 &IoStatusBlock,
1214 OrigBootSector,
1215 sizeof(PARTITION_SECTOR),
1216 &FileOffset,
1217 NULL);
1218 NtClose(FileHandle);
1219 if (!NT_SUCCESS(Status))
1220 {
1221 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1222 return Status;
1223 }
1224
1225 /* Allocate buffer for new bootsector */
1226 NewBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap,
1227 0,
1228 sizeof(PARTITION_SECTOR));
1229 if (NewBootSector == NULL)
1230 {
1231 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1232 return STATUS_INSUFFICIENT_RESOURCES;
1233 }
1234
1235 /* Read new bootsector from SrcPath */
1236 RtlInitUnicodeString(&Name, SrcPath);
1237
1238 InitializeObjectAttributes(&ObjectAttributes,
1239 &Name,
1240 OBJ_CASE_INSENSITIVE,
1241 NULL,
1242 NULL);
1243
1244 Status = NtOpenFile(&FileHandle,
1245 GENERIC_READ | SYNCHRONIZE,
1246 &ObjectAttributes,
1247 &IoStatusBlock,
1248 0,
1249 FILE_SYNCHRONOUS_IO_NONALERT);
1250 if (!NT_SUCCESS(Status))
1251 {
1252 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1253 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1254 return Status;
1255 }
1256
1257 Status = NtReadFile(FileHandle,
1258 NULL,
1259 NULL,
1260 NULL,
1261 &IoStatusBlock,
1262 NewBootSector,
1263 sizeof(PARTITION_SECTOR),
1264 NULL,
1265 NULL);
1266 NtClose(FileHandle);
1267 if (!NT_SUCCESS(Status))
1268 {
1269 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1270 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1271 return Status;
1272 }
1273
1274 /* Copy partition table from old MBR to new */
1275 RtlCopyMemory(&NewBootSector->Signature,
1276 &OrigBootSector->Signature,
1277 sizeof(PARTITION_SECTOR) - offsetof(PARTITION_SECTOR, Signature) /* Length of partition table */);
1278
1279 /* Free the original boot sector */
1280 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1281
1282 /* Write new bootsector to RootPath */
1283 RtlInitUnicodeString(&Name, RootPath);
1284
1285 InitializeObjectAttributes(&ObjectAttributes,
1286 &Name,
1287 0,
1288 NULL,
1289 NULL);
1290
1291 Status = NtOpenFile(&FileHandle,
1292 GENERIC_WRITE | SYNCHRONIZE,
1293 &ObjectAttributes,
1294 &IoStatusBlock,
1295 0,
1296 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1297 if (!NT_SUCCESS(Status))
1298 {
1299 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1300 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1301 return Status;
1302 }
1303
1304 FileOffset.QuadPart = 0ULL;
1305 Status = NtWriteFile(FileHandle,
1306 NULL,
1307 NULL,
1308 NULL,
1309 &IoStatusBlock,
1310 NewBootSector,
1311 sizeof(PARTITION_SECTOR),
1312 &FileOffset,
1313 NULL);
1314 NtClose(FileHandle);
1315
1316 /* Free the new boot sector */
1317 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1318
1319 return Status;
1320 }
1321
1322 static
1323 NTSTATUS
1324 InstallFat12BootCodeToFloppy(
1325 PWSTR SrcPath,
1326 PWSTR RootPath)
1327 {
1328 NTSTATUS Status;
1329 UNICODE_STRING Name;
1330 OBJECT_ATTRIBUTES ObjectAttributes;
1331 IO_STATUS_BLOCK IoStatusBlock;
1332 HANDLE FileHandle;
1333 LARGE_INTEGER FileOffset;
1334 PFAT_BOOTSECTOR OrigBootSector;
1335 PFAT_BOOTSECTOR NewBootSector;
1336
1337 /* Allocate buffer for original bootsector */
1338 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1339 if (OrigBootSector == NULL)
1340 return STATUS_INSUFFICIENT_RESOURCES;
1341
1342 /* Read current boot sector into buffer */
1343 RtlInitUnicodeString(&Name, RootPath);
1344
1345 InitializeObjectAttributes(&ObjectAttributes,
1346 &Name,
1347 OBJ_CASE_INSENSITIVE,
1348 NULL,
1349 NULL);
1350
1351 Status = NtOpenFile(&FileHandle,
1352 GENERIC_READ | SYNCHRONIZE,
1353 &ObjectAttributes,
1354 &IoStatusBlock,
1355 0,
1356 FILE_SYNCHRONOUS_IO_NONALERT);
1357 if (!NT_SUCCESS(Status))
1358 {
1359 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1360 return Status;
1361 }
1362
1363 FileOffset.QuadPart = 0ULL;
1364 Status = NtReadFile(FileHandle,
1365 NULL,
1366 NULL,
1367 NULL,
1368 &IoStatusBlock,
1369 OrigBootSector,
1370 SECTORSIZE,
1371 &FileOffset,
1372 NULL);
1373 NtClose(FileHandle);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1377 return Status;
1378 }
1379
1380 /* Allocate buffer for new bootsector */
1381 NewBootSector = RtlAllocateHeap(ProcessHeap,
1382 0,
1383 SECTORSIZE);
1384 if (NewBootSector == NULL)
1385 {
1386 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1387 return STATUS_INSUFFICIENT_RESOURCES;
1388 }
1389
1390 /* Read new bootsector from SrcPath */
1391 RtlInitUnicodeString(&Name, SrcPath);
1392
1393 InitializeObjectAttributes(&ObjectAttributes,
1394 &Name,
1395 OBJ_CASE_INSENSITIVE,
1396 NULL,
1397 NULL);
1398
1399 Status = NtOpenFile(&FileHandle,
1400 GENERIC_READ | SYNCHRONIZE,
1401 &ObjectAttributes,
1402 &IoStatusBlock,
1403 0,
1404 FILE_SYNCHRONOUS_IO_NONALERT);
1405 if (!NT_SUCCESS(Status))
1406 {
1407 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1408 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1409 return Status;
1410 }
1411
1412 Status = NtReadFile(FileHandle,
1413 NULL,
1414 NULL,
1415 NULL,
1416 &IoStatusBlock,
1417 NewBootSector,
1418 SECTORSIZE,
1419 NULL,
1420 NULL);
1421 NtClose(FileHandle);
1422 if (!NT_SUCCESS(Status))
1423 {
1424 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1425 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1426 return Status;
1427 }
1428
1429 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1430 memcpy(&NewBootSector->OemName,
1431 &OrigBootSector->OemName,
1432 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1433 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1434
1435 /* Free the original boot sector */
1436 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1437
1438 /* Write new bootsector to RootPath */
1439 RtlInitUnicodeString(&Name, RootPath);
1440
1441 InitializeObjectAttributes(&ObjectAttributes,
1442 &Name,
1443 0,
1444 NULL,
1445 NULL);
1446
1447 Status = NtOpenFile(&FileHandle,
1448 GENERIC_WRITE | SYNCHRONIZE,
1449 &ObjectAttributes,
1450 &IoStatusBlock,
1451 0,
1452 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1453 if (!NT_SUCCESS(Status))
1454 {
1455 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1456 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1457 return Status;
1458 }
1459
1460 FileOffset.QuadPart = 0ULL;
1461 Status = NtWriteFile(FileHandle,
1462 NULL,
1463 NULL,
1464 NULL,
1465 &IoStatusBlock,
1466 NewBootSector,
1467 SECTORSIZE,
1468 &FileOffset,
1469 NULL);
1470 NtClose(FileHandle);
1471
1472 /* Free the new boot sector */
1473 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1474
1475 return Status;
1476 }
1477
1478 static
1479 NTSTATUS
1480 InstallFat16BootCodeToDisk(
1481 PWSTR SrcPath,
1482 PWSTR RootPath)
1483 {
1484 NTSTATUS Status;
1485 UNICODE_STRING Name;
1486 OBJECT_ATTRIBUTES ObjectAttributes;
1487 IO_STATUS_BLOCK IoStatusBlock;
1488 HANDLE FileHandle;
1489 LARGE_INTEGER FileOffset;
1490 PFAT_BOOTSECTOR OrigBootSector;
1491 PFAT_BOOTSECTOR NewBootSector;
1492
1493 /* Allocate buffer for original bootsector */
1494 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1495 if (OrigBootSector == NULL)
1496 return STATUS_INSUFFICIENT_RESOURCES;
1497
1498 /* Read current boot sector into buffer */
1499 RtlInitUnicodeString(&Name, RootPath);
1500
1501 InitializeObjectAttributes(&ObjectAttributes,
1502 &Name,
1503 OBJ_CASE_INSENSITIVE,
1504 NULL,
1505 NULL);
1506
1507 Status = NtOpenFile(&FileHandle,
1508 GENERIC_READ | SYNCHRONIZE,
1509 &ObjectAttributes,
1510 &IoStatusBlock,
1511 0,
1512 FILE_SYNCHRONOUS_IO_NONALERT);
1513 if (!NT_SUCCESS(Status))
1514 {
1515 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1516 return Status;
1517 }
1518
1519 FileOffset.QuadPart = 0ULL;
1520 Status = NtReadFile(FileHandle,
1521 NULL,
1522 NULL,
1523 NULL,
1524 &IoStatusBlock,
1525 OrigBootSector,
1526 SECTORSIZE,
1527 &FileOffset,
1528 NULL);
1529 NtClose(FileHandle);
1530 if (!NT_SUCCESS(Status))
1531 {
1532 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1533 return Status;
1534 }
1535
1536 /* Allocate buffer for new bootsector */
1537 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1538 if (NewBootSector == NULL)
1539 {
1540 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1541 return STATUS_INSUFFICIENT_RESOURCES;
1542 }
1543
1544 /* Read new bootsector from SrcPath */
1545 RtlInitUnicodeString(&Name, SrcPath);
1546
1547 InitializeObjectAttributes(&ObjectAttributes,
1548 &Name,
1549 OBJ_CASE_INSENSITIVE,
1550 NULL,
1551 NULL);
1552
1553 Status = NtOpenFile(&FileHandle,
1554 GENERIC_READ | SYNCHRONIZE,
1555 &ObjectAttributes,
1556 &IoStatusBlock,
1557 0,
1558 FILE_SYNCHRONOUS_IO_NONALERT);
1559 if (!NT_SUCCESS(Status))
1560 {
1561 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1562 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1563 return Status;
1564 }
1565
1566 Status = NtReadFile(FileHandle,
1567 NULL,
1568 NULL,
1569 NULL,
1570 &IoStatusBlock,
1571 NewBootSector,
1572 SECTORSIZE,
1573 NULL,
1574 NULL);
1575 NtClose(FileHandle);
1576 if (!NT_SUCCESS(Status))
1577 {
1578 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1579 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1580 return Status;
1581 }
1582
1583 /* Adjust bootsector (copy a part of the FAT16 BPB) */
1584 memcpy(&NewBootSector->OemName,
1585 &OrigBootSector->OemName,
1586 FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
1587 FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
1588
1589 /* Free the original boot sector */
1590 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1591
1592 /* Write new bootsector to RootPath */
1593 RtlInitUnicodeString(&Name, RootPath);
1594
1595 InitializeObjectAttributes(&ObjectAttributes,
1596 &Name,
1597 0,
1598 NULL,
1599 NULL);
1600
1601 Status = NtOpenFile(&FileHandle,
1602 GENERIC_WRITE | SYNCHRONIZE,
1603 &ObjectAttributes,
1604 &IoStatusBlock,
1605 0,
1606 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1607 if (!NT_SUCCESS(Status))
1608 {
1609 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1610 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1611 return Status;
1612 }
1613
1614 FileOffset.QuadPart = 0ULL;
1615 Status = NtWriteFile(FileHandle,
1616 NULL,
1617 NULL,
1618 NULL,
1619 &IoStatusBlock,
1620 NewBootSector,
1621 SECTORSIZE,
1622 &FileOffset,
1623 NULL);
1624 NtClose(FileHandle);
1625
1626 /* Free the new boot sector */
1627 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1628
1629 return Status;
1630 }
1631
1632 static
1633 NTSTATUS
1634 InstallFat32BootCodeToDisk(
1635 PWSTR SrcPath,
1636 PWSTR RootPath)
1637 {
1638 NTSTATUS Status;
1639 UNICODE_STRING Name;
1640 OBJECT_ATTRIBUTES ObjectAttributes;
1641 IO_STATUS_BLOCK IoStatusBlock;
1642 HANDLE FileHandle;
1643 LARGE_INTEGER FileOffset;
1644 PFAT32_BOOTSECTOR OrigBootSector;
1645 PFAT32_BOOTSECTOR NewBootSector;
1646 USHORT BackupBootSector;
1647
1648 /* Allocate buffer for original bootsector */
1649 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1650 if (OrigBootSector == NULL)
1651 return STATUS_INSUFFICIENT_RESOURCES;
1652
1653 /* Read current boot sector into buffer */
1654 RtlInitUnicodeString(&Name, RootPath);
1655
1656 InitializeObjectAttributes(&ObjectAttributes,
1657 &Name,
1658 OBJ_CASE_INSENSITIVE,
1659 NULL,
1660 NULL);
1661
1662 Status = NtOpenFile(&FileHandle,
1663 GENERIC_READ | SYNCHRONIZE,
1664 &ObjectAttributes,
1665 &IoStatusBlock,
1666 0,
1667 FILE_SYNCHRONOUS_IO_NONALERT);
1668 if (!NT_SUCCESS(Status))
1669 {
1670 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1671 return Status;
1672 }
1673
1674 FileOffset.QuadPart = 0ULL;
1675 Status = NtReadFile(FileHandle,
1676 NULL,
1677 NULL,
1678 NULL,
1679 &IoStatusBlock,
1680 OrigBootSector,
1681 SECTORSIZE,
1682 &FileOffset,
1683 NULL);
1684 NtClose(FileHandle);
1685 if (!NT_SUCCESS(Status))
1686 {
1687 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1688 return Status;
1689 }
1690
1691
1692 /* Allocate buffer for new bootsector (2 sectors) */
1693 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE);
1694 if (NewBootSector == NULL)
1695 {
1696 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1697 return STATUS_INSUFFICIENT_RESOURCES;
1698 }
1699
1700 /* Read new bootsector from SrcPath */
1701 RtlInitUnicodeString(&Name, SrcPath);
1702
1703 InitializeObjectAttributes(&ObjectAttributes,
1704 &Name,
1705 OBJ_CASE_INSENSITIVE,
1706 NULL,
1707 NULL);
1708
1709 Status = NtOpenFile(&FileHandle,
1710 GENERIC_READ | SYNCHRONIZE,
1711 &ObjectAttributes,
1712 &IoStatusBlock,
1713 0,
1714 FILE_SYNCHRONOUS_IO_NONALERT);
1715 if (!NT_SUCCESS(Status))
1716 {
1717 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1718 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1719 return Status;
1720 }
1721
1722 Status = NtReadFile(FileHandle,
1723 NULL,
1724 NULL,
1725 NULL,
1726 &IoStatusBlock,
1727 NewBootSector,
1728 2 * SECTORSIZE,
1729 NULL,
1730 NULL);
1731 NtClose(FileHandle);
1732 if (!NT_SUCCESS(Status))
1733 {
1734 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1735 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1736 return Status;
1737 }
1738
1739 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1740 memcpy(&NewBootSector->OemName,
1741 &OrigBootSector->OemName,
1742 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1743 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1744
1745 /* Get the location of the backup boot sector */
1746 BackupBootSector = OrigBootSector->BackupBootSector;
1747
1748 /* Free the original boot sector */
1749 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1750
1751 /* Write the first sector of the new bootcode to DstPath */
1752 RtlInitUnicodeString(&Name, RootPath);
1753
1754 InitializeObjectAttributes(&ObjectAttributes,
1755 &Name,
1756 0,
1757 NULL,
1758 NULL);
1759
1760 Status = NtOpenFile(&FileHandle,
1761 GENERIC_WRITE | SYNCHRONIZE,
1762 &ObjectAttributes,
1763 &IoStatusBlock,
1764 0,
1765 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1766 if (!NT_SUCCESS(Status))
1767 {
1768 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1769 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1770 return Status;
1771 }
1772
1773 /* Write sector 0 */
1774 FileOffset.QuadPart = 0ULL;
1775 Status = NtWriteFile(FileHandle,
1776 NULL,
1777 NULL,
1778 NULL,
1779 &IoStatusBlock,
1780 NewBootSector,
1781 SECTORSIZE,
1782 &FileOffset,
1783 NULL);
1784 if (!NT_SUCCESS(Status))
1785 {
1786 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1787 NtClose(FileHandle);
1788 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1789 return Status;
1790 }
1791
1792 /* Write backup boot sector */
1793 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
1794 {
1795 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
1796 Status = NtWriteFile(FileHandle,
1797 NULL,
1798 NULL,
1799 NULL,
1800 &IoStatusBlock,
1801 NewBootSector,
1802 SECTORSIZE,
1803 &FileOffset,
1804 NULL);
1805 if (!NT_SUCCESS(Status))
1806 {
1807 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1808 NtClose(FileHandle);
1809 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1810 return Status;
1811 }
1812 }
1813
1814 /* Write sector 14 */
1815 FileOffset.QuadPart = 14 * SECTORSIZE;
1816 Status = NtWriteFile(FileHandle,
1817 NULL,
1818 NULL,
1819 NULL,
1820 &IoStatusBlock,
1821 ((PUCHAR)NewBootSector + SECTORSIZE),
1822 SECTORSIZE,
1823 &FileOffset,
1824 NULL);
1825 if (!NT_SUCCESS(Status))
1826 {
1827 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1828 }
1829 NtClose(FileHandle);
1830
1831 /* Free the new boot sector */
1832 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1833
1834 return Status;
1835 }
1836
1837 static
1838 NTSTATUS
1839 InstallExt2BootCodeToDisk(
1840 PWSTR SrcPath,
1841 PWSTR RootPath)
1842 {
1843 NTSTATUS Status;
1844 UNICODE_STRING Name;
1845 OBJECT_ATTRIBUTES ObjectAttributes;
1846 IO_STATUS_BLOCK IoStatusBlock;
1847 HANDLE FileHandle;
1848 LARGE_INTEGER FileOffset;
1849 // PEXT2_BOOTSECTOR OrigBootSector;
1850 PEXT2_BOOTSECTOR NewBootSector;
1851 // USHORT BackupBootSector;
1852
1853 #if 0
1854 /* Allocate buffer for original bootsector */
1855 OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
1856 if (OrigBootSector == NULL)
1857 return STATUS_INSUFFICIENT_RESOURCES;
1858
1859 /* Read current boot sector into buffer */
1860 RtlInitUnicodeString(&Name, RootPath);
1861
1862 InitializeObjectAttributes(&ObjectAttributes,
1863 &Name,
1864 OBJ_CASE_INSENSITIVE,
1865 NULL,
1866 NULL);
1867
1868 Status = NtOpenFile(&FileHandle,
1869 GENERIC_READ | SYNCHRONIZE,
1870 &ObjectAttributes,
1871 &IoStatusBlock,
1872 0,
1873 FILE_SYNCHRONOUS_IO_NONALERT);
1874 if (!NT_SUCCESS(Status))
1875 {
1876 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1877 return Status;
1878 }
1879
1880 FileOffset.QuadPart = 0ULL;
1881 Status = NtReadFile(FileHandle,
1882 NULL,
1883 NULL,
1884 NULL,
1885 &IoStatusBlock,
1886 OrigBootSector,
1887 SECTORSIZE,
1888 &FileOffset,
1889 NULL);
1890 NtClose(FileHandle);
1891 if (!NT_SUCCESS(Status))
1892 {
1893 RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1894 return Status;
1895 }
1896 #endif
1897
1898 /* Allocate buffer for new bootsector */
1899 NewBootSector = RtlAllocateHeap(ProcessHeap, 0, sizeof(EXT2_BOOTSECTOR));
1900 if (NewBootSector == NULL)
1901 {
1902 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1903 return STATUS_INSUFFICIENT_RESOURCES;
1904 }
1905
1906 /* Read new bootsector from SrcPath */
1907 RtlInitUnicodeString(&Name, SrcPath);
1908
1909 InitializeObjectAttributes(&ObjectAttributes,
1910 &Name,
1911 OBJ_CASE_INSENSITIVE,
1912 NULL,
1913 NULL);
1914
1915 Status = NtOpenFile(&FileHandle,
1916 GENERIC_READ | SYNCHRONIZE,
1917 &ObjectAttributes,
1918 &IoStatusBlock,
1919 0,
1920 FILE_SYNCHRONOUS_IO_NONALERT);
1921 if (!NT_SUCCESS(Status))
1922 {
1923 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1924 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1925 return Status;
1926 }
1927
1928 Status = NtReadFile(FileHandle,
1929 NULL,
1930 NULL,
1931 NULL,
1932 &IoStatusBlock,
1933 NewBootSector,
1934 sizeof(EXT2_BOOTSECTOR),
1935 NULL,
1936 NULL);
1937 NtClose(FileHandle);
1938 if (!NT_SUCCESS(Status))
1939 {
1940 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1941 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1942 return Status;
1943 }
1944
1945 #if 0
1946 /* Adjust bootsector (copy a part of the FAT32 BPB) */
1947 memcpy(&NewBootSector->OemName,
1948 &OrigBootSector->OemName,
1949 FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
1950 FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
1951
1952 NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
1953
1954 /* Get the location of the backup boot sector */
1955 BackupBootSector = OrigBootSector->BackupBootSector;
1956
1957 /* Free the original boot sector */
1958 // RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
1959 #endif
1960
1961 /* Write new bootsector to RootPath */
1962 RtlInitUnicodeString(&Name, RootPath);
1963
1964 InitializeObjectAttributes(&ObjectAttributes,
1965 &Name,
1966 0,
1967 NULL,
1968 NULL);
1969
1970 Status = NtOpenFile(&FileHandle,
1971 GENERIC_WRITE | SYNCHRONIZE,
1972 &ObjectAttributes,
1973 &IoStatusBlock,
1974 0,
1975 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1979 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
1980 return Status;
1981 }
1982
1983 /* Write sector 0 */
1984 FileOffset.QuadPart = 0ULL;
1985 Status = NtWriteFile(FileHandle,
1986 NULL,
1987 NULL,
1988 NULL,
1989 &IoStatusBlock,
1990 NewBootSector,
1991 sizeof(EXT2_BOOTSECTOR),
1992 &FileOffset,
1993 NULL);
1994 #if 0
1995 if (!NT_SUCCESS(Status))
1996 {
1997 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
1998 NtClose(FileHandle);
1999 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2000 return Status;
2001 }
2002
2003 /* Write backup boot sector */
2004 if ((BackupBootSector != 0x0000) && (BackupBootSector != 0xFFFF))
2005 {
2006 FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
2007 Status = NtWriteFile(FileHandle,
2008 NULL,
2009 NULL,
2010 NULL,
2011 &IoStatusBlock,
2012 NewBootSector,
2013 SECTORSIZE,
2014 &FileOffset,
2015 NULL);
2016 if (!NT_SUCCESS(Status))
2017 {
2018 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2019 NtClose(FileHandle);
2020 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2021 return Status;
2022 }
2023 }
2024
2025 /* Write sector 14 */
2026 FileOffset.QuadPart = 14 * SECTORSIZE;
2027 Status = NtWriteFile(FileHandle,
2028 NULL,
2029 NULL,
2030 NULL,
2031 &IoStatusBlock,
2032 ((PUCHAR)NewBootSector + SECTORSIZE),
2033 SECTORSIZE,
2034 &FileOffset,
2035 NULL);
2036 if (!NT_SUCCESS(Status))
2037 {
2038 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
2039 }
2040 #endif
2041 NtClose(FileHandle);
2042
2043 /* Free the new boot sector */
2044 RtlFreeHeap(ProcessHeap, 0, NewBootSector);
2045
2046 return Status;
2047 }
2048
2049 static
2050 NTSTATUS
2051 UnprotectBootIni(
2052 PWSTR FileName,
2053 PULONG Attributes)
2054 {
2055 NTSTATUS Status;
2056 UNICODE_STRING Name;
2057 OBJECT_ATTRIBUTES ObjectAttributes;
2058 IO_STATUS_BLOCK IoStatusBlock;
2059 FILE_BASIC_INFORMATION FileInfo;
2060 HANDLE FileHandle;
2061
2062 RtlInitUnicodeString(&Name, FileName);
2063
2064 InitializeObjectAttributes(&ObjectAttributes,
2065 &Name,
2066 OBJ_CASE_INSENSITIVE,
2067 NULL,
2068 NULL);
2069
2070 Status = NtOpenFile(&FileHandle,
2071 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2072 &ObjectAttributes,
2073 &IoStatusBlock,
2074 0,
2075 FILE_SYNCHRONOUS_IO_NONALERT);
2076 if (Status == STATUS_NO_SUCH_FILE)
2077 {
2078 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2079 *Attributes = 0;
2080 return STATUS_SUCCESS;
2081 }
2082 if (!NT_SUCCESS(Status))
2083 {
2084 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2085 return Status;
2086 }
2087
2088 Status = NtQueryInformationFile(FileHandle,
2089 &IoStatusBlock,
2090 &FileInfo,
2091 sizeof(FILE_BASIC_INFORMATION),
2092 FileBasicInformation);
2093 if (!NT_SUCCESS(Status))
2094 {
2095 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2096 NtClose(FileHandle);
2097 return Status;
2098 }
2099
2100 *Attributes = FileInfo.FileAttributes;
2101
2102 /* Delete attributes SYSTEM, HIDDEN and READONLY */
2103 FileInfo.FileAttributes = FileInfo.FileAttributes &
2104 ~(FILE_ATTRIBUTE_SYSTEM |
2105 FILE_ATTRIBUTE_HIDDEN |
2106 FILE_ATTRIBUTE_READONLY);
2107
2108 Status = NtSetInformationFile(FileHandle,
2109 &IoStatusBlock,
2110 &FileInfo,
2111 sizeof(FILE_BASIC_INFORMATION),
2112 FileBasicInformation);
2113 if (!NT_SUCCESS(Status))
2114 {
2115 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2116 }
2117
2118 NtClose(FileHandle);
2119 return Status;
2120 }
2121
2122 static
2123 NTSTATUS
2124 ProtectBootIni(
2125 PWSTR FileName,
2126 ULONG Attributes)
2127 {
2128 NTSTATUS Status;
2129 UNICODE_STRING Name;
2130 OBJECT_ATTRIBUTES ObjectAttributes;
2131 IO_STATUS_BLOCK IoStatusBlock;
2132 FILE_BASIC_INFORMATION FileInfo;
2133 HANDLE FileHandle;
2134
2135 RtlInitUnicodeString(&Name, FileName);
2136
2137 InitializeObjectAttributes(&ObjectAttributes,
2138 &Name,
2139 OBJ_CASE_INSENSITIVE,
2140 NULL,
2141 NULL);
2142
2143 Status = NtOpenFile(&FileHandle,
2144 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2145 &ObjectAttributes,
2146 &IoStatusBlock,
2147 0,
2148 FILE_SYNCHRONOUS_IO_NONALERT);
2149 if (!NT_SUCCESS(Status))
2150 {
2151 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2152 return Status;
2153 }
2154
2155 Status = NtQueryInformationFile(FileHandle,
2156 &IoStatusBlock,
2157 &FileInfo,
2158 sizeof(FILE_BASIC_INFORMATION),
2159 FileBasicInformation);
2160 if (!NT_SUCCESS(Status))
2161 {
2162 DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
2163 NtClose(FileHandle);
2164 return Status;
2165 }
2166
2167 FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
2168
2169 Status = NtSetInformationFile(FileHandle,
2170 &IoStatusBlock,
2171 &FileInfo,
2172 sizeof(FILE_BASIC_INFORMATION),
2173 FileBasicInformation);
2174 if (!NT_SUCCESS(Status))
2175 {
2176 DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
2177 }
2178
2179 NtClose(FileHandle);
2180 return Status;
2181 }
2182
2183 static
2184 NTSTATUS
2185 UpdateBootIni(
2186 PWSTR BootIniPath,
2187 PWSTR EntryName,
2188 PWSTR EntryValue)
2189 {
2190 NTSTATUS Status;
2191 PINICACHE Cache = NULL;
2192 PINICACHESECTION Section = NULL;
2193 ULONG FileAttribute;
2194 PWCHAR OldValue = NULL;
2195
2196 Status = IniCacheLoad(&Cache, BootIniPath, FALSE);
2197 if (!NT_SUCCESS(Status))
2198 {
2199 return Status;
2200 }
2201
2202 Section = IniCacheGetSection(Cache,
2203 L"operating systems");
2204 if (Section == NULL)
2205 {
2206 IniCacheDestroy(Cache);
2207 return STATUS_UNSUCCESSFUL;
2208 }
2209
2210 /* Check - maybe record already exists */
2211 Status = IniCacheGetKey(Section, EntryName, &OldValue);
2212
2213 /* If either key was not found, or contains something else - add new one */
2214 if (!NT_SUCCESS(Status) || wcscmp(OldValue, EntryValue))
2215 {
2216 IniCacheInsertKey(Section,
2217 NULL,
2218 INSERT_LAST,
2219 EntryName,
2220 EntryValue);
2221 }
2222
2223 Status = UnprotectBootIni(BootIniPath,
2224 &FileAttribute);
2225 if (!NT_SUCCESS(Status))
2226 {
2227 IniCacheDestroy(Cache);
2228 return Status;
2229 }
2230
2231 Status = IniCacheSave(Cache, BootIniPath);
2232 if (!NT_SUCCESS(Status))
2233 {
2234 IniCacheDestroy(Cache);
2235 return Status;
2236 }
2237
2238 FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
2239 Status = ProtectBootIni(BootIniPath, FileAttribute);
2240
2241 IniCacheDestroy(Cache);
2242
2243 return Status;
2244 }
2245
2246 static
2247 NTSTATUS
2248 InstallFatBootcodeToPartition(
2249 PUNICODE_STRING SystemRootPath,
2250 PUNICODE_STRING SourceRootPath,
2251 PUNICODE_STRING DestinationArcPath,
2252 UCHAR PartitionType)
2253 {
2254 #ifdef __REACTOS__
2255 NTSTATUS Status;
2256 BOOLEAN DoesFreeLdrExist;
2257 WCHAR SrcPath[MAX_PATH];
2258 WCHAR DstPath[MAX_PATH];
2259
2260 /* FAT or FAT32 partition */
2261 DPRINT("System path: '%wZ'\n", SystemRootPath);
2262
2263 /* Copy FreeLoader to the system partition */
2264 wcscpy(SrcPath, SourceRootPath->Buffer);
2265 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2266 wcscpy(DstPath, SystemRootPath->Buffer);
2267 wcscat(DstPath, L"\\freeldr.sys");
2268
2269 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2270 Status = SetupCopyFile(SrcPath, DstPath);
2271 if (!NT_SUCCESS(Status))
2272 {
2273 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2274 return Status;
2275 }
2276
2277 /* Prepare for possibly copying 'freeldr.ini' */
2278 wcscpy(DstPath, SystemRootPath->Buffer);
2279 wcscat(DstPath, L"\\freeldr.ini");
2280
2281 DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
2282 if (DoesFreeLdrExist)
2283 {
2284 /* Update existing 'freeldr.ini' */
2285 DPRINT1("Update existing 'freeldr.ini'\n");
2286
2287 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2288 if (!NT_SUCCESS(Status))
2289 {
2290 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2291 return Status;
2292 }
2293 }
2294
2295 /* Check for NT and other bootloaders */
2296
2297 // FIXME: Check for Vista+ bootloader!
2298 if (DoesFileExist(SystemRootPath->Buffer, L"ntldr") == TRUE ||
2299 DoesFileExist(SystemRootPath->Buffer, L"boot.ini") == TRUE)
2300 {
2301 /* Search root directory for 'ntldr' and 'boot.ini' */
2302 DPRINT1("Found Microsoft Windows NT/2000/XP boot loader\n");
2303
2304 /* Create or update 'freeldr.ini' */
2305 if (DoesFreeLdrExist == FALSE)
2306 {
2307 /* Create new 'freeldr.ini' */
2308 DPRINT1("Create new 'freeldr.ini'\n");
2309 // wcscpy(DstPath, SystemRootPath->Buffer);
2310 // wcscat(DstPath, L"\\freeldr.ini");
2311
2312 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2313 if (!NT_SUCCESS(Status))
2314 {
2315 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2316 return Status;
2317 }
2318
2319 /* Install new bootcode into a file */
2320 wcscpy(DstPath, SystemRootPath->Buffer);
2321 wcscat(DstPath, L"\\bootsect.ros");
2322
2323 if (PartitionType == PARTITION_FAT32 ||
2324 PartitionType == PARTITION_FAT32_XINT13)
2325 {
2326 /* Install FAT32 bootcode */
2327 wcscpy(SrcPath, SourceRootPath->Buffer);
2328 wcscat(SrcPath, L"\\loader\\fat32.bin");
2329
2330 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, DstPath);
2331 Status = InstallFat32BootCodeToFile(SrcPath, DstPath,
2332 SystemRootPath->Buffer);
2333 if (!NT_SUCCESS(Status))
2334 {
2335 DPRINT1("InstallFat32BootCodeToFile() failed (Status %lx)\n", Status);
2336 return Status;
2337 }
2338 }
2339 else
2340 {
2341 /* Install FAT16 bootcode */
2342 wcscpy(SrcPath, SourceRootPath->Buffer);
2343 wcscat(SrcPath, L"\\loader\\fat.bin");
2344
2345 DPRINT1("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2346 Status = InstallFat16BootCodeToFile(SrcPath, DstPath,
2347 SystemRootPath->Buffer);
2348 if (!NT_SUCCESS(Status))
2349 {
2350 DPRINT1("InstallFat16BootCodeToFile() failed (Status %lx)\n", Status);
2351 return Status;
2352 }
2353 }
2354 }
2355
2356 /* Update 'boot.ini' */
2357 wcscpy(DstPath, SystemRootPath->Buffer);
2358 wcscat(DstPath, L"\\boot.ini");
2359
2360 DPRINT1("Update 'boot.ini': %S\n", DstPath);
2361 Status = UpdateBootIni(DstPath,
2362 L"C:\\bootsect.ros",
2363 L"\"ReactOS\"");
2364 if (!NT_SUCCESS(Status))
2365 {
2366 DPRINT1("UpdateBootIni() failed (Status %lx)\n", Status);
2367 return Status;
2368 }
2369 }
2370 else
2371 {
2372 /* Non-NT bootloaders: install our own bootloader */
2373
2374 PWCHAR Section;
2375 PWCHAR Description;
2376 PWCHAR BootDrive;
2377 PWCHAR BootPartition;
2378 PWCHAR BootSector;
2379 PWCHAR BootSectorFileName;
2380
2381 if (DoesFileExist(SystemRootPath->Buffer, L"io.sys") == TRUE ||
2382 DoesFileExist(SystemRootPath->Buffer, L"msdos.sys") == TRUE)
2383 {
2384 /* Search for root directory for 'io.sys' and 'msdos.sys' */
2385 DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
2386
2387 Section = L"DOS";
2388 Description = L"\"DOS/Windows\"";
2389 BootDrive = L"hd0";
2390 BootPartition = L"1";
2391 BootSector = L"BOOTSECT.DOS";
2392
2393 BootSectorFileName = L"\\bootsect.dos";
2394 }
2395 else
2396 if (DoesFileExist(SystemRootPath->Buffer, L"kernel.sys") == TRUE)
2397 {
2398 /* Search for root directory for 'kernel.sys' */
2399 DPRINT1("Found FreeDOS boot loader\n");
2400
2401 Section = L"DOS";
2402 Description = L"\"FreeDOS\"";
2403 BootDrive = L"hd0";
2404 BootPartition = L"1";
2405 BootSector = L"BOOTSECT.DOS";
2406
2407 BootSectorFileName = L"\\bootsect.dos";
2408 }
2409 else
2410 {
2411 /* No or unknown boot loader */
2412 DPRINT1("No or unknown boot loader found\n");
2413
2414 Section = L"Unknown";
2415 Description = L"\"Unknown Operating System\"";
2416 BootDrive = L"hd0";
2417 BootPartition = L"1";
2418 BootSector = L"BOOTSECT.OLD";
2419
2420 BootSectorFileName = L"\\bootsect.old";
2421 }
2422
2423 /* Create or update 'freeldr.ini' */
2424 if (DoesFreeLdrExist == FALSE)
2425 {
2426 /* Create new 'freeldr.ini' */
2427 DPRINT1("Create new 'freeldr.ini'\n");
2428 // wcscpy(DstPath, SystemRootPath->Buffer);
2429 // wcscat(DstPath, L"\\freeldr.ini");
2430
2431 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2432 {
2433 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2434 DstPath, DestinationArcPath->Buffer,
2435 Section, Description,
2436 BootDrive, BootPartition, BootSector);
2437 if (!NT_SUCCESS(Status))
2438 {
2439 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2440 return Status;
2441 }
2442
2443 /* Save current bootsector */
2444 wcscpy(DstPath, SystemRootPath->Buffer);
2445 wcscat(DstPath, BootSectorFileName);
2446
2447 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2448 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, SECTORSIZE);
2449 if (!NT_SUCCESS(Status))
2450 {
2451 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2452 return Status;
2453 }
2454 }
2455 else
2456 {
2457 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2458 if (!NT_SUCCESS(Status))
2459 {
2460 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2461 return Status;
2462 }
2463 }
2464
2465 /* Install new bootsector on the disk */
2466 if (PartitionType == PARTITION_FAT32 ||
2467 PartitionType == PARTITION_FAT32_XINT13)
2468 {
2469 /* Install FAT32 bootcode */
2470 wcscpy(SrcPath, SourceRootPath->Buffer);
2471 wcscat(SrcPath, L"\\loader\\fat32.bin");
2472
2473 DPRINT1("Install FAT32 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2474 Status = InstallFat32BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2475 if (!NT_SUCCESS(Status))
2476 {
2477 DPRINT1("InstallFat32BootCodeToDisk() failed (Status %lx)\n", Status);
2478 return Status;
2479 }
2480 }
2481 else
2482 {
2483 /* Install FAT16 bootcode */
2484 wcscpy(SrcPath, SourceRootPath->Buffer);
2485 wcscat(SrcPath, L"\\loader\\fat.bin");
2486
2487 DPRINT1("Install FAT16 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2488 Status = InstallFat16BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2489 if (!NT_SUCCESS(Status))
2490 {
2491 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2492 return Status;
2493 }
2494 }
2495 }
2496 }
2497
2498 return STATUS_SUCCESS;
2499 #else
2500 return STATUS_NOT_IMPLEMENTED;
2501 #endif
2502 }
2503
2504 static
2505 NTSTATUS
2506 InstallExt2BootcodeToPartition(
2507 PUNICODE_STRING SystemRootPath,
2508 PUNICODE_STRING SourceRootPath,
2509 PUNICODE_STRING DestinationArcPath,
2510 UCHAR PartitionType)
2511 {
2512 #ifdef __REACTOS__
2513 NTSTATUS Status;
2514 BOOLEAN DoesFreeLdrExist;
2515 WCHAR SrcPath[MAX_PATH];
2516 WCHAR DstPath[MAX_PATH];
2517
2518 /* EXT2 partition */
2519 DPRINT("System path: '%wZ'\n", SystemRootPath);
2520
2521 /* Copy FreeLoader to the system partition */
2522 wcscpy(SrcPath, SourceRootPath->Buffer);
2523 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2524 wcscpy(DstPath, SystemRootPath->Buffer);
2525 wcscat(DstPath, L"\\freeldr.sys");
2526
2527 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2528 Status = SetupCopyFile(SrcPath, DstPath);
2529 if (!NT_SUCCESS(Status))
2530 {
2531 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2532 return Status;
2533 }
2534
2535 /* Prepare for possibly copying 'freeldr.ini' */
2536 wcscpy(DstPath, SystemRootPath->Buffer);
2537 wcscat(DstPath, L"\\freeldr.ini");
2538
2539 DoesFreeLdrExist = DoesFileExist(SystemRootPath->Buffer, L"freeldr.ini");
2540 if (DoesFreeLdrExist)
2541 {
2542 /* Update existing 'freeldr.ini' */
2543 DPRINT1("Update existing 'freeldr.ini'\n");
2544
2545 Status = UpdateFreeLoaderIni(DstPath, DestinationArcPath->Buffer);
2546 if (!NT_SUCCESS(Status))
2547 {
2548 DPRINT1("UpdateFreeLoaderIni() failed (Status %lx)\n", Status);
2549 return Status;
2550 }
2551 }
2552
2553 /* Check for *nix bootloaders */
2554
2555 /* Create or update 'freeldr.ini' */
2556 if (DoesFreeLdrExist == FALSE)
2557 {
2558 /* Create new 'freeldr.ini' */
2559 DPRINT1("Create new 'freeldr.ini'\n");
2560 wcscpy(DstPath, SystemRootPath->Buffer);
2561 wcscat(DstPath, L"\\freeldr.ini");
2562
2563 /* Certainly SysLinux, GRUB, LILO... or an unknown boot loader */
2564 DPRINT1("*nix or unknown boot loader found\n");
2565
2566 if (IsThereAValidBootSector(SystemRootPath->Buffer))
2567 {
2568 Status = CreateFreeLoaderIniForReactOSAndBootSector(
2569 DstPath, DestinationArcPath->Buffer,
2570 L"Linux", L"\"Linux\"",
2571 L"hd0", L"1", L"BOOTSECT.OLD");
2572 if (!NT_SUCCESS(Status))
2573 {
2574 DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
2575 return Status;
2576 }
2577
2578 /* Save current bootsector */
2579 wcscpy(DstPath, SystemRootPath->Buffer);
2580 wcscat(DstPath, L"\\bootsect.old");
2581
2582 DPRINT1("Save bootsector: %S ==> %S\n", SystemRootPath->Buffer, DstPath);
2583 Status = SaveBootSector(SystemRootPath->Buffer, DstPath, sizeof(EXT2_BOOTSECTOR));
2584 if (!NT_SUCCESS(Status))
2585 {
2586 DPRINT1("SaveBootSector() failed (Status %lx)\n", Status);
2587 return Status;
2588 }
2589 }
2590 else
2591 {
2592 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2593 if (!NT_SUCCESS(Status))
2594 {
2595 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2596 return Status;
2597 }
2598 }
2599
2600 /* Install new bootsector on the disk */
2601 // if (PartitionType == PARTITION_EXT2)
2602 {
2603 /* Install EXT2 bootcode */
2604 wcscpy(SrcPath, SourceRootPath->Buffer);
2605 wcscat(SrcPath, L"\\loader\\ext2.bin");
2606
2607 DPRINT1("Install EXT2 bootcode: %S ==> %S\n", SrcPath, SystemRootPath->Buffer);
2608 Status = InstallExt2BootCodeToDisk(SrcPath, SystemRootPath->Buffer);
2609 if (!NT_SUCCESS(Status))
2610 {
2611 DPRINT1("InstallExt2BootCodeToDisk() failed (Status %lx)\n", Status);
2612 return Status;
2613 }
2614 }
2615 }
2616
2617 return STATUS_SUCCESS;
2618 #else
2619 return STATUS_NOT_IMPLEMENTED;
2620 #endif
2621 }
2622
2623
2624 NTSTATUS
2625 InstallVBRToPartition(
2626 PUNICODE_STRING SystemRootPath,
2627 PUNICODE_STRING SourceRootPath,
2628 PUNICODE_STRING DestinationArcPath,
2629 UCHAR PartitionType)
2630 {
2631 switch (PartitionType)
2632 {
2633 case PARTITION_FAT_12:
2634 case PARTITION_FAT_16:
2635 case PARTITION_HUGE:
2636 case PARTITION_XINT13:
2637 case PARTITION_FAT32:
2638 case PARTITION_FAT32_XINT13:
2639 {
2640 return InstallFatBootcodeToPartition(SystemRootPath,
2641 SourceRootPath,
2642 DestinationArcPath,
2643 PartitionType);
2644 }
2645
2646 case PARTITION_EXT2:
2647 {
2648 return InstallExt2BootcodeToPartition(SystemRootPath,
2649 SourceRootPath,
2650 DestinationArcPath,
2651 PartitionType);
2652 }
2653
2654 case PARTITION_IFS:
2655 break;
2656
2657 default:
2658 DPRINT1("PartitionType 0x%02X unknown!\n", PartitionType);
2659 break;
2660 }
2661
2662 return STATUS_UNSUCCESSFUL;
2663 }
2664
2665
2666 NTSTATUS
2667 InstallFatBootcodeToFloppy(
2668 PUNICODE_STRING SourceRootPath,
2669 PUNICODE_STRING DestinationArcPath)
2670 {
2671 #ifdef __REACTOS__
2672 NTSTATUS Status;
2673 UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0");
2674 WCHAR SrcPath[MAX_PATH];
2675 WCHAR DstPath[MAX_PATH];
2676
2677 /* Format the floppy first */
2678 Status = VfatFormat(&FloppyDevice,
2679 FMIFS_FLOPPY,
2680 NULL,
2681 TRUE,
2682 0,
2683 NULL);
2684 if (!NT_SUCCESS(Status))
2685 {
2686 DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
2687 return Status;
2688 }
2689
2690 /* Copy FreeLoader to the boot partition */
2691 wcscpy(SrcPath, SourceRootPath->Buffer);
2692 wcscat(SrcPath, L"\\loader\\freeldr.sys");
2693
2694 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.sys");
2695
2696 DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
2697 Status = SetupCopyFile(SrcPath, DstPath);
2698 if (!NT_SUCCESS(Status))
2699 {
2700 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status);
2701 return Status;
2702 }
2703
2704 /* Create new 'freeldr.ini' */
2705 wcscpy(DstPath, L"\\Device\\Floppy0\\freeldr.ini");
2706
2707 DPRINT("Create new 'freeldr.ini'\n");
2708 Status = CreateFreeLoaderIniForReactOS(DstPath, DestinationArcPath->Buffer);
2709 if (!NT_SUCCESS(Status))
2710 {
2711 DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
2712 return Status;
2713 }
2714
2715 /* Install FAT12/16 boosector */
2716 wcscpy(SrcPath, SourceRootPath->Buffer);
2717 wcscat(SrcPath, L"\\loader\\fat.bin");
2718
2719 wcscpy(DstPath, L"\\Device\\Floppy0");
2720
2721 DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
2722 Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
2723 if (!NT_SUCCESS(Status))
2724 {
2725 DPRINT1("InstallFat16BootCodeToDisk() failed (Status %lx)\n", Status);
2726 return Status;
2727 }
2728
2729 return STATUS_SUCCESS;
2730 #else
2731 return STATUS_NOT_IMPLEMENTED;
2732 #endif
2733 }
2734
2735 /* EOF */