You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
15 KiB
426 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1991-1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ioctl.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Neil Sandlin (neilsa) 26-Apr-99
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
--*/
|
|
#include "pch.h"
|
|
#include "ntddvol.h"
|
|
#include "ntddft.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,SffDiskDeviceControl)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
SffDiskDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the I/O system to perform a device I/O
|
|
control function.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - a pointer to the object that represents the device
|
|
that I/O is to be done on.
|
|
|
|
Irp - a pointer to the I/O Request Packet for this request.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS or STATUS_PENDING if recognized I/O control code,
|
|
STATUS_INVALID_DEVICE_REQUEST otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION irpSp;
|
|
PSFFDISK_EXTENSION sffdiskExtension;
|
|
PDISK_GEOMETRY outputBuffer;
|
|
NTSTATUS status;
|
|
ULONG outputBufferLength;
|
|
UCHAR i;
|
|
ULONG formatExParametersSize;
|
|
PFORMAT_EX_PARAMETERS formatExParameters;
|
|
|
|
sffdiskExtension = DeviceObject->DeviceExtension;
|
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: IOCTL - %.8x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
//
|
|
// If the device has been removed we will just fail this request outright.
|
|
//
|
|
if ( sffdiskExtension->IsRemoved ) {
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
return STATUS_DELETE_PENDING;
|
|
}
|
|
|
|
//
|
|
// If the device hasn't been started we will let the IOCTL through. This
|
|
// is another hack for ACPI.
|
|
//
|
|
if (!sffdiskExtension->IsStarted) {
|
|
|
|
IoSkipCurrentIrpStackLocation( Irp );
|
|
return IoCallDriver( sffdiskExtension->TargetObject, Irp );
|
|
}
|
|
|
|
switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {
|
|
|
|
PMOUNTDEV_NAME mountName;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n",
|
|
DeviceObject, Irp));
|
|
|
|
ASSERT(sffdiskExtension->DeviceName.Buffer);
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(MOUNTDEV_NAME) ) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
mountName = Irp->AssociatedIrp.SystemBuffer;
|
|
mountName->NameLength = sffdiskExtension->DeviceName.Length;
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(USHORT) + mountName->NameLength) {
|
|
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
|
|
break;
|
|
}
|
|
|
|
RtlCopyMemory( mountName->Name, sffdiskExtension->DeviceName.Buffer,
|
|
mountName->NameLength);
|
|
|
|
mountName->Name[mountName->NameLength / sizeof(USHORT)] = L'0';
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(USHORT) + mountName->NameLength;
|
|
break;
|
|
}
|
|
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: {
|
|
|
|
PMOUNTDEV_UNIQUE_ID uniqueId;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( !sffdiskExtension->InterfaceString.Buffer ||
|
|
irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(MOUNTDEV_UNIQUE_ID)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
uniqueId = Irp->AssociatedIrp.SystemBuffer;
|
|
uniqueId->UniqueIdLength =
|
|
sffdiskExtension->InterfaceString.Length;
|
|
|
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(USHORT) + uniqueId->UniqueIdLength) {
|
|
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
|
|
break;
|
|
}
|
|
|
|
RtlCopyMemory( uniqueId->UniqueId,
|
|
sffdiskExtension->InterfaceString.Buffer,
|
|
uniqueId->UniqueIdLength );
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(USHORT) +
|
|
uniqueId->UniqueIdLength;
|
|
break;
|
|
}
|
|
|
|
|
|
case IOCTL_DISK_CHECK_VERIFY: {
|
|
PULONG pChangeCount = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_CHECK_VERIFY\n",
|
|
DeviceObject, Irp));
|
|
|
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
*pChangeCount = 0;
|
|
Irp->IoStatus.Information = sizeof(ULONG);
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
|
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
|
|
PDISK_GEOMETRY outputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_GET_DRIVE_GEOMETRY\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( DISK_GEOMETRY ) ) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
outputBuffer->MediaType = FixedMedia;
|
|
outputBuffer->Cylinders.QuadPart = sffdiskExtension->Cylinders;
|
|
outputBuffer->TracksPerCylinder = sffdiskExtension->TracksPerCylinder;
|
|
outputBuffer->SectorsPerTrack = sffdiskExtension->SectorsPerTrack;
|
|
outputBuffer->BytesPerSector = sffdiskExtension->BytesPerSector;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: Capacity=%.8x => Cyl=%x\n",
|
|
sffdiskExtension->ByteCapacity, outputBuffer->Cylinders.LowPart));
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_IS_WRITABLE: {
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_IS_WRITABLE\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ((*(sffdiskExtension->FunctionBlock->IsWriteProtected))(sffdiskExtension)) {
|
|
status = STATUS_MEDIA_WRITE_PROTECTED;
|
|
} else {
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_VERIFY: {
|
|
PVERIFY_INFORMATION verifyInformation = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//NOTE: not implemented
|
|
Irp->IoStatus.Information = verifyInformation->Length;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
case IOCTL_DISK_GET_DRIVE_LAYOUT: {
|
|
PDRIVE_LAYOUT_INFORMATION outputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_GET_DRIVE_LAYOUT\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DRIVE_LAYOUT_INFORMATION) ) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
RtlZeroMemory(outputBuffer, sizeof(DRIVE_LAYOUT_INFORMATION));
|
|
|
|
outputBuffer->PartitionCount = 1;
|
|
outputBuffer->PartitionEntry[0].StartingOffset.LowPart = 512;
|
|
outputBuffer->PartitionEntry[0].PartitionLength.QuadPart = sffdiskExtension->ByteCapacity;
|
|
outputBuffer->PartitionEntry[0].RecognizedPartition = TRUE;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = sizeof(DRIVE_LAYOUT_INFORMATION);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_GET_PARTITION_INFO: {
|
|
PPARTITION_INFORMATION outputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_GET_PARTITION_INFO\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) ) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(outputBuffer, sizeof(PARTITION_INFORMATION));
|
|
|
|
outputBuffer->RecognizedPartition = TRUE;
|
|
outputBuffer->StartingOffset.LowPart = 512;
|
|
outputBuffer->PartitionLength.QuadPart = sffdiskExtension->ByteCapacity;
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
|
|
break;
|
|
}
|
|
#endif
|
|
case IOCTL_DISK_GET_PARTITION_INFO_EX: {
|
|
PPARTITION_INFORMATION_EX partitionInfo = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_DISK_GET_PARTITION_INFO_EX\n",
|
|
DeviceObject, Irp));
|
|
|
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION_EX)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(partitionInfo, sizeof(PARTITION_INFORMATION_EX));
|
|
|
|
partitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
|
|
partitionInfo->StartingOffset.QuadPart = sffdiskExtension->RelativeOffset;
|
|
partitionInfo->PartitionLength.QuadPart = sffdiskExtension->ByteCapacity - sffdiskExtension->RelativeOffset;
|
|
// partitionInfo->PartitionNumber
|
|
|
|
switch(sffdiskExtension->SystemId) {
|
|
case PARTITION_FAT_12:
|
|
case PARTITION_FAT_16:
|
|
case PARTITION_HUGE:
|
|
partitionInfo->Mbr.PartitionType = sffdiskExtension->SystemId;
|
|
break;
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_GET_LENGTH_INFO: {
|
|
PGET_LENGTH_INFORMATION lengthInfo = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: IOCTL_DISK_GET_LENGTH_INFO\n"));
|
|
|
|
if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_LENGTH_INFORMATION)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
RtlZeroMemory(lengthInfo, sizeof(GET_LENGTH_INFORMATION));
|
|
|
|
lengthInfo->Length.QuadPart = sffdiskExtension->ByteCapacity - sffdiskExtension->RelativeOffset;
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
|
|
break;
|
|
}
|
|
|
|
|
|
case IOCTL_STORAGE_GET_HOTPLUG_INFO: {
|
|
PSTORAGE_HOTPLUG_INFO info = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL_STORAGE_GET_HOTPLUG_INFO\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_HOTPLUG_INFO)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
info->MediaRemovable = FALSE;
|
|
info->MediaHotplug = FALSE;
|
|
info->DeviceHotplug = TRUE;
|
|
info->WriteCacheEnableOverride = FALSE;
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_STORAGE_GET_DEVICE_NUMBER:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_STORAGE_GET_DEVICE_NUMBER \n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case FT_BALANCED_READ_MODE:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - FT_BALANCED_READ_MODE\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_MOUNTDEV_LINK_CREATED:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_MOUNTDEV_LINK_CREATED\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_MOUNTDEV_LINK_DELETED:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_MOUNTDEV_LINK_DELETED\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_MOUNTDEV_QUERY_STABLE_GUID\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_VOLUME_GET_GPT_ATTRIBUTES\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case IOCTL_VOLUME_ONLINE:
|
|
SffDiskDump(SFFDISKIOCTL, ("SffDisk: unsupported! - IOCTL_VOLUME_ONLINE\n"));
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
|
|
default: {
|
|
|
|
SffDiskDump(SFFDISKIOCTL,
|
|
("SffDisk: IOCTL - UNKNOWN - unsupported device request %.8x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( status != STATUS_PENDING ) {
|
|
|
|
Irp->IoStatus.Status = status;
|
|
if (!NT_SUCCESS( status ) && IoIsErrorUserInduced( status )) {
|
|
IoSetHardErrorOrVerifyDevice( Irp, DeviceObject );
|
|
}
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL comp %.8x\n", DeviceObject, Irp, status));
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
}
|
|
|
|
SffDiskDump( SFFDISKIOCTL, ("SffDisk: DO %.8x Irp %.8x IOCTL <-- %.8x \n", DeviceObject, Irp, status));
|
|
return status;
|
|
}
|