管理博文 win10驱动开发17——驱动交互

直接内存模式

参数位置
输入缓冲区Irp->AssociatedIrp.SystemBuffer
输入缓冲区大小stack->Parameters.DeviceIoControl.InputBufferLength
输出缓冲区Irp->AssociatedIrp.SystemBuffer
输出缓冲区大小stack->Parameters.DeviceIoControl.OutputBufferLength
IO控制码stack->Parameters.DeviceIoControl.IoControlCode

内核层

#include <ntddk.h>   
#include <windef.h>
#define  CTLBUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
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 NeitherRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG Length;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	__try
	{
		ProbeForWrite(Irp->UserBuffer, stack->Parameters.Read.Length, 4);
		Length = strlen("这是一段来自内核地址空间的数据");
		RtlCopyMemory(Irp->UserBuffer, "这是一段来自内核地址空间的数据", Length);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}

	Irp->IoStatus.Status = status;//设置返回状态,告诉操作是成功还是失败
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}
//mdl直接方式读取
NTSTATUS DirectRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	KdPrint(("进入DirectRead:\n"));
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	PCHAR Buffer;
	ULONG ByteOffset;
	ULONG ByteCount;
	ULONG Length;
	PVOID Va;
	__try
	{
		ByteOffset = MmGetMdlByteCount(Irp->MdlAddress);
		ByteCount = MmGetMdlByteCount(Irp->MdlAddress);
		Va = MmGetMdlVirtualAddress(Irp->MdlAddress);
		KdPrint(("ByteOffset:%d\n", ByteOffset));
		KdPrint(("ByteCount:%d\n", ByteCount));
		KdPrint(("用户空间地址:%p\n", Va));
		Buffer = (PCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
		if (stack->Parameters.Read.Length <= ByteCount)
		{
			Length = strlen("这是一段来自内核地址空间的数据");
			RtlCopyMemory(Buffer, "这是一段来自内核地址空间的数据", Length);
		}
		else 
		{
			status = STATUS_UNSUCCESSFUL;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}

	Irp->IoStatus.Status = status;//设置返回状态,告诉操作是成功还是失败
	Irp->IoStatus.Information = 0;
	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;
}

NTSTATUS DispatchControl(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG IoCode = stack->Parameters.DeviceIoControl.IoControlCode;
	ULONG InputLength;
	ULONG OutputLength;
	PVOID InputBuffer;
	PVOID OutputBuffer;
	ULONG Length;
	switch (IoCode)
	{
	case CTLBUFFERED:
		InputBuffer = Irp->AssociatedIrp.SystemBuffer;
		InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
		OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
		OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;
		KdPrint(("InputBuffer:%s\n", InputBuffer));
		KdPrint(("InputLength:%d\n", InputLength));
		RtlCopyMemory(OutputBuffer, "这是缓冲区io方式", strlen("这是缓冲区io方式"));
		Length = strlen("这是缓冲区io方式");
		KdPrint(("OutputBuffer:%s\n", OutputBuffer));
		KdPrint(("OutputLength:%d\n", OutputLength));
		break;
	default:
		break;
	}
	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] = NeitherRead;
	//写操作
	//DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	//查操作
	DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
	//让设备对象知道驱动的位置
	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 |= 0;//0表示其他方式读取 配合NeitherRead方法使用  //DO_BUFFERED_IO 配合DirectRead方法使用
	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)
#define  CTLBUFFERED 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);
	printf("驱动提供的地址:%p\n", Buffer);
	ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
	printf("读回来的数据%s\n", Buffer);
	printf("读取数据的个数%d\n", dwRet);
	DWORD dwSize = GetFileSize(hDevice, NULL);
	printf("文件长度%d\n", dwSize);
	char IoBuffer[1024] = { 0 };
	//+1 不至于输出乱码的情况
	DeviceIoControl(hDevice, CTLBUFFERED, (LPVOID)"这是缓冲区方式", strlen("这是缓冲区方式")+1, IoBuffer, sizeof(IoBuffer), &dwRet, NULL);
	printf("%s\n",IoBuffer);
	CloseHandle(hDevice);
	return 0;
}

在这里插入图片描述

其他内存模式

参数位置
输入缓冲区stack->Parameters.DeviceIoControl.Type3InputBuffer
输入缓冲区大小stack->Parameters.DeviceIoControl.InputBufferLength
输出缓冲区Irp->UserBuffer
输出缓冲区大小stack->Parameters.DeviceIoControl.OutputBufferLength
IO控制码stack->Parameters.DeviceIoControl.IoControlCode

内核层

