📄 drvpnp.c
字号:
USB_DEVICE_DESCRIPTOR_TYPE,
0, //Specifies the device-defined index of the descriptor that is to be retrieved.
0, //Specifies the language ID of the descriptor to be retrieved when USB_STRING_DESCRIPTOR_TYPE is set in DescriptorType. This parameter must be 0 for any other value in DescriptorType.
deviceDescriptor, //Points to a resident buffer to receive the descriptor data or is NULL if an MDL is supplied in TransferBufferMDL.
NULL, //Points to an MDL that describes a resident buffer to receive the descriptor data or is NULL if a buffer is supplied in TransferBuffer.
siz, //Specifies the length of the buffer specified in TransferBuffer or described in TransferBufferMDL
NULL //Points to an caller-initialized URB. Link becomes the subsequent URB in a chain of requests with Urb being its predecessor
);
(*p_ntStatus) = hwCallUSBD(fdo, urb);
hwDbgPrint ( "hwCallUSBD %s \n",NT_SUCCESS((*p_ntStatus))?"SUCCESS":"FAILED" );
if (NT_SUCCESS((*p_ntStatus)))
{
hwDbgPrint ( "/******************* Device Descriptor ******************/\n" );
hwDbgPrint("deviceDescriptor = 0x%x, len %d\n",deviceDescriptor,urb->UrbControlDescriptorRequest.TransferBufferLength);
hwDbgPrint("bLength : %d\n", deviceDescriptor->bLength);
hwDbgPrint("bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType);
hwDbgPrint("bcdUSB 0x%x\n", deviceDescriptor->bcdUSB);
hwDbgPrint("bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass);
hwDbgPrint("bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass);
hwDbgPrint("bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol);
hwDbgPrint("bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0);
hwDbgPrint("idVendor 0x%x\n", deviceDescriptor->idVendor);
hwDbgPrint("idProduct 0x%x\n", deviceDescriptor->idProduct);
hwDbgPrint("bcdDevice 0x%x\n", deviceDescriptor->bcdDevice);
hwDbgPrint("iManufacturer 0x%x\n", deviceDescriptor->iManufacturer);
hwDbgPrint("iProduct 0x%x\n", deviceDescriptor->iProduct);
hwDbgPrint("iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber);
hwDbgPrint("bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations);
}
}
if (NT_SUCCESS((*p_ntStatus)))
{
dx->UsbDeviceDescriptor = deviceDescriptor;
}
FreeIfAllocated(urb);
}
else
{
// if we got here we failed to allocate the urb
(*p_ntStatus) = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS((*p_ntStatus)))
{
(*p_ntStatus) = hwConfigureDevice(fdo);
dx->DeviceStarted = TRUE;
}
done:
hwDbgPrint("hwStartDevice (%x)-->>>>>>\n", (*p_ntStatus));
(*p_ntStatus) = CompleteIrp( Irp, (*p_ntStatus),0,IO_NO_INCREMENT);
hwDecrementIoCount(fdo);
return TRUE;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : TRUE - 已经处理完了,调用者可以停止以后的处理
* 直接返回
* FALSE - 处理还没完,调用者应该接着执行以后的操作
* Description : 查询停止设备
*************************************************************************************************/
BOOLEAN hwQueryStopDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, OUT PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwQueryStopDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);
dx = fdo->DeviceExtension;
(*p_ntStatus) = STATUS_SUCCESS;
//------------------------------------------------------------------
// IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE只有在安全礼貌地
// 关闭计算机时才会收到,如果设备突然被移走是不会
// 收到这两个PNP IRP的
// 如果驱动将这个IRP的状态设置为STATUS_SUCCESS
// 那么驱动必须是没有在这个设备上启动任何操作
// 以防止驱动刚好完成一个IRP_MN_STOP_DEVICE的处理
// 对于大数据量存储的设备如磁盘驱动器,当设备在stop-pending
// 状态时,驱动将保存这些访问设备的IRPs请求,但是大多数
// 设备是不会保持长久地存储的。因此我们在IRP_MN_QUERY_STOP_DEVICE
// 时将拒绝所有I/O请求直到设备被重启或者放弃停止设备
// 如果设备栈中的驱动确定设备不能停下来进行资源的重新
// 分配,那么它没必要停止
// IRP下到设备栈后,如果"查询停止设备"返回失败,
// Pnp管理器发送IRP_MN_CANCEL_STOP_DEVICE给设备栈,通知驱动查询
// 已经放弃,设备不用停止
// 当设备没启动的时候可能会收到这个IRP( as on a boot device )
//------------------------------------------------------------------
// 如果设备没有启动,那么将这个IRP交给下层驱动去处理
if (!dx->DeviceStarted)
{
hwDbgPrint("IRP_MN_QUERY_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
hwDecrementIoCount(fdo);
return TRUE;
}
//可以停止设备
dx->StopDeviceRequested = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
(*p_ntStatus) = Irp->IoStatus.Status;
hwDbgPrint("hwQueryStopDevice()-->>>>>>\n");
return FALSE;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : TRUE - 已经处理完了,调用者可以停止以后的处理
* 直接返回
* FALSE - 处理还没完,调用者应该接着执行以后的操作
* Description : 查询移除设备
*************************************************************************************************/
BOOLEAN hwQueryRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwQueryRemoveDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);
dx = fdo->DeviceExtension;
(*p_ntStatus) = STATUS_SUCCESS;
//------------------------------------------------------------------
// 驱动响应这个irp是指示了是否给设备可以被移除
// 而不会破坏整个系统
// 如果一个设备确定设备可以安全移除,驱动将完成所有
// 显著的 I/O请求,安排保存好并发的读写请求,设置
// Irp->IoStatus.Status 为STATUS_SUCCESS。功能驱动和过滤驱动传递
// 这个irp给下层设备栈,下层总线驱动调用IoCompleteRequest()
// 如果驱动给这个irp设置STATUS_SUCCESS,驱动必须不要启动
// 任何在该设备上的操作以保证驱动成功地完成IRP_MN_REMOVE_DEVICE
// IRP,如果驱动确定设备不能被移除,驱动就没必要传递
// query-remove IRP给下层设备栈,如果query-remove IRP失败,PNP
// 管理器将发送一个IRP_MN_CANCEL_REMOVE_DEVICE给设备栈,通知
// 驱动查询移除的irp已经放弃,设备将不会被移除
//------------------------------------------------------------------
// 当设备没有启动的时候可能会收到这个IRP,将这个IRP交给下层驱动处理
if (!dx->DeviceStarted)
{
hwDbgPrint("IRP_MN_QUERY_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
hwDecrementIoCount(fdo);
hwDbgPrint(" hwQueryRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return TRUE;
}
// 将这个标志设为真,新的IOCTL和read/write irps 将被直接传给
// 下层驱动,所有的irps很快地就failed了
dx->RemoveDeviceRequested = TRUE;
// 在返回Success之前等到所有IO请求处理完成,当
// dx->PendingIoCount达到1时将置这个事件
KeWaitForSingleObject( &dx->NoPendingIoEvent,
Suspended,
KernelMode,
FALSE,
NULL);
Irp->IoStatus.Status = STATUS_SUCCESS;
(*p_ntStatus) = Irp->IoStatus.Status;
hwDbgPrint(" hwQueryRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return FALSE;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : TRUE - 已经处理完了,调用者可以停止以后的处理
* 直接返回
* FALSE - 处理还没完,调用者应该接着执行以后的操作
* Description : 放弃移除设备
*************************************************************************************************/
BOOLEAN hwCancelRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwCancelRemoveDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);
dx = fdo->DeviceExtension;
(*p_ntStatus) = STATUS_SUCCESS;
//------------------------------------------------------------------
// Pnp管理器使用这个IPR来通知驱动设备将不会被移走
//------------------------------------------------------------------
// 当设备没有启动的时候可能会收到这个IRP,将这个IRP交给下层驱动处理
if (!dx->DeviceStarted)
{
hwDbgPrint("IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
hwDecrementIoCount(fdo);
hwDbgPrint(" hwCancelRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return TRUE;
}
// 重设这个标志,使IOCTL、IO IRP又将被允许处理
dx->RemoveDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
(*p_ntStatus) = Irp->IoStatus.Status;
hwDbgPrint(" hwCancelRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return FALSE;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : NT status code
* Description : 设备意外被移除时调用。放弃将所有打开的管道的正在
* 处理的传输。用URB_FUNCTION_ABORT_PIPE参数调用USBD,并且
* 在我们保存的管道配置信息(PzjHMCFUsb_PIPESTATE)将这些管道
* 标记为"关闭"
*************************************************************************************************/
NTSTATUS hwAbortPipes(IN PDEVICE_OBJECT fdo)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
PDEVICE_EXTENSION dx = fdo->DeviceExtension;
ULONG i;
PUSBD_INTERFACE_INFORMATION interface;
interface = dx->UsbInterface;
if ( !dx->PipeState )
return STATUS_UNSUCCESSFUL;
//使用URB_FUNCTION_ABORT_PIPE功能关闭打开的管道
for (i=0; i<interface->NumberOfPipes; i++)
{
if ( dx->PipeState[i].fPipeOpened ) // we set this if open, clear if closed
{
hwDbgPrint("Aborting open Pipe %d\n", i);
urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
if (urb)
{
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
urb->UrbPipeRequest.PipeHandle = interface->Pipes[i].PipeHandle;
ntStatus = hwCallUSBD(fdo, urb);
FreeIfAllocated(urb);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
hwDbgPrint("Allocate urb memory failed\n" );
break;
}
if (!(NT_SUCCESS(ntStatus)))
{
break;
}
else
{
dx->PipeState[i].fPipeOpened = FALSE; // mark the pipe 'closed'
dx->OpenPipeCount--;
}
} // end, if pipe open
} // end, for all pipes
return ntStatus;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : TRUE - 已经处理完了,调用者可以停止以后的处理
* 直接返回
* FALSE - 处理还没完,调用者应该接着执行以后的操作
* Description : 意外移除设备
*************************************************************************************************/
BOOLEAN hwSurpriseRemovalDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwSurpriseRemovalDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);
dx = fdo->DeviceExtension;
(*p_ntStatus) = STATUS_SUCCESS;
//------------------------------------------------------------------
// 当设备被突然移走时PNP管理器发送这个IRP,这个
// 这个IRP之前并没有发送"查询移走"的IRP,设备无论在
// 什么状态都得处理这个"设备移走"的IRP
//------------------------------------------------------------------
hwDecrementIoCount(fdo);
// 一旦DeviceRemoved标志被设置,IOCTL 或 read/write irps将被直接
// 发送到下层驱动,所有的irps将很快地处理失败
dx->DeviceRemoved = TRUE;
hwAbortPipes( fdo );
// Mark this handled
Irp->IoStatus.Status = STATUS_SUCCESS;
// We don't explicitly wait for the below driver to complete, but just make
// the call and go on, finishing cleanup
IoCopyCurrentIrpStackLocationToNext(Irp);
(*p_ntStatus) = IoCallDriver(dx->LowerDeviceObject, Irp);
hwDbgPrint(" hwSurpriseRemovalDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return TRUE;
}
/************************************************************************************************
* Function Type : private
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : TRUE - 已经处理完了,调用者可以停止以后的处理
* 直接返回
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -