📄 diskperf.c
字号:
DriverObject - Disk performance driver object.
PhysicalDeviceObject - Physical Device Object from the underlying layered driver
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatus;
PDEVICE_OBJECT filterDeviceObject;
PDEVICE_EXTENSION deviceExtension;
CCHAR ntNameBuffer[DISKPERF_MAXSTR];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
ULONG registrationFlag = 0;
PWMILIB_CONTEXT wmilibContext;
PCHAR buffer;
ULONG buffersize;
PAGED_CODE();
//
// Create a filter device object for this device (partition).
//
DebugPrint((2, "DiskPerfAddDevice: Driver %X Device %X\n",
DriverObject, PhysicalDeviceObject));
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));
//
// Allocate per processor counters. NOTE: To save some memory, it does
// allocate memory beyond QueryTime. Remember to expand size if there
// is a need to use anything beyond this
//
deviceExtension->Processors = KeNumberProcessors;
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);
}
//
// Attaches the device object to the highest device object in the chain and
// return the previously highest device object, which is passed to
// IoCallDriver when pass IRPs down the device stack
//
deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
deviceExtension->TargetDeviceObject =
IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject);
if (deviceExtension->TargetDeviceObject == NULL) {
IoDeleteDevice(filterDeviceObject);
DebugPrint((1, "DiskPerfAddDevice: Unable to attach %X to target %X\n",
filterDeviceObject, PhysicalDeviceObject));
return STATUS_NO_SUCH_DEVICE;
}
//
// Save the filter device object in the device extension
//
deviceExtension->DeviceObject = filterDeviceObject;
deviceExtension->PhysicalDeviceName.Buffer
= deviceExtension->PhysicalDeviceNameBuffer;
KeInitializeEvent(&deviceExtension->PagingPathCountEvent,
NotificationEvent, TRUE);
//
// Initialize WMI library context
//
wmilibContext = &deviceExtension->WmilibContext;
RtlZeroMemory(wmilibContext, sizeof(WMILIB_CONTEXT));
wmilibContext->GuidCount = DiskperfGuidCount;
wmilibContext->GuidList = DiskperfGuidList;
wmilibContext->QueryWmiRegInfo = DiskperfQueryWmiRegInfo;
wmilibContext->QueryWmiDataBlock = DiskperfQueryWmiDataBlock;
wmilibContext->WmiFunctionControl = DiskperfWmiFunctionControl;
//
// default to DO_POWER_PAGABLE
//
filterDeviceObject->Flags |= DO_POWER_PAGABLE;
//
// Clear the DO_DEVICE_INITIALIZING flag
//
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
} // end DiskPerfAddDevice()
NTSTATUS
DiskPerfDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch for PNP
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
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:
//
// Call the Start Routine handler to schedule a completion routine
//
DebugPrint((3,
"DiskPerfDispatchPnp: Schedule completion for START_DEVICE"));
status = DiskPerfStartDevice(DeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
{
//
// Call the Remove Routine handler to schedule a completion routine
//
DebugPrint((3,
"DiskPerfDispatchPnp: Schedule completion for REMOVE_DEVICE"));
status = DiskPerfRemoveDevice(DeviceObject, Irp);
break;
}
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
{
PIO_STACK_LOCATION irpStack;
ULONG count;
BOOLEAN setPagable;
DebugPrint((3,
"DiskPerfDispatchPnp: Processing DEVICE_USAGE_NOTIFICATION"));
irpStack = IoGetCurrentIrpStackLocation(Irp);
if (irpStack->Parameters.UsageNotification.Type != DeviceUsageTypePaging) {
status = DiskPerfSendToNextDriver(DeviceObject, Irp);
break; // out of case statement
}
deviceExtension = DeviceObject->DeviceExtension;
//
// wait on the paging path event
//
status = KeWaitForSingleObject(&deviceExtension->PagingPathCountEvent,
Executive, KernelMode,
FALSE, NULL);
//
// if removing last paging device, need to set DO_POWER_PAGABLE
// bit here, and possible re-set it below on failure.
//
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;
}
}
//
// send the irp synchronously
//
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
//
// now deal with the failure and success cases.
// note that we are not allowed to fail the irp
// once it is sent to the lower drivers.
//
if (NT_SUCCESS(status)) {
IoAdjustPagingPathCount(
&deviceExtension->PagingPathCount,
irpStack->Parameters.UsageNotification.InPath);
if (irpStack->Parameters.UsageNotification.InPath) {
if (deviceExtension->PagingPathCount == 1) {
//
// first paging file addition
//
DebugPrint((3, "DiskPerfDispatchPnp: Clearing PAGABLE bit "
"for DO %p\n", DeviceObject));
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
}
}
} else {
//
// cleanup the changes done above
//
if (setPagable == TRUE) {
DeviceObject->Flags &= ~DO_POWER_PAGABLE;
setPagable = FALSE;
}
}
//
// set the event so the next one can occur.
//
KeSetEvent(&deviceExtension->PagingPathCountEvent,
IO_NO_INCREMENT, FALSE);
//
// and complete the irp
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
break;
}
default:
DebugPrint((3,
"DiskPerfDispatchPnp: Forwarding irp"));
//
// Simply forward all other Irps
//
return DiskPerfSendToNextDriver(DeviceObject, Irp);
}
return status;
} // end DiskPerfDispatchPnp()
NTSTATUS
DiskPerfIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
Forwarded IRP completion routine. Set an event and return
STATUS_MORE_PROCESSING_REQUIRED. Irp forwarder will wait on this
event and then re-complete the irp after cleaning up.
Arguments:
DeviceObject is the device object of the WMI driver
Irp is the WMI irp that was just completed
Context is a PKEVENT that forwarder will wait on
Return Value:
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
)
/*++
Routine Description:
This routine is called when a Pnp Start Irp is received.
It will schedule a completion routine to initialize and register with WMI.
Arguments:
DeviceObject - a pointer to the device object
Irp - a pointer to the irp
Return Value:
Status of processing the Start Irp
--*/
{
PDEVICE_EXTENSION deviceExtension;
KEVENT event;
NTSTATUS status;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
DiskPerfSyncFilterWithTarget(DeviceObject,
deviceExtension->TargetDeviceObject);
//
// Complete WMI registration
//
DiskPerfRegisterDevice(DeviceObject);
//
// Complete the Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
DiskPerfRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called when the device is to be removed.
It will de-register itself from WMI first, detach itself from the
stack before deleting itself.
Arguments:
DeviceObject - a pointer to the device object
Irp - a pointer to the irp
Return Value:
Status of removing the device
--*/
{
NTSTATUS status;
PDEVICE_EXTENSION deviceExtension;
PWMILIB_CONTEXT wmilibContext;
PAGED_CODE();
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// Remove registration with WMI first
//
IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_DEREGISTER);
//
// quickly zero out the count first to invalid the structure
//
wmilibContext = &deviceExtension->WmilibContext;
InterlockedExchange(
(PLONG) &(wmilibContext->GuidCount),
(LONG) 0);
RtlZeroMemory(wmilibContext, sizeof(WMILIB_CONTEXT));
status = DiskPerfForwardIrpSynchronous(DeviceObject, Irp);
IoDetachDevice(deviceExtension->TargetDeviceObject);
IoDeleteDevice(DeviceObject);
//
// Complete the Irp
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -