USB通用驱动源码分析
+ -

设备的卸载删除STATUS_DELETE_PENDING

2025-06-13 0 0

当设备正常运行时,会不可避免地出现设备弹出,在Windows层面,会响应IRP_MN_SURPRISE_REMOVAL,这是设备弹出驱动收到的第一个PNP消息。

在收到IRP_MN_SURPRISE_REMOVAL消息后,驱动应停止设备,并将设备的状态更新至正在删除态,这时对于一些业务上的IRP请求,应返回STATUS_DELETE_PENDING,而一些特殊的IRP,应正常处理。

对于STATUS_DELETE_PENDING给出的解释如下:
STATUS_DELETE_PENDING 是 Windows 驱动程序开发中一个重要的状态码,用于处理设备或资源正在被删除时的 I/O 请求。

  • 设备正在被移除时:当设备收到移除请求(IRP_MN_REMOVE_DEVICE)后但尚未完全移除前设备栈正在被拆除的过程中
  • 资源即将被释放时:当驱动程序确定某个资源(如设备对象、内存区域等)即将被释放但可能还有未完成的 I/O 操作
  • 对象即将被删除时:文件系统驱动中文件/目录被标记删除但仍有打开句柄时任何需要优雅终止操作的场景
/*
 * 确保在设备对象被移除时,除了PNP和CLOSE请求外不处理任何其他IRP
 * 这发生在我们已经增加该IRP的pendingActionCount之后
     */
    if ((majorFunction != IRP_MJ_PNP) && (majorFunction != IRP_MJ_CLOSE)){
        enum deviceState state = (isParentFdo) ? parentFdoExt->state : functionPdoExt->state;
        if (!isParentFdo && majorFunction == IRP_MJ_POWER) {
            /*
         * 对于子功能PDO的电源IRP不中止,即使状态是STATE_REMOVING或STATE_REMOVED,
         * 因为这会否决已禁用的子功能PDO的挂起请求
             */
            ;
        } else if ((state == STATE_REMOVING) || (state == STATE_REMOVED)){
            abortIrp = TRUE;
        }
    }

    if (abortIrp){
        /*
     * 在移除IRP后失败所有IRP。
     * 这通常不应该发生,除了:
     * 我们可能在移除后收到功能PDO的电源IRP,
     * 因为(根据splante)电源状态机不与PNP状态机同步。
     * 我们现在在上面处理这种情况。
         */
        DBGWARN(("Aborting IRP %ph (function %xh/%xh) because delete pending", irp, majorFunction, minorFunction));
        ASSERT((majorFunction == IRP_MJ_POWER) && !isParentFdo);
        status = irp->IoStatus.Status = STATUS_DELETE_PENDING;
        if (majorFunction == IRP_MJ_POWER){
            PoStartNextPowerIrp(irp);
        }
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }

所以本人总结代码如下:

    PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
    UCHAR MajorFunction = IoStack->MajorFunction;
    if ((MajorFunction != IRP_MJ_PNP) && (MajorFunction != IRP_MJ_CLOSE) && (MajorFunction != IRP_MJ_POWER))
    {
        if (!PDODeviceExtension->Present || PDODeviceExtension->state != STATE_STARTED)
        {
            NTSTATUS Status = STATUS_DELETE_PENDING;
            Irp->IoStatus.Status = Status;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return Status;
        }
    }
HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

设备的卸载删除STATUS_DELETE_PENDING
当设备正常运行时,会不可避免地出现设备弹出,在Windows层面,会响应IRP_MN_SURPRISE_REMOVAL,这是设备弹出驱动收到的第一个PNP消息。在收到IRP_MN_SURPRISE_REMOVAL消息后,驱动应停止设备,并将设备的状态更新至正在删除态,这时对于一些业务上的IRP请求......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!