(一)框架
(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;
}