前段时间发现有网友在开发驱动的过程中遇到问题,所以今天我整理了一下我在写驱动中的一点心得。希望大家指导!
win2k的UsbStorage不需要驱动程序就能运行,但是如果我们的设备有特殊功能,像前几天有网友问的那种要显示自已的标号的。那么UsbStor.sys就不能满足我们的需求。当然如果要实现自己的功能,我们也只需要UsbStor.sys的基础上修改就行了!
USB磁盘驱动程序是一个BUS DRIVER,它的主要入口如下:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING pRegistryPath
)
{
#if DBG
DbgPrint("Enter UsbStore DriverEntry!/n");
#endif
DriverObject->DriverExtension->AddDevice = UsbStore_AddDevice;
DriverObject->DriverUnload = UsbStore_Unload;
DriverObject->DriverStartIo = UsbStore_StartIo;
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbStore_CreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] =
DriverObject->MajorFunction[IRP_MJ_WRITE] = UsbStore_ReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbStore_DeviceIoControl;
DriverObject->MajorFunction[IRP_MJ_SCSI] = UsbStore_Scsi;
DriverObject->MajorFunction[IRP_MJ_PNP] = UsbStore_Pnp;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = UsbStore_SystemControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = UsbStore_Power;
return STATUS_SUCCESS;
}
USB STORAGE DRIVER对设备的主要操作MajorFunction是IRP_MJ_SCSI,而不是IRP_MJ_READ 以及IRP_MJ_WRITE 。
USB STORAGE DRIVER的上层程序是CLASS DRIVER。CLASS DRIVER对上层的USB磁盘的读写等操作转换成IRP_MJ_SCSI,USB STORAGE DRIVER根据USB CBI规范和BULK ONLY规范将上层DRIVER传送来的IRP_MJ_SCSI的SRB(SCSI_REQUEST_BLOCK)的相关部分传递给设备。
UsbStore_AddDevice的功能是建立USB STORAGE DRIVER的FDO。
NTSTATUS
UsbStore_AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
NTSTATUS status;
PUSB_DEVICE_EXTENSION pUsb_DeviceExtension;
PDEVICE_OBJECT USbStore_FileDeviceObject = NULL;
KEVENT Event;
#if DBG
DbgPrint("Enter AddDevice Dispatch!/n");
#endif
status = IoCreateDevice(
DriverObject,
sizeof(USB_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_AUTOGENERATED_DEVICE_NAME ,
FALSE,
&USbStore_FileDeviceObject
);
if(!NT_SUCCESS(status))
{
#if DBG
DbgPrint("IoCreateDevice Failed!/n");
#endif
return status;
}
pUsb_DeviceExtension = (PUSB_DEVICE_EXTENSION)USbStore_FileDeviceObject->DeviceExtension;
RtlZeroMemory(pUsb_DeviceExtension,sizeof(USB_DEVICE_EXTENSION));
pUsb_DeviceExtension->DeviceType = USBSTORE_FDO;
pUsb_DeviceExtension->UsbFileDeviceObject = USbStore_FileDeviceObject;
pUsb_DeviceExtension->UsbPhysicalDeviceObject = PhysicalDeviceObject;
pUsb_DeviceExtension->SystemPowerState = PowerSystemWorking;
pUsb_DeviceExtension->CurrentPowerState = PowerDeviceD0;
pUsb_DeviceExtension->UsbStore_TopOfStackDeviceObject =
IoAttachDeviceToDeviceStack(
USbStore_FileDeviceObject,
PhysicalDeviceObject
);
KeInitializeEvent(
&Event,
SynchronizationEvent,
FALSE
);
pUsb_DeviceExtension->Usb_Event = Event;
UsbStore_GetDriverFlags(USbStore_FileDeviceObject);
USbStore_FileDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
USbStore_FileDeviceObject->Flags |= DO_DIRECT_IO;
USbStore_FileDeviceObject->Flags |= DO_POWER_PAGABLE;
return STATUS_SUCCESS;
}
//UsbStore_GetDriverFlags
NTSTATUS
UsbStore_GetDriverFlags(
IN PDEVICE_OBJECT UsbFdo
)
{
PUSB_DEVICE_EXTENSION pUsb_DeviceExtension;
NTSTATUS status;
HANDLE RegHandle;
RTL_QUERY_REGISTRY_TABLE RegTable;
ULONG Value = 0;
RtlZeroMemory(&RegTable,sizeof(RTL_QUERY_REGISTRY_TABLE));
pUsb_DeviceExtension = UsbFdo->DeviceExtension;
status = IoOpenDeviceRegistryKey(
pUsb_DeviceExtension->UsbPhysicalDeviceObject,
PLUGPLAY_REGKEY_DRIVER,
STANDARD_RIGHTS_ALL,
&RegHandle
);
if(NT_SUCCESS(status))
{
RegTable.Flags = RTL_QUERY_REGISTRY_DIRECT;
RegTable.Name = L"DriverFlags";
RegTable.EntryContext = &Value;
RegTable.DefaultType = REG_DWORD;
RegTable.DefaultData = &Value;
RegTable.DefaultLength = sizeof(ULONG);
status = RtlQueryRegistryValues(
RTL_REGISTRY_HANDLE,
RegHandle,
&RegTable,
NULL,
NULL
);
if(!NT_SUCCESS(status))
{
#if DBG
DbgPrint("RtlQueryRegistryValues Failed!/n");
#endif
return status;
}
ZwClose(RegHandle);
}
if(Value>=4)
Value =0;
pUsb_DeviceExtension->DriverFlags = Value;
return status;
}
在这段代码中,
status = IoCreateDevice(
DriverObject,
sizeof(USB_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_AUTOGENERATED_DEVICE_NAME ,
FALSE,
&USbStore_FileDeviceObject
);
负责建立一个USB STORAGE DRIVER的FDO,请各位注意,设备的类型(DEVICE TYPE)是FILE_DEVICE_BUS_EXTENDER。
取注册表的一段代码,主要负责是取出DRIVER FLAGS,它用于标记设备是满足CBI规范还是BULK ONLY规范。
UsbStore_ReadWrite这一函数不做任何实际有用的读写操作。
NTSTATUS UsbStore_ReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
#if DBG
DbgPrint("Enter ReadWrite Dispatch!/n");
#endif
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
UsbStore_Scsi将上层DRIVER的IRP_MJ_SCSI的请求排队,
NTSTATUS UsbStore_Scsi(IN PDEVICE_OBJECT UsbStorePdo, IN PIRP Irp)
{
PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
PIO_STACK_LOCATION irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK Srb = irpStackLocation->Parameters.Scsi.Srb;
NTSTATUS status;
KIRQL Irql;
if(pUsbStoreDeviceExtension->DeviceType == USBSTORE_PDO)
{
if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
{
if(Srb->DataTransferLength <=0x10000)
{
Srb->SrbStatus = SRB_STATUS_PENDING;
IoMarkIrpPending(Irp);
IoStartPacket(UsbStorePdo, Irp, &Srb->QueueSortKey, (PDRIVER_CANCEL)UsbStore_CancelRoutine);
status = STATUS_PENDING;
}
else
{
status = STATUS_INVALID_PARAMETER;
}
}
else if(Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
{
KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock, &Irql);
if(pUsbStoreDeviceExtension->DeviceFlags&0x01)
{
status = STATUS_END_OF_FILE;
Srb->SrbStatus = SRB_STATUS_BUSY;
}
else
{
pUsbStoreDeviceExtension->DeviceFlags|=0x01;
Srb->DataBuffer = UsbStorePdo;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);
}
else if(Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
{
KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock,&Irql);
pUsbStoreDeviceExtension->DeviceFlags &= 0xFFFFFFFE;
KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
status = STATUS_SUCCESS;
}
else if(Srb->Function == SRB_FUNCTION_FLUSH)
{
Srb->SrbStatus = SRB_STATUS_SUCCESS;
status = STATUS_SUCCESS;
}
else
{
status = STATUS_NOT_SUPPORTED;
}
}
else
{
status = STATUS_NOT_SUPPORTED;
}
if(status != STATUS_PENDING)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
而UsbStore_StartIo函数将排队的IRP通过CBI规范或者BULK ONLY规范发送给设备,
VOID UsbStore_StartIo( IN PDEVICE_OBJECT UsbStorePdo, IN PIRP Irp )
{
ULONG TempFlags;
PSCSI_REQUEST_BLOCK Srb;
UCHAR DeviceErrorFlags ;
ULONG NeedSenseRequestFlags;
PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
PIO_STACK_LOCATION irpStackLocation;
KIRQL Irql;
irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
if(irpStackLocation->MajorFunction == IRP_MJ_POWER)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return;
}
else
{
IoAcquireCancelSpinLock(&Irql);
InterlockedExchange((PULONG)&Irp->CancelRoutine,0);
if(Irp->Cancel != 0)
{
KeAcquireSpinLockAtDpcLevel(&pUsbStoreDeviceExtension->SpinLock);
pUsbStoreDeviceExtension->DeviceFlags = pUsbStoreDeviceExtension->DeviceFlags>>3; pUsbStoreDeviceExtension->DeviceFlags = ~pUsbStoreDeviceExtension->DeviceFlags;
pUsbStoreDeviceExtension->DeviceFlags = pUsbStoreDeviceExtension->DeviceFlags&1;
TempFlags = pUsbStoreDeviceExtension->DeviceFlags;
KeReleaseSpinLockFromDpcLevel(&pUsbStoreDeviceExtension->SpinLock);
IoReleaseCancelSpinLock(Irql); Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
if(TempFlags==0)
return;
else
IoStartNextPacket(UsbStorePdo, TRUE);
return;
}
else
{
IoReleaseCancelSpinLock(Irql);
DeviceErrorFlags = 0;
NeedSenseRequestFlags = 0;
Srb = irpStackLocation->Parameters.Scsi.Srb;
pUsbStoreDeviceExtension->Srb = Srb;
KeAcquireSpinLockAtDpcLevel(&pUsbStoreDeviceExtension->SpinLock);
if(pUsbStoreDeviceExtension->DeviceFlags&DEVICE_ERROR)
{
DeviceErrorFlags = 1;
}
else
{
pUsbStoreDeviceExtension->SrbTimeOutValue = Srb->TimeOutValue;
if(pUsbStoreDeviceExtension->DeviceFlags&NEED_SENSEREQUEST)
{
NeedSenseRequestFlags = 1;
pUsbStoreDeviceExtension->DeviceFlags&=~NEED_SENSEREQUEST;
}
}
KeReleaseSpinLockFromDpcLevel(&pUsbStoreDeviceExtension->SpinLock);
if(DeviceErrorFlags ==0)
{
UsbStore_FormatSrb(UsbStorePdo,Irp,Srb,1);
if(pUsbStoreDeviceExtension->DriverFlags==1)
{
UsbStore_BulkOnly(UsbStorePdo,Irp);
return;
}
else
{
if(NeedSenseRequestFlags == 0||Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
{
UsbStore_CBI(UsbStorePdo, Irp);
return;
}
else
{
UsbStore_CBIGetRequestSense(UsbStorePdo,Irp,1);
return;
}
}
}
else
{
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoStartNextPacket(UsbStorePdo, TRUE);
return;
}
}
}
}
UsbStore_DeviceIoControl函数负责处理IRP_MJ_DEVICE_CONTROL,其中IOCONTROLCODE主要有IOCTL_SCSI_PASS_THROUGH,IOCTL_SCSI_PASS_THROUGH_DIRECT,IOCTL_STORAGE_QUERY_PROPERTY。限于篇幅,就不将此函数的代码列下。 UsbStore_Pnp函数负责处理IRP_MJ_PNP,USB STORAGE DRIVER的FDO IRP_MJ_PNP的IRP_MN_START_DEVICE负责建立USB连接,建立USB STORAGE DRIVER的PDO。USB STORAGE DRIVER FDO 的IRP_MN_REMOVE_DEVICE负责清除设备资源及USB连接。 USB STORAGE DRIVER PDO的IRP_MN_QUERY_DEVICE_TEXT 和IRP_MN_QUERY_ID是BUS DRIVER的PNP所必须处理的。
NTSTATUS
UsbStore_Pnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PUSB_DEVICE_EXTENSION pUsbDeviceExtension;
PIO_STACK_LOCATION irpStackLocation;
irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
pUsbDeviceExtension = DeviceObject->DeviceExtension;
if(pUsbDeviceExtension->DeviceType == USBSTORE_FDO)
{
switch(irpStackLocation->MinorFunction)
{
case IRP_MN_STOP_DEVICE:
status = UsbStore_UsbFdoStopDevice(DeviceObject,Irp);
break;
case IRP_MN_START_DEVICE:
status = UsbStore_UsbFdoStartDevice(DeviceObject,Irp);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
status = UsbStore_UsbFdoQueryRemoveDevice(DeviceObject,Irp);
break;
case IRP_MN_REMOVE_DEVICE:
status = UsbStore_UsbFdoRemoveDevice(DeviceObject,Irp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
status = UsbStore_UsbFdoCancelRemoveDevice(DeviceObject,Irp);
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
status = UsbStore_UsbFdoQueryDeviceRelations(DeviceObject,Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
Irp->IoStatus.Status = STATUS_SUCCESS;
default:
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pUsbDeviceExtension->UsbStore_TopOfStackDeviceObject,Irp);
return status;
}
}
else
{
switch(irpStackLocation->MinorFunction)
{
case IRP_MN_QUERY_CAPABILITIES:
status = UsbStore_StorePdoQueryCapabilities(DeviceObject,Irp);
return status;
case IRP_MN_START_DEVICE:
status = UsbStore_StorePdoStartDevice(DeviceObject,Irp);
return status;
case IRP_MN_REMOVE_DEVICE:
status = UsbStore_StoreRemoveDevice(DeviceObject,Irp);
return status;
case IRP_MN_QUERY_DEVICE_RELATIONS:
status = UsbStore_StoreQueryDeviceRelations(DeviceObject,Irp);
return status;
case IRP_MN_QUERY_DEVICE_TEXT:
status = UsbStore_StoreQueryDeviceText(DeviceObject,Irp);
return status;
case IRP_MN_QUERY_ID:
status = UsbStore_StoreQueryID(DeviceObject,Irp);
return status;
default:
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
}
return status;
}
本文以BULK ONLY为例来说明USB STORAGE DRIVER的传输过程。
VOID
UsbStore_BulkOnly(IN PDEVICE_OBJECT UsbStorePdo,
IN PIRP Irp)
{
PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
PUSB_DEVICE_EXTENSION pUsbDeviceExtension = pUsbStoreDeviceExtension->pUsbDeviceExtension;
PIO_STACK_LOCATION nextirpst,irpst,irpStackLocation = IoGetCurrentIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK Srb = irpStackLocation->Parameters.Scsi.Srb;
PUCHAR pCdb = &Srb->Cdb[0];
PBULKONLY_CBW pBulkOnly_Cbw = &pUsbStoreDeviceExtension->BulkOnly_Cbw;
pUsbStoreDeviceExtension->ResaetpipeTimes = 0;
pBulkOnly_Cbw->dCbwSignature = BULKONLY_CBWSIG;
pBulkOnly_Cbw->dCbwTag = (ULONG_PTR)Irp;
pBulkOnly_Cbw->dCbwDataTransferLength = Srb->DataTransferLength;
pBulkOnly_Cbw->bmCbwFlags = ((UCHAR)Srb->SrbFlags&0xC0)<<1;
pBulkOnly_Cbw->bCbwLun = 0;
pBulkOnly_Cbw->bCbwCBLength = Srb->CdbLength;
RtlCopyMemory(pBulkOnly_Cbw->CbwCDB,pCdb,sizeof(CDB));
UsbStore_TransferData(UsbStorePdo,Irp,pUsbDeviceExtension->pBulkOutPipeInfo->PipeHandle,0,0x1F,pBulkOnly_Cbw,NULL,(PIO_COMPLETION_ROUTINE)UsbStore_BulkOnlySendCbwCompleteRoutine,0);
return;
}
根据BULK ONLY规范定义了一个结构:
typedef struct _BULKONLY_CBW{
ULONG dCbwSignature;
ULONG_PTR dCbwTag;
ULONG dCbwDataTransferLength;
UCHAR bmCbwFlags;
UCHAR bCbwLun :4;
UCHAR Reserved0:4;
UCHAR bCbwCBLength:5;
UCHAR Reserved1:3;
UCHAR CbwCDB[16];
}BULKONLY_CBW, *PBULKONLY_CBW;
注意:这个结构的长度在BULKONLY规范里是0X1F,而不是SIZEOF(BULKONLY_CBW),此值传递给UsbStore_TransferData
UsbStore_TransferData负责USB数据传输
VOID
UsbStore_TransferData(
IN PDEVICE_OBJECT UsbStorePdo,
IN PIRP Irp,
IN USBD_PIPE_HANDLE PipeHandle,
IN ULONG TransferFlags,
IN ULONG DataTransferBufferLength,
IN PVOID DataTransferBuffer,
IN PMDL DataTransferBufferMDL,
IN PIO_COMPLETION_ROUTINE CompleteRoutine,
IN PVOID Context
)
{
PUSBSTORE_DEVICE_EXTENSION pUsbStoreDeviceExtension = UsbStorePdo->DeviceExtension;
PUSB_DEVICE_EXTENSION pUsbDeviceExtension = pUsbStoreDeviceExtension->pUsbDeviceExtension;
PURB purb = &pUsbStoreDeviceExtension->CurrentUrb;
PIO_STACK_LOCATION irpStackLocation = IoGetNextIrpStackLocation(Irp);
KIRQL Irql;
RtlZeroMemory(purb,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
UsbBuildInterruptOrBulkTransferRequest(
purb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
PipeHandle,
DataTransferBuffer,
DataTransferBufferMDL,
DataTransferBufferLength,
TransferFlags,
NULL
);
irpStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
irpStackLocation->Parameters.Others.Argument1 = purb;
IoSetCompletionRoutine(Irp, CompleteRoutine, Context, TRUE, TRUE, TRUE);
KeAcquireSpinLock(&pUsbStoreDeviceExtension->SpinLock, &Irql);
pUsbStoreDeviceExtension->DeviceFlags |= TRANSFER_FINISHED;
pUsbStoreDeviceExtension->CurrentIrp = Irp;
KeReleaseSpinLock(&pUsbStoreDeviceExtension->SpinLock, Irql);
IoCallDriver(pUsbDeviceExtension->UsbStore_TopOfStackDeviceObject, Irp);
}