⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diskperf.cpp

📁 实现USB存储设备的只读操作,可以实现所有USB设备
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    LONG               queueLen;

    UNREFERENCED_PARAMETER(Context);

    // Get the per processor partition counters
    // NOTE: DiskPerfReadWrite already check to see if this buffer is NON
    // NULL before scheduling this completion routine, so we assume that it
    // is always non-NULL when we get here

    partitionCounters = (PDISK_PERFORMANCE)
                        ((PCHAR) deviceExtension->DiskCounters
                             + ((ULONG)KeGetCurrentProcessorNumber()
                                * PROCESSOR_COUNTERS_SIZE));
    // Time stamp current request complete.

    if (partitionCounters == NULL) {    // just in case
        return STATUS_SUCCESS;
    };
    difference = (PLARGE_INTEGER) &irpStack->Parameters.Read;
    DiskPerfGetClock(timeStampComplete, NULL);
    difference->QuadPart = timeStampComplete.QuadPart - difference->QuadPart;
    DBGOUT((10, "DiskPerfIoCompletion: TS=%I64u diff %I64u\n",
                     timeStampComplete, difference->QuadPart));

    // Decrement the queue depth counters for the volume.  This is
    // done without the spinlock using the Interlocked functions.
    // This is the only
    // legal way to do this.

    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;
    }

    // Update counters

    if (irpStack->MajorFunction == IRP_MJ_READ) {

        // Add bytes in this request to bytes read counters.

        partitionCounters->BytesRead.QuadPart += Irp->IoStatus.Information;

        // Increment read requests processed counters.

        partitionCounters->ReadCount++;

        // Calculate request processing time.

        partitionCounters->ReadTime.QuadPart += difference->QuadPart;
        DBGOUT((11, "Added RT delta %I64u total %I64u qlen=%d\n",
            difference->QuadPart, partitionCounters->ReadTime.QuadPart,
            queueLen));


		DbgPrint(("读操作 diskperf.c\n"));

    }

    else {

		// 写操作

		// Add bytes in this request to bytes write counters.

		partitionCounters->BytesWritten.QuadPart += Irp->IoStatus.Information;

		// Increment write requests processed counters.

		// partitionCounters->WriteCount++;

		// Calculate request processing time.

		partitionCounters->WriteTime.QuadPart += difference->QuadPart;
		DBGOUT((11, "Added WT delta %I64u total %I64u qlen=%d\n",
			difference->QuadPart, partitionCounters->WriteTime.QuadPart,
			queueLen));


		DbgPrint(("写操作 diskperf.c\n"));


    }

    if (Irp->Flags & IRP_ASSOCIATED_IRP) {
        partitionCounters->SplitCount++;
    }

    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }
    return STATUS_SUCCESS;

} // DiskPerfIoCompletion


NTSTATUS
DiskPerfDeviceControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )

/*++

Routine Description:

    This device control dispatcher handles only the disk performance
    device control. All others are passed down to the disk drivers.
    The disk performane device control returns a current snapshot of
    the performance data.

Arguments:

    DeviceObject - Context for the activity.
    Irp          - The device control argument block.

Return Value:

    Status is returned.

--*/

{
    PDEVICE_EXTENSION  deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);

    DBGOUT((2, "DiskPerfDeviceControl: DeviceObject %X Irp %X\n",
                    DeviceObject, Irp));

//////////////////////////////////////////////////////////////////////////
	if( currentIrpStack->Parameters.DeviceIoControl.IoControlCode == 
		DISK_READONLY )
	{
		// 
		IsReadOnly = TRUE;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		DbgPrint(("My Ioctrl DISK_READONLY \n"));

		return STATUS_SUCCESS;
	}

	if( currentIrpStack->Parameters.DeviceIoControl.IoControlCode == 
		DISK_NONREADONLY )
	{
		// 
		IsReadOnly = FALSE;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		DbgPrint(("My Ioctrl DISK_NONREADONLY \n"));

		return STATUS_SUCCESS;
	}
//////////////////////////////////////////////////////////////////////////
    if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode ==
        IOCTL_DISK_PERFORMANCE) {

        NTSTATUS        status;
        KIRQL     currentIrql;

        // Verify user buffer is large enough for the performance data.

        if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(DISK_PERFORMANCE)) {

        // Indicate unsuccessful status and no data transferred.

        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;

                DBGOUT((10, "DiskPerfDeviceControl: LIC=%I64u\n", deviceExtension->LastIdleClock));
                DBGOUT((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);
        }

        // Complete request.

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;

    }

    else {

        // Set current stack back one.

        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
    )

/*++

Routine Description:

    This routine handles any WMI requests for information. Since the disk
    information is read-only, is always collected and does not have any
    events only QueryAllData, QuerySingleInstance and GetRegInfo requests
    are supported.

Arguments:

    DeviceObject - Context for the activity.
    Irp          - The device control argument block.

Return Value:

    Status is returned.

--*/

{
    PIO_STACK_LOCATION      irpSp;
    NTSTATUS status;
    PWMILIB_CONTEXT wmilibContext;
    SYSCTL_IRP_DISPOSITION disposition;
    PDEVICE_EXTENSION  deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

    PAGED_CODE();

    DBGOUT((2, "DiskPerfWmi: DeviceObject %X Irp %X\n",
                    DeviceObject, Irp));
    wmilibContext = &deviceExtension->WmilibContext;
    if (wmilibContext->GuidCount == 0)  // wmilibContext is not valid
    {
        DBGOUT((3, "DiskPerfWmi: WmilibContext invalid"));
        return DiskPerfSendToNextDriver(DeviceObject, Irp);
    }

    irpSp = IoGetCurrentIrpStackLocation(Irp);

        DBGOUT((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
    )

/*++

Routine Description:

    This routine is called for a shutdown and flush IRPs.  These are sent by the
    system before it actually shuts down or when the file system does a flush.

Arguments:

    DriverObject - Pointer to device object to being shutdown by system.
    Irp          - IRP involved.

Return Value:

    NT Status

--*/

{
    PDEVICE_EXTENSION  deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // Set current stack back one.

    DBGOUT((2, "DiskPerfShutdownFlush: DeviceObject %X Irp %X\n",
                    DeviceObject, Irp));
    Irp->CurrentLocation++,
    Irp->Tail.Overlay.CurrentStackLocation++;

    return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

} // end DiskPerfShutdownFlush()


VOID
DiskPerfUnload(
    IN PDRIVER_OBJECT DriverObject
    )

/*++

Routine Description:

    Free all the allocated resources, etc.

Arguments:

    DriverObject - pointer to a driver object.

Return Value:

    VOID.

--*/
{
    PAGED_CODE();

    return;
}


NTSTATUS
DiskPerfRegisterDevice(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    Routine to initialize a proper name for the device object, and
    register it with WMI

Arguments:

    DeviceObject - pointer to a device object to be initialized.

Return Value:

    Status of the initialization. NOTE: If the registration fails,
    the device name in the DeviceExtension will be left as empty.

--*/

{
    NTSTATUS                status;
    IO_STATUS_BLOCK         ioStatus;
    KEVENT                  event;
    PDEVICE_EXTENSION       deviceExtension;
    PIRP                    irp;
    STORAGE_DEVICE_NUMBER   number;
    ULONG                   registrationFlag = 0;

    PAGED_CODE();

    DBGOUT((2, "DiskPerfRegisterDevice: DeviceObject %X\n",
                    DeviceObject));
    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    // Request for the device number

    irp = IoBuildDeviceIoControlRequest(
                    IOCTL_STORAGE_GET_DEVICE_NUMBER,
                    deviceExtension->TargetDeviceObject,
                    NULL,
                    0,
                    &number,
                    sizeof(number),

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -