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

📄 diskwmi.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 5 页
字号:
                                   &DiskReregHead,
                                   &reregRequest->Next,
                                   &DiskReregSpinlock);
    
        if (InterlockedIncrement(&DiskReregWorkItems) == 1)
        {
            ExQueueWorkItem( &DiskReregWorkItem, DelayedWorkQueue );
        }
        status = STATUS_SUCCESS;
    } else {
        DebugPrint((1, "DiskPostReregisterRequest: could not allocate reregRequest for %p\n",
                    DeviceObject));
        status = STATUS_INSUFFICIENT_RESOURCES;
    }
    
    return(status);
}

NTSTATUS DiskInfoExceptionComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    )
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
    PSCSI_REQUEST_BLOCK srb = Context;
    NTSTATUS status;
    BOOLEAN retry;
    ULONG retryInterval;
    ULONG srbStatus;
    BOOLEAN freeLockAndIrp = TRUE;
    KIRQL oldIrql;

    ASSERT(fdoExtension->CommonExtension.IsFdo);

    srbStatus = SRB_STATUS(srb->SrbStatus);

    //
    // Check SRB status for success of completing request.
    // SRB_STATUS_DATA_OVERRUN also indicates success.
    //
    if ((srbStatus != SRB_STATUS_SUCCESS) &&
        (srbStatus != SRB_STATUS_DATA_OVERRUN))
    {    
        DebugPrint((2, "DiskInfoExceptionComplete: IRP %p, SRB %p\n", Irp, srb));

        retry = ClassInterpretSenseInfo(
                    DeviceObject,
                    srb,
                    irpStack->MajorFunction,
                     0,
                    MAXIMUM_RETRIES -
                        ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
                    &status,
                    &retryInterval);

        //
        // If the status is verified required and the this request
        // should bypass verify required then retry the request.
        //

        if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
            status == STATUS_VERIFY_REQUIRED)
        {
            status = STATUS_IO_DEVICE_ERROR;
            retry = TRUE;
        }

        if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--)
        {

            //
            // Retry request.
            //

            DebugPrint((1, "DiskInfoExceptionComplete: Retry request %p\n", Irp));
            
            ASSERT(srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
            
            //
            // Reset byte count of transfer in SRB Extension.
            //
            srb->DataTransferLength = Irp->MdlAddress->ByteCount;
            
            //
            // Zero SRB statuses.
            //

            srb->SrbStatus = srb->ScsiStatus = 0;

            //
            // Set the no disconnect flag, disable synchronous data transfers and
            // disable tagged queuing. This fixes some errors.
            //

            SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
            SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
            CLEAR_FLAG(srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);

            srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
            srb->QueueTag = SP_UNTAGGED;

            //
            // Set up major SCSI function.
            //

            nextIrpStack->MajorFunction = IRP_MJ_SCSI;

            //
            // Save SRB address in next stack for port driver.
            //

            nextIrpStack->Parameters.Scsi.Srb = srb;


            IoSetCompletionRoutine(Irp,
                                   DiskInfoExceptionComplete,
                                   srb,
                                   TRUE, TRUE, TRUE);
            
            (VOID)IoCallDriver(commonExtension->LowerDeviceObject, Irp);
        
            return STATUS_MORE_PROCESSING_REQUIRED;
        }
    
    } else {

        //
        // Get the results from the mode sense
        //
        PMODE_INFO_EXCEPTIONS pageData;
        PMODE_PARAMETER_HEADER modeData;
        ULONG modeDataLength;

        modeData = srb->DataBuffer;
        modeDataLength = srb->DataTransferLength;
        
        pageData = ClassFindModePage((PUCHAR) modeData,
                                     modeDataLength,
                                     MODE_PAGE_FAULT_REPORTING,
                                     TRUE);
        if (pageData != NULL)
        {
            DebugPrint((1, "DiskInfoExceptionComplete: %p supports SMART\n",
                        DeviceObject));

            if (pageData->Dexcpt == 0)
            {
                diskData->FailurePredictionCapability = FailurePredictionSense;
                status = DiskPostReregisterRequest(DeviceObject, Irp);

                if (NT_SUCCESS(status))
                {
                    //
                    // Make sure we won't free the remove lock and the irp
                    // since we need to keep these until after the work
                    // item has completed running
                    //
                    freeLockAndIrp = FALSE;
                }
            } else {
                DebugPrint((1, "DiskInfoExceptionComplete: %p is not enabled for SMART\n",
                        DeviceObject));
            
            }
            
        } else {
            DebugPrint((1, "DiskInfoExceptionComplete: %p does not supports SMART\n",
                        DeviceObject));
            
        }
        
        //
        // Set status for successful request
        //

        status = STATUS_SUCCESS;

    } // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)

    //
    // Free the srb
    //
    ExFreePool(srb->SenseInfoBuffer);
    ExFreePool(srb->DataBuffer);
    ExFreePool(srb);
        
    if (freeLockAndIrp)
    {
        //
        // Set status in completing IRP.
        //

        Irp->IoStatus.Status = status;

        //
        // If pending has be returned for this irp then mark the current stack as
        // pending.
        //

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

        ClassReleaseRemoveLock(DeviceObject, Irp);
        IoFreeMdl(Irp->MdlAddress);
        IoFreeIrp(Irp);
    }
    
    return(STATUS_MORE_PROCESSING_REQUIRED);
    
}

NTSTATUS DiskInfoExceptionCheck(
    PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PUCHAR modeData;
    PSCSI_REQUEST_BLOCK srb;
    PCDB cdb;
    PIRP irp;
    PIO_STACK_LOCATION irpStack;
    PVOID senseInfoBuffer;
    ULONG isRemoved;
    
    modeData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
                                     MODE_DATA_SIZE,
                                     DISK_TAG_INFO_EXCEPTION);
    if (modeData == NULL)
    {
        DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate mode data "
                        "buffer\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);
    }
        
    srb = ExAllocatePoolWithTag(NonPagedPool,
                                SCSI_REQUEST_BLOCK_SIZE,
                                DISK_TAG_SRB);
    if (srb == NULL)
    {
        ExFreePool(modeData);
        DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate srb "
                        "buffer\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);      
    }
    
    //
    // Build the MODE SENSE CDB.
    //
    RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
    
    cdb = (PCDB)srb->Cdb;
    srb->CdbLength = 6;
    cdb = (PCDB)srb->Cdb;
    
    //
    // Set timeout value from device extension.
    //
    srb->TimeOutValue = FdoExtension->TimeOutValue;

    cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
    cdb->MODE_SENSE.PageCode = MODE_PAGE_FAULT_REPORTING;
    cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
    
    //
    // Write length to SRB.
    //
    srb->Length = SCSI_REQUEST_BLOCK_SIZE;

    //
    // Set SCSI bus address.
    //

    srb->Function = SRB_FUNCTION_EXECUTE_SCSI;

    //
    // Enable auto request sense.
    //  
    
    srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;

    //
    // Sense buffer is in aligned nonpaged pool.
    //

    senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
                                     SENSE_BUFFER_SIZE,
                                     '7CcS');

    if (senseInfoBuffer == NULL)
    {
        ExFreePool(srb);
        ExFreePool(modeData);
        DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate request sense "
                        "buffer\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    srb->SenseInfoBuffer = senseInfoBuffer;
    srb->DataBuffer = modeData;
    
    srb->SrbFlags = FdoExtension->SrbFlags;


    SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN);
    
    //
    // Disable synchronous transfer for these requests.
    //
    SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);

    //
    // Don't freeze the queue on an error
    //  
    SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);

    srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
    srb->QueueTag = SP_UNTAGGED;

        
    //
    // Build device I/O control request with METHOD_NEITHER data transfer.
    // We'll queue a completion routine to cleanup the MDL's and such ourself.
    //

    irp = IoAllocateIrp(
            (CCHAR) (FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
            FALSE);

    if (irp == NULL)
    {
        ExFreePool(senseInfoBuffer);
        ExFreePool(srb);
        ExFreePool(modeData);
        DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate Irp\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    isRemoved = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);

    if (isRemoved)
    {
        ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
        IoFreeIrp(irp);
        ExFreePool(senseInfoBuffer);
        ExFreePool(srb);
        ExFreePool(modeData);
        DebugPrint((1, "DiskInfoExceptionCheck: RemoveLock says isRemoved\n"));
        return(STATUS_DEVICE_DOES_NOT_EXIST);
    }
    
    //
    // Get next stack location.
    //

    IoSetNextIrpStackLocation(irp);
    irpStack = IoGetCurrentIrpStackLocation(irp);
    irpStack->DeviceObject = FdoExtension->DeviceObject;

    //
    // Save retry count in current Irp stack.
    //
    irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
    
    
    irpStack = IoGetNextIrpStackLocation(irp);

    //
    // Set up SRB for execute scsi request. Save SRB address in next stack
    // for the port driver.
    //

    irpStack->MajorFunction = IRP_MJ_SCSI;
    irpStack->Parameters.Scsi.Srb = srb;

    IoSetCompletionRoutine(irp,
                           DiskInfoExceptionComplete,
                           srb,
                           TRUE,
                           TRUE,
                           TRUE);

    irp->MdlAddress = IoAllocateMdl( modeData,
                                     MODE_DATA_SIZE,
                                     FALSE,
                                     FALSE,
                                     irp );
    if (irp->MdlAddress == NULL)
    {
        ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
        ExFreePool(srb);
        ExFreePool(modeData);
        ExFreePool(senseInfoBuffer);
        IoFreeIrp( irp );
        DebugPrint((1, "DiskINfoExceptionCheck: Can't allocate MDL\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool(irp->MdlAddress);
        
    //
    // Set the transfer length.
    //
    srb->DataTransferLength = MODE_DATA_SIZE;

    //
    // Zero out status.
    //
    srb->ScsiStatus = srb->SrbStatus = 0;
    srb->NextSrb = 0;

    //
    // Set up IRP Address.
    //
    srb->OriginalRequest = irp;
    
    //
    // Call the port driver with the request and wait for it to complete.
    //

    IoMarkIrpPending(irp);
    IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject,
                          irp);

    return(STATUS_PENDING);
}

NTSTATUS
DiskDetectFailurePrediction(
    PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
    PFAILURE_PREDICTION_METHOD FailurePredictCapability
    )
/*++

Routine Description:

    Detect if device has any failure prediction capabilities. First we

⌨️ 快捷键说明

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