windows 驱动实例分析系列: libusb驱动分析-应用层源码篇(三)

libusb-win32 应用层源码分析(第三篇):安装工具、过滤器管理、注册表操作与动态加载

1. 引言

本篇聚焦于 libusb-win32 的系统集成部署机制 。用户态库不仅提供 USB 传输 API,还包含一套完整的工具链,用于安装/卸载内核驱动、管理设备/类过滤驱动,以及操作 Windows 注册表。此外,还提供了运行时动态加载机制(libusb_dyn.c),便于应用程序延迟绑定。

核心代码文件:

  • registry.c / registry.h:注册表底层操作封装。
  • install.c:核心安装逻辑(命令行、服务、INF 处理)。
  • install_filter.c:命令行过滤驱动管理入口。
  • install_filter_win.c:图形化过滤驱动管理向导。
  • libusb_dyn.c:动态加载 libusb0.dll 的代理层。

2. 注册表操作模块(registry.c

该模块直接与 Windows 注册表交互,管理类过滤驱动(Class Filters)和设备过滤驱动(Device Filters)。

2.1 关键数据结构

  • filter_class_t:表示一个设备类(通过 GUID 或名称标识),包含 UpperFilters / LowerFilters 的 MULTI_SZ 字符串。
  • filter_device_t:表示一个具体设备(通过硬件 ID 或实例 ID 标识),可包含上/下过滤驱动列表。
  • filter_context_t:聚合所有过滤操作上下文,用于 install.c 中的命令解析和执行。

2.2 MULTI_SZ 字符串操作

Windows 注册表中的多字符串(REG_MULTI_SZ)以双 null 结尾。registry.c 提供了一系列工具函数:

  • usb_registry_mz_string_size:计算多字符串总长度。
  • usb_registry_mz_string_find:查找是否存在指定驱动名(不区分大小写)。
  • usb_registry_mz_string_insert:插入新驱动名(追加到末尾)。
  • usb_registry_mz_string_remove:移除指定驱动名(自动压缩内存)。
  • usb_registry_mz_string_lower:转小写以进行比较。
  • usb_registry_mz_to_sz:将 MULTI_SZ 转换为逗号分隔的字符串(用于显示)。

2.3 类过滤驱动操作

  • 插入usb_registry_insert_class_filter):
    1. 遍历 filter_context->class_filters
    2. 读取该类的 UpperFilters 值。
    3. libusb0 不在其中,则插入并写回注册表。
    4. 标记 class_filters_modified = TRUE
  • 移除usb_registry_remove_class_filter):
    1. 类似地查找并移除 libusb0
    2. 若移除后为空,则删除该注册表值。
  • 类 GUID 路径为 SYSTEM\CurrentControlSet\Control\Class\{GUID}

2.4 设备过滤驱动操作

  • usb_registry_insert_device_filters
    1. 使用 SetupDiGetClassDevs 枚举所有 USB 设备。
    2. 对每个设备,通过硬件 ID 或设备实例 ID 匹配 filter_context->device_filters
    3. 若匹配,则修改 UpperFiltersLowerFilters,添加 libusb0
    4. 删除 SurpriseRemovalOK 注册表项(确保设备可被重启)。
    5. 必要时重启设备。
  • usb_registry_remove_device_filter
    1. 枚举设备,若匹配则从 UpperFilters / LowerFilters 中移除 libusb0
    2. 支持 --all-devices 开关全量移除。

2.5 硬件 ID 解析

  • usb_registry_fill_filter_hwid:从硬件 ID 字符串(如 USB\VID_1234&PID_5678&REV_0001)中提取 VID、PID、MI(接口号)、REV。
  • usb_registry_match_filter_device:基于 VID/PID/MI/REV 或设备实例 ID 进行精确匹配,支持通配(如 MI = -1 表示任意接口)。

2.6 设备状态控制

  • usb_registry_restart_device / stop_device / start_device:通过 DIF_PROPERTYCHANGE 触发设备重启/停止/启动。
  • usb_registry_restart_all_devices:遍历所有 USB 设备,重启根集线器(通常用于强制刷新驱动绑定)。

3. 核心安装逻辑(install.c

这是安装工具集的主模块,支持命令行(install-filter.exe)和图形化(install-filter-win.exe)两种前端。

3.1 命名管道导出函数(rundll32 兼容)

为方便安装程序调用,库导出了多个 CALLBACK 函数,可由 rundll32.exe 直接调用:

  • usb_install_service_np_rundll:安装驱动服务。
  • usb_uninstall_service_np_rundll:卸载驱动服务。
  • usb_install_driver_np_rundll:安装指定 INF 文件。
  • usb_touch_inf_file_np_rundll:破坏 INF 的数字签名(用于绕过系统驱动保护,仅在特殊情况下使用)。
  • usb_install_np_rundll:通用过滤驱动安装入口。

3.2 服务管理(usb_service_*

  • usb_service_create / delete / stop
    • 动态加载 advapi32.dll
    • 使用 OpenSCManagerCreateServiceDeleteService 等 API。
    • 驱动服务名固定为 libusb0,显示名包含版本号。
    • 启动类型为 SERVICE_DEMAND_START(按需启动)。

3.3 INF 文件安装(usb_install_inf_np

  • 使用 SetupCopyOEMInf 将 INF 复制到系统 INF 目录。
  • 解析 INF 的 [Manufacturer][Devices] 节,提取硬件 ID。
  • 调用 UpdateDriverForPlugAndPlayDevices 更新匹配设备的驱动。
  • 对于非存在设备(CR_NO_SUCH_DEVINST),设置 CONFIGFLAG_REINSTALL 标志,使其在下次插入时自动安装。

3.4 过滤驱动上下文解析(usb_install_parse_filter_context

  • 使用 CommandLineToArgvW 解析命令行。
  • 识别命令:list, install, uninstall
  • 识别开关:
    • --all-classes (-ac):操作所有类。
    • --device-classes (-dc):仅操作 USB 枚举器中的类。
    • --class=<GUID/name> (-c=):指定单个类。
    • --device=<hwid> (-d=):指定单个设备。
    • --device-id=<devinst> (-di=):通过设备实例 ID 指定。
    • --inf=<file> (-f=):操作 INF 文件。
    • --all-devices (-ad):移除所有设备过滤驱动。
    • --prompt= / --wait=:交互式提示。
  • 构建 filter_context_t 结构,供后续执行。

3.5 安装/卸载执行流程(usb_install_console

  • FM_INSTALL
    1. 若指定了类/设备过滤,调用 usb_registry_get_usb_class_keysusb_registry_get_all_class_keys 获取所有相关类。
    2. 调用 usb_install_service:创建驱动服务、插入类/设备过滤驱动。
    3. 若指定了 INF,调用 usb_install_inf_np 安装设备驱动。
  • FM_REMOVE
    1. 调用 usb_uninstall_service:移除类/设备过滤驱动、删除服务。
    2. 对指定的 INF,调用 usb_install_inf_np(remove_mode=TRUE) 尝试回滚驱动。
  • FM_LIST
    1. 枚举所有类,并显示类 GUID、名称、以及当前过滤驱动列表(上/下)。
    2. 显示设备名称、硬件 ID、实例 ID 及过滤驱动列表。

3.6 图形化进度窗口

  • usb_install_window 创建自定义进度对话框。
  • 使用 RichEdit 控件显示实时日志,支持颜色区分(错误红色、警告橙色)。
  • 自定义进度条使用 GradientFill 绘制渐变效果。
  • 通过 _beginthread 在后台执行实际安装操作,主窗口保持响应。
  • 使用互斥信号量(install_lock_sem_name)防止多个安装实例同时运行。

4. 过滤驱动管理工具

4.1 命令行版本(install_filter.c

  • 简单的 main 入口,调用 usb_install_npW(NULL, NULL, GetCommandLineW(), 1)
  • 将完整命令行传递给 install.c 处理。

4.2 图形化向导(install_filter_win.c

  • 两个对话框:
    • 对话框 0:选择操作(安装设备过滤 / 移除设备过滤 / 移除所有设备过滤)。
    • 对话框 1 :显示设备列表(通过 ListView),用户选择目标设备。
  • 设备发现 :使用 SetupDiGetClassDevs 枚举 USB 设备。
    • 对于安装模式:显示未绑定 libusb0 过滤驱动的设备。
    • 对于移除模式:显示已绑定 libusb0 过滤驱动的设备。
    • 自动跳过 USB 集线器和根集线器。
  • 热插拔支持 :注册 GUID_DEVINTERFACE_USB_HUBGUID_DEVINTERFACE_USB_DEVICE 设备通知,收到 WM_DEVICECHANGE 时自动刷新列表。
  • 选择设备后,调用 usb_install_npA 执行具体操作,并弹出成功/失败消息框。

5. 动态加载模块(libusb_dyn.c

该模块提供了一种延迟绑定 机制,允许应用程序在运行时决定是否加载 libusb0.dll,而不是在编译时静态链接。

5.1 函数指针表

  • 为所有 libusb API 定义了静态函数指针(如 _usb_open, _usb_bulk_read 等),初始为 NULL

5.2 usb_init() 的特殊实现

  • 调用 LoadLibrary("libusb0.dll")
  • 若成功,使用 GetProcAddress 获取每个导出函数的地址。
  • 若某个函数缺失(如旧版本 DLL),对应指针保持 NULL
  • 最后调用 if (_usb_init) _usb_init(),即如果 DLL 中存在 usb_init 则调用。

5.3 所有 API 包装

  • 每个公共 API(如 usb_bulk_read)检查对应函数指针是否非空:
    • 若非空,调用之。
    • 若为空,返回 -ENOFILE(或对指针返回 NULL)。

5.4 使用场景

  • 应用程序可在调用 usb_init 前检查 libusb0.dll 是否存在,若不存在则给出友好提示。
  • 支持多个版本的 libusb0.dll 共存,运行时决定使用哪个。
  • 注意libusb_dyn.c 是独立的,与 windows.c 中的实现互斥 。通常发布版本使用 windows.c 直接编译进 DLL,而 libusb_dyn.c 用于构建代理库(如 libusb_dyn.dll 或静态库),供第三方软件使用。

6. 技术亮点与安全考虑

  • 原子性操作 :过滤驱动的插入/移除伴随 SurpriseRemovalOK 的删除,确保设备必须重启以生效。
  • 权限检查usb_install_admin_check 验证当前进程是否为管理员,非管理员拒绝操作。
  • WoW64 检测usb_install_iswow64 检测 32 位进程是否运行在 64 位系统上,并提示使用正确的架构版本。
  • 幂等性:插入过滤驱动时先检查是否已存在,避免重复添加。
  • 回滚支持 :移除设备过滤时,若匹配到设备,会尝试恢复设备状态;INF 卸载支持 DiRollbackDriver

7. 总结

本篇揭示了 libusb-win32 强大的系统集成能力:

  • 通过 registry.c 精细操控 Windows 设备类和设备过滤驱动。
  • install.c 提供了一个统一的命令行/图形化前端,支持服务安装、INF 部署、过滤驱动管理的全生命周期。
  • 动态加载模块 libusb_dyn.c 增强了部署灵活性,允许应用按需加载 USB 功能。
相关推荐
sxd20013 小时前
Vmware和multicast
linux·windows·vmware·无线桥接·multicast
智购科技无人售货机工厂5 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
执子星海6 小时前
Registry Win32 API详解
c++·windows·microsoft·visualstudio·微软
defrag2576 小时前
Win9x下用Win32程序调用Win16函数
windows
me8326 小时前
【Tool】Windows 计划任务 + VBScript 弹窗提醒:从零到一的完整指南
windows
2601_962201727 小时前
Java进阶,集合,Colllection,常见数据结构
java·数据结构·windows
loong_XL9 小时前
Windows WSL2 Ubuntu 搭建 Xvfb 虚拟桌面环境,完美支持多 Agent 隔离
linux·windows·ubuntu
DogDaoDao18 小时前
Windows 开发提效工具全景指南:60+ 工具的工程化分层配置
windows·git·程序员·开发工具·powershell·everything·msys2
水饺编程1 天前
第5章,[Win32 章节] :Polygon 函数和多边形填充模式
c语言·c++·windows·visual studio