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.
381 lines
13 KiB
381 lines
13 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"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,MemCardDeviceControl)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
MemCardDeviceControl(
|
|
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;
|
|
PMEMCARD_EXTENSION memcardExtension;
|
|
PDISK_GEOMETRY outputBuffer;
|
|
NTSTATUS status;
|
|
ULONG outputBufferLength;
|
|
UCHAR i;
|
|
ULONG formatExParametersSize;
|
|
PFORMAT_EX_PARAMETERS formatExParameters;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: IOCTL entered\n") );
|
|
|
|
memcardExtension = DeviceObject->DeviceExtension;
|
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
//
|
|
// If the device has been removed we will just fail this request outright.
|
|
//
|
|
if ( memcardExtension->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 (!memcardExtension->IsStarted) {
|
|
|
|
IoSkipCurrentIrpStackLocation( Irp );
|
|
return IoCallDriver( memcardExtension->TargetObject, Irp );
|
|
}
|
|
|
|
switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {
|
|
|
|
PMOUNTDEV_NAME mountName;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n",
|
|
DeviceObject, Irp));
|
|
|
|
ASSERT(memcardExtension->DeviceName.Buffer);
|
|
|
|
if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(MOUNTDEV_NAME) ) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
mountName = Irp->AssociatedIrp.SystemBuffer;
|
|
mountName->NameLength = memcardExtension->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, memcardExtension->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;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ( !memcardExtension->InterfaceString.Buffer ||
|
|
irpSp->Parameters.DeviceIoControl.OutputBufferLength <
|
|
sizeof(MOUNTDEV_UNIQUE_ID)) {
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
uniqueId = Irp->AssociatedIrp.SystemBuffer;
|
|
uniqueId->UniqueIdLength =
|
|
memcardExtension->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,
|
|
memcardExtension->InterfaceString.Buffer,
|
|
uniqueId->UniqueIdLength );
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(USHORT) +
|
|
uniqueId->UniqueIdLength;
|
|
break;
|
|
}
|
|
|
|
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {
|
|
|
|
MemCardDump(MEMCARDIOCTL,("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n",
|
|
DeviceObject, Irp));
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_GET_MEDIA_TYPES: {
|
|
ULONG ByteCapacity;
|
|
|
|
MemCardDump(MEMCARDIOCTL,("MemCard: DO %.8x Irp %.8x IOCTL_DISK_GET_MEDIA_TYPES\n",
|
|
DeviceObject, Irp));
|
|
|
|
outputBufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
//
|
|
// Make sure that the input buffer has enough room to return
|
|
// at least one descriptions of a supported media type.
|
|
//
|
|
if (outputBufferLength < (sizeof(DISK_GEOMETRY))) {
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Assume success, although we might modify it to a buffer
|
|
// overflow warning below (if the buffer isn't big enough
|
|
// to hold ALL of the media descriptions).
|
|
//
|
|
status = STATUS_SUCCESS;
|
|
|
|
i = 0;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
//
|
|
// Fill in capacities from 512K to 8M
|
|
//
|
|
for (ByteCapacity = 0x80000; ByteCapacity <= 0x800000; ByteCapacity*=2) {
|
|
if (outputBufferLength < (sizeof(DISK_GEOMETRY) + Irp->IoStatus.Information)) {
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
break;
|
|
}
|
|
|
|
outputBuffer->MediaType = FixedMedia;
|
|
outputBuffer->Cylinders.LowPart = ByteCapacity / (8 * 2 * 512);
|
|
outputBuffer->Cylinders.HighPart = 0;
|
|
outputBuffer->TracksPerCylinder = 2;
|
|
outputBuffer->SectorsPerTrack = 8;
|
|
outputBuffer->BytesPerSector = 512;
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: Cyls=%x\n", outputBuffer->Cylinders.LowPart));
|
|
|
|
outputBuffer++;
|
|
Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_CHECK_VERIFY:
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_CHECK_VERIFY\n",
|
|
DeviceObject, Irp));
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
|
|
PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: 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;
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
if (!memcardExtension->ByteCapacity) {
|
|
//
|
|
// Just zero out everything. The
|
|
// caller shouldn't look at it.
|
|
//
|
|
outputBuffer->MediaType = Unknown;
|
|
outputBuffer->Cylinders.LowPart = 0;
|
|
outputBuffer->Cylinders.HighPart = 0;
|
|
outputBuffer->TracksPerCylinder = 0;
|
|
outputBuffer->SectorsPerTrack = 0;
|
|
outputBuffer->BytesPerSector = 0;
|
|
|
|
} else {
|
|
//
|
|
// Return the geometry of the current
|
|
// media.
|
|
//
|
|
outputBuffer->MediaType = FixedMedia;
|
|
outputBuffer->Cylinders.HighPart = 0;
|
|
outputBuffer->Cylinders.LowPart = memcardExtension->ByteCapacity / (8 * 2 * 512);
|
|
outputBuffer->TracksPerCylinder = 2;
|
|
outputBuffer->SectorsPerTrack = 8;
|
|
outputBuffer->BytesPerSector = 512;
|
|
}
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: Capacity=%.8x => Cyl=%x\n",
|
|
memcardExtension->ByteCapacity, outputBuffer->Cylinders.LowPart));
|
|
Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
|
|
break;
|
|
}
|
|
|
|
case IOCTL_DISK_IS_WRITABLE: {
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_IS_WRITABLE\n",
|
|
DeviceObject, Irp));
|
|
|
|
if ((memcardExtension->PcmciaInterface.IsWriteProtected)(memcardExtension->UnderlyingPDO)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
} 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;
|
|
}
|
|
|
|
case IOCTL_DISK_GET_DRIVE_LAYOUT: {
|
|
PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: 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.LowPart = memcardExtension->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 = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: 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.LowPart = memcardExtension->ByteCapacity;
|
|
|
|
status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION );
|
|
break;
|
|
}
|
|
|
|
|
|
case IOCTL_DISK_SET_DRIVE_LAYOUT:
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_SET_DRIVE_LAYOUT\n",
|
|
DeviceObject, Irp));
|
|
case IOCTL_MOUNTMGR_CHANGE_NOTIFY:
|
|
case IOCTL_MOUNTDEV_LINK_CREATED:
|
|
case IOCTL_MOUNTDEV_LINK_DELETED:
|
|
default: {
|
|
|
|
MemCardDump(MEMCARDIOCTL,
|
|
("MemCard: IOCTL - unsupported device request %.8x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
//IoSkipCurrentIrpStackLocation( Irp );
|
|
//status = IoCallDriver( memcardExtension->TargetObject, Irp );
|
|
//return status;
|
|
}
|
|
}
|
|
|
|
if ( status != STATUS_PENDING ) {
|
|
|
|
Irp->IoStatus.Status = status;
|
|
if (!NT_SUCCESS( status ) && IoIsErrorUserInduced( status )) {
|
|
IoSetHardErrorOrVerifyDevice( Irp, DeviceObject );
|
|
}
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL comp %.8x\n", DeviceObject, Irp, status));
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
}
|
|
|
|
MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL <-- %.8x \n", DeviceObject, Irp, status));
|
|
return status;
|
|
}
|