WDF学习笔记之CharSample


CharSample这个实例是使应用程序中接收一个数字,然后将其转换为一个中文数字,把结果返回给应用程序。

1.DriverEntry例程,用于驱动对象的创建,第一次添加设备对象的时候调用

#include "private.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#endif

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    WDF_DRIVER_CONFIG  config;
    NTSTATUS		   status;


    WDF_DRIVER_CONFIG_INIT(&config, CharSample_EvtDeviceAdd);//设置Add例程

    status = WdfDriverCreate(//创建驱动对象
        DriverObject,
        RegistryPath,
        WDF_NO_OBJECT_ATTRIBUTES,	
        &config,	
        WDF_NO_HANDLE	
        );

    return status;
}
2. EvtDriverDeviceAdd例程,用于创建设备,创建IO队列,创建GUID接口。

#include "private.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CharSample_EvtDeviceAdd)
#endif

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;
}
3.完成DeviceControl例程,用于应用层与驱动层的通信。

#include "private.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CharSample_EvtIoDeviceControl)
#endif

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;
}
4.完成应用层程序的编写。

// Test_CharSample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include 
#include 
#include 
#include 
#include 
#include 

#include "public.h"

PCHAR
GetDevicePath(
    IN  LPGUID InterfaceGuid
    );

int main(int argc, char* argv[])
{
	PCHAR  DevicePath;
    HANDLE hDevice = INVALID_HANDLE_VALUE;

	printf("Application Test_CharSample starting...\n");

    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;
	}
	printf(":"); 
	_putch(bufOutput[0]); 
	_putch(bufOutput[1]); 
	printf("\n");
	
exit:

    if (hDevice != INVALID_HANDLE_VALUE) {
        CloseHandle(hDevice);
    }
    return 0;
}
//获取设备符号链接路径
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;

}







你可能感兴趣的:(WDF学习笔记之CharSample)