ReactOS 0.4.15-dev-7093-g01a8288
fstubex.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <pshpack1.h>
#include <poppack.h>
Include dependency graph for fstubex.c:

Go to the source code of this file.

Classes

struct  _DISK_INFORMATION
 
struct  _EFI_PARTITION_HEADER
 
struct  _EFI_PARTITION_ENTRY
 
struct  _PARTITION_TABLE_ENTRY
 
struct  _MASTER_BOOT_RECORD
 

Macros

#define NDEBUG
 
#define PARTITION_ENTRY_SIZE   128
 
#define EFI_HEADER_SIGNATURE   0x5452415020494645ULL
 
#define EFI_HEADER_REVISION_1   0x00010000
 
#define EFI_PMBR_OSTYPE_EFI   0xEE
 
#define EFI_GUID_STRING_SIZE   0x27
 
#define IS_VALID_DISK_INFO(Disk)
 

Typedefs

typedef struct _DISK_INFORMATION DISK_INFORMATION
 
typedef struct _DISK_INFORMATIONPDISK_INFORMATION
 
typedef struct _EFI_PARTITION_HEADER EFI_PARTITION_HEADER
 
typedef struct _EFI_PARTITION_HEADERPEFI_PARTITION_HEADER
 
typedef struct _EFI_PARTITION_ENTRY EFI_PARTITION_ENTRY
 
typedef struct _EFI_PARTITION_ENTRYPEFI_PARTITION_ENTRY
 
typedef struct _PARTITION_TABLE_ENTRY PARTITION_TABLE_ENTRY
 
typedef struct _PARTITION_TABLE_ENTRYPPARTITION_TABLE_ENTRY
 
typedef struct _MASTER_BOOT_RECORD MASTER_BOOT_RECORD
 
typedef struct _MASTER_BOOT_RECORDPMASTER_BOOT_RECORD
 

Functions

VOID NTAPI FstubDbgPrintPartitionEx (IN PPARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
 
NTSTATUS NTAPI FstubDetectPartitionStyle (IN PDISK_INFORMATION Disk, IN PARTITION_STYLE *PartitionStyle)
 
VOID NTAPI FstubFreeDiskInformation (IN PDISK_INFORMATION DiskBuffer)
 
NTSTATUS NTAPI FstubGetDiskGeometry (IN PDEVICE_OBJECT DeviceObject, OUT PDISK_GEOMETRY_EX Geometry)
 
NTSTATUS NTAPI FstubReadSector (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, OUT PVOID Buffer)
 
NTSTATUS NTAPI FstubWriteBootSectorEFI (IN PDISK_INFORMATION Disk)
 
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)
 
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)
 
NTSTATUS NTAPI FstubWriteSector (IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, IN PVOID Buffer)
 
VOID NTAPI FstubAdjustPartitionCount (IN ULONG SectorSize, IN OUT PULONG PartitionCount)
 
NTSTATUS NTAPI FstubAllocateDiskInformation (IN PDEVICE_OBJECT DeviceObject, OUT PDISK_INFORMATION *DiskBuffer, IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
 
PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout (IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
 
VOID NTAPI FstubCopyEntryEFI (OUT PEFI_PARTITION_ENTRY Entry, IN PPARTITION_INFORMATION_EX Partition, ULONG SectorSize)
 
NTSTATUS NTAPI FstubCreateDiskMBR (IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_MBR DiskInfo)
 
NTSTATUS NTAPI FstubCreateDiskEFI (IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_GPT DiskInfo)
 
NTSTATUS NTAPI FstubCreateDiskRaw (IN PDEVICE_OBJECT DeviceObject)
 
PCHAR NTAPI FstubDbgGuidToString (IN PGUID Guid, OUT PCHAR String)
 
VOID NTAPI FstubDbgPrintDriveLayoutEx (IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
 
VOID NTAPI FstubDbgPrintSetPartitionEx (IN PSET_PARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
 
NTSTATUS NTAPI FstubReadHeaderEFI (IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, PEFI_PARTITION_HEADER *HeaderBuffer)
 
NTSTATUS NTAPI FstubReadPartitionTableEFI (IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
 
NTSTATUS NTAPI FstubReadPartitionTableMBR (IN PDISK_INFORMATION Disk, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION_EX *ReturnedDriveLayout)
 
NTSTATUS NTAPI FstubSetPartitionInformationEFI (IN PDISK_INFORMATION Disk, IN ULONG PartitionNumber, IN SET_PARTITION_INFORMATION_GPT *PartitionInfo)
 
NTSTATUS NTAPI FstubVerifyPartitionTableEFI (IN PDISK_INFORMATION Disk, IN BOOLEAN FixErrors)
 
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)
 
NTSTATUS NTAPI FstubWritePartitionTableMBR (IN PDISK_INFORMATION Disk, IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
 
NTSTATUS NTAPI IoCreateDisk (IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK Disk)
 
NTSTATUS NTAPI IoGetBootDiskInformation (IN OUT PBOOTDISK_INFORMATION BootDiskInformation, IN ULONG Size)
 
NTSTATUS NTAPI IoReadDiskSignature (IN PDEVICE_OBJECT DeviceObject, IN ULONG BytesPerSector, OUT PDISK_SIGNATURE Signature)
 
NTSTATUS NTAPI IoReadPartitionTableEx (IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
 
NTSTATUS NTAPI IoSetPartitionInformationEx (IN PDEVICE_OBJECT DeviceObject, IN ULONG PartitionNumber, IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
 
NTSTATUS NTAPI IoVerifyPartitionTable (IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FixErrors)
 
NTSTATUS NTAPI IoWritePartitionTableEx (IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
 

Macro Definition Documentation

◆ EFI_GUID_STRING_SIZE

#define EFI_GUID_STRING_SIZE   0x27

Definition at line 88 of file fstubex.c.

◆ EFI_HEADER_REVISION_1

#define EFI_HEADER_REVISION_1   0x00010000

Definition at line 84 of file fstubex.c.

◆ EFI_HEADER_SIGNATURE

#define EFI_HEADER_SIGNATURE   0x5452415020494645ULL

Definition at line 82 of file fstubex.c.

◆ EFI_PMBR_OSTYPE_EFI

#define EFI_PMBR_OSTYPE_EFI   0xEE

Definition at line 86 of file fstubex.c.

◆ IS_VALID_DISK_INFO

#define IS_VALID_DISK_INFO (   Disk)
Value:
(Disk) && \
(Disk->DeviceObject) && \
(Disk->SectorSize) && \
(Disk->Buffer) && \
(Disk->SectorCount)

Definition at line 90 of file fstubex.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file fstubex.c.

◆ PARTITION_ENTRY_SIZE

#define PARTITION_ENTRY_SIZE   128

Definition at line 80 of file fstubex.c.

Typedef Documentation

◆ DISK_INFORMATION

◆ EFI_PARTITION_ENTRY

◆ EFI_PARTITION_HEADER

◆ MASTER_BOOT_RECORD

◆ PARTITION_TABLE_ENTRY

◆ PDISK_INFORMATION

◆ PEFI_PARTITION_ENTRY

◆ PEFI_PARTITION_HEADER

◆ PMASTER_BOOT_RECORD

◆ PPARTITION_TABLE_ENTRY

Function Documentation

◆ FstubAdjustPartitionCount()

VOID NTAPI FstubAdjustPartitionCount ( IN ULONG  SectorSize,
IN OUT PULONG  PartitionCount 
)

Definition at line 166 of file fstubex.c.

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}
#define PAGED_CODE()
#define PARTITION_ENTRY_SIZE
Definition: fstubex.c:80
#define ASSERT(a)
Definition: mode.c:44
int Count
Definition: noreturn.cpp:7
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG SectorSize
Definition: halfuncs.h:291

Referenced by FstubCreateDiskEFI().

◆ FstubAllocateDiskInformation()

NTSTATUS NTAPI FstubAllocateDiskInformation ( IN PDEVICE_OBJECT  DeviceObject,
OUT PDISK_INFORMATION DiskBuffer,
IN PDISK_GEOMETRY_EX DiskGeometry  OPTIONAL 
)

Definition at line 203 of file fstubex.c.

206{
208 PDISK_INFORMATION DiskInformation;
209
210 PAGED_CODE();
211
213 ASSERT(DiskBuffer);
214
215 /* Allocate internal structure */
217 if (!DiskInformation)
218 {
220 }
221
222 /* If caller don't pass needed information, let's get them */
223 if (!DiskGeometry)
224 {
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}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPoolCacheAligned
Definition: env_spec_w32.h:310
#define NonPagedPool
Definition: env_spec_w32.h:307
NTSTATUS NTAPI FstubGetDiskGeometry(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_GEOMETRY_EX Geometry)
Definition: fstubex.c:725
Status
Definition: gdiplustypes.h:25
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define STATUS_SUCCESS
Definition: shellext.h:65
DISK_GEOMETRY Geometry
Definition: winioctl.h:330
LARGE_INTEGER DiskSize
Definition: winioctl.h:331
ULONG BytesPerSector
Definition: ntdddisk.h:409
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
#define TAG_FSTUB
Definition: tag.h:54
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

Referenced by FstubCreateDiskEFI(), FstubCreateDiskMBR(), FstubCreateDiskRaw(), IoReadPartitionTableEx(), IoSetPartitionInformationEx(), IoVerifyPartitionTable(), and IoWritePartitionTableEx().

◆ FstubConvertExtendedToLayout()

PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout ( IN PDRIVE_LAYOUT_INFORMATION_EX  LayoutEx)

Definition at line 266 of file fstubex.c.

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 */
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}
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
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
@ PARTITION_STYLE_MBR
Definition: imports.h:201
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:426
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:413
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:414
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:419
BOOLEAN RewritePartition
Definition: ntdddisk.h:420
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by FstubWritePartitionTableMBR().

◆ FstubCopyEntryEFI()

VOID NTAPI FstubCopyEntryEFI ( OUT PEFI_PARTITION_ENTRY  Entry,
IN PPARTITION_INFORMATION_EX  Partition,
ULONG  SectorSize 
)

Definition at line 314 of file fstubex.c.

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}
base of all file and directory entries
Definition: entries.h:83

Referenced by FstubWritePartitionTableEFI().

◆ FstubCreateDiskEFI()

NTSTATUS NTAPI FstubCreateDiskEFI ( IN PDEVICE_OBJECT  DeviceObject,
IN PCREATE_DISK_GPT  DiskInfo 
)

Definition at line 382 of file fstubex.c.

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}
#define TRUE
Definition: types.h:120
VOID NTAPI FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer)
Definition: fstubex.c:711
NTSTATUS NTAPI FstubAllocateDiskInformation(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_INFORMATION *DiskBuffer, IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
Definition: fstubex.c:203
VOID NTAPI FstubAdjustPartitionCount(IN ULONG SectorSize, IN OUT PULONG PartitionCount)
Definition: fstubex.c:166
NTSTATUS NTAPI FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk, IN GUID DiskGUID, IN ULONG MaxPartitionCount, IN ULONGLONG FirstUsableLBA, IN ULONGLONG LastUsableLBA, IN BOOLEAN WriteBackupTable, IN ULONG PartitionCount, IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
Definition: fstubex.c:1628
NTSTATUS NTAPI FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk)
Definition: fstubex.c:1419
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by IoCreateDisk().

◆ FstubCreateDiskMBR()

NTSTATUS NTAPI FstubCreateDiskMBR ( IN PDEVICE_OBJECT  DeviceObject,
IN PCREATE_DISK_MBR  DiskInfo 
)

Definition at line 335 of file fstubex.c.

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;
368
369 /* Finally, write MBR */
371 Disk->SectorSize,
372 0ULL,
373 Disk->Buffer);
374
375 /* Release internal structure and return */
377 return Status;
378}
NTSTATUS NTAPI FstubWriteSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, IN PVOID Buffer)
Definition: fstubex.c:1742
struct _MASTER_BOOT_RECORD * PMASTER_BOOT_RECORD
NTSTATUS NTAPI FstubReadSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, OUT PVOID Buffer)
Definition: fstubex.c:1186
#define ULL(a, b)
Definition: format_msg.c:27
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:248
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
Definition: parttest.c:75
USHORT MasterBootRecordMagic
Definition: disk.h:78
PARTITION_TABLE_ENTRY PartitionTable[4]
Definition: disk.h:77
ULONG Signature
Definition: disk.h:75
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by IoCreateDisk().

◆ FstubCreateDiskRaw()

NTSTATUS NTAPI FstubCreateDiskRaw ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 451 of file fstubex.c.

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}
NTSTATUS NTAPI FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk, IN PARTITION_STYLE *PartitionStyle)
Definition: fstubex.c:664
enum _PARTITION_STYLE PARTITION_STYLE
@ PARTITION_STYLE_GPT
Definition: imports.h:202

Referenced by IoCreateDisk().

◆ FstubDbgGuidToString()

PCHAR NTAPI FstubDbgGuidToString ( IN PGUID  Guid,
OUT PCHAR  String 
)

Definition at line 529 of file fstubex.c.

531{
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}
#define sprintf(buf, format,...)
Definition: sprintf.c:55
_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

Referenced by FstubDbgPrintDriveLayoutEx(), FstubDbgPrintPartitionEx(), and FstubDbgPrintSetPartitionEx().

◆ FstubDbgPrintDriveLayoutEx()

VOID NTAPI FstubDbgPrintDriveLayoutEx ( IN PDRIVE_LAYOUT_INFORMATION_EX  DriveLayout)

Definition at line 551 of file fstubex.c.

552{
553 ULONG i;
555
556 PAGED_CODE();
557
558 DPRINT("FSTUB: DRIVE_LAYOUT_INFORMATION_EX: %p\n", DriveLayout);
559 switch (DriveLayout->PartitionStyle)
560 {
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;
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}
#define EFI_GUID_STRING_SIZE
Definition: fstubex.c:88
PCHAR NTAPI FstubDbgGuidToString(IN PGUID Guid, OUT PCHAR String)
Definition: fstubex.c:529
VOID NTAPI FstubDbgPrintPartitionEx(IN PPARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
Definition: fstubex.c:593
#define DPRINT
Definition: sndvol32.h:71
char CHAR
Definition: xmlstorage.h:175

Referenced by IoReadPartitionTableEx(), and IoWritePartitionTableEx().

◆ FstubDbgPrintPartitionEx()

VOID NTAPI FstubDbgPrintPartitionEx ( IN PPARTITION_INFORMATION_EX  PartitionEntry,
IN ULONG  PartitionNumber 
)

Definition at line 593 of file fstubex.c.

595{
597
598 PAGED_CODE();
599
600 DPRINT("Printing partition %lu\n", PartitionNumber);
601
602 switch (PartitionEntry[PartitionNumber].PartitionStyle)
603 {
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;
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}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061

Referenced by FstubDbgPrintDriveLayoutEx().

◆ FstubDbgPrintSetPartitionEx()

VOID NTAPI FstubDbgPrintSetPartitionEx ( IN PSET_PARTITION_INFORMATION_EX  PartitionEntry,
IN ULONG  PartitionNumber 
)

Definition at line 633 of file fstubex.c.

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 {
645 DPRINT(" PartitionType: %02x\n", PartitionEntry->Mbr.PartitionType);
646
647 break;
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}

Referenced by IoSetPartitionInformationEx().

◆ FstubDetectPartitionStyle()

NTSTATUS NTAPI FstubDetectPartitionStyle ( IN PDISK_INFORMATION  Disk,
IN PARTITION_STYLE PartitionStyle 
)

Definition at line 664 of file fstubex.c.

666{
668 PPARTITION_DESCRIPTOR PartitionDescriptor;
669
670 PAGED_CODE();
671
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}
unsigned short * PUINT16
Definition: basetsd.h:192
#define IS_VALID_DISK_INFO(Disk)
Definition: fstubex.c:90
#define EFI_PMBR_OSTYPE_EFI
Definition: fstubex.c:86
if(dx< 0)
Definition: linetemp.h:194
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
#define PARTITION_TABLE_OFFSET
Definition: hal.h:244
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:245
CHAR PartitionType
Definition: part_xbox.c:32

Referenced by FstubCreateDiskRaw(), IoReadPartitionTableEx(), IoSetPartitionInformationEx(), and IoVerifyPartitionTable().

◆ FstubFreeDiskInformation()

VOID NTAPI FstubFreeDiskInformation ( IN PDISK_INFORMATION  DiskBuffer)

Definition at line 711 of file fstubex.c.

712{
713 if (DiskBuffer)
714 {
715 if (DiskBuffer->Buffer)
716 {
717 ExFreePoolWithTag(DiskBuffer->Buffer, TAG_FSTUB);
718 }
719 ExFreePoolWithTag(DiskBuffer, TAG_FSTUB);
720 }
721}

Referenced by FstubCreateDiskEFI(), FstubCreateDiskMBR(), FstubCreateDiskRaw(), IoReadPartitionTableEx(), IoSetPartitionInformationEx(), IoVerifyPartitionTable(), and IoWritePartitionTableEx().

◆ FstubGetDiskGeometry()

NTSTATUS NTAPI FstubGetDiskGeometry ( IN PDEVICE_OBJECT  DeviceObject,
OUT PDISK_GEOMETRY_EX  Geometry 
)

Definition at line 725 of file fstubex.c.

727{
729 PIRP Irp;
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 */
766 0,
767 0,
768 DiskGeometry,
769 sizeof(DISK_GEOMETRY_EX),
770 FALSE,
771 Event,
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
793Cleanup:
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}
_In_ PIRP Irp
Definition: csq.h:116
static const WCHAR Cleanup[]
Definition: register.c:80
#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 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
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_PENDING
Definition: ntstatus.h:82
@ Executive
Definition: ketypes.h:415

Referenced by FstubAllocateDiskInformation().

◆ FstubReadHeaderEFI()

NTSTATUS NTAPI FstubReadHeaderEFI ( IN PDISK_INFORMATION  Disk,
IN BOOLEAN  ReadBackupTable,
PEFI_PARTITION_HEADER HeaderBuffer 
)

Definition at line 819 of file fstubex.c.

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);
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 {
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 {
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 */
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}
#define RtlComputeCrc32
Definition: compat.h:810
#define EFI_HEADER_SIGNATURE
Definition: fstubex.c:82
struct _EFI_PARTITION_HEADER * PEFI_PARTITION_HEADER
#define EFI_HEADER_REVISION_1
Definition: fstubex.c:84
#define for
Definition: utility.h:88
ULONGLONG Signature
Definition: fstubex.c:29
ULONGLONG PartitionEntryLBA
Definition: fstubex.c:39
ULONGLONG MyLBA
Definition: fstubex.c:34
ULONG PartitionEntryCRC32
Definition: fstubex.c:42
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147

Referenced by FstubReadPartitionTableEFI(), FstubVerifyPartitionTableEFI(), and IoWritePartitionTableEx().

◆ FstubReadPartitionTableEFI()

NTSTATUS NTAPI FstubReadPartitionTableEFI ( IN PDISK_INFORMATION  Disk,
IN BOOLEAN  ReadBackupTable,
OUT PDRIVE_LAYOUT_INFORMATION_EX *  DriveLayout 
)

Definition at line 967 of file fstubex.c.

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 */
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}
unsigned char BOOLEAN
NTSTATUS NTAPI IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
Definition: fstubex.c:2460
NTSTATUS NTAPI FstubReadHeaderEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, PEFI_PARTITION_HEADER *HeaderBuffer)
Definition: fstubex.c:819
struct _EFI_PARTITION_ENTRY * PEFI_PARTITION_ENTRY
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
Definition: fstubex.c:47
GUID UniquePartition
Definition: fstubex.c:49
GUID PartitionType
Definition: fstubex.c:48
ULONGLONG StartingLBA
Definition: fstubex.c:50
WCHAR Name[0x24]
Definition: fstubex.c:53
ULONGLONG Attributes
Definition: fstubex.c:52
ULONGLONG EndingLBA
Definition: fstubex.c:51
ULONGLONG FirstUsableLBA
Definition: fstubex.c:36
ULONGLONG AlternateLBA
Definition: fstubex.c:35
ULONGLONG LastUsableLBA
Definition: fstubex.c:37

Referenced by IoReadPartitionTableEx().

◆ FstubReadPartitionTableMBR()

NTSTATUS NTAPI FstubReadPartitionTableMBR ( IN PDISK_INFORMATION  Disk,
IN BOOLEAN  ReturnRecognizedPartitions,
OUT PDRIVE_LAYOUT_INFORMATION_EX *  ReturnedDriveLayout 
)

Definition at line 1119 of file fstubex.c.

1122{
1124 ULONG i;
1125 PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
1126 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
1127
1128 PAGED_CODE();
1129
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}
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: partition.c:495
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
_In_ ULONG _In_ BOOLEAN ReturnRecognizedPartitions
Definition: iofuncs.h:2051

Referenced by IoReadPartitionTableEx().

◆ FstubReadSector()

NTSTATUS NTAPI FstubReadSector ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONGLONG StartingSector  OPTIONAL,
OUT PVOID  Buffer 
)

Definition at line 1186 of file fstubex.c.

1190{
1192 PIRP Irp;
1193 KEVENT Event;
1196 PIO_STACK_LOCATION IoStackLocation;
1197
1198 PAGED_CODE();
1199
1201 ASSERT(Buffer);
1203
1204 /* Compute starting offset */
1205 StartingOffset.QuadPart = StartingSector * SectorSize;
1206
1207 /* Initialize waiting event */
1209
1210 /* Prepare IRP */
1213 Buffer,
1214 SectorSize,
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}
Definition: bufpool.h:45
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
#define IRP_MJ_READ
Definition: rdpdr.c:46
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823

Referenced by FstubCreateDiskMBR(), FstubCreateDiskRaw(), FstubDetectPartitionStyle(), FstubReadHeaderEFI(), FstubReadPartitionTableEFI(), FstubVerifyPartitionTableEFI(), FstubWriteBootSectorEFI(), and IoReadDiskSignature().

◆ FstubSetPartitionInformationEFI()

NTSTATUS NTAPI FstubSetPartitionInformationEFI ( IN PDISK_INFORMATION  Disk,
IN ULONG  PartitionNumber,
IN SET_PARTITION_INFORMATION_GPT *  PartitionInfo 
)

Definition at line 1240 of file fstubex.c.

1243{
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 {
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);
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}
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2273
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105

Referenced by IoSetPartitionInformationEx().

◆ FstubVerifyPartitionTableEFI()

NTSTATUS NTAPI FstubVerifyPartitionTableEFI ( IN PDISK_INFORMATION  Disk,
IN BOOLEAN  FixErrors 
)

Definition at line 1289 of file fstubex.c.

1291{
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 {
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 */
1404 SectorsForPartitions,
1405 EFIHeader->DiskGUID,
1406 EFIHeader->NumberOfEntries,
1407 EFIHeader->FirstUsableLBA,
1408 EFIHeader->LastUsableLBA,
1409 EFIHeader->PartitionEntryCRC32,
1410 WriteBackup);
1411
1412Cleanup:
1413 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1414 return Status;
1415}
BOOL FixErrors
Definition: chkdsk.c:69
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

Referenced by IoVerifyPartitionTable().

◆ FstubWriteBootSectorEFI()

NTSTATUS NTAPI FstubWriteBootSectorEFI ( IN PDISK_INFORMATION  Disk)

Definition at line 1419 of file fstubex.c.

1420{
1422 ULONG Signature = 0;
1423 PMASTER_BOOT_RECORD MasterBootRecord;
1424
1425 PAGED_CODE();
1426
1427 ASSERT(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}
static const WCHAR Signature[]
Definition: parser.c:141
ULONG SectorCountBeforePartition
Definition: disk.h:64
ULONG PartitionSectorCount
Definition: disk.h:65
UCHAR StartSector
Definition: disk.h:58
UCHAR SystemIndicator
Definition: disk.h:60
UCHAR EndHead
Definition: disk.h:61
UCHAR EndSector
Definition: disk.h:62
UCHAR EndCylinder
Definition: disk.h:63

Referenced by FstubCreateDiskEFI().

◆ FstubWriteEntryEFI()

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 at line 1471 of file fstubex.c.

1478{
1480 ULONG Offset;
1481 ULONGLONG FirstEntryLBA;
1482
1483 PAGED_CODE();
1484
1485 ASSERT(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;
1509 ASSERT(Offset <= Disk->SectorSize);
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}
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by FstubWritePartitionTableEFI().

◆ FstubWriteHeaderEFI()

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 at line 1539 of file fstubex.c.

1547{
1548 PEFI_PARTITION_HEADER EFIHeader;
1549
1550 PAGED_CODE();
1551
1552 ASSERT(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}
ULONG SizeOfPartitionEntry
Definition: fstubex.c:41

Referenced by FstubVerifyPartitionTableEFI(), and FstubWritePartitionTableEFI().

◆ FstubWritePartitionTableEFI()

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 at line 1628 of file fstubex.c.

1636{
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 */
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 {
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}
VOID NTAPI FstubCopyEntryEFI(OUT PEFI_PARTITION_ENTRY Entry, IN PPARTITION_INFORMATION_EX Partition, ULONG SectorSize)
Definition: fstubex.c:314
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

Referenced by FstubCreateDiskEFI(), and IoWritePartitionTableEx().

◆ FstubWritePartitionTableMBR()

NTSTATUS NTAPI FstubWritePartitionTableMBR ( IN PDISK_INFORMATION  Disk,
IN PDRIVE_LAYOUT_INFORMATION_EX  LayoutEx 
)

Definition at line 1710 of file fstubex.c.

1712{
1714 PDRIVE_LAYOUT_INFORMATION DriveLayout;
1715
1716 PAGED_CODE();
1717
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}
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: ntoskrnl.c:69
PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:266

Referenced by IoWritePartitionTableEx().

◆ FstubWriteSector()

NTSTATUS NTAPI FstubWriteSector ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  SectorSize,
IN ULONGLONG StartingSector  OPTIONAL,
IN PVOID  Buffer 
)

Definition at line 1742 of file fstubex.c.

1746{
1748 PIRP Irp;
1749 KEVENT Event;
1752 PIO_STACK_LOCATION IoStackLocation;
1753
1754 PAGED_CODE();
1755
1757 ASSERT(Buffer);
1759
1760 /* Compute starting offset */
1761 StartingOffset.QuadPart = StartingSector * SectorSize;
1762
1763 /* Initialize waiting event */
1765
1766 /* Prepare IRP */
1769 Buffer,
1770 SectorSize,
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}
#define IRP_MJ_WRITE
Definition: rdpdr.c:47

Referenced by FstubCreateDiskMBR(), FstubCreateDiskRaw(), FstubVerifyPartitionTableEFI(), FstubWriteBootSectorEFI(), FstubWriteEntryEFI(), and FstubWriteHeaderEFI().

◆ IoCreateDisk()

NTSTATUS NTAPI IoCreateDisk ( IN PDEVICE_OBJECT  DeviceObject,
IN PCREATE_DISK  Disk 
)

Definition at line 1801 of file fstubex.c.

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 {
1816 return FstubCreateDiskMBR(DeviceObject, &(Disk->Mbr));
1818 return FstubCreateDiskEFI(DeviceObject, &(Disk->Gpt));
1819 case PARTITION_STYLE_RAW:
1821 default:
1822 return STATUS_NOT_SUPPORTED;
1823 }
1824}
NTSTATUS NTAPI FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
Definition: fstubex.c:451
NTSTATUS NTAPI FstubCreateDiskMBR(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_MBR DiskInfo)
Definition: fstubex.c:335
NTSTATUS NTAPI FstubCreateDiskEFI(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_GPT DiskInfo)
Definition: fstubex.c:382
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423

Referenced by FdoIoctlDiskCreateDisk(), FdoIoctlDiskDeleteDriveLayout(), and FdoIoctlDiskSetDriveLayoutEx().

◆ IoGetBootDiskInformation()

NTSTATUS NTAPI IoGetBootDiskInformation ( IN OUT PBOOTDISK_INFORMATION  BootDiskInformation,
IN ULONG  Size 
)

Definition at line 1831 of file fstubex.c.

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 too late */
1856 if (!IopLoaderBlock)
1857 {
1858 return STATUS_TOO_LATE;
1859 }
1860
1861 /* Check buffer size */
1862 if (Size < sizeof(BOOTDISK_INFORMATION))
1863 {
1865 }
1866
1867 /* Init some useful stuff:
1868 * Get ARC disks information
1869 * Check whether we have a single disk on the machine
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 = (ArcDiskInformation->DiskSignatureListHead.Flink->Flink ==
1876 &ArcDiskInformation->DiskSignatureListHead);
1877
1878 IsBootDiskInfoEx = (Size >= sizeof(BOOTDISK_INFORMATION_EX));
1882
1883 /* If no disk, return success */
1884 if (DiskCount == 0)
1885 {
1886 return STATUS_SUCCESS;
1887 }
1888
1889 /* Now, browse all disks */
1890 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
1891 {
1892 /* Create the device name */
1893 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
1894 RtlInitAnsiString(&DeviceStringA, Buffer);
1895 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1896 if (!NT_SUCCESS(Status))
1897 {
1898 continue;
1899 }
1900
1901 /* Get its device object */
1902 Status = IoGetDeviceObjectPointer(&DeviceStringW,
1904 &FileObject,
1905 &DeviceObject);
1906 RtlFreeUnicodeString(&DeviceStringW);
1907 if (!NT_SUCCESS(Status))
1908 {
1909 continue;
1910 }
1911
1912 /* Prepare for getting disk geometry */
1916 NULL,
1917 0,
1918 &DiskGeometry,
1919 sizeof(DiskGeometry),
1920 FALSE,
1921 &Event,
1922 &IoStatusBlock);
1923 if (!Irp)
1924 {
1926 continue;
1927 }
1928
1929 /* Then, call the drive, and wait for it if needed */
1931 if (Status == STATUS_PENDING)
1932 {
1935 }
1936 if (!NT_SUCCESS(Status))
1937 {
1939 continue;
1940 }
1941
1942 /* Read partition table */
1944 &DriveLayout);
1945
1946 /* FileObject, you can go! */
1948
1949 if (!NT_SUCCESS(Status))
1950 {
1951 continue;
1952 }
1953
1954 /* Ensure we have at least 512 bytes per sector */
1955 if (DiskGeometry.BytesPerSector < 512)
1956 {
1957 DiskGeometry.BytesPerSector = 512;
1958 }
1959
1960 /* Now, for each ARC disk, try to find the matching */
1961 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
1962 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
1963 NextEntry = NextEntry->Flink)
1964 {
1965 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
1967 ListEntry);
1968 /* If they match, i.e.
1969 * - There's only one disk for both BIOS and detected
1970 * - Signatures are matching
1971 * - This is MBR
1972 * (We don't check checksums here)
1973 */
1974 if (((SingleDisk && DiskCount == 1) ||
1975 (IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature))) &&
1976 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR))
1977 {
1978 /* Create ARC name */
1979 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
1980 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
1981
1982 /* Browse all partitions */
1983 for (PartitionNumber = 1; PartitionNumber <= DriveLayout->PartitionCount; PartitionNumber++)
1984 {
1985 /* Create its device name */
1986 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, PartitionNumber);
1987 RtlInitAnsiString(&DeviceStringA, Buffer);
1988 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1989 if (!NT_SUCCESS(Status))
1990 {
1991 continue;
1992 }
1993
1994 /* If IopVerifyDiskSignature returned no signature, take the one from DriveLayout */
1995 if (!Signature)
1996 {
1997 Signature = DriveLayout->Mbr.Signature;
1998 }
1999
2000 /* Create partial ARC name */
2001 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, PartitionNumber);
2002 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
2003
2004 /* If it's matching boot string */
2005 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
2006 {
2007 /* Then, fill in information about boot device */
2008 BootDiskInformation->BootDeviceSignature = Signature;
2009
2010 /* Get its device object */
2011 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2013 &FileObject,
2014 &DeviceObject);
2015 if (!NT_SUCCESS(Status))
2016 {
2017 RtlFreeUnicodeString(&DeviceStringW);
2018 continue;
2019 }
2020
2021 /* And call the drive to get information about partition */
2025 NULL,
2026 0,
2027 &PartitionInformation,
2028 sizeof(PartitionInformation),
2029 FALSE,
2030 &Event,
2031 &IoStatusBlock);
2032 if (!Irp)
2033 {
2035 RtlFreeUnicodeString(&DeviceStringW);
2036 continue;
2037 }
2038
2039 /* Call & wait if needed */
2041 if (Status == STATUS_PENDING)
2042 {
2045 }
2046 if (!NT_SUCCESS(Status))
2047 {
2049 RtlFreeUnicodeString(&DeviceStringW);
2050 continue;
2051 }
2052
2053 /* We get partition offset as demanded and return it */
2054 BootDiskInformation->BootPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2055
2056 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2057 if (IsBootDiskInfoEx)
2058 {
2059 /* Is partition style MBR or GPT? */
2060 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2061 {
2062 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceGuid = DriveLayout->Gpt.DiskId;
2063 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = TRUE;
2064 }
2065 else
2066 {
2067 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = FALSE;
2068 }
2069 }
2070
2071 /* Dereference FileObject */
2073 }
2074
2075 /* If it's matching system string */
2076 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
2077 {
2078 /* Then, fill in information about the system device */
2079 BootDiskInformation->SystemDeviceSignature = Signature;
2080
2081 /* Get its device object */
2082 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2084 &FileObject,
2085 &DeviceObject);
2086 if (!NT_SUCCESS(Status))
2087 {
2088 RtlFreeUnicodeString(&DeviceStringW);
2089 continue;
2090 }
2091
2092 /* And call the drive to get information about partition */
2096 NULL,
2097 0,
2098 &PartitionInformation,
2099 sizeof(PartitionInformation),
2100 FALSE,
2101 &Event,
2102 &IoStatusBlock);
2103 if (!Irp)
2104 {
2106 RtlFreeUnicodeString(&DeviceStringW);
2107 continue;
2108 }
2109
2110 /* Call & wait if needed */
2112 if (Status == STATUS_PENDING)
2113 {
2116 }
2117 if (!NT_SUCCESS(Status))
2118 {
2120 RtlFreeUnicodeString(&DeviceStringW);
2121 continue;
2122 }
2123
2124 /* We get partition offset as demanded and return it */
2125 BootDiskInformation->SystemPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2126
2127 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2128 if (IsBootDiskInfoEx)
2129 {
2130 /* Is partition style MBR or GPT? */
2131 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2132 {
2133 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceGuid = DriveLayout->Gpt.DiskId;
2134 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = TRUE;
2135 }
2136 else
2137 {
2138 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = FALSE;
2139 }
2140 }
2141
2142 /* Dereference FileObject */
2144 }
2145
2146 /* Release device string */
2147 RtlFreeUnicodeString(&DeviceStringW);
2148 }
2149 }
2150 }
2151
2152 /* Finally, release drive layout */
2153 ExFreePool(DriveLayout);
2154 }
2155
2156 /* And return */
2157 return Status;
2158}
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
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
#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)
BOOLEAN NTAPI IopVerifyDiskSignature(IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, IN PARC_DISK_SIGNATURE ArcDiskSignature, OUT PULONG Signature)
Definition: arcname.c:948
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
#define STATUS_TOO_LATE
Definition: ntstatus.h:626
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:268
PCHAR ArcName
Definition: arc.h:257
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
LARGE_INTEGER StartingOffset
Definition: imports.h:221
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_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
struct _BOOTDISK_INFORMATION_EX * PBOOTDISK_INFORMATION_EX
* PFILE_OBJECT
Definition: iotypes.h:1998
struct _BOOTDISK_INFORMATION_EX BOOTDISK_INFORMATION_EX
#define ObDereferenceObject
Definition: obfuncs.h:203

