WDF驱动开发之DriverEntry原理
本文我们从WDF源码出发,分析一下在WDF框架下面驱动的加载和卸载过程;因为WDF框架代码已经开源,所以我们可以直接通过源码进行调试。
- 加载符号
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
- 设置符号路径
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;
}
这里其实逻辑很简单,主要三个流程:
- 初始化WDF框架。
- 调用驱动的
DriverEntry
函数。 - 设置框架的卸载例程
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);
总这里看,主要有两个参数很关键
WdfBindInfo
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);
这个函数的主要作用如下:
*WdfDriverGlobals = FxAllocateDriverGlobals();
创建FX_DRIVER_GLOBALS
的内存,并初始化。- 调用
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;
}
MxMemory::MxAllocatePoolWithTag(NonPagedPool, sizeof(FX_DRIVER_GLOBALS), FX_TAG);
创建内存。- 创建的对象为
_FX_DRIVER_GLOBALS
。 - 初始化
pFxDriverGlobals
。
3.3 DriverEntry初始化
经过上述的这些步骤之后WDF框架已经初始化完成了,接下来就可以进入驱动使用WDF框架了,驱动入口的调用过程如下:
4. 驱动的卸载
从上我们知道,WDF的写字儿是调用FxStubDriverUnload
来完成的,这个过程如下:
WdfDriverStubDisplacedDriverUnload
这个是我们驱动设置的卸载例程。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;
}
pFxDriverGlobals->Driver->DeleteObject();
释放驱动对象信息。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