WDF驱动开发之DriverEntry原理

WDF驱动开发之DriverEntry原理

本文我们从WDF源码出发,分析一下在WDF框架下面驱动的加载和卸载过程;因为WDF框架代码已经开源,所以我们可以直接通过源码进行调试。

  1. 加载符号
kd> .reload 
Connected to Windows 10 18362 x86 compatible target at (Mon Jul 22 08:36:19.764 2019 (UTC + 8:00)), ptr64 FALSE
Loading Kernel Symbols
.......................................

Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.

........................
....................
Loading User Symbols

kd> !lmi wdf01000
Loaded Module Info: [wdf01000] 
         Module: Wdf01000
   Base Address: 82586000
     Image Name: Wdf01000.sys
   Machine Type: 332 (I386)
     Time Stamp: 9edafe3c (This is a reproducible build file hash, not a true timestamp)
           Size: 98000
       CheckSum: 97ae3
Characteristics: 102  
Debug Data Dirs: Type  Size     VA  Pointer
             CODEVIEW    25, 82d48,   81348 RSDS - GUID: {114C18E8-C30B-E2A2-40A5-210342879CB9}
               Age: 1, Pdb: Wdf01000.pdb
                 POGO   548, 82d70,   81370 [Data not mapped]
                REPRO    24, 832b8,   818b8 Reproducible build[Data not mapped]
     Image Type: MEMORY   - Image read successfully from loaded memory.
    Symbol Type: PDB      - Symbols loaded successfully from symbol server.
                 f:\symbols\Wdf01000.pdb\114C18E8C30BE2A240A5210342879CB91\Wdf01000.pdb
       Compiler: C - front end [19.15 bld 26715] - back end [19.15 bld 26715]
    Load Report: private symbols & lines, not source indexed 
                 f:\symbols\Wdf01000.pdb\114C18E8C30BE2A240A5210342879CB91\Wdf01000.pdb
  1. 设置符号路径
kd> .srcpath+ F:\Windows-Driver-Frameworks-master\src\framework
Source search path is: SRV*;F:\Windows-Driver-Frameworks-master\src\framework

此时源码调试设置成功
在这里插入图片描述

1. 入口函数

首先在工程中,设置了如下的入口函数
在这里插入图片描述

2. FxDriverEntry 函数流程

这个函数取代了WDM框架的DriverEntry,在WDF框架的代码中,声明如下:
在这里插入图片描述
发现没有开源,逆向的结果如下:

NTSTATUS __stdcall FxDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
  return FxDriverEntryWorker(DriverObject, RegistryPath);
}

NTSTATUS __stdcall FxDriverEntryWorker(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
  NTSTATUS result; // eax MAPDST

  if ( !DriverObject )
    return DriverEntry(0, RegistryPath);
  WdfDriverStubDriverObject = DriverObject;     // 全局驱动对象变量
  *(_DWORD *)&WdfDriverStubRegistryPath.Length = 0x2080000;// 全局注册表路径变量
  WdfDriverStubRegistryPath.Buffer = WdfDriverStubRegistryPathBuffer;
  RtlCopyUnicodeString(&WdfDriverStubRegistryPath, RegistryPath);
  result = WdfVersionBind((int)DriverObject, (int)&WdfDriverStubRegistryPath, (int)&WdfBindInfo, (int)&WdfDriverGlobals);// 调用绑定
  if ( result >= 0 )
  {
    WdfDriverMiniportUnloadOverride = (void (__stdcall *)())*((_DWORD *)WdfFunctions_01015 + 0xC9);
    result = FxStubBindClasses(&WdfBindInfo);
    if ( result < 0
      || (result = FxStubInitTypes(), result < 0)
      || (result = DriverEntry(DriverObject, RegistryPath), result < 0) )// 驱动的入口
    {
      FxStubDriverUnloadCommon();
    }
    else
    {
      if ( WdfDriverGlobals->DisplaceDriverUnload )
      {
        if ( DriverObject->DriverUnload )
          WdfDriverStubDisplacedDriverUnload = DriverObject->DriverUnload;// 保存驱动设置的卸载例程
        DriverObject->DriverUnload = FxStubDriverUnload;// 卸载例程
      }
      else if ( WdfDriverGlobals->DriverFlags & 2 )
      {
        WdfDriverMiniportUnloadOverride = (void (__stdcall *)())FxStubDriverMiniportUnload;
      }
      result = 0;
    }
  }
  return result;
}

这里其实逻辑很简单,主要三个流程:

  1. 初始化WDF框架。
  2. 调用驱动的DriverEntry函数。
  3. 设置框架的卸载例程FxStubDriverUnload.

为什么需要设置FxStubDriverUnload呢? 因为在我们调用DriverEntry之前,初始化了WDF框架,那么同理,卸载驱动的之后(调用我们编写的卸载例程之后),需要调用清理函数清理WDF框架。

代码逻辑如下:

void __stdcall FxStubDriverUnload(_DRIVER_OBJECT *DriverObject)
{
  if ( WdfDriverStubDisplacedDriverUnload && WdfDriverStubDisplacedDriverUnload != FxStubDriverUnload )
    WdfDriverStubDisplacedDriverUnload(DriverObject);  //WdfDriverStubDisplacedDriverUnload = DriverObject->DriverUnload;

  FxStubDriverUnloadCommon();
}

void __stdcall FxStubDriverUnloadCommon()
{
  FxStubUnbindClasses(&WdfBindInfo);
  WdfVersionUnbind(&WdfDriverStubRegistryPath, &WdfBindInfo, WdfDriverGlobals);
}

3. FxDriverEntryWorker函数解析

这个函数在入口的时候,将驱动对象和注册表保存到WDF框架的全局变量中,如下:

kd> dt WdfDriverStubDriverObject
WdfSample!WdfDriverStubDriverObject
0x8df81c30 
   +0x000 Type             : 0n4
   +0x002 Size             : 0n168
   +0x004 DeviceObject     : (null) 
   +0x008 Flags            : 2
   +0x00c DriverStart      : 0xa5fc0000 Void
   +0x010 DriverSize       : 0x7000
   +0x014 DriverSection    : 0x8d7e2318 Void
   +0x018 DriverExtension  : 0x8df81cd8 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\WdfSample"
   +0x024 HardwareDatabase : 0x818f1338 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null) 
   +0x02c DriverInit       : 0xa5fc10f0     long  WdfSample!FxDriverEntry+0
   +0x030 DriverStartIo    : (null) 
   +0x034 DriverUnload     : (null) 
   +0x038 MajorFunction    : [28] 0x8139589c     long  nt!IopInvalidDeviceRequest+0

kd> dt WdfDriverStubRegistryPath
WdfSample!WdfDriverStubRegistryPath
 "\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\WdfSample"
   +0x000 Length           : 0x72
   +0x002 MaximumLength    : 0x208
   +0x004 Buffer           : 0xa5fc3048  "\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\WdfSample"

之后,就会调用WdfVersionBind绑定WDF版本(其实就是初始化WDF框架)。

WdfVersionBind这个函数主要的作用就是调用了Module->LibraryInfo->LibraryRegisterClient(v5, v4, &Context)这个函数的初始化为:

typedef struct _WDF_LIBRARY_INFO {
    ULONG                             Size;
    PFNLIBRARYCOMMISSION              LibraryCommission;  //开始使用
    PFNLIBRARYDECOMMISSION            LibraryDecommission;  //停止使用
    PFNLIBRARYREGISTERCLIENT          LibraryRegisterClient;  //注册客户端
    PFNLIBRARYUNREGISTERCLIENT        LibraryUnregisterClient;  //反注册客户端
    WDF_VERSION                       Version;
} WDF_LIBRARY_INFO, *PWDF_LIBRARY_INFO;

WDF_LIBRARY_INFO  WdfLibraryInfo = {
    sizeof(WDF_LIBRARY_INFO),
    (PFNLIBRARYCOMMISSION)        WDF_LIBRARY_COMMISSION,
    (PFNLIBRARYDECOMMISSION)      WDF_LIBRARY_DECOMMISSION,
    (PFNLIBRARYREGISTERCLIENT)    WDF_LIBRARY_REGISTER_CLIENT,
    (PFNLIBRARYUNREGISTERCLIENT)  WDF_LIBRARY_UNREGISTER_CLIENT,
    { __WDF_MAJOR_VERSION, __WDF_MINOR_VERSION, __WDF_BUILD_NUMBER }
};

3.1 WdfVersionBind参数

这个函数的调用如下:

WdfVersionBind((int)DriverObject, (int)&WdfDriverStubRegistryPath, (int)&WdfBindInfo, (int)&WdfDriverGlobals);

总这里看,主要有两个参数很关键

  1. WdfBindInfo
  2. WdfDriverGlobals

接下来看下这两个参数的具体结构。

3.1.1 WdfBindInfo

这个结构在WDF框架中的定义如下:

typedef struct _WDF_BIND_INFO {
    ULONG              Size;
    PWCHAR             Component;
    WDF_VERSION        Version;
    ULONG              FuncCount;
    __field_bcount(FuncCount*sizeof(WDFFUNC)) WDFFUNC* FuncTable;

#ifndef __FXLDRUM_H__
    PLIBRARY_MODULE    Module;     // Mgmt and diagnostic use only
#else
    PVOID              Module;
#endif
} WDF_BIND_INFO, * PWDF_BIND_INFO;

在内存中的数据如下:

kd> dt WdfBindInfo
WdfSample!WdfBindInfo
   +0x000 Size             : 0x20
   +0x004 Component        : 0xa5fc2050  "KmdfLibrary"
   +0x008 Version          : _WDF_VERSION
   +0x014 FuncCount        : 0x1bc
   +0x018 FuncTable        : 0xa5fc3260  -> 0x8200a0e8     void  Wdf01000!WdfVersion+0
   +0x01c Module           : 0x85b93230 _LIBRARY_MODULE

FxDriverEntryWorker的代码中,我们大概可以猜出这是一个全局变量,那么是否真的是这样的呢?从IDA中我们可以发现确实是如此的:

在这里插入图片描述
在这里插入图片描述

3.1.2 WdfDriverGlobals

在WDF框架中,这个成员定义为如下:

typedef struct _WDF_DRIVER_GLOBALS {

    // backpointer to the handle for this driver
    WDFDRIVER Driver;

    // Flags indicated by the driver during create
    ULONG DriverFlags;

    // Tag generated by WDF for the driver.  Tag used by allocations made on
    // behalf of the driver by WDF.
    ULONG DriverTag;

    CHAR DriverName[WDF_DRIVER_GLOBALS_NAME_LEN];

    // If TRUE, the stub code will capture DriverObject->DriverUnload and insert
    // itself first in the unload chain.  If FALSE, DriverUnload is left alone
    // (but WDF will not be notified of unload and there will be no auto cleanup).
    BOOLEAN DisplaceDriverUnload;

} WDF_DRIVER_GLOBALS, *PWDF_DRIVER_GLOBALS;

内存中,这个结构成员如下:

kd> dt wdf01000!WDF_DRIVER_GLOBALS 8c741520 
   +0x000 Driver           : (null) 
   +0x004 DriverFlags      : 0
   +0x008 DriverTag        : 0
   +0x00c DriverName       : [32]  ""
   +0x02c DisplaceDriverUnload : 0 ''

从名字来看,这个结构体就是用过保存驱动全局数据使用的。

3.2 WdfVersionBind流程

这个函数的主要作用是调用Module->LibraryInfo->LibraryRegisterClient(v5, v4, &Context),看一下这个调用的主要作用。

