我是靠谱客的博主 感性便当,最近开发中收集的这篇文章主要介绍windows 驱动与内核调试 学习2前言微软IRP设计reference,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

我们知道我们驱动存在的意义往往是用于驱动硬件,而一个硬件读写大多数操作系统都是为文件io。既然是文件那么必然涉及到文件打开,读写等。我们看看在内核驱动该如何实现这些逻辑操作。


//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)
{
	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("hello  drive loaded");
	//触发一个断点
	//DbgBreakPoint();
	//驱动卸载回调注册
	DriverObject->DriverUnload = myUnload;


	//设置一个驱动映射的文件名称,RtlInitUnicodeString是一个便捷创建内核UNICODE_STRING函数
	UNICODE_STRING ustrDevName;
	//使用工具函数创建一个名叫MytestDriver驱动文件
	RtlInitUnicodeString(&ustrDevName, L"\Device\MytestDriver");
	//用于保存创建结果
	PDEVICE_OBJECT  pDevObj = NULL;
	
	//IoCreateDevice用于创建一个DEVICE_OBJECT对象
	auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);


	if (NT_SUCCESS(ret))
	{
	//
		DbgPrint("IoCreateDevice 成功 %prn", ret);
	}
	else {
		DbgPrint("IoCreateDevice 失败rn");
		return STATUS_FAIL_CHECK;
	}

	//这里便是注册驱动文件读写相关回调
	//注册一个创建文件回调
	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	//注册文件关闭
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	//读取
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	//写入
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	//控制相关 其实也可以使用写入代替 但是为了职责分明额外多一个回调
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;

	return STATUS_SUCCESS;
}

当函数卸载的时候一定要记得删除驱动文件哦

//这个函数被注册用于驱动卸载调用
VOID myUnload(
	struct _DRIVER_OBJECT* DriverObject
) {
	UNREFERENCED_PARAMETER(DriverObject);

	DbgPrint("hello  drive unloaded");

	PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;

	if (DriverObject->DeviceObject !=NULL)
	{
		DbgPrint("驱动文件不为空执行删除");
		IoDeleteDevice(DeviceObject);
	}
}


我们贴出完成相关代码


#include <Ntddk.h>

//这个函数被注册用于驱动卸载调用
VOID myUnload(
	struct _DRIVER_OBJECT* DriverObject
) {
	UNREFERENCED_PARAMETER(DriverObject);

	DbgPrint("hello  drive unloaded");

	PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;

	if (DriverObject->DeviceObject !=NULL)
	{
		DbgPrint("驱动文件不为空执行删除");
		IoDeleteDevice(DeviceObject);
	}
}



NTSTATUS
DispatchCreate(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}
NTSTATUS
DispatchClose(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}

NTSTATUS
DispatchRead(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}
NTSTATUS
DispatchWrite(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}

NTSTATUS
DispatchControl(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}


//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)
{
	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("hello  drive loaded");
	//触发一个断点
	//DbgBreakPoint();
	//驱动卸载回调注册
	DriverObject->DriverUnload = myUnload;


	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;


	UNICODE_STRING ustrDevName;
	RtlInitUnicodeString(&ustrDevName, L"\Device\MytestDriver");
	PDEVICE_OBJECT  pDevObj = NULL;
	auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);


	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateDevice 成功 %prn", ret);
	}
	else {
		DbgPrint("IoCreateDevice 失败rn");
		return STATUS_FAIL_CHECK;
	}


	return STATUS_SUCCESS;
}

我们利用工具将驱动文件进行加载
在这里插入图片描述
然后我们在利用winobj查看我们注册驱动文件

在这里插入图片描述
我们最后执行卸载操作。
在这里插入图片描述
上面的注册驱动文件不能在ring3 进行文件读写,如果你期望ring3也可以驱动需要额外注册一个另一个映射名(符号链接 )
相关代码如下

	UNICODE_STRING symbolDevName;
	RtlInitUnicodeString(&symbolDevName, L"\DosDevices\MytestDriver");
	ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateSymbolicLink 成功 rn");
	}
	else {
		DbgPrint("IoCreateSymbolicLink 失败%drn", ret);

		IoDeleteDevice(pDevObj);

		return STATUS_FAIL_CHECK;
	}

同样我们加载驱动
在这里插入图片描述

在这里插入图片描述
再卸载的时候同样记得要删除。

#include <Ntddk.h>



//这个函数被注册用于驱动卸载调用
VOID myUnload(
	struct _DRIVER_OBJECT* DriverObject
) {
	UNREFERENCED_PARAMETER(DriverObject);

	DbgPrint("hello  drive unloaded");

	PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;

	if (DriverObject->DeviceObject != NULL)
	{
		DbgPrint("驱动文件不为空执行删除");
		IoDeleteDevice(DeviceObject);


		UNICODE_STRING symbolDevName;
		RtlInitUnicodeString(&symbolDevName, L"\DosDevices\MytestDriver");
		IoDeleteSymbolicLink(&symbolDevName);
	}
}



//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)
{
	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("hello  drive loaded");
	//触发一个断点
	//DbgBreakPoint();
	//驱动卸载回调注册
	DriverObject->DriverUnload = myUnload;


	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;


	UNICODE_STRING ustrDevName;
	RtlInitUnicodeString(&ustrDevName, L"\Device\MytestDriver");
	PDEVICE_OBJECT  pDevObj = NULL;
	auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);




	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateDevice 成功 rn");
	}
	else {
		DbgPrint("IoCreateDevice 失败 %drn", ret);
		return STATUS_FAIL_CHECK;
	}


	UNICODE_STRING symbolDevName;
	RtlInitUnicodeString(&symbolDevName, L"\DosDevices\MytestDriver");
	ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateSymbolicLink 成功 rn");
	}
	else {
		DbgPrint("IoCreateSymbolicLink 失败%drn", ret);

		IoDeleteDevice(pDevObj);

		return STATUS_FAIL_CHECK;
	}

	return STATUS_SUCCESS;
}

微软IRP设计

以下来自微软官方的一个设计架构图
在这里插入图片描述
具体可参阅
(2) End-User I/O Requests and File Objects

微软使用IRP设计用于应用层和驱动层传递数据,并且驱动可以进行继续分层处理(比如文件系统驱动 可能有多个驱动 1级驱动提供读写 2级别提供特定大小的缓存功能的读写)。

我们现在完善上文驱动读写操作

NTSTATUS
DispatchRead(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	DbgPrint("DispatchRead");

	UNREFERENCED_PARAMETER(DeviceObject);

	//因为分层驱动的设计,所以需要从Irp获取当前层级的参数
	PIO_STACK_LOCATION	pIrp = IoGetCurrentIrpStackLocation(Irp);
	//上册指定缓存区长度
	ULONG nLength = pIrp->Parameters.Read.Length;

	DbgPrint("DispatchRead buffer:%s bytes:%d", Irp->UserBuffer, nLength);
	//拷贝缓冲区
	memcpy(Irp->UserBuffer,"helloread",10);
	
	//通知上册成功写入
	Irp->IoStatus.Status = STATUS_SUCCESS;
	//通知上层写入的大小
	Irp->IoStatus.Information = 10;
	//回调给io处理器完成请求
	IoCompleteRequest(Irp, IO_NO_INCREMENT);


	return STATUS_SUCCESS;
}

其他读写操作类似就不再举例

#include <Ntddk.h>



//这个函数被注册用于驱动卸载调用
VOID myUnload(
	struct _DRIVER_OBJECT* DriverObject
) {
	UNREFERENCED_PARAMETER(DriverObject);

	DbgPrint("hello  drive unloaded");

	PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;

	if (DriverObject->DeviceObject != NULL)
	{
		DbgPrint("驱动文件不为空执行删除");
		IoDeleteDevice(DeviceObject);


		UNICODE_STRING symbolDevName;
		RtlInitUnicodeString(&symbolDevName, L"\DosDevices\MytestDriver");
		IoDeleteSymbolicLink(&symbolDevName);
	}
}



NTSTATUS
DispatchCreate(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	DbgPrint("DispatchCreate");

	return STATUS_SUCCESS;
}
NTSTATUS
DispatchClose(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	DbgPrint("DispatchClose");

	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}

NTSTATUS
DispatchRead(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	DbgPrint("DispatchRead");

	UNREFERENCED_PARAMETER(DeviceObject);


	PIO_STACK_LOCATION	pIrp = IoGetCurrentIrpStackLocation(Irp);
	ULONG nLength = pIrp->Parameters.Read.Length;

	DbgPrint("DispatchRead buffer:%s bytes:%d", Irp->UserBuffer, nLength);
	memcpy(Irp->UserBuffer,"helloread",10);

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 10;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);


	return STATUS_SUCCESS;
}
NTSTATUS
DispatchWrite(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	DbgPrint("DispatchWrite");
	UNREFERENCED_PARAMETER(DeviceObject);


	PIO_STACK_LOCATION	pIrp = IoGetCurrentIrpStackLocation(Irp);
	ULONG nLength = pIrp->Parameters.Write.Length;

	DbgPrint("DispatchWrite buffer:%s bytes:%d", Irp->UserBuffer, nLength);

	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 6;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

NTSTATUS
DispatchControl(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) {
	DbgPrint("DispatchControl");

	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);
	return STATUS_SUCCESS;
}


//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)
{
	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("hello  drive loaded");
	//触发一个断点
	//DbgBreakPoint();
	//驱动卸载回调注册
	DriverObject->DriverUnload = myUnload;


	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;


	UNICODE_STRING ustrDevName;
	RtlInitUnicodeString(&ustrDevName, L"\Device\MytestDriver");
	PDEVICE_OBJECT  pDevObj = NULL;
	auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);




	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateDevice 成功 rn");
	}
	else {
		DbgPrint("IoCreateDevice 失败 %drn", ret);
		return STATUS_FAIL_CHECK;
	}


	UNICODE_STRING symbolDevName;
	RtlInitUnicodeString(&symbolDevName, L"\DosDevices\MytestDriver");
	ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
	if (NT_SUCCESS(ret))
	{
		DbgPrint("IoCreateSymbolicLink 成功 rn");
	}
	else {
		DbgPrint("IoCreateSymbolicLink 失败%drn", ret);

		IoDeleteDevice(pDevObj);

		return STATUS_FAIL_CHECK;
	}

	return STATUS_SUCCESS;
}

最后写一个应用层代码进行读写

// InvotationDevApp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<Windows.h>
#include<stdlib.h>
int main()
{
	std::cout << "Hello World!n";


	HANDLE hFile;
	hFile = CreateFile("\\?\MytestDriver",
		GENERIC_WRITE | GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		std::cout << "INVALID_HANDLE_VALUE  "<< GetLastError()<<"n";

		return EXIT_FAILURE;
	}

	std::cout << "open okn";
	DWORD dwBytes = 0;
	if (WriteFile(hFile, "hello", 6, &dwBytes, NULL))
	{
		std::cout << "write ok " << dwBytes << std::endl;
	}
	else {
		std::cout << "write failure " << dwBytes << std::endl;
	}

	DWORD drBytes = 0;
	char szBuffer[120];
	if (ReadFile(hFile, szBuffer, sizeof szBuffer, &drBytes, NULL))
	{
		std::cout << "read ok  " << drBytes << " "<< szBuffer << std::endl;
	}
	else {
		std::cout << "read failure " << std::endl;
	}


	CloseHandle(hFile);
	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

reference

(1) a simple demo for WDM driver

(2) End-User I/O Requests and File Objects

最后

以上就是感性便当为你收集整理的windows 驱动与内核调试 学习2前言微软IRP设计reference的全部内容,希望文章能够帮你解决windows 驱动与内核调试 学习2前言微软IRP设计reference所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部