水平有限,欢迎大家多批评。有什么意见请跟贴,我尽量回复,谢谢大家。
Diskperf代码分析
/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
diskperf.c
Abstract:
This driver monitors disk accesses capturing performance data.
Environment:
kernel mode only
Notes:
--*/
#define INITGUID
#include "ntddk.h"
#include "ntdddisk.h"
#include "stdarg.h"
#include "stdio.h"
#include <ntddvol.h>
#include <mountdev.h>
#include "wmistr.h"
#include "wmidata.h"
#include "wmiguid.h"
#include "wmilib.h"
#include "ntstrsafe.h"
// 下面这个宏用来把ExAllocatePool替换成ExAllocatePoolWithTag,MS的文档中推荐用后
// 者,以便调试,所以做了这个替换
#ifdef POOL_TAGGING
#ifdef ExAllocatePool
#undef ExAllocatePool
#endif
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'frPD')
#endif
#define DISKPERF_MAXSTR 64
//
// Device Extension
//
typedef struct _DEVICE_EXTENSION {
//
// Back pointer to device object
//
PDEVICE_OBJECT DeviceObject;
//
// 目标设备对象
//
PDEVICE_OBJECT TargetDeviceObject;
//
// 物理设备对象
//
PDEVICE_OBJECT PhysicalDeviceObject;
//
// Disk number for reference in WMI
//
ULONG DiskNumber;
//
// If device is enabled for counting always
//
LONG EnabledAlways;
//
// Use to keep track of Volume info from ntddvol.h
//
WCHAR StorageManagerName[8];
//
// Disk performance counters
// and locals used to compute counters
//
ULONG Processors;
PDISK_PERFORMANCE DiskCounters; // per processor counters
LARGE_INTEGER LastIdleClock;
LONG QueueDepth;
LONG CountersEnabled;
//
// 同步分页路径通知用
//
KEVENT PagingPathCountEvent;
LONG PagingPathCount;
//
// 物理设备名或者WMI 实例名字
//
UNICODE_STRING PhysicalDeviceName;
WCHAR PhysicalDeviceNameBuffer[DISKPERF_MAXSTR];
//
// Private context for using WmiLib
//
WMILIB_CONTEXT WmilibContext;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
#define PROCESSOR_COUNTERS_SIZE FIELD_OFFSET(DISK_PERFORMANCE, QueryTime)
/*
每个处理器的计数器的布局,是一个连续的内存块:
处理器1
+-----------------------+ +-----------------------+
|PROCESSOR_COUNTERS_SIZE| ... |PROCESSOR_COUNTERS_SIZE|
+-----------------------+ +-----------------------+
这里PROCESSOR_COUNTERS_SIZE比DISK_PERFORMANCE的尺寸要小,因为我们只统计实际使用的。
*/
UNICODE_STRING DiskPerfRegistryPath;
//
// 函数定义
//
DRIVER_INITIALIZE DriverEntry;
DRIVER_ADD_DEVICE DiskPerfAddDevice;
DRIVER_DISPATCH DiskPerfForwardIrpSynchronous;
__drv_dispatchType(IRP_MJ_PNP)
DRIVER_DISPATCH DiskPerfDispatchPnp;
__drv_dispatchType(IRP_MJ_POWER)
DRIVER_DISPATCH DiskPerfDispatchPower;
DRIVER_DISPATCH DiskPerfSendToNextDriver;
__drv_dispatchType(IRP_MJ_CREATE)
DRIVER_DISPATCH DiskPerfCreate;
__drv_dispatchType(IRP_MJ_READ)
__drv_dispatchType(IRP_MJ_WRITE)
DRIVER_DISPATCH DiskPerfReadWrite;
__drv_dispatchType(IRP_MJ_DEVICE_CONTROL)
DRIVER_DISPATCH DiskPerfDeviceControl;
__drv_dispatchType(IRP_MJ_SYSTEM_CONTROL)
DRIVER_DISPATCH DiskPerfWmi;
__drv_dispatchType(IRP_MJ_FLUSH_BUFFERS)
__drv_dispatchType(IRP_MJ_SHUTDOWN)
DRIVER_DISPATCH DiskPerfShutdownFlush;
DRIVER_DISPATCH DiskPerfStartDevice;
DRIVER_DISPATCH DiskPerfRemoveDevice;
IO_COMPLETION_ROUTINE DiskPerfIoCompletion;
IO_COMPLETION_ROUTINE DiskPerfIrpCompletion;
DRIVER_UNLOAD DiskPerfUnload;
VOID
DiskPerfLogError(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG UniqueId,
IN NTSTATUS ErrorCode,
IN NTSTATUS Status
);
NTSTATUS
DiskPerfRegisterDevice(
IN PDEVICE_OBJECT DeviceObject
);
WMI_QUERY_REGINFO_CALLBACK DiskperfQueryWmiRegInfo;
WMI_QUERY_DATABLOCK_CALLBACK DiskperfQueryWmiDataBlock;
VOID
DiskPerfSyncFilterWithTarget(
IN PDEVICE_OBJECT FilterDevice,
IN PDEVICE_OBJECT TargetDevice
);
WMI_FUNCTION_CONTROL_CALLBACK DiskperfWmiFunctionControl;
VOID
DiskPerfAddCounters(
IN OUT PDISK_PERFORMANCE TotalCounters,
IN PDISK_PERFORMANCE NewCounters,
IN LARGE_INTEGER Frequency
);
#if DBG
ULONG DiskPerfDebug = 0;
VOID
DiskPerfDebugPrint(
ULONG DebugPrintLevel,
PCCHAR DebugMessage,
...
);
#define DebugPrint(x) DiskPerfDebugPrint x
#else
#define DebugPrint(x)
#endif
//
// 下面的宏定义用来优化编译器,取消一些无关代码(比如分页代码)。
//
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, DiskPerfCreate)
#pragma alloc_text (PAGE, DiskPerfAddDevice)
#pragma alloc_text (PAGE, DiskPerfDispatchPnp)
#pragma alloc_text (PAGE, DiskPerfStartDevice)
#pragma alloc_text (PAGE, DiskPerfRemoveDevice)
#pragma alloc_text (PAGE, DiskPerfUnload)
#pragma alloc_text (PAGE, DiskPerfWmi)
#pragma alloc_text (PAGE, DiskperfQueryWmiRegInfo)
#pragma alloc_text (PAGE, DiskperfQueryWmiDataBlock)
#pragma alloc_text (PAGE, DiskPerfRegisterDevice)
#pragma alloc_text (PAGE, DiskPerfSyncFilterWithTarget)
#endif
WMIGUIDREGINFO DiskperfGuidList[] =
{
{ &DiskPerfGuid,
1,
0
}
};
#define DiskperfGuidCount (sizeof(DiskperfGuidList) / sizeof(WMIGUIDREGINFO))
#define USE_PERF_CTR
#ifdef USE_PERF_CTR
#define DiskPerfGetClock(a, b) (a) = KeQueryPerformanceCounter((b))
#else
#define DiskPerfGetClock(a, b) KeQuerySystemTime(&(a))
#endif
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
函数说明:
可安装驱动的初始化入口点。
这个方法直接被I/O管理器调用,用来创建磁盘性能驱动。这里的driver对象创建好,
然后Pnp管理器调用DiskPerfAddDevice来把它附加到启动设备上。
参数:
DriverObject – 磁盘性能驱动对象。
RegistryPath – 指向一个unicode的字符串,表示路径。
也就是注册表中,驱动特定的键。
返回值:
STATUS_SUCCESS 如果成功的话
--*/
{
ULONG ulIndex;
PDRIVER_DISPATCH * dispatch;
//
// 保存注册表路径
//
DiskPerfRegistryPath.MaximumLength = RegistryPath->Length
+ sizeof(UNICODE_NULL);
DiskPerfRegistryPath.Buffer = ExAllocatePool(
PagedPool,
DiskPerfRegistryPath.MaximumLength);
if (DiskPerfRegistryPath.Buffer != NULL)
{
RtlCopyUnicodeString(&DiskPerfRegistryPath, RegistryPath);
} else {
DiskPerfRegistryPath.Length = 0;
DiskPerfRegistryPath.MaximumLength = 0;
}
//
// 创建分派函数
//
for (ulIndex = 0, dispatch = DriverObject->MajorFunction;
ulIndex <= IRP_MJ_MAXIMUM_FUNCTION;
ulIndex++, dispatch++) {
*dispatch = DiskPerfSendToNextDriver;
}
//
// 创建设备驱动入口点
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = DiskPerfCreate;
DriverObject->MajorFunction[IRP_MJ_READ] = DiskPerfReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DiskPerfReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DiskPerfDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DiskPerfWmi;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DiskPerfShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DiskPerfShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_PNP] = DiskPerfDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DiskPerfDispatchPower;
// 下面这行代码请尤其注意:这行代码是确保本驱动被装载的时候会执行
// DiskPerfAddDevice的关键
DriverObject->DriverExtension->AddDevice = DiskPerfAddDevice;
DriverObject->DriverUnload = DiskPerfUnload;
return(STATUS_SUCCESS);
} // end DriverEntry()
#define FILTER_DEVICE_PROPOGATE_FLAGS 0
#define FILTER_DEVICE_PROPOGATE_CHARACTERISTICS (FILE_REMOVABLE_MEDIA | /
FILE_READ_ONLY_DEVICE | /
FILE_FLOPPY_DISKETTE /
)
VOID
DiskPerfSyncFilterWithTarget(
IN PDEVICE_OBJECT FilterDevice,
IN PDEVICE_OBJECT TargetDevice
)
{
ULONG propFlags;
PAGED_CODE();
//
// 把目标设备的一些有用标记复制到diskperf中。挂载管理器将查找
// diskperf对象的功能点,并且表明磁盘是可移动设备还是其他的
// 设备
//
propFlags = TargetDevice->Flags & FILTER_DEVICE_PROPOGATE_FLAGS;
FilterDevice->Flags |= propFlags;
propFlags = TargetDevice->Characteristics & FILTER_DEVICE_PROPOGATE_CHARACTERISTICS;
FilterDevice->Characteristics |= propFlags;
}
NTSTATUS
DiskPerfAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
方法说明:
为对应得物理设备对象(PDO=Physical Device Object)创建一个新的过滤设备对
象(FiDO)。然后把这个设备对象“粘”到驱动的堆栈上去。
参数:
DriverObject – 磁盘性能驱动对象。
PhysicalDeviceObject – 下层驱动的物理设备对象。
返回值:
NTSTATUS
--*/
{
NTSTATUS status;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
PWMILIB_CONTEXT wmilibContext;
PCHAR buffer;
ULONG buffersize;
PAGED_CODE();
//
// 为本设备创建一个过滤设备对象(分离)。
//
DebugPrint((2, "DiskPerfAddDevice: Driver %X Device %X/n",
DriverObject, PhysicalDeviceObject));
// 这里尤其要注意FILE_DEVICE_DISK这个参数,这个用来表示你创建的
// 设备需要“粘”到磁盘设备对象,如果这个参数弄错了,你可能就“粘”
// 到其他地方去了。
status = IoCreateDevice(DriverObject,
DEVICE_EXTENSION_SIZE,
NULL,
FILE_DEVICE_DISK,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&filterDeviceObject);
if (!NT_SUCCESS(status)) {
DebugPrint((1, "DiskPerfAddDevice: Cannot create filterDeviceObject/n"));
return status;
}
filterDeviceObject->Flags |= DO_DIRECT_IO;
deviceExtension = (PDEVICE_EXTENSION) filterDeviceObject->DeviceExtension;
RtlZeroMemory(deviceExtension, DEVICE_EXTENSION_SIZE);
DiskPerfGetClock(deviceExtension->LastIdleClock, NULL);
DebugPrint((10, "DiskPerfAddDevice: LIC=%I64u/n",
deviceExtension->LastIdleClock));
//
// 为每个处理器分配计数器
//
// 注意:为了节省内存,我们不必为QueryTime分配额外的内存。
// 如果有额外需要的话,记录需要的额外的内存大小。
//
#if (NTDDI_VERSION >= NTDDI_WIN7)
deviceExtension->Processors = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
#elif (NTDDI_VERSION >= NTDDI_VISTA)
deviceExtension->Processors = KeQueryActiveProcessorCount(NULL);
#else
deviceExtension->Processors = KeNumberProcessors;
#endif
buffersize= PROCESSOR_COUNTERS_SIZE * deviceExtension->Processors;
buffer = (PCHAR) ExAllocatePool(NonPagedPool, buffersize);
if (buffer != NULL) {
RtlZeroMemory(buffer, buffersize);
deviceExtension->DiskCounters = (PDISK_PERFORMANCE) buffer;
}
else {
DiskPerfLogError(
filterDeviceObject,
513,
STATUS_SUCCESS,
IO_ERR_INSUFFICIENT_RESOURCES);
}
//
// 把设备对象“粘”到设备链中最高层的设备对象中
// 同时返回上次的最高层设备对象,这个用来在调用IoCallDriver
// 把IRP下发的时候用。
//
deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);
if (deviceExtension->TargetDeviceObject == NULL) {
ExFreePool(deviceExtension->DiskCounters);
deviceExtension->DiskCounters = NULL;
IoDeleteDevice(filterDeviceObject);
DebugPrint((1, "DiskPerfAddDevice: Unable to attach %X to target %X/n",
filterDeviceObject, PhysicalDeviceObject));
return STATUS_NO_SUCH_DEVICE;
}
//
// 在device extension中保存过滤设备对象。
//
deviceExtension->DeviceObject = filterDeviceObject;
deviceExtension->PhysicalDeviceName.Buffer
= deviceExtension->PhysicalDeviceNameBuffer;
KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
NotificationEvent, TRUE);
//
// 初始化WMI库上下文
//
wmilibContext = &deviceExtension->WmilibContext;
RtlZeroMemory(wmilibContext, sizeof(WMILIB_CONTEXT));
wmilibContext->GuidCount = DiskperfGuidCount;
wmilibContext->GuidList = DiskperfGuidList;
wmilibContext->QueryWmiRegInfo = DiskperfQueryWmiRegInfo;
wmilibContext->QueryWmiDataBlock = DiskperfQueryWmiDataBlock;
wmilibContext->WmiFunctionControl = DiskperfWmiFunctionControl;
//
// 默认DO_POWER_PAGABLE
//
filterDeviceObject->Flags |= DO_POWER_PAGABLE;
//
// 清除DO_DEVICE_INITIALIZING标记
//
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
} // end DiskPerfAddDevice()
NTSTATUS
DiskPerfDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
方法说明:
PNP分派
参数:
DeviceObject - 设备对象
Irp - I/O请求包
返回值:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PAGED_CODE();
DebugPrint((2, "DiskPerfDispatchPnp: Device %X Irp %X/n",
DeviceObject, Irp));
switch(irpSp->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// 调用StartRoutine
//
DebugPrint((3,
"DiskPerfDispatchPnp: Schedule completion for START_DEVICE"));
status = DiskPerfStartDevice(DeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
{
//
// 调用移除方法
//
DebugPrint((3,
"DiskPerfDispatchPnp: Schedule completion for REMOVE_DEVICE"));
status = DiskPerfRemoveDevice(DeviceObject, Irp);
break;
}
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
{
PIO_STACK_LOCATION irpStack;
BOOLEAN setPagable;
DebugPrint((3,
"DiskPerfDispatchPnp: Processing DEVICE_USAGE_NOTIFICATION"));
irpStack = IoGetCurrentIrpStackLocation(Irp);
if (irpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) {
status = DiskPerfSendToNextDriver(DeviceObject, Irp);
break; // 跳出 case 语句
}
deviceExtension = DeviceObject->DeviceExtension;
//
// 等待分页路径事件
//
status = KeWaitForSingleObject(&deviceExtension->PagingPathCountEvent,
Executive, KernelMode,
FALSE, NULL);
//
// 如果移除上一次分页的设备,需要设置DO_POWER_PAGABLE
// 如果失败,则清除这个标志
//
setPagable = FALSE;
if (!irpStack->Parameters.UsageNotification.InPath &&
deviceExtension->PagingPathCount == 1 ) {
//
// removing the last paging file
// must have DO_POWER_PAGABLE bits set
//
if (DeviceObject->Flags & DO_POWER_INRUSH) {
DebugPrint((3, "DiskPerfDispatchPnp: last paging file "
"removed but DO_POWER_INRUSH set, so not "
"setting PAGABLE bit "
"for DO %p/n", DeviceObject));
} else {
DebugPrint((2, "DiskPerfDispatchPnp: Setting PAGABLE "
"bit for DO %p/n", DeviceObject));
DeviceObject->Flags |= DO_POWER_PAGABLE;
setPagable = TRUE;
}
}
//
// 同步发送irp
//
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
//
// 处理成功,失败的情况。now deal with the failure and success cases.
// 注意,发送到下层驱动后,irp不允许失败。
//
//
if (NT_SUCCESS(status)) {
IoAdjustPagingPathCount(
&deviceExtension->PagingPathCount,
irpStack->Parameters.UsageNotification.InPath);
if (irpStack->Parameters.UsageNotification.InPath) {
if (deviceExtension->PagingPathCount == 1) {
//
// 分页文件第1条件
//
DebugPrint((3, "DiskPerfDispatchPnp: Clearing PAGABLE bit "
"for DO %p/n", DeviceObject));
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
}
}
} else {
//
// 清除上文的改变
//
if (setPagable == TRUE) {
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
setPagable = FALSE;
}
}
//
// 设置事件,以便下一个事件可以触发
//
KeSetEvent(&deviceExtension->PagingPathCountEvent,
IO_NO_INCREMENT, FALSE);
//
// 并且完成irp
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
break;
}
default:
DebugPrint((3,
"DiskPerfDispatchPnp: Forwarding irp"));
//
// 简单的转发所有其他的Irp
//
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
return status;
} // end DiskPerfDispatchPnp()
NTSTATUS
DiskPerfIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
函数说明:
转发IRP 完成方法。设置一个事件并且返回
STATUS_MORE_PROCESSING_REQUIRED,这样Irp转发的时候会等待这个事件,
然后在清理工作完成后再次完成。
参数:
DeviceObject 是WMI驱动的设备对象。
Irp 就是WMI的irp
Context 是转发器等待的事件句柄 PKEVENT。
返回值:
STATUS_MORE_PORCESSING_REQUIRED
--*/
{
PKEVENT Event = (PKEVENT) Context;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
return(STATUS_MORE_PROCESSING_REQUIRED);
} // end DiskPerfIrpCompletion()
NTSTATUS
DiskPerfStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
当收到Pnp启动Irp时调用本函数。
它将调用完成函数,初始化和注册WMI。
参数:
DeviceObject - 指向设备对象的指针
Irp – 指向irp的指针
返回值:
处理开始Irp的状态
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS status;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
DiskPerfSyncFilterWithTarget(DeviceObject,
deviceExtension->TargetDeviceObject);
//
// 完成WMI注册
//
DiskPerfRegisterDevice(DeviceObject);
//
// 完成Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
DiskPerfRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
当设备被移除时调用此函数。
首先将把自身从WMI反注册,删除自身前把自己从
设备栈上移除。
参数:
DeviceObject – 指向设备对象的指针
Irp – 指向irp的指针
返回值:
移除设备后的状态
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PWMILIB_CONTEXT wmilibContext;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// 首先从WMI中反注册
//
IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_DEREGISTER);
//
// 尽快把计数器清零,来把结构置为不可用
//
wmilibContext = &deviceExtension->WmilibContext;
InterlockedExchange(
(PLONG) &(wmilibContext->GuidCount),
(LONG) 0);
RtlZeroMemory(wmilibContext, sizeof(WMILIB_CONTEXT));
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
if (deviceExtension->DiskCounters) {
ExFreePool(deviceExtension->DiskCounters);
}
IoDetachDevice(deviceExtension->TargetDeviceObject);
IoDeleteDevice(DeviceObject);
//
// 完成Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
DiskPerfSendToNextDriver(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
当本驱动不处理某个Irp时
这个函数发送Irp 到队列的下一个驱动
参数:
DeviceObject
Irp
返回值:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end DiskPerfSendToNextDriver()
NTSTATUS
DiskPerfDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension;
#if (NTDDI_VERSION < NTDDI_VISTA)
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
return PoCallDriver(deviceExtension->TargetDeviceObject, Irp);
#else
IoSkipCurrentIrpStackLocation(Irp);
deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
#endif
} // end DiskPerfDispatchPower
NTSTATUS
DiskPerfForwardIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
当Irp 需要底层驱动优先处理的时候,把
本Irp发送到下一个驱动处理。
参数:
DeviceObject
Irp
返回值:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension;
KEVENT event;
NTSTATUS status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// 把irp堆栈拷贝到下一个设备
//
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// 设置完成方法
//
IoSetCompletionRoutine(Irp, DiskPerfIrpCompletion,
&event, TRUE, TRUE, TRUE);
//
// 调用更低层设备
//
status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
//
// 等待真正完成
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
return status;
} // end DiskPerfForwardIrpSynchronous()
NTSTATUS
DiskPerfCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
这个函数接受打开命令。通过状态返回建立驱动。
参数:
DeviceObject – 活动的上下文
Irp - 设备控制参数块
返回值:
NT 状态
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
} // end DiskPerfCreate()
NTSTATUS
DiskPerfReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
方法说明:
这是diskperf驱动粘帖到的磁盘的读写入口点。
这个驱动收集统计信息并且设置完成方法,这样当
请求完成时可以收集额外的信息。然后调用下层的
驱动。
参数:
DeviceObject
Irp
返回值:
NTSTATUS
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
#if (NTDDI_VERSION >= NTDDI_WIN7)
ULONG processor = KeGetCurrentProcessorNumberEx(NULL);
#else
ULONG processor = KeGetCurrentProcessorNumber();
#endif
PDISK_PERFORMANCE partitionCounters = NULL;
LONG queueLen;
PLARGE_INTEGER timeStamp;
//
// 因为处理器可能动态添加,确保
// 这里有当前处理器的上下文环境。
//
if (deviceExtension->DiskCounters != NULL &&
processor < deviceExtension->Processors) {
partitionCounters = (PDISK_PERFORMANCE)
((PCHAR) deviceExtension->DiskCounters
+ (processor*PROCESSOR_COUNTERS_SIZE));
}
//
// 设备没有合适的初始化。只能盲目的传递irp
//
if (deviceExtension->CountersEnabled <= 0 ||
deviceExtension->PhysicalDeviceNameBuffer[0] == 0 ||
partitionCounters == NULL) {
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
//
// 增加队列深度计数
//
queueLen = InterlockedIncrement(&deviceExtension->QueueDepth);
//
// 把当前的堆栈拷贝到下一个堆栈
//
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// 当前请求开始的事件戳
//
timeStamp = (PLARGE_INTEGER) ¤tIrpStack->Parameters.Read;
DiskPerfGetClock(*timeStamp, NULL);
DebugPrint((10, "DiskPerfReadWrite: TS=%I64u/n", *timeStamp));
if (queueLen == 1) {
partitionCounters->IdleTime.QuadPart
+= timeStamp->QuadPart -
deviceExtension->LastIdleClock.QuadPart;
deviceExtension->LastIdleClock.QuadPart = timeStamp->QuadPart;
}
//
// 设置回调完成方法
//
IoSetCompletionRoutine(Irp,
DiskPerfIoCompletion,
DeviceObject,
TRUE,
TRUE,
TRUE);
//
// 返回所有调用磁盘驱动的结果
//
return IoCallDriver(deviceExtension->TargetDeviceObject,
Irp);
} // end DiskPerfReadWrite()
NTSTATUS
DiskPerfIoCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
函数说明:
完成一个IRP后,本方法从系统获取控制。
它将计算IRP开始时间和当前时间的差异,
然后减小队列深度
参数:
DeviceObject –为IRP准备
Irp - 刚完成的I/O请求。
Context - 未使用
返回值:
IRP 的状态
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
#if (NTDDI_VERSION >= NTDDI_WIN7)
ULONG processor = KeGetCurrentProcessorNumberEx(NULL);
#else
ULONG processor = KeGetCurrentProcessorNumber();
#endif
PDISK_PERFORMANCE partitionCounters = NULL;
LARGE_INTEGER timeStampComplete;
PLARGE_INTEGER difference;
LONG queueLen;
UNREFERENCED_PARAMETER(Context);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// 当前请求完成的事件戳
//
difference = (PLARGE_INTEGER) &irpStack->Parameters.Read;
DiskPerfGetClock(timeStampComplete, NULL);
difference->QuadPart = timeStampComplete.QuadPart - difference->QuadPart;
DebugPrint((10, "DiskPerfIoCompletion: TS=%I64u diff %I64u/n",
timeStampComplete, difference->QuadPart));
//
// 减少卷的队列深度计数。
// 这个不需要自旋锁,使用Interlocked函数完成即可。
// 这是唯一合法的方法。
//
queueLen = InterlockedDecrement(&deviceExtension->QueueDepth);
if (queueLen < 0) { // do not over-decrement. Only happens at start
queueLen = InterlockedIncrement(&deviceExtension->QueueDepth);
}
if (queueLen == 0) {
deviceExtension->LastIdleClock = timeStampComplete;
}
//
// 更新计数器,但是,仅当在单处理器具有预分配上下
// 文时才使用。
//
if (deviceExtension->DiskCounters != NULL &&
processor < deviceExtension->Processors) {
partitionCounters = (PDISK_PERFORMANCE)
((PCHAR) deviceExtension->DiskCounters
+ (processor*PROCESSOR_COUNTERS_SIZE));
}
if (partitionCounters == NULL) {
return STATUS_SUCCESS;
};
if (irpStack->MajorFunction == IRP_MJ_READ) {
//
// 增加这个请求的字节数。用字节来表示读取计数器。
//
partitionCounters->BytesRead.QuadPart += Irp->IoStatus.Information;
//
// 增加读取请求的处理计数器。
//
partitionCounters->ReadCount++;
//
// 计算请求处理时间。
//
partitionCounters->ReadTime.QuadPart += difference->QuadPart;
DebugPrint((11, "Added RT delta %I64u total %I64u qlen=%d/n",
difference->QuadPart, partitionCounters->ReadTime.QuadPart,
queueLen));
}
else {
//
//增加这个请求的字节数。用字节来表示写入计数器。
//
partitionCounters->BytesWritten.QuadPart += Irp->IoStatus.Information;
//
//增加写入请求的处理计数器。
//
partitionCounters->WriteCount++;
//
//计算请求处理时间。
//
partitionCounters->WriteTime.QuadPart += difference->QuadPart;
DebugPrint((11, "Added WT delta %I64u total %I64u qlen=%d/n",
difference->QuadPart, partitionCounters->WriteTime.QuadPart,
queueLen));
}
if (Irp->Flags & IRP_ASSOCIATED_IRP) {
partitionCounters->SplitCount++;
}
return STATUS_SUCCESS;
} // DiskPerfIoCompletion
NTSTATUS
DiskPerfDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
函数说明:
设备控制分派函数,只处理磁盘性能设备控制。
所有其他的控制命令都直接发送给下层磁盘驱动。
磁盘性能驱动返回当前的性能数据快照。
参数:
DeviceObject – 活动上下文
Irp -设备控制参数快
返回值:
返回状态。
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((2, "DiskPerfDeviceControl: DeviceObject %X Irp %X/n",
DeviceObject, Irp));
if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_DISK_PERFORMANCE) {
NTSTATUS status;
//
// 校验对于性能数据来说用户缓冲区是否够大。
//
if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(DISK_PERFORMANCE)) {
//
// 表示非成功状态,没有数据传输。
//
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
}
else {
ULONG i;
PDISK_PERFORMANCE totalCounters;
PDISK_PERFORMANCE diskCounters = deviceExtension->DiskCounters;
LARGE_INTEGER frequency, perfctr;
if (diskCounters == NULL) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
if (InterlockedCompareExchange(&deviceExtension->EnabledAlways, 1, 0) == 0)
{
InterlockedIncrement(&deviceExtension->CountersEnabled);
//
// reset per processor counters only
//
if (deviceExtension->DiskCounters != NULL)
{
RtlZeroMemory(deviceExtension->DiskCounters, PROCESSOR_COUNTERS_SIZE * deviceExtension->Processors);
}
DiskPerfGetClock(deviceExtension->LastIdleClock, NULL);
deviceExtension->QueueDepth = 0;
DebugPrint((10, "DiskPerfDeviceControl: LIC=%I64u/n", deviceExtension->LastIdleClock));
DebugPrint((3, "DiskPerfDeviceControl: Counters enabled %d/n", deviceExtension->CountersEnabled));
}
totalCounters = (PDISK_PERFORMANCE) Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(totalCounters, sizeof(DISK_PERFORMANCE));
#ifdef USE_PERF_CTR
perfctr = KeQueryPerformanceCounter(&frequency);
#endif
KeQuerySystemTime(&totalCounters->QueryTime);
for (i=0; i<deviceExtension->Processors; i++) {
DiskPerfAddCounters(totalCounters, diskCounters, frequency);
diskCounters = (PDISK_PERFORMANCE)
((PCHAR) diskCounters + PROCESSOR_COUNTERS_SIZE);
}
totalCounters->QueueDepth = deviceExtension->QueueDepth;
if (totalCounters->QueueDepth == 0) {
LARGE_INTEGER difference;
difference.QuadPart =
#ifdef USE_PERF_CTR
perfctr.QuadPart
#else
totalCounters->QueryTime.QuadPart
#endif
- deviceExtension->LastIdleClock.QuadPart;
if (difference.QuadPart > 0) {
totalCounters->IdleTime.QuadPart +=
#ifdef USE_PERF_CTR
10000000 * difference.QuadPart / frequency.QuadPart;
#else
difference.QuadPart;
#endif
}
}
totalCounters->StorageDeviceNumber
= deviceExtension->DiskNumber;
RtlCopyMemory(
&totalCounters->StorageManagerName[0],
&deviceExtension->StorageManagerName[0],
8 * sizeof(WCHAR));
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(DISK_PERFORMANCE);
}
//
// 完成请求。
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
else {
//
// 将当前的堆栈回退1。
//
Irp->CurrentLocation++,
Irp->Tail.Overlay.CurrentStackLocation++;
//
// Pass unrecognized device control requests
// down to next driver layer.
//
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
}
} // end DiskPerfDeviceControl()
NTSTATUS DiskPerfWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
这个函数处理WMI的信息请求。由于磁盘性能信息是只读的,
所以总是收集数据,没有任何的事件,除非是QueryAllData,QuerySingleInstance和
GetRegInfo请求支持的事件。
参数:
DeviceObject – 活动的上下文
Irp - 设备控制参数块
返回值:
返回的状态
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PWMILIB_CONTEXT wmilibContext;
SYSCTL_IRP_DISPOSITION disposition;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
DebugPrint((2, "DiskPerfWmi: DeviceObject %X Irp %X/n",
DeviceObject, Irp));
wmilibContext = &deviceExtension->WmilibContext;
if (wmilibContext->GuidCount == 0) // wmilibContext is not valid
{
DebugPrint((3, "DiskPerfWmi: WmilibContext invalid"));
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
irpSp = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((3, "DiskPerfWmi: Calling WmiSystemControl/n"));
status = WmiSystemControl(wmilibContext,
DeviceObject,
Irp,
&disposition);
switch (disposition)
{
case IrpProcessed:
{
break;
}
case IrpNotCompleted:
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
// case IrpForward:
// case IrpNotWmi:
default:
{
status = DiskPerfSendToNextDriver(DeviceObject, Irp);
break;
}
}
return(status);
}
NTSTATUS
DiskPerfShutdownFlush(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
函数说明:
关闭或者刷新IRP时候调用本函数。在系统真正关闭之前或者系统刷新时
发送这些IRP。
参数:
DriverObject –指向将被系统关闭的设备对象。
Irp -包含的Irp
返回值:
NT 状态
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
DebugPrint((2, "DiskPerfShutdownFlush: DeviceObject %X Irp %X/n",
DeviceObject, Irp));
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
} // end DiskPerfShutdownFlush()
VOID
DiskPerfUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
函数说明:
释放所有分配的资源.。
参数:
DriverObject - 指向驱动对象。
返回值:
VOID.
--*/
{
PAGED_CODE();
UNREFERENCED_PARAMETER(DriverObject);
return;
}
NTSTATUS
DiskPerfRegisterDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
函数说明:
为设备初始化合适的名字,
并且向WMI注册。
参数:
DeviceObject – 指向需要初始化的设备对象。
返回值:
初始化的状态。注意:如果注册失败,
DeviceExtension中的设备名称将为空。
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PDEVICE_EXTENSION deviceExtension;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PAGED_CODE();
DebugPrint((2, "DiskPerfRegisterDevice: DeviceObject %X/n",
DeviceObject));
deviceExtension = DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
//
// 请求设备号
//
irp = IoBuildDeviceIoControlRequest(
IOCTL_STORAGE_GET_DEVICE_NUMBER,
deviceExtension->TargetDeviceObject,
NULL,
0,
&number,
sizeof(number),
FALSE,
&event,
&ioStatus);
if (!irp) {
DiskPerfLogError(
DeviceObject,
256,
STATUS_SUCCESS,
IO_ERR_INSUFFICIENT_RESOURCES);
DebugPrint((3, "DiskPerfRegisterDevice: Fail to build irp/n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(deviceExtension->TargetDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (NT_SUCCESS(status)) {
//
// 保存设备号,作为DiskIoNotifyRoutine的参数使用。
//
deviceExtension->DiskNumber = number.DeviceNumber;
//
// 为每个分区创建设备名字
//
RtlStringCbPrintfW(
deviceExtension->PhysicalDeviceNameBuffer,
sizeof(deviceExtension->PhysicalDeviceNameBuffer),
L"//Device//Harddisk%d//Partition%d",
number.DeviceNumber, number.PartitionNumber);
RtlInitUnicodeString(&deviceExtension->PhysicalDeviceName, &deviceExtension->PhysicalDeviceNameBuffer[0]);
//
// 为物理磁盘设置默认名字
//
RtlCopyMemory(
&(deviceExtension->StorageManagerName[0]),
L"PhysDisk",
8 * sizeof(WCHAR));
DebugPrint((3, "DiskPerfRegisterDevice: Device name %ws/n",
deviceExtension->PhysicalDeviceNameBuffer));
}
else {
// request for partition's information failed, try volume
ULONG outputSize = sizeof(MOUNTDEV_NAME);
PMOUNTDEV_NAME output;
VOLUME_NUMBER volumeNumber;
ULONG nameSize;
output = ExAllocatePool(PagedPool, outputSize);
if (!output) {
DiskPerfLogError(
DeviceObject,
257,
STATUS_SUCCESS,
IO_ERR_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
deviceExtension->TargetDeviceObject, NULL, 0,
output, outputSize, FALSE, &event, &ioStatus);
if (!irp) {
ExFreePool(output);
DiskPerfLogError(
DeviceObject,
258,
STATUS_SUCCESS,
IO_ERR_INSUFFICIENT_RESOURCES);
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(deviceExtension->TargetDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (status == STATUS_BUFFER_OVERFLOW) {
outputSize = sizeof(MOUNTDEV_NAME) + output->NameLength;
ExFreePool(output);
output = ExAllocatePool(PagedPool, outputSize);
if (!output) {
DiskPerfLogError(
DiskPerf代码解读
最新推荐文章于 2023-12-26 10:17:05 发布