3.2.1 WDF_LIBRARY_REGISTER_CLIENT
NTSTATUS
WDF_LIBRARY_REGISTER_CLIENT(
    __in  PWDF_BIND_INFO        Info,
    __deref_out   PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
    __deref_inout PVOID             * Context
    )
{
    //变量定义和初始化
    //... ...

    status = FxLibraryCommonRegisterClient(Info, WdfDriverGlobals, clientInfo);

    if (NT_SUCCESS(status)) {
        //
        // The context will be a pointer to FX_DRIVER_GLOBALS
        //
        *Context = GetFxDriverGlobals(*WdfDriverGlobals);   //重要结构

        //
        // Set the WDF_BIND_INFO structure pointer in FxDriverGlobals
        //
        pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals);
        pFxDriverGlobals->WdfBindInfo = Info;
    }

    return status;
}

PFX_DRIVER_GLOBALS
GetFxDriverGlobals(
    __in PWDF_DRIVER_GLOBALS DriverGlobals
    )
{
    return CONTAINING_RECORD( DriverGlobals, FX_DRIVER_GLOBALS, Public );
}

从这里可以发现,我们分析的那个全局驱动变量,只是FX_DRIVER_GLOBALS 的一个Public成员,整个结构信息如下:

kd> dt Wdf01000!_FX_DRIVER_GLOBALS 8c741520-108
   +0x000 Linkage          : _LIST_ENTRY [ 0x8df8bc18 - 0x8200b9ec ]
   +0x008 Refcnt           : 0n1
   +0x00c DestroyEvent     : MxEvent
   +0x020 WdfHandleMask    : 0xfffffff8
   +0x024 WdfVerifierAllocateFailCount : 0n-1
   +0x028 Tag              : 0
   +0x02c Driver           : (null) 
   +0x030 DebugExtension   : (null) 
   +0x034 LibraryGlobals   : 0x8200b870 FxLibraryGlobalsType
   +0x038 WdfLogHeader     : (null) 
   +0x03c FxPoolFrameworks : FX_POOL
   +0x098 FxPoolTrackingOn : 0 ''
   +0x09c ThreadTableLock  : MxLock
   +0x0a4 ThreadTable      : (null) 
   +0x0a8 WdfBindInfo      : 0xa5fc3000 _WDF_BIND_INFO
   +0x0ac ImageAddress     : (null) 
   +0x0b0 ImageSize        : 0
   +0x0b4 FxVerifierOn     : 0 ''
   +0x0b5 FxVerifyDownlevel : 0 ''
   +0x0b6 FxVerifierDbgBreakOnError : 0 ''
   +0x0b7 FxVerifierDbgBreakOnDeviceStateError : 0 ''
   +0x0b8 FxVerifierHandle : 0 ''
   +0x0b9 FxVerifierIO     : 0 ''
   +0x0ba FxVerifierLock   : 0 ''
   +0x0bb FxVerifyOn       : 0 ''
   +0x0bc FxVerboseOn      : 0 ''
   +0x0c0 FxVerifyLeakDetection : (null) 
   +0x0c4 FxVerifyTagTrackingEnabled : 0 ''
   +0x0c5 FxRequestParentOptimizationOn : 0x1 ''
   +0x0c6 FxDsfOn          : 0 ''
   +0x0c7 FxForceLogsInMiniDump : 0 ''
   +0x0c8 FxTrackDriverForMiniDumpLog : 0x1 ''
   +0x0c9 IsUserModeDriver : 0 ''
   +0x0cc RemoveLockOptionFlags : 0
   +0x0d0 BugCheckDriverInfoIndex : 0
   +0x0d4 BugCheckCallbackRecord : _KBUGCHECK_REASON_CALLBACK_RECORD
   +0x0f0 WdfLogHeaderRefCount : 0n0
   +0x0f4 FxEnhancedVerifierOptions : 0
   +0x0f8 FxVerifierDbgWaitForSignalTimeoutInSec : 0x3c
   +0x0fc DbgWaitForWakeInterruptIsrTimeoutInSec : 0x3c
   +0x100 TelemetryContext : 0x8e0ef428 _FX_TELEMETRY_CONTEXT
   +0x104 IsDriverCompanion : 0 ''
   +0x108 Public           : _WDF_DRIVER_GLOBALS

