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

📄 disk.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 5 页
字号:
                                            srbControl,
                                            sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
                                            srbControl,
                                            sizeof(SRB_IO_CONTROL) + length,
                                            FALSE,
                                            &event,
                                            &ioStatus);

        if (irp2 == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            ExFreePool(srbControl);
            break;
        }

        //
        // Call the port driver with the request and wait for it to complete.
        //

        status = IoCallDriver(commonExtension->LowerDeviceObject, irp2);

        if (status == STATUS_PENDING) {
            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
            status = ioStatus.Status;
        }

        //
        // Copy the data received into the output buffer. Since the status buffer
        // contains error information also, always perform this copy. IO will will
        // either pass this back to the app, or zero it, in case of error.
        //

        buffer = (PUCHAR)srbControl;
        (ULONG_PTR)buffer += srbControl->HeaderLength;

        //
        // Update the return buffer size based on the sub-command.
        //

        if (cmdInParameters->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) {
            length = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
        } else {
            length = sizeof(SENDCMDOUTPARAMS) - 1;
        }

        RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, buffer, length);
        Irp->IoStatus.Information = length;

        ExFreePool(srbControl);
        break;

    }

    case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: {

        PMODE_PARAMETER_BLOCK blockDescriptor;
        ULONG modeLength;
        ULONG retries = 4;
        BOOLEAN writable = FALSE;
        BOOLEAN mediaPresent = FALSE;

        DebugPrint((3,
                   "Disk.DiskDeviceControl: GetMediaTypes\n"));

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(GET_MEDIA_TYPES)) {
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(GET_MEDIA_TYPES);
            break;
        }

        if(!commonExtension->IsFdo) {
            ClassReleaseRemoveLock(DeviceObject, Irp);
            ExFreePool(srb);
            SendToFdo(DeviceObject, Irp, status);
            return status;
        }

        //
        // Send a TUR to determine if media is present.
        //

        srb->CdbLength = 6;
        cdb = (PCDB)srb->Cdb;
        cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;

        //
        // Set timeout value.
        //

        srb->TimeOutValue = fdoExtension->TimeOutValue;

        status = ClassSendSrbSynchronous(DeviceObject,
                                         srb,
                                         NULL,
                                         0,
                                         FALSE);


        if (NT_SUCCESS(status)) {
            mediaPresent = TRUE;
        }

        RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);

        //
        // Allocate memory for mode header and block descriptor.
        //

        modeLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
        modeData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
                                         modeLength,
                                         DISK_TAG_MODE_DATA);

        if (modeData == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        RtlZeroMemory(modeData, modeLength);

        //
        // Build the MODE SENSE CDB.
        //

        srb->CdbLength = 6;
        cdb = (PCDB)srb->Cdb;

        //
        // Set timeout value from device extension.
        //

        srb->TimeOutValue = fdoExtension->TimeOutValue;

        //
        // Page code of 0 will return header and block descriptor only.
        //

        cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        cdb->MODE_SENSE.PageCode = 0;
        cdb->MODE_SENSE.AllocationLength = (UCHAR)modeLength;

Retry:
        status = ClassSendSrbSynchronous(DeviceObject,
                                         srb,
                                         modeData,
                                         modeLength,
                                         FALSE);


        if (status == STATUS_VERIFY_REQUIRED) {

            if (retries--) {

                //
                // Retry request.
                //

                goto Retry;
            }
        } else if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
            status = STATUS_SUCCESS;
        }

        if (NT_SUCCESS(status) || (status == STATUS_NO_MEDIA_IN_DEVICE)) {

            //
            // Get the block descriptor.
            //

            blockDescriptor = (PMODE_PARAMETER_BLOCK)modeData;
            (ULONG_PTR)blockDescriptor += sizeof(MODE_PARAMETER_HEADER);

            //
            // Do some validation.
            //

            if (modeData->BlockDescriptorLength != sizeof(MODE_PARAMETER_BLOCK)) {

                DebugPrint((1,
                           "DiskDeviceControl: BlockDescriptor length - "
                           "Expected %x, actual %x\n",
                           modeData->BlockDescriptorLength,
                           sizeof(MODE_PARAMETER_BLOCK)));
            }

            DebugPrint((1,
                       "DiskDeviceControl: DensityCode %x, MediumType %x\n",
                       blockDescriptor->DensityCode,
                       modeData->MediumType));

            if (TEST_FLAG(modeData->DeviceSpecificParameter,
                          MODE_DSP_WRITE_PROTECT)) {
                writable = FALSE;
            } else {
                writable = TRUE;
            }

            status = DiskDetermineMediaTypes(DeviceObject,
                                             Irp,
                                             modeData->MediumType,
                                             blockDescriptor->DensityCode,
                                             mediaPresent,
                                             writable);

            //
            // If the buffer was too small, DetermineMediaTypes updated the status and information and the request will fail.
            //

        } else {
            DebugPrint((1,
                       "DiskDeviceControl: Mode sense for header/bd failed. %lx\n",
                       status));
        }

        ExFreePool(modeData);
        break;
    }

    case IOCTL_DISK_GET_DRIVE_GEOMETRY: {

        DebugPrint((2, "IOCTL_DISK_GET_DRIVE_GEOMETRY to device %p through irp %p\n",
                    DeviceObject, Irp));
        DebugPrint((2, "Device is a%s.\n",
                    commonExtension->IsFdo ? "n fdo" : " pdo"));

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(DISK_GEOMETRY)) {

            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
            break;
        }

        if(!commonExtension->IsFdo) {

            //
            // Pdo should issue this request to the lower device object
            //

            ClassReleaseRemoveLock(DeviceObject, Irp);
            ExFreePool(srb);
            SendToFdo(DeviceObject, Irp, status);
            return status;
        }

        // DiskAcquirePartitioningLock(fdoExtension);

        if (TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {

            //
            // Issue ReadCapacity to update device extension
            // with information for current media.
            //

            status = DiskReadDriveCapacity(
                        commonExtension->PartitionZeroExtension->DeviceObject);

            //
            // Note whether the drive is ready.
            //

            diskData->ReadyStatus = status;

            if (!NT_SUCCESS(status)) {
                // DiskReleasePartitioningLock(fdoExtension);
                break;
            }
        }

        //
        // Copy drive geometry information from device extension.
        //

        RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
                      &(fdoExtension->DiskGeometry),
                      sizeof(DISK_GEOMETRY));

        status = STATUS_SUCCESS;
        Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
        // DiskReleasePartitioningLock(fdoExtension);
        break;
    }

    case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: {
        DebugPrint((1, "IOCTL_DISK_GET_DRIVE_GEOMETRY_EX to device %p through irp %p\n",
                DeviceObject, Irp));
        DebugPrint((1, "Device Is a%s.\n",
                commonExtension->IsFdo ? "n fdo" : " pdo"));


        if (!commonExtension->IsFdo) {

            //
            // Pdo should issue this request to the lower device object
            //

            ClassReleaseRemoveLock (DeviceObject, Irp);
            ExFreePool (srb);
            SendToFdo (DeviceObject, Irp, status);
            return status;

        } else {

            status = DiskIoctlGetDriveGeometryEx( DeviceObject, Irp );
        }

        break;
    }

    case IOCTL_STORAGE_PREDICT_FAILURE : {

        PSTORAGE_PREDICT_FAILURE checkFailure;
        STORAGE_FAILURE_PREDICT_STATUS diskSmartStatus;

        DebugPrint((2, "IOCTL_STORAGE_PREDICT_FAILURE to device %p through irp %p\n",
                    DeviceObject, Irp));
        DebugPrint((2, "Device is a%s.\n",
                    commonExtension->IsFdo ? "n fdo" : " pdo"));

        checkFailure = (PSTORAGE_PREDICT_FAILURE)Irp->AssociatedIrp.SystemBuffer;

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(STORAGE_PREDICT_FAILURE)) {

            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);
            break;
        }

        if(!commonExtension->IsFdo) {

            //
            // Pdo should issue this request to the lower device object
            //

            ClassReleaseRemoveLock(DeviceObject, Irp);
            ExFreePool(srb);
            SendToFdo(DeviceObject, Irp, status);
            return status;
        }

        //
        // See if the disk is predicting failure
        //

        if (diskData->FailurePredictionCapability == FailurePredictionSense) {
            ULONG readBufferSize;
            PUCHAR readBuffer;
            PIRP readIrp;
            IO_STATUS_BLOCK ioStatus;
            PDEVICE_OBJECT topOfStack;

            checkFailure->PredictFailure = 0;

            KeInitializeEvent(&event, SynchronizationEvent, FALSE);

            topOfStack = IoGetAttachedDeviceReference(DeviceObject);

            //
            // SCSI disks need to have a read sent down to provoke any
            // failures to be reported.
            //
            // Issue a normal read operation.  The error-handling code in
            // classpnp will take care of a failure prediction by logging the
            // correct event.
            //

            readBufferSize = fdoExtension->DiskGeometry.BytesPerSector;
            readBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                               readBufferSize,
                                               DISK_TAG_SMART);

            if (readBuffer != NULL) {
                LARGE_INTEGER offset;

                offset.QuadPart = 0;
                readIrp = IoBuildSynchronousFsdRequest(
                        IRP_MJ_READ,
                        topOfStack,
                        readBuffer,
                        readBufferSize,
                        &offset,
                        &event,
                        &ioStatus);


                if (readIrp != NULL) {
                    status = IoCallDriver(topOfStack, readIrp);
                    if (status == STATUS_PENDING) {
                        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
                        status = ioStatus.Status;
                    }
                }

                ExFreePool(readBuffer);
            }
            ObDereferenceObject(topOfStack);
        }

        if ((diskData->FailurePredictionCapability == FailurePredictionSmart) ||
            (diskData->FailurePredictionCapability == FailurePredictionSense))
        {
            status = DiskReadFailurePredictStatus(fdoExtension,
                                                  &diskSmartStatus);

            if (NT_SUCCESS(status))
            {
                status = DiskReadFailurePredictData(fdoExtension,
                                           Irp->AssociatedIrp.SystemBuffer);

                if (diskSmartStatus.PredictFailure)
                {
                    checkFailure->PredictFailure = 1;
               

⌨️ 快捷键说明

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