分层驱动之循环读数据

本文介绍了两个设备驱动程序的实现,包括卸载函数和读操作处理。`DriverUnload`函数负责删除设备符号链接并释放设备对象。`DispatchRead`函数处理读请求,填充内存并完成I/O请求。`DriverEntry`函数创建设备并设置调度函数。文章深入探讨了读操作的分阶段处理和内存管理,展示了如何在驱动程序中处理大型数据包。
摘要由CSDN通过智能技术生成
// driverA.c
#include <ntddk.h>

// 卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
	UNICODE_STRING DevSymboliclinkName = { 0 };
	RtlInitUnicodeString(&DevSymboliclinkName, L"\\??\\LayerDriver");

	IoDeleteSymbolicLink(&DevSymboliclinkName);
	
	if (pDriverObject->DeviceObject != NULL)
	{
		IoDeleteDevice(pDriverObject->DeviceObject);
	}
}

// 派遣函数-常规操作
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

// 派遣函数-读操作
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulTotalLength = 0;
	PVOID pMdlAddress = NULL;

	UNREFERENCED_PARAMETER(pDeviceObject);

	if (pIrp->MdlAddress == NULL)
	{
		status = STATUS_UNSUCCESSFUL;
	}
	else
	{
		pMdlAddress = MmGetMdlVirtualAddress(pIrp->MdlAddress);
		ulTotalLength = MmGetMdlByteCount(pIrp->MdlAddress);

		RtlFillMemory(pMdlAddress, ulTotalLength, 0xFF);
	}

	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = ulTotalLength;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}

// 入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING DevName = { 0 };
	UNICODE_STRING DevSymbolicLinkName = { 0 };
	PDEVICE_OBJECT pDevObj = NULL;
	SIZE_T sub = 0;

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

	RtlInitUnicodeString(&DevName, L"\\Device\\LayerDriver");
	RtlInitUnicodeString(&DevSymbolicLinkName, L"\\??\\LayerDriver");

	status = IoCreateDevice(pDriverObject, 0, &DevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建设备失败\n"));
		return status;
	}

	status = IoCreateSymbolicLink(&DevSymbolicLinkName, &DevName);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建符号链接失败\n"));
		IoDeleteDevice(pDevObj);
		return status;
	}

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

	pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;

	pDevObj->Flags |= DO_DIRECT_IO;
	pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

	pDriverObject->DriverUnload = DriverUnload;

	return status;
}

// driverB.c
#include <ntddk.h>

#define MAX_PACKAGE_SIZE 1024

typedef struct _DEVICE_EXTENSION
{
	PDEVICE_OBJECT pTargetDevice;
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef struct _DEVICE_RW_CONTEXT
{
	PMDL							NewMdl;
	PMDL							OldMdl;
	ULONG							Length;
	ULONG							Numxfer;
	ULONG_PTR					VirtualAddress;
	PDEVICE_EXTENSION DeviceExtension;
}DEVICE_RW_CONTEXT, *PDEVICE_RW_CONTEXT;

// 卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING DevSymbolicLinkName = { 0 };
	RtlInitUnicodeString(&DevSymbolicLinkName, L"\\??\\LayerDriverEx");

	IoDeleteSymbolicLink(&DevSymbolicLinkName);

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

// 派遣函数-常规操作
NTSTATUS DispatchRoutine(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);

	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;
}

