驱动牛犊
|
阅读:4853回复:2
DiskPerf代码解读
水平有限,欢迎大家多批评。有什么意见请跟贴,我尽量回复,谢谢大家。
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( DeviceObject, 258, 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, 259, 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 (!NT_SUCCESS(status)) { ExFreePool(output); DiskPerfLogError( DeviceObject, 260, STATUS_SUCCESS, IO_ERR_CONFIGURATION_ERROR); return status; } // // 由于我们获取的是卷的名字而不是磁盘号, // 所以设置一个虚的值 // 跟踪的时候,替代磁盘号,可以传递一个 // deviceExtension->DiskNumber = (ULONG)-1; nameSize = min(output->NameLength, sizeof(deviceExtension->PhysicalDeviceNameBuffer) - sizeof(WCHAR)); RtlStringCbCopyW(deviceExtension->PhysicalDeviceNameBuffer, nameSize, output->Name); RtlInitUnicodeString(&deviceExtension->PhysicalDeviceName, &deviceExtension->PhysicalDeviceNameBuffer[0]); ExFreePool(output); // // 现在,获取VOLUME_NUMBER信息 // outputSize = sizeof(VOLUME_NUMBER); RtlZeroMemory(&volumeNumber, sizeof(VOLUME_NUMBER)); KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IOCTL_VOLUME_QUERY_VOLUME_NUMBER, deviceExtension->TargetDeviceObject, NULL, 0, &volumeNumber, sizeof(VOLUME_NUMBER), FALSE, &event, &ioStatus); if (!irp) { DiskPerfLogError( DeviceObject, 265, 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 (!NT_SUCCESS(status) || volumeNumber.VolumeManagerName[0] == (WCHAR) UNICODE_NULL) { RtlCopyMemory( &deviceExtension->StorageManagerName[0], L"LogiDisk", 8 * sizeof(WCHAR)); if (NT_SUCCESS(status)) deviceExtension->DiskNumber = volumeNumber.VolumeNumber; } else { RtlCopyMemory( &deviceExtension->StorageManagerName[0], &volumeNumber.VolumeManagerName[0], 8 * sizeof(WCHAR)); deviceExtension->DiskNumber = volumeNumber.VolumeNumber; } DebugPrint((3, "DiskPerfRegisterDevice: Device name %ws\n", deviceExtension->PhysicalDeviceNameBuffer)); } status = IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_REGISTER | registrationFlag ); if (! NT_SUCCESS(status)) { DiskPerfLogError( DeviceObject, 261, STATUS_SUCCESS, IO_ERR_INTERNAL_ERROR); } return status; } VOID DiskPerfLogError( IN PDEVICE_OBJECT DeviceObject, IN ULONG UniqueId, IN NTSTATUS ErrorCode, IN NTSTATUS Status ) /*++ 函数说明: 记录错误日志的方法。 参数: DeviceObject – 发生错误的设备对象 UniqueId - 错误的Id Status - 错误的状态 返回值: 无 --*/ { PIO_ERROR_LOG_PACKET errorLogEntry; errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject, (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + sizeof(DEVICE_OBJECT)) ); if (errorLogEntry != NULL) { errorLogEntry->ErrorCode = ErrorCode; errorLogEntry->UniqueErrorValue = UniqueId; errorLogEntry->FinalStatus = Status; // // 下面的代码是必须的。因为Dump数据是ULONG型的。 // 而且DeviceObject 比那个还要多。 // RtlCopyMemory( &errorLogEntry->DumpData[0], DeviceObject, sizeof(DEVICE_OBJECT)); errorLogEntry->DumpDataSize = sizeof(DEVICE_OBJECT); IoWriteErrorLogEntry(errorLogEntry); } } NTSTATUS DiskperfQueryWmiRegInfo( IN PDEVICE_OBJECT DeviceObject, OUT ULONG *RegFlags, OUT PUNICODE_STRING InstanceName, OUT PUNICODE_STRING *RegistryPath, OUT PUNICODE_STRING MofResourceName, OUT PDEVICE_OBJECT *Pdo ) /*++ 函数说明: 这是个回调函数,回调到驱动内部获取注册的guid信息。 这个函数的实现可以在分页内存中。 参数: DeviceObject 要取得注册信息的设备对象 *RegFlags 返回一组标志位,描述所有的属于注册到这个设备的guid。 如果设备希望在收到注册guid查询前启用或者禁用回调集合,则返回 WMIREG_FLAG_EXPENSIVE标志。 同样,如果实力的名字由PDO相关的设备对象决定的时候,标志中返回 WMIREG_FLAG_INSTANCE_PDO。注意:PDO必须和设备节点关联。如果 没有设置WMIREG_FLAG_INSTANCE_PDO,那么Name必须返回一个唯一的 设备名字。这些值都是每个guid的GUIDREGINFO的或运算生成的。 InstanceName 如果*RegFlags返回的标志里没有设置 WMIREG_FLAG_INSTANCE_PDO,那么,InstanceName返回guid的实例名字。 调用者需要调用对返回的缓冲区执行ExFreePool。 *RegistryPath返回驱动的注册表路径。这个是必须的。 MofResourceName返回和二进制文件相关的资源MOF的名字。 如果驱动没有相关的mof资源,这里可以返回未改变。如果 返回了一个值,那么它没有被释放掉。 *Pdo 如果标志返回李包含了WMIREG_FLAG_INSTANCE_PDO标志, *Pdo返回PDO关联的设备对象。 返回值:: 状态 --*/ { USHORT size; NTSTATUS status; PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; PAGED_CODE(); UNREFERENCED_PARAMETER(MofResourceName); size = deviceExtension->PhysicalDeviceName.Length + sizeof(UNICODE_NULL); InstanceName->Buffer = ExAllocatePool(PagedPool, size); if (InstanceName->Buffer != NULL) { *RegistryPath = &DiskPerfRegistryPath; *RegFlags = WMIREG_FLAG_INSTANCE_PDO | WMIREG_FLAG_EXPENSIVE; *Pdo = deviceExtension->PhysicalDeviceObject; status = STATUS_SUCCESS; } else { status = STATUS_INSUFFICIENT_RESOURCES; } return(status); } NTSTATUS DiskperfQueryWmiDataBlock( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG InstanceCount, IN OUT PULONG InstanceLengthArray, IN ULONG BufferAvail, OUT PUCHAR Buffer ) /*++ 函数说明: 这个函数回调到驱动中,用来查询实例的数据块的内容。当驱动 完成填充数据块时,它会调用WmiCompleteRequest来完成irp。 驱动可以返回STATUS_PENDING如果irp不能马上完成。 参数: DeviceObject 是将要查询数据块的设备。 Irp 是发出这个请求的Irp。 GuidIndex 是guid的列表索引,这个列表是设备注册时提供的。 InstanceCount 希望返回数据块的实例的数量。 InstanceLengthArray 指向一个ULONG的队列,队列中是每个实例的数据块的长度。 如果这个参数为NULL,说明没有足够的空间来满足需求。所以,这个irp应该用 所需的缓冲区来完成。 BufferAvail 可写入数据块的最大尺寸。 Buffer 填充入数据块的缓冲区。注意,每个实例的数据块必须8字节对齐。 返回值: 状态 --*/ { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; ULONG sizeNeeded; PDISK_PERFORMANCE totalCounters; PDISK_PERFORMANCE diskCounters; PWMI_DISK_PERFORMANCE diskPerformance; ULONG deviceNameSize; PWCHAR diskNamePtr; PAGED_CODE(); UNREFERENCED_PARAMETER(InstanceIndex); UNREFERENCED_PARAMETER(InstanceCount); deviceExtension = DeviceObject->DeviceExtension; if (GuidIndex == 0) { deviceNameSize = deviceExtension->PhysicalDeviceName.Length + sizeof(USHORT); sizeNeeded = ((sizeof(WMI_DISK_PERFORMANCE) + 1) & ~1) + deviceNameSize; diskCounters = deviceExtension->DiskCounters; if (diskCounters == NULL) { status = STATUS_UNSUCCESSFUL; } else if (BufferAvail >= sizeNeeded) { // // 如果磁盘处于空闲状态,则更新空闲时间。 // ULONG i; LARGE_INTEGER perfctr, frequency; RtlZeroMemory(Buffer, sizeof(WMI_DISK_PERFORMANCE)); diskPerformance = (PWMI_DISK_PERFORMANCE)Buffer; totalCounters = (PDISK_PERFORMANCE)diskPerformance; KeQuerySystemTime(&totalCounters->QueryTime); #ifdef USE_PERF_CTR perfctr = KeQueryPerformanceCounter(&frequency); #endif for (i=0; i<deviceExtension->Processors; i++) { DiskPerfAddCounters( totalCounters, diskCounters, frequency); DebugPrint((11, "DiskPerfQueryWmiDataBlock: R%d %I64u W%d%I64u ", i, diskCounters->ReadTime, diskCounters->WriteTime)); diskCounters = (PDISK_PERFORMANCE) ((PCHAR)diskCounters + PROCESSOR_COUNTERS_SIZE); } DebugPrint((11, "\n")); totalCounters->QueueDepth = deviceExtension->QueueDepth; DebugPrint((9, "QueryWmiDataBlock: Dev %X RT %I64u WT %I64u Rds %d Wts %d freq %I64u\n", totalCounters, totalCounters->ReadTime, totalCounters->WriteTime, totalCounters->ReadCount, totalCounters->WriteCount, frequency)); if (totalCounters->QueueDepth == 0) { LARGE_INTEGER difference; difference.QuadPart #ifdef USE_PERF_CTR = perfctr.QuadPart - #else = totalCounters->QueryTime.QuadPart - #endif deviceExtension->LastIdleClock.QuadPart; if (frequency.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)); diskNamePtr = (PWCHAR)(Buffer + ((sizeof(DISK_PERFORMANCE) + 1) & ~1)); *diskNamePtr++ = deviceExtension->PhysicalDeviceName.Length; RtlCopyMemory(diskNamePtr, deviceExtension->PhysicalDeviceName.Buffer, deviceExtension->PhysicalDeviceName.Length); *InstanceLengthArray = sizeNeeded; status = STATUS_SUCCESS; } else { status = STATUS_BUFFER_TOO_SMALL; } } else { status = STATUS_WMI_GUID_NOT_FOUND; sizeNeeded = 0; } status = WmiCompleteRequest( DeviceObject, Irp, status, sizeNeeded, IO_NO_INCREMENT); return(status); } NTSTATUS DiskperfWmiFunctionControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex, IN WMIENABLEDISABLECONTROL Function, IN BOOLEAN Enable ) /*++ 函数说明: 这个函数也是回调到驱动中查询启用或者禁用数据收集事件。 当驱动完成时,必须调用WmiCompleterequest来完成irp。这个 驱动会返回STATUS_PENDING 参数: DeviceObject 表示一个设备,这个设备的事件或者数据正在被启用或禁用。 Irp 产生请求的Irp。 GuidIndex 设备注册时的guid列表中的索引。 Function 事件和数据收集的不同操作函数。 Enable表示启用还是禁用。 返回值: 状态 --*/ { NTSTATUS status; PDEVICE_EXTENSION deviceExtension; deviceExtension = DeviceObject->DeviceExtension; if (GuidIndex == 0) { if (Function == WmiDataBlockControl) { if (Enable) { if (InterlockedIncrement(&deviceExtension->CountersEnabled) == 1) { // // 把每个处理器的计数器清0 // if (deviceExtension->DiskCounters != NULL) { RtlZeroMemory( deviceExtension->DiskCounters, PROCESSOR_COUNTERS_SIZE * deviceExtension->Processors); } DiskPerfGetClock(deviceExtension->LastIdleClock, NULL); DebugPrint((10, "DiskPerfWmiFunctionControl: LIC=%I64u\n", deviceExtension->LastIdleClock)); deviceExtension->QueueDepth = 0; DebugPrint((3, "DiskPerfWmi: Counters enabled %d\n", deviceExtension->CountersEnabled)); } } else { if (InterlockedDecrement(&deviceExtension->CountersEnabled) <= 0) { deviceExtension->CountersEnabled = 0; deviceExtension->QueueDepth = 0; DebugPrint((3, "DiskPerfWmi: Counters disabled %d\n", deviceExtension->CountersEnabled)); } } } status = STATUS_SUCCESS; } else { status = STATUS_WMI_GUID_NOT_FOUND; } status = WmiCompleteRequest( DeviceObject, Irp, status, 0, IO_NO_INCREMENT); return(status); } VOID DiskPerfAddCounters( IN OUT PDISK_PERFORMANCE TotalCounters, IN PDISK_PERFORMANCE NewCounters, IN LARGE_INTEGER Frequency ) { TotalCounters->BytesRead.QuadPart += NewCounters->BytesRead.QuadPart; TotalCounters->BytesWritten.QuadPart+= NewCounters->BytesWritten.QuadPart; TotalCounters->ReadCount += NewCounters->ReadCount; TotalCounters->WriteCount += NewCounters->WriteCount; TotalCounters->SplitCount += NewCounters->SplitCount; #ifdef USE_PERF_CTR if (Frequency.QuadPart > 0) { TotalCounters->ReadTime.QuadPart += NewCounters->ReadTime.QuadPart * 10000000 / Frequency.QuadPart; TotalCounters->WriteTime.QuadPart += NewCounters->WriteTime.QuadPart * 10000000 / Frequency.QuadPart; TotalCounters->IdleTime.QuadPart += NewCounters->IdleTime.QuadPart * 10000000 / Frequency.QuadPart; } else #endif { TotalCounters->ReadTime.QuadPart += NewCounters->ReadTime.QuadPart; TotalCounters->WriteTime.QuadPart += NewCounters->WriteTime.QuadPart; TotalCounters->IdleTime.QuadPart += NewCounters->IdleTime.QuadPart; } } #if DBG VOID DiskPerfDebugPrint( ULONG DebugPrintLevel, PCCHAR DebugMessage, ... ) /*++ 函数说明: 打印DiskPerf的调试信息 参数: 打印等级0到等级3的调试信息。等级3最详细。 返回值: 无 --*/ { va_list ap; va_start(ap, DebugMessage); if ((DebugPrintLevel <= (DiskPerfDebug & 0x0000ffff)) || ((1 << (DebugPrintLevel + 15)) & DiskPerfDebug)) { DbgPrint(DebugMessage, ap); } va_end(ap); } #endif |
|
沙发#
发布于:2010-10-28 16:58
楼主很强啊~
貌似这个是WDK文档里的diskperf |
|
|
禁止发言
|
板凳#
发布于:2010-10-29 09:44
用户被禁言,该主题自动屏蔽! |