/*
* cfadisk.c - CompactFlash fixed disk filter driver
*
* Copyright (c) Hitachi Global Storage Technologies 2003. All rights reserved.
*
* This driver filters IOCTL_STORAGE_QUERY_PROPERTY so that Windows XP can
* correctly handle CompactFlash device as a fixed disk.
*
* ----------------------------------------------------------------------------------
*
* THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
* A PARTICULAR PURPOSE.
*
*/
#include "ntddk.h"
#include "ntddscsi.h"
#include "ntdddisk.h"
#include "scsi.h"
#include "stdio.h"
//
// function declarations
//
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT TargetDeviceObject;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
VOID CfaUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS CfaAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
);
NTSTATUS CfaDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS CfaDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS CfaDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS CfaShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS CfaSendToNextDriver(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
// -----------------
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
ULONG n;
KdPrint(("CfaDisk@DriverEntry - DriverObject = %p\n", DriverObject));
for(n = 0; n <= IRP_MJ_MAXIMUM_FUNCTION; n++){
DriverObject->MajorFunction[n] = CfaSendToNextDriver;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CfaDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = CfaShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = CfaShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_PNP] = CfaDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = CfaDispatchPower;
DriverObject->DriverExtension->AddDevice = CfaAddDevice;
DriverObject->DriverUnload = CfaUnload;
return(STATUS_SUCCESS);
}
//
// This routine sends the Irp to the lower driver in the driver stack
//
NTSTATUS CfaSendToNextDriver(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(deviceExtension->TargetDeviceObject, Irp));
}
//
// This routine is called when the device is unloaded.
//
VOID CfaUnload(
IN PDRIVER_OBJECT DriverObject
)
{
KdPrint(("CfaUnload\n"));
ASSERT(DriverObject->DeviceObject);
return;
}
#define CHECKBOUND ((size_t)&((*(PSTORAGE_DEVICE_DESCRIPTOR)0).RemovableMedia) + \
sizeof((*(PSTORAGE_DEVICE_DESCRIPTOR)0).RemovableMedia))
//
// This routine is called when IOCTL_STORAGE_QUERY_PROPERTY has completed.
//
NTSTATUS CfaQueryPropertyCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Context);
if(Irp->PendingReturned){
IoMarkIrpPending(Irp);
}
if(NT_SUCCESS(Irp->IoStatus.Status)){
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG bufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
if(bufferLength >= CHECKBOUND){
PSTORAGE_DEVICE_DESCRIPTOR devdesc = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
BOOLEAN rmv = devdesc->RemovableMedia;
DbgPrint("CfaQueryPropertyCompletion: IOCTL_STORAGE_QUERY_PROPERTY completed\n");
KdPrint((" Buffer size = %d\n", bufferLength));
KdPrint((" Bound = %d\n", CHECKBOUND));
DbgPrint(" RemovableMedia = %d", rmv);
if(rmv){
devdesc->RemovableMedia = 0;
DbgPrint(" -> %d", devdesc->RemovableMedia);
}
DbgPrint("\n");
}
}
return(Irp->IoStatus.Status);
}
//
// This routine is called by the I/O subsystem for device controls.
//
NTSTATUS CfaDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status;
ULONG controlCode;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
KdPrint(("CfaDeviceControl: control code = %08X\n", controlCode));
if(IOCTL_STORAGE_QUERY_PROPERTY == controlCode){
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PSTORAGE_PROPERTY_QUERY prop = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
BOOLEAN hookup = FALSE;
__try {
// check if query is for STOREAGE_DEVICE_DESCRIPTOR
if((StorageDeviceProperty == prop->PropertyId) && (PropertyStandardQuery == prop->QueryType)){
hookup = TRUE;
}
} __except(EXCEPTION_EXECUTE_HANDLER) { ; }
if(hookup){
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, CfaQueryPropertyCompletion, (PVOID)0, TRUE, TRUE, TRUE);
return(IoCallDriver(deviceExtension->TargetDeviceObject, Irp));
}
}
return(CfaSendToNextDriver(DeviceObject, Irp));
}
//
// This routine creates and initializes a new function device object
// for the given physical device object.
//
NTSTATUS CfaAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
NTSTATUS status;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
KdPrint(("CfaAddDevice: PDO = %p\n", PhysicalDeviceObject));
//
// create a filter device object
//
status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_DISK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&filterDeviceObject);
if(!NT_SUCCESS(status)){
KdPrint(("CfaAddDevice: IoCreateDevice returned error %08lX\n", status));
return(status);
}
//
// initialize filter device object
//
KdPrint(("CfaAddDevice: filterDeviceObject->Flags = %08lX\n", filterDeviceObject->Flags));
deviceExtension = filterDeviceObject->DeviceExtension;
RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);
KdPrint(("TargetDevice->Characteristics = %08X\n",
deviceExtension->TargetDeviceObject->Characteristics));
KdPrint(("TargetDevice->Flags = %08X\n",
deviceExtension->TargetDeviceObject->Flags));
if(!deviceExtension->TargetDeviceObject){
KdPrint(("CfaAddDevice: IoAttachDeviceToDeviceStack failed\n"));
IoDeleteDevice(filterDeviceObject);
return(STATUS_NO_SUCH_DEVICE);
}
deviceExtension->DeviceObject = filterDeviceObject;
filterDeviceObject->Flags |= DO_DIRECT_IO;
// finish initializing
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return(STATUS_SUCCESS);
}
//
// This routine is called when IRP_MN_QUERY_CAPABILITIES has completed.
//
NTSTATUS CfaQueryCapabilitiesCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Context);
if(Irp->PendingReturned){
IoMarkIrpPending(Irp);
}
if(NT_SUCCESS(Irp->IoStatus.Status)){
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_CAPABILITIES devcaps = irpStack->Parameters.DeviceCapabilities.Capabilities;
KdPrint(("IRP_MN_QUERY_CAPABILITIES co
评论0