Wdf框架:FxDriverEntry----驱动程序的入口函数

本文解析了FxDriverEntry及其内部FxDriverEntryWorker函数的功能。详细介绍了FxDriverEntryWorker如何通过WdfVersionBind设置Wdf框架信息,并关联WdfDriverGlobals变量。最终调用DriverEntry作为驱动程序的入口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在前面的文章<Wdf框架中WdfDriverGlobals对象的创建>中简单的提到过WdfVersionBind函数的作用,但是没有来得及分析这个函数的调用处。今天得空,借这篇文章写下WdfVersionBind函数的调用者:FxDriverEntry。

    在写这篇文章前,我被WdfLdr.sys的名字误导,以为这个sys文件是内核的加载器,用于加载整个内核启动(Ldr是Loader的缩写)。所以,当时我很粗浅的认为这个驱动只在系统引导阶段才被调用,之后就靠边站了。然而事实却是,当系统启动后,只要加载基于WDF框架的驱动,就会中断在WdfVersionBind函数上。以登录到系统后,加载WinDDK中WdfSimple.sys驱动(toast驱动的WDF版本)为例:

kd> bp WDFLDR!WdfVersionBind
kd> g
Breakpoint 1 hit
WDFLDR!WdfVersionBind:
fffff802`9598d2d0 488bc4          mov     rax,rsp
kd> kb
RetAddr           : Args to Child                                                           : Call Site
fffff802`98a414a3 : ffff8881`fc86f000 ffff8881`fbf2c750 00000000`00000000 ffff327f`24cdc304 : WDFLDR!WdfVersionBind 
fffff802`5ab053e9 : 00000000`00000000 ffffd381`a819d460 ffff8881`fbf2c750 ffffffff`00000000 : wdfsimple!FxDriverEntryWorker+0x7f
fffff802`5abab13e : 00000000`00000000 00000000`00000000 00000000`00000004 ffffc285`00000004 : nt!IopLoadDriver+0x521
fffff802`5ab04495 : ffffd381`a819da01 ffffd381`a819d6c8 00000000`c0000000 ffffd381`a819d6a4 : nt!PipCallDriverAddDeviceQueryRoutine+0x1b6
fffff802`5ab03e93 : 00000000`00000000 00000000`00000014 00000000`c0000034 ffff8881`fbd6cd30 : nt!PnpCallDriverQueryServiceHelper+0xbd
fffff802`5ab0323d : ffff8881`fbd6cd30 ffffd381`a819d8e0 ffff8881`fbd6cd30 00000000`00000000 : nt!PipCallDriverAddDevice+0x317
fffff802`5acd5eda : ffff8881`fbd6cd30 00000000`00000001 ffffd381`a819db19 fffff802`5ab0397b : nt!PipProcessDevNodeTree+0x1cd
fffff802`5a824d9e : 00000001`00000003 00000000`00000000 ffffd381`a819daf0 00000000`00000000 : nt!PiRestartDevice+0xba
fffff802`5a6e0d79 : ffff8881`f97af040 fffff802`5a9a5320 fffff802`5aa46280 fffff802`5aa46280 : nt! ?? ::FNODOBFM::`string'+0x42bde
fffff802`5a7254bd : fffff802`5a9cb180 00000000`00000080 ffff8881`f88af6c0 ffff8881`f97af040 : nt!ExpWorkerThread+0xe9
fffff802`5a7d8456 : fffff802`5a9cb180 ffff8881`f97af040 fffff802`5a72547c 43ffff41`04080003 : nt!PspSystemThreadStartup+0x41
00000000`00000000 : ffffd381`a819e000 ffffd381`a8198000 00000000`00000000 00000000`00000000 : nt!KxStartSystemThread+0x16
图1:

图1结合调试输出显示,在登录系统后,加载驱动也会中断到WdfVersionBind。由此可见,OS会为每个Wdf驱动设置WDF框架的版本号等信息。这些内容属于上一篇文章的延伸,我要借助它引出这篇文章的主题:FxDriverEntry。

    上面的函数调用栈中只有frame 1与我们的驱动模块有关,但名字却是FxDriverEntryWorker。整份Sample源码中没有调用这个函数,可见,它是由编译器插入的。这就又引出2个疑问:

1.驱动入口DriverEntry在FxDriverEntryWorker函数执行完后调用;

2.反之,驱动入口DriverEntry在FxDriverEntryWorker函数之前执行。

如果属于情况2,可能我要重启或者重新加载驱动。怕麻烦的我最终选择用IDA加载wdfsimple.sys分析了函数流程。下图是在IDA中对DriverEntry函数执行"XRefs graph to"后生成的调用图,调用次序依次为FxDriverEntry->FxDriverEntryWorker->DriverEntry:


    FxDriverEntry只是一个包装函数,真正的工作全交由FxDriverEntryWorker完成。下面的代码是IDA对FxDriverEntryWorker函数反汇编后生成的伪代码。FxDriverEntryWorker首先为WdfSimple驱动对象DriverObject调用WdfVersionBind,设置Wdf框架信息并关联WdfDriverGlobals这个重要的全局变量。如果WdfVersionBind调用成功,则会调用DriverEntry进入我们程序的入口。这才是原来WDM模型中驱动程序的入口。

int __fastcall FxDriverEntryWorker(_DRIVER_OBJECT *DriverObject, _UNICODE_STRING *RegistryPath)
{
  _UNICODE_STRING *v2; // rsi@1
  _DRIVER_OBJECT *v3; // rdi@1
  int result; // eax@2
  int v5; // ebx@4
  void (__cdecl *v6)(_DRIVER_OBJECT *); // rax@7

  v2 = RegistryPath;
  v3 = DriverObject;
  if ( DriverObject )
  {
    result = WdfVersionBind_0(v3, &WdfDriverStubRegistryPath, &WdfBindInfo, &WdfDriverGlobals);
    if ( result >= 0 )
    {
      v5 = FxStubBindClasses(&WdfBindInfo);
      if ( v5 < 0 || (FxStubInitTypes(), v5 = DriverEntry(v3, v2), v5 < 0) )  //WdfVersionBind执行成功后,调用DrvierEntry
      {
      }
    本篇完



### PyCharm 打开文件显示全的解决方案 当遇到PyCharm打开文件显示全的情况时,可以尝试以下几种方法来解决问题。 #### 方法一:清理缓存并重启IDE 有时IDE内部缓存可能导致文件加载异常。通过清除缓存再启动程序能够有效改善此状况。具体操作路径为`File -> Invalidate Caches / Restart...`,之后按照提示完成相应动作即可[^1]。 #### 方法二:调整编辑器字体设置 如果是因为字体原因造成的内容显示问题,则可以通过修改编辑区内的文字样式来进行修复。进入`Settings/Preferences | Editor | Font`选项卡内更改合适的字号大小以及启用抗锯齿功能等参数配置[^2]。 #### 方法三:检查项目结构配置 对于某些特定场景下的源码视图缺失现象,可能是由于当前工作空间未能正确识别全部模块所引起。此时应该核查Project Structure的Content Roots设定项是否涵盖了整个工程根目录;必要时可手动添加遗漏部分,并保存变更生效[^3]。 ```python # 示例代码用于展示如何获取当前项目的根路径,在实际应用中可根据需求调用该函数辅助排查问题 import os def get_project_root(): current_file = os.path.abspath(__file__) project_dir = os.path.dirname(current_file) while not os.path.exists(os.path.join(project_dir, '.idea')): parent_dir = os.path.dirname(project_dir) if parent_dir == project_dir: break project_dir = parent_dir return project_dir print(f"Current Project Root Directory is {get_project_root()}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值