disk.c
来自「一个类似windows」· C语言 代码 · 共 2,090 行 · 第 1/5 页
C
2,090 行
ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
8);
/* Link current partition device extension to previous disk data */
DiskData->NextPartition = PartitionDeviceExtension;
/* Initialize current disk data */
DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
DiskData->NextPartition = NULL;
DiskData->PartitionType = PartitionEntry->PartitionType;
DiskData->PartitionNumber = PartitionNumber + 1;
DiskData->PartitionOrdinal = PartitionNumber + 1;
DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
DiskData->BootIndicator = PartitionEntry->BootIndicator;
DiskData->DriveNotReady = FALSE;
}
else
{
DPRINT("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
break;
}
}
}
if (PartitionList != NULL)
ExFreePool(PartitionList);
DPRINT("DiskClassCreateDeviceObjects() done\n");
return(STATUS_SUCCESS);
}
static NTSTATUS
DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
IN PIRP Irp)
{
PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
PDEVICE_EXTENSION DiskDeviceExtension, DDE;
PDISK_DATA DiskData, DD;
PPARTITION_INFORMATION PartitionEntry;
ULONG PartitionNumber;
NTSTATUS Status;
DPRINT("DiskBuildPartitionTable() start\n");
DiskDeviceExtension = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;
DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
DDE = (PDEVICE_EXTENSION) DiskDeviceExtension->PhysicalDevice->DeviceExtension;
DD = (PDISK_DATA)(DDE +1);
/* Clear flag for Partition0, just incase it was set. */
DD->DriveNotReady = FALSE;
Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
if (!NT_SUCCESS(Status))
{
/* Drive is not ready. */
DPRINT("Drive not ready\n");
DiskData->DriveNotReady = TRUE;
return Status;
}
/* Read partition table */
Status = IoReadPartitionTable(DiskDeviceExtension->PhysicalDevice,
DiskDeviceExtension->DiskGeometry->BytesPerSector,
TRUE,
&PartitionList);
DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
if (!NT_SUCCESS(Status))
{
/* Drive is not ready. */
DPRINT("Drive not ready\n");
DiskData->DriveNotReady = TRUE;
if (PartitionList != NULL)
ExFreePool(PartitionList);
return Status;
}
if (NT_SUCCESS(Status))
{
DPRINT("Read partition table!\n");
DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
/* Set disk signature */
DiskData->Signature = PartitionList->Signature;
DiskData->NextPartition = NULL;
if (PartitionList->PartitionCount)
{
for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
{
PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
DiskData->PartitionType = PartitionEntry->PartitionType;
DiskData->PartitionNumber = PartitionNumber + 1;
DiskData->PartitionOrdinal = PartitionNumber + 1;
DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
DiskData->BootIndicator = PartitionEntry->BootIndicator;
DiskData->DriveNotReady = FALSE;
DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
PartitionNumber,
DiskData->PartitionNumber,
DiskData->BootIndicator,
DiskData->PartitionType,
DiskDeviceExtension->StartingOffset.QuadPart /
DiskDeviceExtension->DiskGeometry->BytesPerSector,
DiskDeviceExtension->PartitionLength.QuadPart /
DiskDeviceExtension->DiskGeometry->BytesPerSector);
}
}
else
{
DiskData->PartitionType = 0;
DiskData->PartitionNumber = 1;
DiskData->PartitionOrdinal = 0;
DiskData->HiddenSectors = 0;
DiskData->BootIndicator = 0;
DiskData->DriveNotReady = FALSE;
DiskDeviceExtension->StartingOffset.QuadPart = 0;
DiskDeviceExtension->PartitionLength.QuadPart += DiskDeviceExtension->StartingOffset.QuadPart;
}
}
DPRINT("DiskBuildPartitionTable() done\n");
if (PartitionList != NULL)
ExFreePool(PartitionList);
return(STATUS_SUCCESS);
}
/**********************************************************************
* NAME EXPORTED
* DiskClassDeviceControl
*
* DESCRIPTION
* Answer requests for device control calls
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* Standard dispatch arguments
*
* RETURNS
* Status
*/
NTSTATUS STDCALL
DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
ULONG ControlCode, InputLength, OutputLength;
PDISK_DATA DiskData;
ULONG Information;
NTSTATUS Status;
KEVENT Event;
IO_STATUS_BLOCK IoSB;
PIRP LocalIrp;
PSRB_IO_CONTROL SrbIoControl;
PSENDCMDINPARAMS InParams;
DPRINT("DiskClassDeviceControl() called!\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
Information = 0;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
DiskData = (PDISK_DATA)(DeviceExtension + 1);
switch (ControlCode)
{
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
if (DeviceExtension->DiskGeometry == NULL)
{
DPRINT("No disk geometry available!\n");
DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
sizeof(DISK_GEOMETRY));
}
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
Status = ScsiClassReadDriveCapacity(DeviceObject);
DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
if (!NT_SUCCESS(Status))
{
/* Drive is not ready */
DiskData->DriveNotReady = TRUE;
break;
}
/* Drive is ready */
DiskData->DriveNotReady = FALSE;
}
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
DeviceExtension->DiskGeometry,
sizeof(DISK_GEOMETRY));
Status = STATUS_SUCCESS;
Information = sizeof(DISK_GEOMETRY);
break;
case IOCTL_DISK_GET_PARTITION_INFO:
DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
{
/* Update a partition list for a single entry. */
Status = DiskBuildPartitionTable(DeviceObject,Irp);
}
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARTITION_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else if (DiskData->PartitionNumber == 0)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
}
else
{
PPARTITION_INFORMATION PartitionInfo;
PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
PartitionInfo->PartitionType = DiskData->PartitionType;
PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
PartitionInfo->BootIndicator = DiskData->BootIndicator;
PartitionInfo->RewritePartition = FALSE;
PartitionInfo->RecognizedPartition =
IsRecognizedPartition(DiskData->PartitionType);
Status = STATUS_SUCCESS;
Information = sizeof(PARTITION_INFORMATION);
}
break;
case IOCTL_DISK_SET_PARTITION_INFO:
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SET_PARTITION_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else if (DiskData->PartitionNumber == 0)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
}
else
{
PSET_PARTITION_INFORMATION PartitionInfo;
PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
DeviceExtension->DiskGeometry->BytesPerSector,
DiskData->PartitionOrdinal,
PartitionInfo->PartitionType);
if (NT_SUCCESS(Status))
{
DiskData->PartitionType = PartitionInfo->PartitionType;
}
}
break;
case IOCTL_DISK_GET_DRIVE_LAYOUT:
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DRIVE_LAYOUT_INFORMATION))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
PDRIVE_LAYOUT_INFORMATION PartitionList;
Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
DeviceExtension->DiskGeometry->BytesPerSector,
FALSE,
&PartitionList);
if (NT_SUCCESS(Status))
{
ULONG BufferSize;
BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
PartitionEntry[0]);
BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
PartitionList,
BufferSize);
Status = STATUS_SUCCESS;
Information = BufferSize;
}
ExFreePool(PartitionList);
}
}
break;
case IOCTL_DISK_SET_DRIVE_LAYOUT:
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(DRIVE_LAYOUT_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
PDRIVE_LAYOUT_INFORMATION PartitionList;
ULONG TableSize;
PartitionList = Irp->AssociatedIrp.SystemBuffer;
TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
/* Update partition device objects */
DiskClassUpdatePartitionDeviceObjects (DeviceObject,
Irp);
/* Write partition table */
Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
DeviceExtension->DiskGeometry->BytesPerSector,
DeviceExtension->DiskGeometry->SectorsPerTrack,
DeviceExtension->DiskGeometry->TracksPerCylinder,
PartitionList);
}
}
break;
case IOCTL_DISK_IS_WRITABLE:
{
PMODE_PARAMETER_HEADER ModeData;
ULONG Length;
ModeData = ExAllocatePool (NonPagedPool,
MODE_DATA_SIZE);
if (ModeData == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory (ModeData,
MODE_DATA_SIZE);
Length = ScsiClassModeSense (DeviceObject,
(PVOID)ModeData,
MODE_DATA_SIZE,
MODE_SENSE_RETURN_ALL);
if (Length < sizeof(MODE_PARAMETER_HEADER))
{
/* FIXME: Retry */
Status = STATUS_IO_DEVICE_ERROR;
ExFreePool (ModeData);
break;
}
if (ModeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT)
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
}
else
{
Status = STATUS_SUCCESS;
}
ExFreePool (ModeData);
}
break;
case IOCTL_DISK_VERIFY:
case IOCTL_DISK_FORMAT_TRACKS:
case IOCTL_DISK_PERFORMANCE:
case IOCTL_DISK_LOGGING:
case IOCTL_DISK_FORMAT_TRACKS_EX:
case IOCTL_DISK_HISTOGRAM_STRUCTURE:
case IOCTL_DISK_HISTOGRAM_DATA:
case IOCTL_DISK_HISTOGRAM_RESET:
case IOCTL_DISK_REQUEST_STRUCTURE:
case IOCTL_DISK_REQUEST_DATA:
/* If we get here, something went wrong. Inform the requestor */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?