云计算百科
云计算领域专业知识百科平台

Windows 驱动实例分析系列:libwdi 驱动分析 - libwdi 篇(四)

子文档四:令牌生成器(tokenizer)与 INF/CAT 模板处理

tokenizer.c 实现了一个轻量级模板引擎,是 libwdi 动态生成 INF 和 CAT 文件的核心组件。它不依赖任何外部库,仅使用标准 C 字符串操作,设计简洁高效。

设计理念

模板文件(如 winusb.inf.in)中包含形如 #TOKEN_NAME# 的占位符。tokenizer 在运行时扫描模板内容,将占位符替换为实际值(如设备描述、硬件 ID 等),生成最终的文件内容。这种设计将静态模板与动态数据分离,使得 INF 和 CAT 文件无需针对每个设备单独编写。

核心数据结构

typedef struct _token_entity_t {
const char* match; // 要匹配的令牌名(不含前后缀)
char replace[1024]; // 替换后的字符串
} token_entity_t;

libwdi.c 中定义了一个 inf_entities 数组,包含 16 个令牌实体,分别对应 INF 模板中的 #DEVICE_DESCRIPTION#、#DEVICE_HARDWARE_ID#、#DEVICE_INTERFACE_GUID# 等。

tokenize_string 函数实现

该函数是令牌引擎的核心,其算法如下:

  • 初始化输出缓冲区,大小为输入大小 + 1024。
  • 在输入字符串中搜索前缀(默认为 #)。
  • 若找到前缀,则提取从前缀后到后缀(默认为 #)之间的子串作为令牌名。
  • 遍历 token_entities 数组,查找匹配的令牌名。
  • 若找到匹配,将匹配的 replace 字符串追加到输出缓冲区。
  • 若未找到匹配,原样保留 #TOKEN#。
  • 继续搜索下一个令牌,直到输入字符串结束。
  • 支持递归替换(recursive 参数),即替换后的内容可能包含新的令牌,会再次进行替换,直到无更多令牌为止(但 libwdi 中通常只执行一轮)。
  • 性能优化:grow_strcpy 函数动态扩展输出缓冲区,避免固定大小限制。每次扩展的大小为所需大小 + 1024,减少 realloc 调用次数。

    使用场景

  • INF 生成:wdi_prepare_driver 通过 wdi_tokenize_resource 调用 tokenize_string 处理 winusb.inf.in 等模板,传入 inf_entities 数组,得到完整的 INF 内容,然后以 UTF-16 编码写入磁盘。
  • CAT 生成:pki.c 中的 CreateCat 函数内部也会使用令牌引擎?实际上,CAT 模板仅包含文件列表(每行一个文件名),而 CreateCat 直接解析模板内容(通过 strtok)获取文件列表,并未使用令牌引擎,因为 CAT 模板中不需要动态替换(除了一些版本信息,但 libwdi 采用固定格式)。不过,wdi_prepare_driver 在生成 CAT 文件前也会调用 wdi_tokenize_resource 处理 CAT 模板,以替换 #WDF_VERSION# 等令牌,确保 CAT 中的 WDF 版本与 INF 一致。
  • 错误处理

    tokenize_string 返回负数表示错误(如 -ERROR_BAD_ARGUMENTS),0 表示输入为空,正数表示输出长度。调用方检查返回值,若小于等于 0 则视为失败。

    优点与局限

    • 简单可靠:无递归下降解析,代码量小(约 200 行),易于调试。
    • 灵活:可自定义前缀和后缀(默认 #)。
    • 局限性:不支持条件替换、循环等高级功能,但对于 INF 和 CAT 生成已足够。
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Windows 驱动实例分析系列:libwdi 驱动分析 - libwdi 篇(四)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!