ReactOS 0.4.16-dev-2613-g9533ad7
fstubex.c
Go to the documentation of this file.
1/*
2* PROJECT: ReactOS Kernel
3* LICENSE: GPL - See COPYING in the top level directory
4* FILE: ntoskrnl/fstub/fstubex.c
5* PURPOSE: Extended FSTUB Routines (not linked to HAL)
6* PROGRAMMERS: Pierre Schweitzer (pierre.schweitzer@reactos.org)
7*/
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* PRIVATE FUNCTIONS *********************************************************/
16
17typedef struct _DISK_INFORMATION
18{
25
26#include <pshpack1.h>
28{
45#include <poppack.h>
46
48{
54 WCHAR Name[0x24]; // 56
57
58typedef struct _PARTITION_TABLE_ENTRY
59{
72
73#include <pshpack1.h>
74typedef struct _MASTER_BOOT_RECORD
75{
77 ULONG Signature; // 440
78 USHORT Reserved; // 444
83#include <poppack.h>
84
85/* Partition entry size (bytes) - FIXME: It's hardcoded as Microsoft does, but according to specs, it shouldn't be */
86#define PARTITION_ENTRY_SIZE 128
87/* Defines "EFI PART" */
88#define EFI_HEADER_SIGNATURE 0x5452415020494645ULL
89/* Defines version 1.0 */
90#define EFI_HEADER_REVISION_1 0x00010000
91/* Defines system type for MBR showing that a GPT is following */
92#define EFI_PMBR_OSTYPE_EFI 0xEE
93/* Defines size to store a complete GUID + null char */
94#define EFI_GUID_STRING_SIZE 0x27
95
96#define IS_VALID_DISK_INFO(Disk) \
97 ((Disk) && \
98 ((Disk)->DeviceObject) && \
99 ((Disk)->SectorSize) && \
100 ((Disk)->Buffer) && \
101 ((Disk)->SectorCount))
102
104NTAPI
106 IN PARTITION_STYLE * PartitionStyle
107);
108
109VOID
110NTAPI
112);
113
115NTAPI
117 OUT PDISK_GEOMETRY_EX Geometry
118);
119
121NTAPI
124 IN ULONGLONG StartingSector OPTIONAL,
126);
127
129NTAPI
131);
132
134NTAPI
136 IN ULONG PartitionsSizeSector,
137 IN GUID DiskGUID,
138 IN ULONG NumberOfEntries,
139 IN ULONGLONG FirstUsableLBA,
140 IN ULONGLONG LastUsableLBA,
141 IN ULONG PartitionEntryCRC32,
142 IN BOOLEAN WriteBackupTable);
143
145NTAPI
147 IN GUID DiskGUID,
148 IN ULONG MaxPartitionCount,
149 IN ULONGLONG FirstUsableLBA,
150 IN ULONGLONG LastUsableLBA,
151 IN BOOLEAN WriteBackupTable,
152 IN ULONG PartitionCount,
153 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL
154);
155
157NTAPI
160 IN ULONGLONG StartingSector OPTIONAL,
162);
163
164VOID
165NTAPI
167 IN OUT PULONG PartitionCount)
168{
169 ULONG Count;
170
171 PAGED_CODE();
172
174 ASSERT(PartitionCount);
175
176 /* Get partition count */
177 Count = *PartitionCount;
178 /* We need at least 128 entries */
179 if (Count < 128)
180 {
181 Count = 128;
182 }
183
184 /* Then, ensure that we will have a round value,
185 * i.e. all sectors will be full of entries.
186 * There won't be lonely entries. */
189 ASSERT(*PartitionCount <= Count);
190 /* Return result */
191 *PartitionCount = Count;
192
193 /* One more sanity check */
194 if (SectorSize == 512)
195 {
196 ASSERT(Count % 4 == 0);
197 }
198}
199
201NTAPI
203 OUT PDISK_INFORMATION * DiskBuffer,
204 IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
205{
207 PDISK_INFORMATION DiskInformation;
208
209 PAGED_CODE();
210
212 ASSERT(DiskBuffer);
213
214 /* Allocate internal structure */
216 if (!DiskInformation)
217 {
219 }
220
221 /* If caller don't pass needed information, let's get them */
222 if (!DiskGeometry)
223 {
225 if (!NT_SUCCESS(Status))
226 {
227 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
228 return Status;
229 }
230 }
231 else
232 {
233 RtlCopyMemory(&DiskInformation->DiskGeometry, DiskGeometry, sizeof(DISK_GEOMETRY_EX));
234 }
235
236 /* Ensure read/received information are correct */
237 if (DiskInformation->DiskGeometry.Geometry.BytesPerSector == 0 ||
238 DiskInformation->DiskGeometry.DiskSize.QuadPart == 0)
239 {
240 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
242 }
243
244 /* Store vital information as well */
245 DiskInformation->DeviceObject = DeviceObject;
246 DiskInformation->SectorSize = DiskInformation->DiskGeometry.Geometry.BytesPerSector;
247 DiskInformation->SectorCount = DiskInformation->DiskGeometry.DiskSize.QuadPart / DiskInformation->SectorSize;
248
249 /* Finally, allocate the buffer that will be used for different read */
250 DiskInformation->Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskInformation->SectorSize, TAG_FSTUB);
251 if (!DiskInformation->Buffer)
252 {
253 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
255 }
256
257 /* Return allocated internal structure */
258 *DiskBuffer = DiskInformation;
259
260 return STATUS_SUCCESS;
261}
262
264NTAPI
265FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
266{
267 ULONG i;
268 PDRIVE_LAYOUT_INFORMATION DriveLayout;
269
270 PAGED_CODE();
271
272 ASSERT(LayoutEx);
273
274 /* Check whether we're dealing with MBR partition table */
275 if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR)
276 {
277 ASSERT(FALSE);
278 return NULL;
279 }
280
281 /* Allocate needed buffer */
283 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
284 LayoutEx->PartitionCount * sizeof(PARTITION_INFORMATION),
285 TAG_FSTUB);
286 if (!DriveLayout)
287 {
288 return NULL;
289 }
290
291 /* Convert information about partition table */
292 DriveLayout->PartitionCount = LayoutEx->PartitionCount;
293 DriveLayout->Signature = LayoutEx->Mbr.Signature;
294
295 /* Convert each partition */
296 for (i = 0; i < LayoutEx->PartitionCount; i++)
297 {
298 DriveLayout->PartitionEntry[i].StartingOffset = LayoutEx->PartitionEntry[i].StartingOffset;
299 DriveLayout->PartitionEntry[i].PartitionLength = LayoutEx->PartitionEntry[i].PartitionLength;
300 DriveLayout->PartitionEntry[i].HiddenSectors = LayoutEx->PartitionEntry[i].Mbr.HiddenSectors;
301 DriveLayout->PartitionEntry[i].PartitionNumber = LayoutEx->PartitionEntry[i].PartitionNumber;
302 DriveLayout->PartitionEntry[i].PartitionType = LayoutEx->PartitionEntry[i].Mbr.PartitionType;
303 DriveLayout->PartitionEntry[i].BootIndicator = LayoutEx->PartitionEntry[i].Mbr.BootIndicator;
304 DriveLayout->PartitionEntry[i].RecognizedPartition = LayoutEx->PartitionEntry[i].Mbr.RecognizedPartition;
305 DriveLayout->PartitionEntry[i].RewritePartition = LayoutEx->PartitionEntry[i].RewritePartition;
306 }
307
308 return DriveLayout;
309}
310
311VOID
312NTAPI
316{
317 PAGED_CODE();
318
319 ASSERT(Entry);
320 ASSERT(Partition);
322
323 /* Just convert data to EFI partition entry type */
324 Entry->PartitionType = Partition->Gpt.PartitionType;
325 Entry->UniquePartition = Partition->Gpt.PartitionId;
326 Entry->StartingLBA = Partition->StartingOffset.QuadPart / SectorSize;
327 Entry->EndingLBA = (Partition->StartingOffset.QuadPart + Partition->PartitionLength.QuadPart - 1) / SectorSize;
328 Entry->Attributes = Partition->Gpt.Attributes;
329 RtlCopyMemory(Entry->Name, Partition->Gpt.Name, sizeof(Entry->Name));
330}
331
333NTAPI
335 IN PCREATE_DISK_MBR DiskInfo)
336{
338 PDISK_INFORMATION Disk = NULL;
339 PMASTER_BOOT_RECORD MasterBootRecord;
340
341 PAGED_CODE();
342
344
345 /* Allocate internal structure */
347 if (!NT_SUCCESS(Status))
348 {
349 return Status;
350 }
351
352 /* Read previous MBR, if any */
354 Disk->SectorSize,
355 0ULL,
356 Disk->Buffer);
357 if (!NT_SUCCESS(Status))
358 {
360 return Status;
361 }
362 /* Fill the buffer with needed information, we won't overwrite boot code */
363 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
364 MasterBootRecord->Signature = DiskInfo->Signature;
367
368 /* Finally, write MBR */
370 Disk->SectorSize,
371 0ULL,
372 Disk->Buffer);
373
374 /* Release internal structure and return */
376 return Status;
377}
378
380NTAPI
382 IN PCREATE_DISK_GPT DiskInfo)
383{
385 PDISK_INFORMATION Disk = NULL;
386 ULONGLONG FirstUsableLBA, LastUsableLBA;
387 ULONG MaxPartitionCount, SectorsForPartitions;
388
389 PAGED_CODE();
390
392 ASSERT(DiskInfo);
393
394 /* Allocate internal structure */
396 if (!NT_SUCCESS(Status))
397 {
398 return Status;
399 }
400 ASSERT(Disk);
401
402 /* Write legacy MBR */
404 if (!NT_SUCCESS(Status))
405 {
407 return Status;
408 }
409
410 /* Get max entries and adjust its number */
411 MaxPartitionCount = DiskInfo->MaxPartitionCount;
412 FstubAdjustPartitionCount(Disk->SectorSize, &MaxPartitionCount);
413
414 /* Count number of sectors needed to store partitions */
415 SectorsForPartitions = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
416 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
417 FirstUsableLBA = SectorsForPartitions + 2;
418 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
419 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
420
421 /* First, write primary table */
423 DiskInfo->DiskId,
424 MaxPartitionCount,
425 FirstUsableLBA,
426 LastUsableLBA,
427 FALSE,
428 0,
429 NULL);
430 /* Then, write backup table */
431 if (NT_SUCCESS(Status))
432 {
434 DiskInfo->DiskId,
435 MaxPartitionCount,
436 FirstUsableLBA,
437 LastUsableLBA,
438 TRUE,
439 0,
440 NULL);
441 }
442
443 /* Release internal structure and return */
445 return Status;
446}
447
449NTAPI
451{
453 PDISK_INFORMATION Disk = NULL;
454 PARTITION_STYLE PartitionStyle;
455 PMASTER_BOOT_RECORD MasterBootRecord;
456
457 PAGED_CODE();
458
460
461 /* Allocate internal structure */
463 if (!NT_SUCCESS(Status))
464 {
465 return Status;
466 }
467
468 /* Detect current disk partition style */
469 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
470 if (!NT_SUCCESS(Status))
471 {
473 return Status;
474 }
475
476 /* Read MBR, if any */
478 Disk->SectorSize,
479 0ULL,
480 Disk->Buffer);
481 if (!NT_SUCCESS(Status))
482 {
484 return Status;
485 }
486
487 /* Only zero useful stuff */
488 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
489 MasterBootRecord->Signature = 0;
490 RtlZeroMemory(MasterBootRecord->PartitionTable, sizeof(PARTITION_TABLE_ENTRY));
491 MasterBootRecord->MasterBootRecordMagic = 0;
492
493 /* Write back that destroyed MBR */
495 Disk->SectorSize,
496 0ULL,
497 Disk->Buffer);
498 /* If previous style wasn't GPT, we're done here */
499 if (PartitionStyle != PARTITION_STYLE_GPT)
500 {
502 return Status;
503 }
504
505 /* Otherwise, we've to zero the two GPT headers */
506 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
507 /* Erase primary header */
509 Disk->SectorSize,
510 1ULL,
511 Disk->Buffer);
512 /* In case of success, erase backup header */
513 if (NT_SUCCESS(Status))
514 {
516 Disk->SectorSize,
517 Disk->SectorCount - 1ULL,
518 Disk->Buffer);
519 }
520
521 /* Release internal structure and return */
523 return Status;
524}
525
526#ifndef NDEBUG
527static __inline
528VOID
529FstubDbgGuidToString(
532{
534 "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
535 Guid->Data1, Guid->Data2, Guid->Data3,
536 Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
537 Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
538}
539
540static VOID
541FstubDbgPrintPartitionEx(
542 _In_ PPARTITION_INFORMATION_EX PartitionEntry,
544
545static VOID
547 _In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
548{
549 ULONG i;
550
551 PAGED_CODE();
552
553 DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
554 switch (DriveLayout->PartitionStyle)
555 {
557 {
558 if (DriveLayout->PartitionCount % NUM_PARTITION_TABLE_ENTRIES != 0)
559 {
560 DbgPrint(" Warning: Partition count isn't a 4-factor: %lu!\n", DriveLayout->PartitionCount);
561 }
562 DbgPrint(" Signature: %8.8x\n", DriveLayout->Mbr.Signature);
563 for (i = 0; i < DriveLayout->PartitionCount; i++)
564 {
565 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
566 }
567 break;
568 }
569
571 {
573 FstubDbgGuidToString(&(DriveLayout->Gpt.DiskId), Guid);
574 DbgPrint(" DiskId: %s\n", Guid);
575 DbgPrint(" StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
576 DbgPrint(" UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
577 DbgPrint(" MaxPartitionCount: %lu\n", DriveLayout->Gpt.MaxPartitionCount);
578 for (i = 0; i < DriveLayout->PartitionCount; i++)
579 {
580 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
581 }
582 break;
583 }
584
585 default:
586 DbgPrint(" Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
587 }
588}
589
590static VOID
591FstubDbgPrintPartitionEx(
592 _In_ PPARTITION_INFORMATION_EX PartitionEntry,
594{
595 PAGED_CODE();
596
597 DPRINT("Printing partition %lu\n", PartitionNumber);
598 switch (PartitionEntry[PartitionNumber].PartitionStyle)
599 {
601 {
602 DbgPrint(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
603 DbgPrint(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
604 DbgPrint(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
605 DbgPrint(" PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
606 DbgPrint(" BootIndicator: %u\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
607 DbgPrint(" RecognizedPartition: %u\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
608 DbgPrint(" HiddenSectors: %lu\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
609 break;
610 }
611
613 {
615 DbgPrint(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
616 DbgPrint(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
617 DbgPrint(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
618 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionType), Guid);
619 DbgPrint(" PartitionType: %s\n", Guid);
620 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionId), Guid);
621 DbgPrint(" PartitionId: %s\n", Guid);
622 DbgPrint(" Attributes: %I64x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
623 DbgPrint(" Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
624 break;
625 }
626
627 default:
628 DbgPrint(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
629 }
630}
631
632static VOID
634 _In_ PSET_PARTITION_INFORMATION_EX PartitionEntry,
636{
637 PAGED_CODE();
638
639 DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
640 DbgPrint("Modifying partition %lu\n", PartitionNumber);
641 switch (PartitionEntry->PartitionStyle)
642 {
644 DbgPrint(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
645 break;
646
648 {
650 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionType), Guid);
651 DbgPrint(" PartitionType: %s\n", Guid);
652 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionId), Guid);
653 DbgPrint(" PartitionId: %s\n", Guid);
654 DbgPrint(" Attributes: %I64x\n", PartitionEntry->Gpt.Attributes);
655 DbgPrint(" Name: %ws\n", PartitionEntry->Gpt.Name);
656 break;
657 }
658
659 default:
660 DbgPrint(" Unsupported partition style: %ld\n", PartitionEntry->PartitionStyle);
661 }
662}
663
664#else
665#define FstubDbgPrintDriveLayoutEx(DriveLayout)
666#define FstubDbgPrintSetPartitionEx(PartitionEntry, PartitionNumber)
667#endif // !NDEBUG
668
670NTAPI
672 IN PARTITION_STYLE * PartitionStyle)
673{
675 PPARTITION_DESCRIPTOR PartitionDescriptor;
676
677 PAGED_CODE();
678
680 ASSERT(PartitionStyle);
681
682 /* Read disk first sector */
683 Status = FstubReadSector(Disk->DeviceObject,
684 Disk->SectorSize,
685 0,
686 Disk->Buffer);
687 if (!NT_SUCCESS(Status))
688 {
689 return Status;
690 }
691
692 /* Get the partition descriptor array */
693 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Disk->Buffer[PARTITION_TABLE_OFFSET];
694 /* If we have not the 0xAA55 then it's raw partition */
696 {
697 *PartitionStyle = PARTITION_STYLE_RAW;
698 }
699 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
700 else if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
701 PartitionDescriptor[1].PartitionType == 0 &&
702 PartitionDescriptor[2].PartitionType == 0 &&
703 PartitionDescriptor[3].PartitionType == 0)
704 {
705 *PartitionStyle = PARTITION_STYLE_GPT;
706 }
707 /* Otherwise, partition table is in MBR */
708 else
709 {
710 *PartitionStyle = PARTITION_STYLE_MBR;
711 }
712
713 return STATUS_SUCCESS;
714}
715
716VOID
717NTAPI
719{
720 if (DiskBuffer)
721 {
722 if (DiskBuffer->Buffer)
723 {
724 ExFreePoolWithTag(DiskBuffer->Buffer, TAG_FSTUB);
725 }
726 ExFreePoolWithTag(DiskBuffer, TAG_FSTUB);
727 }
728}
729
731NTAPI
733 OUT PDISK_GEOMETRY_EX Geometry)
734{
736 PIRP Irp;
738 PDISK_GEOMETRY_EX DiskGeometry = NULL;
740
741 PAGED_CODE();
742
744 ASSERT(Geometry);
745
746 /* Allocate needed components */
748 if (!DiskGeometry)
749 {
751 goto Cleanup;
752 }
753
755 if (!IoStatusBlock)
756 {
758 goto Cleanup;
759 }
760
762 if (!Event)
763 {
765 goto Cleanup;
766 }
767 /* Initialize the waiting event */
769
770 /* Build the request to get disk geometry */
773 0,
774 0,
775 DiskGeometry,
776 sizeof(DISK_GEOMETRY_EX),
777 FALSE,
778 Event,
780 if (!Irp)
781 {
783 goto Cleanup;
784 }
785
786 /* Call the driver and wait for completion if needed */
788 if (Status == STATUS_PENDING)
789 {
792 }
793
794 /* In case of a success, return read data */
795 if (NT_SUCCESS(Status))
796 {
797 *Geometry = *DiskGeometry;
798 }
799
800Cleanup:
801 if (DiskGeometry)
802 {
803 ExFreePoolWithTag(DiskGeometry, TAG_FSTUB);
804
805 if (NT_SUCCESS(Status))
806 {
807 ASSERT(Geometry->Geometry.BytesPerSector % PARTITION_ENTRY_SIZE == 0);
808 }
809 }
810
811 if (IoStatusBlock)
812 {
814 }
815
816 if (Event)
817 {
819 }
820
821 return Status;
822}
823
825NTAPI
827 IN BOOLEAN ReadBackupTable,
828 PEFI_PARTITION_HEADER * HeaderBuffer)
829{
831 PUCHAR Sector = NULL;
832 ULONGLONG StartingSector;
833 PEFI_PARTITION_HEADER EFIHeader;
834 ULONG i, HeaderCRC32, PreviousCRC32, SectoredPartitionEntriesSize, LonelyPartitions;
835
836 PAGED_CODE();
837
838 ASSERT(Disk);
840 ASSERT(HeaderBuffer);
841
842 /* In case we want to read backup table, we read last disk sector */
843 if (ReadBackupTable)
844 {
845 StartingSector = Disk->SectorCount - 1ULL;
846 }
847 else
848 {
849 /* Otherwise we start at first sector (as sector 0 is the MBR) */
850 StartingSector = 1ULL;
851 }
852
853 Status = FstubReadSector(Disk->DeviceObject,
854 Disk->SectorSize,
855 StartingSector,
856 Disk->Buffer);
857 if (!NT_SUCCESS(Status))
858 {
859 DPRINT("EFI::Failed reading header!\n");
860 return Status;
861 }
862 /* Let's use read buffer as EFI_PARTITION_HEADER */
863 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
864
865
866 /* First check signature
867 * Then, check version (we only support v1)
868 * Finally check header size
869 */
870 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
871 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
872 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
873 {
874 DPRINT("EFI::Wrong signature/version/header size!\n");
875 DPRINT("%I64x (expected: %I64x)\n", EFIHeader->Signature, EFI_HEADER_SIGNATURE);
876 DPRINT("%03x (expected: %03x)\n", EFIHeader->Revision, EFI_HEADER_REVISION_1);
877 DPRINT("%02x (expected: %02x)\n", EFIHeader->HeaderSize, sizeof(EFI_PARTITION_HEADER));
879 }
880
881 /* Save current checksum */
882 HeaderCRC32 = EFIHeader->HeaderCRC32;
883 /* Then zero the one in EFI header. This is needed to compute header checksum */
884 EFIHeader->HeaderCRC32 = 0;
885 /* Compute header checksum and compare with the one present in partition table */
886 if (RtlComputeCrc32(0, Disk->Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
887 {
888 DPRINT("EFI::Not matching header checksum!\n");
890 }
891 /* Put back removed checksum in header */
892 EFIHeader->HeaderCRC32 = HeaderCRC32;
893
894 /* Check if current LBA is matching with ours */
895 if (EFIHeader->MyLBA != StartingSector)
896 {
897 DPRINT("EFI::Not matching starting sector!\n");
899 }
900
901 /* Allocate a buffer to read a sector on the disk */
903 Disk->SectorSize,
904 TAG_FSTUB);
905 if (!Sector)
906 {
907 DPRINT("EFI::Lacking resources!\n");
909 }
910
911 /* Count how much sectors we'll have to read to read the whole partition table */
912 SectoredPartitionEntriesSize = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
913 /* Compute partition table checksum */
914 for (i = 0, PreviousCRC32 = 0; i < SectoredPartitionEntriesSize; i++)
915 {
916 Status = FstubReadSector(Disk->DeviceObject,
917 Disk->SectorSize,
918 EFIHeader->PartitionEntryLBA + i,
919 Sector);
920 if (!NT_SUCCESS(Status))
921 {
923 DPRINT("EFI::Failed reading sector for partition entry!\n");
924 return Status;
925 }
926
927 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector, Disk->SectorSize);
928 }
929
930 /* Check whether we have a last sector not full of partitions */
931 LonelyPartitions = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) % Disk->SectorSize;
932 /* In such case, we have to complete checksum computation */
933 if (LonelyPartitions != 0)
934 {
935 /* Read the sector that contains those partitions */
936 Status = FstubReadSector(Disk->DeviceObject,
937 Disk->SectorSize,
938 EFIHeader->PartitionEntryLBA + i,
939 Sector);
940 if (!NT_SUCCESS(Status))
941 {
943 DPRINT("EFI::Failed reading sector for partition entry!\n");
944 return Status;
945 }
946
947 /* Then complete checksum by computing on each partition */
948 for (i = 0; i < LonelyPartitions; i++)
949 {
950 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector + i * PARTITION_ENTRY_SIZE, PARTITION_ENTRY_SIZE);
951 }
952 }
953
954 /* Finally, release memory */
956
957 /* Compare checksums */
958 if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
959 {
960 /* In case of a success, return read header */
961 *HeaderBuffer = EFIHeader;
962 return STATUS_SUCCESS;
963 }
964 else
965 {
966 DPRINT("EFI::Not matching partition table checksum!\n");
967 DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
969 }
970}
971
973NTAPI
975 IN BOOLEAN ReadBackupTable,
976 OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
977{
979 ULONG NumberOfEntries;
980 PEFI_PARTITION_HEADER EfiHeader;
981 EFI_PARTITION_ENTRY PartitionEntry;
982#if 0
983 BOOLEAN UpdatedPartitionTable = FALSE;
984 ULONGLONG SectorsForPartitions, PartitionEntryLBA;
985#else
986 ULONGLONG PartitionEntryLBA;
987#endif
988 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
990 ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
991
992 PAGED_CODE();
993
994 ASSERT(Disk);
995
996 /* Zero output */
997 *DriveLayout = NULL;
998
999 /* Read EFI header */
1001 ReadBackupTable,
1002 &EfiHeader);
1003 if (!NT_SUCCESS(Status))
1004 {
1005 return Status;
1006 }
1007
1008 /* Backup the number of entries, will be used later on */
1009 NumberOfEntries = EfiHeader->NumberOfEntries;
1010
1011 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1012 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1013 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1014 EfiHeader->NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
1015 TAG_FSTUB);
1016 if (!DriveLayoutEx)
1017 {
1019 }
1020
1021#if 0
1022 if (!ReadBackupTable)
1023 {
1024 /* If we weren't ask to read backup table,
1025 * check the status of the backup table.
1026 * In case it's not where we're expecting it, move it and ask
1027 * for a partition table rewrite.
1028 */
1029 if ((Disk->SectorCount - 1ULL) != EfiHeader->AlternateLBA)
1030 {
1031 /* We'll update it. First, count number of sectors needed to store partitions */
1032 SectorsForPartitions = ((ULONGLONG)EfiHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1033 /* Then set first usable LBA: Legacy MBR + GPT header + Partitions entries */
1034 EfiHeader->FirstUsableLBA = SectorsForPartitions + 2;
1035 /* Then set last usable LBA: Last sector - GPT header - Partitions entries */
1036 EfiHeader->LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
1037 /* Inform that we'll rewrite partition table */
1038 UpdatedPartitionTable = TRUE;
1039 }
1040 }
1041#endif
1042
1043 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_GPT;
1044 /* Translate LBA -> Offset */
1045 DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader->FirstUsableLBA * Disk->SectorSize;
1046 DriveLayoutEx->Gpt.UsableLength.QuadPart = (EfiHeader->LastUsableLBA - EfiHeader->FirstUsableLBA) * Disk->SectorSize;
1047 DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader->NumberOfEntries;
1048 DriveLayoutEx->Gpt.DiskId = EfiHeader->DiskGUID;
1049
1050 /* Backup partition entry position */
1051 PartitionEntryLBA = EfiHeader->PartitionEntryLBA;
1052 /* Count number of partitions per sector */
1053 PartitionsPerSector = (Disk->SectorSize / PARTITION_ENTRY_SIZE);
1054 /* Read all partitions and fill in structure
1055 * BEWARE! Past that point EfiHeader IS NOT VALID ANYMORE
1056 * It will be erased by the reading of the partition entry
1057 */
1058 for (i = 0, PartitionCount = 0, PartitionIndex = PartitionsPerSector;
1059 i < NumberOfEntries;
1060 i++)
1061 {
1062 /* Only read following sector if we finished with previous sector */
1063 if (PartitionIndex == PartitionsPerSector)
1064 {
1065 Status = FstubReadSector(Disk->DeviceObject,
1066 Disk->SectorSize,
1067 PartitionEntryLBA + (i / PartitionsPerSector),
1068 Disk->Buffer);
1069 if (!NT_SUCCESS(Status))
1070 {
1071 ExFreePoolWithTag(DriveLayoutEx, TAG_FSTUB);
1072 return Status;
1073 }
1074
1075 PartitionIndex = 0;
1076 }
1077 /* Read following partition */
1078 PartitionEntry = ((PEFI_PARTITION_ENTRY)Disk->Buffer)[PartitionIndex];
1079 PartitionIndex++;
1080
1081 /* Skip unused partition */
1082 if (IsEqualGUID(&PartitionEntry.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
1083 continue;
1084
1085 /* Write data to structure. Don't forget GPT is using sectors, Windows offsets */
1086 PartitionInfo = &DriveLayoutEx->PartitionEntry[PartitionCount];
1087
1088 PartitionInfo->StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
1089 PartitionInfo->PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
1090 PartitionEntry.StartingLBA + 1) * Disk->SectorSize;
1091 /* This number starts from 1 */
1092 PartitionInfo->PartitionNumber = PartitionCount + 1;
1093 PartitionInfo->RewritePartition = FALSE;
1094 PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT;
1095 PartitionInfo->Gpt.PartitionType = PartitionEntry.PartitionType;
1096 PartitionInfo->Gpt.PartitionId = PartitionEntry.UniquePartition;
1097 PartitionInfo->Gpt.Attributes = PartitionEntry.Attributes;
1098 RtlCopyMemory(PartitionInfo->Gpt.Name,
1099 PartitionEntry.Name, sizeof(PartitionEntry.Name));
1100
1101 /* Update partition count */
1102 PartitionCount++;
1103 }
1104 DriveLayoutEx->PartitionCount = PartitionCount;
1105
1106#if 0
1107 /* If we updated partition table using backup table, rewrite partition table */
1108 if (UpdatedPartitionTable)
1109 {
1110 IoWritePartitionTableEx(Disk->DeviceObject,
1111 DriveLayoutEx);
1112 }
1113#endif
1114
1115 /* Finally, return read data */
1116 *DriveLayout = DriveLayoutEx;
1117
1118 return Status;
1119}
1120
1122NTAPI
1125 OUT PDRIVE_LAYOUT_INFORMATION_EX* ReturnedDriveLayout)
1126{
1128 ULONG i;
1129 PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
1130 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
1131
1132 PAGED_CODE();
1133
1135 ASSERT(ReturnedDriveLayout);
1136
1137 /* Zero output */
1138 *ReturnedDriveLayout = NULL;
1139
1140 /* Read partition table the old way */
1141 Status = IoReadPartitionTable(Disk->DeviceObject,
1142 Disk->SectorSize,
1144 &DriveLayout);
1145 if (!NT_SUCCESS(Status))
1146 {
1147 return Status;
1148 }
1149
1150 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1151 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1152 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1153 DriveLayout->PartitionCount * sizeof(PARTITION_INFORMATION_EX),
1154 TAG_FSTUB);
1155 if (!DriveLayoutEx)
1156 {
1157 /* Let's not leak memory as in Windows 2003 */
1158 ExFreePool(DriveLayout);
1160 }
1161
1162 /* Start converting the DRIVE_LAYOUT_INFORMATION structure */
1163 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
1164 DriveLayoutEx->PartitionCount = DriveLayout->PartitionCount;
1165 DriveLayoutEx->Mbr.Signature = DriveLayout->Signature;
1166
1167 /* Convert each found partition */
1168 for (i = 0; i < DriveLayout->PartitionCount; i++)
1169 {
1170 DriveLayoutEx->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
1171 DriveLayoutEx->PartitionEntry[i].StartingOffset = DriveLayout->PartitionEntry[i].StartingOffset;
1172 DriveLayoutEx->PartitionEntry[i].PartitionLength = DriveLayout->PartitionEntry[i].PartitionLength;
1173 DriveLayoutEx->PartitionEntry[i].PartitionNumber = DriveLayout->PartitionEntry[i].PartitionNumber;
1174 DriveLayoutEx->PartitionEntry[i].RewritePartition = DriveLayout->PartitionEntry[i].RewritePartition;
1175 DriveLayoutEx->PartitionEntry[i].Mbr.PartitionType = DriveLayout->PartitionEntry[i].PartitionType;
1176 DriveLayoutEx->PartitionEntry[i].Mbr.BootIndicator = DriveLayout->PartitionEntry[i].BootIndicator;
1177 DriveLayoutEx->PartitionEntry[i].Mbr.RecognizedPartition = DriveLayout->PartitionEntry[i].RecognizedPartition;
1178 DriveLayoutEx->PartitionEntry[i].Mbr.HiddenSectors = DriveLayout->PartitionEntry[i].HiddenSectors;
1179 }
1180
1181 /* Finally, return data and free old structure */
1182 *ReturnedDriveLayout = DriveLayoutEx;
1183 ExFreePool(DriveLayout);
1184
1185 return STATUS_SUCCESS;
1186}
1187
1189NTAPI
1192 IN ULONGLONG StartingSector OPTIONAL,
1194{
1196 PIRP Irp;
1197 KEVENT Event;
1201
1202 PAGED_CODE();
1203
1205 ASSERT(Buffer);
1207
1208 /* Compute starting offset */
1209 StartingOffset.QuadPart = StartingSector * SectorSize;
1210
1211 /* Initialize waiting event */
1213
1214 /* Prepare IRP */
1217 Buffer,
1218 SectorSize,
1220 &Event,
1221 &IoStatusBlock);
1222 if (!Irp)
1223 {
1225 }
1226
1227 /* Override volume verify */
1230
1231 /* Then call driver, and wait for completion if needed */
1233 if (Status == STATUS_PENDING)
1234 {
1237 }
1238
1239 return Status;
1240}
1241
1243NTAPI
1246 IN SET_PARTITION_INFORMATION_GPT * PartitionInfo)
1247{
1249 PDRIVE_LAYOUT_INFORMATION_EX Layout = NULL;
1250
1251 PAGED_CODE();
1252
1253 ASSERT(Disk);
1255
1256 /* Partition 0 isn't correct (should start at 1) */
1257 if (PartitionNumber == 0)
1258 {
1260 }
1261
1262 /* Read partition table */
1263 Status = IoReadPartitionTableEx(Disk->DeviceObject, &Layout);
1264 if (!NT_SUCCESS(Status))
1265 {
1266 return Status;
1267 }
1268 ASSERT(Layout);
1269
1270 /* If our partition (started at 0 now) is higher than partition count, then, there's an issue */
1271 if (Layout->PartitionCount <= --PartitionNumber)
1272 {
1273 ExFreePool(Layout);
1275 }
1276
1277 /* Erase actual partition entry data with provided ones */
1278 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionType = PartitionInfo->PartitionType;
1279 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionId = PartitionInfo->PartitionId;
1280 Layout->PartitionEntry[PartitionNumber].Gpt.Attributes = PartitionInfo->Attributes;
1281 RtlCopyMemory(Layout->PartitionEntry[PartitionNumber].Gpt.Name, PartitionInfo->Name, sizeof(PartitionInfo->Name));
1282
1283 /* Rewrite the whole partition table to update the modified entry */
1284 Status = IoWritePartitionTableEx(Disk->DeviceObject, Layout);
1285
1286 /* Free partition table and return */
1287 ExFreePool(Layout);
1288 return Status;
1289}
1290
1292NTAPI
1295{
1297 PEFI_PARTITION_HEADER EFIHeader, ReadEFIHeader;
1298 BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE, WriteBackup;
1299 ULONGLONG ReadPosition, WritePosition, SectorsForPartitions, PartitionIndex;
1300
1301 PAGED_CODE();
1302
1304 if (!EFIHeader)
1305 {
1307 }
1308
1309 Status = FstubReadHeaderEFI(Disk, FALSE, &ReadEFIHeader);
1310 if (NT_SUCCESS(Status))
1311 {
1312 PrimaryValid = TRUE;
1313 ASSERT(ReadEFIHeader);
1314 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1315 }
1316
1317 Status = FstubReadHeaderEFI(Disk, TRUE, &ReadEFIHeader);
1318 if (NT_SUCCESS(Status))
1319 {
1320 BackupValid = TRUE;
1321 ASSERT(ReadEFIHeader);
1322 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1323 }
1324
1325 /* If both are sane, just return */
1326 if (PrimaryValid && BackupValid)
1327 {
1328 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1329 return STATUS_SUCCESS;
1330 }
1331
1332 /* If both are damaged OR if we have not been ordered to fix
1333 * Then, quit and warn about disk corruption
1334 */
1335 if ((!PrimaryValid && !BackupValid) || !FixErrors)
1336 {
1337 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1339 }
1340
1341 /* Compute sectors taken by partitions */
1342 SectorsForPartitions = (((ULONGLONG)EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) + Disk->SectorSize - 1) / Disk->SectorSize;
1343 if (PrimaryValid)
1344 {
1345 WriteBackup = TRUE;
1346 /* Take position at backup table for writing */
1347 WritePosition = Disk->SectorCount - SectorsForPartitions;
1348 /* And read from primary table */
1349 ReadPosition = 2ULL;
1350
1351 DPRINT("EFI::Will repair backup table from primary\n");
1352 }
1353 else
1354 {
1355 ASSERT(BackupValid);
1356 WriteBackup = FALSE;
1357 /* Take position at primary table for writing */
1358 WritePosition = 2ULL;
1359 /* And read from backup table */
1360 ReadPosition = Disk->SectorCount - SectorsForPartitions;
1361
1362 DPRINT("EFI::Will repair primary table from backup\n");
1363 }
1364
1365 PartitionIndex = 0ULL;
1366
1367 /* If no partitions are to be copied, just restore header */
1368 if (SectorsForPartitions <= 0)
1369 {
1371 SectorsForPartitions,
1372 EFIHeader->DiskGUID,
1373 EFIHeader->NumberOfEntries,
1374 EFIHeader->FirstUsableLBA,
1375 EFIHeader->LastUsableLBA,
1376 EFIHeader->PartitionEntryCRC32,
1377 WriteBackup);
1378
1379 goto Cleanup;
1380 }
1381
1382 /* Copy all the partitions */
1383 for (; PartitionIndex < SectorsForPartitions; ++PartitionIndex)
1384 {
1385 /* First, read the partition from the first table */
1386 Status = FstubReadSector(Disk->DeviceObject,
1387 Disk->SectorSize,
1388 ReadPosition + PartitionIndex,
1389 Disk->Buffer);
1390 if (!NT_SUCCESS(Status))
1391 {
1392 goto Cleanup;
1393 }
1394
1395 /* Then, write it in the other table */
1396 Status = FstubWriteSector(Disk->DeviceObject,
1397 Disk->SectorSize,
1398 WritePosition + PartitionIndex,
1399 Disk->Buffer);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 goto Cleanup;
1403 }
1404 }
1405
1406 /* Now we're done, write the header */
1408 SectorsForPartitions,
1409 EFIHeader->DiskGUID,
1410 EFIHeader->NumberOfEntries,
1411 EFIHeader->FirstUsableLBA,
1412 EFIHeader->LastUsableLBA,
1413 EFIHeader->PartitionEntryCRC32,
1414 WriteBackup);
1415
1416Cleanup:
1417 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1418 return Status;
1419}
1420
1422NTAPI
1424{
1426 ULONG Signature = 0;
1427 PMASTER_BOOT_RECORD MasterBootRecord;
1428
1429 PAGED_CODE();
1430
1431 ASSERT(Disk);
1433
1434 /* Read if a MBR is already present */
1435 Status = FstubReadSector(Disk->DeviceObject,
1436 Disk->SectorSize,
1437 0ULL,
1438 Disk->Buffer);
1439 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
1440 /* If one has been found */
1442 {
1443 /* Save its signature */
1444 Signature = MasterBootRecord->Signature;
1445 }
1446
1447 /* Reset the MBR */
1448 RtlZeroMemory(MasterBootRecord, Disk->SectorSize);
1449 /* Then create a fake MBR matching those purposes:
1450 * It must have only partition. Type of this partition
1451 * has to be 0xEE to signal a GPT is following.
1452 * This partition has to cover the whole disk. To prevent
1453 * any disk modification by a program that wouldn't
1454 * understand anything to GPT.
1455 */
1456 MasterBootRecord->Signature = Signature;
1457 MasterBootRecord->PartitionTable[0].StartSector = 2;
1458 MasterBootRecord->PartitionTable[0].SystemIndicator = EFI_PMBR_OSTYPE_EFI;
1459 MasterBootRecord->PartitionTable[0].EndHead = 0xFF;
1460 MasterBootRecord->PartitionTable[0].EndSector = 0xFF;
1461 MasterBootRecord->PartitionTable[0].EndCylinder = 0xFF;
1462 MasterBootRecord->PartitionTable[0].SectorCountBeforePartition = 1;
1463 MasterBootRecord->PartitionTable[0].PartitionSectorCount = 0xFFFFFFFF;
1464 MasterBootRecord->MasterBootRecordMagic = BOOT_RECORD_SIGNATURE;
1465
1466 /* Finally, write that MBR */
1467 return FstubWriteSector(Disk->DeviceObject,
1468 Disk->SectorSize,
1469 0,
1470 Disk->Buffer);
1471}
1472
1474NTAPI
1476 IN ULONG PartitionsSizeSector,
1477 IN ULONG PartitionEntryNumber,
1478 IN PEFI_PARTITION_ENTRY PartitionEntry,
1479 IN BOOLEAN WriteBackupTable,
1480 IN BOOLEAN ForceWrite,
1481 OUT PULONG PartitionEntryCRC32 OPTIONAL)
1482{
1484 ULONG Offset;
1485 ULONGLONG FirstEntryLBA;
1486
1487 PAGED_CODE();
1488
1489 ASSERT(Disk);
1491
1492 /* Get the first LBA where the partition table is:
1493 * On primary table, it's sector 2 (skip MBR & Header)
1494 * On backup table, it's ante last sector (Header) minus partition table size
1495 */
1496 if (!WriteBackupTable)
1497 {
1498 FirstEntryLBA = 2ULL;
1499 }
1500 else
1501 {
1502 FirstEntryLBA = Disk->SectorCount - PartitionsSizeSector - 1;
1503 }
1504
1505 /* Copy the entry at the proper place into the buffer
1506 * That way, we don't erase previous entries
1507 */
1508 RtlCopyMemory((PVOID)((ULONG_PTR)Disk->Buffer + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize)),
1509 PartitionEntry,
1510 sizeof(EFI_PARTITION_ENTRY));
1511 /* Compute size of buffer */
1512 Offset = (PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize + PARTITION_ENTRY_SIZE;
1513 ASSERT(Offset <= Disk->SectorSize);
1514
1515 /* If it's full of partition entries, or if call ask for it, write down the data */
1516 if (Offset == Disk->SectorSize || ForceWrite)
1517 {
1518 /* We will write at first entry LBA + a shift made by already present/written entries */
1519 Status = FstubWriteSector(Disk->DeviceObject,
1520 Disk->SectorSize,
1521 FirstEntryLBA + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) / Disk->SectorSize),
1522 Disk->Buffer);
1523 if (!NT_SUCCESS(Status))
1524 {
1525 return Status;
1526 }
1527
1528 /* We clean buffer */
1529 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
1530 }
1531
1532 /* If we have a buffer for CRC32, then compute it */
1533 if (PartitionEntryCRC32)
1534 {
1535 *PartitionEntryCRC32 = RtlComputeCrc32(*PartitionEntryCRC32, (PUCHAR)PartitionEntry, PARTITION_ENTRY_SIZE);
1536 }
1537
1538 return Status;
1539}
1540
1542NTAPI
1544 IN ULONG PartitionsSizeSector,
1545 IN GUID DiskGUID,
1546 IN ULONG NumberOfEntries,
1547 IN ULONGLONG FirstUsableLBA,
1548 IN ULONGLONG LastUsableLBA,
1549 IN ULONG PartitionEntryCRC32,
1550 IN BOOLEAN WriteBackupTable)
1551{
1552 PEFI_PARTITION_HEADER EFIHeader;
1553
1554 PAGED_CODE();
1555
1556 ASSERT(Disk);
1558
1559 /* Let's use read buffer as EFI_PARTITION_HEADER */
1560 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
1561
1562 /* Complete standard header information */
1563 EFIHeader->Signature = EFI_HEADER_SIGNATURE;
1564 EFIHeader->Revision = EFI_HEADER_REVISION_1;
1565 EFIHeader->HeaderSize = sizeof(EFI_PARTITION_HEADER);
1566 /* Set no CRC32 checksum at the moment */
1567 EFIHeader->HeaderCRC32 = 0;
1568 EFIHeader->Reserved = 0;
1569 /* Check whether we're writing primary or backup
1570 * That way, we can ajust LBA setting:
1571 * Primary is on first sector
1572 * Backup is on last sector
1573 */
1574 if (!WriteBackupTable)
1575 {
1576 EFIHeader->MyLBA = 1ULL;
1577 EFIHeader->AlternateLBA = Disk->SectorCount - 1ULL;
1578 }
1579 else
1580 {
1581 EFIHeader->MyLBA = Disk->SectorCount - 1ULL;
1582 EFIHeader->AlternateLBA = 1ULL;
1583 }
1584 /* Fill in with received data */
1585 EFIHeader->FirstUsableLBA = FirstUsableLBA;
1586 EFIHeader->LastUsableLBA = LastUsableLBA;
1587 EFIHeader->DiskGUID = DiskGUID;
1588 /* Check whether we're writing primary or backup
1589 * That way, we can ajust LBA setting:
1590 * On primary, partition entries are just after header, so sector 2
1591 * On backup, partition entries are just before header, so, last sector minus partition table size
1592 */
1593 if (!WriteBackupTable)
1594 {
1595 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA + 1ULL;
1596 }
1597 else
1598 {
1599 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA - PartitionsSizeSector;
1600 }
1601 /* Complete filling in */
1602 EFIHeader->NumberOfEntries = NumberOfEntries;
1604 EFIHeader->PartitionEntryCRC32 = PartitionEntryCRC32;
1605 /* Finally, compute header checksum */
1606 EFIHeader->HeaderCRC32 = RtlComputeCrc32(0, (PUCHAR)EFIHeader, sizeof(EFI_PARTITION_HEADER));
1607
1608 /* Debug the way we'll break disk, to let user pray */
1609 DPRINT("FSTUB: About to write the following header for %s table\n", (WriteBackupTable ? "backup" : "primary"));
1610 DPRINT(" Signature: %I64x\n", EFIHeader->Signature);
1611 DPRINT(" Revision: %x\n", EFIHeader->Revision);
1612 DPRINT(" HeaderSize: %x\n", EFIHeader->HeaderSize);
1613 DPRINT(" HeaderCRC32: %x\n", EFIHeader->HeaderCRC32);
1614 DPRINT(" MyLBA: %I64x\n", EFIHeader->MyLBA);
1615 DPRINT(" AlternateLBA: %I64x\n", EFIHeader->AlternateLBA);
1616 DPRINT(" FirstUsableLBA: %I64x\n", EFIHeader->FirstUsableLBA);
1617 DPRINT(" LastUsableLBA: %I64x\n", EFIHeader->LastUsableLBA);
1618 DPRINT(" PartitionEntryLBA: %I64x\n", EFIHeader->PartitionEntryLBA);
1619 DPRINT(" NumberOfEntries: %x\n", EFIHeader->NumberOfEntries);
1620 DPRINT(" SizeOfPartitionEntry: %x\n", EFIHeader->SizeOfPartitionEntry);
1621 DPRINT(" PartitionEntryCRC32: %x\n", EFIHeader->PartitionEntryCRC32);
1622
1623 /* Write header to disk */
1624 return FstubWriteSector(Disk->DeviceObject,
1625 Disk->SectorSize,
1626 EFIHeader->MyLBA,
1627 Disk->Buffer);
1628}
1629
1631NTAPI
1633 IN GUID DiskGUID,
1634 IN ULONG MaxPartitionCount,
1635 IN ULONGLONG FirstUsableLBA,
1636 IN ULONGLONG LastUsableLBA,
1637 IN BOOLEAN WriteBackupTable,
1638 IN ULONG PartitionCount,
1639 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
1640{
1643 ULONG i, WrittenPartitions, SectoredPartitionEntriesSize, PartitionEntryCRC32;
1644
1645 PAGED_CODE();
1646
1647 ASSERT(Disk);
1648 ASSERT(MaxPartitionCount >= 128);
1649 ASSERT(PartitionCount <= MaxPartitionCount);
1650
1651 PartitionEntryCRC32 = 0;
1652 /* Count how much sectors we'll have to read to read the whole partition table */
1653 SectoredPartitionEntriesSize = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1654
1655 for (i = 0, WrittenPartitions = 0; i < PartitionCount; i++)
1656 {
1657 /* Skip unused partition */
1658 if (IsEqualGUID(&PartitionEntries[i].Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
1659 continue;
1660
1661 /* Copy the entry in the partition entry format */
1662 FstubCopyEntryEFI(&Entry, &PartitionEntries[i], Disk->SectorSize);
1663 /* Then write the entry to the disk */
1665 SectoredPartitionEntriesSize,
1666 WrittenPartitions,
1667 &Entry,
1668 WriteBackupTable,
1669 FALSE,
1670 &PartitionEntryCRC32);
1671 if (!NT_SUCCESS(Status))
1672 {
1673 return Status;
1674 }
1675 WrittenPartitions++;
1676 }
1677
1678 /* Zero the buffer to write zeros to the disk */
1680 /* Write the disks with zeros for every unused remaining partition entry */
1681 for (i = WrittenPartitions; i < MaxPartitionCount; i++)
1682 {
1684 SectoredPartitionEntriesSize,
1685 i,
1686 &Entry,
1687 WriteBackupTable,
1688 FALSE,
1689 &PartitionEntryCRC32);
1690 if (!NT_SUCCESS(Status))
1691 {
1692 return Status;
1693 }
1694 }
1695
1696 /* Once we're done, write the GPT header */
1697 return FstubWriteHeaderEFI(Disk,
1698 SectoredPartitionEntriesSize,
1699 DiskGUID,
1700 MaxPartitionCount,
1701 FirstUsableLBA,
1702 LastUsableLBA,
1703 PartitionEntryCRC32,
1704 WriteBackupTable);
1705}
1706
1708NTAPI
1710 IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
1711{
1713 PDRIVE_LAYOUT_INFORMATION DriveLayout;
1714
1715 PAGED_CODE();
1716
1718 ASSERT(LayoutEx);
1719
1720 /* Convert data to the correct format */
1721 DriveLayout = FstubConvertExtendedToLayout(LayoutEx);
1722 if (!DriveLayout)
1723 {
1725 }
1726
1727 /* Really write information */
1728 Status = IoWritePartitionTable(Disk->DeviceObject,
1729 Disk->SectorSize,
1730 Disk->DiskGeometry.Geometry.SectorsPerTrack,
1731 Disk->DiskGeometry.Geometry.TracksPerCylinder,
1732 DriveLayout);
1733
1734 /* Free allocated structure and return */
1735 ExFreePoolWithTag(DriveLayout, TAG_FSTUB);
1736 return Status;
1737}
1738
1740NTAPI
1743 IN ULONGLONG StartingSector OPTIONAL,
1744 IN PVOID Buffer)
1745{
1747 PIRP Irp;
1748 KEVENT Event;
1752
1753 PAGED_CODE();
1754
1756 ASSERT(Buffer);
1758
1759 /* Compute starting offset */
1760 StartingOffset.QuadPart = StartingSector * SectorSize;
1761
1762 /* Initialize waiting event */
1764
1765 /* Prepare IRP */
1768 Buffer,
1769 SectorSize,
1771 &Event,
1772 &IoStatusBlock);
1773 if (!Irp)
1774 {
1776 }
1777
1778 /* Override volume verify */
1781
1782 /* Then call driver, and wait for completion if needed */
1784 if (Status == STATUS_PENDING)
1785 {
1788 }
1789
1790 return Status;
1791}
1792
1793/* PUBLIC FUNCTIONS **********************************************************/
1794
1795/*
1796 * @implemented
1797 */
1799NTAPI
1801 IN PCREATE_DISK Disk)
1802{
1803 PARTITION_STYLE PartitionStyle;
1804
1805 PAGED_CODE();
1806
1808
1809 /* Get partition style. If caller didn't provided data, assume it's raw */
1810 PartitionStyle = ((Disk) ? Disk->PartitionStyle : PARTITION_STYLE_RAW);
1811 /* Then, call appropriate internal function */
1812 switch (PartitionStyle)
1813 {
1815 return FstubCreateDiskMBR(DeviceObject, &(Disk->Mbr));
1817 return FstubCreateDiskEFI(DeviceObject, &(Disk->Gpt));
1818 case PARTITION_STYLE_RAW:
1820 default:
1821 return STATUS_NOT_SUPPORTED;
1822 }
1823}
1824
1825/*
1826 * @implemented
1827 */
1829NTAPI
1831 IN ULONG Size)
1832{
1834 PIRP Irp;
1835 KEVENT Event;
1836 PLIST_ENTRY NextEntry;
1838 DISK_GEOMETRY DiskGeometry;
1840 UNICODE_STRING DeviceStringW;
1842 CHAR Buffer[128], ArcBuffer[128];
1843 BOOLEAN SingleDisk, IsBootDiskInfoEx;
1844 PARC_DISK_SIGNATURE ArcDiskSignature;
1845 PARC_DISK_INFORMATION ArcDiskInformation;
1846 PARTITION_INFORMATION_EX PartitionInformation;
1847 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
1848 ULONG DiskCount, DiskNumber, Signature, PartitionNumber;
1849 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA;
1851
1852 PAGED_CODE();
1853
1854 /* Get loader block. If it's null, we come too late */
1855 if (!IopLoaderBlock)
1856 {
1857 return STATUS_TOO_LATE;
1858 }
1859
1860 /* Check buffer size */
1861 if (Size < sizeof(BOOTDISK_INFORMATION))
1862 {
1864 }
1865
1866 /* Init some useful stuff:
1867 * Get ARC disks information
1868 * Check whether we have a single disk on the machine
1869 * Check received structure size (extended or not?)
1870 * Init boot strings (system/boot)
1871 * Finaly, get disk count
1872 */
1873 ArcDiskInformation = IopLoaderBlock->ArcDiskInformation;
1874 SingleDisk = (ArcDiskInformation->DiskSignatureListHead.Flink->Flink ==
1875 &ArcDiskInformation->DiskSignatureListHead);
1876
1877 IsBootDiskInfoEx = (Size >= sizeof(BOOTDISK_INFORMATION_EX));
1881
1882 /* If no disk, return success */
1883 if (DiskCount == 0)
1884 {
1885 return STATUS_SUCCESS;
1886 }
1887
1888 /* Now, browse all disks */
1889 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
1890 {
1891 /* Create the device name */
1892 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
1893 RtlInitAnsiString(&DeviceStringA, Buffer);
1894 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1895 if (!NT_SUCCESS(Status))
1896 {
1897 continue;
1898 }
1899
1900 /* Get its device object */
1901 Status = IoGetDeviceObjectPointer(&DeviceStringW,
1903 &FileObject,
1904 &DeviceObject);
1905 RtlFreeUnicodeString(&DeviceStringW);
1906 if (!NT_SUCCESS(Status))
1907 {
1908 continue;
1909 }
1910
1911 /* Prepare for getting disk geometry */
1915 NULL,
1916 0,
1917 &DiskGeometry,
1918 sizeof(DiskGeometry),
1919 FALSE,
1920 &Event,
1921 &IoStatusBlock);
1922 if (!Irp)
1923 {
1925 continue;
1926 }
1927
1928 /* Then, call the drive, and wait for it if needed */
1930 if (Status == STATUS_PENDING)
1931 {
1934 }
1935 if (!NT_SUCCESS(Status))
1936 {
1938 continue;
1939 }
1940
1941 /* Read partition table */
1943 &DriveLayout);
1944
1945 /* FileObject, you can go! */
1947
1948 if (!NT_SUCCESS(Status))
1949 {
1950 continue;
1951 }
1952
1953 /* Ensure we have at least 512 bytes per sector */
1954 if (DiskGeometry.BytesPerSector < 512)
1955 {
1956 DiskGeometry.BytesPerSector = 512;
1957 }
1958
1959 /* Now, for each ARC disk, try to find the matching */
1960 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
1961 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
1962 NextEntry = NextEntry->Flink)
1963 {
1964 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
1966 ListEntry);
1967
1968 /*
1969 * If this is the only MBR disk in the ARC list and detected in
1970 * the device tree, just go ahead and retrieve the information.
1971 * Otherwise, verify whether the signatures match before proceeding.
1972 * Note that contrary to IopCreateArcNamesDisk(), we don't verify
1973 * the checksums here.
1974 */
1975 if ((SingleDisk && (DiskCount == 1) &&
1976 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
1977 IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature))
1978 {
1979 /* Create ARC name */
1980 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
1981 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
1982
1983 /* Browse all partitions */
1984 for (PartitionNumber = 1; PartitionNumber <= DriveLayout->PartitionCount; PartitionNumber++)
1985 {
1986 /* Create its device name */
1987 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, PartitionNumber);
1988 RtlInitAnsiString(&DeviceStringA, Buffer);
1989 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1990 if (!NT_SUCCESS(Status))
1991 {
1992 continue;
1993 }
1994
1995 /* If IopVerifyDiskSignature returned no signature, take the one from DriveLayout */
1996 if (!Signature)
1997 {
1998 Signature = DriveLayout->Mbr.Signature;
1999 }
2000
2001 /* Create partial ARC name */
2002 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, PartitionNumber);
2003 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
2004
2005 /* If it's matching boot string */
2006 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
2007 {
2008 /* Then, fill in information about boot device */
2009 BootDiskInformation->BootDeviceSignature = Signature;
2010
2011 /* Get its device object */
2012 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2014 &FileObject,
2015 &DeviceObject);
2016 if (!NT_SUCCESS(Status))
2017 {
2018 RtlFreeUnicodeString(&DeviceStringW);
2019 continue;
2020 }
2021
2022 /* And call the drive to get information about partition */
2026 NULL,
2027 0,
2028 &PartitionInformation,
2029 sizeof(PartitionInformation),
2030 FALSE,
2031 &Event,
2032 &IoStatusBlock);
2033 if (!Irp)
2034 {
2036 RtlFreeUnicodeString(&DeviceStringW);
2037 continue;
2038 }
2039
2040 /* Call & wait if needed */
2042 if (Status == STATUS_PENDING)
2043 {
2046 }
2047 if (!NT_SUCCESS(Status))
2048 {
2050 RtlFreeUnicodeString(&DeviceStringW);
2051 continue;
2052 }
2053
2054 /* We get partition offset as demanded and return it */
2055 BootDiskInformation->BootPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2056
2057 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2058 if (IsBootDiskInfoEx)
2059 {
2060 /* Is partition style MBR or GPT? */
2061 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2062 {
2063 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceGuid = DriveLayout->Gpt.DiskId;
2064 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = TRUE;
2065 }
2066 else
2067 {
2068 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = FALSE;
2069 }
2070 }
2071
2072 /* Dereference FileObject */
2074 }
2075
2076 /* If it's matching system string */
2077 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
2078 {
2079 /* Then, fill in information about the system device */
2080 BootDiskInformation->SystemDeviceSignature = Signature;
2081
2082 /* Get its device object */
2083 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2085 &FileObject,
2086 &DeviceObject);
2087 if (!NT_SUCCESS(Status))
2088 {
2089 RtlFreeUnicodeString(&DeviceStringW);
2090 continue;
2091 }
2092
2093 /* And call the drive to get information about partition */
2097 NULL,
2098 0,
2099 &PartitionInformation,
2100 sizeof(PartitionInformation),
2101 FALSE,
2102 &Event,
2103 &IoStatusBlock);
2104 if (!Irp)
2105 {
2107 RtlFreeUnicodeString(&DeviceStringW);
2108 continue;
2109 }
2110
2111 /* Call & wait if needed */
2113 if (Status == STATUS_PENDING)
2114 {
2117 }
2118 if (!NT_SUCCESS(Status))
2119 {
2121 RtlFreeUnicodeString(&DeviceStringW);
2122 continue;
2123 }
2124
2125 /* We get partition offset as demanded and return it */
2126 BootDiskInformation->SystemPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2127
2128 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2129 if (IsBootDiskInfoEx)
2130 {
2131 /* Is partition style MBR or GPT? */
2132 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2133 {
2134 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceGuid = DriveLayout->Gpt.DiskId;
2135 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = TRUE;
2136 }
2137 else
2138 {
2139 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = FALSE;
2140 }
2141 }
2142
2143 /* Dereference FileObject */
2145 }
2146
2147 /* Release device string */
2148 RtlFreeUnicodeString(&DeviceStringW);
2149 }
2150 }
2151 }
2152
2153 /* Finally, release drive layout */
2154 ExFreePool(DriveLayout);
2155 }
2156
2157 /* And return */
2158 return Status;
2159}
2160
2161/*
2162 * @implemented
2163 */
2165NTAPI
2167 IN ULONG BytesPerSector,
2169{
2171 PUCHAR Buffer;
2172 ULONG HeaderCRC32, i, CheckSum;
2173 PEFI_PARTITION_HEADER EFIHeader;
2174 PPARTITION_DESCRIPTOR PartitionDescriptor;
2175
2176 PAGED_CODE();
2177
2178 /* Ensure we'll read at least 512 bytes */
2179 if (BytesPerSector < 512)
2180 {
2181 BytesPerSector = 512;
2182 }
2183
2184 /* Allocate a buffer for reading operations */
2186 if (!Buffer)
2187 {
2188 return STATUS_NO_MEMORY;
2189 }
2190
2191 /* Read first sector (sector 0) for MBR */
2193 BytesPerSector,
2194 0ULL,
2195 Buffer);
2196 if (!NT_SUCCESS(Status))
2197 {
2198 goto Cleanup;
2199 }
2200
2201 /* Get the partition descriptor array */
2202 PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2204 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
2205 if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
2206 PartitionDescriptor[1].PartitionType == 0 &&
2207 PartitionDescriptor[2].PartitionType == 0 &&
2208 PartitionDescriptor[3].PartitionType == 0)
2209 {
2210 /* If we have GPT, read second sector (sector 1) for GPT header */
2212 BytesPerSector,
2213 1ULL,
2214 Buffer);
2215 if (!NT_SUCCESS(Status))
2216 {
2217 goto Cleanup;
2218 }
2219 EFIHeader = (PEFI_PARTITION_HEADER)Buffer;
2220
2221 /* First check signature
2222 * Then, check version (we only support v1
2223 * Finally check header size
2224 */
2225 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
2226 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
2227 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
2228 {
2230 goto Cleanup;
2231 }
2232
2233 /* Save current checksum */
2234 HeaderCRC32 = EFIHeader->HeaderCRC32;
2235 /* Then zero the one in EFI header. This is needed to compute header checksum */
2236 EFIHeader->HeaderCRC32 = 0;
2237 /* Compute header checksum and compare with the one present in partition table */
2238 if (RtlComputeCrc32(0, Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
2239 {
2241 goto Cleanup;
2242 }
2243
2244 /* Set partition table style to GPT and return disk GUID */
2245 Signature->PartitionStyle = PARTITION_STYLE_GPT;
2246 Signature->Gpt.DiskId = EFIHeader->DiskGUID;
2247 }
2248 else
2249 {
2250 /* Compute MBR checksum */
2251 for (i = 0, CheckSum = 0; i < 512; i += sizeof(UINT32))
2252 {
2253 CheckSum += *(PUINT32)&Buffer[i];
2254 }
2255 CheckSum = ~CheckSum + 1;
2256
2257 /* Set partition table style to MBR and return signature (offset 440) and checksum */
2258 Signature->PartitionStyle = PARTITION_STYLE_MBR;
2259 Signature->Mbr.Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
2260 Signature->Mbr.CheckSum = CheckSum;
2261 }
2262
2263Cleanup:
2264 /* Free buffer and return */
2266 return Status;
2267}
2268
2269/*
2270 * @implemented
2271 */
2273NTAPI
2275 OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
2276{
2278 PDISK_INFORMATION Disk;
2279 PARTITION_STYLE PartitionStyle;
2280
2281 PAGED_CODE();
2282
2284 ASSERT(DriveLayout);
2285
2286 /* First of all, allocate internal structure */
2288 if (!NT_SUCCESS(Status))
2289 {
2290 return Status;
2291 }
2292 ASSERT(Disk);
2293
2294 /* Then, detect partition style (MBR? GPT/EFI? RAW?) */
2295 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2296 if (!NT_SUCCESS(Status))
2297 {
2299 return Status;
2300 }
2301
2302 /* Here partition table is really read, depending on its style */
2303 switch (PartitionStyle)
2304 {
2306 case PARTITION_STYLE_RAW:
2307 Status = FstubReadPartitionTableMBR(Disk, FALSE, DriveLayout);
2308 break;
2309
2311 /* Read primary table */
2312 Status = FstubReadPartitionTableEFI(Disk, FALSE, DriveLayout);
2313 /* If it failed, try reading backup table */
2314 if (!NT_SUCCESS(Status))
2315 {
2316 Status = FstubReadPartitionTableEFI(Disk, TRUE, DriveLayout);
2317 }
2318 break;
2319
2320 default:
2321 DPRINT("Unknown partition type\n");
2323 }
2324
2325 /* It's over, internal structure not needed anymore */
2327
2328 /* In case of success, print data */
2329 if (NT_SUCCESS(Status))
2330 FstubDbgPrintDriveLayoutEx(*DriveLayout);
2331
2332 return Status;
2333}
2334
2335/*
2336 * @implemented
2337 */
2339NTAPI
2342 IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
2343{
2345 PDISK_INFORMATION Disk;
2346 PARTITION_STYLE PartitionStyle;
2347
2348 PAGED_CODE();
2349
2352
2353 /* Debug given modifications */
2355
2356 /* Allocate internal structure */
2358 if (!NT_SUCCESS(Status))
2359 {
2360 return Status;
2361 }
2362
2363 /* Get partition table style on disk */
2364 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2365 if (!NT_SUCCESS(Status))
2366 {
2368 return Status;
2369 }
2370
2371 /* If it's not matching partition style given in modifications, give up */
2372 if (PartitionInfo->PartitionStyle != PartitionStyle)
2373 {
2376 }
2377
2378 /* Finally, handle modifications using proper function */
2379 switch (PartitionStyle)
2380 {
2383 Disk->SectorSize,
2385 PartitionInfo->Mbr.PartitionType);
2386 break;
2390 &(PartitionInfo->Gpt));
2391 break;
2392 default:
2394 }
2395
2396 /* Release internal structure and return */
2398 return Status;
2399}
2400
2401/*
2402 * @implemented
2403 */
2405NTAPI
2408{
2410 PDISK_INFORMATION Disk;
2411 PARTITION_STYLE PartitionStyle;
2412
2413 PAGED_CODE();
2414
2416
2417 /* Allocate internal structure */
2419 if (!NT_SUCCESS(Status))
2420 {
2421 return Status;
2422 }
2423 ASSERT(Disk);
2424
2425 /* Get partition table style on disk */
2426 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2427 if (!NT_SUCCESS(Status))
2428 {
2430 return Status;
2431 }
2432
2433 /* Action will depend on partition style */
2434 switch (PartitionStyle)
2435 {
2436 /* For MBR, assume it's always OK */
2439 break;
2440 /* For GPT, call internal function */
2443 break;
2444 /* Otherwise, signal we can't work */
2445 default:
2447 }
2448
2449 /* Release internal structure and return */
2451 return Status;
2452}
2453
2454/*
2455 * @implemented
2456 */
2458NTAPI
2460 IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
2461{
2463 GUID DiskGuid;
2464 ULONG NumberOfEntries;
2465 PDISK_INFORMATION Disk;
2466 PEFI_PARTITION_HEADER EfiHeader;
2467 ULONGLONG SectorsForPartitions, FirstUsableLBA, LastUsableLBA;
2468
2469 PAGED_CODE();
2470
2472 ASSERT(DriveLayout);
2473
2474 /* Debug partition table that must be written */
2475 FstubDbgPrintDriveLayoutEx(DriveLayout);
2476
2477 /* Allocate internal structure */
2479 if (!NT_SUCCESS(Status))
2480 {
2481 return Status;
2482 }
2483 ASSERT(Disk);
2484
2485 switch (DriveLayout->PartitionStyle)
2486 {
2488 Status = FstubWritePartitionTableMBR(Disk, DriveLayout);
2489 break;
2490
2492 /* Read primary table header */
2494 FALSE,
2495 &EfiHeader);
2496 /* If it failed, try reading back table header */
2497 if (!NT_SUCCESS(Status))
2498 {
2500 TRUE,
2501 &EfiHeader);
2502 }
2503
2504 /* We have a header! */
2505 if (NT_SUCCESS(Status))
2506 {
2507 /* Check if there are enough places for the partitions to be written */
2508 if (DriveLayout->PartitionCount <= EfiHeader->NumberOfEntries)
2509 {
2510 /* Backup data */
2511 NumberOfEntries = EfiHeader->NumberOfEntries;
2512 RtlCopyMemory(&DiskGuid, &EfiHeader->DiskGUID, sizeof(GUID));
2513 /* Count number of sectors needed to store partitions */
2514 SectorsForPartitions = ((ULONGLONG)NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
2515 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
2516 FirstUsableLBA = SectorsForPartitions + 2;
2517 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
2518 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
2519 /* Write primary table */
2521 DiskGuid,
2522 NumberOfEntries,
2523 FirstUsableLBA,
2524 LastUsableLBA,
2525 FALSE,
2526 DriveLayout->PartitionCount,
2527 DriveLayout->PartitionEntry);
2528 /* If it succeeded, also update backup table */
2529 if (NT_SUCCESS(Status))
2530 {
2532 DiskGuid,
2533 NumberOfEntries,
2534 FirstUsableLBA,
2535 LastUsableLBA,
2536 TRUE,
2537 DriveLayout->PartitionCount,
2538 DriveLayout->PartitionEntry);
2539 }
2540 }
2541 else
2542 {
2544 }
2545 }
2546 break;
2547
2548 default:
2549 DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
2551 }
2552
2553 /* It's over, internal structure not needed anymore */
2555
2556 return Status;
2557}
2558
2559/* EOF */
#define PAGED_CODE()
#define __inline
Definition: _wctype.cpp:15
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
BOOL FixErrors
Definition: chkdsk.c:69
unsigned int * PUINT32
Definition: basetsd.h:119
unsigned short * PUINT16
Definition: basetsd.h:186
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: ntoskrnl.c:212
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: ntoskrnl.c:50
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: ntoskrnl.c:115
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RtlComputeCrc32
Definition: compat.h:810
static const WCHAR Signature[]
Definition: parser.c:141
static const WCHAR Cleanup[]
Definition: register.c:80
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPoolCacheAligned
Definition: env_spec_w32.h:310
#define NonPagedPool
Definition: env_spec_w32.h:307
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
#define EFI_GUID_STRING_SIZE
Definition: fstubex.c:94
#define IS_VALID_DISK_INFO(Disk)
Definition: fstubex.c:96
struct _PARTITION_TABLE_ENTRY PARTITION_TABLE_ENTRY
#define EFI_HEADER_SIGNATURE
Definition: fstubex.c:88
NTSTATUS NTAPI FstubWriteSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, IN PVOID Buffer)
Definition: fstubex.c:1741
VOID NTAPI FstubCopyEntryEFI(OUT PEFI_PARTITION_ENTRY Entry, IN PPARTITION_INFORMATION_EX Partition, ULONG SectorSize)
Definition: fstubex.c:313
NTSTATUS NTAPI IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation, IN ULONG Size)
Definition: fstubex.c:1830
NTSTATUS NTAPI FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
Definition: fstubex.c:450
NTSTATUS NTAPI FstubGetDiskGeometry(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_GEOMETRY_EX Geometry)
Definition: fstubex.c:732
NTSTATUS NTAPI IoCreateDisk(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK Disk)
Definition: fstubex.c:1800
NTSTATUS NTAPI FstubSetPartitionInformationEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionNumber, IN SET_PARTITION_INFORMATION_GPT *PartitionInfo)
Definition: fstubex.c:1244
VOID NTAPI FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer)
Definition: fstubex.c:718
NTSTATUS NTAPI IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
Definition: fstubex.c:2459
struct _DISK_INFORMATION * PDISK_INFORMATION
struct _PARTITION_TABLE_ENTRY * PPARTITION_TABLE_ENTRY
struct _MASTER_BOOT_RECORD * PMASTER_BOOT_RECORD
NTSTATUS NTAPI FstubWriteHeaderEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionsSizeSector, IN GUID DiskGUID, IN ULONG NumberOfEntries, IN ULONGLONG FirstUsableLBA, IN ULONGLONG LastUsableLBA, IN ULONG PartitionEntryCRC32, IN BOOLEAN WriteBackupTable)
Definition: fstubex.c:1543
NTSTATUS NTAPI FstubReadPartitionTableMBR(IN PDISK_INFORMATION Disk, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION_EX *ReturnedDriveLayout)
Definition: fstubex.c:1123
#define PARTITION_ENTRY_SIZE
Definition: fstubex.c:86
struct _EFI_PARTITION_HEADER EFI_PARTITION_HEADER
NTSTATUS NTAPI FstubAllocateDiskInformation(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_INFORMATION *DiskBuffer, IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
Definition: fstubex.c:202
#define FstubDbgPrintDriveLayoutEx(DriveLayout)
Definition: fstubex.c:665
NTSTATUS NTAPI IoSetPartitionInformationEx(IN PDEVICE_OBJECT DeviceObject, IN ULONG PartitionNumber, IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
Definition: fstubex.c:2340
struct _EFI_PARTITION_HEADER * PEFI_PARTITION_HEADER
#define FstubDbgPrintSetPartitionEx(PartitionEntry, PartitionNumber)
Definition: fstubex.c:666
NTSTATUS NTAPI FstubCreateDiskMBR(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_MBR DiskInfo)
Definition: fstubex.c:334
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2274
struct _MASTER_BOOT_RECORD MASTER_BOOT_RECORD
NTSTATUS NTAPI FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN FixErrors)
Definition: fstubex.c:1293
NTSTATUS NTAPI FstubReadHeaderEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, PEFI_PARTITION_HEADER *HeaderBuffer)
Definition: fstubex.c:826
NTSTATUS NTAPI FstubWriteEntryEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionsSizeSector, IN ULONG PartitionEntryNumber, IN PEFI_PARTITION_ENTRY PartitionEntry, IN BOOLEAN WriteBackupTable, IN BOOLEAN ForceWrite, OUT PULONG PartitionEntryCRC32 OPTIONAL)
Definition: fstubex.c:1475
NTSTATUS NTAPI FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk, IN PARTITION_STYLE *PartitionStyle)
Definition: fstubex.c:671
NTSTATUS NTAPI IoVerifyPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FixErrors)
Definition: fstubex.c:2406
#define EFI_PMBR_OSTYPE_EFI
Definition: fstubex.c:92
struct _EFI_PARTITION_ENTRY * PEFI_PARTITION_ENTRY
VOID NTAPI FstubAdjustPartitionCount(IN ULONG SectorSize, IN OUT PULONG PartitionCount)
Definition: fstubex.c:166
NTSTATUS NTAPI FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk, IN GUID DiskGUID, IN ULONG MaxPartitionCount, IN ULONGLONG FirstUsableLBA, IN ULONGLONG LastUsableLBA, IN BOOLEAN WriteBackupTable, IN ULONG PartitionCount, IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
Definition: fstubex.c:1632
struct _EFI_PARTITION_ENTRY EFI_PARTITION_ENTRY
PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:265
struct _DISK_INFORMATION DISK_INFORMATION
NTSTATUS NTAPI FstubWritePartitionTableMBR(IN PDISK_INFORMATION Disk, IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:1709
NTSTATUS NTAPI IoReadDiskSignature(IN PDEVICE_OBJECT DeviceObject, IN ULONG BytesPerSector, OUT PDISK_SIGNATURE Signature)
Definition: fstubex.c:2166
#define EFI_HEADER_REVISION_1
Definition: fstubex.c:90
NTSTATUS NTAPI FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk)
Definition: fstubex.c:1423
NTSTATUS NTAPI FstubCreateDiskEFI(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_GPT DiskInfo)
Definition: fstubex.c:381
NTSTATUS NTAPI FstubReadSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, OUT PVOID Buffer)
Definition: fstubex.c:1190
NTSTATUS NTAPI FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:974
for(i=0;i< ARRAY_SIZE(offsets);i++)
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
#define C_ASSERT(e)
Definition: intsafe.h:73
PLOADER_PARAMETER_BLOCK IopLoaderBlock
Definition: iomgr.c:88
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
enum _PARTITION_STYLE PARTITION_STYLE
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define sprintf
Definition: sprintf.c:45
#define ULL(a, b)
Definition: format_msg.c:27
#define KernelMode
Definition: asm.h:38
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlEqualString(PSTRING String1, PSTRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
#define PARTITION_TABLE_OFFSET
Definition: hal.h:244
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:245
#define DISK_SIGNATURE_OFFSET
Definition: hal.h:243
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:248
BOOLEAN IopVerifyDiskSignature(_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, _In_ PARC_DISK_SIGNATURE ArcDiskSignature, _Out_ PULONG Signature)
Definition: arcname.c:946
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1446
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_TOO_LATE
Definition: ntstatus.h:720
UCHAR PartitionType
Definition: part_brfr.c:23
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
char CHAR
Definition: pedump.c:57
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
Entry
Definition: section.c:5210
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: parttest.c:75
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:356
PCHAR ArcName
Definition: arc.h:345
DISK_GEOMETRY Geometry
Definition: winioctl.h:530
LARGE_INTEGER DiskSize
Definition: winioctl.h:531
ULONG BytesPerSector
Definition: ntdddisk.h:404
PDEVICE_OBJECT DeviceObject
Definition: fstubex.c:19
ULONG SectorSize
Definition: fstubex.c:20
PUCHAR Buffer
Definition: fstubex.c:22
ULONGLONG SectorCount
Definition: fstubex.c:23
DISK_GEOMETRY_EX DiskGeometry
Definition: fstubex.c:21
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:421
Definition: fstubex.c:48
GUID UniquePartition
Definition: fstubex.c:50
GUID PartitionType
Definition: fstubex.c:49
ULONGLONG StartingLBA
Definition: fstubex.c:51
WCHAR Name[0x24]
Definition: fstubex.c:54
ULONGLONG Attributes
Definition: fstubex.c:53
ULONGLONG EndingLBA
Definition: fstubex.c:52
ULONGLONG FirstUsableLBA
Definition: fstubex.c:36
ULONGLONG AlternateLBA
Definition: fstubex.c:35
ULONGLONG Signature
Definition: fstubex.c:29
ULONGLONG LastUsableLBA
Definition: fstubex.c:37
ULONGLONG PartitionEntryLBA
Definition: fstubex.c:39
ULONGLONG MyLBA
Definition: fstubex.c:34
ULONG PartitionEntryCRC32
Definition: fstubex.c:42
ULONG SizeOfPartitionEntry
Definition: fstubex.c:41
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PARC_DISK_INFORMATION ArcDiskInformation
Definition: arc.h:847
PSTR ArcBootDeviceName
Definition: arc.h:841
UCHAR MasterBootRecordCodeAndData[0x1b8]
Definition: part_mbr.h:36
USHORT MasterBootRecordMagic
Definition: part_mbr.h:40
PARTITION_TABLE_ENTRY PartitionTable[4]
Definition: part_mbr.h:39
LARGE_INTEGER StartingOffset
Definition: imports.h:221
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:408
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:409
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:414
BOOLEAN RewritePartition
Definition: ntdddisk.h:415
Definition: part_mbr.h:16
ULONG SectorCountBeforePartition
Definition: part_mbr.h:26
ULONG PartitionSectorCount
Definition: part_mbr.h:27
UCHAR BootIndicator
Definition: part_mbr.h:17
UCHAR StartCylinder
Definition: part_mbr.h:21
UCHAR StartSector
Definition: part_mbr.h:20
UCHAR SystemIndicator
Definition: part_mbr.h:22
UCHAR EndHead
Definition: part_mbr.h:23
UCHAR EndSector
Definition: part_mbr.h:24
UCHAR EndCylinder
Definition: part_mbr.h:25
UCHAR StartHead
Definition: part_mbr.h:19
#define TAG_FSTUB
Definition: tag.h:54
#define STATUS_PENDING
Definition: telnetd.h:14
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t UINT32
Definition: typedefs.h:59
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:265
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_In_ ULONG SectorSize
Definition: halfuncs.h:291
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
_In_ ULONG _In_ BOOLEAN ReturnRecognizedPartitions
Definition: iofuncs.h:2051
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
struct _BOOTDISK_INFORMATION_EX * PBOOTDISK_INFORMATION_EX
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
* PFILE_OBJECT
Definition: iotypes.h:1998
struct _BOOTDISK_INFORMATION_EX BOOTDISK_INFORMATION_EX
@ Executive
Definition: ketypes.h:467
#define ObDereferenceObject
Definition: obfuncs.h:203