📄 drvpnp.c
字号:
* FALSE - 处理还没完,调用者应该接着执行以后的操作
* Description : 放弃停止设备
*************************************************************************************************/
BOOLEAN hwCancelStopDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwCancelStopDevice(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交给下层驱动处理
if (!dx->DeviceStarted)
{
hwDbgPrint("IRP_MN_CANCEL_STOP_DEVICE when device not started\n");
IoSkipCurrentIrpStackLocation (Irp);
(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
hwDecrementIoCount(fdo);
hwDbgPrint(" hwCancelStopDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return TRUE;
}
// 重设这个标志,以后IOCTL和IO Irp处理将重新被允许
dx->StopDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
(*p_ntStatus) = Irp->IoStatus.Status;
hwDbgPrint(" hwCancelStopDevice(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 hwRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
PDEVICE_EXTENSION dx;
UNICODE_STRING deviceLinkUnicodeString;
NTSTATUS ntStatus = STATUS_SUCCESS;
hwDbgPrint(" -->>>>>> hwRemoveDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);
dx = fdo->DeviceExtension;
(*p_ntStatus) = STATUS_SUCCESS;
//------------------------------------------------------------------
// Pnp管理器使用这个IRP来移走一个设备
// 作为一个"礼貌"的移走设备,Pnp管理器在移走设
// 备前先发送IRP_MN_QUERY_REMOVE_DEVICE
//------------------------------------------------------------------
hwDecrementIoCount(fdo);
// 一旦DeviceRemoved标志被设置,IOCTL or read/write irps将被直接
// 发送到下层驱动,所有的irps将很快地处理失败
dx->DeviceRemoved = TRUE;
// 如果任何管道仍然是打开的,用URB_FUNCTION_ABORT_PIPE
// 调用USBD来放弃所有管道并关闭所有管道
hwAbortPipes( fdo );
// 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);
//再次减1,正在处理的IRP数量在AddDevice中
//初始化为1,也就是说只有停止事件被
//标记,而要想卸载事件被标记,必须多
//减一次,当所有的IRP处理结束时,这个
//数量才会变成0,卸载事件才会被标记
hwDecrementIoCount(fdo);
// 等待设备所有正在处理的IO请求完成
KeWaitForSingleObject( &dx->RemoveEvent,
Suspended,
KernelMode,
FALSE,
NULL);
dx = fdo->DeviceExtension;
RtlInitUnicodeString (&deviceLinkUnicodeString,dx->DeviceLinkNameBuffer);
// remove the GUID-based symbolic link
ntStatus = IoSetDeviceInterfaceState(&deviceLinkUnicodeString, FALSE);
hwASSERT( NT_SUCCESS( ntStatus ) );
FreeDx( dx );
hwDbgPrint("Detaching from 0x%x\n",dx->LowerDeviceObject);
IoDetachDevice(dx->LowerDeviceObject);
hwDbgPrint("Deleting fdo = 0x%08x\n",fdo);
IoDeleteDevice (fdo);
hwDbgPrint(" hwRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
return TRUE;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : NT status code
* Description : 停止一个给定的USB设备实例
* 基本上我们只是告诉这个设备现在是'没有配置'的状态
*************************************************************************************************/
NTSTATUS hwStopDevice(IN PDEVICE_OBJECT fdo)
{
PDEVICE_EXTENSION dx;
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
ULONG siz;
//------------------------------------------------------------------
// Pnp 管理器发送这个IRP来停止一个设备,因此它
// 能重新配置硬件资源。Pnp管理器只是在
// IRP_MN_QUERY_STOP_DEVICE成功处理后才发送这个IRP的
//------------------------------------------------------------------
hwDbgPrint(" -->>>>>> hwStopDevice(fdo=0x%x)\n",fdo);
dx = fdo->DeviceExtension;
//------------------------------------------------------------------
// 发送选择配置的urb且配置句柄用NULL,这里将关闭配置
// 将设备置为没有"没有配置"的状态
//------------------------------------------------------------------
siz = sizeof(struct _URB_SELECT_CONFIGURATION);
urb = ExAllocatePool(NonPagedPool, siz);
if (urb)
{
UsbBuildSelectConfigurationRequest(urb,(USHORT) siz,NULL);
ntStatus = hwCallUSBD(fdo, urb);
hwDbgPrint("hwCallUSBD() Configuration Closed status = 0x%x usb status = 0x%x\n", ntStatus, urb->UrbHeader.Status);
FreeIfAllocated(urb);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(ntStatus))
{
dx->DeviceStarted = FALSE;
}
dx->StopDeviceRequested = FALSE;
hwDbgPrint("hwStopDevice() (ntStatus = %x)-->>>>>>\n", ntStatus);
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to fdo pointer to return created device object.
* deviceLinkUnicodeString - Points to a unicode string structure allocated by the caller.
* If this routine is successful, it initializes the unicode string and allocates
* the string buffer containing the kernel-mode path to the symbolic link for this
* device interface.
* Return Value : STATUS_SUCCESS - if successful,
* STATUS_UNSUCCESSFUL - otherwise
* Description : This routine is called to create and initialize
* a GUID-based symbolic link to our device to be used to open/create
* instances of us from user mode.
* Called from hwCreateDeviceObject() to create the link.
*************************************************************************************************/
NTSTATUS hwRegisterSymbolicLink
(
IN PDEVICE_OBJECT pdo,
IN PDEVICE_OBJECT fdo,
IN OUT PUNICODE_STRING deviceLinkUnicodeString
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_EXTENSION dx = fdo->DeviceExtension;
//------------------------------------------------------------------
//生成一个符号连接,IoRegisterDeviceInterfaceAPI将注册一个供
//应用程序或其他系统组件使用的设备功能接口
//------------------------------------------------------------------
ntStatus = IoRegisterDeviceInterface(
pdo,
(LPGUID)&GUID_CLASS_zjHMCFUsb_BULK,
NULL,
deviceLinkUnicodeString);
hwDbgPrint("%s to IoRegisterDeviceInterface()\n",NT_SUCCESS(ntStatus)?"Success":"Fail");
if (NT_SUCCESS(ntStatus))
{
// 将设备连接名拷贝到设备扩展结构体中
RtlCopyMemory ( dx->DeviceLinkNameBuffer,
deviceLinkUnicodeString->Buffer,
deviceLinkUnicodeString->Length );
hwDbgPrint ( "SymbolicLink : %s\n", dx->DeviceLinkNameBuffer );
// IoSetDeviceInterfaceState 函数禁用或启用一个先前已经注册的符号连接
ntStatus = IoSetDeviceInterfaceState(deviceLinkUnicodeString, TRUE);
hwDbgPrint("%s to IoSetDeviceInterfaceState()\n",NT_SUCCESS(ntStatus)?"Success":"Fail");
}
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : DriverObject - pointer to the driver object for device
* pdo - pointer to a device object created by the bus
* fdo - pointer to fdo pointer to return created device object.
* Return Value : STATUS_SUCCESS - if successful,
* STATUS_UNSUCCESSFUL - otherwise
* Description : 根据系统提供的驱动对象、物理设备对象创建一个功能
* 设备对象
*************************************************************************************************/
NTSTATUS hwCreateDeviceObject
(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT pdo,
OUT PDEVICE_OBJECT *ppDeviceObject
)
{
NTSTATUS ntStatus;
PDEVICE_EXTENSION dx;
USHORT i;
hwDbgPrint(" -->>>>>> hwCreateDeviceObject()\n");
hwDbgPrint ( "DriverObject=0x%x\n",DriverObject );
hwDbgPrint ( "pdo=0x%x\n",pdo );
hwDbgPrint ( "ppDeviceObject=0x%x\n",ppDeviceObject );
//IoCreateDevice函数申请内存并初始化一个驱动使用的设备对象
//设备对象就是驱动所支持的物理、虚拟或逻辑设备
ntStatus = IoCreateDevice (
DriverObject, //Points to the driver object for the caller.
//Each driver receives a pointer to its driver
//object in a parameter to its DriverEntry
//routine. PnP function and filter drivers also
//receive a driver object pointer in their
//AddDevice routines.
sizeof (DEVICE_EXTENSION), //设备扩展结构的大小
NULL, //设备名字,过滤驱动和功
//能驱动一般不命名,核心
//的总线驱动则指定一个
//unicode字符串作为设备的名字
FILE_DEVICE_UNKNOWN, //设备类型(such as FILE_DEVICE_DISK, FILE_DEVICE_KEYBOARD, etc.)
FILE_AUTOGENERATED_DEVICE_NAME, //提供设备附加信息
//FILE_AUTOGENERATED_DEVICE_NAME表示
//设备名字由I/O管理器自动创建,这样
//可以保证名字的唯一性
FALSE, //不是一个排他性的设备,I/O管理器允许打开该设备的多个句柄
ppDeviceObject //指向新生成的设备对象
);
if (!NT_SUCCESS(ntStatus))
{
hwDbgPrint("IoCreateDevice() FAILED\n");
goto done;
}
hwDbgPrint("IoCreateDevice() SUCCESS\n");
dx = (PDEVICE_EXTENSION) ((*ppDeviceObject)->DeviceExtension);
if ( !InitDx ( dx ) )
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
IoDeleteDevice( *ppDeviceObject );
goto done;
}
done:
hwDbgPrint(" hwCreateDeviceObject() -->>>>>> \n");
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - Pointer to the device object for the class device.
* Irp - Irp completed.
* Context - Driver defined context, in this case a pointer to an event.
* Return Value : The function value is the final status from the operation.
* Description : 这是一个最简单的irp完成例程,只是将事件置个信号
* 以通知正在等待的调用者
*************************************************************************************************/
NTSTATUS hwIRPCompletionRoutine
(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PVOID Context
)
{
PKEVENT event = (PKEVENT)Context;
KeSetEvent( event,
1, // 正在等待的线程优先权增加
FALSE); // Flag this call is not immediately followed by wait.
// 这个例程必须返回STATUS_MORE_PROCESSING_REQUIRED,因为我们在这
// 个irp上从未调用过IoFreeIrp()
return STATUS_MORE_PROCESSING_REQUIRED;
}
/************************************************************************************************
* Function Type : private
* Parameter : LowerDeviceObject - 在这个设备栈下层的设备对象.
* DeviceCapabilities - 设备性能对象指针
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -