windows驱动之WDF---CharSample

驱动程序部分:

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    DriverEntry initializes the driver and is the first routine called by the
    system after the driver is loaded.

Parameters Description:

    DriverObject - represents the instance of the function driver that is loaded
    into memory. DriverEntry must initialize members of DriverObject before it
    returns to the caller. DriverObject is allocated by the system before the
    driver is loaded, and it is released by the system after the system unloads
    the function driver from memory.

    RegistryPath - represents the driver specific path in the Registry.
    The function driver can use the path to store driver related data between
    reboots. The path does not store hardware instance specific data.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    WDF_DRIVER_CONFIG  config;
    NTSTATUS		   status;

    //
    // Initiialize driver config to control the attributes that
    // are global to the driver. Note that framework by default
    // provides a driver unload routine. If you create any resources
    // in the DriverEntry and want to be cleaned in driver unload,
    // you can override that by manually setting the EvtDriverUnload in the
    // config structure. In general xxx_CONFIG_INIT macros are provided to
    // initialize most commonly used members.
    //

    WDF_DRIVER_CONFIG_INIT(&config, CharSample_EvtDeviceAdd);

    //
    // Create a framework driver object to represent our driver.
    //
    status = WdfDriverCreate(
        DriverObject,
        RegistryPath,
        WDF_NO_OBJECT_ATTRIBUTES,	// Driver Attributes
        &config,					// Driver Config Info
        WDF_NO_HANDLE				// hDriver
        );

    return status;
}

DeviceAdd也可以自定义了,呵呵

NTSTATUS
CharSample_EvtDeviceAdd(
    IN WDFDRIVER       Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
{
    NTSTATUS			status;
    WDFDEVICE			device;
    WDF_IO_QUEUE_CONFIG	ioQueueConfig;

	//例程的首句PAGED_CODE,表示该例程的代码占用分页内存。
	//只能在PASSIVE_LEVEL中断级别调用该例程,否则会蓝屏。
	//如不说明,则占用系统的非分页内存,要珍惜使用。
    PAGED_CODE();

	//创建设备,没有对象属性和设备对象环境变量结构
    status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

	//初始化缺省队列配置,设置I/O请求分发处理方式为串行。
	//对这个实例而言,选择串行或并行都可以,但不能选手工。
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential);

	//设置EvtIoDeviceControl例程,处理应用程序的DeviceIoControl()函数调用
    ioQueueConfig.EvtIoDeviceControl  = CharSample_EvtIoDeviceControl;

	//创建队列
    status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL);
    if (!NT_SUCCESS(status)) {
        return status;
    }

	//创建设备GUID接口
    status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &CharSample_DEVINTERFACE_GUID, NULL);
    if (!NT_SUCCESS(status)) {
    }

    return status;
}

VOID
CharSample_EvtIoDeviceControl(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     OutputBufferLength,
    IN size_t     InputBufferLength,
    IN ULONG      IoControlCode
    )
{
    NTSTATUS  status;
    PVOID	  buffer;
	CHAR	  n,c[]="零一二三四五六七八九";

    PAGED_CODE();

    switch(IoControlCode) {

    case CharSample_IOCTL_800:
		if (InputBufferLength  == 0 || OutputBufferLength < 2)
		{	//检查输入、输出参数有效性
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
		}
		else
		{
			//输入缓冲区地址可通过调用WdfRequestRetrieveInputBuffer函数获得
			//输出缓冲区地址可通过调用WdfRequestRetrieveOutputBuffer函数获得

			//获取输入缓冲区地址buffer
			//要求1字节空间
			status = WdfRequestRetrieveInputBuffer(Request, 1, &buffer, NULL);
			if (!NT_SUCCESS(status)) {
				WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
		        break;
			}

			//这里buffer表示输入缓冲区地址
			//输入n=应用程序传给驱动程序的数字ASCII码
			n = *(CHAR *)buffer;
			if ((n>=‘0‘) && (n<=‘9‘))
			{	//若为数字,则处理
				n-=‘0‘;	//n=数字(0-9)

				//获取输出缓冲区地址buffer
				status = WdfRequestRetrieveOutputBuffer(Request, 2, &buffer, NULL);
				if (!NT_SUCCESS(status)) {
					WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
					break;
				}

				//这里buffer表示输出缓冲区地址
				//输出:从中文数组c[]中取出对应的数字的中文码,拷贝到输出缓冲区
				strncpy((PCHAR)buffer,&c[n*2],2);

				//完成I/O请求,驱动程序传给应用程序的数据长度为2字节(一个中文)
				WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 2);
			}
			else //否则返回无效参数
				WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
		}
        break;

    default :
        status = STATUS_INVALID_DEVICE_REQUEST;
		WdfRequestCompleteWithInformation(Request, status, 0);
        break;
    }

    return;
}

应用部分:对于习惯了ds编译的程序区别还是比较大的。

    DevicePath = GetDevicePath((LPGUID)&CharSample_DEVINTERFACE_GUID);

    hDevice = CreateFile(DevicePath,
                         GENERIC_READ|GENERIC_WRITE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL,
                         OPEN_EXISTING,
                         0,
                         NULL );

    if (hDevice == INVALID_HANDLE_VALUE) {
		printf("ERROR opening device: (%0x) returned from CreateFile\n", GetLastError());
        return 0;
    }

	printf("OK.\n");

	CHAR	bufInput[1];	// Input to device
	CHAR	bufOutput[2];	// Output from device
	ULONG	nOutput;	// Count written to bufOutput

	printf("请输入数字(0-9)\n");
l0:	bufInput[0] = _getch();
	if ((bufInput[0]<‘0‘) || (bufInput[0]>‘9‘)) goto l0;
	_putch(bufInput[0]);

	// Call device IO Control interface (CharSample_IOCTL_800) in driver
	if (!DeviceIoControl(hDevice,
						 CharSample_IOCTL_800,
						 bufInput,
						 1,
						 bufOutput,
						 2,
						 &nOutput,
						 NULL)
	   )
	{
		printf("ERROR: DeviceIoControl returns %0x.", GetLastError());
        goto exit;
	}

PCHAR
GetDevicePath(
    IN  LPGUID InterfaceGuid
    )
{
    HDEVINFO HardwareDeviceInfo;
    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
    ULONG Length, RequiredLength = 0;
    BOOL bResult;

    HardwareDeviceInfo = SetupDiGetClassDevs(
                             InterfaceGuid,
                             NULL,
                             NULL,
                             (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));

    if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
        printf("SetupDiGetClassDevs failed!\n");
        exit(1);
    }

    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
                                              0,
                                              InterfaceGuid,
                                              0,
                                              &DeviceInterfaceData);

    if (bResult == FALSE) {

        printf("SetupDiEnumDeviceInterfaces failed.\n");

        SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
        exit(1);
    }

    SetupDiGetDeviceInterfaceDetail(
        HardwareDeviceInfo,
        &DeviceInterfaceData,
        NULL,
        0,
        &RequiredLength,
        NULL
        );

    DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LMEM_FIXED, RequiredLength);

    if (DeviceInterfaceDetailData == NULL) {
        SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
        printf("Failed to allocate memory.\n");
        exit(1);
    }

    DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    Length = RequiredLength;

    bResult = SetupDiGetDeviceInterfaceDetail(
                  HardwareDeviceInfo,
                  &DeviceInterfaceData,
                  DeviceInterfaceDetailData,
                  Length,
                  &RequiredLength,
                  NULL);

    if (bResult == FALSE) {

        printf("Error in SetupDiGetDeviceInterfaceDetail\n");

        SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
        LocalFree(DeviceInterfaceDetailData);
        exit(1);
    }

    return DeviceInterfaceDetailData->DevicePath;

}
时间: 2024-11-09 02:00:56

windows驱动之WDF---CharSample的相关文章

Windows 驱动开发 - 7

在<Windows 驱动开发 - 5>我们所说的读写操作在本篇实现. 在WDF中实现此功能主要为:EvtIoRead和EvtIoWrite. 首先,在EvtDeviceAdd设置以上两个回调事件. ioQueueConfig.EvtIoRead = EvtIoRead; ioQueueConfig.EvtIoWrite = EvtIoWrite; 然后,在EvtDevicePrepareHardware中获取WDFUSBPIPE并测试他. pDeviceContext->BulkRead

Windows 驱动开发 - 8

最后的一点开发工作:跟踪驱动. 一.驱动跟踪 1. 包含TMH头文件 #include "step5.tmh" 2. 初始化跟踪 在DriverEntry中初始化. WPP_INIT_TRACING( DriverObject, RegistryPath ); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.EvtCleanupCallback = EvtDriverContextCleanup; (1) WPP跟踪初始化

Windows 驱动开发 - 1

上篇<Windows 驱动开发 - 基础2>已经介绍了windows大概的框架.那么使用WDF有那些的不同呢? 我们知道在WDF中,KMDF是必须的.而KMDF是架构在WDM之上的.  WDM驱动程序模型 在 WDM 驱动程序模型中,每个硬件设备至少有两个驱动程序.其中一个驱动程序我们称为功能(function)驱动程序,通常它就是你认为的那个硬件设备驱动程序.它了解使硬件工作的所有细节,负责初始化 I/O 操作,有责任处理 I/O 操作完成时所带来的中断事件,有责任为用户提供一种设备适合的控

windows驱动开发推荐书籍

[作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从事驱动开发时间不长也不短,大概也就3~4年时间.大多数人都认为会驱动开发的都是牛人,高手之类的.其实高手,牛人不是这样定义的.我们在学习驱动开发之前,一定要明白一个道理:术业有专攻,不要盲目跟风. [贡献者] 1> defddr 看雪学院 2> Stu

Windows 驱动开发 - 5

上篇<Windows 驱动开发 - 4>我们已经完成了硬件准备.但是我们还没有具体的数据操作,例如接收读写操作. 在WDF中进行此类操作前需要进行设备的IO控制,已保持数据的完整性. 我们知道进行WDF开发主要是跟随IRPs的"脚步". I/O Request Delivery Mechanism I/O request type UMDF delivery mechanism KMDF delivery mechanism Read Queue Queue Write Q

Windows 驱动开发 - 基础1

原来的驱动开发都是WDM(Windows Driver Model)的,那时微软推出DDK(Driver Developer Kit)工具. 现在微软进行了升级由WDF(Windows Driver Foundation)来替代WDM,同时推出WDK(Windows Driver Kit)工具. 安装WDK要求的最低系统为Win XP SP3以上. 推荐使用的IDE:VS2010 一.WDM与WDF的区别 (1) 前者使用面向过程,后者可使用面向对象. (2) 前者可开发总线筛选驱动程序; 后者

Windows 驱动开发 - 6

上篇<Windows 驱动开发 - 5>我们设置了回调事件EvtIoDeviceControl,我们在此篇来实现他. 我们知道在进行读写之前我们要进行一定约定,比如同步. 在WDF中控制同步约定的方法为:WdfUsbTargetDeviceSendControlTransferSynchronously NTSTATUS WdfUsbTargetDeviceSendControlTransferSynchronously( [in] WDFUSBDEVICE UsbDevice, [in, o

Windows 驱动开发 - 2

上一篇<Windows 驱动开发 - 1>我们已经实现一个WDF"骨架".但是,他什么也没有干... WDF对象分为3类:方法.事件和属性. 在上节中WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAdd); WDF通知驱动程序执行EvtDeviceAdd事件. 接下来我们需要通知计算机准备硬件! 我们知道大部分IRP都是通过PnP/电源管理.I/O和WMI来实现功能. 参考文献: 1. Architecture of the Ke

Windows 驱动开发 - 4

上篇<Windows 驱动开发 - 3>我们使用了PnP,现在还差WMI. WMI:Windows Management Interface WMI 提供预装的类架构,允许使用脚本语言(VBS).C#.VB .NET 或 C++ 编写的脚本或应用程序监视和配置计算机中的应用程序.系统或网络组件以及硬件. 一.WMI 虽然WDF帮你完成很多工作,但是你还必须自己触发事件和实例化回调函数. 在WDM中使用 wmilib.sys 静态注册很容易,但难以动态注册. 但是在WDF中这些很容易实现. 1.

【转】Windows驱动开发如何入门

1.http://blog.csdn.net/charlessimonyi/article/details/50904854 (2016年03月16日 14:55:36) 2. 搞Windows驱动开发是一件痛苦的事情,特别是初学Windows驱动开发.有的人觉得Windows驱动开发就是把开发包WDK下载下来,然后只要掌握了C/C++语言,接下来无非就是类库调来调去,像调用MFC.QT之类的库那样,看着书和MSDN上的文档来就行了.等真正接触以后才发现根本不是那么一回事,痛苦源于以下几点: 痛