{
KEVENT Event;
IO_STATUS_BLOCKIoStatusBlock;
PIRPIrp;
NTSTATUSStatus = STATUS_SUCCESS;
ULONGBufferSize;
PUSHORTBuffer;
PPTE Entry;
PPARTITION_TABLE PartitionTable;
LARGE_INTEGEROffset, NextOffset, ExtendedOffset, SectorOffset;
LARGE_INTEGER StartOffset, PartitionLength;
ULONG i, j;
CCHARk;
BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
ULONG ConventionalCylinders;
LONGLONG DiskSize;
PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer;
PVOID MbrBuffer;
UCHARPartitionType;
PIO_STACK_LOCATION IoStackLocation;
PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry;
PPARTITION_INFORMATION TableEntry;
ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
PAGED_CODE();
/* Normalize the buffer size */
BufferSize = max(512, SectorSize);
/* Get the partial drive geometry */xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
/* Check for EZ Drive */HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
if (MbrBuffer)
{
/* EZ Drive found, bias the offset */
IsEzDrive = TRUE;
ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
Offset.QuadPart = 512;
}
/* Get the number of bits to shift to multiply by the sector size */for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
/* Check if there's only one partition */if (PartitionBuffer->PartitionCount == 1)
{
/* Check if it has no starting offset or hidden sectors */if (!(PartitionInfo->StartingOffset.QuadPart) &&
!(PartitionInfo->HiddenSectors))
{
/* Then it's a super floppy */
IsSuperFloppy = TRUE;
/* Which also means it must be non-bootable FAT-16 */if ((PartitionInfo->PartitionNumber) ||
(PartitionInfo->PartitionType != PARTITION_FAT_16) ||
(PartitionInfo->BootIndicator))
{
/* It's not, so we fail */returnSTATUS_INVALID_PARAMETER;
}
/* Check if it needs a rewrite, and disable EZ drive for sure */if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
IsEzDrive = FALSE;
}
}
/* Count the number of partition tables */
DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4;
/* Allocate our partition buffer */
Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM);
if (!Buffer) returnSTATUS_INSUFFICIENT_RESOURCES;
/* Loop the entries */
Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET];
for (i = 0; i < DiskLayout->TableCount; i++)
{
/* Set if this is the MBR partition */
IsMbr= (BOOLEAN)!i;
/* Initialize th event */KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Build the read IRP */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Buffer,
BufferSize,
&Offset,
&Event,
&IoStatusBlock);
if (!Irp)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Make sure to disable volume verification */
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
/* Call the driver */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for completion */KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatusBlock.Status;
}
/* Check for failure */if (!NT_SUCCESS(Status)) break;
/* If we biased for EZ-Drive, unbias now */if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
/* Check if this is a normal disk */if (!IsSuperFloppy)
{
/* Set the boot record signature */
Buffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE;
/* By default, don't require a rewrite */
DoRewrite = FALSE;
/* Check if we don't have an offset */if (!Offset.QuadPart)
{
/* Check if the signature doesn't match */if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] !=
PartitionBuffer->Signature)
{
/* Then write the signature and now w need a rewrite */
((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] =
PartitionBuffer->Signature;
DoRewrite = TRUE;
}
}
/* Loop the partition table entries */
PartitionTable = &DiskLayout->PartitionTable[i];
for (j = 0; j < 4; j++)
{
/* Get the current entry and type */
TableEntry = &PartitionTable->PartitionEntry[j];
PartitionType = TableEntry->PartitionType;
/* Check if the entry needs a rewrite */if (TableEntry->RewritePartition)
{
/* Then we need one too */
DoRewrite = TRUE;
/* Save the type and if it's a bootable partition */
Entry[j].PartitionType = TableEntry->PartitionType;
Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
/* Make sure it's used */if (PartitionType != PARTITION_ENTRY_UNUSED)
{
/* Make sure it's not a container (unless primary) */if ((IsMbr) || !(IsContainerPartition(PartitionType)))
{
/* Use the partition offset */
StartOffset.QuadPart = Offset.QuadPart;
}
else
{
/* Use the extended logical partition offset */
StartOffset.QuadPart = ExtendedOffset.QuadPart;
}
/* Set the sector offset */
SectorOffset.QuadPart = TableEntry->
StartingOffset.QuadPart -
StartOffset.QuadPart;
/* Now calculate the starting sector */
StartOffset.QuadPart = SectorOffset.QuadPart >> k;
Entry[j].StartingSector = StartOffset.LowPart;
/* As well as the length */
PartitionLength.QuadPart = TableEntry->PartitionLength.
QuadPart >> k;
Entry[j].PartitionLength = PartitionLength.LowPart;
/* Calculate the CHS values */HalpCalculateChsValues(&TableEntry->StartingOffset,
&TableEntry->PartitionLength,
k,
SectorsPerTrack,
NumberOfHeads,
ConventionalCylinders,
(PPARTITION_DESCRIPTOR)
&Entry[j]);
}
else
{
/* Otherwise set up an empty entry */
Entry[j].StartingSector = 0;
Entry[j].PartitionLength = 0;
Entry[j].StartingTrack = 0;
Entry[j].EndingTrack = 0;
Entry[j].StartingCylinder = 0;
Entry[j].EndingCylinder = 0;
}
}
/* Check if this is a container partition */if (IsContainerPartition(PartitionType))
{
/* Then update the offset to use */
NextOffset = TableEntry->StartingOffset;
}
}
}
/* Check if we need to write back the buffer */if (DoRewrite)
{
/* We don't need to do this again */
DoRewrite = FALSE;
/* Initialize the event */KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* If we unbiased for EZ-Drive, rebias now */if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512;
/* Build the write IRP */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
DeviceObject,
Buffer,
BufferSize,
&Offset,
&Event,
&IoStatusBlock);
if (!Irp)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Make sure to disable volume verification */
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
/* Call the driver */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
/* Wait for completion */KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
/* Check for failure */if (!NT_SUCCESS(Status)) break;
/* If we biased for EZ-Drive, unbias now */if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
}
/* Update the partition offset and set the extended offset if needed */
Offset = NextOffset;
if (IsMbr) ExtendedOffset = NextOffset;
}
/* If we had a buffer, free it, then return status */if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
returnStatus;
}
Generated on Mon May 28 2012 06:07:13 for ReactOS by
1.7.6.1
ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.