windows驱动之WDF---CharSample

简介: <p>驱动程序部分:</p><p></p><pre code_snippet_id="575640" snippet_file_name="blog_20150109_1_8121140" name="code" class="html">NTSTATUSDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_S

驱动程序部分:

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;

}


相关文章
|
2月前
|
Windows
Windows 映射网络驱动器及删除-此网格连接不存在
Windows 映射网络驱动器及删除-此网格连接不存在
148 0
|
3月前
|
安全 测试技术 Windows
LabVIEW版本、硬件驱动和Windows版本之间兼容性
LabVIEW版本、硬件驱动和Windows版本之间兼容性
71 2
|
4月前
|
网络安全 C++ Windows
【Windows驱动开发】(主机)VS2017+(虚拟机)win10系统------双机调试
【Windows驱动开发】(主机)VS2017+(虚拟机)win10系统------双机调试
|
4月前
|
Windows
【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)
【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)
|
4月前
|
Windows
【Windows内核驱动函数(1)】IoCreateSymbolicLink()-----创建符号链接函数
【Windows内核驱动函数(1)】IoCreateSymbolicLink()-----创建符号链接函数
|
5月前
|
存储 安全 数据安全/隐私保护
【Windows manage-bde 命令】BitLocker 2.0:一步步解锁您的加密驱动器
【Windows manage-bde 命令】BitLocker 2.0:一步步解锁您的加密驱动器
1533 0
|
5月前
|
监控 安全 API
5.9 Windows驱动开发:内核InlineHook挂钩技术
在上一章`《内核LDE64引擎计算汇编长度》`中,`LyShark`教大家如何通过`LDE64`引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的`InlineHook`函数挂钩其实与应用层一致,都是使用`劫持执行流`并跳转到我们自己的函数上来做处理,唯一的不同的是内核`Hook`只针对`内核API`函数,但由于其身处在`最底层`所以一旦被挂钩其整个应用层都将会受到影响,这就直接决定了在内核层挂钩的效果是应用层无法比拟的,对于安全从业者来说学会使用内核挂钩也是很重要。
5.9 Windows驱动开发:内核InlineHook挂钩技术
|
10月前
|
监控 安全 API
7.6 Windows驱动开发:内核监控FileObject文件回调
本篇文章与上一篇文章`《内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShark`将回调结构体`OB_OPERATION_REGISTRATION`中的`ObjectType`填充为了`PsProcessType`和`PsThreadType`格式从而实现监控进程与线程,本章我们需要将该结构填充为`IoFileObjectType`以此来实现对文件的监控,文件过滤驱动不仅仅可以用来监控文件的打开,还可以用它实现对文件的保护,一旦驱动加载则文件是不可被删除和改动的。
7.6 Windows驱动开发:内核监控FileObject文件回调
|
10月前
|
监控 安全 API
6.9 Windows驱动开发:内核枚举进线程ObCall回调
在笔者上一篇文章`《内核枚举Registry注册表回调》`中我们通过特征码定位实现了对注册表回调的枚举,本篇文章`LyShark`将教大家如何枚举系统中的`ProcessObCall`进程回调以及`ThreadObCall`线程回调,之所以放在一起来讲解是因为这两中回调在枚举是都需要使用通用结构体`_OB_CALLBACK`以及`_OBJECT_TYPE`所以放在一起来讲解最好不过。
6.9 Windows驱动开发:内核枚举进线程ObCall回调
|
10月前
|
监控 安全 API
6.8 Windows驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章`《内核枚举LoadImage映像回调》`中`LyShark`教大家实现了枚举系统回调中的`LoadImage`通知消息,本章将实现对`Registry`注册表通知消息的枚举,与`LoadImage`消息不同`Registry`消息不需要解密只要找到`CallbackListHead`消息回调链表头并解析为`_CM_NOTIFY_ENTRY`结构即可实现枚举。
6.8 Windows驱动开发:内核枚举Registry注册表回调