327 lines
8.6 KiB
C
327 lines
8.6 KiB
C
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||
|
||
Module Name:
|
||
|
||
disk.c
|
||
|
||
Abstract:
|
||
|
||
SCSI disk class driver
|
||
|
||
Environment:
|
||
|
||
kernel mode only
|
||
|
||
Notes:
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "disk.h"
|
||
|
||
#define PtCache ClassDebugExternal1
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
|
||
#pragma alloc_text(PAGE, DiskReadPartitionTableEx)
|
||
#pragma alloc_text(PAGE, DiskWritePartitionTableEx)
|
||
#pragma alloc_text(PAGE, DiskSetPartitionInformationEx)
|
||
#endif
|
||
|
||
ULONG DiskBreakOnPtInval = FALSE;
|
||
|
||
//
|
||
// By default, 64-bit systems can see GPT disks and 32-bit systems
|
||
// cannot. This will likely change in the future.
|
||
//
|
||
|
||
#if defined(_WIN64)
|
||
ULONG DiskDisableGpt = FALSE;
|
||
#else
|
||
ULONG DiskDisableGpt = TRUE;
|
||
#endif
|
||
|
||
NTSTATUS
|
||
DiskReadPartitionTableEx(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN BOOLEAN BypassCache,
|
||
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will return the current layout information for the disk.
|
||
If the cached information is still valid then it will be returned,
|
||
otherwise the layout will be retreived from the kernel and cached for
|
||
future use.
|
||
|
||
This routine must be called with the partitioning lock held. The
|
||
partition list which is returned is not guaranteed to remain valid
|
||
once the lock has been released.
|
||
|
||
Arguments:
|
||
|
||
Fdo - a pointer to the FDO for the disk.
|
||
|
||
DriveLayout - a location to store a pointer to the drive layout information.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if successful or an error status indicating what failed.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
NTSTATUS status;
|
||
PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
|
||
|
||
layoutEx = NULL;
|
||
|
||
if(BypassCache) {
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
DebugPrint((PtCache, "DiskRPTEx: cache bypassed and invalidated for "
|
||
"FDO %#p\n", Fdo));
|
||
}
|
||
|
||
//
|
||
// If the cached partition table is present then return a copy of it.
|
||
//
|
||
|
||
if(diskData->CachedPartitionTableValid == TRUE) {
|
||
|
||
ULONG partitionNumber;
|
||
PDRIVE_LAYOUT_INFORMATION_EX layout = diskData->CachedPartitionTable;
|
||
|
||
//
|
||
// Clear the partition numbers from the list entries
|
||
//
|
||
|
||
for(partitionNumber = 0;
|
||
partitionNumber < layout->PartitionCount;
|
||
partitionNumber++) {
|
||
layout->PartitionEntry[partitionNumber].PartitionNumber = 0;
|
||
}
|
||
|
||
*DriveLayout = diskData->CachedPartitionTable;
|
||
|
||
DebugPrint((PtCache, "DiskRPTEx: cached PT returned (%#p) for "
|
||
"FDO %#p\n",
|
||
*DriveLayout, Fdo));
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
ASSERTMSG("DiskReadPartitionTableEx is not using cached partition table",
|
||
(DiskBreakOnPtInval == FALSE));
|
||
|
||
//
|
||
// If there's a cached partition table still around then free it.
|
||
//
|
||
|
||
if(diskData->CachedPartitionTable) {
|
||
DebugPrint((PtCache, "DiskRPTEx: cached PT (%#p) freed for FDO %#p\n",
|
||
diskData->CachedPartitionTable, Fdo));
|
||
|
||
ExFreePool(diskData->CachedPartitionTable);
|
||
diskData->CachedPartitionTable = NULL;
|
||
}
|
||
|
||
//
|
||
// By default, X86 disables recognition of GPT disks. Instead we
|
||
// return the protective MBR partition. Use IoReadPartitionTable
|
||
// to get this.
|
||
//
|
||
|
||
status = IoReadPartitionTableEx(Fdo->DeviceObject, &layoutEx);
|
||
|
||
if (DiskDisableGpt) {
|
||
PDRIVE_LAYOUT_INFORMATION layout;
|
||
|
||
if (NT_SUCCESS (status) &&
|
||
layoutEx->PartitionStyle == PARTITION_STYLE_GPT) {
|
||
|
||
//
|
||
// ISSUE - 2000/29/08 - math: Remove from final product.
|
||
// Leave this debug print in for a while until everybody
|
||
// has had a chance to convert their GPT disks to MBR.
|
||
//
|
||
|
||
DbgPrint ("DISK: Disk %p recognized as a GPT disk on a system without GPT support.\n"
|
||
" Disk will appear as RAW.\n",
|
||
Fdo->DeviceObject);
|
||
|
||
ExFreePool (layoutEx);
|
||
status = IoReadPartitionTable(Fdo->DeviceObject,
|
||
Fdo->DiskGeometry.BytesPerSector,
|
||
FALSE,
|
||
&layout);
|
||
if (NT_SUCCESS (status)) {
|
||
layoutEx = DiskConvertLayoutToExtended(layout);
|
||
ExFreePool (layout);
|
||
}
|
||
}
|
||
}
|
||
|
||
diskData->CachedPartitionTable = layoutEx;
|
||
|
||
//
|
||
// If the routine fails make sure we don't have a stale partition table
|
||
// pointer. Otherwise indicate that the table is now valid.
|
||
//
|
||
|
||
if(!NT_SUCCESS(status)) {
|
||
diskData->CachedPartitionTable = NULL;
|
||
} else {
|
||
diskData->CachedPartitionTableValid = TRUE;
|
||
}
|
||
|
||
*DriveLayout = diskData->CachedPartitionTable;
|
||
|
||
DebugPrint((PtCache, "DiskRPTEx: returning PT %#p for FDO %#p with status "
|
||
"%#08lx. PT is %scached\n",
|
||
*DriveLayout,
|
||
Fdo,
|
||
status,
|
||
(diskData->CachedPartitionTableValid ? "" : "not ")));
|
||
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DiskWritePartitionTableEx(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will invalidate the cached partition table. It will then
|
||
write the new drive layout to disk.
|
||
|
||
Arguments:
|
||
|
||
Fdo - the FDO for the disk getting the new partition table.
|
||
|
||
DriveLayout - the new drive layout.
|
||
|
||
Return Value:
|
||
|
||
status
|
||
|
||
--*/
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
|
||
//
|
||
// Invalidate the cached partition table. Do not free it as it may be
|
||
// the very drive layout that was passed in to us.
|
||
//
|
||
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
|
||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||
Fdo));
|
||
|
||
if (DiskDisableGpt) {
|
||
if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) {
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
}
|
||
|
||
return IoWritePartitionTableEx(Fdo->DeviceObject, DriveLayout);
|
||
}
|
||
|
||
NTSTATUS
|
||
DiskSetPartitionInformationEx(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN ULONG PartitionNumber,
|
||
IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
|
||
)
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
DebugPrint((PtCache, "DiskSPIEx: Invalidating PT cache for FDO %#p\n",
|
||
Fdo));
|
||
|
||
if (DiskDisableGpt) {
|
||
if (PartitionInfo->PartitionStyle == PARTITION_STYLE_GPT) {
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
}
|
||
|
||
return IoSetPartitionInformationEx(Fdo->DeviceObject,
|
||
PartitionNumber,
|
||
PartitionInfo);
|
||
}
|
||
|
||
NTSTATUS
|
||
DiskSetPartitionInformation(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN ULONG SectorSize,
|
||
IN ULONG PartitionNumber,
|
||
IN ULONG PartitionType
|
||
)
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
DebugPrint((PtCache, "DiskSPI: Invalidating PT cache for FDO %#p\n",
|
||
Fdo));
|
||
|
||
return IoSetPartitionInformation(Fdo->DeviceObject,
|
||
SectorSize,
|
||
PartitionNumber,
|
||
PartitionType);
|
||
}
|
||
|
||
BOOLEAN
|
||
DiskInvalidatePartitionTable(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN BOOLEAN PartitionLockHeld
|
||
)
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
BOOLEAN wasValid;
|
||
|
||
wasValid = (BOOLEAN) (diskData->CachedPartitionTableValid ? TRUE : FALSE);
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
|
||
DebugPrint((PtCache, "DiskIPT: Invalidating PT cache for FDO %#p\n",
|
||
Fdo));
|
||
|
||
if((PartitionLockHeld) && (diskData->CachedPartitionTable != NULL)) {
|
||
DebugPrint((PtCache, "DiskIPT: Freeing PT cache (%#p) for FDO %#p\n",
|
||
diskData->CachedPartitionTable, Fdo));
|
||
ExFreePool(diskData->CachedPartitionTable);
|
||
diskData->CachedPartitionTable = NULL;
|
||
}
|
||
|
||
return wasValid;
|
||
}
|
||
|
||
NTSTATUS
|
||
DiskVerifyPartitionTable(
|
||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||
IN BOOLEAN FixErrors
|
||
)
|
||
{
|
||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||
|
||
if(FixErrors) {
|
||
diskData->CachedPartitionTableValid = FALSE;
|
||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||
Fdo));
|
||
}
|
||
|
||
return IoVerifyPartitionTable(Fdo->DeviceObject, FixErrors);
|
||
}
|