ReactOS 0.4.16-dev-2613-g9533ad7
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)
 
#define FstubDbgPrintDriveLayoutEx(DriveLayout)
 
#define FstubDbgPrintSetPartitionEx(PartitionEntry, PartitionNumber)
 

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

 C_ASSERT (sizeof(EFI_PARTITION_HEADER)==92)
 
 C_ASSERT (sizeof(EFI_PARTITION_ENTRY)==128)
 
 C_ASSERT (sizeof(PARTITION_TABLE_ENTRY)==16)
 
 C_ASSERT (sizeof(MASTER_BOOT_RECORD)==512)
 
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)
 
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, OUT 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 94 of file fstubex.c.

◆ EFI_HEADER_REVISION_1

#define EFI_HEADER_REVISION_1   0x00010000

Definition at line 90 of file fstubex.c.

◆ EFI_HEADER_SIGNATURE

#define EFI_HEADER_SIGNATURE   0x5452415020494645ULL

Definition at line 88 of file fstubex.c.

◆ EFI_PMBR_OSTYPE_EFI

#define EFI_PMBR_OSTYPE_EFI   0xEE

Definition at line 92 of file fstubex.c.

◆ FstubDbgPrintDriveLayoutEx

#define FstubDbgPrintDriveLayoutEx (   DriveLayout)

Definition at line 665 of file fstubex.c.

◆ FstubDbgPrintSetPartitionEx

#define FstubDbgPrintSetPartitionEx (   PartitionEntry,
  PartitionNumber 
)

Definition at line 666 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 96 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 86 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

◆ C_ASSERT() [1/4]

C_ASSERT ( sizeof(EFI_PARTITION_ENTRY = =128)

◆ C_ASSERT() [2/4]

C_ASSERT ( sizeof(EFI_PARTITION_HEADER = =92)

◆ C_ASSERT() [3/4]

C_ASSERT ( sizeof(MASTER_BOOT_RECORD = =512)

◆ C_ASSERT() [4/4]

C_ASSERT ( sizeof(PARTITION_TABLE_ENTRY = =16)

◆ 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 * i.e. all sectors will be full of entries.
186 * There won't be lonely entries. */
189 ASSERT(*PartitionCount <= Count);
190 /* Return result */
191 *PartitionCount = Count;
192
193 /* One more sanity check */
194 if (SectorSize == 512)
195 {
196 ASSERT(Count % 4 == 0);
197 }
198}
#define PAGED_CODE()
#define PARTITION_ENTRY_SIZE
Definition: fstubex.c:86
#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 202 of file fstubex.c.

205{
207 PDISK_INFORMATION DiskInformation;
208
209 PAGED_CODE();
210
212 ASSERT(DiskBuffer);
213
214 /* Allocate internal structure */
216 if (!DiskInformation)
217 {
219 }
220
221 /* If caller don't pass needed information, let's get them */
222 if (!DiskGeometry)
223 {
225 if (!NT_SUCCESS(Status))
226 {
227 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
228 return Status;
229 }
230 }
231 else
232 {
233 RtlCopyMemory(&DiskInformation->DiskGeometry, DiskGeometry, sizeof(DISK_GEOMETRY_EX));
234 }
235
236 /* Ensure read/received information are correct */
237 if (DiskInformation->DiskGeometry.Geometry.BytesPerSector == 0 ||
238 DiskInformation->DiskGeometry.DiskSize.QuadPart == 0)
239 {
240 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
242 }
243
244 /* Store vital information as well */
245 DiskInformation->DeviceObject = DeviceObject;
246 DiskInformation->SectorSize = DiskInformation->DiskGeometry.Geometry.BytesPerSector;
247 DiskInformation->SectorCount = DiskInformation->DiskGeometry.DiskSize.QuadPart / DiskInformation->SectorSize;
248
249 /* Finally, allocate the buffer that will be used for different read */
250 DiskInformation->Buffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned, DiskInformation->SectorSize, TAG_FSTUB);
251 if (!DiskInformation->Buffer)
252 {
253 ExFreePoolWithTag(DiskInformation, TAG_FSTUB);
255 }
256
257 /* Return allocated internal structure */
258 *DiskBuffer = DiskInformation;
259
260 return STATUS_SUCCESS;
261}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#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:732
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:530
LARGE_INTEGER DiskSize
Definition: winioctl.h:531
ULONG BytesPerSector
Definition: ntdddisk.h:404
PDEVICE_OBJECT DeviceObject
Definition: fstubex.c:19
ULONG SectorSize
Definition: fstubex.c:20
PUCHAR Buffer
Definition: fstubex.c:22
ULONGLONG SectorCount
Definition: fstubex.c:23
DISK_GEOMETRY_EX DiskGeometry
Definition: fstubex.c:21
#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:2061

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 265 of file fstubex.c.

266{
267 ULONG i;
268 PDRIVE_LAYOUT_INFORMATION DriveLayout;
269
270 PAGED_CODE();
271
272 ASSERT(LayoutEx);
273
274 /* Check whether we're dealing with MBR partition table */
275 if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR)
276 {
277 ASSERT(FALSE);
278 return NULL;
279 }
280
281 /* Allocate needed buffer */
283 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) +
284 LayoutEx->PartitionCount * sizeof(PARTITION_INFORMATION),
285 TAG_FSTUB);
286 if (!DriveLayout)
287 {
288 return NULL;
289 }
290
291 /* Convert information about partition table */
292 DriveLayout->PartitionCount = LayoutEx->PartitionCount;
293 DriveLayout->Signature = LayoutEx->Mbr.Signature;
294
295 /* Convert each partition */
296 for (i = 0; i < LayoutEx->PartitionCount; i++)
297 {
298 DriveLayout->PartitionEntry[i].StartingOffset = LayoutEx->PartitionEntry[i].StartingOffset;
299 DriveLayout->PartitionEntry[i].PartitionLength = LayoutEx->PartitionEntry[i].PartitionLength;
300 DriveLayout->PartitionEntry[i].HiddenSectors = LayoutEx->PartitionEntry[i].Mbr.HiddenSectors;
301 DriveLayout->PartitionEntry[i].PartitionNumber = LayoutEx->PartitionEntry[i].PartitionNumber;
302 DriveLayout->PartitionEntry[i].PartitionType = LayoutEx->PartitionEntry[i].Mbr.PartitionType;
303 DriveLayout->PartitionEntry[i].BootIndicator = LayoutEx->PartitionEntry[i].Mbr.BootIndicator;
304 DriveLayout->PartitionEntry[i].RecognizedPartition = LayoutEx->PartitionEntry[i].Mbr.RecognizedPartition;
305 DriveLayout->PartitionEntry[i].RewritePartition = LayoutEx->PartitionEntry[i].RewritePartition;
306 }
307
308 return DriveLayout;
309}
#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:421
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:408
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:409
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:414
BOOLEAN RewritePartition
Definition: ntdddisk.h:415
#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 313 of file fstubex.c.

316{
317 PAGED_CODE();
318
319 ASSERT(Entry);
320 ASSERT(Partition);
322
323 /* Just convert data to EFI partition entry type */
324 Entry->PartitionType = Partition->Gpt.PartitionType;
325 Entry->UniquePartition = Partition->Gpt.PartitionId;
326 Entry->StartingLBA = Partition->StartingOffset.QuadPart / SectorSize;
327 Entry->EndingLBA = (Partition->StartingOffset.QuadPart + Partition->PartitionLength.QuadPart - 1) / SectorSize;
328 Entry->Attributes = Partition->Gpt.Attributes;
329 RtlCopyMemory(Entry->Name, Partition->Gpt.Name, sizeof(Entry->Name));
330}
Entry
Definition: section.c:5210

Referenced by FstubWritePartitionTableEFI().

◆ FstubCreateDiskEFI()

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

Definition at line 381 of file fstubex.c.

383{
385 PDISK_INFORMATION Disk = NULL;
386 ULONGLONG FirstUsableLBA, LastUsableLBA;
387 ULONG MaxPartitionCount, SectorsForPartitions;
388
389 PAGED_CODE();
390
392 ASSERT(DiskInfo);
393
394 /* Allocate internal structure */
396 if (!NT_SUCCESS(Status))
397 {
398 return Status;
399 }
400 ASSERT(Disk);
401
402 /* Write legacy MBR */
404 if (!NT_SUCCESS(Status))
405 {
407 return Status;
408 }
409
410 /* Get max entries and adjust its number */
411 MaxPartitionCount = DiskInfo->MaxPartitionCount;
412 FstubAdjustPartitionCount(Disk->SectorSize, &MaxPartitionCount);
413
414 /* Count number of sectors needed to store partitions */
415 SectorsForPartitions = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
416 /* Set first usable LBA: Legacy MBR + GPT header + Partitions entries */
417 FirstUsableLBA = SectorsForPartitions + 2;
418 /* Set last usable LBA: Last sector - GPT header - Partitions entries */
419 LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
420
421 /* First, write primary table */
423 DiskInfo->DiskId,
424 MaxPartitionCount,
425 FirstUsableLBA,
426 LastUsableLBA,
427 FALSE,
428 0,
429 NULL);
430 /* Then, write backup table */
431 if (NT_SUCCESS(Status))
432 {
434 DiskInfo->DiskId,
435 MaxPartitionCount,
436 FirstUsableLBA,
437 LastUsableLBA,
438 TRUE,
439 0,
440 NULL);
441 }
442
443 /* Release internal structure and return */
445 return Status;
446}
#define TRUE
Definition: types.h:120
VOID NTAPI FstubFreeDiskInformation(IN PDISK_INFORMATION DiskBuffer)
Definition: fstubex.c:718
NTSTATUS NTAPI FstubAllocateDiskInformation(IN PDEVICE_OBJECT DeviceObject, OUT PDISK_INFORMATION *DiskBuffer, IN PDISK_GEOMETRY_EX DiskGeometry OPTIONAL)
Definition: fstubex.c:202
VOID NTAPI FstubAdjustPartitionCount(IN ULONG SectorSize, IN OUT PULONG PartitionCount)
Definition: fstubex.c:166
NTSTATUS NTAPI FstubWritePartitionTableEFI(IN PDISK_INFORMATION Disk, IN GUID DiskGUID, IN ULONG MaxPartitionCount, IN ULONGLONG FirstUsableLBA, IN ULONGLONG LastUsableLBA, IN BOOLEAN WriteBackupTable, IN ULONG PartitionCount, IN PPARTITION_INFORMATION_EX PartitionEntries OPTIONAL)
Definition: fstubex.c:1632
NTSTATUS NTAPI FstubWriteBootSectorEFI(IN PDISK_INFORMATION Disk)
Definition: fstubex.c:1423
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 334 of file fstubex.c.

336{
338 PDISK_INFORMATION Disk = NULL;
339 PMASTER_BOOT_RECORD MasterBootRecord;
340
341 PAGED_CODE();
342
344
345 /* Allocate internal structure */
347 if (!NT_SUCCESS(Status))
348 {
349 return Status;
350 }
351
352 /* Read previous MBR, if any */
354 Disk->SectorSize,
355 0ULL,
356 Disk->Buffer);
357 if (!NT_SUCCESS(Status))
358 {
360 return Status;
361 }
362 /* Fill the buffer with needed information, we won't overwrite boot code */
363 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
364 MasterBootRecord->Signature = DiskInfo->Signature;
367
368 /* Finally, write MBR */
370 Disk->SectorSize,
371 0ULL,
372 Disk->Buffer);
373
374 /* Release internal structure and return */
376 return Status;
377}
NTSTATUS NTAPI FstubWriteSector(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONGLONG StartingSector OPTIONAL, IN PVOID Buffer)
Definition: fstubex.c:1741
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:1190
#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: part_mbr.h:40
PARTITION_TABLE_ENTRY PartitionTable[4]
Definition: part_mbr.h:39
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by IoCreateDisk().

◆ FstubCreateDiskRaw()

NTSTATUS NTAPI FstubCreateDiskRaw ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 450 of file fstubex.c.

451{
453 PDISK_INFORMATION Disk = NULL;
454 PARTITION_STYLE PartitionStyle;
455 PMASTER_BOOT_RECORD MasterBootRecord;
456
457 PAGED_CODE();
458
460
461 /* Allocate internal structure */
463 if (!NT_SUCCESS(Status))
464 {
465 return Status;
466 }
467
468 /* Detect current disk partition style */
469 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
470 if (!NT_SUCCESS(Status))
471 {
473 return Status;
474 }
475
476 /* Read MBR, if any */
478 Disk->SectorSize,
479 0ULL,
480 Disk->Buffer);
481 if (!NT_SUCCESS(Status))
482 {
484 return Status;
485 }
486
487 /* Only zero useful stuff */
488 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
489 MasterBootRecord->Signature = 0;
490 RtlZeroMemory(MasterBootRecord->PartitionTable, sizeof(PARTITION_TABLE_ENTRY));
491 MasterBootRecord->MasterBootRecordMagic = 0;
492
493 /* Write back that destroyed MBR */
495 Disk->SectorSize,
496 0ULL,
497 Disk->Buffer);
498 /* If previous style wasn't GPT, we're done here */
499 if (PartitionStyle != PARTITION_STYLE_GPT)
500 {
502 return Status;
503 }
504
505 /* Otherwise, we've to zero the two GPT headers */
506 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
507 /* Erase primary header */
509 Disk->SectorSize,
510 1ULL,
511 Disk->Buffer);
512 /* In case of success, erase backup header */
513 if (NT_SUCCESS(Status))
514 {
516 Disk->SectorSize,
517 Disk->SectorCount - 1ULL,
518 Disk->Buffer);
519 }
520
521 /* Release internal structure and return */
523 return Status;
524}
NTSTATUS NTAPI FstubDetectPartitionStyle(IN PDISK_INFORMATION Disk, IN PARTITION_STYLE *PartitionStyle)
Definition: fstubex.c:671
enum _PARTITION_STYLE PARTITION_STYLE
@ PARTITION_STYLE_GPT
Definition: imports.h:202

Referenced by IoCreateDisk().

◆ FstubDetectPartitionStyle()

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

Definition at line 671 of file fstubex.c.

673{
675 PPARTITION_DESCRIPTOR PartitionDescriptor;
676
677 PAGED_CODE();
678
680 ASSERT(PartitionStyle);
681
682 /* Read disk first sector */
683 Status = FstubReadSector(Disk->DeviceObject,
684 Disk->SectorSize,
685 0,
686 Disk->Buffer);
687 if (!NT_SUCCESS(Status))
688 {
689 return Status;
690 }
691
692 /* Get the partition descriptor array */
693 PartitionDescriptor = (PPARTITION_DESCRIPTOR)&Disk->Buffer[PARTITION_TABLE_OFFSET];
694 /* If we have not the 0xAA55 then it's raw partition */
696 {
697 *PartitionStyle = PARTITION_STYLE_RAW;
698 }
699 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
700 else if (PartitionDescriptor[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
701 PartitionDescriptor[1].PartitionType == 0 &&
702 PartitionDescriptor[2].PartitionType == 0 &&
703 PartitionDescriptor[3].PartitionType == 0)
704 {
705 *PartitionStyle = PARTITION_STYLE_GPT;
706 }
707 /* Otherwise, partition table is in MBR */
708 else
709 {
710 *PartitionStyle = PARTITION_STYLE_MBR;
711 }
712
713 return STATUS_SUCCESS;
714}
unsigned short * PUINT16
Definition: basetsd.h:186
#define IS_VALID_DISK_INFO(Disk)
Definition: fstubex.c:96
#define EFI_PMBR_OSTYPE_EFI
Definition: fstubex.c:92
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
UCHAR PartitionType
Definition: part_brfr.c:23

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

◆ FstubFreeDiskInformation()

VOID NTAPI FstubFreeDiskInformation ( IN PDISK_INFORMATION  DiskBuffer)

Definition at line 718 of file fstubex.c.

719{
720 if (DiskBuffer)
721 {
722 if (DiskBuffer->Buffer)
723 {
724 ExFreePoolWithTag(DiskBuffer->Buffer, TAG_FSTUB);
725 }
726 ExFreePoolWithTag(DiskBuffer, TAG_FSTUB);
727 }
728}

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 732 of file fstubex.c.

734{
736 PIRP Irp;
738 PDISK_GEOMETRY_EX DiskGeometry = NULL;
740
741 PAGED_CODE();
742
744 ASSERT(Geometry);
745
746 /* Allocate needed components */
748 if (!DiskGeometry)
749 {
751 goto Cleanup;
752 }
753
755 if (!IoStatusBlock)
756 {
758 goto Cleanup;
759 }
760
762 if (!Event)
763 {
765 goto Cleanup;
766 }
767 /* Initialize the waiting event */
769
770 /* Build the request to get disk geometry */
773 0,
774 0,
775 DiskGeometry,
776 sizeof(DISK_GEOMETRY_EX),
777 FALSE,
778 Event,
780 if (!Irp)
781 {
783 goto Cleanup;
784 }
785
786 /* Call the driver and wait for completion if needed */
788 if (Status == STATUS_PENDING)
789 {
792 }
793
794 /* In case of a success, return read data */
795 if (NT_SUCCESS(Status))
796 {
797 *Geometry = *DiskGeometry;
798 }
799
800Cleanup:
801 if (DiskGeometry)
802 {
803 ExFreePoolWithTag(DiskGeometry, TAG_FSTUB);
804
805 if (NT_SUCCESS(Status))
806 {
807 ASSERT(Geometry->Geometry.BytesPerSector % PARTITION_ENTRY_SIZE == 0);
808 }
809 }
810
811 if (IoStatusBlock)
812 {
814 }
815
816 if (Event)
817 {
819 }
820
821 return Status;
822}
_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
#define KernelMode
Definition: asm.h:38
@ NotificationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
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: telnetd.h:14
@ Executive
Definition: ketypes.h:467

Referenced by FstubAllocateDiskInformation().

◆ FstubReadHeaderEFI()

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

Definition at line 826 of file fstubex.c.

829{
831 PUCHAR Sector = NULL;
832 ULONGLONG StartingSector;
833 PEFI_PARTITION_HEADER EFIHeader;
834 ULONG i, HeaderCRC32, PreviousCRC32, SectoredPartitionEntriesSize, LonelyPartitions;
835
836 PAGED_CODE();
837
838 ASSERT(Disk);
840 ASSERT(HeaderBuffer);
841
842 /* In case we want to read backup table, we read last disk sector */
843 if (ReadBackupTable)
844 {
845 StartingSector = Disk->SectorCount - 1ULL;
846 }
847 else
848 {
849 /* Otherwise we start at first sector (as sector 0 is the MBR) */
850 StartingSector = 1ULL;
851 }
852
853 Status = FstubReadSector(Disk->DeviceObject,
854 Disk->SectorSize,
855 StartingSector,
856 Disk->Buffer);
857 if (!NT_SUCCESS(Status))
858 {
859 DPRINT("EFI::Failed reading header!\n");
860 return Status;
861 }
862 /* Let's use read buffer as EFI_PARTITION_HEADER */
863 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
864
865
866 /* First check signature
867 * Then, check version (we only support v1)
868 * Finally check header size
869 */
870 if (EFIHeader->Signature != EFI_HEADER_SIGNATURE ||
871 EFIHeader->Revision != EFI_HEADER_REVISION_1 ||
872 EFIHeader->HeaderSize != sizeof(EFI_PARTITION_HEADER))
873 {
874 DPRINT("EFI::Wrong signature/version/header size!\n");
875 DPRINT("%I64x (expected: %I64x)\n", EFIHeader->Signature, EFI_HEADER_SIGNATURE);
876 DPRINT("%03x (expected: %03x)\n", EFIHeader->Revision, EFI_HEADER_REVISION_1);
877 DPRINT("%02x (expected: %02x)\n", EFIHeader->HeaderSize, sizeof(EFI_PARTITION_HEADER));
879 }
880
881 /* Save current checksum */
882 HeaderCRC32 = EFIHeader->HeaderCRC32;
883 /* Then zero the one in EFI header. This is needed to compute header checksum */
884 EFIHeader->HeaderCRC32 = 0;
885 /* Compute header checksum and compare with the one present in partition table */
886 if (RtlComputeCrc32(0, Disk->Buffer, sizeof(EFI_PARTITION_HEADER)) != HeaderCRC32)
887 {
888 DPRINT("EFI::Not matching header checksum!\n");
890 }
891 /* Put back removed checksum in header */
892 EFIHeader->HeaderCRC32 = HeaderCRC32;
893
894 /* Check if current LBA is matching with ours */
895 if (EFIHeader->MyLBA != StartingSector)
896 {
897 DPRINT("EFI::Not matching starting sector!\n");
899 }
900
901 /* Allocate a buffer to read a sector on the disk */
903 Disk->SectorSize,
904 TAG_FSTUB);
905 if (!Sector)
906 {
907 DPRINT("EFI::Lacking resources!\n");
909 }
910
911 /* Count how much sectors we'll have to read to read the whole partition table */
912 SectoredPartitionEntriesSize = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
913 /* Compute partition table checksum */
914 for (i = 0, PreviousCRC32 = 0; i < SectoredPartitionEntriesSize; i++)
915 {
916 Status = FstubReadSector(Disk->DeviceObject,
917 Disk->SectorSize,
918 EFIHeader->PartitionEntryLBA + i,
919 Sector);
920 if (!NT_SUCCESS(Status))
921 {
923 DPRINT("EFI::Failed reading sector for partition entry!\n");
924 return Status;
925 }
926
927 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector, Disk->SectorSize);
928 }
929
930 /* Check whether we have a last sector not full of partitions */
931 LonelyPartitions = (EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) % Disk->SectorSize;
932 /* In such case, we have to complete checksum computation */
933 if (LonelyPartitions != 0)
934 {
935 /* Read the sector that contains those partitions */
936 Status = FstubReadSector(Disk->DeviceObject,
937 Disk->SectorSize,
938 EFIHeader->PartitionEntryLBA + i,
939 Sector);
940 if (!NT_SUCCESS(Status))
941 {
943 DPRINT("EFI::Failed reading sector for partition entry!\n");
944 return Status;
945 }
946
947 /* Then complete checksum by computing on each partition */
948 for (i = 0; i < LonelyPartitions; i++)
949 {
950 PreviousCRC32 = RtlComputeCrc32(PreviousCRC32, Sector + i * PARTITION_ENTRY_SIZE, PARTITION_ENTRY_SIZE);
951 }
952 }
953
954 /* Finally, release memory */
956
957 /* Compare checksums */
958 if (PreviousCRC32 == EFIHeader->PartitionEntryCRC32)
959 {
960 /* In case of a success, return read header */
961 *HeaderBuffer = EFIHeader;
962 return STATUS_SUCCESS;
963 }
964 else
965 {
966 DPRINT("EFI::Not matching partition table checksum!\n");
967 DPRINT("EFI::Expected: %x, received: %x\n", EFIHeader->PartitionEntryCRC32, PreviousCRC32);
969 }
970}
#define RtlComputeCrc32
Definition: compat.h:810
#define EFI_HEADER_SIGNATURE
Definition: fstubex.c:88
struct _EFI_PARTITION_HEADER * PEFI_PARTITION_HEADER
#define EFI_HEADER_REVISION_1
Definition: fstubex.c:90
for(i=0;i< ARRAY_SIZE(offsets);i++)
#define DPRINT
Definition: sndvol32.h:73
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 974 of file fstubex.c.

977{
979 ULONG NumberOfEntries;
980 PEFI_PARTITION_HEADER EfiHeader;
981 EFI_PARTITION_ENTRY PartitionEntry;
982#if 0
983 BOOLEAN UpdatedPartitionTable = FALSE;
984 ULONGLONG SectorsForPartitions, PartitionEntryLBA;
985#else
986 ULONGLONG PartitionEntryLBA;
987#endif
988 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
990 ULONG i, PartitionCount, PartitionIndex, PartitionsPerSector;
991
992 PAGED_CODE();
993
994 ASSERT(Disk);
995
996 /* Zero output */
997 *DriveLayout = NULL;
998
999 /* Read EFI header */
1001 ReadBackupTable,
1002 &EfiHeader);
1003 if (!NT_SUCCESS(Status))
1004 {
1005 return Status;
1006 }
1007
1008 /* Backup the number of entries, will be used later on */
1009 NumberOfEntries = EfiHeader->NumberOfEntries;
1010
1011 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1012 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1013 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1014 EfiHeader->NumberOfEntries * sizeof(PARTITION_INFORMATION_EX),
1015 TAG_FSTUB);
1016 if (!DriveLayoutEx)
1017 {
1019 }
1020
1021#if 0
1022 if (!ReadBackupTable)
1023 {
1024 /* If we weren't ask to read backup table,
1025 * check the status of the backup table.
1026 * In case it's not where we're expecting it, move it and ask
1027 * for a partition table rewrite.
1028 */
1029 if ((Disk->SectorCount - 1ULL) != EfiHeader->AlternateLBA)
1030 {
1031 /* We'll update it. First, count number of sectors needed to store partitions */
1032 SectorsForPartitions = ((ULONGLONG)EfiHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1033 /* Then set first usable LBA: Legacy MBR + GPT header + Partitions entries */
1034 EfiHeader->FirstUsableLBA = SectorsForPartitions + 2;
1035 /* Then set last usable LBA: Last sector - GPT header - Partitions entries */
1036 EfiHeader->LastUsableLBA = Disk->SectorCount - SectorsForPartitions - 1;
1037 /* Inform that we'll rewrite partition table */
1038 UpdatedPartitionTable = TRUE;
1039 }
1040 }
1041#endif
1042
1043 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_GPT;
1044 /* Translate LBA -> Offset */
1045 DriveLayoutEx->Gpt.StartingUsableOffset.QuadPart = EfiHeader->FirstUsableLBA * Disk->SectorSize;
1046 DriveLayoutEx->Gpt.UsableLength.QuadPart = (EfiHeader->LastUsableLBA - EfiHeader->FirstUsableLBA) * Disk->SectorSize;
1047 DriveLayoutEx->Gpt.MaxPartitionCount = EfiHeader->NumberOfEntries;
1048 DriveLayoutEx->Gpt.DiskId = EfiHeader->DiskGUID;
1049
1050 /* Backup partition entry position */
1051 PartitionEntryLBA = EfiHeader->PartitionEntryLBA;
1052 /* Count number of partitions per sector */
1053 PartitionsPerSector = (Disk->SectorSize / PARTITION_ENTRY_SIZE);
1054 /* Read all partitions and fill in structure
1055 * BEWARE! Past that point EfiHeader IS NOT VALID ANYMORE
1056 * It will be erased by the reading of the partition entry
1057 */
1058 for (i = 0, PartitionCount = 0, PartitionIndex = PartitionsPerSector;
1059 i < NumberOfEntries;
1060 i++)
1061 {
1062 /* Only read following sector if we finished with previous sector */
1063 if (PartitionIndex == PartitionsPerSector)
1064 {
1065 Status = FstubReadSector(Disk->DeviceObject,
1066 Disk->SectorSize,
1067 PartitionEntryLBA + (i / PartitionsPerSector),
1068 Disk->Buffer);
1069 if (!NT_SUCCESS(Status))
1070 {
1071 ExFreePoolWithTag(DriveLayoutEx, TAG_FSTUB);
1072 return Status;
1073 }
1074
1075 PartitionIndex = 0;
1076 }
1077 /* Read following partition */
1078 PartitionEntry = ((PEFI_PARTITION_ENTRY)Disk->Buffer)[PartitionIndex];
1079 PartitionIndex++;
1080
1081 /* Skip unused partition */
1082 if (IsEqualGUID(&PartitionEntry.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
1083 continue;
1084
1085 /* Write data to structure. Don't forget GPT is using sectors, Windows offsets */
1086 PartitionInfo = &DriveLayoutEx->PartitionEntry[PartitionCount];
1087
1088 PartitionInfo->StartingOffset.QuadPart = PartitionEntry.StartingLBA * Disk->SectorSize;
1089 PartitionInfo->PartitionLength.QuadPart = (PartitionEntry.EndingLBA -
1090 PartitionEntry.StartingLBA + 1) * Disk->SectorSize;
1091 /* This number starts from 1 */
1092 PartitionInfo->PartitionNumber = PartitionCount + 1;
1093 PartitionInfo->RewritePartition = FALSE;
1094 PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT;
1095 PartitionInfo->Gpt.PartitionType = PartitionEntry.PartitionType;
1096 PartitionInfo->Gpt.PartitionId = PartitionEntry.UniquePartition;
1097 PartitionInfo->Gpt.Attributes = PartitionEntry.Attributes;
1098 RtlCopyMemory(PartitionInfo->Gpt.Name,
1099 PartitionEntry.Name, sizeof(PartitionEntry.Name));
1100
1101 /* Update partition count */
1102 PartitionCount++;
1103 }
1104 DriveLayoutEx->PartitionCount = PartitionCount;
1105
1106#if 0
1107 /* If we updated partition table using backup table, rewrite partition table */
1108 if (UpdatedPartitionTable)
1109 {
1110 IoWritePartitionTableEx(Disk->DeviceObject,
1111 DriveLayoutEx);
1112 }
1113#endif
1114
1115 /* Finally, return read data */
1116 *DriveLayout = DriveLayoutEx;
1117
1118 return Status;
1119}
unsigned char BOOLEAN
Definition: actypes.h:127
NTSTATUS NTAPI IoWritePartitionTableEx(IN PDEVICE_OBJECT DeviceObject, IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout)
Definition: fstubex.c:2459
NTSTATUS NTAPI FstubReadHeaderEFI(IN PDISK_INFORMATION Disk, IN BOOLEAN ReadBackupTable, PEFI_PARTITION_HEADER *HeaderBuffer)
Definition: fstubex.c:826
struct _EFI_PARTITION_ENTRY * PEFI_PARTITION_ENTRY
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
Definition: fstubex.c:48
GUID UniquePartition
Definition: fstubex.c:50
GUID PartitionType
Definition: fstubex.c:49
ULONGLONG StartingLBA
Definition: fstubex.c:51
WCHAR Name[0x24]
Definition: fstubex.c:54
ULONGLONG Attributes
Definition: fstubex.c:53
ULONGLONG EndingLBA
Definition: fstubex.c:52
ULONGLONG FirstUsableLBA
Definition: fstubex.c:36
ULONGLONG AlternateLBA
Definition: fstubex.c:35
ULONGLONG LastUsableLBA
Definition: fstubex.c:37
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105

Referenced by IoReadPartitionTableEx().

◆ FstubReadPartitionTableMBR()

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

Definition at line 1123 of file fstubex.c.

1126{
1128 ULONG i;
1129 PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
1130 PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = NULL;
1131
1132 PAGED_CODE();
1133
1135 ASSERT(ReturnedDriveLayout);
1136
1137 /* Zero output */
1138 *ReturnedDriveLayout = NULL;
1139
1140 /* Read partition table the old way */
1141 Status = IoReadPartitionTable(Disk->DeviceObject,
1142 Disk->SectorSize,
1144 &DriveLayout);
1145 if (!NT_SUCCESS(Status))
1146 {
1147 return Status;
1148 }
1149
1150 /* Allocate a DRIVE_LAYOUT_INFORMATION_EX struct big enough */
1151 DriveLayoutEx = ExAllocatePoolWithTag(NonPagedPool,
1152 FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) +
1153 DriveLayout->PartitionCount * sizeof(PARTITION_INFORMATION_EX),
1154 TAG_FSTUB);
1155 if (!DriveLayoutEx)
1156 {
1157 /* Let's not leak memory as in Windows 2003 */
1158 ExFreePool(DriveLayout);
1160 }
1161
1162 /* Start converting the DRIVE_LAYOUT_INFORMATION structure */
1163 DriveLayoutEx->PartitionStyle = PARTITION_STYLE_MBR;
1164 DriveLayoutEx->PartitionCount = DriveLayout->PartitionCount;
1165 DriveLayoutEx->Mbr.Signature = DriveLayout->Signature;
1166
1167 /* Convert each found partition */
1168 for (i = 0; i < DriveLayout->PartitionCount; i++)
1169 {
1170 DriveLayoutEx->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
1171 DriveLayoutEx->PartitionEntry[i].StartingOffset = DriveLayout->PartitionEntry[i].StartingOffset;
1172 DriveLayoutEx->PartitionEntry[i].PartitionLength = DriveLayout->PartitionEntry[i].PartitionLength;
1173 DriveLayoutEx->PartitionEntry[i].PartitionNumber = DriveLayout->PartitionEntry[i].PartitionNumber;
1174 DriveLayoutEx->PartitionEntry[i].RewritePartition = DriveLayout->PartitionEntry[i].RewritePartition;
1175 DriveLayoutEx->PartitionEntry[i].Mbr.PartitionType = DriveLayout->PartitionEntry[i].PartitionType;
1176 DriveLayoutEx->PartitionEntry[i].Mbr.BootIndicator = DriveLayout->PartitionEntry[i].BootIndicator;
1177 DriveLayoutEx->PartitionEntry[i].Mbr.RecognizedPartition = DriveLayout->PartitionEntry[i].RecognizedPartition;
1178 DriveLayoutEx->PartitionEntry[i].Mbr.HiddenSectors = DriveLayout->PartitionEntry[i].HiddenSectors;
1179 }
1180
1181 /* Finally, return data and free old structure */
1182 *ReturnedDriveLayout = DriveLayoutEx;
1183 ExFreePool(DriveLayout);
1184
1185 return STATUS_SUCCESS;
1186}
NTSTATUS FASTCALL IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN BOOLEAN ReturnRecognizedPartitions, OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
Definition: ntoskrnl.c:115
#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 1190 of file fstubex.c.

1194{
1196 PIRP Irp;
1197 KEVENT Event;
1201
1202 PAGED_CODE();
1203
1205 ASSERT(Buffer);
1207
1208 /* Compute starting offset */
1209 StartingOffset.QuadPart = StartingSector * SectorSize;
1210
1211 /* Initialize waiting event */
1213
1214 /* Prepare IRP */
1217 Buffer,
1218 SectorSize,
1220 &Event,
1221 &IoStatusBlock);
1222 if (!Irp)
1223 {
1225 }
1226
1227 /* Override volume verify */
1230
1231 /* Then call driver, and wait for completion if needed */
1233 if (Status == STATUS_PENDING)
1234 {
1237 }
1238
1239 return Status;
1240}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
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
_In_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:265
__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 1244 of file fstubex.c.

1247{
1249 PDRIVE_LAYOUT_INFORMATION_EX Layout = NULL;
1250
1251 PAGED_CODE();
1252
1253 ASSERT(Disk);
1255
1256 /* Partition 0 isn't correct (should start at 1) */
1257 if (PartitionNumber == 0)
1258 {
1260 }
1261
1262 /* Read partition table */
1263 Status = IoReadPartitionTableEx(Disk->DeviceObject, &Layout);
1264 if (!NT_SUCCESS(Status))
1265 {
1266 return Status;
1267 }
1268 ASSERT(Layout);
1269
1270 /* If our partition (started at 0 now) is higher than partition count, then, there's an issue */
1271 if (Layout->PartitionCount <= --PartitionNumber)
1272 {
1273 ExFreePool(Layout);
1275 }
1276
1277 /* Erase actual partition entry data with provided ones */
1278 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionType = PartitionInfo->PartitionType;
1279 Layout->PartitionEntry[PartitionNumber].Gpt.PartitionId = PartitionInfo->PartitionId;
1280 Layout->PartitionEntry[PartitionNumber].Gpt.Attributes = PartitionInfo->Attributes;
1281 RtlCopyMemory(Layout->PartitionEntry[PartitionNumber].Gpt.Name, PartitionInfo->Name, sizeof(PartitionInfo->Name));
1282
1283 /* Rewrite the whole partition table to update the modified entry */
1284 Status = IoWritePartitionTableEx(Disk->DeviceObject, Layout);
1285
1286 /* Free partition table and return */
1287 ExFreePool(Layout);
1288 return Status;
1289}
NTSTATUS NTAPI IoReadPartitionTableEx(IN PDEVICE_OBJECT DeviceObject, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: fstubex.c:2274
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061

Referenced by IoSetPartitionInformationEx().

◆ FstubVerifyPartitionTableEFI()

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

Definition at line 1293 of file fstubex.c.

1295{
1297 PEFI_PARTITION_HEADER EFIHeader, ReadEFIHeader;
1298 BOOLEAN PrimaryValid = FALSE, BackupValid = FALSE, WriteBackup;
1299 ULONGLONG ReadPosition, WritePosition, SectorsForPartitions, PartitionIndex;
1300
1301 PAGED_CODE();
1302
1304 if (!EFIHeader)
1305 {
1307 }
1308
1309 Status = FstubReadHeaderEFI(Disk, FALSE, &ReadEFIHeader);
1310 if (NT_SUCCESS(Status))
1311 {
1312 PrimaryValid = TRUE;
1313 ASSERT(ReadEFIHeader);
1314 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1315 }
1316
1317 Status = FstubReadHeaderEFI(Disk, TRUE, &ReadEFIHeader);
1318 if (NT_SUCCESS(Status))
1319 {
1320 BackupValid = TRUE;
1321 ASSERT(ReadEFIHeader);
1322 RtlCopyMemory(EFIHeader, ReadEFIHeader, sizeof(EFI_PARTITION_HEADER));
1323 }
1324
1325 /* If both are sane, just return */
1326 if (PrimaryValid && BackupValid)
1327 {
1328 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1329 return STATUS_SUCCESS;
1330 }
1331
1332 /* If both are damaged OR if we have not been ordered to fix
1333 * Then, quit and warn about disk corruption
1334 */
1335 if ((!PrimaryValid && !BackupValid) || !FixErrors)
1336 {
1337 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1339 }
1340
1341 /* Compute sectors taken by partitions */
1342 SectorsForPartitions = (((ULONGLONG)EFIHeader->NumberOfEntries * PARTITION_ENTRY_SIZE) + Disk->SectorSize - 1) / Disk->SectorSize;
1343 if (PrimaryValid)
1344 {
1345 WriteBackup = TRUE;
1346 /* Take position at backup table for writing */
1347 WritePosition = Disk->SectorCount - SectorsForPartitions;
1348 /* And read from primary table */
1349 ReadPosition = 2ULL;
1350
1351 DPRINT("EFI::Will repair backup table from primary\n");
1352 }
1353 else
1354 {
1355 ASSERT(BackupValid);
1356 WriteBackup = FALSE;
1357 /* Take position at primary table for writing */
1358 WritePosition = 2ULL;
1359 /* And read from backup table */
1360 ReadPosition = Disk->SectorCount - SectorsForPartitions;
1361
1362 DPRINT("EFI::Will repair primary table from backup\n");
1363 }
1364
1365 PartitionIndex = 0ULL;
1366
1367 /* If no partitions are to be copied, just restore header */
1368 if (SectorsForPartitions <= 0)
1369 {
1371 SectorsForPartitions,
1372 EFIHeader->DiskGUID,
1373 EFIHeader->NumberOfEntries,
1374 EFIHeader->FirstUsableLBA,
1375 EFIHeader->LastUsableLBA,
1376 EFIHeader->PartitionEntryCRC32,
1377 WriteBackup);
1378
1379 goto Cleanup;
1380 }
1381
1382 /* Copy all the partitions */
1383 for (; PartitionIndex < SectorsForPartitions; ++PartitionIndex)
1384 {
1385 /* First, read the partition from the first table */
1386 Status = FstubReadSector(Disk->DeviceObject,
1387 Disk->SectorSize,
1388 ReadPosition + PartitionIndex,
1389 Disk->Buffer);
1390 if (!NT_SUCCESS(Status))
1391 {
1392 goto Cleanup;
1393 }
1394
1395 /* Then, write it in the other table */
1396 Status = FstubWriteSector(Disk->DeviceObject,
1397 Disk->SectorSize,
1398 WritePosition + PartitionIndex,
1399 Disk->Buffer);
1400 if (!NT_SUCCESS(Status))
1401 {
1402 goto Cleanup;
1403 }
1404 }
1405
1406 /* Now we're done, write the header */
1408 SectorsForPartitions,
1409 EFIHeader->DiskGUID,
1410 EFIHeader->NumberOfEntries,
1411 EFIHeader->FirstUsableLBA,
1412 EFIHeader->LastUsableLBA,
1413 EFIHeader->PartitionEntryCRC32,
1414 WriteBackup);
1415
1416Cleanup:
1417 ExFreePoolWithTag(EFIHeader, TAG_FSTUB);
1418 return Status;
1419}
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:1543

Referenced by IoVerifyPartitionTable().

◆ FstubWriteBootSectorEFI()

NTSTATUS NTAPI FstubWriteBootSectorEFI ( IN PDISK_INFORMATION  Disk)

Definition at line 1423 of file fstubex.c.

1424{
1426 ULONG Signature = 0;
1427 PMASTER_BOOT_RECORD MasterBootRecord;
1428
1429 PAGED_CODE();
1430
1431 ASSERT(Disk);
1433
1434 /* Read if a MBR is already present */
1435 Status = FstubReadSector(Disk->DeviceObject,
1436 Disk->SectorSize,
1437 0ULL,
1438 Disk->Buffer);
1439 MasterBootRecord = (PMASTER_BOOT_RECORD)Disk->Buffer;
1440 /* If one has been found */
1442 {
1443 /* Save its signature */
1444 Signature = MasterBootRecord->Signature;
1445 }
1446
1447 /* Reset the MBR */
1448 RtlZeroMemory(MasterBootRecord, Disk->SectorSize);
1449 /* Then create a fake MBR matching those purposes:
1450 * It must have only partition. Type of this partition
1451 * has to be 0xEE to signal a GPT is following.
1452 * This partition has to cover the whole disk. To prevent
1453 * any disk modification by a program that wouldn't
1454 * understand anything to GPT.
1455 */
1456 MasterBootRecord->Signature = Signature;
1457 MasterBootRecord->PartitionTable[0].StartSector = 2;
1458 MasterBootRecord->PartitionTable[0].SystemIndicator = EFI_PMBR_OSTYPE_EFI;
1459 MasterBootRecord->PartitionTable[0].EndHead = 0xFF;
1460 MasterBootRecord->PartitionTable[0].EndSector = 0xFF;
1461 MasterBootRecord->PartitionTable[0].EndCylinder = 0xFF;
1462 MasterBootRecord->PartitionTable[0].SectorCountBeforePartition = 1;
1463 MasterBootRecord->PartitionTable[0].PartitionSectorCount = 0xFFFFFFFF;
1464 MasterBootRecord->MasterBootRecordMagic = BOOT_RECORD_SIGNATURE;
1465
1466 /* Finally, write that MBR */
1467 return FstubWriteSector(Disk->DeviceObject,
1468 Disk->SectorSize,
1469 0,
1470 Disk->Buffer);
1471}
static const WCHAR Signature[]
Definition: parser.c:141
ULONG SectorCountBeforePartition
Definition: part_mbr.h:26
ULONG PartitionSectorCount
Definition: part_mbr.h:27
UCHAR StartSector
Definition: part_mbr.h:20
UCHAR SystemIndicator
Definition: part_mbr.h:22
UCHAR EndHead
Definition: part_mbr.h:23
UCHAR EndSector
Definition: part_mbr.h:24
UCHAR EndCylinder
Definition: part_mbr.h:25

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 1475 of file fstubex.c.

1482{
1484 ULONG Offset;
1485 ULONGLONG FirstEntryLBA;
1486
1487 PAGED_CODE();
1488
1489 ASSERT(Disk);
1491
1492 /* Get the first LBA where the partition table is:
1493 * On primary table, it's sector 2 (skip MBR & Header)
1494 * On backup table, it's ante last sector (Header) minus partition table size
1495 */
1496 if (!WriteBackupTable)
1497 {
1498 FirstEntryLBA = 2ULL;
1499 }
1500 else
1501 {
1502 FirstEntryLBA = Disk->SectorCount - PartitionsSizeSector - 1;
1503 }
1504
1505 /* Copy the entry at the proper place into the buffer
1506 * That way, we don't erase previous entries
1507 */
1508 RtlCopyMemory((PVOID)((ULONG_PTR)Disk->Buffer + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize)),
1509 PartitionEntry,
1510 sizeof(EFI_PARTITION_ENTRY));
1511 /* Compute size of buffer */
1512 Offset = (PartitionEntryNumber * PARTITION_ENTRY_SIZE) % Disk->SectorSize + PARTITION_ENTRY_SIZE;
1513 ASSERT(Offset <= Disk->SectorSize);
1514
1515 /* If it's full of partition entries, or if call ask for it, write down the data */
1516 if (Offset == Disk->SectorSize || ForceWrite)
1517 {
1518 /* We will write at first entry LBA + a shift made by already present/written entries */
1519 Status = FstubWriteSector(Disk->DeviceObject,
1520 Disk->SectorSize,
1521 FirstEntryLBA + ((PartitionEntryNumber * PARTITION_ENTRY_SIZE) / Disk->SectorSize),
1522 Disk->Buffer);
1523 if (!NT_SUCCESS(Status))
1524 {
1525 return Status;
1526 }
1527
1528 /* We clean buffer */
1529 RtlZeroMemory(Disk->Buffer, Disk->SectorSize);
1530 }
1531
1532 /* If we have a buffer for CRC32, then compute it */
1533 if (PartitionEntryCRC32)
1534 {
1535 *PartitionEntryCRC32 = RtlComputeCrc32(*PartitionEntryCRC32, (PUCHAR)PartitionEntry, PARTITION_ENTRY_SIZE);
1536 }
1537
1538 return Status;
1539}
_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 1543 of file fstubex.c.

1551{
1552 PEFI_PARTITION_HEADER EFIHeader;
1553
1554 PAGED_CODE();
1555
1556 ASSERT(Disk);
1558
1559 /* Let's use read buffer as EFI_PARTITION_HEADER */
1560 EFIHeader = (PEFI_PARTITION_HEADER)Disk->Buffer;
1561
1562 /* Complete standard header information */
1563 EFIHeader->Signature = EFI_HEADER_SIGNATURE;
1564 EFIHeader->Revision = EFI_HEADER_REVISION_1;
1565 EFIHeader->HeaderSize = sizeof(EFI_PARTITION_HEADER);
1566 /* Set no CRC32 checksum at the moment */
1567 EFIHeader->HeaderCRC32 = 0;
1568 EFIHeader->Reserved = 0;
1569 /* Check whether we're writing primary or backup
1570 * That way, we can ajust LBA setting:
1571 * Primary is on first sector
1572 * Backup is on last sector
1573 */
1574 if (!WriteBackupTable)
1575 {
1576 EFIHeader->MyLBA = 1ULL;
1577 EFIHeader->AlternateLBA = Disk->SectorCount - 1ULL;
1578 }
1579 else
1580 {
1581 EFIHeader->MyLBA = Disk->SectorCount - 1ULL;
1582 EFIHeader->AlternateLBA = 1ULL;
1583 }
1584 /* Fill in with received data */
1585 EFIHeader->FirstUsableLBA = FirstUsableLBA;
1586 EFIHeader->LastUsableLBA = LastUsableLBA;
1587 EFIHeader->DiskGUID = DiskGUID;
1588 /* Check whether we're writing primary or backup
1589 * That way, we can ajust LBA setting:
1590 * On primary, partition entries are just after header, so sector 2
1591 * On backup, partition entries are just before header, so, last sector minus partition table size
1592 */
1593 if (!WriteBackupTable)
1594 {
1595 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA + 1ULL;
1596 }
1597 else
1598 {
1599 EFIHeader->PartitionEntryLBA = EFIHeader->MyLBA - PartitionsSizeSector;
1600 }
1601 /* Complete filling in */
1602 EFIHeader->NumberOfEntries = NumberOfEntries;
1604 EFIHeader->PartitionEntryCRC32 = PartitionEntryCRC32;
1605 /* Finally, compute header checksum */
1606 EFIHeader->HeaderCRC32 = RtlComputeCrc32(0, (PUCHAR)EFIHeader, sizeof(EFI_PARTITION_HEADER));
1607
1608 /* Debug the way we'll break disk, to let user pray */
1609 DPRINT("FSTUB: About to write the following header for %s table\n", (WriteBackupTable ? "backup" : "primary"));
1610 DPRINT(" Signature: %I64x\n", EFIHeader->Signature);
1611 DPRINT(" Revision: %x\n", EFIHeader->Revision);
1612 DPRINT(" HeaderSize: %x\n", EFIHeader->HeaderSize);
1613 DPRINT(" HeaderCRC32: %x\n", EFIHeader->HeaderCRC32);
1614 DPRINT(" MyLBA: %I64x\n", EFIHeader->MyLBA);
1615 DPRINT(" AlternateLBA: %I64x\n", EFIHeader->AlternateLBA);
1616 DPRINT(" FirstUsableLBA: %I64x\n", EFIHeader->FirstUsableLBA);
1617 DPRINT(" LastUsableLBA: %I64x\n", EFIHeader->LastUsableLBA);
1618 DPRINT(" PartitionEntryLBA: %I64x\n", EFIHeader->PartitionEntryLBA);
1619 DPRINT(" NumberOfEntries: %x\n", EFIHeader->NumberOfEntries);
1620 DPRINT(" SizeOfPartitionEntry: %x\n", EFIHeader->SizeOfPartitionEntry);
1621 DPRINT(" PartitionEntryCRC32: %x\n", EFIHeader->PartitionEntryCRC32);
1622
1623 /* Write header to disk */
1624 return FstubWriteSector(Disk->DeviceObject,
1625 Disk->SectorSize,
1626 EFIHeader->MyLBA,
1627 Disk->Buffer);
1628}
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 1632 of file fstubex.c.

1640{
1643 ULONG i, WrittenPartitions, SectoredPartitionEntriesSize, PartitionEntryCRC32;
1644
1645 PAGED_CODE();
1646
1647 ASSERT(Disk);
1648 ASSERT(MaxPartitionCount >= 128);
1649 ASSERT(PartitionCount <= MaxPartitionCount);
1650
1651 PartitionEntryCRC32 = 0;
1652 /* Count how much sectors we'll have to read to read the whole partition table */
1653 SectoredPartitionEntriesSize = (MaxPartitionCount * PARTITION_ENTRY_SIZE) / Disk->SectorSize;
1654
1655 for (i = 0, WrittenPartitions = 0; i < PartitionCount; i++)
1656 {
1657 /* Skip unused partition */
1658 if (IsEqualGUID(&PartitionEntries[i].Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
1659 continue;
1660
1661 /* Copy the entry in the partition entry format */
1662 FstubCopyEntryEFI(&Entry, &PartitionEntries[i], Disk->SectorSize);
1663 /* Then write the entry to the disk */
1665 SectoredPartitionEntriesSize,
1666 WrittenPartitions,
1667 &Entry,
1668 WriteBackupTable,
1669 FALSE,
1670 &PartitionEntryCRC32);
1671 if (!NT_SUCCESS(Status))
1672 {
1673 return Status;
1674 }
1675 WrittenPartitions++;
1676 }
1677
1678 /* Zero the buffer to write zeros to the disk */
1680 /* Write the disks with zeros for every unused remaining partition entry */
1681 for (i = WrittenPartitions; i < MaxPartitionCount; i++)
1682 {
1684 SectoredPartitionEntriesSize,
1685 i,
1686 &Entry,
1687 WriteBackupTable,
1688 FALSE,
1689 &PartitionEntryCRC32);
1690 if (!NT_SUCCESS(Status))
1691 {
1692 return Status;
1693 }
1694 }
1695
1696 /* Once we're done, write the GPT header */
1697 return FstubWriteHeaderEFI(Disk,
1698 SectoredPartitionEntriesSize,
1699 DiskGUID,
1700 MaxPartitionCount,
1701 FirstUsableLBA,
1702 LastUsableLBA,
1703 PartitionEntryCRC32,
1704 WriteBackupTable);
1705}
VOID NTAPI FstubCopyEntryEFI(OUT PEFI_PARTITION_ENTRY Entry, IN PPARTITION_INFORMATION_EX Partition, ULONG SectorSize)
Definition: fstubex.c:313
NTSTATUS NTAPI FstubWriteEntryEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionsSizeSector, IN ULONG PartitionEntryNumber, IN PEFI_PARTITION_ENTRY PartitionEntry, IN BOOLEAN WriteBackupTable, IN BOOLEAN ForceWrite, OUT PULONG PartitionEntryCRC32 OPTIONAL)
Definition: fstubex.c:1475

Referenced by FstubCreateDiskEFI(), and IoWritePartitionTableEx().

◆ FstubWritePartitionTableMBR()

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

Definition at line 1709 of file fstubex.c.

1711{
1713 PDRIVE_LAYOUT_INFORMATION DriveLayout;
1714
1715 PAGED_CODE();
1716
1718 ASSERT(LayoutEx);
1719
1720 /* Convert data to the correct format */
1721 DriveLayout = FstubConvertExtendedToLayout(LayoutEx);
1722 if (!DriveLayout)
1723 {
1725 }
1726
1727 /* Really write information */
1728 Status = IoWritePartitionTable(Disk->DeviceObject,
1729 Disk->SectorSize,
1730 Disk->DiskGeometry.Geometry.SectorsPerTrack,
1731 Disk->DiskGeometry.Geometry.TracksPerCylinder,
1732 DriveLayout);
1733
1734 /* Free allocated structure and return */
1735 ExFreePoolWithTag(DriveLayout, TAG_FSTUB);
1736 return Status;
1737}
NTSTATUS FASTCALL IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG SectorsPerTrack, IN ULONG NumberOfHeads, IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
Definition: ntoskrnl.c:212
PDRIVE_LAYOUT_INFORMATION NTAPI FstubConvertExtendedToLayout(IN PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: fstubex.c:265

Referenced by IoWritePartitionTableEx().

◆ FstubWriteSector()

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

Definition at line 1741 of file fstubex.c.

1745{
1747 PIRP Irp;
1748 KEVENT Event;
1752
1753 PAGED_CODE();
1754
1756 ASSERT(Buffer);
1758
1759 /* Compute starting offset */
1760 StartingOffset.QuadPart = StartingSector * SectorSize;
1761
1762 /* Initialize waiting event */
1764
1765 /* Prepare IRP */
1768 Buffer,
1769 SectorSize,
1771 &Event,
1772 &IoStatusBlock);
1773 if (!Irp)
1774 {
1776 }
1777
1778 /* Override volume verify */
1781
1782 /* Then call driver, and wait for completion if needed */
1784 if (Status == STATUS_PENDING)
1785 {
1788 }
1789
1790 return Status;
1791}
#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 1800 of file fstubex.c.

1802{
1803 PARTITION_STYLE PartitionStyle;
1804
1805 PAGED_CODE();
1806
1808
1809 /* Get partition style. If caller didn't provided data, assume it's raw */
1810 PartitionStyle = ((Disk) ? Disk->PartitionStyle : PARTITION_STYLE_RAW);
1811 /* Then, call appropriate internal function */
1812 switch (PartitionStyle)
1813 {
1815 return FstubCreateDiskMBR(DeviceObject, &(Disk->Mbr));
1817 return FstubCreateDiskEFI(DeviceObject, &(Disk->Gpt));
1818 case PARTITION_STYLE_RAW:
1820 default:
1821 return STATUS_NOT_SUPPORTED;
1822 }
1823}
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
NTSTATUS NTAPI FstubCreateDiskRaw(IN PDEVICE_OBJECT DeviceObject)
Definition: fstubex.c:450
NTSTATUS NTAPI FstubCreateDiskMBR(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_MBR DiskInfo)
Definition: fstubex.c:334
NTSTATUS NTAPI FstubCreateDiskEFI(IN PDEVICE_OBJECT DeviceObject, IN PCREATE_DISK_GPT DiskInfo)
Definition: fstubex.c:381

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

◆ IoGetBootDiskInformation()

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

Definition at line 1830 of file fstubex.c.

