忆杰的博客

忆杰的博客

分层驱动程序

分层驱动程序也不难嘛, 就是逻辑上有点乱了. 不过逻辑上分开以后写代码就清晰多了. 在结构上可以得到很多好处,恩, 这个分层驱动也不只是WDM式驱动才支持, NT式驱动也是可以的, 优点很多.

首先比原来写的驱动就是自己写的驱动套在一个已经有的驱动上面, 然后呢, 所有的原来驱动的Irp都会发送到现有的驱动中, 非常的暴力. 那么前面已经我们已经可以写一个驱动程序了, 接下来需要做的是把我们写的驱动挂载到想要挂载的驱动上面, 所以写这个驱动程序, 要准备好几个驱动程序来做, 所以感觉有点乱, 不过呢, 确实是很好用的.

挂载的函数是IoAttachDeviceToDeviceStack.. 将一个设备挂载到另外一个设备上面, 挂上去以后被挂载设备的所有Irp就会先经过我们写的驱动了, 是不是很好.

当Irp来到我们的驱动程序的时候, 我们可以做几件事情, 首先可以直接调用IoCompleteRequest函数, 这样Irp就不会往下传递了, 这时候我们在Status中如果返回错误, 那么显然上面调用就成了错误了, 想想这时候我们绑定的是一个硬盘设备, 这样就可以实现只读U盘了, 哈哈. 第2种就是调用StartIo, 操作系统就会将该Irp串行化, 这个用的不是很多, 略. 第3种就是不管, 直接略过. 这种处理方法就最简单了..

基本也就这么多东西了. 其他有些细节的话在代码中很好体现. 先来写一个最简单的驱动程序, 所有的Irp直接下发. 回头再做更进一步的操作, 因为这里需要一个底层设备, 这个驱动还是前两篇写得测试驱动, 不动, 这边只需要写挂载的驱动就可以了.. 看代码. 这边是用户态的:
 

/*
	最简单的分层驱动程序, 所有Irp直接下发 3环代码
	编译方法参见makefile. TAB = 8
*/
#include <stdio.h>
#include <windows.h>

#define DEVICE_NAME		"\\\\.\\SysLinkFiltering"

VOID Jmain( ) {
	HANDLE hFile;
	UCHAR ucBuf[10];
	DWORD dwByteWrite;
	DWORD dwByteRead;
	BOOL bRet;

	do {
		hFile = CreateFile( DEVICE_NAME, GENERIC_READ | GENERIC_WRITE,
				    FILE_SHARE_READ, NULL, OPEN_EXISTING,
				    FILE_ATTRIBUTE_NORMAL, NULL );
		if ( hFile == INVALID_HANDLE_VALUE ) {
			printf( "打开设备失败!\n" );
			break;
		}

		RtlFillMemory( ucBuf, sizeof( ucBuf ), 'a' );
		bRet = WriteFile( hFile, ucBuf, sizeof( ucBuf ), &dwByteWrite, NULL  );
		if ( !bRet ) {
			printf( "写入失败失败!\n" );
			break;
		}

		RtlZeroMemory( ucBuf, sizeof( ucBuf ) );
		bRet = ReadFile( hFile, ucBuf, sizeof( ucBuf ), &dwByteRead, NULL );
		if ( !bRet ) {
			printf( "读取设备失败!\n" );
			break;
		}
		printf( "操作设备成功!\n" );
	} while ( FALSE );

	if ( hFile != INVALID_HANDLE_VALUE ) {
		CloseHandle( hFile );
	}
}

内核这边的代码:

/*
	最简单的分层驱动程序, 所有Irp直接下发 0环代码
	编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>

#define DEVICE_NAME		L"\\Device\\DevFiltering"
#define SYSLINK_NAME		L"\\??\\SysLinkFiltering"
#define BING_DEVICE_NAME	L"\\Device\\DevTestDriver"

typedef struct tagDevice_Ext {
	PDEVICE_OBJECT pFilterDeviceObj;	//当前设备对象
	PDEVICE_OBJECT pTargetDevice;		//下一层设备对象
	UNICODE_STRING USzDeviceName;
	UNICODE_STRING USzSysLinkName;
} DEVICE_EXT, *PDEVICE_EXT;

//===========================================================================
//驱动卸载例程
//===========================================================================
VOID DriverUnload( PDRIVER_OBJECT pDriverObj ) {
	PDEVICE_EXT pDeviceExt = NULL;
	PDEVICE_OBJECT	pNextDeviceObj = NULL;

	pNextDeviceObj = pDriverObj->DeviceObject;

	while ( pNextDeviceObj != NULL ) {
		pDeviceExt = pNextDeviceObj->DeviceExtension;

		IoDeleteSymbolicLink( &pDeviceExt->USzSysLinkName );
		//解除设备栈上的绑定
		IoDetachDevice( pDeviceExt->pTargetDevice );

		IoDeleteDevice( pDeviceExt->pFilterDeviceObj );

		KdPrint( ( "删除%wZ设备成功!\n", &pDeviceExt->USzDeviceName ) );

		pNextDeviceObj = pNextDeviceObj->NextDevice;
	}
}
//===========================================================================
//所有不关心的Irp处理
//===========================================================================
NTSTATUS DispatchRoutine( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
	PDEVICE_EXT pDeviceExt = NULL;
	NTSTATUS Status;

	pDeviceExt = pDeviceObj->DeviceExtension;

	//跳过当前I/O堆栈
	IoSkipCurrentIrpStackLocation( pIrp );

	//向下转发IRP
	Status = IoCallDriver( pDeviceExt->pTargetDevice, pIrp );

	KdPrint( ( "不关心的Irp来了一次!\n" ) );
	return Status;
}
//===========================================================================
//创建设备
//===========================================================================
NTSTATUS _CreateDeviec( PDRIVER_OBJECT pDriverObj, PDEVICE_EXT* ppDeviceExt ) {
	NTSTATUS Status;
	PDEVICE_OBJECT pDeviceObj = NULL;
	UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
	UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYSLINK_NAME );

	//创建设备对象
	Status = IoCreateDevice( pDriverObj, sizeof( DEVICE_EXT ), &USzDeviceName,
				 FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObj );
	if ( !NT_SUCCESS( Status ) ) {
		return Status;
	}

	//创建符号链接
	Status = IoCreateSymbolicLink( &USzSysLinkName, &USzDeviceName );
	if ( !NT_SUCCESS( Status ) ) {
		return Status;
	}

	ASSERT( ppDeviceExt != NULL );

	pDeviceObj->Flags |= DO_BUFFERED_IO;
	*ppDeviceExt = pDeviceObj->DeviceExtension;
	( *ppDeviceExt )->USzDeviceName = USzDeviceName;
	( *ppDeviceExt )->USzSysLinkName = USzSysLinkName;
	( *ppDeviceExt )->pFilterDeviceObj = pDeviceObj;

	return Status;
}
//===========================================================================
//读取请求处理例程
//===========================================================================
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
	PDEVICE_EXT pDeviceExt = NULL;
	NTSTATUS Status;

	pDeviceExt = pDeviceObj->DeviceExtension;

	//跳过当前I/O堆栈
	IoSkipCurrentIrpStackLocation( pIrp );

	//向下转发IRP
	Status = IoCallDriver( pDeviceExt->pTargetDevice, pIrp );

	KdPrint( ( "Filter: DispatchRead来了一次!\n" ) );
	return Status;
}
//===========================================================================
//写入请求处理例程
//===========================================================================
NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
	PDEVICE_EXT pDeviceExt = NULL;
	NTSTATUS Status;

	pDeviceExt = pDeviceObj->DeviceExtension;

	//跳过当前I/O堆栈
	IoSkipCurrentIrpStackLocation( pIrp );

	//向下转发IRP
	Status = IoCallDriver( pDeviceExt->pTargetDevice, pIrp );

	KdPrint( ( "Filter: DispatchWrite来了一次!\n" ) );
	return Status;
}
//===========================================================================
//驱动入口
//===========================================================================
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
	ULONG i;
	NTSTATUS Status;
	PDEVICE_EXT pDeviceExt = NULL;
	PFILE_OBJECT pBingFileObj = NULL;
	PDEVICE_OBJECT pTargetDevice = NULL;
	PDEVICE_OBJECT pBingDeviceObj = NULL;
	UNICODE_STRING USzBindDeviceName = RTL_CONSTANT_STRING( BING_DEVICE_NAME );

	for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
		pDriverObj->MajorFunction[i] = &DispatchRoutine;
	}
	pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead;
	pDriverObj->MajorFunction[IRP_MJ_WRITE] = &DispatchWrite;
	pDriverObj->DriverUnload = &DriverUnload;
//---------------------------------------------------------------------------
	do {
		//寻找欲打开的设备
		Status = IoGetDeviceObjectPointer( &USzBindDeviceName, FILE_ALL_ACCESS,
						   &pBingFileObj, &pBingDeviceObj );
		if ( !NT_SUCCESS( Status ) ) {
			KdPrint( ( "欲绑定的设备不存在, 是否是没有启动设备!\n" ) );
			break;
		}

		Status = _CreateDeviec( pDriverObj, &pDeviceExt );
		if ( !NT_SUCCESS( Status ) ) {
			KdPrint( ( "创建自身设备失败!\n" ) );
			break;
		}

		//将自己的设备对象挂载在目标设备对象上
		pTargetDevice = IoAttachDeviceToDeviceStack(
					pDeviceExt->pFilterDeviceObj, pBingDeviceObj );

		pDeviceExt->pTargetDevice = pTargetDevice;
		if ( !pTargetDevice ) {
			KdPrint( ( "挂载目标设备失败!\n" ) );
			break;
		}

		//设置过滤设备属性
		pDeviceExt->pFilterDeviceObj->DeviceType = pTargetDevice->DeviceType;
		pDeviceExt->pFilterDeviceObj->Characteristics = pTargetDevice->Characteristics;
		pDeviceExt->pFilterDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;

		pDeviceExt->pFilterDeviceObj->Flags |= pTargetDevice->Flags &
						       ( DO_DIRECT_IO | DO_BUFFERED_IO );

		if ( pBingFileObj ) {
			ObDereferenceObject( pBingFileObj );
			pBingFileObj = NULL;
		}

		KdPrint( ( "绑定设备成功!\n" ) );
	} while ( FALSE );
//---------------------------------------------------------------------------
	//释放资源
	if ( !NT_SUCCESS( Status ) ) {

		if ( pBingFileObj ) {
			ObDereferenceObject( pBingFileObj );
		}

		if ( pDeviceExt && pDeviceExt->pFilterDeviceObj ) {
			IoDeleteDevice( pDeviceExt->pFilterDeviceObj );
		}

		if ( pBingFileObj ) {
			ObDereferenceObject( pBingFileObj );
		}

	}
	return Status;
}

 

发表评论

您必须登录 才能进行评论。