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

📄 disk.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 5 页
字号:
            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);

        modeLength = MODE_DATA_SIZE;
        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 0x3F will return all pages.
        //

        cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        cdb->MODE_SENSE.PageCode         = MODE_SENSE_RETURN_ALL;
        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.
            //

            if (modeData->BlockDescriptorLength != 0)
            {
                blockDescriptor = (PMODE_PARAMETER_BLOCK)modeData;
                (ULONG_PTR)blockDescriptor += sizeof(MODE_PARAMETER_HEADER);

                densityCode = blockDescriptor->DensityCode;
            }

            if (TEST_FLAG(modeData->DeviceSpecificParameter,
                          MODE_DSP_WRITE_PROTECT)) {

                writable = FALSE;
            }

            status = DiskDetermineMediaTypes(DeviceObject,
                                             Irp,
                                             modeData->MediumType,
                                             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;
            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;
        }

        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)) {
                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);
        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;
            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;
            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;
                    }
                }
                else
                {
                    status = STATUS_INSUFFICIENT_RESOURCES;
                }

                ExFreePool(readBuffer);
            }
            else
            {
                status = STATUS_INSUFFICIENT_RESOURCES;
            }

            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;
                } else {
                    checkFailure->PredictFailure = 0;
                }

                Irp->IoStatus.Information = sizeof(STORAGE_PREDICT_FAILURE);
            }
        } else {
            status = STATUS_INVALID_DEVICE_REQUEST;
        }

        break;
    }

    case IOCTL_DISK_VERIFY: {

        PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
        LARGE_INTEGER byteOffset;

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

        //
        // Validate buffer length.
        //

        if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(VERIFY_INFORMATION)) {

            status = STATUS_INFO_LENGTH_MISMATCH;
            break;
        }

        //
        // Add disk offset to starting sector.
        //

        byteOffset.QuadPart = commonExtension->StartingOffset.QuadPart +
                              verifyInfo->StartingOffset.QuadPart;

        if(!commonExtension->IsFdo) {

            //
            // Adjust the request and forward it down
            //

            verifyInfo->StartingOffset.QuadPart = byteOffset.QuadPart;

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

        //
        // Perform a bounds check on the sector range
        //

        if ((verifyInfo->StartingOffset.QuadPart > commonExtension->PartitionLength.QuadPart) ||
            (verifyInfo->StartingOffset.QuadPart < 0))
        {
            status = STATUS_NONEXISTENT_SECTOR;
            break;
        }
        else
        {
            ULONGLONG bytesRemaining = commonExtension->PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart;

            if ((ULONGLONG)verifyInfo->Length > bytesRemaining)
            {
                status = STATUS_NONEXISTENT_SECTOR;
                break;
            }
        }

        {
            PDISK_VERIFY_WORKITEM_CONTEXT Context = NULL;

            Context = ExAllocatePoolWithTag(NonPagedPool,
                                            sizeof(DISK_VERIFY_WORKITEM_CONTEXT),
                                            DISK_TAG_WI_CONTEXT);

            if (Context)
            {
             

⌨️ 快捷键说明

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