驱动 与应用层DeviceIoContro() 通信

驱动代码
.h文件

#pragma once
#include			// 引入内核文件

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
		// 驱动入口
	NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path);		

#ifdef __cplusplus
}
#endif // __cplusplus


#define DEVICE_NAME L"\\Device\\MaoYu"		// 驱动名

#define SYMBOL_NAME L"\\??\\MaoYu"			// 对外的符号链接

// 自定义代码控制
#define USER_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0xFFF, METHOD_BUFFERED, FILE_ANY_ACCESS)

void driver_unload(PDRIVER_OBJECT driver);		// 驱动卸载回调

// 派遣函数
NTSTATUS dis_create(PDEVICE_OBJECT device, PIRP irp);			// 创建
NTSTATUS dis_clean_up(PDEVICE_OBJECT device, PIRP irp);		// 清除
NTSTATUS dis_close(PDEVICE_OBJECT device, PIRP irp);			// 关闭
NTSTATUS dis_user_code(PDEVICE_OBJECT device, PIRP irp);	// 自定义控制IO通信

// 驱动运行对象
class Cat_Driver
{
public:
	explicit Cat_Driver(PDRIVER_OBJECT driver);		// 构造
	bool add_device(PUNICODE_STRING name);			// 添加设备
	bool set_symbol(PUNICODE_STRING d, PUNICODE_STRING s);		// 设置符号链接
	void set_flags_io(ULONG flag = DO_BUFFERED_IO);		// 设置设备的传输标志
	PDRIVER_DISPATCH* get_dis();		// 获取派遣函数的数组
protected:
	PDRIVER_OBJECT driver_;		// 驱动对象
};


.cpp文件

#include "driver.h"

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	DbgPrint("++++++ 驱动加载 ++++++");

	Cat_Driver cat(driver);		// 定义一个对象

	UNICODE_STRING d, s;		// 定义驱动名称、链接符号
	RtlInitUnicodeString(&d, DEVICE_NAME);		// 初始化驱动名称
	RtlInitUnicodeString(&s, SYMBOL_NAME);	// 初始化链接符号

	if (!cat.add_device(&d))		// 如果添加驱动设备失败
	{
		DbgPrint("添加设备失败");
		return STATUS_UNSUCCESSFUL;
	}

	if (!cat.set_symbol(&d, &s))		// 如果设置符号链接失败
	{
		DbgPrint("设置符号链接失败");
	}

	cat.set_flags_io(DO_BUFFERED_IO);			// 设置驱动设备的传输方式

	// IRP派遣函数尚未实现
	cat.get_dis()[IRP_MJ_CREATE] = dis_create;
	cat.get_dis()[IRP_MJ_CLEANUP] = dis_clean_up;
	cat.get_dis()[IRP_MJ_CLOSE] = dis_close;
	cat.get_dis()[IRP_MJ_DEVICE_CONTROL] = dis_user_code;

	return STATUS_SUCCESS;
}

void driver_unload(PDRIVER_OBJECT driver)			// 驱动卸载回调
{
	DbgPrint(" ----------- 驱动卸载  -----------");

	if (driver->DeviceObject)		// 如果有创建驱动设备
	{
		// 删除符号链接
		UNICODE_STRING s;
		RtlInitUnicodeString(&s, SYMBOL_NAME);
		IoDeleteSymbolicLink(&s);

		IoDeleteDevice(driver->DeviceObject);		// 删除设备
	}
}

NTSTATUS dis_create(PDEVICE_OBJECT device, PIRP irp)		// 创建
{
	DbgPrint("dis 创建");
	// 返回的IRP状态处理
	irp->IoStatus.Status = STATUS_SUCCESS;
	irp->IoStatus.Information = 0L;
	IoCompleteRequest(irp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS dis_clean_up(PDEVICE_OBJECT device, PIRP irp)		// 清除
{
	DbgPrint("dis 清除");
	// 返回的IRP状态处理
	irp->IoStatus.Status = STATUS_SUCCESS;
	irp->IoStatus.Information = 0L;
	IoCompleteRequest(irp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS dis_close(PDEVICE_OBJECT device, PIRP irp)			// 关闭
{
	DbgPrint("dis 关闭");
	// 返回的IRP状态处理
	irp->IoStatus.Status = STATUS_SUCCESS;
	irp->IoStatus.Information = 0L;
	IoCompleteRequest(irp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS dis_user_code(PDEVICE_OBJECT device, PIRP irp)
{
	DbgPrint("dis 自定义控制");

	auto stack = IoGetCurrentIrpStackLocation(irp);					// 获取当前栈IO位置											
	auto in_length = stack->Parameters.DeviceIoControl.InputBufferLength;							// 可读长度
	auto out_length = stack->Parameters.DeviceIoControl.OutputBufferLength;						// 可写长度
	auto code = stack->Parameters.DeviceIoControl.IoControlCode;										// 控制代码
	PDWORD32 buffer = reinterpret_cast<PDWORD32>(irp->AssociatedIrp.SystemBuffer);		// 缓冲区

	DbgPrint("获取到应用的输入 %u", *buffer);

	switch (code)
	{
	case USER_CODE:
		*buffer *= 5;		// 将应用层的值 *5 在返回去
		irp->IoStatus.Status = STATUS_SUCCESS;			// 成功
		irp->IoStatus.Information = 4L;							// 传输的字节长度
		break;
	default:
		irp->IoStatus.Status = STATUS_UNSUCCESSFUL;		// 不成功
		irp->IoStatus.Information = 0L;								// 传输的字节长度
		break;
	}

	IoCompleteRequest(irp, IO_NO_INCREMENT);		// 调用者已经完成了对给定I/O请求的所有处理	

	return STATUS_SUCCESS;						
}

Cat_Driver::Cat_Driver(PDRIVER_OBJECT driver)		// 构造
	:driver_(driver)
{
	driver_->DriverUnload = driver_unload;		// 驱动设置卸载回调
}

bool Cat_Driver::add_device(PUNICODE_STRING name)		// 添加设备
{
	PDEVICE_OBJECT d = nullptr;				// 设备指针
	return NT_SUCCESS(IoCreateDevice(driver_, 0, name, FILE_DEVICE_UNKNOWN, 0L, TRUE, &d));
}

bool Cat_Driver::set_symbol(PUNICODE_STRING d, PUNICODE_STRING s)			// 设置符号链接
{
	return NT_SUCCESS(IoCreateSymbolicLink(s, d));
}

void Cat_Driver::set_flags_io(ULONG flag)			// 设置传输方式
{
	driver_->DeviceObject->Flags |= flag;
}

PDRIVER_DISPATCH* Cat_Driver::get_dis()			// 返回派遣数组
{
	return driver_->MajorFunction;
}

应用层代码

#include
#in#pragma once
#include			// 引入内核文件

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

	NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path);		// 驱动入口

#ifdef __cplusplus
}
#endif // __cplusplus


#define DEVICE_NAME L"\\Device\\MaoYu"		// 驱动名

#define SYMBOL_NAME L"\\??\\MaoYu"			// 对外的符号链接

// 自定义代码控制
#define USER_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0xFFF, METHOD_BUFFERED, FILE_ANY_ACCESS)

void driver_unload(PDRIVER_OBJECT driver);

// 派遣函数
NTSTATUS dis_create(PDEVICE_OBJECT device, PIRP irp);			// 创建
NTSTATUS dis_clean_up(PDEVICE_OBJECT device, PIRP irp);		// 清除
NTSTATUS dis_close(PDEVICE_OBJECT device, PIRP irp);			// 关闭
NTSTATUS dis_user_code(PDEVICE_OBJECT device, PIRP irp);	// 自定义控制IO通信

class Cat_Driver
{
public:
	explicit Cat_Driver(PDRIVER_OBJECT driver);
	bool add_device(PUNICODE_STRING name);
	bool set_symbol(PUNICODE_STRING d, PUNICODE_STRING s);
	void set_flags_io(ULONG flag = DO_BUFFERED_IO);
	PDRIVER_DISPATCH* get_dis();
protected:
	PDRIVER_OBJECT driver_;
};

clude<Windows.h>

#define DEVICE_NAME L"\\\\.\\MaoYu"		// 驱动设备的符号链接

// 驱动通信IO控制码
#define USER_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0xFFF, METHOD_BUFFERED, FILE_ANY_ACCESS)

using namespace std;

int main(int argc, char** argv)
{
	//	打开驱动设备
	auto h_file = ::CreateFileW(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (h_file == INVALID_HANDLE_VALUE)		// 如果设备打开失败,则打印错误码
	{
		cout << "错误码:" << ::GetLastError() << endl;
		system("pause");
		return 1;
	}
	else
	{
		cout << "打开设备成功" << endl;
	}

	system("pause");

	DWORD a = 666, b = 0;			

	DWORD out_length = 0;		// 此变量接收驱动返回的长度

	OVERLAPPED overlapped;		// 包含异步(重叠)输入/输出(I/O)中使用的信息。包含异步(重叠)输入/输出(I/O)中使用的信息。

	memset(&overlapped, 0, sizeof(overlapped));		// 使用之前必须初始化该内存为 0

	// 与驱动设备进行通信		驱动设备会将 a *=5   然后写入到 b 变量中
	if (!DeviceIoControl(h_file, USER_CODE, &a, sizeof(a), &b, sizeof(b), &out_length, &overlapped))
	{
		cout << "错误码:" << ::GetLastError() << endl;
	}
	else
	{
		cout << "b = " << b << endl;
	}

	if (::CloseHandle(h_file))			// 关闭驱动设备
	{
		cout << "关闭设备成功" << endl;
	}
	else
	{
		cout << "关闭设备失败" << endl;
	}

	system("pause");
}


你可能感兴趣的:(驱动 与应用层DeviceIoContro() 通信)