win10驱动开发15——派遣函数(缓冲区方式读写操作)

驱动层

#include <ntddk.h>   
#include <windef.h>

VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
	IoDeleteSymbolicLink(&SymbolicLinkName);//删除连接
	IoDeleteDevice(pDriverObject->DeviceObject);//释放驱动对象
	//驱动卸载的时候显示
	KdPrint(("Goodbye driver\n"));
}


NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	static char* irpname[] = {
		"IRP_MJ_CREATE                  ",
		"IRP_MJ_CREATE_NAMED_PIPE       ",
		"IRP_MJ_CLOSE                   ",
		"IRP_MJ_READ                    ",
		"IRP_MJ_WRITE                   ",
		"IRP_MJ_QUERY_INFORMATION       ",
		"IRP_MJ_SET_INFORMATION         ",
		"IRP_MJ_QUERY_EA                ",
		"IRP_MJ_SET_EA                  ",
		"IRP_MJ_FLUSH_BUFFERS           ",
		"IRP_MJ_QUERY_VOLUME_INFORMATION",
		"IRP_MJ_SET_VOLUME_INFORMATION  ",
		"IRP_MJ_DIRECTORY_CONTROL       ",
		"IRP_MJ_FILE_SYSTEM_CONTROL     ",
		"IRP_MJ_DEVICE_CONTROL          ",
		"IRP_MJ_INTERNAL_DEVICE_CONTROL ",
		"IRP_MJ_SHUTDOWN                ",
		"IRP_MJ_LOCK_CONTROL            ",
		"IRP_MJ_CLEANUP                 ",
		"IRP_MJ_CREATE_MAILSLOT         ",
		"IRP_MJ_QUERY_SECURITY          ",
		"IRP_MJ_SET_SECURITY            ",
		"IRP_MJ_POWER                   ",
		"IRP_MJ_SYSTEM_CONTROL          ",
		"IRP_MJ_DEVICE_CHANGE           ",
		"IRP_MJ_QUERY_QUOTA             ",
		"IRP_MJ_SET_QUOTA               ",
		"IRP_MJ_PNP                     ",
		"IRP_MJ_PNP_POWER               ",
		"IRP_MJ_MAXIMUM_FUNCTION        "
	};

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	KdPrint(("%s\n", irpname[stack->MajorFunction]));
	Irp->IoStatus.Information = 0;
	Irp->IoStatus.Status = STATUS_SUCCESS;//设置返回状态,告诉操作是成功还是失败
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return STATUS_SUCCESS;
};

NTSTATUS DispatchRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	PVOID pReadBuffer = NULL;
	NTSTATUS status;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG Length;
	ULONG uMin;
	KdPrint(("读操作\n"));
	__try 
	{
		if (stack->Parameters.Read.Length > 512)
		{
			//ULONG  uHelloStr = (wcslen(L"这是一段来自内核空间的字符串") + 1) * sizeof(WCHAR);
			//uMin = Length > uHelloStr ? uHelloStr : Length;
			uMin = strlen("这是一段来自内核空间的字符串");
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, "这是一段来自内核空间的字符串", uMin); //拷贝到缓冲区中给3环
			status = STATUS_SUCCESS;
			Length = strlen("这是一段来自内核空间的字符串");
		}
		else
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER) 
	{
		status = GetExceptionCode();
		Length = 0;
	}

	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = Length;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}

NTSTATUS DispatchWrite(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG Length;
	KdPrint(("写操作\n"));
	__try
	{
		Length = stack->Parameters.Write.Length;
		if (Length>1)
		{
			KdPrint(("%s\n", Irp->AssociatedIrp.SystemBuffer));
			status = STATUS_SUCCESS;
		}
		else 
		{
			status = STATUS_INVALID_PARAMETER;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = Length;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}

NTSTATUS DispatchQueryInfo(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG Length;
	KdPrint(("查操作\n"));
	__try
	{
		Length = stack->Parameters.QueryFile.Length;
		if (stack->Parameters.QueryFile.FileInformationClass == FileStandardInformation &&
			Length>=sizeof(FILE_STANDARD_INFORMATION)
			)
		{
			PFILE_STANDARD_INFORMATION  pfsi = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
			pfsi->EndOfFile.LowPart = 512 * 10;
			status = STATUS_SUCCESS;
			Length = sizeof(FILE_STANDARD_INFORMATION);
		}
		else
		{
			status = STATUS_BUFFER_TOO_SMALL;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = Length;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}



extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK");
	UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
	NTSTATUS status;
	PDEVICE_OBJECT DeviceObject;
	ULONG i = 0;
	KdPrint(("Hello driver\n"));
	DriverObject->DriverUnload = Unload;
	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
	{
		DriverObject->MajorFunction[i] = DispatchRoutine;
	}
	//读操作
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	//写操作
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	//查操作
	DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
	//让设备对象知道驱动的位置
	status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建设备失败%x\n", status));
		return status;
	}
	status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("符号连接创建失败%x\n", status));
		IoDeleteDevice(DeviceObject);
		return status;
	}
	DeviceObject->Flags |= DO_BUFFERED_IO;
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	return STATUS_SUCCESS;
}

