验证 Windows 驱动程序

使用 InfVerif、Driver Verifier Driver Isolation Checks 和 ApiValidator 工具来测试驱动程序包是否符合 Windows 驱动程序开发入门中所述的 Windows 驱动程序要求。

InfVerif

InfVerif 是一种工具,用于验证 INF 语法,并检查 INF 是否符合要求和限制。

使用带有 /w 的 InfVerif 来验证 Windows 驱动程序是否:

如需了解更多详情,请参阅通过命令行运行 InfVerif

InfVerif 使用“/w”参数验证驱动程序隔离要求,如下所示:

infverif.exe /w <INF file> [<INF file>]

如果 InfVerif 在使用 /w 进行验证时未报告任何错误,则说明 INF 满足 Windows 驱动程序的驱动程序包隔离要求。

面向当前版本的 Windows 和早期版本的 Windows

如果 INF 包含最新版本的 Windows 中引入的语法,例如从 Windows 10 版本 1809 开始可用的 INF AddEventProvider 指令,并且还希望面向以前的 Windows 版本,则使用 INF 修饰 来标记特定版本的 INF 条目。 有关演示如何使用操作系统版本修饰的示例代码,请参阅将平台扩展与操作系统版本相结合

使用 OS 版本修饰的 INF 文件可能会导致 InfVerif 失败,因为以前 Windows 版本可能不支持驱动程序隔离要求。 要验证此类 INF,可以使用“/wbuild”参数指定应应用驱动程序隔离检查的最低 Windows 版本。 例如,使用 AddEventProvider 指令的 INF 文件可能使用以下内容,以便仅将驱动程序隔离检查应用于 Windows 10 版本 1809 及更高版本:

infverif.exe /w /wbuild NTAMD64.10.0.0.17763 <INF file> [<INF file>]

驱动程序验证器驱动程序隔离检查

要符合 Windows 驱动程序的资格,驱动程序包必须满足驱动程序包隔离要求。 从 Windows 11 开始,驱动程序验证程序 (DV) 可以监视内核二进制文件,以获取独立驱动程序包不允许的注册表和文件系统读取和写入。

你可以在内核调试程序中查看冲突,也可以查看系统事件日志中报告的冲突,也可以将 DV 配置为在发生冲突时停止系统并生成包含详细信息的内存转储。 可通过第一种和第二种方法开始驱动程序开发,然后在驱动程序快要完成时,切换到第二种方法。

要启用驱动程序隔离检查,以便通过内核调试程序和系统事件日志报告它们但不检查系统 bug,请执行以下操作:

verifier /rc 33 36 /driver myDriver.sys [myDriver2.sys ...]

要配置 DV,使它在发生驱动程序隔离违规行为时进行 bug 检查,请使用以下语法:

verifier /onecheck /rc 33 36 /driver myDriver1.sys [myDriver2.sys ...]

无论选择哪种监视方法,都需要重新启动才能启用验证设置。 要通过命令行执行此操作,请指定:

shutdown /r /t 0

下面是内核调试程序中显示的一些错误消息示例:

示例:ZwCreateKey 提供完整的绝对路径:

DRIVER_ISOLATION_VIOLATION: <driver name>: Registry operations should not use absolute paths. Detected creation of unisolated registry key \Registry\Machine\SYSTEM

示例:ZwCreateKey 提供相对于句柄的路径,该句柄不是来自批准的 API:

DRIVER_ISOLATION_VIOLATION: <driver name>: Registry operations should only use key handles returned from WDF or WDM APIs. Detected creation of unisolated registry key \REGISTRY\MACHINE\SYSTEM\SomeKeyThatShouldNotExist

请考虑在驱动程序上启用 DV 驱动程序隔离检查的情况下运行设备基础功能测试,以帮助及早捕获驱动程序隔离违规。

注意

DV 不希望向用户报告大量相同的冲突,因此它具有一种限制机制,可以限制报告每个唯一的错误。 从 Windows 11 24H2 开始,为了确保你看到一项测试或一系列测试的任何给定运行的驱动程序隔离违规完整集合,你可以请求使用以下命令重置驱动程序隔离违规的限制:

verifier /dif 33 /action 1

如果在运行测试之前未执行此操作,则在测试运行过程中,如果测试启动之前已发生这些冲突,则可能不会看到某些冲突。

WHCP 符合性

目前,Windows 硬件兼容性计划 (WHCP) 程序不要求进行完全驱动程序包隔离。 但是,从 Windows 11 24H2 开始,WHCP 程序开始包括与驱动程序隔离相关的要求。 要启用与 Hardware Lab Kit (HLK) 相同的驱动程序包隔离验证级别作为强制实施 WHCP 要求的一部分,请使用以下语法:

Verifier /dif 33 /33 whcp /driver myDriver.sys [myDriver2.sys ...]

使用此语法时,仍会报告所有驱动程序隔离冲突,但当前未为 HLK 强制执行的要求将报告为警告而不是错误。 如果你使用 /onecheck 启用驱动程序隔离检查以在发生违规时生成 bug 检查,则列出的警告不会导致 HLK 失败,并且不会导致系统进行 bug 检查。

使用内核调试程序查看事件时,被视为的错误将带有 DRIVER_ISOLATION_VIOLATION 前缀,而被视为的警告将带有 DRIVER_ISOLATION_WARNING 前缀。

在系统事件日志中查看事件时,具有 0 的 ErrorLevel 属性的事件被视为错误,具有另一个 ErrorLevel 值的事件不被视为错误。 有关详细信息,请参阅下面的“查看系统事件日志中的冲突”部分。

在系统事件日志中查看冲突

系统在提供程序 Microsoft-Windows-Kernel-XDV 的系统事件日志中报告事件 ID 为“4”的驱动程序验证程序冲突。 在 Windows 11 24H2 及更高版本上,事件将包含 ErrorLevel 值。 生成冲突时,根据主动驱动程序隔离模式(完全驱动程序隔离符合性与 WHCP 隔离符合性),ErrorLevel 值为 0 的事件被视为错误。 具有其他 ErrorLevel 值的事件不会被视为错误。 例如,具有以下属性的事件会被视为错误:

EventData
	RuleId	0x210001
	ErrorMessage	Registry operations should not use absolute paths. Detected opening of unisolated registry key \Registry\Machine\System\CurrentControlSet\Services\ExampleDriver\Parameters
	Module	\SystemRoot\System32\drivers\ExampleDriver.sys
	Irql	0
	ErrorLevel	0x0

而具有以下属性的事件不会被视为错误:

EventData
	RuleId	0x210001
	ErrorMessage	Registry operations should only use key handles returned from WDF or WDM APIs. Detected querying of value under unisolated registry key \REGISTRY\MACHINE\SYSTEM\ControlSet001\Control
	Module	\SystemRoot\System32\drivers\ExampleDriver.sys
	Irql	0
	ErrorLevel	0xf4240

如果你使用事件查看器应用程序查看系统事件日志,则可以通过单击“筛选当前日志”来筛选应用程序右侧的菜单来筛选日志视图。 在弹出的对话框中,如果你转到“XML”选项卡并手动编辑查询,则可以使用此查询筛选系统事件日志以仅显示应视为错误的 DV 冲突:

<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System/Provider[@Name='Microsoft-Windows-Kernel-XDV'] and System[(EventID='4')] and (EventData/Data[@Name='ErrorLevel']='0')]</Select>
  </Query>
</QueryList>

如果要筛选事件日志视图以显示在一定时间后(例如,测试通过开始之后)应被视为错误的所有 DV 冲突,你可以执行以下操作:

<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System/Provider[@Name='Microsoft-Windows-Kernel-XDV'] and System[(EventID='4')] and System/TimeCreated[@SystemTime&gt;='2024-01-24T23:00:00.0Z'] and (EventData/Data[@Name='ErrorLevel']='0')]</Select>
  </Query>
</QueryList>

或者,如果你更喜欢可以加载到视图的 XML 文件,则可以使用 wevtutil 根据相同的查询生成此类 XML:

wevtutil qe System /q:"*[System/Provider[@Name='Microsoft-Windows-Kernel-XDV'] and System[(EventID='4')] and (EventData/Data[@Name='ErrorLevel']='0')]" /e:Events > DriverVerifierErrors.xml