◆ IoReadDiskSignature()

NTSTATUS NTAPI IoReadDiskSignature ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  BytesPerSector,
OUT PDISK_SIGNATURE  Signature 
)

Definition at line 2165 of file fstubex.c.

2168{
2170 PUCHAR Buffer;
2171 ULONG HeaderCRC32, i, CheckSum;
2172 PEFI_PARTITION_HEADER EFIHeader;
2173 PPARTITION_DESCRIPTOR PartitionDescriptor;
2174
2175 PAGED_CODE();
2176
2177 /* Ensure we'll read at least 512 bytes */
2178 if (BytesPerSector < 512)
2179 {
2180 BytesPerSector = 512;
2181 }
2182
2183 /* Allocate a buffer for reading operations */
2185 if (!Buffer)
2186 {
2187 return STATUS_NO_MEMORY;
2188 }
2189
2190 /* Read first sector (sector 0) for MBR */
2192 BytesPerSector,
2193 0ULL,
2194 Buffer);
2195 if (!NT_SUCCESS(Status))
2196 {
2197 goto Cleanup;
2198 }
2199
2200 /* Get the partition descriptor array */
2201 PartitionDescriptor = (PPARTITION_DESCRIPTOR)
2203 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
2204 if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
2205 PartitionDescriptor[1].PartitionType == 0 &&
2206 PartitionDescriptor[2].PartitionType == 0 &&
2207 PartitionDescriptor[3].PartitionType == 0)
2208 {
2209 /* If we have GPT, read second sector (sector 1) for GPT header */
2211 BytesPerSector,
2212 1ULL,
2213 Buffer);
2214 if (!NT_SUCCESS(Status))
2215 {
2216 goto Cleanup;
2217 }
2218 EFIHeader = (PEFI_PARTITION_HEADER)Buffer;
2219
2220 /* First check signature
2221 * Then, check version (we only support v1
2222 * Finally check header size
2223 */
2224 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
2225 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
2226 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
2227 {
2229 goto Cleanup;
2230 }
2231
2232 /* Save current checksum */
2233 HeaderCRC32 = EFIHeader->HeaderCRC32;
2234 /* Then zero the one in EFI header. This is needed to compute header checksum */
2235 EFIHeader->HeaderCRC32 = 0;
2236 /* Compute header checksum and compare with the one present in partition table */
2237 if (RtlComputeCrc32(0, Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
2238 {
2240 goto Cleanup;
2241 }
2242
2243 /* Set partition table style to GPT and return disk GUID */
2244 Signature->PartitionStyle = PARTITION_STYLE_GPT;
2245 Signature->Gpt.DiskId = EFIHeader->DiskGUID;
2246 }
2247 else
2248 {
2249 /* Compute MBR checksum */
2250 for (i = 0, CheckSum = 0; i < 512; i += sizeof(UINT32))
2251 {
2252 CheckSum += *(PUINT32)&Buffer[i];
2253 }
2254 CheckSum = ~CheckSum + 1;
2255
2256 /* Set partition table style to MBR and return signature (offset 440) and checksum */
2257 Signature->PartitionStyle = PARTITION_STYLE_MBR;
2258 Signature->Mbr.Signature = *(PUINT32)&Buffer[DISK_SIGNATURE_OFFSET];
2259 Signature->Mbr.CheckSum = CheckSum;
2260 }
2261
2262Cleanup:
2263 /* Free buffer and return */
2265 return Status;
2266}
unsigned int UINT32
unsigned int * PUINT32
Definition: basetsd.h:125
#define DISK_SIGNATURE_OFFSET
Definition: hal.h:243
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260