// 读操作-完成例程
NTSTATUS CompletionRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
{
	PDEVICE_RW_CONTEXT pRWContext = (PDEVICE_RW_CONTEXT)Context;
	NTSTATUS status = pIrp->IoStatus.Status;
	ULONG ulStageLength = 0;
	PIO_STACK_LOCATION pNextStack = NULL;

	UNREFERENCED_PARAMETER(pDeviceObject);

	if (pRWContext && NT_SUCCESS(status))
	{
		// 已经传送了多少字节
		pRWContext->Numxfer += (ULONG)pIrp->IoStatus.Information;
		if (pRWContext->Length)
		{
			ulStageLength = pRWContext->Length > MAX_PACKAGE_SIZE ? MAX_PACKAGE_SIZE : pRWContext->Length;
			
			MmPrepareMdlForReuse(pRWContext->NewMdl);
			IoBuildPartialMdl(pIrp->MdlAddress, pRWContext->NewMdl, (PVOID)pRWContext->VirtualAddress, ulStageLength);
			pRWContext->VirtualAddress += ulStageLength;
			pRWContext->Length -= ulStageLength;
			
			IoCopyCurrentIrpStackLocationToNext(pIrp);
			pNextStack = IoGetNextIrpStackLocation(pIrp);
			pNextStack->Parameters.Read.Length = ulStageLength;
			
			IoSetCompletionRoutine(pIrp, CompletionRead, pRWContext, TRUE, TRUE, TRUE);
			IoCallDriver(pRWContext->DeviceExtension->pTargetDevice, pIrp);
			return STATUS_MORE_PROCESSING_REQUIRED;
		}
		else
		{
			// 最后一次传输
			pIrp->IoStatus.Information = pRWContext->Numxfer;
		}
	}

	return STATUS_MORE_PROCESSING_REQUIRED;
}

// 派遣函数-读操作
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulTotalLength = 0;
	ULONG ulStageLength = 0;
	PVOID pVirtualAddress = NULL;
	PMDL mdl = NULL;
	PDEVICE_RW_CONTEXT pRWContext = NULL;
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
	PIO_STACK_LOCATION pNextStack = NULL;

	if (pIrp->MdlAddress == NULL)
	{
		status = STATUS_UNSUCCESSFUL;
	}
	else
	{
		pVirtualAddress = MmGetMdlVirtualAddress(pIrp->MdlAddress);
		ulTotalLength = MmGetMdlByteCount(pIrp->MdlAddress);

		ulStageLength = (ulTotalLength > MAX_PACKAGE_SIZE) ? MAX_PACKAGE_SIZE : ulTotalLength;

		mdl = IoAllocateMdl((PVOID)pVirtualAddress, ulTotalLength, FALSE, FALSE, NULL);
		if (mdl == NULL)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
		}
		else
		{
			// 将IRP的MDL做重新映射
			IoBuildPartialMdl(pIrp->MdlAddress, mdl, (PVOID)pVirtualAddress, ulStageLength);

			pRWContext = (PDEVICE_RW_CONTEXT)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RW_CONTEXT));
			pRWContext->NewMdl = mdl;
			pRWContext->OldMdl = pIrp->MdlAddress;
			pRWContext->Length = ulTotalLength - ulStageLength;	// 还剩下多少字节没读取
			pRWContext->Numxfer = 0;
			pRWContext->VirtualAddress = ((ULONG_PTR)pVirtualAddress + ulStageLength);
			pRWContext->DeviceExtension = pDevExt;

			IoCopyCurrentIrpStackLocationToNext(pIrp);
			pNextStack = IoGetNextIrpStackLocation(pIrp);
			pNextStack->Parameters.Read.Length = ulStageLength;
			pIrp->MdlAddress = mdl;

			IoSetCompletionRoutine(pIrp,
				(PIO_COMPLETION_ROUTINE)CompletionRead,
				pRWContext,
				TRUE,
				TRUE,
				TRUE);

			IoCallDriver(pDevExt->pTargetDevice, pIrp);
			pIrp->MdlAddress = pRWContext->OldMdl;
			IoFreeMdl(pRWContext->NewMdl);
		}
	}

	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = ulTotalLength;

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}

// 入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING DevName = { 0 };
	UNICODE_STRING DevSymbolicLinkName = { 0 };
	PDEVICE_OBJECT pDevObj = NULL;
	SIZE_T sub = 0;

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

	RtlInitUnicodeString(&DevName, L"\\Device\\LayerDriverEx");
	RtlInitUnicodeString(&DevSymbolicLinkName, L"\\??\\LayerDriverEx");

	status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &DevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN,
		FALSE, &pDevObj);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建设备失败\n"));
		return status;
	}

	status = IoCreateSymbolicLink(&DevSymbolicLinkName, &DevName);

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

	pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;

	pDevObj->Flags |= DO_DIRECT_IO;
	pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

	pDriverObject->DriverUnload = DriverUnload;

	return status;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值