其实status = FxLibraryCommonRegisterClient(Info, WdfDriverGlobals, clientInfo);这个函数的主要作用如下:

  1. *WdfDriverGlobals = FxAllocateDriverGlobals();创建FX_DRIVER_GLOBALS的内存,并初始化。
  2. 调用RtlCopyMemory拷贝函数表。
RtlCopyMemory( Info->FuncTable,
                               &WdfVersion.Functions,
                               Info->FuncCount * sizeof(PVOID) );

这个结构定义成为:

WDFVERSION WdfVersion = {
    sizeof(WDFVERSION),
    sizeof(WDFFUNCTIONS)/sizeof(PVOID),
    {
        WDFEXPORT(WdfCollectionCreate),
        WDFEXPORT(WdfCollectionGetCount),
        WDFEXPORT(WdfCollectionAdd),
        WDFEXPORT(WdfCollectionRemove),
        WDFEXPORT(WdfCollectionRemoveItem),
        WDFEXPORT(WdfCollectionGetItem),
        WDFEXPORT(WdfCollectionGetFirstItem),
        WDFEXPORT(WdfCollectionGetLastItem),
        WDFEXPORT(WdfCxDeviceInitAllocate),
        WDFEXPORT(WdfCxDeviceInitSetRequestAttributes),
        WDFEXPORT(WdfCxDeviceInitSetFileObjectConfig),
        WDFEXPORT(WdfCxVerifierKeBugCheck),
        WDFEXPORT(WdfDeviceGetDeviceState),
   
#define WDFEXPORT(a) imp_ ## a

并且从下面这里可以知道,WdfVersion.Functions这个函数表放在了全局变量WdfFunctions_01015中了。
在这里插入图片描述

3.2.2 FxAllocateDriverGlobals
_Must_inspect_result_
PWDF_DRIVER_GLOBALS
FxAllocateDriverGlobals(
    VOID
    )
{
    PFX_DRIVER_GLOBALS  pFxDriverGlobals;
    KIRQL               irql;
    NTSTATUS            status;

    pFxDriverGlobals = (PFX_DRIVER_GLOBALS)
        MxMemory::MxAllocatePoolWithTag(NonPagedPool, sizeof(FX_DRIVER_GLOBALS), FX_TAG);

    if (pFxDriverGlobals == NULL) {
        return NULL;
    }

    RtlZeroMemory(pFxDriverGlobals, sizeof(FX_DRIVER_GLOBALS));

    pFxDriverGlobals->Refcnt = 1;

    status = pFxDriverGlobals->DestroyEvent.Initialize(NotificationEvent, FALSE);
#if (FX_CORE_MODE==FX_CORE_USER_MODE)
    if (!NT_SUCCESS(status)) {
        MxMemory::MxFreePool(pFxDriverGlobals);
        return NULL;
    }
#else
    UNREFERENCED_PARAMETER(status);
#endif

    //
    // Initialize this new FxDriverGlobals structure.
    //
    FxLibraryGlobals.FxDriverGlobalsListLock.Acquire(&irql);
    InsertHeadList(&FxLibraryGlobals.FxDriverGlobalsList,
                   &pFxDriverGlobals->Linkage);
    FxLibraryGlobals.FxDriverGlobalsListLock.Release(irql);

    pFxDriverGlobals->WdfHandleMask                  = FxHandleValueMask;
    pFxDriverGlobals->WdfVerifierAllocateFailCount   = (ULONG) -1;
    pFxDriverGlobals->Driver                         = NULL;
    pFxDriverGlobals->DebugExtension                 = NULL;
    pFxDriverGlobals->LibraryGlobals                 = &FxLibraryGlobals;
    pFxDriverGlobals->WdfLogHeader                   = NULL;

    //
    // Verifier settings.  Off by default.
    //
    pFxDriverGlobals->SetVerifierState(FALSE);

    //
    // By default don't apply latest-version restricted verifier checks
    // to downlevel version drivers.
    //
    pFxDriverGlobals->FxVerifyDownlevel              = FALSE;

    //
    // Verbose is separate knob
    //
    pFxDriverGlobals->FxVerboseOn                    = FALSE;

    //
    // Do not parent queue presented requests.
    // This performance optimization is on by default.
    //
    pFxDriverGlobals->FxRequestParentOptimizationOn  = TRUE;

    //
    // Enhanced verifier options. Off by default
    //
    pFxDriverGlobals->FxEnhancedVerifierOptions = 0;

    //
    // If FxVerifierDbgBreakOnError is true, WaitForSignal interrupts the
    // execution of the system after waiting for the specified number
    // of seconds. Developer will have an opportunity to validate the state
    // of the driver when breakpoint is hit. Developer can continue to wait
    // by entering 'g' in the debugger.
    //
    pFxDriverGlobals->FxVerifierDbgWaitForSignalTimeoutInSec = 60;

    //
    // Timeout used by the wake interrupt ISR in WaitForSignal to catch
    // scenarios where the interrupt ISR is blocked because the device stack
    // is taking too long to power up
    //
    pFxDriverGlobals->DbgWaitForWakeInterruptIsrTimeoutInSec = 60;

    //
    // Minidump log related settings.
    //
    pFxDriverGlobals->FxForceLogsInMiniDump          = FALSE;

#if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
    pFxDriverGlobals->FxTrackDriverForMiniDumpLog    = TRUE;
    pFxDriverGlobals->IsUserModeDriver               = FALSE;
#else
    pFxDriverGlobals->FxTrackDriverForMiniDumpLog    = FALSE;
    pFxDriverGlobals->IsUserModeDriver               = TRUE;
#endif

#if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
    //
    // Minidump driver info related settings.
    //
    pFxDriverGlobals->BugCheckDriverInfoIndex        = 0;
#endif

    //
    // By default disable the support for device simulation framework (DSF).
    //
    pFxDriverGlobals->FxDsfOn  = FALSE;

    pFxDriverGlobals->FxVerifyLeakDetection = NULL;
    pFxDriverGlobals->FxVerifyTagTrackingEnabled = FALSE;

    //
    // Allocate a telemetry context if a telemetry client is enabled, for any level/keyword.
    //
    pFxDriverGlobals->TelemetryContext = NULL;
    if (TraceLoggingProviderEnabled(g_TelemetryProvider, 0 ,0)) {
        AllocAndInitializeTelemetryContext(&(pFxDriverGlobals->TelemetryContext));
    }

    return &pFxDriverGlobals->Public;
}
  1. MxMemory::MxAllocatePoolWithTag(NonPagedPool, sizeof(FX_DRIVER_GLOBALS), FX_TAG);创建内存。
  2. 创建的对象为_FX_DRIVER_GLOBALS
  3. 初始化pFxDriverGlobals

3.3 DriverEntry初始化

经过上述的这些步骤之后WDF框架已经初始化完成了,接下来就可以进入驱动使用WDF框架了,驱动入口的调用过程如下:
在这里插入图片描述

4. 驱动的卸载

从上我们知道,WDF的写字儿是调用FxStubDriverUnload来完成的,这个过程如下:
在这里插入图片描述

  1. WdfDriverStubDisplacedDriverUnload这个是我们驱动设置的卸载例程。
  2. FxStubDriverUnloadCommon()用来卸载WDF框架使用。

FxStubDriverUnloadCommon伪代码如下:
在这里插入图片描述

4.1 WdfVersionUnbind

这个函数的伪代码如下:

__int64 __fastcall WdfVersionUnbind(_UNICODE_STRING *RegistryPath, _WDF_BIND_INFO *Info, void **Globals)
{
  __int64 result; // rax
  unsigned int v4; // ebx

  result = DereferenceVersion(Info, Globals, (__int64)Globals);
  v4 = result;
  if ( WdfLdrDiags.DiagFlags & 1 )
  {
    DbgPrint("WdfLdr: WdfVersionUnbind - ");
    DbgPrint("WdfLdr: WdfVersionUnbind: exit: %X\n", v4);
    result = v4;
  }
  return result;
}

__int64 __fastcall DereferenceVersion(_WDF_BIND_INFO *Info, void **Globals, __int64 a3)
{
  _LIBRARY_MODULE *Module; // rbx
  _WDF_BIND_INFO *v4; // rdi
  unsigned int v5; // esi
  int v6; // esi
  __int64 result; // rax

  Module = Info->Module;
  v4 = Info;
  if ( Globals )
  {
    v5 = ((__int64 (__fastcall *)(_WDF_BIND_INFO *, void **, __int64))Module->LibraryInfo->LibraryUnregisterClient)(
           Info,
           Globals,
           a3);
    if ( (v5 & 0x80000000) != 0 )
    {
      if ( WdfLdrDiags.DiagFlags & 1 )
      {
        DbgPrint("WdfLdr: DereferenceVersion - ");
        DbgPrint("WdfLdr: DereferenceVersion: LibraryUnregisterClient failed 0x%X\n", v5);
      }
    }
  }
  v6 = LibraryUnlinkClient(Module, v4);
  if ( v6 < 0 && WdfLdrDiags.DiagFlags & 1 )
  {
    DbgPrint("WdfLdr: DereferenceVersion - ");
    DbgPrint("WdfLdr: DereferenceVersion: LibraryUnlinkClient failed 0x%X\n", (unsigned int)v6);
  }
  KeEnterCriticalRegion();
  ExAcquireResourceExclusiveLite(&Resource, 1);
  ++Module->LibraryRefCount;
  ExReleaseResourceLite(&Resource);
  KeLeaveCriticalRegion();
  LibraryLoaderLock(Module);
  LibraryReleaseClientReferenceLocked(Module);
  Module->LoaderThread = 0i64;
  KeSetEvent(&Module->LoaderEvent, 0, 0);
  LibraryReleaseReference(Module);
  result = 0i64;
  v4->Module = 0i64;
  return result;
}

这里主要是用来释放WDF框架的内存数据信息,主要有一个调用操作LibraryUnregisterClient,来看一下这个操作的调用流程.

4.2 FxLibraryCommonUnregisterClient

NTSTATUS
FxLibraryCommonUnregisterClient(
    PWDF_BIND_INFO        Info,
    PWDF_DRIVER_GLOBALS   WdfDriverGlobals
    )
{
    NTSTATUS status;

    __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT) ": enter\n"));

    ASSERT(Info != NULL);
    ASSERT(WdfDriverGlobals != NULL);

    if (Info != NULL && WdfDriverGlobals != NULL) {
        PFX_DRIVER_GLOBALS pFxDriverGlobals;

        status = STATUS_SUCCESS;

        pFxDriverGlobals = GetFxDriverGlobals(WdfDriverGlobals);

        //
        // Destroy this FxDriver instance, if its still indicated.
        //
        if (pFxDriverGlobals->Driver != NULL) {
            //
            // Association support, we are a root with no parent
            //
            pFxDriverGlobals->Driver->DeleteObject();

            FxDestroy(pFxDriverGlobals);
        }

        //
        // Stop IFR logging
        //
        FxIFRStop(pFxDriverGlobals);

        //
        // This will free the client's FxDriverGlobals area
        //
        FxFreeDriverGlobals(WdfDriverGlobals);
    }
    else {
        status = STATUS_UNSUCCESSFUL;
    }

    __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT)
             ": exit: status %X\n", status));

    return status;
}
  1. pFxDriverGlobals->Driver->DeleteObject(); 释放驱动对象信息。
  2. FxDestroy(pFxDriverGlobals); 删除驱动管理的全局信息。