应用层

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

#define IOTEST CTL_CODE(FILE_DEVICE_UNKNOWN,0X800,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main() 
{
	HANDLE hDevice = CreateFile(TEXT("\\\\.\\HelloDDK"),
		GENERIC_ALL,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);
	if (hDevice ==INVALID_HANDLE_VALUE)
	{
		printf("设备打开失败%d\n", GetLastError());
		return -1;
	}
	DWORD dwRet;
	CHAR Buffer[1024] = { 0 };
	ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
	printf("读回来的数据%s\n",Buffer);
	printf("读取数据的个数%d\n", dwRet);
	WriteFile(hDevice, "这是一段来自用户层的数据", strlen("这是一段来自用户层的数据"), &dwRet, NULL);
	DWORD dwSize=GetFileSize(hDevice, NULL);
	printf("文件长度%d\n", dwSize);
	DeviceIoControl(hDevice, IOTEST, NULL, 0, NULL, 0, &dwRet, NULL);
	CloseHandle(hDevice);
	return 0;
}

在这里插入图片描述

高级篇(完整的读写操作)
内核层

#include <ntddk.h>   
#include <windef.h>

typedef struct _DEVICE_EXTENSION 
{
	PCHAR Buffer;//内存首地址
	ULONG Length;//文件长度
#define MAX_FILE_LEN 4096
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

VOID Unload(IN PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
	IoDeleteSymbolicLink(&SymbolicLinkName);//删除连接
	IoDeleteDevice(pDriverObject->DeviceObject);//释放驱动对象
	//驱动卸载的时候显示
	KdPrint(("Goodbye driver\n"));
}


NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	static char* irpname[] = {
		"IRP_MJ_CREATE                  ",
		"IRP_MJ_CREATE_NAMED_PIPE       ",
		"IRP_MJ_CLOSE                   ",
		"IRP_MJ_READ                    ",
		"IRP_MJ_WRITE                   ",
		"IRP_MJ_QUERY_INFORMATION       ",
		"IRP_MJ_SET_INFORMATION         ",
		"IRP_MJ_QUERY_EA                ",
		"IRP_MJ_SET_EA                  ",
		"IRP_MJ_FLUSH_BUFFERS           ",
		"IRP_MJ_QUERY_VOLUME_INFORMATION",
		"IRP_MJ_SET_VOLUME_INFORMATION  ",
		"IRP_MJ_DIRECTORY_CONTROL       ",
		"IRP_MJ_FILE_SYSTEM_CONTROL     ",
		"IRP_MJ_DEVICE_CONTROL          ",
		"IRP_MJ_INTERNAL_DEVICE_CONTROL ",
		"IRP_MJ_SHUTDOWN                ",
		"IRP_MJ_LOCK_CONTROL            ",
		"IRP_MJ_CLEANUP                 ",
		"IRP_MJ_CREATE_MAILSLOT         ",
		"IRP_MJ_QUERY_SECURITY          ",
		"IRP_MJ_SET_SECURITY            ",
		"IRP_MJ_POWER                   ",
		"IRP_MJ_SYSTEM_CONTROL          ",
		"IRP_MJ_DEVICE_CHANGE           ",
		"IRP_MJ_QUERY_QUOTA             ",
		"IRP_MJ_SET_QUOTA               ",
		"IRP_MJ_PNP                     ",
		"IRP_MJ_PNP_POWER               ",
		"IRP_MJ_MAXIMUM_FUNCTION        "
	};

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	KdPrint(("%s\n", irpname[stack->MajorFunction]));
	Irp->IoStatus.Information = 0;
	Irp->IoStatus.Status = STATUS_SUCCESS;//设置返回状态,告诉操作是成功还是失败
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return STATUS_SUCCESS;
};