#include <ntddk.h>   
#include <windef.h>
#define  CTLBUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
// METHOD_IN_DIRECT              只能输入
// METHOD_OUT_DIRECT             能输入也能输出
#define  CTLDIRECT   CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
#define  CTLNEITHER   CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_NEITHER,FILE_ANY_ACCESS)
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 NeitherRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG Length;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	__try
	{
		ProbeForWrite(Irp->UserBuffer, stack->Parameters.Read.Length, 4);
		Length = strlen("这是一段来自内核地址空间的数据");
		RtlCopyMemory(Irp->UserBuffer, "这是一段来自内核地址空间的数据", Length);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}

	Irp->IoStatus.Status = status;//设置返回状态,告诉操作是成功还是失败
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);//是不改变
	return status;
}
//mdl直接方式读取
NTSTATUS DirectRead(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	KdPrint(("进入DirectRead:\n"));
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	PCHAR Buffer;
	ULONG ByteOffset;
	ULONG ByteCount;
	ULONG Length;
	PVOID Va;
	__try
	{
		ByteOffset = MmGetMdlByteCount(Irp->MdlAddress);
		ByteCount = MmGetMdlByteCount(Irp->MdlAddress);
		Va = MmGetMdlVirtualAddress(Irp->MdlAddress);
		KdPrint(("ByteOffset:%d\n", ByteOffset));
		KdPrint(("ByteCount:%d\n", ByteCount));
		KdPrint(("用户空间地址:%p\n", Va));
		Buffer = (PCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
		if (stack->Parameters.Read.Length <= ByteCount)
		{
			Length = strlen("这是一段来自内核地址空间的数据");
			RtlCopyMemory(Buffer, "这是一段来自内核地址空间的数据", Length);
		}
		else
		{
			status = STATUS_UNSUCCESSFUL;
			Length = 0;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		Length = 0;
	}

	Irp->IoStatus.Status = status;//设置返回状态,告诉操作是成功还是失败
	Irp->IoStatus.Information = 0;
	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;
}

NTSTATUS DispatchControl(IN PDEVICE_OBJECT deviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);//获取当前栈单元
	ULONG IoCode = stack->Parameters.DeviceIoControl.IoControlCode;
	ULONG InputLength;
	ULONG OutputLength;
	PVOID InputBuffer;
	PVOID OutputBuffer;
	ULONG Length;
	__try
	{
		switch (IoCode)
		{
		case CTLBUFFERED:
			InputBuffer = Irp->AssociatedIrp.SystemBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;
			KdPrint(("InputBuffer:%s\n", InputBuffer));
			KdPrint(("InputLength:%d\n", InputLength));
			RtlCopyMemory(OutputBuffer, "这是缓冲区io方式", strlen("这是缓冲区io方式"));
			Length = strlen("这是缓冲区io方式");
			break;

		case CTLDIRECT:
			InputBuffer = Irp->AssociatedIrp.SystemBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;
			KdPrint(("InputBuffer:%s\n", InputBuffer));
			KdPrint(("InputLength:%d\n", InputLength));
			RtlCopyMemory(OutputBuffer, "直接方式io控制操作", strlen("直接方式io控制操作"));
			Length = strlen("直接方式io控制操作");
			break;
		case CTLNEITHER:
			InputBuffer = stack->Parameters.DeviceIoControl.Type3InputBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = Irp->UserBuffer;
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;
			KdPrint(("InputBuffer:%s\n", InputBuffer));
			KdPrint(("InputLength:%d\n", InputLength));
			RtlCopyMemory(OutputBuffer, "其他方式io控制操作", strlen("其他方式io控制操作"));
			Length = strlen("其他方式io控制操作");
			break;
		default:
			break;
		}
	}
	__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] = NeitherRead;
	//写操作
	//DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	//查操作
	DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInfo;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
	//让设备对象知道驱动的位置
	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 |= 0;//0表示其他方式读取 配合NeitherRead方法使用
	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)
#define  CTLBUFFERED  CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
// METHOD_IN_DIRECT              只能输入
// METHOD_OUT_DIRECT             能输入也能输出
#define  CTLDIRECT   CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_OUT_DIRECT,FILE_ANY_ACCESS)
#define  CTLNEITHER   CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_NEITHER,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);
	printf("驱动提供的地址:%p\n", Buffer);
	ReadFile(hDevice, Buffer, sizeof(Buffer), &dwRet, NULL);
	printf("读回来的数据%s\n", Buffer);
	printf("读取数据的个数%d\n", dwRet);
	DWORD dwSize = GetFileSize(hDevice, NULL);
	printf("文件长度%d\n", dwSize);
	char IoBuffer[1024] = { 0 };
	//+1 不至于输出乱码的情况
	DeviceIoControl(hDevice, CTLBUFFERED, (LPVOID)"这是缓冲区方式", strlen("这是缓冲区方式")+1, IoBuffer, sizeof(IoBuffer), &dwRet, NULL);
	printf("%s\n", IoBuffer);
	RtlZeroMemory(IoBuffer,sizeof(Buffer));
	DeviceIoControl(hDevice, CTLDIRECT, (LPVOID)"这是直接方式", strlen("这是直接方式")+1, IoBuffer, sizeof(IoBuffer), &dwRet, NULL);
	printf("%s\n", IoBuffer);
	RtlZeroMemory(IoBuffer, sizeof(Buffer));
	DeviceIoControl(hDevice, CTLNEITHER, (LPVOID)"这是其他方式", strlen("这是其他方式")+1, IoBuffer, sizeof(IoBuffer), &dwRet, NULL);
	printf("%s\n", IoBuffer);
	RtlZeroMemory(IoBuffer, sizeof(Buffer));
	CloseHandle(hDevice);
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值