5. 总结

从上分析,基本可以发现WDF框架应该是对WMD编程的一种封装,微软在编译WDF框架的驱动的时候,使用了

$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib
$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib

lib库取代代码的入口函数,在lib库中的入口函数先初始化完成框架,然后在调用开发者编写代码的入口。

最后,附上一个调用堆栈:

 # ChildEBP RetAddr  Args to Child              
00 872579bc 81fa6675 87257aa0 00000000 a5fc3000 Wdf01000!FxLibraryCommonRegisterClient [minkernel\wdf\framework\kmdf\src\librarycommon\fxlibrarycommon.cpp @ 344] 
01 87257a80 81ddd279 a5fc3000 a5fc3264 87257ab0 Wdf01000!LibraryRegisterClient+0x75 [minkernel\wdf\framework\kmdf\src\dynamic\version\version.cpp @ 511] 
02 87257ab4 a5fc1158 8df81c30 a5fc3258 a5fc3000 WDFLDR!WdfVersionBind+0xa9 [minkernel\wdf\framework\kmdf\src\dynamic\loader\wdfldr.cpp @ 1954] 
03 87257ad8 81609709 8df81c30 8dd95000 a4fabba8 WdfSample!FxDriverEntryWorker+0x58 [minkernel\wdf\framework\kmdf\src\dynamic\stub\stub.cpp @ 322] 
04 87257bc8 8169252c 00000000 87257be4 85b89de0 nt!IopLoadDriver+0x443
05 87257be8 8134ca6a a4fabba8 00000000 8744b600 nt!IopLoadUnloadDriver+0x42
06 87257c38 8131b0f0 85b89de0 be065d3a 00000000 nt!ExpWorkerThread+0xea
07 87257c70 813f718d 8134c980 85b89de0 00000000 nt!PspSystemThreadStartup+0x4a
08 87257c7c 00000000 00000000 01e181c9 5fc00000 nt!KiThreadStartup+0x15