NTSTATUS DispatchRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
	ULONG Length=0;
	ULONG offset;
	ULONG ReadLength;//读取到的实际长度
	KdPrint(("读操作\n"));
	__try 
	{
		Length = stack->Parameters.Read.Length;
		offset = stack->Parameters.Read.ByteOffset.LowPart;
		if (Length + offset <= MAX_FILE_LEN)
		{
			if (Length + offset > pdx->Length)
			{
				//空间不足,实际能读取到的长度;
				ReadLength = pdx->Length -offset;
			}
			else 
			{
				ReadLength = Length;
			}
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, pdx->Buffer+offset, ReadLength); //拷贝到缓冲区中给3环
			status = STATUS_SUCCESS;
		}
		else
		{
			status = STATUS_BUFFER_TOO_SMALL;
			ReadLength = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER) 
	{
		status = GetExceptionCode();
		ReadLength = 0;
	}
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = ReadLength;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}
//首先不能超过内存块,在内存卡之内我写的文件长度,超过文件长度就需要更新文件长度,不超过文件长度保持不变
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
	ULONG Length;
	ULONG offset;
	ULONG WriteLenth;//写出的实际长度
	KdPrint(("写操作\n"));
	__try
	{
		Length = stack->Parameters.Write.Length;
		offset=stack->Parameters.Write.ByteOffset.LowPart;
		if (Length+offset <= MAX_FILE_LEN)
		{
			if (Length+offset>pdx->Length)
			{
				//更新文件长度
				pdx->Length = Length + offset;
			}
			RtlCopyMemory(pdx->Buffer+offset,Irp->AssociatedIrp.SystemBuffer,Length);
			WriteLenth = Length;
		}
		else 
		{
			status = STATUS_BUFFER_TOO_SMALL;//缓冲区太小的错误
			WriteLenth = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		WriteLenth = 0;
	}
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = WriteLenth;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}

NTSTATUS DispatchQueryInfo(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status;
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG Length;
	KdPrint(("查操作\n"));
	__try
	{
		Length = stack->Parameters.QueryFile.Length;
		if (stack->Parameters.QueryFile.FileInformationClass == FileStandardInformation &&
			Length>=sizeof(FILE_STANDARD_INFORMATION)
			)
		{
			PFILE_STANDARD_INFORMATION  pfsi = (PFILE_STANDARD_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
			pfsi->EndOfFile.LowPart = pdx->Length;
			status = STATUS_SUCCESS;
			Length = sizeof(FILE_STANDARD_INFORMATION);
		}
		else
		{
			status = STATUS_BUFFER_TOO_SMALL;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = Length;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK");
	UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\HelloDDK");
	NTSTATUS status;
	PDEVICE_OBJECT DeviceObject;
	PDEVICE_EXTENSION pdx;
	ULONG i = 0;
	KdPrint(("Hello driver\n"));
	DriverObject->DriverUnload = Unload;
	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++)
	{
		DriverObject->MajorFunction[i] = DispatchRoutine;
	}
	//读操作
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	//写操作
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	//查操作
	DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
	//让设备对象知道驱动的位置
	status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建设备失败%x\n", status));
		return status;
	}
	status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("符号连接创建失败%x\n", status));
		IoDeleteDevice(DeviceObject);
		return status;
	}
	DeviceObject->Flags |= DO_BUFFERED_IO;
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	pdx = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
	pdx->Buffer = (PCHAR)ExAllocatePoolWithTag(PagedPool, 4096, 'a');
	pdx->Length = 0;
	return STATUS_SUCCESS;
}

应用层

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

#define IOTEST CTL_CODE(FILE_DEVICE_UNKNOWN,0X800,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main() 
{
	HANDLE hDevice = CreateFile(TEXT("\\\\.\\HelloDDK"),
		GENERIC_ALL,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);
	if (hDevice ==INVALID_HANDLE_VALUE)
	{
		printf("设备打开失败%d\n", GetLastError());
		return -1;
	}
	DWORD dwRet;
	CHAR Buffer[1024] = { 0 };
	WriteFile(hDevice, "这是一段来自用户层的数据", strlen("这是一段来自用户层的数据"), &dwRet, NULL);
	ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
	printf("读回来的数据%s\n",Buffer);
	printf("读取数据的个数%d\n", dwRet);
	DWORD dwSize=GetFileSize(hDevice, NULL);
	printf("文件长度%d\n", dwSize);
	DeviceIoControl(hDevice, IOTEST, NULL, 0, NULL, 0, &dwRet, NULL);
	CloseHandle(hDevice);
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值