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