概述
前言
我们知道我们驱动存在的意义往往是用于驱动硬件,而一个硬件读写大多数操作系统都是为文件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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复