驱动分层-挂载设备对象示例

(一)框架

(1)标准驱动A(被挂载的驱动):IRP_MJ_READ派遣函数演示,添加timer例程,用来延时异步的调用过程

(2)挂载驱动B(将此驱动挂载到标准驱动A上面):获得标准驱动A的设备对象指针,在IRP_MJ_READ派遣函数内不做任何处理,仅仅将IRP传递给标准驱动

(3)exe程序,打开标准驱动A设备,并使用ReadFile出发一个IRP_MJ_READ的IRP


(二)结果:应用程序调用标准驱动A,但首先是挂载的驱动B收到IRP_MJ_READ的IRP,然后驱动B将IRP传递给标准驱动A


标准驱动A代码:

///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: StandardDriver.cpp
/// Project          : StandardDriver
/// Date of creation : 2014-06-24
/// Author(s)        : <author name(s)>
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2014-06-24] Initial revision.
///
///

// $Id$

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "StandardDriver.h"

#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif





typedef struct _DEVICE_EXTENSION 
{
	UNICODE_STRING usDevName;
	UNICODE_STRING usLinkName;
	PDEVICE_OBJECT pDevObj;

	KDPC pollingDPC;//存储DPC对象
	KTIMER pollingTimer;//存储计时器对象
	PIRP pendingIrp;//记录当前挂起的IRP

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;



VOID TimerDpc(
			  __in struct _KDPC  *Dpc,
			  __in_opt PVOID  DeferredContext,
			  __in_opt PVOID  SystemArgument1,
			  __in_opt PVOID  SystemArgument2
			  )
{

	PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext;
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

	PIRP currentPendingIrp = pDevExt->pendingIrp;

	NTSTATUS status = STATUS_SUCCESS;

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

	KdPrint(("StandardDriver-TimerDpc.."));


}



NTSTATUS STANDARDDRIVER_DispatchCreateClose(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS STANDARDDRIVER_DispatchDeviceControl(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_STANDARDDRIVER_OPERATION:
        // status = SomeHandlerFunction(irpSp);
        break;
    default:
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;
        break;
    }

    status = Irp->IoStatus.Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

VOID STANDARDDRIVER_DriverUnload(
    IN PDRIVER_OBJECT		DriverObject
    )
{
    PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
    IoDeleteSymbolicLink(&usSymlinkName);

    // Delete all the device objects
    while(pdoNextDeviceObj)
    {
        PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
        pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
        IoDeleteDevice(pdoThisDeviceObj);
    }

	KdPrint(("StandardDriver-DriverUnload.."));

}

NTSTATUS StandardDriver_ReadDispath(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;

	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

	IoMarkIrpPending(pIrp);

	pDevExt->pendingIrp = pIrp;

	ULONG uMicroSec = 3000000;
	LARGE_INTEGER lTime = RtlConvertLongToLargeInteger(-10*uMicroSec);

	KeSetTimer(&(pDevExt->pollingTimer),lTime,&(pDevExt->pollingDPC));

	status = STATUS_PENDING;

	KdPrint(("StandardDriver-ReadDispath.."));


	return status;
}




#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{
    PDEVICE_OBJECT pdoDeviceObj = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pdoGlobalDrvObj = DriverObject;

	KdPrint(("StandardDriver-DriverEntry.."));


    // Create the device object.
    if(!NT_SUCCESS(status = IoCreateDevice(
        DriverObject,
        sizeof(DEVICE_EXTENSION),//0,
        &usDeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pdoDeviceObj
        )))
    {
        // Bail out (implicitly forces the driver to unload).
        return status;
    };



	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension;
	pDevExt->usDevName = usDeviceName;
	pDevExt->usLinkName = usSymlinkName;
	pDevExt->pDevObj = pdoDeviceObj;


	KeInitializeDpc(&(pDevExt->pollingDPC),TimerDpc,(PVOID)pdoDeviceObj);
	KeInitializeTimer(&(pDevExt->pollingTimer));


	pdoDeviceObj->Flags |= DO_BUFFERED_IO;

    // Now create the respective symbolic link object
    if(!NT_SUCCESS(status = IoCreateSymbolicLink(
        &usSymlinkName,
        &usDeviceName
        )))
    {
        IoDeleteDevice(pdoDeviceObj);
        return status;
    }

    // NOTE: You need not provide your own implementation for any major function that
    //       you do not want to handle. I have seen code using DDKWizard that left the
    //       *empty* dispatch routines intact. This is not necessary at all!
    DriverObject->MajorFunction[IRP_MJ_CREATE] =
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = STANDARDDRIVER_DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = STANDARDDRIVER_DispatchDeviceControl;
	DriverObject->MajorFunction[IRP_MJ_READ] = StandardDriver_ReadDispath;
    DriverObject->DriverUnload = STANDARDDRIVER_DriverUnload;

    return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif

挂载驱动B的代码:

///
///
/// Copyright (c) 2014 - <company name here>
///
/// Original filename: AttDevStandardDev.cpp
/// Project          : AttDevStandardDev
/// Date of creation : 2014-06-25
/// Author(s)        : <author name(s)>
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2014-06-25] Initial revision.
///
///

// $Id$

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <string.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "AttDevStandardDev.h"

#ifdef __cplusplus
namespace { // anonymous namespace to limit the scope of this global variable!
#endif
PDRIVER_OBJECT pdoGlobalDrvObj = 0;
#ifdef __cplusplus
}; // anonymous namespace
#endif



typedef struct _DEVICE_EXTENSION 
{

	UNICODE_STRING usDevName;
	UNICODE_STRING usLinkName;
	PDEVICE_OBJECT pDevObj;


	//PDEVICE_OBJECT pNextDevObj;
	PDEVICE_OBJECT pTargetDevobj;

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;


NTSTATUS ATTDEVSTANDARDDEV_DispatchCreateClose(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS ATTDEVSTANDARDDEV_DispatchDeviceControl(
    IN PDEVICE_OBJECT		DeviceObject,
    IN PIRP					Irp
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

    switch(irpSp->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_ATTDEVSTANDARDDEV_OPERATION:
        // status = SomeHandlerFunction(irpSp);
        break;
    default:
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;
        break;
    }

    status = Irp->IoStatus.Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}

VOID ATTDEVSTANDARDDEV_DriverUnload(
    IN PDRIVER_OBJECT		DriverObject
    )
{

	KdPrint(("ATTDEVSTANDARDDEV_DriverUnload .."));


    PDEVICE_OBJECT pdoNextDeviceObj = pdoGlobalDrvObj->DeviceObject;
    //IoDeleteSymbolicLink(&usSymlinkName);

    // Delete all the device objects
    while(pdoNextDeviceObj)
    {
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pdoNextDeviceObj->DeviceExtension;

		pdoNextDeviceObj =pdoNextDeviceObj->NextDevice;

		//从设备栈弹出
		IoDetachDevice(pDevExt->pTargetDevobj);

		//删除该设备对象
		IoDeleteDevice(pDevExt->pDevObj);

        //PDEVICE_OBJECT pdoThisDeviceObj = pdoNextDeviceObj;
       // pdoNextDeviceObj = pdoThisDeviceObj->NextDevice;
        //IoDeleteDevice(pdoThisDeviceObj);
    }

	KdPrint(("ATTDEVSTANDARDDEV_DriverUnload leave"));
}


NTSTATUS ReadDiaptch(PDEVICE_OBJECT pDevObj,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;

	KdPrint(("Attach Device ReadDiaptch...."));
	//转发给下一层驱动
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;

	//略过当前堆栈
	IoSkipCurrentIrpStackLocation(pIrp);

	//调用下一层驱动
	status = IoCallDriver(pDevExt->pTargetDevobj,pIrp);


	KdPrint(("Attach Device ReadDiaptch....leave..."));

	return status;
}


#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(
    IN OUT PDRIVER_OBJECT   DriverObject,
    IN PUNICODE_STRING      RegistryPath
    )
{

	KdPrint(("Attach Device DriverEntry....."));


    PDEVICE_OBJECT pdoDeviceObj = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pdoGlobalDrvObj = DriverObject;
	PDEVICE_EXTENSION pDevExt;



	//获得将要绑定的设备的对象指针和文件对象指针
	UNICODE_STRING usStandardDevName;
	RtlInitUnicodeString(&usStandardDevName,L"\\Device\\STANDARDDRIVER_DeviceName");
	PDEVICE_OBJECT pDeviceObj;
	PFILE_OBJECT pFileObject;
	status = IoGetDeviceObjectPointer(&usStandardDevName,FILE_ALL_ACCESS,&pFileObject,&pDeviceObj);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("AttaceDev:IoGetDeviceObjectPointer Error:0x%x",status));
		return status;
	}

	//创建自己的设备
    if(!NT_SUCCESS(status = IoCreateDevice(
        DriverObject,
        sizeof(DEVICE_EXTENSION),//0,
        &usDeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pdoDeviceObj
        )))
    {
		KdPrint(("AttaceDev:IoCreateDevice Error:0x%x",status));

        // Bail out (implicitly forces the driver to unload).
		ObDereferenceObject(pFileObject);//引用计数减一
        return status;
    };

	pdoDeviceObj->Flags |= DO_BUFFERED_IO;


	pDevExt = (PDEVICE_EXTENSION)pdoDeviceObj->DeviceExtension;
	pDevExt->usDevName = usDeviceName;
	pDevExt->usLinkName = usSymlinkName;
	pDevExt->pDevObj = pdoDeviceObj;

	// Now create the respective symbolic link object
	if(!NT_SUCCESS(status = IoCreateSymbolicLink(
		&usSymlinkName,
		&usDeviceName
		)))
	{
		KdPrint(("AttaceDev:IoCreateSymbolicLink Error:0x%x",status));

		IoDeleteDevice(pdoDeviceObj);
		return status;
	}
	DriverObject->MajorFunction[IRP_MJ_CREATE] =
		DriverObject->MajorFunction[IRP_MJ_CLOSE] = ATTDEVSTANDARDDEV_DispatchCreateClose;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ATTDEVSTANDARDDEV_DispatchDeviceControl;
	DriverObject->MajorFunction[IRP_MJ_READ] = ReadDiaptch;
	DriverObject->DriverUnload = ATTDEVSTANDARDDEV_DriverUnload;



	//保存信息到设备扩展
	pDevExt = (PDEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
	//设备扩展得到下层驱动设备
	PDEVICE_OBJECT pFilterDevObj = pDevExt->pDevObj;

	//自己的设备挂载到标准驱动的设备上
	PDEVICE_OBJECT pTargetDevObj = IoAttachDeviceToDeviceStack(pFilterDevObj,pDeviceObj);

	pDevExt->pTargetDevobj = pTargetDevObj;

	if (!pTargetDevObj)
	{
		KdPrint(("AttaceDev:IoAttachDeviceToDeviceStack Error:0x%x",status));

		ObDereferenceObject(pFileObject);
		IoDeleteDevice(pFilterDevObj);
		return STATUS_INSUFFICIENT_RESOURCES;
	}


	//设置设备类型
	pFilterDevObj->DeviceType = pTargetDevObj->DeviceType;
	//设置设备对象特征
	pFilterDevObj->Characteristics = pTargetDevObj->Characteristics;
	//设置设备对象标记
	pFilterDevObj->Flags &= ~ DO_DEVICE_INITIALIZING;
	pFilterDevObj->Flags |= (pTargetDevObj->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO));

	ObDereferenceObject(pFileObject);

	KdPrint(("Attach Device DriverEntry..... leave"));

    return STATUS_SUCCESS;
}
#ifdef __cplusplus
}; // extern "C"
#endif

exe应用程序代码:

// CallDriver.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "CallDriver.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 唯一的应用程序对象

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// 初始化 MFC 并在失败时显示错误
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: 更改错误代码以符合您的需要
		_tprintf(_T("错误: MFC 初始化失败\n"));
		nRetCode = 1;
	}
	else
	{
		// TODO: 在此处为应用程序的行为编写代码。
	}

	HANDLE hdl = CreateFile(L"\\\\.\\STANDARDDRIVER_DeviceName",
		GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL ,NULL);
	if (hdl == INVALID_HANDLE_VALUE)
	{
		CString csLog;
		csLog.Format(L"CreateFile Error:%d",GetLastError());
		AfxMessageBox(csLog);
		return -1;
	}

	DWORD dwRetLen = 0;
	BOOL bRetRead = ReadFile(hdl,NULL,0,&dwRetLen,NULL);
	if (bRetRead)
	{
		cout<<"ReadFile OK!"<<endl;
	}
	CloseHandle(hdl);

	system("PAUSE");

	return nRetCode;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值