◆ IoReadPartitionTableEx()

NTSTATUS NTAPI IoReadPartitionTableEx ( IN PDEVICE_OBJECT  DeviceObject,
IN PDRIVE_LAYOUT_INFORMATION_EX *  DriveLayout 
)

Definition at line 2273 of file fstubex.c.

2275{
2277 PDISK_INFORMATION Disk;
2278 PARTITION_STYLE PartitionStyle;
2279
2280 PAGED_CODE();
2281
2283 ASSERT(DriveLayout);
2284
2285 /* First of all, allocate internal structure */
2287 if (!NT_SUCCESS(Status))
2288 {
2289 return Status;
2290 }
2291 ASSERT(Disk);
2292
2293 /* Then, detect partition style (MBR? GPT/EFI? RAW?) */
2294 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2295 if (!NT_SUCCESS(Status))
2296 {
2298 return Status;
2299 }
2300
2301 /* Here partition table is really read, depending on its style */
2302 switch (PartitionStyle)
2303 {
2305 case PARTITION_STYLE_RAW:
2306 Status = FstubReadPartitionTableMBR(Disk, FALSE, DriveLayout);
2307 break;
2308
2310 /* Read primary table */
2311 Status = FstubReadPartitionTableEFI(Disk, FALSE, DriveLayout);
2312 /* If it failed, try reading backup table */
2313 if (!NT_SUCCESS(Status))
2314 {
2315 Status = FstubReadPartitionTableEFI(Disk, TRUE, DriveLayout);
2316 }
2317 break;
2318
2319 default:
2320 DPRINT("Unknown partition type\n");
2322 }
2323
2324 /* It's over, internal structure not needed anymore */
2326
2327 /* In case of success, print data */
2328 if (NT_SUCCESS(Status))
2329 {
2330 FstubDbgPrintDriveLayoutEx(*DriveLayout);
2331 }
2332
2333 return Status;
2334}
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
NTSTATUS NTAPI FstubReadPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:967
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by ClasspDuidGetDriveLayout(), FstubSetPartitionInformationEFI(), IoGetBootDiskInformation(), IopCreateArcNamesDisk(), and PartMgrGetDriveLayout().

◆ IoSetPartitionInformationEx()

NTSTATUS NTAPI IoSetPartitionInformationEx ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  PartitionNumber,
IN PSET_PARTITION_INFORMATION_EX  PartitionInfo 
)

Definition at line 2341 of file fstubex.c.

2344{
2346 PDISK_INFORMATION Disk;
2347 PARTITION_STYLE PartitionStyle;
2348
2349 PAGED_CODE();
2350
2353
2354 /* Debug given modifications */
2356
2357 /* Allocate internal structure */
2359 if (!NT_SUCCESS(Status))
2360 {
2361 return Status;
2362 }
2363
2364 /* Get partition table style on disk */
2365 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2366 if (!NT_SUCCESS(Status))
2367 {
2369 return Status;
2370 }
2371
2372 /* If it's not matching partition style given in modifications, give up */
2373 if (PartitionInfo->PartitionStyle != PartitionStyle)
2374 {
2377 }
2378
2379 /* Finally, handle modifications using proper function */
2380 switch (PartitionStyle)
2381 {
2384 Disk->SectorSize,
2386 PartitionInfo->Mbr.PartitionType);
2387 break;
2391 &(PartitionInfo->Gpt));
2392 break;
2393 default:
2395 }
2396
2397 /* Release internal structure and return */
2399 return Status;
2400}
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: ntoskrnl.c:46
NTSTATUS NTAPI FstubSetPartitionInformationEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionNumber, IN SET_PARTITION_INFORMATION_GPT *PartitionInfo)
Definition: fstubex.c:1240
VOID NTAPI FstubDbgPrintSetPartitionEx(IN PSET_PARTITION_INFORMATION_EX PartitionEntry, IN ULONG PartitionNumber)
Definition: fstubex.c:633

Referenced by PartitionHandleDeviceControl().

◆ IoVerifyPartitionTable()

NTSTATUS NTAPI IoVerifyPartitionTable ( IN PDEVICE_OBJECT  DeviceObject,
IN BOOLEAN  FixErrors 
)

Definition at line 2407 of file fstubex.c.

2409{
2411 PDISK_INFORMATION Disk;
2412 PARTITION_STYLE PartitionStyle;
2413
2414 PAGED_CODE();
2415
2417
2418 /* Allocate internal structure */
2420 if (!NT_SUCCESS(Status))
2421 {
2422 return Status;
2423 }
2424 ASSERT(Disk);
2425
2426 /* Get partition table style on disk */
2427 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2428 if (!NT_SUCCESS(Status))
2429 {
2431 return Status;
2432 }
2433
2434 /* Action will depend on partition style */
2435 switch (PartitionStyle)
2436 {
2437 /* For MBR, assume it's always OK */
2440 break;
2441 /* For GPT, call internal function */
2444 break;
2445 /* Otherwise, signal we can't work */
2446 default:
2448 }
2449
2450 /* Release internal structure and return */
2452 return Status;
2453}
NTSTATUS NTAPI FstubVerifyPartitionTableEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN FixErrors)
Definition: fstubex.c:1289

◆ IoWritePartitionTableEx()

NTSTATUS NTAPI IoWritePartitionTableEx ( IN PDEVICE_OBJECT  DeviceObject,
IN PDRIVE_LAYOUT_INFORMATION_EX  DriveLayout 
)

Definition at line 2460 of file fstubex.c.

2462{
2464 GUID DiskGuid;
2465 ULONG NumberOfEntries;
2466 PDISK_INFORMATION Disk;
2467 PEFI_PARTITION_HEADER EfiHeader;
2468 ULONGLONG SectorsForPartitions, FirstUsableLBA, LastUsableLBA;
2469
2470 PAGED_CODE();
2471
2473 ASSERT(DriveLayout);
2474
2475 /* Debug partition table that must be written */
2476 FstubDbgPrintDriveLayoutEx(DriveLayout);
2477
2478 /* Allocate internal structure */
2480 if (!NT_SUCCESS(Status))
2481 {
2482 return Status;
2483 }
2484 ASSERT(Disk);
2485
2486 switch (DriveLayout->PartitionStyle)
2487 {
2489 Status = FstubWritePartitionTableMBR(Disk, DriveLayout);
2490 break;
2491
2493 /* Read primary table header */
2495 FALSE,
2496 &EfiHeader);
2497 /* If it failed, try reading back table header */
2498 if (!NT_SUCCESS(Status))
2499 {
2501 TRUE,
2502 &EfiHeader);
2503 }
2504
2505 /* We have a header! */
2506 if (NT_SUCCESS(Status))
2507 {
2508 /* Check if there are enough places for the partitions to be written */
2509 if (DriveLayout->PartitionCount <= EfiHeader->NumberOfEntries)
2510 {
2511 /* Backup data */
2512 NumberOfEntries = EfiHeader->NumberOfEntries;
2513 RtlCopyMemory(&DiskGuid, &EfiHeader->DiskGUID, sizeof(GUID));
2514 /* Count number of sectors needed to store partitions */
2515 SectorsForPartitions = ((ULONGLONG)NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
2516 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
2517 FirstUsableLBA = SectorsForPartitions + 2;
2518 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
2519 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
2520 /* Write primary table */
2522 DiskGuid,
2523 NumberOfEntries,
2524 FirstUsableLBA,
2525 LastUsableLBA,
2526 FALSE,
2527 DriveLayout->PartitionCount,
2528 DriveLayout->PartitionEntry);
2529 /* If it succeeded, also update backup table */
2530 if (NT_SUCCESS(Status))
2531 {
2533 DiskGuid,
2534 NumberOfEntries,
2535 FirstUsableLBA,
2536 LastUsableLBA,
2537 TRUE,
2538 DriveLayout->PartitionCount,
2539 DriveLayout->PartitionEntry);
2540 }
2541 }
2542 else
2543 {
2545 }
2546 }
2547 break;
2548
2549 default:
2550 DPRINT("Unsupported partition style: %lu\n", DriveLayout->PartitionStyle);
2552 }
2553
2554 /* It's over, internal structure not needed anymore */
2556
2557 return Status;
2558}
NTSTATUS NTAPI FstubWritePartitionTableMBR(IN PDISK_INFORMATION Disk, IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:1710

Referenced by FdoIoctlDiskSetDriveLayout(), FdoIoctlDiskSetDriveLayoutEx(), FstubReadPartitionTableEFI(), and FstubSetPartitionInformationEFI().