卸载时候的调用栈

00 Wdf01000!FxLibraryCommonUnregisterClient
01 WDFLDR!DereferenceVersion
02 WDFLDR!WdfVersionUnbind
03 nonpnp!FxStubDriverUnloadCommon
04 nonpnp!FxStubDriverUnload
05 nt!IopLoadUnloadDriver
06 nt!ExpWorkerThread
07 nt!PspSystemThreadStartup
08 nt!KiThreadStartup
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Windows设备驱动程序开发(WDF)是一种用于创建和管理Windows设备驱动程序的框架。WDF提供了一种高级的编程模型,使开发人员能够更轻松地创建、调试和维护设备驱动程序。武安河是一个专门的培训机构,提供WDF开发的相关培训课程。 WDF提供了两种不同的驱动程序模型:Kernel-Mode Driver Framework(KMDF)和User-Mode Driver Framework(UMDF)。KMDF允许开发人员创建在内核模式下运行的设备驱动程序,而UMDF允许开发人员创建在用户模式下运行的设备驱动程序。这两种模型都提供了丰富的API和工具集,使开发人员能够更加高效地编写设备驱动程序。 WDF还提供了一些特性和功能,帮助开发人员管理设备驱动程序的生命周期。例如,WDF提供了一组用于处理设备添加和移除、电源管理、设备关联以及设备通信的功能,简化了开发人员的工作。此外,WDF还提供了一系列调试工具,帮助开发人员定位和解决驱动程序中的问题。 武安河是一个专门的培训机构,致力于为开发人员提供关于WDF开发的培训课程。培训课程将介绍WDF的基础知识、API和工具集,帮助学员掌握WDF驱动程序的开发技巧和最佳实践。通过参加武安河的培训课程,开发人员可以更加深入地了解WDF开发,并能够在实际项目中应用所学知识,提高设备驱动程序的开发效率和质量。 总之,WDF是一种用于创建和管理Windows设备驱动程序的框架,提供了丰富的功能和工具集。武安河提供相关培训课程,帮助开发人员掌握WDF开发的技能,并在实际项目中应用所学知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值