0
点赞
收藏
分享

微信扫一扫

Windows驱动开发-IO访问

像小强一样活着 2022-04-08 阅读 56
windows
// 驱动代码
#include <ntddk.h>

#define CTLBUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CTLDIRECTIN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define CTLDIRECTOUT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)

typedef struct _DevExt
{
	ULONG Flags;
}DevExt, *PDevExt;

// 卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);

// 派遣函数-常规
NTSTATUS DispatchGeneric(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

// 派遣函数-IoDeviceControl
NTSTATUS DispatchIoDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

// 入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\IoDeviceControl");
	UNICODE_STRING DeviceSymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\IoDeviceControl");
	PDEVICE_OBJECT DeviceObject = NULL;
	ULONG sub = 0;

	UNREFERENCED_PARAMETER(RegistryPath);
	KdPrint(("驱动加载\n"));

	for (sub = 0; sub <= IRP_MJ_MAXIMUM_FUNCTION; sub++)
	{
		DriverObject->MajorFunction[sub] = DispatchGeneric;
	}

	// IODeviceControl
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoDeviceControl;

	// 创建设备
	status = IoCreateDevice(DriverObject, sizeof(DevExt), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建设备失败:%x\n", status));
		return status;
	}

	// 创建符号链接
	status = IoCreateSymbolicLink(&DeviceSymbolicLinkName, &DeviceName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建符号链接失败:%x", status));
		IoDeleteDevice(DeviceObject);
		DeviceObject = NULL;
		return status;
	}

	DeviceObject->Flags |= DO_BUFFERED_IO;
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

	DriverObject->DriverUnload = DriverUnload;

	return status;
}

// 卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING DeviceSymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\IoDeviceControl");

	UNREFERENCED_PARAMETER(DriverObject);
	KdPrint(("驱动卸载\n"));

	if (DriverObject->DeviceObject != NULL)
	{
		IoDeleteSymbolicLink(&DeviceSymbolicLinkName);
		IoDeleteDevice(DriverObject->DeviceObject);
	}
}

// 派遣函数-常规
NTSTATUS DispatchGeneric(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;

	UNREFERENCED_PARAMETER(DeviceObject);

	Irp->IoStatus.Information = 0;
	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return status;
}
// 派遣函数-IoDeviceControl
NTSTATUS DispatchIoDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
	PDevExt devExt = (PDevExt)DeviceObject->DeviceExtension;
	ULONG IoCode = stack->Parameters.DeviceIoControl.IoControlCode;
	ULONG InputLength = 0;
	ULONG OutputLength = 0;
	PVOID InputBuffer = NULL;
	PVOID OutputBuffer = NULL;
	ULONG ReturnLength = 0;

	__try
	{
		devExt->Flags = 0;
		switch (IoCode)
		{
		case CTLBUFFERED:
		{
			InputBuffer = Irp->AssociatedIrp.SystemBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;

			KdPrint(("***********************************************\n"));

			KdPrint(("Input Data:%s\nOutput Data:%s\n", InputBuffer, OutputBuffer));
			KdPrint(("Input Address:%x\nInput Length:%d\nOutput Address:%x\nOutput Length:%d\n", InputBuffer, InputLength, OutputBuffer, OutputLength));

			RtlCopyMemory(OutputBuffer, "这是IO缓冲区方式", strlen("这是IO缓冲区方式"));
			ReturnLength = (ULONG)strlen("这是IO缓冲区方式");

		}
			break;
		case CTLDIRECTIN:
		{
			InputBuffer = Irp->AssociatedIrp.SystemBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;

			KdPrint(("***********************************************\n"));

			KdPrint(("Input Data:%s\nOutput Data:%s\n", InputBuffer, OutputBuffer));
			KdPrint(("Input Address:%x\nInput Length:%d\nOutput Address:%x\nOutput Length:%d\n", InputBuffer, InputLength, OutputBuffer, OutputLength));

			ReturnLength = 0;
		}
			break;
		case CTLDIRECTOUT:
		{
			InputBuffer = Irp->AssociatedIrp.SystemBuffer;
			InputLength = stack->Parameters.DeviceIoControl.InputBufferLength;
			OutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
			OutputLength = stack->Parameters.DeviceIoControl.OutputBufferLength;

			KdPrint(("***********************************************\n"));

			KdPrint(("Input Data:%s\nOutput Data:%s\n", InputBuffer, OutputBuffer));
			KdPrint(("Input Address:%x\nInput Length:%d\nOutput Address:%x\nOutput Length:%d\n", InputBuffer, InputLength, OutputBuffer, OutputLength));

			RtlCopyMemory(OutputBuffer, "这是直接访问方式", strlen("这是直接访问方式"));
			ReturnLength = (ULONG)strlen("这是直接访问方式");
		}
			break;

		}
	}

	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		status = GetExceptionCode();
		ReturnLength = 0;
	}

	Irp->IoStatus.Information = ReturnLength;
	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return status;
}

// 用户代码
#include <Windows.h>
#include <stdio.h>
#include <winioctl.h>

#define IOBUFTEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IODIRECTIN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define IODIRECTOUT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0800, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)

int main(int argc, char* argv[])
{
	HANDLE hDevice = CreateFile(L"\\\\.\\IoDeviceControl", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("设备打开失败:%d\n", GetLastError());
		getchar();
		return -1;
	}

	// 发送IO请求
	CHAR buf[1024] = { 0 };
	DWORD dwRet = 0;
	DeviceIoControl(hDevice, IOBUFTEST, (LPVOID)"这是用户缓冲区方式", (DWORD)strlen("这是用户缓冲区方式") + 1, buf, 1024, &dwRet, NULL);
	printf("%s\n", buf);

	DeviceIoControl(hDevice, IODIRECTIN, (LPVOID)"这是用户缓冲区方式", (DWORD)strlen("这是用户缓冲区方式") + 1, NULL, 0, &dwRet, NULL);

	DeviceIoControl(hDevice, IODIRECTOUT, NULL, 0, buf, 1024, &dwRet, NULL);
	printf("%s\n", buf);

	CloseHandle(hDevice);

	getchar();
	return 0;
}


举报

相关推荐

0 条评论