1832{
1834 PIRP Irp;
1835 KEVENT Event;
1836 PLIST_ENTRY NextEntry;
1838 DISK_GEOMETRY DiskGeometry;
1840 UNICODE_STRING DeviceStringW;
1842 CHAR Buffer[128], ArcBuffer[128];
1843 BOOLEAN SingleDisk, IsBootDiskInfoEx;
1844 PARC_DISK_SIGNATURE ArcDiskSignature;
1845 PARC_DISK_INFORMATION ArcDiskInformation;
1846 PARTITION_INFORMATION_EX PartitionInformation;
1847 PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = NULL;
1848 ULONG DiskCount, DiskNumber, Signature, PartitionNumber;
1849 ANSI_STRING ArcBootString, ArcSystemString, DeviceStringA, ArcNameStringA;
1851
1852 PAGED_CODE();
1853
1854 /* Get loader block. If it's null, we come too late */
1855 if (!IopLoaderBlock)
1856 {
1857 return STATUS_TOO_LATE;
1858 }
1859
1860 /* Check buffer size */
1861 if (Size < sizeof(BOOTDISK_INFORMATION))
1862 {
1864 }
1865
1866 /* Init some useful stuff:
1867 * Get ARC disks information
1868 * Check whether we have a single disk on the machine
1869 * Check received structure size (extended or not?)
1870 * Init boot strings (system/boot)
1871 * Finaly, get disk count
1872 */
1873 ArcDiskInformation = IopLoaderBlock->ArcDiskInformation;
1874 SingleDisk = (ArcDiskInformation->DiskSignatureListHead.Flink->Flink ==
1875 &ArcDiskInformation->DiskSignatureListHead);
1876
1877 IsBootDiskInfoEx = (Size >= sizeof(BOOTDISK_INFORMATION_EX));
1881
1882 /* If no disk, return success */
1883 if (DiskCount == 0)
1884 {
1885 return STATUS_SUCCESS;
1886 }
1887
1888 /* Now, browse all disks */
1889 for (DiskNumber = 0; DiskNumber < DiskCount; DiskNumber++)
1890 {
1891 /* Create the device name */
1892 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition0", DiskNumber);
1893 RtlInitAnsiString(&DeviceStringA, Buffer);
1894 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1895 if (!NT_SUCCESS(Status))
1896 {
1897 continue;
1898 }
1899
1900 /* Get its device object */
1901 Status = IoGetDeviceObjectPointer(&DeviceStringW,
1903 &FileObject,
1904 &DeviceObject);
1905 RtlFreeUnicodeString(&DeviceStringW);
1906 if (!NT_SUCCESS(Status))
1907 {
1908 continue;
1909 }
1910
1911 /* Prepare for getting disk geometry */
1915 NULL,
1916 0,
1917 &DiskGeometry,
1918 sizeof(DiskGeometry),
1919 FALSE,
1920 &Event,
1921 &IoStatusBlock);
1922 if (!Irp)
1923 {
1925 continue;
1926 }
1927
1928 /* Then, call the drive, and wait for it if needed */
1930 if (Status == STATUS_PENDING)
1931 {
1934 }
1935 if (!NT_SUCCESS(Status))
1936 {
1938 continue;
1939 }
1940
1941 /* Read partition table */
1943 &DriveLayout);
1944
1945 /* FileObject, you can go! */
1947
1948 if (!NT_SUCCESS(Status))
1949 {
1950 continue;
1951 }
1952
1953 /* Ensure we have at least 512 bytes per sector */
1954 if (DiskGeometry.BytesPerSector < 512)
1955 {
1956 DiskGeometry.BytesPerSector = 512;
1957 }
1958
1959 /* Now, for each ARC disk, try to find the matching */
1960 for (NextEntry = ArcDiskInformation->DiskSignatureListHead.Flink;
1961 NextEntry != &ArcDiskInformation->DiskSignatureListHead;
1962 NextEntry = NextEntry->Flink)
1963 {
1964 ArcDiskSignature = CONTAINING_RECORD(NextEntry,
1966 ListEntry);
1967
1968 /*
1969 * If this is the only MBR disk in the ARC list and detected in
1970 * the device tree, just go ahead and retrieve the information.
1971 * Otherwise, verify whether the signatures match before proceeding.
1972 * Note that contrary to IopCreateArcNamesDisk(), we don't verify
1973 * the checksums here.
1974 */
1975 if ((SingleDisk && (DiskCount == 1) &&
1976 (DriveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
1977 IopVerifyDiskSignature(DriveLayout, ArcDiskSignature, &Signature))
1978 {
1979 /* Create ARC name */
1980 sprintf(ArcBuffer, "\\ArcName\\%s", ArcDiskSignature->ArcName);
1981 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
1982
1983 /* Browse all partitions */
1984 for (PartitionNumber = 1; PartitionNumber <= DriveLayout->PartitionCount; PartitionNumber++)
1985 {
1986 /* Create its device name */
1987 sprintf(Buffer, "\\Device\\Harddisk%lu\\Partition%lu", DiskNumber, PartitionNumber);
1988 RtlInitAnsiString(&DeviceStringA, Buffer);
1989 Status = RtlAnsiStringToUnicodeString(&DeviceStringW, &DeviceStringA, TRUE);
1990 if (!NT_SUCCESS(Status))
1991 {
1992 continue;
1993 }
1994
1995 /* If IopVerifyDiskSignature returned no signature, take the one from DriveLayout */
1996 if (!Signature)
1997 {
1998 Signature = DriveLayout->Mbr.Signature;
1999 }
2000
2001 /* Create partial ARC name */
2002 sprintf(ArcBuffer, "%spartition(%lu)", ArcDiskSignature->ArcName, PartitionNumber);
2003 RtlInitAnsiString(&ArcNameStringA, ArcBuffer);
2004
2005 /* If it's matching boot string */
2006 if (RtlEqualString(&ArcNameStringA, &ArcBootString, TRUE))
2007 {
2008 /* Then, fill in information about boot device */
2009 BootDiskInformation->BootDeviceSignature = Signature;
2010
2011 /* Get its device object */
2012 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2014 &FileObject,
2015 &DeviceObject);
2016 if (!NT_SUCCESS(Status))
2017 {
2018 RtlFreeUnicodeString(&DeviceStringW);
2019 continue;
2020 }
2021
2022 /* And call the drive to get information about partition */
2026 NULL,
2027 0,
2028 &PartitionInformation,
2029 sizeof(PartitionInformation),
2030 FALSE,
2031 &Event,
2032 &IoStatusBlock);
2033 if (!Irp)
2034 {
2036 RtlFreeUnicodeString(&DeviceStringW);
2037 continue;
2038 }
2039
2040 /* Call & wait if needed */
2042 if (Status == STATUS_PENDING)
2043 {
2046 }
2047 if (!NT_SUCCESS(Status))
2048 {
2050 RtlFreeUnicodeString(&DeviceStringW);
2051 continue;
2052 }
2053
2054 /* We get partition offset as demanded and return it */
2055 BootDiskInformation->BootPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2056
2057 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2058 if (IsBootDiskInfoEx)
2059 {
2060 /* Is partition style MBR or GPT? */
2061 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2062 {
2063 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceGuid = DriveLayout->Gpt.DiskId;
2064 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = TRUE;
2065 }
2066 else
2067 {
2068 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->BootDeviceIsGpt = FALSE;
2069 }
2070 }
2071
2072 /* Dereference FileObject */
2074 }
2075
2076 /* If it's matching system string */
2077 if (RtlEqualString(&ArcNameStringA, &ArcSystemString, TRUE))
2078 {
2079 /* Then, fill in information about the system device */
2080 BootDiskInformation->SystemDeviceSignature = Signature;
2081
2082 /* Get its device object */
2083 Status = IoGetDeviceObjectPointer(&DeviceStringW,
2085 &FileObject,
2086 &DeviceObject);
2087 if (!NT_SUCCESS(Status))
2088 {
2089 RtlFreeUnicodeString(&DeviceStringW);
2090 continue;
2091 }
2092
2093 /* And call the drive to get information about partition */
2097 NULL,
2098 0,
2099 &PartitionInformation,
2100 sizeof(PartitionInformation),
2101 FALSE,
2102 &Event,
2103 &IoStatusBlock);
2104 if (!Irp)
2105 {
2107 RtlFreeUnicodeString(&DeviceStringW);
2108 continue;
2109 }
2110
2111 /* Call & wait if needed */
2113 if (Status == STATUS_PENDING)
2114 {
2117 }
2118 if (!NT_SUCCESS(Status))
2119 {
2121 RtlFreeUnicodeString(&DeviceStringW);
2122 continue;
2123 }
2124
2125 /* We get partition offset as demanded and return it */
2126 BootDiskInformation->SystemPartitionOffset = PartitionInformation.StartingOffset.QuadPart;
2127
2128 /* If called passed a BOOTDISK_INFORMATION_EX structure, give more intel */
2129 if (IsBootDiskInfoEx)
2130 {
2131 /* Is partition style MBR or GPT? */
2132 if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT)
2133 {
2134 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceGuid = DriveLayout->Gpt.DiskId;
2135 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = TRUE;
2136 }
2137 else
2138 {
2139 ((PBOOTDISK_INFORMATION_EX)BootDiskInformation)->SystemDeviceIsGpt = FALSE;
2140 }
2141 }
2142
2143 /* Dereference FileObject */
2145 }
2146
2147 /* Release device string */
2148 RtlFreeUnicodeString(&DeviceStringW);
2149 }
2150 }
2151 }
2152
2153 /* Finally, release drive layout */
2154 ExFreePool(DriveLayout);
2155 }
2156
2157 /* And return */
2158 return Status;
2159}
#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:88
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define sprintf
Definition: sprintf.c:45
#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 IopVerifyDiskSignature(_In_ PDRIVE_LAYOUT_INFORMATION_EX DriveLayout, _In_ PARC_DISK_SIGNATURE ArcDiskSignature, _Out_ PULONG Signature)
Definition: arcname.c:946
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1446
#define STATUS_TOO_LATE
Definition: ntstatus.h:720
char CHAR
Definition: pedump.c:57
LIST_ENTRY DiskSignatureListHead
Definition: arc.h:356
PCHAR ArcName
Definition: arc.h:345
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PARC_DISK_INFORMATION ArcDiskInformation
Definition: arc.h:847
PSTR ArcBootDeviceName
Definition: arc.h:841
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:4539
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 2166 of file fstubex.c.

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

◆ IoReadPartitionTableEx()

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

Definition at line 2274 of file fstubex.c.

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

2343{
2345 PDISK_INFORMATION Disk;
2346 PARTITION_STYLE PartitionStyle;
2347
2348 PAGED_CODE();
2349
2352
2353 /* Debug given modifications */
2355
2356 /* Allocate internal structure */
2358 if (!NT_SUCCESS(Status))
2359 {
2360 return Status;
2361 }
2362
2363 /* Get partition table style on disk */
2364 Status = FstubDetectPartitionStyle(Disk, &PartitionStyle);
2365 if (!NT_SUCCESS(Status))
2366 {
2368 return Status;
2369 }
2370
2371 /* If it's not matching partition style given in modifications, give up */
2372 if (PartitionInfo->PartitionStyle != PartitionStyle)
2373 {
2376 }
2377
2378 /* Finally, handle modifications using proper function */
2379 switch (PartitionStyle)
2380 {
2383 Disk->SectorSize,
2385 PartitionInfo->Mbr.PartitionType);
2386 break;
2390 &(PartitionInfo->Gpt));
2391 break;
2392 default:
2394 }
2395
2396 /* Release internal structure and return */
2398 return Status;
2399}
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: ntoskrnl.c:50
NTSTATUS NTAPI FstubSetPartitionInformationEFI(IN PDISK_INFORMATION Disk, IN ULONG PartitionNumber, IN SET_PARTITION_INFORMATION_GPT *PartitionInfo)
Definition: fstubex.c:1244
#define FstubDbgPrintSetPartitionEx(PartitionEntry, PartitionNumber)
Definition: fstubex.c:666

Referenced by PartitionHandleDeviceControl().

◆ IoVerifyPartitionTable()

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

Definition at line 2406 of file fstubex.c.

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

◆ IoWritePartitionTableEx()

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

Definition at line 2459 of file fstubex.c.

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

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