ReactOS 0.4.16-dev-320-g3bd9ddc
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
103VOID
104NTAPI
107);
108
110NTAPI
112 IN PARTITION_STYLE * PartitionStyle
113);
114
115VOID
116NTAPI
118);
119
121NTAPI
123 OUT PDISK_GEOMETRY_EX Geometry
124);
125
127NTAPI
130 IN ULONGLONG StartingSector OPTIONAL,
132);
133
135NTAPI
137);
138
140NTAPI
142 IN ULONG PartitionsSizeSector,
143 IN GUID DiskGUID,
144 IN ULONG NumberOfEntries,
145 IN ULONGLONG FirstUsableLBA,
146 IN ULONGLONG LastUsableLBA,
147 IN ULONG PartitionEntryCRC32,
148 IN BOOLEAN WriteBackupTable);
149
151NTAPI
153 IN GUID DiskGUID,
154 IN ULONG MaxPartitionCount,
155 IN ULONGLONG FirstUsableLBA,
156 IN ULONGLONG LastUsableLBA,
157 IN BOOLEAN WriteBackupTable,
158 IN ULONG PartitionCount,
159 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL
160);
161
163NTAPI
166 IN ULONGLONG StartingSector OPTIONAL,
168);
169
170VOID
171NTAPI
173 IN OUT PULONG PartitionCount)
174{
175 ULONG Count;
176
177 PAGED_CODE();
178
180 ASSERT(PartitionCount);
181
182 /* Get partition count */
183 Count = *PartitionCount;
184 /* We need at least 128 entries */
185 if (Count < 128)
186 {
187 Count = 128;
188 }
189
190 /* Then, ensure that we will have a round value,
191 * ie, all sectors will be full of entries
192 * There won't be lonely entries
193 */
196 ASSERT(*PartitionCount <= Count);
197 /* Return result */
198 *PartitionCount = Count;
199
200 /* One more sanity check */
201 if (SectorSize == 512)
202 {
203 ASSERT(Count % 4 == 0);
204 }
205}
206
208NTAPI
210 OUT PDISK_INFORMATION * DiskBuffer,
211 IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
212{
214 PDISK_INFORMATION DiskInformation;
215
216 PAGED_CODE();
217
219 ASSERT(DiskBuffer);
220
221 /* Allocate internal structure */
223 if (!DiskInformation)
224 {
226 }
227
228 /* If caller don't pass needed information, let's get them */
229 if (!DiskGeometry)
230 {
232 if (!NT_SUCCESS(Status))
233 {
234 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
235 return Status;
236 }
237 }
238 else
239 {
240 RtlCopyMemory(&DiskInformation->DiskGeometry, DiskGeometry, sizeof(DISK_GEOMETRY_EX));
241 }
242
243 /* Ensure read/received information are correct */
244 if (DiskInformation->DiskGeometry.Geometry.BytesPerSector == 0 ||
245 DiskInformation->DiskGeometry.DiskSize.QuadPart == 0)
246 {
247 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
249 }
250
251 /* Store vital information as well */
252 DiskInformation->DeviceObject = DeviceObject;
253 DiskInformation->SectorSize = DiskInformation->DiskGeometry.Geometry.BytesPerSector;
254 DiskInformation->SectorCount = DiskInformation->DiskGeometry.DiskSize.QuadPart / DiskInformation->SectorSize;
255
256 /* Finally, allocate the buffer that will be used for different read */
257 DiskInformation->Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskInformation->SectorSize, TAG_FSTUB);
258 if (!DiskInformation->Buffer)
259 {
260 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
262 }
263
264 /* Return allocated internal structure */
265 *DiskBuffer = DiskInformation;
266
267 return STATUS_SUCCESS;
268}
269
271NTAPI
272FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
273{
274 ULONG i;
275 PDRIVE_LAYOUT_INFORMATION DriveLayout;
276
277 PAGED_CODE();
278
279 ASSERT(LayoutEx);
280
281 /* Check whether we're dealing with MBR partition table */
282 if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR)
283 {
284 ASSERT(FALSE);
285 return NULL;
286 }
287
288 /* Allocate needed buffer */
290 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
291 LayoutEx->PartitionCount * sizeof(PARTITION_INFORMATION),
292 TAG_FSTUB);
293 if (!DriveLayout)
294 {
295 return NULL;
296 }
297
298 /* Convert information about partition table */
299 DriveLayout->PartitionCount = LayoutEx->PartitionCount;
300 DriveLayout->Signature = LayoutEx->Mbr.Signature;
301
302 /* Convert each partition */
303 for (i = 0; i < LayoutEx->PartitionCount; i++)
304 {
305 DriveLayout->PartitionEntry[i].StartingOffset = LayoutEx->PartitionEntry[i].StartingOffset;
306 DriveLayout->PartitionEntry[i].PartitionLength = LayoutEx->PartitionEntry[i].PartitionLength;
307 DriveLayout->PartitionEntry[i].HiddenSectors = LayoutEx->PartitionEntry[i].Mbr.HiddenSectors;
308 DriveLayout->PartitionEntry[i].PartitionNumber = LayoutEx->PartitionEntry[i].PartitionNumber;
309 DriveLayout->PartitionEntry[i].PartitionType = LayoutEx->PartitionEntry[i].Mbr.PartitionType;
310 DriveLayout->PartitionEntry[i].BootIndicator = LayoutEx->PartitionEntry[i].Mbr.BootIndicator;
311 DriveLayout->PartitionEntry[i].RecognizedPartition = LayoutEx->PartitionEntry[i].Mbr.RecognizedPartition;
312 DriveLayout->PartitionEntry[i].RewritePartition = LayoutEx->PartitionEntry[i].RewritePartition;
313 }
314
315 return DriveLayout;
316}
317
318VOID
319NTAPI
323{
324 PAGED_CODE();
325
326 ASSERT(Entry);
327 ASSERT(Partition);
329
330 /* Just convert data to EFI partition entry type */
331 Entry->PartitionType = Partition->Gpt.PartitionType;
332 Entry->UniquePartition = Partition->Gpt.PartitionId;
333 Entry->StartingLBA = Partition->StartingOffset.QuadPart / SectorSize;
334 Entry->EndingLBA = (Partition->StartingOffset.QuadPart + Partition->PartitionLength.QuadPart - 1) / SectorSize;
335 Entry->Attributes = Partition->Gpt.Attributes;
336 RtlCopyMemory(Entry->Name, Partition->Gpt.Name, sizeof(Entry->Name));
337}
338
340NTAPI
342 IN PCREATE_DISK_MBR DiskInfo)
343{
345 PDISK_INFORMATION Disk = NULL;
346 PMASTER_BOOT_RECORD MasterBootRecord;
347
348 PAGED_CODE();
349
351
352 /* Allocate internal structure */
354 if (!NT_SUCCESS(Status))
355 {
356 return Status;
357 }
358
359 /* Read previous MBR, if any */
361 Disk->SectorSize,
362 0ULL,
363 Disk->Buffer);
364 if (!NT_SUCCESS(Status))
365 {
367 return Status;
368 }
369 /* Fill the buffer with needed information, we won't overwrite boot code */
370 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
371 MasterBootRecord->Signature = DiskInfo->Signature;
374
375 /* Finally, write MBR */
377 Disk->SectorSize,
378 0ULL,
379 Disk->Buffer);
380
381 /* Release internal structure and return */
383 return Status;
384}
385
387NTAPI
389 IN PCREATE_DISK_GPT DiskInfo)
390{
392 PDISK_INFORMATION Disk = NULL;
393 ULONGLONG FirstUsableLBA, LastUsableLBA;
394 ULONG MaxPartitionCount, SectorsForPartitions;
395
396 PAGED_CODE();
397
399 ASSERT(DiskInfo);
400
401 /* Allocate internal structure */
403 if (!NT_SUCCESS(Status))
404 {
405 return Status;
406 }
407 ASSERT(Disk);
408
409 /* Write legacy MBR */
411 if (!NT_SUCCESS(Status))
412 {
414 return Status;
415 }
416
417 /* Get max entries and adjust its number */
418 MaxPartitionCount = DiskInfo->MaxPartitionCount;
419 FstubAdjustPartitionCount(Disk->SectorSize, &MaxPartitionCount);
420
421 /* Count number of sectors needed to store partitions */
422 SectorsForPartitions = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
423 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
424 FirstUsableLBA = SectorsForPartitions + 2;
425 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
426 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
427
428 /* First, write primary table */
430 DiskInfo->DiskId,
431 MaxPartitionCount,
432 FirstUsableLBA,
433 LastUsableLBA,
434 FALSE,
435 0,
436 NULL);
437 /* Then, write backup table */
438 if (NT_SUCCESS(Status))
439 {
441 DiskInfo->DiskId,
442 MaxPartitionCount,
443 FirstUsableLBA,
444 LastUsableLBA,
445 TRUE,
446 0,
447 NULL);
448 }
449
450 /* Release internal structure and return */
452 return Status;
453}
454
456NTAPI
458{
460 PDISK_INFORMATION Disk = NULL;
461 PARTITION_STYLE PartitionStyle;
462 PMASTER_BOOT_RECORD MasterBootRecord;
463
464 PAGED_CODE();
465
467
468 /* Allocate internal structure */
470 if (!NT_SUCCESS(Status))
471 {
472 return Status;
473 }
474
475 /* Detect current disk partition style */
476 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
477 if (!NT_SUCCESS(Status))
478 {
480 return Status;
481 }
482
483 /* Read MBR, if any */
485 Disk->SectorSize,
486 0ULL,
487 Disk->Buffer);
488 if (!NT_SUCCESS(Status))
489 {
491 return Status;
492 }
493
494 /* Only zero useful stuff */
495 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
496 MasterBootRecord->Signature = 0;
497 RtlZeroMemory(MasterBootRecord->PartitionTable, sizeof(PARTITION_TABLE_ENTRY));
498 MasterBootRecord->MasterBootRecordMagic = 0;
499
500 /* Write back that destroyed MBR */
502 Disk->SectorSize,
503 0ULL,
504 Disk->Buffer);
505 /* If previous style wasn't GPT, we're done here */
506 if (PartitionStyle != PARTITION_STYLE_GPT)
507 {
509 return Status;
510 }
511
512 /* Otherwise, we've to zero the two GPT headers */
513 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
514 /* Erase primary header */
516 Disk->SectorSize,
517 1ULL,
518 Disk->Buffer);
519 /* In case of success, erase backup header */
520 if (NT_SUCCESS(Status))
521 {
523 Disk->SectorSize,
524 Disk->SectorCount - 1ULL,
525 Disk->Buffer);
526 }
527
528 /* Release internal structure and return */
530 return Status;
531}
532
533PCHAR
534NTAPI
537{
539 "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
540 Guid->Data1,
541 Guid->Data2,
542 Guid->Data3,
543 Guid->Data4[0],
544 Guid->Data4[1],
545 Guid->Data4[2],
546 Guid->Data4[3],
547 Guid->Data4[4],
548 Guid->Data4[5],
549 Guid->Data4[6],
550 Guid->Data4[7]);
551
552 return String;
553}
554
555VOID
556NTAPI
557FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
558{
559 ULONG i;
561
562 PAGED_CODE();
563
564 DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
565 switch (DriveLayout->PartitionStyle)
566 {
568 if (DriveLayout->PartitionCount % 4 != 0)
569 {
570 DPRINT("Warning: Partition count isn't a 4-factor: %lu!\n", DriveLayout->PartitionCount);
571 }
572
573 DPRINT("Signature: %8.8x\n", DriveLayout->Mbr.Signature);
574 for (i = 0; i < DriveLayout->PartitionCount; i++)
575 {
576 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
577 }
578
579 break;
581 FstubDbgGuidToString(&(DriveLayout->Gpt.DiskId), Guid);
582 DPRINT("DiskId: %s\n", Guid);
583 DPRINT("StartingUsableOffset: %I64x\n", DriveLayout->Gpt.StartingUsableOffset.QuadPart);
584 DPRINT("UsableLength: %I64x\n", DriveLayout->Gpt.UsableLength.QuadPart);
585 DPRINT("MaxPartitionCount: %lu\n", DriveLayout->Gpt.MaxPartitionCount);
586 for (i = 0; i < DriveLayout->PartitionCount; i++)
587 {
588 FstubDbgPrintPartitionEx(DriveLayout->PartitionEntry, i);
589 }
590
591 break;
592 default:
593 DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
594 }
595}
596
597VOID
598NTAPI
601{
603
604 PAGED_CODE();
605
606 DPRINT("Printing partition %lu\n", PartitionNumber);
607
608 switch (PartitionEntry[PartitionNumber].PartitionStyle)
609 {
611 DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
612 DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
613 DPRINT(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
614 DPRINT(" PartitionType: %02x\n", PartitionEntry[PartitionNumber].Mbr.PartitionType);
615 DPRINT(" BootIndicator: %u\n", PartitionEntry[PartitionNumber].Mbr.BootIndicator);
616 DPRINT(" RecognizedPartition: %u\n", PartitionEntry[PartitionNumber].Mbr.RecognizedPartition);
617 DPRINT(" HiddenSectors: %lu\n", PartitionEntry[PartitionNumber].Mbr.HiddenSectors);
618
619 break;
621 DPRINT(" StartingOffset: %I64x\n", PartitionEntry[PartitionNumber].StartingOffset.QuadPart);
622 DPRINT(" PartitionLength: %I64x\n", PartitionEntry[PartitionNumber].PartitionLength.QuadPart);
623 DPRINT(" RewritePartition: %u\n", PartitionEntry[PartitionNumber].RewritePartition);
624 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionType), Guid);
625 DPRINT(" PartitionType: %s\n", Guid);
626 FstubDbgGuidToString(&(PartitionEntry[PartitionNumber].Gpt.PartitionId), Guid);
627 DPRINT(" PartitionId: %s\n", Guid);
628 DPRINT(" Attributes: %I64x\n", PartitionEntry[PartitionNumber].Gpt.Attributes);
629 DPRINT(" Name: %ws\n", PartitionEntry[PartitionNumber].Gpt.Name);
630
631 break;
632 default:
633 DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
634 }
635}
636
637VOID
638NTAPI
639FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry,
641{
643
644 PAGED_CODE();
645
646 DPRINT("FSTUB: SET_PARTITION_INFORMATION_EX: %p\n", PartitionEntry);
647 DPRINT("Modifying partition %lu\n", PartitionNumber);
648 switch (PartitionEntry->PartitionStyle)
649 {
651 DPRINT(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
652
653 break;
655 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionType), Guid);
656 DPRINT(" PartitionType: %s\n", Guid);
657 FstubDbgGuidToString(&(PartitionEntry->Gpt.PartitionId), Guid);
658 DPRINT(" PartitionId: %s\n", Guid);
659 DPRINT(" Attributes: %I64x\n", PartitionEntry->Gpt.Attributes);
660 DPRINT(" Name: %ws\n", PartitionEntry->Gpt.Name);
661
662 break;
663 default:
664 DPRINT(" Unsupported partition style: %ld\n", PartitionEntry[PartitionNumber].PartitionStyle);
665 }
666}
667
669NTAPI
671 IN PARTITION_STYLE * PartitionStyle)
672{
674 PPARTITION_DESCRIPTOR PartitionDescriptor;
675
676 PAGED_CODE();
677
679 ASSERT(PartitionStyle);
680
681 /* Read disk first sector */
682 Status = FstubReadSector(Disk->DeviceObject,
683 Disk->SectorSize,
684 0,
685 Disk->Buffer);
686 if (!NT_SUCCESS(Status))
687 {
688 return Status;
689 }
690
691 /* Get the partition descriptor array */
692 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Disk->Buffer[PARTITION_TABLE_OFFSET];
693 /* If we have not the 0xAA55 then it's raw partition */
695 {
696 *PartitionStyle = PARTITION_STYLE_RAW;
697 }
698 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
699 else if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
700 PartitionDescriptor[1].PartitionType == 0 &&
701 PartitionDescriptor[2].PartitionType == 0 &&
702 PartitionDescriptor[3].PartitionType == 0)
703 {
704 *PartitionStyle = PARTITION_STYLE_GPT;
705 }
706 /* Otherwise, partition table is in MBR */
707 else
708 {
709 *PartitionStyle = PARTITION_STYLE_MBR;
710 }
711
712 return STATUS_SUCCESS;
713}
714
715VOID
716NTAPI
718{
719 if (DiskBuffer)
720 {
721 if (DiskBuffer->Buffer)
722 {
723 ExFreePoolWithTag(DiskBuffer->Buffer, TAG_FSTUB);
724 }
725 ExFreePoolWithTag(DiskBuffer, TAG_FSTUB);
726 }
727}
728
730NTAPI
732 OUT PDISK_GEOMETRY_EX Geometry)
733{
735 PIRP Irp;
737 PDISK_GEOMETRY_EX DiskGeometry = NULL;
739
740 PAGED_CODE();
741
743 ASSERT(Geometry);
744
745 /* Allocate needed components */
747 if (!DiskGeometry)
748 {
750 goto Cleanup;
751 }
752
754 if (!IoStatusBlock)
755 {
757 goto Cleanup;
758 }
759
761 if (!Event)
762 {
764 goto Cleanup;
765 }
766 /* Initialize the waiting event */
768
769 /* Build the request to get disk geometry */
772 0,
773 0,
774 DiskGeometry,
775 sizeof(DISK_GEOMETRY_EX),
776 FALSE,
777 Event,
779 if (!Irp)
780 {
782 goto Cleanup;
783 }
784
785 /* Call the driver and wait for completion if needed */
787 if (Status == STATUS_PENDING)
788 {
791 }
792
793 /* In case of a success, return read data */
794 if (NT_SUCCESS(Status))
795 {
796 *Geometry = *DiskGeometry;
797 }
798
799Cleanup:
800 if (DiskGeometry)
801 {
802 ExFreePoolWithTag(DiskGeometry, TAG_FSTUB);
803
804 if (NT_SUCCESS(Status))
805 {
806 ASSERT(Geometry->Geometry.BytesPerSector % PARTITION_ENTRY_SIZE == 0);
807 }
808 }
809
810 if (IoStatusBlock)
811 {
813 }
814
815 if (Event)
816 {
818 }
819
820 return Status;
821}
822
824NTAPI
826 IN BOOLEAN ReadBackupTable,
827 PEFI_PARTITION_HEADER * HeaderBuffer)
828{
830 PUCHAR Sector = NULL;
831 ULONGLONG StartingSector;
832 PEFI_PARTITION_HEADER EFIHeader;
833 ULONG i, HeaderCRC32, PreviousCRC32, SectoredPartitionEntriesSize, LonelyPartitions;
834
835 PAGED_CODE();
836
837 ASSERT(Disk);
839 ASSERT(HeaderBuffer);
840
841 /* In case we want to read backup table, we read last disk sector */
842 if (ReadBackupTable)
843 {
844 StartingSector = Disk->SectorCount - 1ULL;
845 }
846 else
847 {
848 /* Otherwise we start at first sector (as sector 0 is the MBR) */
849 StartingSector = 1ULL;
850 }
851
852 Status = FstubReadSector(Disk->DeviceObject,
853 Disk->SectorSize,
854 StartingSector,
855 Disk->Buffer);
856 if (!NT_SUCCESS(Status))
857 {
858 DPRINT("EFI::Failed reading header!\n");
859 return Status;
860 }
861 /* Let's use read buffer as EFI_PARTITION_HEADER */
862 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
863
864
865 /* First check signature
866 * Then, check version (we only support v1)
867 * Finally check header size
868 */
869 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
870 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
871 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
872 {
873 DPRINT("EFI::Wrong signature/version/header size!\n");
874 DPRINT("%I64x (expected: %I64x)\n", EFIHeader->Signature, EFI_HEADER_SIGNATURE);
875 DPRINT("%03x (expected: %03x)\n", EFIHeader->Revision, EFI_HEADER_REVISION_1);
876 DPRINT("%02x (expected: %02x)\n", EFIHeader->HeaderSize, sizeof(EFI_PARTITION_HEADER));
878 }
879
880 /* Save current checksum */
881 HeaderCRC32 = EFIHeader->HeaderCRC32;
882 /* Then zero the one in EFI header. This is needed to compute header checksum */
883 EFIHeader->HeaderCRC32 = 0;
884 /* Compute header checksum and compare with the one present in partition table */
885 if (RtlComputeCrc32(0, Disk->Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
886 {
887 DPRINT("EFI::Not matching header checksum!\n");
889 }
890 /* Put back removed checksum in header */
891 EFIHeader->HeaderCRC32 = HeaderCRC32;
892
893 /* Check if current LBA is matching with ours */
894 if (EFIHeader->MyLBA != StartingSector)
895 {
896 DPRINT("EFI::Not matching starting sector!\n");
898 }
899
900 /* Allocate a buffer to read a sector on the disk */
902 Disk->SectorSize,
903 TAG_FSTUB);
904 if (!Sector)
905 {
906 DPRINT("EFI::Lacking resources!\n");
908 }
909
910 /* Count how much sectors we'll have to read to read the whole partition table */
911 SectoredPartitionEntriesSize = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
912 /* Compute partition table checksum */
913 for (i = 0, PreviousCRC32 = 0; i < SectoredPartitionEntriesSize; i++)
914 {
915 Status = FstubReadSector(Disk->DeviceObject,
916 Disk->SectorSize,
917 EFIHeader->PartitionEntryLBA + i,
918 Sector);
919 if (!NT_SUCCESS(Status))
920 {
922 DPRINT("EFI::Failed reading sector for partition entry!\n");
923 return Status;
924 }
925
926 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector, Disk->SectorSize);
927 }
928
929 /* Check whether we have a last sector not full of partitions */
930 LonelyPartitions = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) % Disk->SectorSize;
931 /* In such case, we have to complete checksum computation */
932 if (LonelyPartitions != 0)
933 {
934 /* Read the sector that contains those partitions */
935 Status = FstubReadSector(Disk->DeviceObject,
936 Disk->SectorSize,
937 EFIHeader->PartitionEntryLBA + i,
938 Sector);
939 if (!NT_SUCCESS(Status))
940 {
942 DPRINT("EFI::Failed reading sector for partition entry!\n");
943 return Status;
944 }
945
946 /* Then complete checksum by computing on each partition */
947 for (i = 0; i < LonelyPartitions; i++)
948 {
949 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector + i * PARTITION_ENTRY_SIZE, PARTITION_ENTRY_SIZE);
950 }
951 }
952
953 /* Finally, release memory */
955
956 /* Compare checksums */
957 if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
958 {
959 /* In case of a success, return read header */
960 *HeaderBuffer = EFIHeader;
961 return STATUS_SUCCESS;
962 }
963 else
964 {
965 DPRINT("EFI::Not matching partition table checksum!\n");
966 DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
968 }
969}
970
972NTAPI
974 IN BOOLEAN ReadBackupTable,
975 OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
976{
978 ULONG NumberOfEntries;
979 PEFI_PARTITION_HEADER EfiHeader;
980 EFI_PARTITION_ENTRY PartitionEntry;
981#if 0
982 BOOLEAN UpdatedPartitionTable = FALSE;
983 ULONGLONG SectorsForPartitions, PartitionEntryLBA;
984#else
985 ULONGLONG PartitionEntryLBA;
986#endif
987 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
988 ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
989
990 PAGED_CODE();
991
992 ASSERT(Disk);
993
994 /* Zero output */
995 *DriveLayout = NULL;
996
997 /* Read EFI header */
999 ReadBackupTable,
1000 &EfiHeader);
1001 if (!NT_SUCCESS(Status))
1002 {
1003 return Status;
1004 }
1005
1006 /* Backup the number of entries, will be used later on */
1007 NumberOfEntries = EfiHeader->NumberOfEntries;
1008
1009 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1010 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1011 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1012 EfiHeader->NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
1013 TAG_FSTUB);
1014 if (!DriveLayoutEx)
1015 {
1017 }
1018
1019#if 0
1020 if (!ReadBackupTable)
1021 {
1022 /* If we weren't ask to read backup table,
1023 * check the status of the backup table.
1024 * In case it's not where we're expecting it, move it and ask
1025 * for a partition table rewrite.
1026 */
1027 if ((Disk->SectorCount - 1ULL) != EfiHeader->AlternateLBA)
1028 {
1029 /* We'll update it. First, count number of sectors needed to store partitions */
1030 SectorsForPartitions = ((ULONGLONG)EfiHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1031 /* Then set first usable LBA: Legacy MBR + GPT header + Partitions entries */
1032 EfiHeader->FirstUsableLBA = SectorsForPartitions + 2;
1033 /* Then set last usable LBA: Last sector - GPT header - Partitions entries */
1034 EfiHeader->LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
1035 /* Inform that we'll rewrite partition table */
1036 UpdatedPartitionTable = TRUE;
1037 }
1038 }
1039#endif
1040
1041 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_GPT;
1042 /* Translate LBA -> Offset */
1043 DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader->FirstUsableLBA * Disk->SectorSize;
1044 DriveLayoutEx->Gpt.UsableLength.QuadPart = EfiHeader->LastUsableLBA - EfiHeader->FirstUsableLBA * Disk->SectorSize;
1045 DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader->NumberOfEntries;
1046 DriveLayoutEx->Gpt.DiskId = EfiHeader->DiskGUID;
1047
1048 /* Backup partition entry position */
1049 PartitionEntryLBA = EfiHeader->PartitionEntryLBA;
1050 /* Count number of partitions per sector */
1051 PartitionsPerSector = (Disk->SectorSize / PARTITION_ENTRY_SIZE);
1052 /* Read all partitions and fill in structure
1053 * BEWARE! Past that point EfiHeader IS NOT VALID ANYMORE
1054 * It will be erased by the reading of the partition entry
1055 */
1056 for (i = 0, PartitionCount = 0, PartitionIndex = PartitionsPerSector;
1057 i < NumberOfEntries;
1058 i++)
1059 {
1060 /* Only read following sector if we finished with previous sector */
1061 if (PartitionIndex == PartitionsPerSector)
1062 {
1063 Status = FstubReadSector(Disk->DeviceObject,
1064 Disk->SectorSize,
1065 PartitionEntryLBA + (i / PartitionsPerSector),
1066 Disk->Buffer);
1067 if (!NT_SUCCESS(Status))
1068 {
1069 ExFreePoolWithTag(DriveLayoutEx, TAG_FSTUB);
1070 return Status;
1071 }
1072
1073 PartitionIndex = 0;
1074 }
1075 /* Read following partition */
1076 PartitionEntry = ((PEFI_PARTITION_ENTRY)Disk->Buffer)[PartitionIndex];
1077 PartitionIndex++;
1078
1079 /* If partition GUID is 00000000-0000-0000-0000-000000000000, then it's unused, skip it */
1080 if (PartitionEntry.PartitionType.Data1 == 0 &&
1081 PartitionEntry.PartitionType.Data2 == 0 &&
1082 PartitionEntry.PartitionType.Data3 == 0 &&
1083 ((PULONGLONG)PartitionEntry.PartitionType.Data4)[0] == 0)
1084 {
1085 continue;
1086 }
1087
1088 /* Write data to structure. Don't forget GPT is using sectors, Windows offsets */
1089 DriveLayoutEx->PartitionEntry[PartitionCount].StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
1090 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
1091 PartitionEntry.StartingLBA + 1) *
1092 Disk->SectorSize;
1093 /* This number starts from 1 */
1094 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionNumber = PartitionCount + 1;
1095 DriveLayoutEx->PartitionEntry[PartitionCount].RewritePartition = FALSE;
1096 DriveLayoutEx->PartitionEntry[PartitionCount].PartitionStyle = PARTITION_STYLE_GPT;
1097 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionType = PartitionEntry.PartitionType;
1098 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.PartitionId = PartitionEntry.UniquePartition;
1099 DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Attributes = PartitionEntry.Attributes;
1100 RtlCopyMemory(DriveLayoutEx->PartitionEntry[PartitionCount].Gpt.Name,
1101 PartitionEntry.Name, sizeof(PartitionEntry.Name));
1102
1103 /* Update partition count */
1104 PartitionCount++;
1105 }
1106 DriveLayoutEx->PartitionCount = PartitionCount;
1107
1108#if 0
1109 /* If we updated partition table using backup table, rewrite partition table */
1110 if (UpdatedPartitionTable)
1111 {
1112 IoWritePartitionTableEx(Disk->DeviceObject,
1113 DriveLayoutEx);
1114 }
1115#endif
1116
1117 /* Finally, return read data */
1118 *DriveLayout = DriveLayoutEx;
1119
1120 return Status;
1121}
1122
1124NTAPI
1127 OUT PDRIVE_LAYOUT_INFORMATION_EX* ReturnedDriveLayout)
1128{
1130 ULONG i;
1131 PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
1132 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
1133
1134 PAGED_CODE();
1135
1137 ASSERT(ReturnedDriveLayout);
1138
1139 /* Zero output */
1140 *ReturnedDriveLayout = NULL;
1141
1142 /* Read partition table the old way */
1143 Status = IoReadPartitionTable(Disk->DeviceObject,
1144 Disk->SectorSize,
1146 &DriveLayout);
1147 if (!NT_SUCCESS(Status))
1148 {
1149 return Status;
1150 }
1151
1152 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1153 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1154 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1155 DriveLayout->PartitionCount * sizeof(PARTITION_INFORMATION_EX),
1156 TAG_FSTUB);
1157 if (!DriveLayoutEx)
1158 {
1159 /* Let's not leak memory as in Windows 2003 */
1160 ExFreePool(DriveLayout);
1162 }
1163
1164 /* Start converting the DRIVE_LAYOUT_INFORMATION structure */
1165 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
1166 DriveLayoutEx->PartitionCount = DriveLayout->PartitionCount;
1167 DriveLayoutEx->Mbr.Signature = DriveLayout->Signature;
1168
1169 /* Convert each found partition */
1170 for (i = 0; i < DriveLayout->PartitionCount; i++)
1171 {
1172 DriveLayoutEx->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
1173 DriveLayoutEx->PartitionEntry[i].StartingOffset = DriveLayout->PartitionEntry[i].StartingOffset;
1174 DriveLayoutEx->PartitionEntry[i].PartitionLength = DriveLayout->PartitionEntry[i].PartitionLength;
1175 DriveLayoutEx->PartitionEntry[i].PartitionNumber = DriveLayout->PartitionEntry[i].PartitionNumber;
1176 DriveLayoutEx->PartitionEntry[i].RewritePartition = DriveLayout->PartitionEntry[i].RewritePartition;
1177 DriveLayoutEx->PartitionEntry[i].Mbr.PartitionType = DriveLayout->PartitionEntry[i].PartitionType;
1178 DriveLayoutEx->PartitionEntry[i].Mbr.BootIndicator = DriveLayout->PartitionEntry[i].BootIndicator;
1179 DriveLayoutEx->PartitionEntry[i].Mbr.RecognizedPartition = DriveLayout->PartitionEntry[i].RecognizedPartition;
1180 DriveLayoutEx->PartitionEntry[i].Mbr.HiddenSectors = DriveLayout->PartitionEntry[i].HiddenSectors;
1181 }
1182
1183 /* Finally, return data and free old structure */
1184 *ReturnedDriveLayout = DriveLayoutEx;
1185 ExFreePool(DriveLayout);
1186
1187 return STATUS_SUCCESS;
1188}
1189
1191NTAPI
1194 IN ULONGLONG StartingSector OPTIONAL,
1196{
1198 PIRP Irp;
1199 KEVENT Event;
1202 PIO_STACK_LOCATION IoStackLocation;
1203
1204 PAGED_CODE();
1205
1207 ASSERT(Buffer);
1209
1210 /* Compute starting offset */
1211 StartingOffset.QuadPart = StartingSector * SectorSize;
1212
1213 /* Initialize waiting event */
1215
1216 /* Prepare IRP */
1219 Buffer,
1220 SectorSize,
1222 &Event,
1223 &IoStatusBlock);
1224 if (!Irp)
1225 {
1227 }
1228
1229 /* Override volume verify */
1230 IoStackLocation = IoGetNextIrpStackLocation(Irp);
1231 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1232
1233 /* Then call driver, and wait for completion if needed */
1235 if (Status == STATUS_PENDING)
1236 {
1239 }
1240
1241 return Status;
1242}
1243
1245NTAPI
1248 IN SET_PARTITION_INFORMATION_GPT * PartitionInfo)
1249{
1251 PDRIVE_LAYOUT_INFORMATION_EX Layout = NULL;
1252
1253 PAGED_CODE();
1254
1255 ASSERT(Disk);
1257
1258 /* Partition 0 isn't correct (should start at 1) */
1259 if (PartitionNumber == 0)
1260 {
1262 }
1263
1264 /* Read partition table */
1265 Status = IoReadPartitionTableEx(Disk->DeviceObject, &Layout);
1266 if (!NT_SUCCESS(Status))
1267 {
1268 return Status;
1269 }
1270 ASSERT(Layout);
1271
1272 /* If our partition (started at 0 now) is higher than partition count, then, there's an issue */
1273 if (Layout->PartitionCount <= --PartitionNumber)
1274 {
1275 ExFreePool(Layout);
1277 }
1278
1279 /* Erase actual partition entry data with provided ones */
1280 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionType = PartitionInfo->PartitionType;
1281 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionId = PartitionInfo->PartitionId;
1282 Layout->PartitionEntry[PartitionNumber].Gpt.Attributes = PartitionInfo->Attributes;
1283 RtlCopyMemory(Layout->PartitionEntry[PartitionNumber].Gpt.Name, PartitionInfo->Name, sizeof(PartitionInfo->Name));
1284
1285 /* Rewrite the whole partition table to update the modified entry */
1286 Status = IoWritePartitionTableEx(Disk->DeviceObject, Layout);
1287
1288 /* Free partition table and return */
1289 ExFreePool(Layout);
1290 return Status;
1291}
1292
1294NTAPI
1297{
1299 PEFI_PARTITION_HEADER EFIHeader, ReadEFIHeader;
1300 BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE, WriteBackup;
1301 ULONGLONG ReadPosition, WritePosition, SectorsForPartitions, PartitionIndex;
1302
1303 PAGED_CODE();
1304
1306 if (!EFIHeader)
1307 {
1309 }
1310
1311 Status = FstubReadHeaderEFI(Disk, FALSE, &ReadEFIHeader);
1312 if (NT_SUCCESS(Status))
1313 {
1314 PrimaryValid = TRUE;
1315 ASSERT(ReadEFIHeader);
1316 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1317 }
1318
1319 Status = FstubReadHeaderEFI(Disk, TRUE, &ReadEFIHeader);
1320 if (NT_SUCCESS(Status))
1321 {
1322 BackupValid = TRUE;
1323 ASSERT(ReadEFIHeader);
1324 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1325 }
1326
1327 /* If both are sane, just return */
1328 if (PrimaryValid && BackupValid)
1329 {
1330 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1331 return STATUS_SUCCESS;
1332 }
1333
1334 /* If both are damaged OR if we have not been ordered to fix
1335 * Then, quit and warn about disk corruption
1336 */
1337 if ((!PrimaryValid && !BackupValid) || !FixErrors)
1338 {
1339 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1341 }
1342
1343 /* Compute sectors taken by partitions */
1344 SectorsForPartitions = (((ULONGLONG)EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) + Disk->SectorSize - 1) / Disk->SectorSize;
1345 if (PrimaryValid)
1346 {
1347 WriteBackup = TRUE;
1348 /* Take position at backup table for writing */
1349 WritePosition = Disk->SectorCount - SectorsForPartitions;
1350 /* And read from primary table */
1351 ReadPosition = 2ULL;
1352
1353 DPRINT("EFI::Will repair backup table from primary\n");
1354 }
1355 else
1356 {
1357 ASSERT(BackupValid);
1358 WriteBackup = FALSE;
1359 /* Take position at primary table for writing */
1360 WritePosition = 2ULL;
1361 /* And read from backup table */
1362 ReadPosition = Disk->SectorCount - SectorsForPartitions;
1363
1364 DPRINT("EFI::Will repair primary table from backup\n");
1365 }
1366
1367 PartitionIndex = 0ULL;
1368
1369 /* If no partitions are to be copied, just restore header */
1370 if (SectorsForPartitions <= 0)
1371 {
1373 SectorsForPartitions,
1374 EFIHeader->DiskGUID,
1375 EFIHeader->NumberOfEntries,
1376 EFIHeader->FirstUsableLBA,
1377 EFIHeader->LastUsableLBA,
1378 EFIHeader->PartitionEntryCRC32,
1379 WriteBackup);
1380
1381 goto Cleanup;
1382 }
1383
1384 /* Copy all the partitions */
1385 for (; PartitionIndex < SectorsForPartitions; ++PartitionIndex)
1386 {
1387 /* First, read the partition from the first table */
1388 Status = FstubReadSector(Disk->DeviceObject,
1389 Disk->SectorSize,
1390 ReadPosition + PartitionIndex,
1391 Disk->Buffer);
1392 if (!NT_SUCCESS(Status))
1393 {
1394 goto Cleanup;
1395 }
1396
1397 /* Then, write it in the other table */
1398 Status = FstubWriteSector(Disk->DeviceObject,
1399 Disk->SectorSize,
1400 WritePosition + PartitionIndex,
1401 Disk->Buffer);
1402 if (!NT_SUCCESS(Status))
1403 {
1404 goto Cleanup;
1405 }
1406 }
1407
1408 /* Now we're done, write the header */
1410 SectorsForPartitions,
1411 EFIHeader->DiskGUID,
1412 EFIHeader->NumberOfEntries,
1413 EFIHeader->FirstUsableLBA,
1414 EFIHeader->LastUsableLBA,
1415 EFIHeader->PartitionEntryCRC32,
1416 WriteBackup);
1417
1418Cleanup:
1419 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1420 return Status;
1421}
1422
1424NTAPI
1426{
1428 ULONG Signature = 0;
1429 PMASTER_BOOT_RECORD MasterBootRecord;
1430
1431 PAGED_CODE();
1432
1433 ASSERT(Disk);
1435
1436 /* Read if a MBR is already present */
1437 Status = FstubReadSector(Disk->DeviceObject,
1438 Disk->SectorSize,
1439 0ULL,
1440 Disk->Buffer);
1441 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
1442 /* If one has been found */
1444 {
1445 /* Save its signature */
1446 Signature = MasterBootRecord->Signature;
1447 }
1448
1449 /* Reset the MBR */
1450 RtlZeroMemory(MasterBootRecord, Disk->SectorSize);
1451 /* Then create a fake MBR matching those purposes:
1452 * It must have only partition. Type of this partition
1453 * has to be 0xEE to signal a GPT is following.
1454 * This partition has to cover the whole disk. To prevent
1455 * any disk modification by a program that wouldn't
1456 * understand anything to GPT.
1457 */
1458 MasterBootRecord->Signature = Signature;
1459 MasterBootRecord->PartitionTable[0].StartSector = 2;
1460 MasterBootRecord->PartitionTable[0].SystemIndicator = EFI_PMBR_OSTYPE_EFI;
1461 MasterBootRecord->PartitionTable[0].EndHead = 0xFF;
1462 MasterBootRecord->PartitionTable[0].EndSector = 0xFF;
1463 MasterBootRecord->PartitionTable[0].EndCylinder = 0xFF;
1464 MasterBootRecord->PartitionTable[0].SectorCountBeforePartition = 1;
1465 MasterBootRecord->PartitionTable[0].PartitionSectorCount = 0xFFFFFFFF;
1466 MasterBootRecord->MasterBootRecordMagic = BOOT_RECORD_SIGNATURE;
1467
1468 /* Finally, write that MBR */
1469 return FstubWriteSector(Disk->DeviceObject,
1470 Disk->SectorSize,
1471 0,
1472 Disk->Buffer);
1473}
1474
1476NTAPI
1478 IN ULONG PartitionsSizeSector,
1479 IN ULONG PartitionEntryNumber,
1480 IN PEFI_PARTITION_ENTRY PartitionEntry,
1481 IN BOOLEAN WriteBackupTable,
1482 IN BOOLEAN ForceWrite,
1483 OUT PULONG PartitionEntryCRC32 OPTIONAL)
1484{
1486 ULONG Offset;
1487 ULONGLONG FirstEntryLBA;
1488
1489 PAGED_CODE();
1490
1491 ASSERT(Disk);
1493
1494 /* Get the first LBA where the partition table is:
1495 * On primary table, it's sector 2 (skip MBR & Header)
1496 * On backup table, it's ante last sector (Header) minus partition table size
1497 */
1498 if (!WriteBackupTable)
1499 {
1500 FirstEntryLBA = 2ULL;
1501 }
1502 else
1503 {
1504 FirstEntryLBA = Disk->SectorCount - PartitionsSizeSector - 1;
1505 }
1506
1507 /* Copy the entry at the proper place into the buffer
1508 * That way, we don't erase previous entries
1509 */
1510 RtlCopyMemory((PVOID)((ULONG_PTR)Disk->Buffer + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize)),
1511 PartitionEntry,
1512 sizeof(EFI_PARTITION_ENTRY));
1513 /* Compute size of buffer */
1514 Offset = (PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize + PARTITION_ENTRY_SIZE;
1515 ASSERT(Offset <= Disk->SectorSize);
1516
1517 /* If it's full of partition entries, or if call ask for it, write down the data */
1518 if (Offset == Disk->SectorSize || ForceWrite)
1519 {
1520 /* We will write at first entry LBA + a shift made by already present/written entries */
1521 Status = FstubWriteSector(Disk->DeviceObject,
1522 Disk->SectorSize,
1523 FirstEntryLBA + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) / Disk->SectorSize),
1524 Disk->Buffer);
1525 if (!NT_SUCCESS(Status))
1526 {
1527 return Status;
1528 }
1529
1530 /* We clean buffer */
1531 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
1532 }
1533
1534 /* If we have a buffer for CRC32, then compute it */
1535 if (PartitionEntryCRC32)
1536 {
1537 *PartitionEntryCRC32 = RtlComputeCrc32(*PartitionEntryCRC32, (PUCHAR)PartitionEntry, PARTITION_ENTRY_SIZE);
1538 }
1539
1540 return Status;
1541}
1542
1544NTAPI
1546 IN ULONG PartitionsSizeSector,
1547 IN GUID DiskGUID,
1548 IN ULONG NumberOfEntries,
1549 IN ULONGLONG FirstUsableLBA,
1550 IN ULONGLONG LastUsableLBA,
1551 IN ULONG PartitionEntryCRC32,
1552 IN BOOLEAN WriteBackupTable)
1553{
1554 PEFI_PARTITION_HEADER EFIHeader;
1555
1556 PAGED_CODE();
1557
1558 ASSERT(Disk);
1560
1561 /* Let's use read buffer as EFI_PARTITION_HEADER */
1562 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
1563
1564 /* Complete standard header information */
1565 EFIHeader->Signature = EFI_HEADER_SIGNATURE;
1566 EFIHeader->Revision = EFI_HEADER_REVISION_1;
1567 EFIHeader->HeaderSize = sizeof(EFI_PARTITION_HEADER);
1568 /* Set no CRC32 checksum at the moment */
1569 EFIHeader->HeaderCRC32 = 0;
1570 EFIHeader->Reserved = 0;
1571 /* Check whether we're writing primary or backup
1572 * That way, we can ajust LBA setting:
1573 * Primary is on first sector
1574 * Backup is on last sector
1575 */
1576 if (!WriteBackupTable)
1577 {
1578 EFIHeader->MyLBA = 1ULL;
1579 EFIHeader->AlternateLBA = Disk->SectorCount - 1ULL;
1580 }
1581 else
1582 {
1583 EFIHeader->MyLBA = Disk->SectorCount - 1ULL;
1584 EFIHeader->AlternateLBA = 1ULL;
1585 }
1586 /* Fill in with received data */
1587 EFIHeader->FirstUsableLBA = FirstUsableLBA;
1588 EFIHeader->LastUsableLBA = LastUsableLBA;
1589 EFIHeader->DiskGUID = DiskGUID;
1590 /* Check whether we're writing primary or backup
1591 * That way, we can ajust LBA setting:
1592 * On primary, partition entries are just after header, so sector 2
1593 * On backup, partition entries are just before header, so, last sector minus partition table size
1594 */
1595 if (!WriteBackupTable)
1596 {
1597 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA + 1ULL;
1598 }
1599 else
1600 {
1601 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA - PartitionsSizeSector;
1602 }
1603 /* Complete filling in */
1604 EFIHeader->NumberOfEntries = NumberOfEntries;
1606 EFIHeader->PartitionEntryCRC32 = PartitionEntryCRC32;
1607 /* Finally, compute header checksum */
1608 EFIHeader->HeaderCRC32 = RtlComputeCrc32(0, (PUCHAR)EFIHeader, sizeof(EFI_PARTITION_HEADER));
1609
1610 /* Debug the way we'll break disk, to let user pray */
1611 DPRINT("FSTUB: About to write the following header for %s table\n", (WriteBackupTable ? "backup" : "primary"));
1612 DPRINT(" Signature: %I64x\n", EFIHeader->Signature);
1613 DPRINT(" Revision: %x\n", EFIHeader->Revision);
1614 DPRINT(" HeaderSize: %x\n", EFIHeader->HeaderSize);
1615 DPRINT(" HeaderCRC32: %x\n", EFIHeader->HeaderCRC32);
1616 DPRINT(" MyLBA: %I64x\n", EFIHeader->MyLBA);
1617 DPRINT(" AlternateLBA: %I64x\n", EFIHeader->AlternateLBA);
1618 DPRINT(" FirstUsableLBA: %I64x\n", EFIHeader->FirstUsableLBA);
1619 DPRINT(" LastUsableLBA: %I64x\n", EFIHeader->LastUsableLBA);
1620 DPRINT(" PartitionEntryLBA: %I64x\n", EFIHeader->PartitionEntryLBA);
1621 DPRINT(" NumberOfEntries: %x\n", EFIHeader->NumberOfEntries);
1622 DPRINT(" SizeOfPartitionEntry: %x\n", EFIHeader->SizeOfPartitionEntry);
1623 DPRINT(" PartitionEntryCRC32: %x\n", EFIHeader->PartitionEntryCRC32);
1624
1625 /* Write header to disk */
1626 return FstubWriteSector(Disk->DeviceObject,
1627 Disk->SectorSize,
1628 EFIHeader->MyLBA,
1629 Disk->Buffer);
1630}
1631
1633NTAPI
1635 IN GUID DiskGUID,
1636 IN ULONG MaxPartitionCount,
1637 IN ULONGLONG FirstUsableLBA,
1638 IN ULONGLONG LastUsableLBA,
1639 IN BOOLEAN WriteBackupTable,
1640 IN ULONG PartitionCount,
1641 IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
1642{
1645 ULONG i, WrittenPartitions, SectoredPartitionEntriesSize, PartitionEntryCRC32;
1646
1647 PAGED_CODE();
1648
1649 ASSERT(Disk);
1650 ASSERT(MaxPartitionCount >= 128);
1651 ASSERT(PartitionCount <= MaxPartitionCount);
1652
1653 PartitionEntryCRC32 = 0;
1654 /* Count how much sectors we'll have to read to read the whole partition table */
1655 SectoredPartitionEntriesSize = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1656
1657 for (i = 0, WrittenPartitions = 0; i < PartitionCount; i++)
1658 {
1659 /* If partition GUID is 00000000-0000-0000-0000-000000000000, then it's unused, skip it */
1660 if (PartitionEntries[i].Gpt.PartitionType.Data1 == 0 &&
1661 PartitionEntries[i].Gpt.PartitionType.Data2 == 0 &&
1662 PartitionEntries[i].Gpt.PartitionType.Data3 == 0 &&
1663 ((PULONGLONG)PartitionEntries[i].Gpt.PartitionType.Data4)[0] == 0)
1664 {
1665 continue;
1666 }
1667
1668 /* Copy the entry in the partition entry format */
1669 FstubCopyEntryEFI(&Entry, &PartitionEntries[i], Disk->SectorSize);
1670 /* Then write the entry to the disk */
1672 SectoredPartitionEntriesSize,
1673 WrittenPartitions,
1674 &Entry,
1675 WriteBackupTable,
1676 FALSE,
1677 &PartitionEntryCRC32);
1678 if (!NT_SUCCESS(Status))
1679 {
1680 return Status;
1681 }
1682 WrittenPartitions++;
1683 }
1684
1685 /* Zero the buffer to write zeros to the disk */
1687 /* Write the disks with zeros for every unused remaining partition entry */
1688 for (i = WrittenPartitions; i < MaxPartitionCount; i++)
1689 {
1691 SectoredPartitionEntriesSize,
1692 i,
1693 &Entry,
1694 WriteBackupTable,
1695 FALSE,
1696 &PartitionEntryCRC32);
1697 if (!NT_SUCCESS(Status))
1698 {
1699 return Status;
1700 }
1701 }
1702
1703 /* Once we're done, write the GPT header */
1704 return FstubWriteHeaderEFI(Disk,
1705 SectoredPartitionEntriesSize,
1706 DiskGUID,
1707 MaxPartitionCount,
1708 FirstUsableLBA,
1709 LastUsableLBA,
1710 PartitionEntryCRC32,
1711 WriteBackupTable);
1712}
1713
1715NTAPI
1717 IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
1718{
1720 PDRIVE_LAYOUT_INFORMATION DriveLayout;
1721
1722 PAGED_CODE();
1723
1725 ASSERT(LayoutEx);
1726
1727 /* Convert data to the correct format */
1728 DriveLayout = FstubConvertExtendedToLayout(LayoutEx);
1729 if (!DriveLayout)
1730 {
1732 }
1733
1734 /* Really write information */
1735 Status = IoWritePartitionTable(Disk->DeviceObject,
1736 Disk->SectorSize,
1737 Disk->DiskGeometry.Geometry.SectorsPerTrack,
1738 Disk->DiskGeometry.Geometry.TracksPerCylinder,
1739 DriveLayout);
1740
1741 /* Free allocated structure and return */
1742 ExFreePoolWithTag(DriveLayout, TAG_FSTUB);
1743 return Status;
1744}
1745
1747NTAPI
1750 IN ULONGLONG StartingSector OPTIONAL,
1751 IN PVOID Buffer)
1752{
1754 PIRP Irp;
1755 KEVENT Event;
1758 PIO_STACK_LOCATION IoStackLocation;
1759
1760 PAGED_CODE();
1761
1763 ASSERT(Buffer);
1765
1766 /* Compute starting offset */
1767 StartingOffset.QuadPart = StartingSector * SectorSize;
1768
1769 /* Initialize waiting event */
1771
1772 /* Prepare IRP */
1775 Buffer,
1776 SectorSize,
1778 &Event,
1779 &IoStatusBlock);
1780 if (!Irp)
1781 {
1783 }
1784
1785 /* Override volume verify */
1786 IoStackLocation = IoGetNextIrpStackLocation(Irp);
1787 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1788
1789 /* Then call driver, and wait for completion if needed */
1791 if (Status == STATUS_PENDING)
1792 {
1795 }
1796
1797 return Status;
1798}
1799
1800/* FUNCTIONS *****************************************************************/
1801
1802/*
1803 * @implemented
1804 */
1806NTAPI
1808 IN PCREATE_DISK Disk)
1809{
1810 PARTITION_STYLE PartitionStyle;
1811
1812 PAGED_CODE();
1813
1815
1816 /* Get partition style. If caller didn't provided data, assume it's raw */
1817 PartitionStyle = ((Disk) ? Disk->PartitionStyle : PARTITION_STYLE_RAW);
1818 /* Then, call appropriate internal function */
1819 switch (PartitionStyle)
1820 {
1822 return FstubCreateDiskMBR(DeviceObject, &(Disk->Mbr));
1824 return FstubCreateDiskEFI(DeviceObject, &(Disk->Gpt));
1825 case PARTITION_STYLE_RAW:
1827 default:
1828 return STATUS_NOT_SUPPORTED;
1829 }
1830}
1831
1832/*
1833 * @implemented
1834 */
1836NTAPI
1838 IN ULONG Size)
1839{
1841 PIRP Irp;
1842 KEVENT Event;
1843 PLIST_ENTRY NextEntry;
1845 DISK_GEOMETRY DiskGeometry;
1847 UNICODE_STRING DeviceStringW;
1849 CHAR Buffer[128], ArcBuffer[128];
1850 BOOLEAN SingleDisk, IsBootDiskInfoEx;
1851 PARC_DISK_SIGNATURE ArcDiskSignature;
1852 PARC_DISK_INFORMATION ArcDiskInformation;
1853 PARTITION_INFORMATION_EX PartitionInformation;
1854 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
1855 ULONG DiskCount, DiskNumber, Signature, PartitionNumber;
1856 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA;
1858
1859 PAGED_CODE();
1860
1861 /* Get loader block. If it's null, we come too late */
1862 if (!IopLoaderBlock)
1863 {
1864 return STATUS_TOO_LATE;
1865 }
1866
1867 /* Check buffer size */
1868 if (Size < sizeof(BOOTDISK_INFORMATION))
1869 {
1871 }
1872
1873 /* Init some useful stuff:
1874 * Get ARC disks information
1875 * Check whether we have a single disk on the machine
1876 * Check received structure size (extended or not?)
1877 * Init boot strings (system/boot)
1878 * Finaly, get disk count
1879 */
1880 ArcDiskInformation = IopLoaderBlock->ArcDiskInformation;
1881 SingleDisk = (ArcDiskInformation->DiskSignatureListHead.Flink->Flink ==
1882 &ArcDiskInformation->DiskSignatureListHead);
1883
1884 IsBootDiskInfoEx = (Size >= sizeof(BOOTDISK_INFORMATION_EX));
1888
1889 /* If no disk, return success */
1890 if (DiskCount == 0)
1891 {
1892 return STATUS_SUCCESS;
1893 }
1894
1895 /* Now, browse all disks */
1896 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
1897 {
1898 /* Create the device name */
1899 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
1900 RtlInitAnsiString(&DeviceStringA, Buffer);
1901 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1902 if (!NT_SUCCESS(Status))
1903 {
1904 continue;
1905 }
1906
1907 /* Get its device object */
1908 Status = IoGetDeviceObjectPointer(&DeviceStringW,
1910 &FileObject,
1911 &DeviceObject);
1912 RtlFreeUnicodeString(&DeviceStringW);
1913 if (!NT_SUCCESS(Status))
1914 {
1915 continue;
1916 }
1917
1918 /* Prepare for getting disk geometry */
1922 NULL,
1923 0,
1924 &DiskGeometry,
1925 sizeof(DiskGeometry),
1926 FALSE,
1927 &Event,
1928 &IoStatusBlock);
1929 if (!Irp)
1930 {
1932 continue;
1933 }
1934
1935 /* Then, call the drive, and wait for it if needed */
1937 if (Status == STATUS_PENDING)
1938 {
1941 }
1942 if (!NT_SUCCESS(Status))
1943 {
1945 continue;
1946 }
1947
1948 /* Read partition table */
1950 &DriveLayout);
1951
1952 /* FileObject, you can go! */
1954
1955 if (!NT_SUCCESS(Status))
1956 {
1957 continue;
1958 }
1959
1960 /* Ensure we have at least 512 bytes per sector */
1961 if (DiskGeometry.BytesPerSector < 512)
1962 {
1963 DiskGeometry.BytesPerSector = 512;
1964 }
1965
1966 /* Now, for each ARC disk, try to find the matching */
1967 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
1968 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
1969 NextEntry = NextEntry->Flink)
1970 {
1971 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
1973 ListEntry);
1974 /* If they match, i.e.
1975 * - There's only one disk for both BIOS and detected
1976 * - Signatures are matching
1977 * - This is MBR
1978 * (We don't check checksums here)
1979 */
1980 if (((SingleDisk && DiskCount == 1) ||
1981 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature))) &&
1982 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
1983 {
1984 /* Create ARC name */
1985 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
1986 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
1987
1988 /* Browse all partitions */
1989 for (PartitionNumber = 1; PartitionNumber <= DriveLayout->PartitionCount; PartitionNumber++)
1990 {
1991 /* Create its device name */
1992 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, PartitionNumber);
1993 RtlInitAnsiString(&DeviceStringA, Buffer);
1994 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1995 if (!NT_SUCCESS(Status))
1996 {
1997 continue;
1998 }
1999
2000 /* If IopVerifyDiskSignature returned no signature, take the one from DriveLayout */
2001 if (!Signature)
2002 {
2003 Signature = DriveLayout->Mbr.Signature;
2004 }
2005
2006 /* Create partial ARC name */
2007 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, PartitionNumber);
2008 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
2009
2010 /* If it's matching boot string */
2011 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
2012 {
2013 /* Then, fill in information about boot device */
2014 BootDiskInformation->BootDeviceSignature = Signature;
2015
2016 /* Get its device object */
2017 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2019 &FileObject,
2020 &DeviceObject);
2021 if (!NT_SUCCESS(Status))
2022 {
2023 RtlFreeUnicodeString(&DeviceStringW);
2024 continue;
2025 }
2026
2027 /* And call the drive to get information about partition */
2031 NULL,
2032 0,
2033 &PartitionInformation,
2034 sizeof(PartitionInformation),
2035 FALSE,
2036 &Event,
2037 &IoStatusBlock);
2038 if (!Irp)
2039 {
2041 RtlFreeUnicodeString(&DeviceStringW);
2042 continue;
2043 }
2044
2045 /* Call & wait if needed */
2047 if (Status == STATUS_PENDING)
2048 {
2051 }
2052 if (!NT_SUCCESS(Status))
2053 {
2055 RtlFreeUnicodeString(&DeviceStringW);
2056 continue;
2057 }
2058
2059 /* We get partition offset as demanded and return it */
2060 BootDiskInformation->BootPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2061
2062 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2063 if (IsBootDiskInfoEx)
2064 {
2065 /* Is partition style MBR or GPT? */
2066 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2067 {
2068 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceGuid = DriveLayout->Gpt.DiskId;
2069 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = TRUE;
2070 }
2071 else
2072 {
2073 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = FALSE;
2074 }
2075 }
2076
2077 /* Dereference FileObject */
2079 }
2080
2081 /* If it's matching system string */
2082 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
2083 {
2084 /* Then, fill in information about the system device */
2085 BootDiskInformation->SystemDeviceSignature = Signature;
2086
2087 /* Get its device object */
2088 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2090 &FileObject,
2091 &DeviceObject);
2092 if (!NT_SUCCESS(Status))
2093 {
2094 RtlFreeUnicodeString(&DeviceStringW);
2095 continue;
2096 }
2097
2098 /* And call the drive to get information about partition */
2102 NULL,
2103 0,
2104 &PartitionInformation,
2105 sizeof(PartitionInformation),
2106 FALSE,
2107 &Event,
2108 &IoStatusBlock);
2109 if (!Irp)
2110 {
2112 RtlFreeUnicodeString(&DeviceStringW);
2113 continue;
2114 }
2115
2116 /* Call & wait if needed */
2118 if (Status == STATUS_PENDING)
2119 {
2122 }
2123 if (!NT_SUCCESS(Status))
2124 {
2126 RtlFreeUnicodeString(&DeviceStringW);
2127 continue;
2128 }
2129
2130 /* We get partition offset as demanded and return it */
2131 BootDiskInformation->SystemPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2132
2133 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2134 if (IsBootDiskInfoEx)
2135 {
2136 /* Is partition style MBR or GPT? */
2137 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2138 {
2139 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceGuid = DriveLayout->Gpt.DiskId;
2140 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = TRUE;
2141 }
2142 else
2143 {
2144 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = FALSE;
2145 }
2146 }
2147
2148 /* Dereference FileObject */
2150 }
2151
2152 /* Release device string */
2153 RtlFreeUnicodeString(&DeviceStringW);
2154 }
2155 }
2156 }
2157
2158 /* Finally, release drive layout */
2159 ExFreePool(DriveLayout);
2160 }
2161
2162 /* And return */
2163 return Status;
2164}
2165
2166/*
2167 * @implemented
2168 */
2170NTAPI
2172 IN ULONG BytesPerSector,
2174{
2176 PUCHAR Buffer;
2177 ULONG HeaderCRC32, i, CheckSum;
2178 PEFI_PARTITION_HEADER EFIHeader;
2179 PPARTITION_DESCRIPTOR PartitionDescriptor;
2180
2181 PAGED_CODE();
2182
2183 /* Ensure we'll read at least 512 bytes */
2184 if (BytesPerSector < 512)
2185 {
2186 BytesPerSector = 512;
2187 }
2188
2189 /* Allocate a buffer for reading operations */
2191 if (!Buffer)
2192 {
2193 return STATUS_NO_MEMORY;
2194 }
2195
2196 /* Read first sector (sector 0) for MBR */
2198 BytesPerSector,
2199 0ULL,
2200 Buffer);
2201 if (!NT_SUCCESS(Status))
2202 {
2203 goto Cleanup;
2204 }
2205
2206 /* Get the partition descriptor array */
2207 PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2209 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
2210 if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
2211 PartitionDescriptor[1].PartitionType == 0 &&
2212 PartitionDescriptor[2].PartitionType == 0 &&
2213 PartitionDescriptor[3].PartitionType == 0)
2214 {
2215 /* If we have GPT, read second sector (sector 1) for GPT header */
2217 BytesPerSector,
2218 1ULL,
2219 Buffer);
2220 if (!NT_SUCCESS(Status))
2221 {
2222 goto Cleanup;
2223 }
2224 EFIHeader = (PEFI_PARTITION_HEADER)Buffer;
2225
2226 /* First check signature
2227 * Then, check version (we only support v1
2228 * Finally check header size
2229 */
2230 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
2231 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
2232 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
2233 {
2235 goto Cleanup;
2236 }
2237
2238 /* Save current checksum */
2239 HeaderCRC32 = EFIHeader->HeaderCRC32;
2240 /* Then zero the one in EFI header. This is needed to compute header checksum */
2241 EFIHeader->HeaderCRC32 = 0;
2242 /* Compute header checksum and compare with the one present in partition table */
2243 if (RtlComputeCrc32(0, Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
2244 {
2246 goto Cleanup;
2247 }
2248
2249 /* Set partition table style to GPT and return disk GUID */
2250 Signature->PartitionStyle = PARTITION_STYLE_GPT;
2251 Signature->Gpt.DiskId = EFIHeader->DiskGUID;
2252 }
2253 else
2254 {
2255 /* Compute MBR checksum */
2256 for (i = 0, CheckSum = 0; i < 512; i += sizeof(UINT32))
2257 {
2258 CheckSum += *(PUINT32)&Buffer[i];
2259 }
2260 CheckSum = ~CheckSum + 1;
2261
2262 /* Set partition table style to MBR and return signature (offset 440) and checksum */
2263 Signature->PartitionStyle = PARTITION_STYLE_MBR;
2264 Signature->Mbr.Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
2265 Signature->Mbr.CheckSum = CheckSum;
2266 }
2267
2268Cleanup:
2269 /* Free buffer and return */
2271 return Status;
2272}
2273
2274/*
2275 * @implemented
2276 */
2278NTAPI
2280 IN PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout)
2281{
2283 PDISK_INFORMATION Disk;
2284 PARTITION_STYLE PartitionStyle;
2285
2286 PAGED_CODE();
2287
2289 ASSERT(DriveLayout);
2290
2291 /* First of all, allocate internal structure */
2293 if (!NT_SUCCESS(Status))
2294 {
2295 return Status;
2296 }
2297 ASSERT(Disk);
2298
2299 /* Then, detect partition style (MBR? GPT/EFI? RAW?) */
2300 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2301 if (!NT_SUCCESS(Status))
2302 {
2304 return Status;
2305 }
2306
2307 /* Here partition table is really read, depending on its style */
2308 switch (PartitionStyle)
2309 {
2311 case PARTITION_STYLE_RAW:
2312 Status = FstubReadPartitionTableMBR(Disk, FALSE, DriveLayout);
2313 break;
2314
2316 /* Read primary table */
2317 Status = FstubReadPartitionTableEFI(Disk, FALSE, DriveLayout);
2318 /* If it failed, try reading backup table */
2319 if (!NT_SUCCESS(Status))
2320 {
2321 Status = FstubReadPartitionTableEFI(Disk, TRUE, DriveLayout);
2322 }
2323 break;
2324
2325 default:
2326 DPRINT("Unknown partition type\n");
2328 }
2329
2330 /* It's over, internal structure not needed anymore */
2332
2333 /* In case of success, print data */
2334 if (NT_SUCCESS(Status))
2335 {
2336 FstubDbgPrintDriveLayoutEx(*DriveLayout);
2337 }
2338
2339 return Status;
2340}
2341
2342/*
2343 * @implemented
2344 */
2346NTAPI
2349 IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
2350{
2352 PDISK_INFORMATION Disk;
2353 PARTITION_STYLE PartitionStyle;
2354
2355 PAGED_CODE();
2356
2359
2360 /* Debug given modifications */
2362
2363 /* Allocate internal structure */
2365 if (!NT_SUCCESS(Status))
2366 {
2367 return Status;
2368 }
2369
2370 /* Get partition table style on disk */
2371 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2372 if (!NT_SUCCESS(Status))
2373 {
2375 return Status;
2376 }
2377
2378 /* If it's not matching partition style given in modifications, give up */
2379 if (PartitionInfo->PartitionStyle != PartitionStyle)
2380 {
2383 }
2384
2385 /* Finally, handle modifications using proper function */
2386 switch (PartitionStyle)
2387 {
2390 Disk->SectorSize,
2392 PartitionInfo->Mbr.PartitionType);
2393 break;
2397 &(PartitionInfo->Gpt));
2398 break;
2399 default:
2401 }
2402
2403 /* Release internal structure and return */
2405 return Status;
2406}
2407
2408/*
2409 * @implemented
2410 */
2412NTAPI
2415{
2417 PDISK_INFORMATION Disk;
2418 PARTITION_STYLE PartitionStyle;
2419
2420 PAGED_CODE();
2421
2423
2424 /* Allocate internal structure */
2426 if (!NT_SUCCESS(Status))
2427 {
2428 return Status;
2429 }
2430 ASSERT(Disk);
2431
2432 /* Get partition table style on disk */
2433 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2434 if (!NT_SUCCESS(Status))
2435 {
2437 return Status;
2438 }
2439
2440 /* Action will depend on partition style */
2441 switch (PartitionStyle)
2442 {
2443 /* For MBR, assume it's always OK */
2446 break;
2447 /* For GPT, call internal function */
2450 break;
2451 /* Otherwise, signal we can't work */
2452 default:
2454 }
2455
2456 /* Release internal structure and return */
2458 return Status;
2459}
2460
2461/*
2462 * @implemented
2463 */
2465NTAPI
2467 IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
2468{
2470 GUID DiskGuid;
2471 ULONG NumberOfEntries;
2472 PDISK_INFORMATION Disk;
2473 PEFI_PARTITION_HEADER EfiHeader;
2474 ULONGLONG SectorsForPartitions, FirstUsableLBA, LastUsableLBA;
2475
2476 PAGED_CODE();
2477
2479 ASSERT(DriveLayout);
2480
2481 /* Debug partition table that must be written */
2482 FstubDbgPrintDriveLayoutEx(DriveLayout);
2483
2484 /* Allocate internal structure */
2486 if (!NT_SUCCESS(Status))
2487 {
2488 return Status;
2489 }
2490 ASSERT(Disk);
2491
2492 switch (DriveLayout->PartitionStyle)
2493 {
2495 Status = FstubWritePartitionTableMBR(Disk, DriveLayout);
2496 break;
2497
2499 /* Read primary table header */
2501 FALSE,
2502 &EfiHeader);
2503 /* If it failed, try reading back table header */
2504 if (!NT_SUCCESS(Status))
2505 {
2507 TRUE,
2508 &EfiHeader);
2509 }
2510
2511 /* We have a header! */
2512 if (NT_SUCCESS(Status))
2513 {
2514 /* Check if there are enough places for the partitions to be written */
2515 if (DriveLayout->PartitionCount <= EfiHeader->NumberOfEntries)
2516 {
2517 /* Backup data */
2518 NumberOfEntries = EfiHeader->NumberOfEntries;
2519 RtlCopyMemory(&DiskGuid, &EfiHeader->DiskGUID, sizeof(GUID));
2520 /* Count number of sectors needed to store partitions */
2521 SectorsForPartitions = ((ULONGLONG)NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
2522 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
2523 FirstUsableLBA = SectorsForPartitions + 2;
2524 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
2525 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
2526 /* Write primary table */
2528 DiskGuid,
2529 NumberOfEntries,
2530 FirstUsableLBA,
2531 LastUsableLBA,
2532 FALSE,
2533 DriveLayout->PartitionCount,
2534 DriveLayout->PartitionEntry);
2535 /* If it succeeded, also update backup table */
2536 if (NT_SUCCESS(Status))
2537 {
2539 DiskGuid,
2540 NumberOfEntries,
2541 FirstUsableLBA,
2542 LastUsableLBA,
2543 TRUE,
2544 DriveLayout->PartitionCount,
2545 DriveLayout->PartitionEntry);
2546 }
2547 }
2548 else
2549 {
2551 }
2552 }
2553 break;
2554
2555 default:
2556 DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
2558 }
2559
2560 /* It's over, internal structure not needed anymore */
2562
2563 return Status;
2564}
2565
2566/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
unsigned int UINT32
LONG NTSTATUS
Definition: precomp.h:26
BOOL FixErrors
Definition: chkdsk.c:69
unsigned int * PUINT32
Definition: basetsd.h:125
unsigned short * PUINT16
Definition: basetsd.h:192
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: ntoskrnl.c:210
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:113
_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_PENDING
Definition: d3dkmdt.h:43
#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
PCHAR NTAPI FstubDbgGuidToString(IN PGUID Guid, OUT PCHAR String)
Definition: fstubex.c:535
#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:1748
VOID NTAPI FstubCopyEntryEFI(OUT PEFI_PARTITION_ENTRY Entry, IN PPARTITION_INFORMATION_EX Partition, ULONG SectorSize)
Definition: fstubex.c:320
NTSTATUS NTAPI IoGetBootDiskInformation(IN OUT PBOOTDISK_INFORMATION BootDiskInformation, IN ULONG Size)
Definition: fstubex.c:1837
NTSTATUS NTAPI FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
Definition: fstubex.c:457
NTSTATUS NTAPI FstubGetDiskGeometry(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_GEOMETRY_EX Geometry)
Definition: fstubex.c:731
NTSTATUS NTAPI IoCreateDisk(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK Disk)
Definition: fstubex.c:1807
NTSTATUS NTAPI FstubSetPartitionInformationEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionNumber, IN SET_PARTITION_INFORMATION_GPT *PartitionInfo)
Definition: fstubex.c:1246
VOID NTAPI FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer)
Definition: fstubex.c:717
NTSTATUS NTAPI IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
Definition: fstubex.c:2466
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:1545
NTSTATUS NTAPI FstubReadPartitionTableMBR(IN PDISK_INFORMATION Disk, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION_EX *ReturnedDriveLayout)
Definition: fstubex.c:1125
#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:209
NTSTATUS NTAPI IoSetPartitionInformationEx(IN PDEVICE_OBJECT DeviceObject, IN ULONG PartitionNumber, IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
Definition: fstubex.c:2347
struct _EFI_PARTITION_HEADER * PEFI_PARTITION_HEADER
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2279
NTSTATUS NTAPI FstubCreateDiskMBR(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_MBR DiskInfo)
Definition: fstubex.c:341
VOID NTAPI FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
Definition: fstubex.c:639
VOID NTAPI FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
Definition: fstubex.c:599
struct _MASTER_BOOT_RECORD MASTER_BOOT_RECORD
NTSTATUS NTAPI FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN FixErrors)
Definition: fstubex.c:1295
NTSTATUS NTAPI FstubReadHeaderEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, PEFI_PARTITION_HEADER *HeaderBuffer)
Definition: fstubex.c:825
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:1477
NTSTATUS NTAPI FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk, IN PARTITION_STYLE *PartitionStyle)
Definition: fstubex.c:670
NTSTATUS NTAPI IoVerifyPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FixErrors)
Definition: fstubex.c:2413
#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:172
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:1634
struct _EFI_PARTITION_ENTRY EFI_PARTITION_ENTRY
PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:272
struct _DISK_INFORMATION DISK_INFORMATION
NTSTATUS NTAPI FstubWritePartitionTableMBR(IN PDISK_INFORMATION Disk, IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:1716
NTSTATUS NTAPI IoReadDiskSignature(IN PDEVICE_OBJECT DeviceObject, IN ULONG BytesPerSector, OUT PDISK_SIGNATURE Signature)
Definition: fstubex.c:2171
#define EFI_HEADER_REVISION_1
Definition: fstubex.c:90
NTSTATUS NTAPI FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk)
Definition: fstubex.c:1425
VOID NTAPI FstubDbgPrintDriveLayoutEx(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
Definition: fstubex.c:557
NTSTATUS NTAPI FstubCreateDiskEFI(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_GPT DiskInfo)
Definition: fstubex.c:388
NTSTATUS NTAPI FstubReadSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, OUT PVOID Buffer)
Definition: fstubex.c:1192
NTSTATUS NTAPI FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:973
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 C_ASSERT(e)
Definition: intsafe.h:73
PLOADER_PARAMETER_BLOCK IopLoaderBlock
Definition: iomgr.c:87
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
#define for
Definition: utility.h:88
enum _PARTITION_STYLE PARTITION_STYLE
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define ULL(a, b)
Definition: format_msg.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define KernelMode
Definition: asm.h:34
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)
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:391
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
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:949
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
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:626
CHAR PartitionType
Definition: part_xbox.c:32
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
unsigned short USHORT
Definition: pedump.c:61
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#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
base of all file and directory entries
Definition: entries.h:83
Definition: parttest.c:75
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:268
PCHAR ArcName
Definition: arc.h:257
DISK_GEOMETRY Geometry
Definition: winioctl.h:330
LARGE_INTEGER DiskSize
Definition: winioctl.h:331
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:556
PSTR ArcBootDeviceName
Definition: arc.h:550
UCHAR MasterBootRecordCodeAndData[0x1b8]
Definition: disk.h:75
USHORT MasterBootRecordMagic
Definition: disk.h:79
PARTITION_TABLE_ENTRY PartitionTable[4]
Definition: disk.h:78
USHORT Reserved
Definition: disk.h:77
ULONG Signature
Definition: disk.h:76
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: disk.h:56
ULONG SectorCountBeforePartition
Definition: disk.h:66
ULONG PartitionSectorCount
Definition: disk.h:67
UCHAR BootIndicator
Definition: disk.h:57
UCHAR StartCylinder
Definition: disk.h:61
UCHAR StartSector
Definition: disk.h:60
UCHAR SystemIndicator
Definition: disk.h:62
UCHAR EndHead
Definition: disk.h:63
UCHAR EndSector
Definition: disk.h:64
UCHAR EndCylinder
Definition: disk.h:65
UCHAR StartHead
Definition: disk.h:59
#define TAG_FSTUB
Definition: tag.h:54
uint32_t * PULONG
Definition: typedefs.h:59
#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
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_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_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:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_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:415
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175