disk.c
来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
PartitionDeviceExtension->SenseData = DiskDeviceExtension->SenseData;
PartitionDeviceExtension->LockCount = 0;
PartitionDeviceExtension->DeviceNumber = DiskNumber;
PartitionDeviceExtension->DeviceObject = PartitionDeviceObject;
PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
PartitionDeviceExtension->PortCapabilities = Capabilities;
PartitionDeviceExtension->StartingOffset.QuadPart =
PartitionEntry->StartingOffset.QuadPart;
PartitionDeviceExtension->PartitionLength.QuadPart =
PartitionEntry->PartitionLength.QuadPart;
PartitionDeviceExtension->DMSkew = DiskDeviceExtension->DMSkew;
PartitionDeviceExtension->DMByteSkew = DiskDeviceExtension->DMByteSkew;
PartitionDeviceExtension->DMActive = DiskDeviceExtension->DMActive;
PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
PartitionDeviceExtension->PathId = InquiryData->PathId;
PartitionDeviceExtension->TargetId = InquiryData->TargetId;
PartitionDeviceExtension->Lun = InquiryData->Lun;
PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
PartitionDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
/* Initialize lookaside list for SRBs */
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;
/* Tell mount manager that we have a new partition for him. This should be replaced
* by the registration of MOUNTDEV_MOUNTED_DEVICE_GUID interface on partition PDO.
*/
{
UNICODE_STRING MountManagerU = RTL_CONSTANT_STRING(MOUNTMGR_DEVICE_NAME);
IO_STATUS_BLOCK IoStatusBlock;
ULONG Length = strlen(NameBuffer2) * sizeof(WCHAR);
PMOUNTMGR_TARGET_NAME TargetName;
HANDLE hMountManager;
InitializeObjectAttributes(
&ObjectAttributes,
&MountManagerU,
0,
NULL,
NULL);
Status = NtOpenFile(&hMountManager, FILE_READ_ACCESS, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN);
if (!NT_SUCCESS(Status))
{
DPRINT("NtOpenFile(%wZ) failed with status 0x%08lx\n", &MountManagerU, Status);
}
else
{
TargetName = ExAllocatePool(PagedPool, FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Length + sizeof(UNICODE_NULL));
if (!TargetName)
{
DPRINT("ExAllocatePool() failed\n");
}
else
{
TargetName->DeviceNameLength = Length;
swprintf(
TargetName->DeviceName,
L"\\Device\\Harddisk%lu\\Partition%lu",
DiskNumber,
PartitionNumber + 1);
Status = NtDeviceIoControlFile(
hMountManager,
NULL,
NULL,
NULL,
&IoStatusBlock,
IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
TargetName, FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Length,
NULL, 0);
if (NT_SUCCESS(Status))
Status = NtWaitForSingleObject(hMountManager, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtDeviceIoControlFile() failed with status 0x%08lx\n", Status);
}
ExFreePool(TargetName);
}
NtClose(hMountManager);
}
}
}
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,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?