实现WDF的I/O队列

如果应用程序有多个线程同时对设备发起访问,就可以使用队列来处理这里IRP
WDF中使用队列也十分简单,提供了对应的函数.

#include <ntddk.h>
#include <wdf.h>
VOID EvtFileCreate(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request,
	_In_ WDFFILEOBJECT FileObject
)
{
	KdPrint(("文件创建成功\n"));
	WdfRequestComplete(Request,STATUS_SUCCESS);
}

VOID EvtFileClose(_In_ WDFFILEOBJECT FileObject)
{
	KdPrint(("文件关闭成功\n"));
}

VOID EvtFileCleanup(_In_ WDFFILEOBJECT FileObject)
{
	KdPrint(("文件清理成功\n"));
}


VOID EvtIoDeviceControl(
	_In_
	WDFQUEUE Queue,
	_In_
	WDFREQUEST Request,
	_In_
	size_t OutputBufferLength,
	_In_
	size_t InputBufferLength,
	_In_
	ULONG IoControlCode
	)
{
	WdfRequestComplete(Request,STATUS_SUCCESS);
	KdPrint(("enter IoDeviceControl\n"));
}


VOID EvtDriverUnload(WDFDRIVER Driver)
{
	
	KdPrint(("卸载成功\n"));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING RegPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	WDF_DRIVER_CONFIG Config;
	WDFDEVICE Device = {0};
	PWDFDEVICE_INIT pDeviceInit;
	WDFDRIVER WdfDriver;
	UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloWdf");
	UNICODE_STRING SymlicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloWdf");
	WDF_FILEOBJECT_CONFIG FileConfig;
	WDF_IO_QUEUE_CONFIG IoQueueConfig;
	WDFQUEUE WdfQueue;

	//对结构体清0 第二个参数为AddDevice 
	
	WDF_DRIVER_CONFIG_INIT(&Config,NULL);
	//非Pnp驱动
	Config.DriverInitFlags = WdfDriverInitNonPnpDriver;

	//配置卸载函数
	Config.EvtDriverUnload = EvtDriverUnload;
	
	//为驱动创建WDF框架 最后一个参数为out_opt 指向新创建的WDF驱动框架指针
	status = WdfDriverCreate(pDriverObject, RegPath, WDF_NO_OBJECT_ATTRIBUTES, &Config, &WdfDriver);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("WDF驱动框架创建失败\n"));
		return status;
	}
	
	//返回值为框架分配的WDFDEVICE_INIT结构的指针
	pDeviceInit = WdfControlDeviceInitAllocate(WdfDriver, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX);
	if (!pDeviceInit)
	{
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	//为设备分配名字  在NT驱动中是在创建设备时指定的 而在WDF驱动中,把设备名放在了WDFDEVICE_INIT结构体中
	status = WdfDeviceInitAssignName(pDeviceInit, &DeviceName);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("分配设备名失败\n"));
		return status;
	}
	//初始化WDF_FILEOBJECT_CONFIG结构,设置了几个回调函数 在什么时候触发?
	WDF_FILEOBJECT_CONFIG_INIT(&FileConfig, EvtFileCreate, EvtFileClose, EvtFileCleanup);

	//注册事件回调函数,并为驱动程序的框架文件对象设置配置信息。
	WdfDeviceInitSetFileObjectConfig(pDeviceInit,&FileConfig,WDF_NO_OBJECT_ATTRIBUTES);

	//创建设备对象 第三个参数就是返回的设备对象
	status = WdfDeviceCreate(&pDeviceInit, WDF_NO_OBJECT_ATTRIBUTES,&Device);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("设备创建失败\n"));
		return status;
	}
	/*I/O队列操作*/
	//初始化I/O队列 WdfIoQueueDispatchSequential表示IO队列自动串行化 
	WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);

	//设置处理IRP IRP_MJ_CONTROL的函数
	IoQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;  //也可以在这里配置ReadFile 和WriteFile函数的队列
	
	//创建I/O队列
	status = WdfIoQueueCreate(Device, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &WdfQueue);
	
	if (!NT_SUCCESS(status))
	{
		KdPrint(("WDF驱动I/O队列创建失败\n"));
		return status;
	}

	//为设备创建符号链接
	status = WdfDeviceCreateSymbolicLink(Device,&SymlicLinkName);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("符号链接创建失败\n"));
		//这里要删除设备吗?
		return status;
	}

	//通知框架驱动程序已完成对指定的控制设备对象的初始化 在调用该函数之前,系统不会给驱动发送I/O请求
	WdfControlFinishInitializing(Device);
	KdPrint(("WDF驱动框架创建成功\n"));
	return status;

}

应用层通过DeviceIoControl发起访问

// WdfApp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

#define IO_TEST CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
int _tmain(int argc, _TCHAR* argv[])
{

	HANDLE hDevice=CreateFile(TEXT("\\\\.\\HelloWdf"),
		GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("打开设备失败\n");
		getchar();
		return -1;
	}

	DWORD dwRet = 0;
	DeviceIoControl(hDevice, IO_TEST,NULL,0,0,0,&dwRet,NULL);

	CloseHandle(hDevice);
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值