wevtutil qe System /q:"*[System/Provider[@Name='Microsoft-Windows-Kernel-XDV'] and System[(EventID='4')] and System/TimeCreated[@SystemTime>='2024-01-24T23:00:00.0Z'] and (EventData/Data[@Name='ErrorLevel']='0')]" /e:Events > DriverVerifierErrors.xml

KMDF 驱动程序

当 KMDF 驱动程序使用 WDF API 访问注册表(例如 WdfRegistryCreateKeyWdfRegistryOpenKeyWdfRegistryQueryValue)时,注册表访问将通过 wdf01000.sys 进行,而不是直接访问 KMDF 驱动程序二进制文件。 要查看 KMDF 驱动程序二进制文件导致的冲突,除了 KMDF 驱动程序二进制文件外,还请在 wdf01000.sys 上启用驱动程序隔离检查。 请注意,执行此操作时,会看到系统上所有 KMDF 驱动程序的冲突,这些驱动程序使用 WDF 进行注册表访问。

ApiValidator

ApiValidator 工具用于验证二进制文件调用的 API 是否对 Windows 驱动程序是有效的。 如果二进制文件调用的 API 在 Windows 驱动程序的有效 API 集之外,此工具就会返回错误。 此工具属于适用于 Windows 10 的 WDK。

ApiValidator 用于验证驱动程序是否支持 API 分层,这是 Windows 驱动程序的要求之一。 有关完整的要求列表,请参阅 Windows 驱动程序开发入门

在 Visual Studio 中运行 ApiValidator

如果驱动程序项目的“目标平台”属性设置为“Windows 驱动程序”,Visual Studio 就会自动运行 ApiValidator 作为生成后步骤。

要查看 ApiValidator 显示的所有消息,请依次转到工具->选项->项目和解决方案->生成并运行,并将 MSBuild 项目生成输出详细程度设置为详细。 从命令行生成时,请将开关 /v:detailed/v:diag 添加到生成命令以提高详细级别。

对于 umdf2_fx2 驱动程序示例,API 验证错误如下所示:

Warning  1   warning : API DecodePointer in kernel32.dll is not supported. osrusbfx2um.dll calls this API.   C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 2   warning : API DisableThreadLibraryCalls in kernel32.dll is not supported. osrusbfx2um.dll calls this API.   C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 3   warning : API EncodePointer in kernel32.dll is not supported. osrusbfx2um.dll calls this API.   C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 4   warning : API GetCurrentProcessId in kernel32.dll is not supported. osrusbfx2um.dll calls this API. C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 5   warning : API GetCurrentThreadId in kernel32.dll is not supported. osrusbfx2um.dll calls this API.  C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 6   warning : API GetSystemTimeAsFileTime in kernel32.dll is not supported. osrusbfx2um.dll calls this API. C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 7   warning : API IsDebuggerPresent in kernel32.dll is not supported. osrusbfx2um.dll calls this API.   C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 8   warning : API IsProcessorFeaturePresent in kernel32.dll is not supported. osrusbfx2um.dll calls this API.   C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Warning 9   warning : API QueryPerformanceCounter in kernel32.dll is not supported. osrusbfx2um.dll calls this API. C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe    osrusbfx2um
Error   10  error MSB3721: The command ""C:\Program Files (x86)\Windows Kits\10\bin\x64\ApiValidator.exe" -DriverPackagePath:"C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\Debug\\" -SupportedApiXmlFiles:"C:\Program Files (x86)\Windows Kits\10\build\universalDDIs\x86\UniversalDDIs.xml" -ApiExtractorExePath:"C:\Program Files (x86)\Windows Kits\10\bin\x64"" exited with code -1.    C:\Program Files (x86)\Windows Kits\10\build\WindowsDriver.common.targets   1531    5   osrusbfx2um

修复验证错误

  1. 如果已将旧的桌面 UMDF 驱动程序项目切换为 Windows 驱动程序,请验证在生成二进制文件时是否添加了正确的库。 选择并按住(或右键单击)项目,然后选择属性。 导航到“链接器”-“输入”>其他依赖项应包含:

    %AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib
    

    要查看针对 OneCore SKU 的其他链接器选项,请参阅针对 OneCore 生成

  2. 一次删除或替换一个不允许的 API 调用,并重新运行此工具,直到没有错误。

  3. 在某些情况下,可以使用仅用于桌面的 DDI 参考页列出的备用 DDI 替换这些调用。 如果没有适合的替换项,可能必须编写解决方法代码。 如果需要,可以从 WDK 中的驱动程序模板开始编写新的 Windows 驱动程序。

如果看到如下所示的错误,请参阅针对 OneCore 生成中的指南。

ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSEnumerateSessionsW' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: Error: FlexLinkTest.exe has a dependency on 'wtsapi32.dll!WTSFreeMemory' but is missing: IsApiSetImplemented("ext-ms-win-session-wtsapi32-l1-1-0")
ApiValidation: NOT all binaries are Universal

从命令提示符运行 ApiValidator

也可以从命令提示符运行 Apivalidator.exe。 在 WDK 安装中,转到 C:\Program Files (x86)\Windows Kits\10\bin<arch>C:\Program Files (x86)\Windows Kits\10\build\universalDDIs<arch>

重要说明:

  • ApiValidator 需要以下文件:ApiValidator.exe、Aitstatic.exe、Microsoft.Kits.Drivers.ApiValidator.dll 和 UniversalDDIs.xml。
  • UniversalDDIs.xml 必须与要验证的二进制文件体系结构相匹配(例如,对于 x64 驱动程序,使用 x64 UniversalDDI.xml)
  • ApiValidator 一次只测试一个体系结构
  • 有关其他信息,请参阅下面的“已知 ApiValidator 问题”

使用以下语法:

Apivalidator.exe -DriverPackagePath: <driver folder path> -SupportedApiXmlFiles: (path to XML files containing supported APIs for Windows drivers)

例如,要验证 WDK 中的“活动”示例调用的 API,应首先在 Visual Studio 中生成示例。 然后,打开命令提示符,并转到包含此工具的目录(例如,C:\Program Files (x86\Windows Kits\10\bin\x64)。 输入以下命令:

apivalidator.exe -DriverPackagePath:"C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2\_fx2\Debug" -SupportedApiXmlFiles:"c:\Program Files (x86)\Windows Kits\10\build\universalDDIs\x64\UniversalDDIs.xml"

此命令将生成以下输出:

ApiValidator.exe: Warning: API DecodePointer in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API DisableThreadLibraryCalls in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API EncodePointer in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API GetCurrentProcessId in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API GetCurrentThreadId in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API GetSystemTimeAsFileTime in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API IsDebuggerPresent in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API IsProcessorFeaturePresent in kernel32.dll is not supported. osrusbfx2um.dll calls this API.
ApiValidator.exe: Warning: API QueryPerformanceCounter in kernel32.dll is not supported. osrusbfx2um.dll calls this API.

ApiValidator.exe Driver located at C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\Debug is NOT a Universal Driver

排除 ApiValidator 故障

如果 ApiValidator.exe 输出格式不正确错误(如下所示):

Error      1              error : AitStatic output file has incorrect format or analysis run on incorrect file types.     C:\Program Files (x86)\Windows Kits\10\src\usb\umdf2_fx2\driver\ApiValidator.exe            osrusbfx2um

请使用此解决方法:

  1. 打开“项目”属性,导航到“常规”,将“输出目录”重命名为以下内容:

    $(SolutionDir)$(Platform)\$(ConfigurationName)\
    
  2. 重新生成解决方案。

已知 ApiValidator 问题

  • ApiValidator 不能在 Arm64 上运行,因为 AitStatic 不能在 Arm64 上运行。
  • Arm64 二进制文件可以在 x64 计算机上测试,但不能在 x86 计算机上测试。
  • ApiValidator 可以在 x86 上运行,以测试 x86 二进制文件和 Arm 二进制文件。
  • ApiValidator 可以在 x64 上运行,以测试 x86、x64、Arm 和 Arm64 二进制文件。