)
子文档三核心 API 模块libwdi.clibwdi.c是 libwdi 库的中枢神经系统它实现了所有对外 API 函数并协调其他模块完成设备枚举、驱动准备和安装。该文件约 1500 行是核心库中最大的源文件。对外 API 总览libwdi 对外暴露了以下 9 个函数在libwdi.h中声明wdi_strerror将错误码转换为字符串。wdi_is_driver_supported检查某驱动类型是否被当前库支持并返回版本信息。wdi_is_file_embedded检查某个文件是否嵌入在资源中。wdi_get_vendor_name根据 VID 返回厂商名称通过vid_data.c。wdi_create_list枚举 USB 设备返回设备链表。wdi_destroy_list释放设备链表。wdi_prepare_driver准备驱动文件生成 INF、CAT提取二进制。wdi_install_driver安装驱动调用提权安装器。wdi_install_trusted_certificate安装嵌入的证书到受信任发布者存储。wdi_set_log_level、wdi_register_logger、wdi_unregister_logger、wdi_read_logger日志控制函数。wdi_get_wdf_version返回 WDF 版本号。内部关键函数与流程1.wdi_create_list设备枚举该函数是设备发现的核心其实现步骤调用SetupDiGetClassDevs(NULL, USB, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES)获取所有已连接的 USB 设备信息集。使用SetupDiEnumDeviceInfo遍历每个设备。对于每个设备读取SPDRP_HARDWAREID、SPDRP_COMPATIBLEIDS、SPDRP_SERVICE、SPDRP_DRIVER驱动服务名和驱动版本。通过CM_Get_Device_ID从 Cfgmgr32.dll获取设备实例 ID。解析硬件 ID 字符串提取 VID、PID 和 MI接口号。读取设备描述优先使用DEVPKEY_Device_BusReportedDeviceDescWindows 8回退到SPDRP_DEVICEDESC。过滤掉 USB 集线器通过检查服务名是否匹配预定义的集线器驱动列表除非用户要求包含集线器。构建wdi_device_info链表每个节点包含 VID、PID、MI、描述、驱动名、硬件 ID、设备 ID、兼容 ID、上层过滤器、驱动版本等字段。若设备为复合设备则在描述后添加(Interface X)后缀以区分不同接口。并发控制该函数使用CreateMutex以函数名为互斥体名称确保同一时刻只有一个线程执行设备枚举避免资源竞争。2.wdi_prepare_driver驱动准备这是驱动安装前的准备阶段负责生成 INF 和 CAT 文件并提取所有必需的二进制文件。流程如下验证参数设备信息、目标路径、INF 名称。若未指定路径使用%TEMP%环境变量作为默认提取目录。调用check_dir确保目标目录存在若不存在则创建。调用extract_binaries将嵌入的所有资源文件提取到目标目录包括驱动 .sys/.dll、安装器 .exe 等。若驱动类型为WDI_USER自定义驱动则提取完成后直接返回不生成 INF/CAT。否则根据驱动类型选择对应的 INF 模板如winusb.inf.in和 CAT 模板。填充inf_entities令牌数组包括设备描述、硬件 ID、设备接口 GUID、制造商、驱动日期、驱动版本、WDF 版本等。调用wdi_tokenize_resource内部通过tokenizer将模板中的#TOKEN#替换为实际值生成 INF 内容。将生成的 INF 内容以 UTF-16 编码写入文件并添加 BOM。若用户未禁用 CAT 生成且进程具有管理员权限则生成 CAT 文件调用wdi_tokenize_resource处理 CAT 模板得到文件列表。调用CreateCat在pki.c中创建 CAT 文件包含所有驱动文件的 SHA-1 哈希。调用SelfSignFile在pki.c中使用自签名证书对 CAT 进行 Authenticode 签名。若options-disable_signing为 FALSE还会自动将自签名证书安装到Root和TrustedPublisher存储区。3.wdi_install_driver安装调度该函数负责启动提权安装器并等待其完成。它接受一个options参数其中hWnd字段若不为 NULL则表示调用方希望显示进度条对话框。若hWnd为 NULL直接调用install_driver_internal同步执行。若hWnd非 NULL调用run_with_progress_bar在libwdi_dlg.c中该函数会创建一个模态进度对话框在后台线程中执行install_driver_internal并将进度通过管道反馈给对话框。install_driver_internal是实际安装执行函数其核心操作创建命名管道\\.\pipe\libwdi-installer作为通信通道。确定当前系统架构x86/x64/ARM64选择对应的安装器可执行文件installer_x86.exe、installer_x64.exe或installer_arm64.exe这些文件已在wdi_prepare_driver阶段提取到目标目录。若当前进程无管理员权限通过ShellExecuteEx配合runas动词启动安装器触发 UAC 提权。若已有管理员权限直接CreateProcess启动安装器并传递 INF 名称作为命令行参数。进入循环读取管道消息。若收到IC_SET_STATUS消息提取并返回错误码若收到IC_PRINT_MESSAGE或IC_SYSLOG_MESSAGE通过日志系统输出若收到IC_GET_DEVICE_ID等请求将设备信息写入管道。等待安装器进程结束检查退出码。辅助函数check_dir检查目录是否存在若不存在则创建通过SHCreateDirectoryEx递归创建并设置安全描述符使目录归属于当前用户而非管理员避免权限问题。fopen_as_userU使用CreateFile创建文件并设置安全描述符使文件所有者与当前用户一致确保后续操作如写入日志不会因权限不足而失败。get_version_info从嵌入的驱动文件如winusbcoinstaller2.dll中提取版本信息用于 INF 中的DriverVer字段。guid_to_string将 GUID 转换为带大括号的字符串格式。错误处理与日志所有内部函数广泛使用wdi_dbg、wdi_info、wdi_warn、wdi_err宏记录日志这些宏最终调用wdi_log在logging.c中将日志输出到控制台或注册的窗口。错误码通过wdi_strerror转换为用户可读的字符串。