|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1991 Microsoft Corporation
4:
5: Module Name:
6:
7: diskperf.c
8:
9: Abstract:
10:
11: This driver monitors disk accesses capturing performance data.
12:
13: Authors:
14:
15: Mike Glass
16: Bob Rinne
17:
18: Environment:
19:
20: kernel mode only
21:
22: Notes:
23:
24: Revision History:
25:
26: --*/
27:
28: #include "ntddk.h"
29: #include "stdarg.h"
30: #include "stdio.h"
31: #include "ntdddisk.h"
32:
33: //
34: // This macro has the effect of Bit = log2(Data)
35: // and is used to calculate sector shifts.
36: //
37:
38: #define WHICH_BIT(Data, Bit) { \
39: for (Bit = 0; Bit < 32; Bit++) { \
40: if ((Data >> Bit) == 1) { \
41: break; \
42: } \
43: } \
44: }
45:
46: //
47: // Device Extension
48: //
49:
50: typedef struct _DEVICE_EXTENSION {
51:
52: //
53: // Back pointer to device object
54: //
55:
56: PDEVICE_OBJECT DeviceObject;
57:
58: //
59: // Target Device Object
60: //
61:
62: PDEVICE_OBJECT TargetDeviceObject;
63:
64: //
65: // Physical Device Object
66: //
67:
68: PDEVICE_OBJECT PhysicalDevice;
69:
70: //
71: // Sector size
72: //
73:
74: ULONG SectorSize;
75:
76: //
77: // Sector Shift Count
78: //
79:
80: ULONG SectorShift;
81:
82: //
83: // Disk performance counters
84: //
85:
86: DISK_PERFORMANCE DiskCounters;
87:
88: //
89: // Spinlock for counters (physical disks only)
90: //
91:
92: KSPIN_LOCK Spinlock;
93:
94: } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
95:
96: #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
97:
98:
99: //
100: // Function declarations
101: //
102:
103: NTSTATUS
104: DriverEntry(
105: IN PDRIVER_OBJECT DriverObject,
106: IN PUNICODE_STRING RegistryPath
107: );
108:
109: VOID
110: DiskPerfInitialize(
111: IN PDRIVER_OBJECT DriverObject,
112: IN PVOID NextDisk,
113: IN ULONG Count
114: );
115:
116: NTSTATUS
117: DiskPerfCreate(
118: IN PDEVICE_OBJECT DeviceObject,
119: IN PIRP Irp
120: );
121:
122: NTSTATUS
123: DiskPerfReadWrite(
124: IN PDEVICE_OBJECT DeviceObject,
125: IN PIRP Irp
126: );
127:
128: NTSTATUS
129: DiskPerfIoCompletion(
130: IN PDEVICE_OBJECT DeviceObject,
131: IN PIRP Irp,
132: IN PVOID Context
133: );
134:
135: NTSTATUS
136: DiskPerfDeviceControl(
137: IN PDEVICE_OBJECT DeviceObject,
138: IN PIRP Irp
139: );
140:
141: NTSTATUS
142: DiskPerfShutdownFlush(
143: IN PDEVICE_OBJECT DeviceObject,
144: IN PIRP Irp
145: );
146:
147:
148: NTSTATUS
149: DriverEntry(
150: IN PDRIVER_OBJECT DriverObject,
151: IN PUNICODE_STRING RegistryPath
152: )
153:
154: /*++
155:
156: Routine Description:
157:
158: This is the routine called by the system to initialize the disk
159: performance driver. The driver object is set up and then the
160: driver calls DiskPerfInitialize to attach to the boot devices.
161:
162: Arguments:
163:
164: DriverObject - The disk performance driver object.
165:
166: Return Value:
167:
168: NTSTATUS
169:
170: --*/
171:
172: {
173:
174: //
175: // Set up the device driver entry points.
176: //
177:
178: DriverObject->MajorFunction[IRP_MJ_CREATE] = DiskPerfCreate;
179: DriverObject->MajorFunction[IRP_MJ_READ] = DiskPerfReadWrite;
180: DriverObject->MajorFunction[IRP_MJ_WRITE] = DiskPerfReadWrite;
181: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DiskPerfDeviceControl;
182: DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DiskPerfShutdownFlush;
183: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DiskPerfShutdownFlush;
184:
185: //
186: // Call the initialization routine for the first time.
187: //
188:
189: DiskPerfInitialize(DriverObject, 0, 0);
190:
191: return(STATUS_SUCCESS);
192:
193: } // DriverEntry
194:
195:
196: VOID
197: DiskPerfInitialize(
198: IN PDRIVER_OBJECT DriverObject,
199: IN PVOID NextDisk,
200: IN ULONG Count
201: )
202:
203: /*++
204:
205: Routine Description:
206:
207: Attach to new disk devices and partitions.
208: Set up device objects for counts and times.
209: If this is the first time this routine is called,
210: then register with the IO system to be called
211: after all other disk device drivers have initiated.
212:
213: Arguments:
214:
215: DriverObject - Disk performance driver object.
216: NextDisk - Starting disk for this part of the initialization.
217: Count - Not used. Number of times this routine has been called.
218:
219: Return Value:
220:
221: NTSTATUS
222:
223: --*/
224:
225: {
226: PCONFIGURATION_INFORMATION configurationInformation;
227: CCHAR ntNameBuffer[256];
228: STRING ntNameString;
229: UNICODE_STRING ntUnicodeString;
230: PDEVICE_OBJECT deviceObject;
231: PDEVICE_OBJECT physicalDevice;
232: PDEVICE_EXTENSION deviceExtension;
233: PFILE_OBJECT fileObject;
234: PIRP irp;
235: PDISK_GEOMETRY diskGeometry;
236: PDRIVE_LAYOUT_INFORMATION partitionInfo;
237: KEVENT event;
238: IO_STATUS_BLOCK ioStatusBlock;
239: NTSTATUS status;
240: ULONG diskNumber;
241: ULONG partNumber;
242:
243: //
244: // Get the configuration information.
245: //
246:
247: configurationInformation = IoGetConfigurationInformation();
248:
249: //
250: // Find disk devices.
251: //
252:
253: for (diskNumber = (ULONG)NextDisk;
254: diskNumber < configurationInformation->DiskCount;
255: diskNumber++) {
256:
257: //
258: // Create device name for the physical disk.
259: //
260:
261: sprintf(ntNameBuffer,
262: "\\Device\\Harddisk%d\\Partition0",
263: diskNumber);
264:
265: RtlInitAnsiString(&ntNameString,
266: ntNameBuffer);
267:
268: RtlAnsiStringToUnicodeString(&ntUnicodeString,
269: &ntNameString,
270: TRUE);
271:
272: //
273: // Create device object for partition 0.
274: //
275:
276: status = IoCreateDevice(DriverObject,
277: sizeof(DEVICE_EXTENSION),
278: NULL,
279: FILE_DEVICE_DISK,
280: 0,
281: FALSE,
282: &physicalDevice);
283:
284: physicalDevice->Flags |= DO_DIRECT_IO;
285:
286: //
287: // Point device extension back at device object.
288: //
289:
290: deviceExtension = physicalDevice->DeviceExtension;
291: deviceExtension->DeviceObject = physicalDevice;
292:
293: //
294: // This is the physical device object.
295: //
296:
297: deviceExtension->PhysicalDevice = physicalDevice;
298:
299: //
300: // Attach to partition0. This call links the newly created
301: // device to the target device, returning the target device object.
302: //
303:
304: status = IoAttachDevice(physicalDevice,
305: &ntUnicodeString,
306: &deviceExtension->TargetDeviceObject);
307:
308: if (!NT_SUCCESS(status)) {
309: IoDeleteDevice(physicalDevice);
310: break;
311: }
312:
313: RtlFreeUnicodeString(&ntUnicodeString);
314:
315: //
316: // Allocate buffer for drive geometry.
317: //
318:
319: diskGeometry = ExAllocatePool(NonPagedPool,
320: sizeof(DISK_GEOMETRY));
321:
322: //
323: // Create IRP for get drive geometry device control.
324: //
325:
326: irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
327: deviceExtension->TargetDeviceObject,
328: NULL,
329: 0,
330: diskGeometry,
331: sizeof(DISK_GEOMETRY),
332: FALSE,
333: &event,
334: &ioStatusBlock);
335:
336: //
337: // Set the event object to the unsignaled state.
338: // It will be used to signal request completion.
339: //
340:
341: KeInitializeEvent(&event,
342: NotificationEvent,
343: FALSE);
344:
345: //
346: // No need to check the following two returned statuses as
347: // ioBlockStatus will have ending status.
348: //
349:
350: IoCallDriver(deviceExtension->TargetDeviceObject,
351: irp);
352:
353: KeWaitForSingleObject(&event,
354: Suspended,
355: KernelMode,
356: FALSE,
357: NULL);
358:
359: if (!NT_SUCCESS(ioStatusBlock.Status)) {
360: ExFreePool(diskGeometry);
361: IoDeleteDevice(physicalDevice);
362: break;
363: }
364:
365: //
366: // Store number of bytes per sector.
367: //
368:
369: deviceExtension->SectorSize = diskGeometry->BytesPerSector;
370:
371: //
372: // Calculate and store sector shift.
373: //
374:
375: WHICH_BIT(deviceExtension->SectorSize, deviceExtension->SectorShift);
376:
377: //
378: // Initialize spinlock for performance measures.
379: //
380:
381: KeInitializeSpinLock(&deviceExtension->Spinlock);
382:
383: //
384: // Allocate buffer for drive layout.
385: //
386:
387: partitionInfo = ExAllocatePool(NonPagedPool,
388: (26 * sizeof(PARTITION_INFORMATION) + 4));
389:
390: //
391: // Create IRP for get drive layout device control.
392: //
393:
394: irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_LAYOUT,
395: deviceExtension->TargetDeviceObject,
396: NULL,
397: 0,
398: partitionInfo,
399: (26 * sizeof(PARTITION_INFORMATION) + 4),
400: FALSE,
401: &event,
402: &ioStatusBlock);
403:
404: //
405: // Set the event object to the unsignaled state.
406: // It will be used to signal request completion.
407: //
408:
409: KeInitializeEvent(&event,
410: NotificationEvent,
411: FALSE);
412:
413: //
414: // No need to check the following two returned statuses as
415: // ioBlockStatus will have ending status.
416: //
417:
418: IoCallDriver(deviceExtension->TargetDeviceObject,
419: irp);
420:
421: KeWaitForSingleObject(&event,
422: Suspended,
423: KernelMode,
424: FALSE,
425: NULL);
426:
427: if (!NT_SUCCESS(ioStatusBlock.Status)) {
428: ExFreePool(partitionInfo);
429: ExFreePool(diskGeometry);
430: IoDeleteDevice(physicalDevice);
431: break;
432: }
433:
434: for (partNumber = 1;
435: partNumber < partitionInfo->PartitionCount;
436: partNumber++) {
437:
438: //
439: // Create device name for partition.
440: //
441:
442: sprintf(ntNameBuffer,
443: "\\Device\\Harddisk%d\\Partition%d",
444: diskNumber,
445: partNumber);
446:
447: RtlInitAnsiString(&ntNameString,
448: ntNameBuffer);
449:
450: RtlAnsiStringToUnicodeString(&ntUnicodeString,
451: &ntNameString,
452: TRUE);
453:
454: //
455: // Get target device object.
456: //
457:
458: status = IoGetDeviceObjectPointer(&ntUnicodeString,
459: FILE_READ_ATTRIBUTES,
460: &fileObject,
461: &deviceObject);
462:
463: if (!NT_SUCCESS(status)) {
464: RtlFreeUnicodeString(&ntUnicodeString);
465: continue;
466: }
467:
468: //
469: // Check if this device is already mounted.
470: //
471:
472: if (!deviceObject->Vpb ||
473: (deviceObject->Vpb->Flags & VPB_MOUNTED)) {
474:
475: //
476: // Can't attach to a device that is already mounted.
477: //
478:
479: ObDereferenceObject(fileObject);
480: RtlFreeUnicodeString(&ntUnicodeString);
481: continue;
482: }
483:
484: ObDereferenceObject(fileObject);
485:
486: //
487: // Create device object for this partition.
488: //
489:
490: status = IoCreateDevice(DriverObject,
491: sizeof(DEVICE_EXTENSION),
492: NULL,
493: FILE_DEVICE_DISK,
494: 0,
495: FALSE,
496: &deviceObject);
497:
498: deviceObject->Flags |= DO_DIRECT_IO;
499:
500: //
501: // Point device extension back at device object.
502: //
503:
504: deviceExtension = deviceObject->DeviceExtension;
505: deviceExtension->DeviceObject = deviceObject;
506:
507: //
508: // Store pointer to physical device.
509: //
510:
511: deviceExtension->PhysicalDevice = physicalDevice;
512:
513: //
514: // Attach to the partition. This call links the newly created
515: // device to the target device, returning the target device object.
516: //
517:
518: status = IoAttachDevice(deviceObject,
519: &ntUnicodeString,
520: &deviceExtension->TargetDeviceObject);
521:
522: RtlFreeUnicodeString(&ntUnicodeString);
523:
524: if (!NT_SUCCESS(status)) {
525: ExFreePool(diskGeometry);
526: IoDeleteDevice(deviceObject);
527: break;
528: }
529: }
530: }
531:
532: //
533: // Check if this is the first time this routine has been called.
534: //
535:
536: if (!NextDisk) {
537:
538: //
539: // Register with IO system to be called a second time after all
540: // other device drivers have initialized.
541: //
542:
543: IoRegisterDriverReinitialization(DriverObject,
544: DiskPerfInitialize,
545: (PVOID)configurationInformation->DiskCount);
546: }
547:
548: return;
549:
550: } // end DiskPerfInitialize()
551:
552:
553: NTSTATUS
554: DiskPerfCreate(
555: IN PDEVICE_OBJECT DeviceObject,
556: IN PIRP Irp
557: )
558:
559: /*++
560:
561: Routine Description:
562:
563: This routine services open commands. It establishes
564: the driver's existance by returning status success.
565:
566: Arguments:
567:
568: DeviceObject - Context for the activity.
569: Irp - The device control argument block.
570:
571: Return Value:
572:
573: NT Status
574:
575: --*/
576:
577: {
578: UNREFERENCED_PARAMETER(DeviceObject);
579:
580: Irp->IoStatus.Status = STATUS_SUCCESS;
581:
582: IoCompleteRequest(Irp, 0);
583: return STATUS_SUCCESS;
584:
585: } // end DiskPerfCreate()
586:
587:
588: NTSTATUS
589: DiskPerfReadWrite(
590: IN PDEVICE_OBJECT DeviceObject,
591: IN PIRP Irp
592: )
593:
594: /*++
595:
596: Routine Description:
597:
598: This is the driver entry point for read and write requests
599: to disks to which the diskperf driver has attached.
600: This driver collects statistics and then sets a completion
601: routine so that it can collect additional information when
602: the request completes. Then it calls the next driver below
603: it.
604:
605: Arguments:
606:
607: DeviceObject
608: Irp
609:
610: Return Value:
611:
612: NTSTATUS
613:
614: --*/
615:
616: {
617: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
618: PDEVICE_EXTENSION physicalDisk =
619: deviceExtension->PhysicalDevice->DeviceExtension;
620: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
621: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
622:
623: //
624: // Increment queue depth counter.
625: //
626:
627: ExInterlockedIncrementLong(&deviceExtension->DiskCounters.QueueDepth,
628: &physicalDisk->Spinlock);
629:
630: //
631: // Now get the physical disk counters and increment queue depth.
632: //
633:
634: ExInterlockedIncrementLong(&physicalDisk->DiskCounters.QueueDepth,
635: &physicalDisk->Spinlock);
636:
637: //
638: // Copy current stack to next stack.
639: //
640:
641: *nextIrpStack = *currentIrpStack;
642:
643: //
644: // Time stamp current request start.
645: //
646:
647: currentIrpStack->Parameters.Read.ByteOffset = KeQueryPerformanceCounter((PVOID)NULL);
648:
649: //
650: // Set completion routine callback.
651: //
652:
653: IoSetCompletionRoutine(Irp,
654: DiskPerfIoCompletion,
655: DeviceObject,
656: TRUE,
657: TRUE,
658: TRUE);
659:
660: //
661: // Return the results of the call to the disk driver.
662: //
663:
664: return IoCallDriver(deviceExtension->TargetDeviceObject,
665: Irp);
666:
667: } // end DiskPerfReadWrite()
668:
669:
670: NTSTATUS
671: DiskPerfIoCompletion(
672: IN PDEVICE_OBJECT DeviceObject,
673: IN PIRP Irp,
674: IN PVOID Context
675: )
676:
677: /*++
678:
679: Routine Description:
680:
681: This routine will get control from the system at the completion of an IRP.
682: It will calculate the difference between the time the IRP was started
683: and the current time, and decrement the queue depth.
684:
685: Arguments:
686:
687: DeviceObject - for the IRP.
688: Irp - The I/O request that just completed.
689: Context - Not used.
690:
691: Return Value:
692:
693: The IRP status.
694:
695: --*/
696:
697: {
698: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
699: PDEVICE_EXTENSION physicalDisk =
700: deviceExtension->PhysicalDevice->DeviceExtension;
701: PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
702: PDISK_PERFORMANCE partitionCounters = &deviceExtension->DiskCounters;
703: PDISK_PERFORMANCE diskCounters = &physicalDisk->DiskCounters;
704: LARGE_INTEGER timeStampStart =
705: irpStack->Parameters.Read.ByteOffset;
706: LARGE_INTEGER timeStampComplete;
707: KIRQL currentIrql;
708:
709: UNREFERENCED_PARAMETER(Context);
710:
711: //
712: // Determine if STATUS_PENDING was returned in the dispatch routine.
713: //
714:
715: if (Irp->PendingReturned) {
716: IoMarkIrpPending(Irp);
717: }
718: //
719: // Time stamp current request complete.
720: //
721:
722: timeStampComplete = KeQueryPerformanceCounter((PVOID)NULL);
723:
724: //
725: // Update counters under spinlock protection.
726: //
727:
728: KeAcquireSpinLock(&physicalDisk->Spinlock, ¤tIrql);
729:
730: //
731: // Decrement the queue depth counters for the volume and physical disk.
732: //
733:
734: partitionCounters->QueueDepth--;
735: diskCounters->QueueDepth--;
736:
737: #if DBG
738:
739: //
740: // Verify that the information field, which is used to
741: // return bytes transferred, is being updated by lower drivers.
742: //
743:
744: if (NT_SUCCESS(Irp->IoStatus.Status)) {
745: ASSERT(Irp->IoStatus.Information);
746: }
747:
748: #endif
749:
750: if (irpStack->MajorFunction == IRP_MJ_READ) {
751:
752: //
753: // Add bytes in this request to bytes read counters.
754: //
755:
756: partitionCounters->BytesRead = RtlLargeIntegerAdd(partitionCounters->BytesRead,
757: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information));
758:
759: diskCounters->BytesRead = RtlLargeIntegerAdd(diskCounters->BytesRead,
760: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information));
761:
762: //
763: // Increment read requests processed counters.
764: //
765:
766: partitionCounters->ReadCount++;
767: diskCounters->ReadCount++;
768:
769: //
770: // Calculate request processing time.
771: //
772:
773: partitionCounters->ReadTime = RtlLargeIntegerAdd(partitionCounters->ReadTime,
774: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart));
775:
776: diskCounters->ReadTime = RtlLargeIntegerAdd(diskCounters->ReadTime,
777: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart));
778:
779: } else {
780:
781: //
782: // Add bytes in this request to bytes write counters.
783: //
784:
785: partitionCounters->BytesWritten = RtlLargeIntegerAdd(partitionCounters->BytesWritten,
786: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information));
787:
788: diskCounters->BytesWritten = RtlLargeIntegerAdd(diskCounters->BytesWritten,
789: RtlConvertUlongToLargeInteger(Irp->IoStatus.Information));
790:
791: //
792: // Increment write requests processed counters.
793: //
794:
795: partitionCounters->WriteCount++;
796: diskCounters->WriteCount++;
797:
798: //
799: // Calculate request processing time.
800: //
801:
802: partitionCounters->WriteTime = RtlLargeIntegerAdd(partitionCounters->WriteTime,
803: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart));
804:
805: diskCounters->WriteTime = RtlLargeIntegerAdd(diskCounters->WriteTime,
806: RtlLargeIntegerSubtract(timeStampComplete, timeStampStart));
807: }
808:
809: //
810: // Release spinlock.
811: //
812:
813: KeReleaseSpinLock(&physicalDisk->Spinlock, currentIrql);
814:
815: return Irp->IoStatus.Status;
816:
817: } // DiskPerfIoCompletion
818:
819:
820: NTSTATUS
821: DiskPerfDeviceControl(
822: PDEVICE_OBJECT DeviceObject,
823: PIRP Irp
824: )
825:
826: /*++
827:
828: Routine Description:
829:
830: This device control dispatcher handles only the disk performance
831: device control. All others are passed down to the disk drivers.
832: The disk performane device control returns a current snapshot of
833: the performance data.
834:
835: Arguments:
836:
837: DeviceObject - Context for the activity.
838: Irp - The device control argument block.
839:
840: Return Value:
841:
842: Status is returned.
843:
844: --*/
845:
846: {
847: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
848: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
849: KIRQL currentIrql;
850:
851: if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
852: IOCTL_DISK_PERFORMANCE) {
853:
854: NTSTATUS status;
855:
856: //
857: // Verify user buffer is large enough for the performance data.
858: //
859:
860: if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
861: sizeof(DISK_PERFORMANCE)) {
862:
863: //
864: // Indicate unsuccessful status and no data transferred.
865: //
866:
867: status = STATUS_BUFFER_TOO_SMALL;
868: Irp->IoStatus.Information = 0;
869:
870: } else {
871:
872: PDEVICE_EXTENSION physicalDisk =
873: deviceExtension->PhysicalDevice->DeviceExtension;
874:
875: //
876: // Copy disk counters to buffer under spinlock protection.
877: //
878:
879: KeAcquireSpinLock(&physicalDisk->Spinlock, ¤tIrql);
880:
881: RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
882: &deviceExtension->DiskCounters,
883: sizeof(DISK_PERFORMANCE));
884:
885: KeReleaseSpinLock(&physicalDisk->Spinlock, currentIrql);
886:
887: //
888: // Set IRP status to success and indicate bytes transferred.
889: //
890:
891: status = STATUS_SUCCESS;
892: Irp->IoStatus.Information = sizeof(DISK_PERFORMANCE);
893: }
894:
895: //
896: // Complete request.
897: //
898:
899: Irp->IoStatus.Status = status;
900: IoCompleteRequest(Irp, 0);
901: return status;
902:
903: } else {
904:
905: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
906:
907: #if 0
908: //
909: // Copy stack parameters to next stack.
910: //
911:
912: RtlMoveMemory(nextIrpStack,
913: currentIrpStack,
914: sizeof(IO_STACK_LOCATION));
915:
916: //
917: // Set IRP so IoComplete does not call completion routine
918: // for this driver.
919: //
920:
921: IoSetCompletionRoutine(Irp,
922: NULL,
923: DeviceObject,
924: FALSE,
925: FALSE,
926: FALSE);
927: #endif
928:
929: //
930: // Set current stack back one.
931: //
932:
933: Irp->CurrentLocation++,
934: Irp->Tail.Overlay.CurrentStackLocation++;
935:
936: //
937: // Pass unrecognized device control requests
938: // down to next driver layer.
939: //
940:
941: return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
942: }
943:
944: } // end DiskPerfDeviceControl()
945:
946:
947: NTSTATUS
948: DiskPerfShutdownFlush(
949: IN PDEVICE_OBJECT DeviceObject,
950: IN PIRP Irp
951: )
952:
953: /*++
954:
955: Routine Description:
956:
957: This routine is called for a shutdown and flush IRPs. These are sent by the
958: system before it actually shuts down or when the file system does a flush.
959:
960: Arguments:
961:
962: DriverObject - Pointer to device object to being shutdown by system.
963: Irp - IRP involved.
964:
965: Return Value:
966:
967: NT Status
968:
969: --*/
970:
971: {
972: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
973:
974: //
975: // Set current stack back one.
976: //
977:
978: Irp->CurrentLocation++,
979: Irp->Tail.Overlay.CurrentStackLocation++;
980:
981: return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
982:
983: } // end DiskPerfShutdownFlush()
984:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.