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

📄 disk.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
                    controlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
                    break;

                case SAVE_ATTRIBUTE_VALUES:
                    controlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
                    break;

                case EXECUTE_OFFLINE_DIAGS:
                    controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;

                default:
                    status = STATUS_INVALID_PARAMETER;
                    break;
            }
        } else {

            status = STATUS_INVALID_PARAMETER;
        }

        if (controlCode == 0) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }

        length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? sizeof(SENDCMDOUTPARAMS) : sizeof(SENDCMDINPARAMS);;
        srbControl = ExAllocatePool(NonPagedPool,
                                    sizeof(SRB_IO_CONTROL) + length);

        if (!srbControl) {
            status =  STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        //
        // fill in srbControl fields
        //

        srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
        RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
        srbControl->Timeout = deviceExtension->TimeOutValue;
        srbControl->Length = length;

        //
        // Point to the 'buffer' portion of the SRB_CONTROL
        //

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

        //
        // Ensure correct target is set in the cmd parameters.
        //

        cmdInParameters->bDriveNumber = deviceExtension->TargetId;

        //
        // Copy the IOCTL parameters to the srb control buffer area.
        //

        RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);

        srbControl->ControlCode = controlCode;

        irp2 = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
                                            deviceExtension->PortDeviceObject,
                                            srbControl,
                                            sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
                                            srbControl,
                                            sizeof(SRB_IO_CONTROL) + length,
                                            FALSE,
                                            &event,
                                            &ioStatus);

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

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

        status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);

        if (status == STATUS_PENDING) {
            KeWaitForSingleObject(&event, Suspended, 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 = (ULONG_PTR)srbControl + 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, (PVOID)buffer, length);
        Irp->IoStatus.Information = length;

        ExFreePool(srbControl);
        break;

    }

    case IOCTL_DISK_GET_DRIVE_GEOMETRY:

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

            status = STATUS_INFO_LENGTH_MISMATCH;
            break;
        }

        if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {

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

            status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);

            if (!NT_SUCCESS(status)) {

                //
                // Note the drive is not ready.
                //

                diskData->DriveNotReady = TRUE;

                break;
            }

            //
            // Note the drive is now ready.
            //

            diskData->DriveNotReady = FALSE;
        }

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

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

        status = STATUS_SUCCESS;
        Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);

        break;

    case IOCTL_DISK_VERIFY:

        {

        PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
        LARGE_INTEGER byteOffset;
        ULONG         sectorOffset;
        USHORT        sectorCount;

        //
        // Validate buffer length.
        //

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

            status = STATUS_INFO_LENGTH_MISMATCH;
            break;
        }

        //
        // Verify sectors
        //

        srb->CdbLength = 10;

        cdb->CDB10.OperationCode = SCSIOP_VERIFY;

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

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

        //
        // Convert byte offset to sector offset.
        //

        sectorOffset = (ULONG)(byteOffset.QuadPart >> deviceExtension->SectorShift);

        //
        // Convert ULONG byte count to USHORT sector count.
        //

        sectorCount = (USHORT)(verifyInfo->Length >> deviceExtension->SectorShift);

        //
        // Move little endian values into CDB in big endian format.
        //

        cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&sectorOffset)->Byte3;
        cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
        cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
        cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;

        cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
        cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->Byte0;

        //
        // The verify command is used by the NT FORMAT utility and
        // requests are sent down for 5% of the volume size. The
        // request timeout value is calculated based on the number of
        // sectors verified.
        //

        srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) *
                                              deviceExtension->TimeOutValue;

        status = ScsiClassSendSrbAsynchronous(DeviceObject,
                                              srb,
                                              Irp,
                                              NULL,
                                              0,
                                              FALSE);

        return(status);

        }

    case IOCTL_DISK_GET_PARTITION_INFO:

        //
        // Return the information about the partition specified by the device
        // object.  Note that no information is ever returned about the size
        // or partition type of the physical disk, as this doesn't make any
        // sense.
        //

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

            status = STATUS_INFO_LENGTH_MISMATCH;

        }
#if 0 // HACK: ReactOS partition numbers must be wrong
        else if (diskData->PartitionNumber == 0) {

            //
            // Paritition zero is not a partition so this is not a
            // reasonable request.
            //

            status = STATUS_INVALID_DEVICE_REQUEST;

        }
#endif
        else {

            PPARTITION_INFORMATION outputBuffer;

            //
            // Update the geometry in case it has changed.
            //

            status = UpdateRemovableGeometry (DeviceObject, Irp);

            if (!NT_SUCCESS(status)) {

                //
                // Note the drive is not ready.
                //

                diskData->DriveNotReady = TRUE;
                break;
            }

            //
            // Note the drive is now ready.
            //

            diskData->DriveNotReady = FALSE;
// HACK: ReactOS partition numbers must be wrong (>0 part)
            if (diskData->PartitionType == 0 && (diskData->PartitionNumber > 0)) {

                status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }

            outputBuffer =
                    (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

            outputBuffer->PartitionType = diskData->PartitionType;
            outputBuffer->StartingOffset = deviceExtension->StartingOffset;
            outputBuffer->PartitionLength.QuadPart = (diskData->PartitionNumber) ?
                deviceExtension->PartitionLength.QuadPart : 2305843009213693951LL; // HACK
            outputBuffer->HiddenSectors = diskData->HiddenSectors;
            outputBuffer->PartitionNumber = diskData->PartitionNumber;
            outputBuffer->BootIndicator = diskData->BootIndicator;
            outputBuffer->RewritePartition = FALSE;
            outputBuffer->RecognizedPartition =
                IsRecognizedPartition(diskData->PartitionType);

            status = STATUS_SUCCESS;
            Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
        }

        break;

    case IOCTL_DISK_SET_PARTITION_INFO:

        if (diskData->PartitionNumber == 0) {

            status = STATUS_UNSUCCESSFUL;

        } else {

            PSET_PARTITION_INFORMATION inputBuffer =
                (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

            //
            // Validate buffer length.
            //

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

                status = STATUS_INFO_LENGTH_MISMATCH;
                break;
            }

            //
            // The HAL routines IoGet- and IoSetPartitionInformation were
            // developed before support of dynamic partitioning and therefore
            // don't distinguish between partition ordinal (that is the order
            // of a partition on a disk) and the partition number. (The
            // partition number is assigned to a partition to identify it to
            // the system.) Use partition ordinals for these legacy calls.
            //

            status = IoSetPartitionInformation(
                          deviceExtension->PhysicalDevice,
                          deviceExtension->DiskGeometry->BytesPerSector,
                          diskData->PartitionOrdinal,
                          inputBuffer->PartitionType);

            if (NT_SUCCESS(status)) {

                diskData->PartitionType = inputBuffer->PartitionType;
            }
        }

        break;

    case IOCTL_DISK_GET_DRIVE_LAYOUT:

        //
        // Return the partition layout for the physical drive.  Note that
        // the layout is returned for the actual physical drive, regardless
        // of which partition was specified for the request.
        //

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(DRIVE_LAYOUT_INFORMATION)) {
            status = STATUS_INFO_LENGTH_MISMATCH;

        } else {

            PDRIVE_LAYOUT_INFORMATION partitionList;
            PDEVICE_EXTENSION         physicalExtension = deviceExtension;
            PPARTITION_INFORMATION    partitionEntry;
            PDISK_DATA                diskData;
            ULONG                     tempSize;
            ULONG                     i;

            //
            // Read partition information.
            //

            status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
                              deviceExtension->DiskGeometry->BytesPerSector,
                              FALSE,
                              &partitionList);

            if (!NT_SUCCESS(status)) {
                break;
            }

            //
            // The disk layout has been returned in the partitionList
            // buffer.  Determine its size and, if the data will fit
            // into the intermediatery buffer, return it.
            //

            tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,PartitionEntry[0]);
            tempSize += partitionList->PartitionCount *
                        sizeof(PARTITION_INFORMATION);

            if (tempSize >
               irpStack->Parameters.DeviceIoControl.OutputBufferLength) {

                status = STATUS_BUFFER_TOO_SMALL;
                ExFreePool(partitionList);
                break;
            }

            //
            // Walk partition list to associate partition numbers with
            // partition entries.
            //

            for (i = 0; i < partitionList->PartitionCount; i++) {

                //
                // Walk partition chain anchored at physical disk extension.
                //

                deviceExtension = physicalExtension;
                diskData = (PDISK_DATA)(deviceExtension + 1);

                do {

                    deviceExtension = diskData->NextPartition;

                    //
                    // Check if this is the last partition in the chain.
                    //

                    if (!deviceExtension) {
                       break;
                    }

                    //
                    // Get the partition device extension from disk data.
                    //

                    diskData = (PDISK_DATA)(deviceExtension + 1);

                    //
                    /

⌨️ 快捷键说明

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