📄 drvdispatch.c
字号:
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
urb->UrbHeader.Status);
// decrement the driver's overall pending irp count
hwDecrementIoCount(deviceObject);
//------------------------------------------------------------------
// IoCallDriver has been called on this Irp;
// Set the length based on the TransferBufferLength
// value in the URB
//------------------------------------------------------------------
ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
CompleteIrp ( Irp,
STATUS_SUCCESS,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
IO_NO_INCREMENT);
#if DBG
#ifdef _BUFFERED_IO
hwDbgPrint ( "TransferFlags = %d, TransferBuffer = 0x%x, TransferBufferLength = %d\n",
urb->UrbBulkOrInterruptTransfer.TransferFlags ,
urb->UrbBulkOrInterruptTransfer.TransferBuffer,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
if ( urb->UrbBulkOrInterruptTransfer.TransferBuffer )
{
hwPrintCommData ( (char*)urb->UrbBulkOrInterruptTransfer.TransferBuffer ,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength );
}
#else
hwDbgPrint ( "TransferFlags = %d, TransferBufferMDL = 0x%x, TransferBufferLength = %d\n",
urb->UrbBulkOrInterruptTransfer.TransferFlags ,
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
if ( urb->UrbBulkOrInterruptTransfer.TransferBufferMDL )
{
hwPrintCommData ( (char*) urb->UrbBulkOrInterruptTransfer.TransferBufferMDL ,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength );
}
#endif
#endif
hwDbgPrint("hwReadWriteComplete( ntStatus = 0x%x )-->>>>>>\n",ntStatus );
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to the FDO ( Functional Device Object )
* Irp - A staged IRP allocated and mapped by this driver in zjHMCFUsb_StageReadWrite()
* to perform a single dx->MaximumTransferSize IO request
* PipeHandle - 我们要读或写的端点句柄
* pUserBuffer - 用户缓冲,如果使用缓冲IO时这个参数有用
* Read - TRUE for reads, FALSE for writes
* Return Value : ptr to initialized async urb. ( USB Request Block )
* Description : Called from zjHMCFUsb_StageReadWrite() for IRP_MJ_READ or IRP_MJ_WRITE
* Note :
* 1. 调用ExAllocatePool()分配一个非分页的内存用来存储URB结构体,这个内存
* 将在完成例程zjHMCFUsb_SimpleReadWrite_Complete()中释放
* 2. 填好里面的参数,主要是端点句柄、传输标志、缓冲地址、要传输
* 的数据长度
*************************************************************************************************/
PURB hwBuildAsyncReadWriteURB
(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PURB urb,
IN PVOID pUserBuffer,
IN PUSBD_PIPE_INFORMATION PipeHandle,
IN ULONG length,
IN BOOLEAN Read
)
{
ULONG SizeofUrbBulkOrInterruptTransfer;
hwASSERT( urb );
SizeofUrbBulkOrInterruptTransfer = sizeof ( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
hwDbgPrint(" -->>>>>> hwBuildAsyncReadWriteURB() len = 0x%x decimal %d \n SizeofUrbBulkOrInterruptTransfer = 0x%x urb 0x%x\n Pipehandle 0x%x",
length, length, SizeofUrbBulkOrInterruptTransfer, urb, PipeHandle);
RtlZeroMemory(urb, SizeofUrbBulkOrInterruptTransfer);
urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) SizeofUrbBulkOrInterruptTransfer;
urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
urb->UrbBulkOrInterruptTransfer.PipeHandle = PipeHandle->PipeHandle;
// 传输方向
urb->UrbBulkOrInterruptTransfer.TransferFlags = Read ? USBD_TRANSFER_DIRECTION_IN : 0;
// short packet is not treated as an error.
urb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
// not using linked urb's
urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
#ifdef _BUFFERED_IO
urb->UrbBulkOrInterruptTransfer.TransferBuffer = pUserBuffer;
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
#else
urb->UrbBulkOrInterruptTransfer.TransferBuffer = NULL;
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = Irp->MdlAddress;
#endif
urb->UrbBulkOrInterruptTransfer.TransferBufferLength = length;
hwDbgPrint("hwBuildAsyncReadWriteURB() Init async urb Length = 0x%x decimal %d, buf = 0x%x, MDLBuf = 0x%x\n",
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
urb->UrbBulkOrInterruptTransfer.TransferBuffer,
urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
hwDbgPrint(" <<<<< hwBuildAsyncReadWriteURB()\n");
return urb;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Irp - pointer to the IRP_MJ_READ or IRP_MJ_WRITE
* Read - Read - TRUE for read, FALSE for write
* Return Value : NT status code
* Description : 要传输的长度小于dx->MaximumTransferSize字节,因此不需要进行
* 多次提交URB,提交一次就可以搞定
* Note :
* 1. 从文件对象fileObject中取到管道信息pipeHandle。这个pipeHandle是在Create()时
* 也就是应用程序CreateFile()时驱动保存起来的,实际就是我们要进行读或写
* 的端点。应用程序在同时多次打开同一设备时,文件对象fileObject是各不
* 相同的,可以使用fileObject->FsContext 来保存一些可以相互区分的信息,比如
* 这里保存了同一设备的不同 管道信息
* 2. 调用zjHMCFUsb_BuildAsyncRequest() 构建一个URB
* 3. 调用IoGetNextIrpStackLocation()函数取得下层驱动栈的地址nextStack
* 4. 将创建好的URB赋到nextStack里面去,并设置好其他IRP请求参数
* 5. 设置好完成例程zjHMCFUsb_SimpleReadWrite_Complete(),调用zjHMCFUsb_IncrementIoCount()
* 将IO计数加1
* 6. 调用IoCallDriver()将这个带有URB的IRP提交给下层驱动USBD, IoCallDriver()会返回
* 一个STATUS_PENDING上来,我们将它直接返回给应用层,告诉它你的IRP正
* 在处理
*
*************************************************************************************************/
NTSTATUS hwProcessReadWrite
(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN BOOLEAN Read
)
{
NTSTATUS ntStatus;
ULONG siz;
PURB urb;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PUSBD_PIPE_INFORMATION pipeHandle = NULL;
PDEVICE_EXTENSION dx = fdo->DeviceExtension;
ULONG totalLength;
PUCHAR pUserBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
hwDbgPrint(" -->>>>>> hwProcessReadWrite ( fdo = %x, Irp = 0x%x, Read = %d\n",
fdo,Irp,Read );
PrintCurIrql();
Irp->IoStatus.Information = 0;
if ( !hwCanAcceptIoRequests( fdo ) )
{
hwDbgPrint("Can't accept requests, returning STATUS_INSUFFICIENT_RESOURCES\n");
return CompleteIrp( Irp, STATUS_DELETE_PENDING,0,IO_NO_INCREMENT);
}
siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
#ifdef _BUFFERED_IO
if ( Read )
{
totalLength = irpStack->Parameters.Read.Length;
}
else
{
totalLength = irpStack->Parameters.Write.Length;
}
hwDbgPrint("totalLength = decimal %d, pUserBuffer = 0x%x\n",totalLength, pUserBuffer );
#else
if ( !Irp->MdlAddress )
{
hwDbgPrint("Irp->MdlAddress = NULL!!!\n");
return CompleteIrp( Irp, STATUS_INVALID_PARAMETER,0,IO_NO_INCREMENT);
}
totalLength = MmGetMdlByteCount(Irp->MdlAddress);
hwDbgPrint("totalLength = decimal %d, Irp->MdlAddress = 0x%x\n",totalLength, Irp->MdlAddress );
#endif
if ( totalLength > dx->MaximumTransferSize )
{
hwDbgPrint ( "totalLength(%d) > dx->MaximumTransferSize(%d)\n",totalLength,dx->MaximumTransferSize );
totalLength = dx->MaximumTransferSize;
}
if (!pipeHandle)
{
ntStatus = STATUS_INVALID_HANDLE;
hwDbgPrint("Rejecting on invalid pipeHandle 0x%x decimal %d\n",pipeHandle, pipeHandle );
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
hwASSERT( UsbdPipeTypeBulk == pipeHandle->PipeType );
// Build our URB for USBD
urb = hwBuildAsyncReadWriteURB(fdo,
Irp,
dx->TransferDataUrb,
pUserBuffer,
pipeHandle,
totalLength,
Read);
//------------------------------------------------------------------
// 现在我们已经创建好了URB,我们将发送一个请求
// 给USB设备对象
//
// 调用类驱动来履行这个操作
//
// IoGetNextIrpStackLocation()给于一个通过IRP从高层驱动访问
// 下层驱动I/O栈位置,因此调用者可以设置下层驱动
//------------------------------------------------------------------
nextStack = IoGetNextIrpStackLocation(Irp);
hwASSERT(nextStack != NULL);
// pass the URB to the USB driver stack
nextStack->Parameters.Others.Argument1 = urb;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp, // irp to use
hwReadWriteComplete, // routine to call when irp is done
fdo, // we pass our FDO as context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE); // call on cancel
// Call IoCallDriver to send the irp to the usb port.
hwIncrementIoCount(fdo);
ntStatus = IoCallDriver(dx->LowerDeviceObject, Irp );
hwDbgPrint("IoCallDriver status (pending) 0x%x\n", ntStatus);
//------------------------------------------------------------------
// The USB driver should always return STATUS_PENDING when
// it receives an irp with major function code IRP_MJ_WRITE or IRP_MJ_READ.
//------------------------------------------------------------------
ASSERT( ntStatus == STATUS_PENDING);
hwDbgPrint("hwProcessReadWrite(ntStatus = 0x%x) -->>>>>>\n",ntStatus);
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* IRP - pointer to the IRP_MJ_WRITE
* Return Value : NT status code
* Description : This is the IRP_MJ_WRITE routine set in our dispatch table;
* WriteFile() calls from user mode ultimately land here
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Write(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
NTSTATUS ntStatus = hwProcessReadWrite(fdo,Irp,FALSE); // false to write, true to read
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* IRP - pointer to the IRP_MJ_READ
* Return Value : NT status code
* Description : This is the IRP_MJ_READ routine set in our dispatch table;
* ReadFile() calls from user mode ultimately land here
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Read(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
NTSTATUS ntStatus = hwProcessReadWrite(fdo,Irp, TRUE); // false to write, true to read
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* IRP - pointer to an I/O Request Packet
* Return Value : Status returned from lower driver
* Description : Main dispatch table routine for IRP_MJ_SYSTEM_CONTROL
* We basically just pass these down to the PDO
*************************************************************************************************/
NTSTATUS zjHMCFUsb_SysControl(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION dx;
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS waitStatus;
PDEVICE_OBJECT stackDeviceObject;
hwDbgPrint(" -->>>>>> zjHMCFUsb_SysControl()\n");
PrintCurIrql();
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//------------------------------------------------------------------
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//------------------------------------------------------------------
irpStack = IoGetCurrentIrpStackLocation (Irp);
// Get a pointer to the device extension
dx = fdo->DeviceExtension;
stackDeviceObject = dx->LowerDeviceObject;
hwIncrementIoCount(fdo);
hwASSERT( IRP_MJ_SYSTEM_CONTROL == irpStack->MajorFunction);
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,Irp);
hwDecrementIoCount(fdo);
hwDbgPrint("zjHMCFUsb_SysControl() Exit zjHMCFUsb_SysControl %x\n", ntStatus);
return ntStatus;
}
NTSTATUS zjHMCFUsb_Cleanup( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PDEVICE_EXTENSION dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
KIRQL OldIrql;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
PFILE_OBJECT fileObject = irpStack->FileObject;
// Cancel all IRPs in the I/O Manager maintained queue in device object
PKDEVICE_QUEUE_ENTRY QueueEntry;
hwDbgPrint("-->>>>>> ZjMdmDispatchCleanup(fdo=0x%x, Irp=0x%x\n",fdo,Irp);
PrintCurIrql();
IoAcquireCancelSpinLock(&OldIrql);
while( (QueueEntry=KeRemoveDeviceQueue(&fdo->DeviceQueue)) != NULL)
{
PIRP CancelIrp = CONTAINING_RECORD( QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry);
PIO_STACK_LOCATION CancelIrpStack =
IoGetCurrentIrpStackLocation(CancelIrp);
if (CancelIrpStack->FileObject != fileObject )
{
hwDbgPrint ( "因为文件对象不同,所以说明这个IRP不应该放弃\n");
continue;
}
CancelIrp->Cancel = TRUE;
CancelIrp->CancelIrql = OldIrql;
CancelIrp->CancelRoutine = NULL;
IoReleaseCancelSpinLock(OldIrql);
hwDbgPrint("ZjMdmDispatchCleanup: Cancelling %x 0x%x\n",CancelIrp,CancelIrp);
CompleteIrp( CancelIrp, STATUS_CANCELLED,0,IO_NO_INCREMENT);
IoAcquireCancelSpinLock(&OldIrql);
}
IoReleaseCancelSpinLock(OldIrql);
hwDbgPrint("ZjMdmDispatchCleanup()-->>>>>>\n");
return CompleteIrp( Irp, STATUS_SUCCESS,0,IO_NO_INCREMENT);
}
/////////////////////////////////////////////////////////////////////////////
// CompleteIrp: Sets IoStatus and completes the IRP
/************************************************************************************************
* Function Type : global
* Parameter : Irp - 要完成的IRP
* status - IRP的状态
* info - IRP的附加信息,一般是返回传输的字节数
* PriorityBoost - Specifies a system-defined constant by which to increment the runtime
* priority of the original thread that requested the operation
* Return Value : IRP完成的状态
* Description : 完成一个指定的IRP
*************************************************************************************************/
NTSTATUS CompleteIrp
(
IN PIRP Irp,
IN NTSTATUS status,
IN ULONG info/*=0*/,
IN CCHAR PriorityBoost/*=IO_NO_INCREMENT*/)
{
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp,PriorityBoost);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -