WDF框架学习
WDF是什么?
Windows Driver Framework (WDF) 是微软提供的一套用于开发Windows设备驱动程序的框架。WDF分为两个子框架:
KMDF (Kernel-Mode Driver Framework):用于开发内核模式的驱动程序。
UMDF (User-Mode Driver Framework):用于开发用户模式的驱动程序。
WDF框架简化了驱动程序开发的复杂性,提供了丰富的API和工具,使得开发者能够更专注于业务逻辑的实现,而不是底层驱动的细节。
总之,将WDF理解为对WDM做了封装,类似于SDK和MFC之间的关系
第一节:第一个WFP驱动程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <ntddk.h> #include <wdf.h>
#define DebugPrint(...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,__VA_ARGS__)
void MyDriverUnload( _In_ WDFDRIVER Driver ) { Driver;
DebugPrint("MyDriverUnload: Driver is being unloaded.\n"); }
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS status; WDF_DRIVER_CONFIG config; WDFDRIVER driver; KdBreakPoint(); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); config.DriverInitFlags |= WdfDriverInitNonPnpDriver; config.EvtDriverUnload = MyDriverUnload;
status = WdfDriverCreate( DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver );
if (!NT_SUCCESS(status)) { DebugPrint("WFP驱动初始化失败!\n"); return status; }
DebugPrint("WFP驱动初始化成功!\n"); return STATUS_SUCCESS; }
|
相关函数介绍
WDF_DRIVER_CONFIG_INIT
WDF_DRIVER_CONFIG_INIT
是 Windows Driver Framework (WDF) 中的一个宏,用于初始化 WDF_DRIVER_CONFIG
结构体。
1 2 3 4 5 6 7
| typedef struct _WDF_DRIVER_CONFIG { ULONG Size; PFN_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; PFN_WDF_DRIVER_UNLOAD EvtDriverUnload; ULONG DriverInitFlags; ULONG DriverPoolTag; } WDF_DRIVER_CONFIG, *PWDF_DRIVER_CONFIG;
|
EvtDriverDeviceAdd
作用:指定设备添加回调函数。当设备被添加到驱动程序时,WDF 框架会调用这个函数。
EvtDriverUnload
:指定驱动程序卸载回调函数。当驱动程序被卸载时,WDF 框架会调用这个函数。如果不需要卸载回调函数,可以设置为 NULL。并WDF 框架会自动释放 WDF 对象(如设备对象、队列对象等,因此不需要手动释放这些对象,只需要释放掉自己用到的其他对象
DriverInitFlags
:
WdfDriverInitNonPnpDriver
:表示这是一个非 PnP 驱动程序。
WdfDriverInitNoDispatchOverride
:表示驱动程序不会覆盖默认的调度例程。
WdfDriverInitNoFormatChaining
:表示驱动程序不会使用格式链。
DriverPoolTag
:指定驱动程序使用的内存池标签。内存池标签是一个 4 字符的标识符,用于调试和跟踪内存分配。如果不需要自定义内存池标签,可以设置为 0。
WDF_DRIVER_CONFIG
是 Windows Driver Framework (WDF) 中的一个重要结构体,用于配置 WDF 驱动程序的行为和属性。它在 DriverEntry
函数中用于初始化驱动程序,并传递给 WdfDriverCreate
函数。
1 2 3 4 5 6
| VOID FORCEINLINE WDF_DRIVER_CONFIG_INIT( _Out_ PWDF_DRIVER_CONFIG Config, _In_opt_ PFN_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd )
|
其中:**EvtDriverDeviceAdd
** 如果不需要设备添加回调函数,可以传递 WDF_NO_EVENT_CALLBACK
。
调用时机:当该驱动有相关设备被创建,则会调用这个EvtDriverDeviceAdd
WdfDriverCreate
WdfDriverCreate
并不是创建一个新的驱动对象,而是创建一个 WDF 驱动程序对象,并将其与现有的 DriverObject
关联起来,以便使用 WDF 框架的功能。
1 2 3 4 5 6 7
| NTSTATUS WdfDriverCreate( [in] PDRIVER_OBJECT DriverObject, [in] PCUNICODE_STRING RegistryPath, [in, optional] PWDF_OBJECT_ATTRIBUTES DriverAttributes, [in] PWDF_DRIVER_CONFIG DriverConfig, [out, optional] WDFDRIVER *Driver );
|
WDF_DRIVER_CONFIG
是 Windows Driver Framework (WDF) 中的一个重要结构体,用于配置 WDF 驱动程序的行为和属性。它在 DriverEntry
函数中用于初始化驱动程序,并传递给 WdfDriverCreate
函数。
介绍下_WDF_OBJECT_ATTRIBUTES
结构
1 2 3 4 5 6 7 8 9 10
| typedef struct _WDF_OBJECT_ATTRIBUTES { ULONG Size; PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback; PFN_WDF_OBJECT_CONTEXT_DESTROY EvtDestroyCallback; WDF_EXECUTION_LEVEL ExecutionLevel; WDF_SYNCHRONIZATION_SCOPE SynchronizationScope; WDFOBJECT ParentObject; size_t ContextSizeOverride; PCWDF_OBJECT_CONTEXT_TYPE_INFO ContextTypeInfo; } WDF_OBJECT_ATTRIBUTES, *PWDF_OBJECT_ATTRIBUTES;
|
其中, 如果你定义了 EvtCleanupCallback
和 EvtDestroyCallback
,那么你需要在这些回调函数中手动释放与 WDF 对象相关的资源。 否则WDF框架会自动清除掉这些对象的资源
- **
EvtCleanupCallback
**:
- 当 WDF 设备对象 的引用计数降为 0 时,WDF 框架会调用
EvtCleanupCallback
。
- 此时设备对象仍然有效,开发人员可以访问对象的上下文内存和其他属性。
- **
EvtDestroyCallback
**:
- 在
EvtCleanupCallback
执行完毕后,WDF 框架会调用 EvtDestroyCallback
。
- 此时设备对象已经无效,开发人员不能访问对象的上下文内存或其他属性。
WdfObjectDereference
用来减少WDF设备的引用计数
第二节:设备对象,文件操作,符号链接
WdfControlDeviceInitAllocate
是 Windows Driver Framework (WDF) 中的一个函数,用于为控制设备分配一个 WDFDEVICE_INIT 结构体。
1 2 3 4
| PWDFDEVICE_INIT WdfControlDeviceInitAllocate( [in] WDFDRIVER Driver, [in] const UNICODE_STRING *SDDLString );
|
SDDLString
:举个例子SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX
定义了以下权限:
- 系统(SY):完全访问。
- 管理员组(BA):完全访问。
- 所有用户(WD):完全访问。
- 受限代码(RC):完全访问。
WdfDeviceInitAssignName
是 Windows 驱动程序框架(WDF)中的一个函数,用于为设备对象分配一个名称。
1 2 3 4
| NTSTATUS WdfDeviceInitAssignName( [in] PWDFDEVICE_INIT DeviceInit, [in, optional] PCUNICODE_STRING DeviceName );
|
设备对象中的驱动程序框架文件对象(WDFFILEOBJECT) 可以理解为内核驱动程序与应用层通信的桥梁。它在 WDF(Windows 驱动程序框架)中扮演了非常重要的角色,主要用于管理与设备对象相关的用户模式句柄和上下文数据。
WDF_FILEOBJECT_CONFIG_INIT 函数初始化驱动程序WDF_FILEOBJECT_CONFIG
结构。
1 2 3 4 5 6
| void WDF_FILEOBJECT_CONFIG_INIT( [out] PWDF_FILEOBJECT_CONFIG FileEventCallbacks, [in, optional] PFN_WDF_DEVICE_FILE_CREATE EvtDeviceFileCreate, [in, optional] PFN_WDF_FILE_CLOSE EvtFileClose, [in, optional] PFN_WDF_FILE_CLEANUP EvtFileCleanup );
|
当用户模式应用程序调用 CreateFile
或内核模式组件调用 ZwCreateFile
时, WDF 会触发 EvtDeviceFileCreate
用户模式应用程序调用 CloseHandle
或内核模式组件调用 ZwClose
时,WDF 会触发EvtWdfFileCleanup
。
当文件对象完全关闭时,驱动程序的 EvtWdfFileClose
被调用。
WdfDeviceInitSetFileObjectConfig
该方法注册事件回调函数并设置驱动程序框架文件对象的配置信息。
1 2 3 4 5
| void WdfDeviceInitSetFileObjectConfig( [in] PWDFDEVICE_INIT DeviceInit, [in] PWDF_FILEOBJECT_CONFIG FileObjectConfig, [in, optional] PWDF_OBJECT_ATTRIBUTES FileObjectAttributes );
|
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| #include <ntddk.h> #include <wdf.h> #include <sddl.h> #define DebugPrint(...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,__VA_ARGS__)
EVT_WDF_DEVICE_FILE_CREATE EvtWdfDeviceFileCreate; EVT_WDF_FILE_CLOSE EvtWdfFileClose; EVT_WDF_FILE_CLEANUP EvtWdfFileCleanup;
void EvtWdfFileCleanup( WDFFILEOBJECT FileObject ) { FileObject; }
void EvtWdfFileClose( WDFFILEOBJECT FileObject ) { FileObject; }
void EvtWdfDeviceFileCreate( WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject ) { Device; Request; FileObject; }
void MyDriverUnload( _In_ WDFDRIVER Driver ) { Driver;
DebugPrint("MyDriverUnload: Driver is being unloaded.\n"); }
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS status; WDF_DRIVER_CONFIG config; WDFDRIVER driver; WDFDEVICE Device; PWDFDEVICE_INIT DeviceInit; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloWDF"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloWDF"); WDF_FILEOBJECT_CONFIG FileConfig;
KdBreakPoint(); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); config.DriverInitFlags |= WdfDriverInitNonPnpDriver; config.EvtDriverUnload = MyDriverUnload;
status = WdfDriverCreate( DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver );
DeviceInit = WdfControlDeviceInitAllocate(driver,&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX); if (DeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto End; }
status=WdfDeviceInitAssignName(DeviceInit, &DeviceName); if (!NT_SUCCESS(status)) { DebugPrint("设备分配失败!\n"); goto End; }
WDF_FILEOBJECT_CONFIG_INIT(&FileConfig, EvtWdfDeviceFileCreate, EvtWdfFileClose, EvtWdfFileCleanup);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &FileConfig, WDF_NO_OBJECT_ATTRIBUTES);
status = WdfDeviceCreate(&DeviceInit,WDF_NO_OBJECT_ATTRIBUTES,&Device); if (!NT_SUCCESS(status)) { DebugPrint("设备创建失败\n"); goto End; } status = WdfDeviceCreateSymbolicLink(Device, &SymbolicLinkName); if (!NT_SUCCESS(status)) { DebugPrint("符号链接创建失败\n"); goto End; }
WdfControlFinishInitializing(Device);
DebugPrint("WFP驱动初始化成功!\n"); return STATUS_SUCCESS;
End: DebugPrint("WFP驱动初始化失败!\n"); return STATUS_UNSUCCESSFUL;
}
|
总结
- **
DriverEntry
**:驱动程序的入口函数,负责初始化驱动程序。
- **
WdfDriverCreate
**:创建 WDF 驱动程序对象。
- **
WdfControlDeviceInitAllocate
**:分配设备初始化结构。
- **
WdfDeviceInitAssignName
**:设置设备名称。
- **
WDF_FILEOBJECT_CONFIG_INIT
**:初始化文件对象配置。
- **
WdfDeviceInitSetFileObjectConfig
**:设置文件对象配置。
- **
WdfDeviceCreate
**:创建设备对象。
- **
WdfDeviceCreateSymbolicLink
**:创建符号链接。
- **
WdfControlFinishInitializing
**:完成设备初始化。
第三节:编写应用程序访问WDF驱动
在第二节,我们写了对于文件的三个回调,分别是以下三个
当然要说明: 文件对象的回调函数(如 EvtWdfDeviceFileCreate
、EvtWdfFileClose
和 EvtWdfFileCleanup
)主要用于管理文件对象的生命周期,而不是直接处理 I/O 请求(如 ReadFile
和 WriteFile
)。WDF 使用队列(Queue)机制来处理 I/O 请求,而不是像 WDM 那样直接通过回调函数处理。
1 2 3 4 5 6 7 8 9 10 11 12 13
| void EvtWdfFileCleanup( WDFFILEOBJECT FileObject )
void EvtWdfFileClose( WDFFILEOBJECT FileObject )
void EvtWdfDeviceFileCreate( WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject )
|
其中,Create回调里面有一个Request,这个我们必须处理它
处理的方式还是比较多的,例如
1.直接完成请求:(当然你也可以验证资质)
1 2
| WdfRequestComplete(Request, STATUS_SUCCESS);
|
2.初始化文件对象上下文
1 2 3 4 5 6 7 8 9 10 11 12
| PFILE_CONTEXT fileContext = FileObjectGetContext(FileObject);
fileContext->Buffer = ExAllocatePoolWithTag(NonPagedPool, 1024, 'BufT'); if (fileContext->Buffer == NULL) { WdfRequestComplete(Request,STATUS_INSUFFICIENT_RESOURCES); return; }
WdfRequestComplete(Request, STATUS_SUCCESS);
|
3.异步完成请求: 如果设备对象的打开操作需要较长时间(例如等待某个资源),可以将请求标记为挂起,并在操作完成后异步完成请求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void EvtWdfDeviceFileCreate( WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject ) { UNREFERENCED_PARAMETER(Device); UNREFERENCED_PARAMETER(FileObject);
WdfRequestMarkPending(Request);
MyAsyncOpenDevice(Request); }
void MyAsyncOpenDevice(WDFREQUEST Request) { KeDelayExecutionThread(KernelMode, FALSE, 1000);
WdfRequestComplete(Request, STATUS_SUCCESS); }
|
用winobj
可以看到全局的符号链接:
直接在应用层去访问这个设备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <windows.h> #include <stdio.h>
#define DEVICE_NAME L"\\\\.\\HelloWDF"
int main() { system("pause"); HANDLE hDevice = INVALID_HANDLE_VALUE; BOOL result = FALSE; DWORD bytesReturned = 0; char outputBuffer[100] = { 0 };
hDevice = CreateFile( DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hDevice == INVALID_HANDLE_VALUE) { printf("Failed to open device. Error: %d\n", GetLastError()); return 1; } return 0; }
|
可以看到成功断下来了
第四节:实现WDF的IO队列
本节将实现对文件设备的控制操作
首先我们先建立一个IO队列的配置
1
| WDF_IO_QUEUE_CONFIG ioConfig
|
然后用WDF_IO_QUEUE_CONFIG_INIT
来初始化这个ioConfig
1 2 3 4
| void WDF_IO_QUEUE_CONFIG_INIT( [out] PWDF_IO_QUEUE_CONFIG Config, [in] WDF_IO_QUEUE_DISPATCH_TYPE DispatchType );
|
其中 DispatchType枚举值是这样的
值 |
描述 |
WdfIoQueueDispatchInvalid |
无效的分发类型(仅用于内部验证)。 |
WdfIoQueueDispatchSequential |
顺序分发:I/O 请求按顺序处理,一次只处理一个请求。 |
WdfIoQueueDispatchParallel |
并行分发:I/O 请求可以同时处理,适用于高性能场景。 |
WdfIoQueueDispatchManual |
手动分发:驱动程序需要手动从队列中取出请求并处理。 |
WdfIoQueueDispatchMax |
枚举的最大值(仅用于内部验证)。 |
在_WDF_IO_QUEUE_CONFIG
结构中,我们可以发现很多WDM熟悉的东西,例如READ,WRITE,IO_DEVICE_CONTROL,这就是对应的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| typedef struct _WDF_IO_QUEUE_CONFIG { ULONG Size; WDF_IO_QUEUE_DISPATCH_TYPE DispatchType; WDF_TRI_STATE PowerManaged; BOOLEAN AllowZeroLengthRequests; BOOLEAN DefaultQueue; PFN_WDF_IO_QUEUE_IO_DEFAULT EvtIoDefault; PFN_WDF_IO_QUEUE_IO_READ EvtIoRead; PFN_WDF_IO_QUEUE_IO_WRITE EvtIoWrite; PFN_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl; PFN_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL EvtIoInternalDeviceControl; PFN_WDF_IO_QUEUE_IO_STOP EvtIoStop; PFN_WDF_IO_QUEUE_IO_RESUME EvtIoResume; PFN_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue; union { struct { ULONG NumberOfPresentedRequests; } Parallel; } Settings; WDFDRIVER Driver; } WDF_IO_QUEUE_CONFIG, *PWDF_IO_QUEUE_CONFIG;
|
这里做一个表格帮助理解
WDF 回调函数 |
对应三环 API |
描述 |
EvtIoDefault |
无直接对应 |
默认处理逻辑,覆盖未分类的请求。 |
EvtIoRead |
ReadFile, ReadFileEx |
处理读请求。 |
EvtIoWrite |
WriteFile , WriteFileEx |
处理写请求。 |
EvtIoDeviceControl |
DeviceIoControl |
处理用户模式的 IOCTL 请求。 |
EvtIoInternalDeviceControl |
无直接对应 |
处理内核模式的 IOCTL 请求。 |
EvtIoStop |
无直接对应 |
恢复队列请求 |
EvtIoResume |
无直接对应 |
恢复队列请求 |
EvtIoCanceledOnQueue |
CancelIo , CancelIoEx |
用户取消队列中未完成的请求时调用。 |
总结一下顺序
- 设备初始化:
- 调用
WdfDeviceInitAllocate
或 WdfControlDeviceInitAllocate
分配并初始化 WDFDEVICE_INIT
结构。
- 设置设备属性(如设备名称、安全描述符等)。
- 文件对象配置初始化:
- 使用
WDF_FILEOBJECT_CONFIG_INIT
初始化 WDF_FILEOBJECT_CONFIG
结构。
- 设置文件对象的回调函数(如
EvtWdfDeviceFileCreate
、EvtWdfFileClose
等)。
- 设置文件对象配置:
- 调用
WdfDeviceInitSetFileObjectConfig
将文件对象配置与设备初始化结构关联。
- 创建设备对象:
- 调用
WdfDeviceCreate
创建设备对象。
- 创建 I/O 队列:
- 在设备对象创建成功后,调用
WdfIoQueueCreate
创建 I/O 队列。
- 完成设备创建
WdfControlFinishInitializing(Device);
本节完整驱动程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
| #include <ntddk.h> #include <wdf.h> #include <sddl.h> #define DebugPrint(...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,__VA_ARGS__)
EVT_WDF_DEVICE_FILE_CREATE EvtWdfDeviceFileCreate; EVT_WDF_FILE_CLOSE EvtWdfFileClose; EVT_WDF_FILE_CLEANUP EvtWdfFileCleanup;
VOID m_EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) { Queue; Request; OutputBufferLength; InputBufferLength; IoControlCode; DebugPrint("IO_DEVICE_CONTROL\n"); WdfRequestComplete(Request, STATUS_SUCCESS); }
void EvtWdfFileCleanup( WDFFILEOBJECT FileObject ) { FileObject; DebugPrint("clean_up\n"); }
void EvtWdfFileClose( WDFFILEOBJECT FileObject ) { FileObject; DebugPrint("close\n"); }
void EvtWdfDeviceFileCreate( WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject ) { Device; Request; FileObject;
DebugPrint("file_create\n"); WdfRequestComplete(Request, STATUS_SUCCESS);
}
void MyDriverUnload( _In_ WDFDRIVER Driver ) { Driver;
DebugPrint("MyDriverUnload: Driver is being unloaded.\n"); }
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS status; WDF_DRIVER_CONFIG config; WDFDRIVER driver; WDFDEVICE Device; PWDFDEVICE_INIT DeviceInit; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloWDF"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloWDF"); WDF_FILEOBJECT_CONFIG FileConfig; WDF_IO_QUEUE_CONFIG ioConfig; WDFQUEUE Queue;
KdBreakPoint(); WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); config.DriverInitFlags |= WdfDriverInitNonPnpDriver; config.EvtDriverUnload = MyDriverUnload;
status = WdfDriverCreate( DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver );
DeviceInit = WdfControlDeviceInitAllocate(driver,&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX); if (DeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto End; }
status=WdfDeviceInitAssignName(DeviceInit, &DeviceName); if (!NT_SUCCESS(status)) { DebugPrint("设备分配失败!\n"); goto End; }
WDF_FILEOBJECT_CONFIG_INIT(&FileConfig, EvtWdfDeviceFileCreate, EvtWdfFileClose, EvtWdfFileCleanup);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &FileConfig, WDF_NO_OBJECT_ATTRIBUTES);
status = WdfDeviceCreate(&DeviceInit,WDF_NO_OBJECT_ATTRIBUTES,&Device); if (!NT_SUCCESS(status)) { DebugPrint("设备创建失败\n"); goto End; }
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioConfig, WdfIoQueueDispatchSequential);
ioConfig.EvtIoDeviceControl = m_EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL;
status = WdfIoQueueCreate(Device, &ioConfig, WDF_NO_OBJECT_ATTRIBUTES, &Queue); if (!NT_SUCCESS(status)) { DebugPrint("设备队列创建失败\n"); goto End; }
status = WdfDeviceCreateSymbolicLink(Device, &SymbolicLinkName); if (!NT_SUCCESS(status)) { DebugPrint("符号链接创建失败\n"); goto End; }
WdfControlFinishInitializing(Device);
DebugPrint("WFP驱动初始化成功!\n"); return STATUS_SUCCESS;
End: DebugPrint("WFP驱动初始化失败!\n"); return STATUS_UNSUCCESSFUL;
}
|
应用层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <windows.h> #include <stdio.h>
#define DEVICE_NAME L"\\\\.\\HelloWDF"
int main() { system("pause"); HANDLE hDevice = INVALID_HANDLE_VALUE; BOOL result = FALSE; DWORD bytesReturned = 0; char inputBuffer[100] = "Test input data"; char outputBuffer[100] = { 0 }; hDevice = CreateFile( DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hDevice == INVALID_HANDLE_VALUE) { printf("Failed to open device. Error: %d\n", GetLastError()); return 1; }
result = DeviceIoControl( hDevice, NULL, inputBuffer, sizeof(inputBuffer), outputBuffer, sizeof(outputBuffer), &bytesReturned, NULL ); return 0; }
|
实现效果:
遇到的坑