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

📄 ioctl.c

📁 The CD ROM driver is used with Classpnp.sys to provide access to CD ROMs and DVD ROMs. It supports P
💻 C
📖 第 1 页 / 共 5 页
字号:

        //
        // the original irp's systembuffer has a copy of the info that
        // should be passed down in the request
        //

        dvdRegion = Irp->AssociatedIrp.SystemBuffer;

        dvdRegion->CopySystem = copyRightDescriptor->CopyrightProtectionType;
        dvdRegion->RegionData = copyRightDescriptor->RegionManagementInformation;

        //
        // now reuse the buffer to request the copy protection info
        //

        copyProtectKey = (PDVD_COPY_PROTECT_KEY) readStructure;
        RtlZeroMemory (copyProtectKey, DVD_RPC_KEY_LENGTH);
        copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH;
        copyProtectKey->KeyType = DvdGetRpcKey;

        //
        // send a request for READ_KEY
        //

        ClassSendDeviceIoControlSynchronous(
            IOCTL_DVD_READ_KEY,
            DeviceObject,
            copyProtectKey,
            DVD_RPC_KEY_LENGTH,
            DVD_RPC_KEY_LENGTH,
            FALSE,
            &ioStatus);
        status = ioStatus.Status;

        if (!NT_SUCCESS(status)) {
            TraceLog((CdromDebugWarning,
                        "CdRomDvdGetRegion => read key failed %x\n",
                        status));
            ExFreePool(readStructure);
            break;
        }

        //
        // the request succeeded.  if a supported scheme is returned,
        // then return the information to the caller
        //

        rpcKey = (PDVD_RPC_KEY) copyProtectKey->KeyData;

        if (rpcKey->RpcScheme == 1) {

            if (rpcKey->TypeCode) {

                dvdRegion->SystemRegion = ~rpcKey->RegionMask;
                dvdRegion->ResetCount = rpcKey->UserResetsAvailable;

            } else {

                //
                // the drive has not been set for any region
                //

                dvdRegion->SystemRegion = 0;
                dvdRegion->ResetCount = rpcKey->UserResetsAvailable;
            }
            Irp->IoStatus.Information = sizeof(DVD_REGION);

        } else {

            TraceLog((CdromDebugWarning,
                        "CdRomDvdGetRegion => rpcKey->RpcScheme != 1\n"));
            status = STATUS_INVALID_DEVICE_REQUEST;
        }

        ExFreePool(readStructure);
        break;
    }


    case IOCTL_STORAGE_SET_READ_AHEAD: {

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

            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: SetReadAhead buffer too small\n"));
            status = STATUS_INVALID_PARAMETER;
            break;
        }

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);

        return STATUS_PENDING;
    }

    case IOCTL_DISK_IS_WRITABLE: {

        // all verification done in StartIo()
        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);

        return STATUS_PENDING;

    }

    case IOCTL_DISK_GET_DRIVE_LAYOUT: {

        ULONG size;

        //
        // we always fake zero or one partitions, and one partition
        // structure is included in DRIVE_LAYOUT_INFORMATION
        //

        size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);

        TraceLog((CdromDebugTrace,
                    "CdRomDeviceControl: Get drive layout\n"));
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < size) {
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = size;
            break;
        }

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;


    }
    case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: {

        ULONG size;

        //
        // we always fake zero or one partitions, and one partition
        // structure is included in DRIVE_LAYOUT_INFORMATION_EX
        //

        size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);

        TraceLog((CdromDebugTrace,
                    "CdRomDeviceControl: Get drive layout ex\n"));
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < size) {
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = size;
            break;
        }

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;

    }


    case IOCTL_DISK_GET_PARTITION_INFO: {

        //
        // Check that the buffer is large enough.
        //

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

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

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;

    }
    case IOCTL_DISK_GET_PARTITION_INFO_EX: {

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

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

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;
    }

    case IOCTL_DISK_VERIFY: {

        TraceLog((CdromDebugTrace,
                    "IOCTL_DISK_VERIFY to device %p through irp %p\n",
                    DeviceObject, Irp));

        //
        // Validate buffer length.
        //

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

            status = STATUS_INFO_LENGTH_MISMATCH;
            break;
        }
        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;
    }

    case IOCTL_DISK_GET_LENGTH_INFO: {

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(GET_LENGTH_INFORMATION)) {
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
            break;
        }
        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;
    }

    case IOCTL_CDROM_GET_CONFIGURATION: {

        TraceLog((CdromDebugTrace,
                    "IOCTL_CDROM_GET_CONFIGURATION to via irp %p\n", Irp));

        //
        // Validate buffer length.
        //

        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
            sizeof(GET_CONFIGURATION_HEADER)) {
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = sizeof(GET_CONFIGURATION_HEADER);
            break;
        }
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength > 0xffff) {
            // output buffer is too large
            status = STATUS_INVALID_BUFFER_SIZE;
            break;
        }
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength &
            fdoExtension->AdapterDescriptor->AlignmentMask) {
            // buffer is not proper size multiple
            status = STATUS_INVALID_PARAMETER;
            break;
        }

#if defined (_WIN64)
        if (IoIs32bitProcess(Irp)) {

            PGET_CONFIGURATION_IOCTL_INPUT32 inputBuffer;

            if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(GET_CONFIGURATION_IOCTL_INPUT32)) {
                status = STATUS_INFO_LENGTH_MISMATCH;
                break;
            }
            //
            // also verify the arguments are reasonable.
            //

            inputBuffer = Irp->AssociatedIrp.SystemBuffer;
            if (inputBuffer->Feature > 0xffff) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
            if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) &&
                (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) &&
                (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL)) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
            if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1]) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
        }
        else
#endif
        {
            PGET_CONFIGURATION_IOCTL_INPUT inputBuffer;

            if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(GET_CONFIGURATION_IOCTL_INPUT)) {
                status = STATUS_INFO_LENGTH_MISMATCH;
                break;
            }
            //
            // also verify the arguments are reasonable.
            //

            inputBuffer = Irp->AssociatedIrp.SystemBuffer;
            if (inputBuffer->Feature > 0xffff) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
            if ((inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE) &&
                (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT) &&
                (inputBuffer->RequestType != SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL)) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
            if (inputBuffer->Reserved[0] || inputBuffer->Reserved[1]) {
                status = STATUS_INVALID_PARAMETER;
                break;
            }
        }

        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, NULL);
        return STATUS_PENDING;

    }

    default: {

        BOOLEAN synchronize = (KeGetCurrentIrql() == PASSIVE_LEVEL);
        PKEVENT deviceControlEvent;

        //
        // If the ioctl has come in at passive level then we will synchronize
        // with our start-io routine when sending the ioctl.  If the ioctl
        // has come in at a higher interrupt level and it was not handled
        // above then it's unlikely to be a request for the class DLL - however
        // we'll still use it's common code to forward the request through.
        //

        if (synchronize) {

            deviceControlEvent = ExAllocatePoolWithTag(NonPagedPool,
                                                       sizeof(KEVENT),
                                                       CDROM_TAG_DC_EVENT);

            if (deviceControlEvent == NULL) {

                //
                // must complete this irp unsuccessful here
                //
                status = STATUS_INSUFFICIENT_RESOURCES;
                break;

            } else {

                PIO_STACK_LOCATION currentStack;

                UCHAR uniqueAddress;

                KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE);

                currentStack = IoGetCurrentIrpStackLocation(Irp);
                nextStack = IoGetNextIrpStackLocation(Irp);

                //
                // Copy the stack down a notch
                //

                IoCopyCurrentIrpStackLocationToNext(Irp);

                IoSetCompletionRoutine(
                    Irp,
                    CdRomClassIoctlCompletion,
                    deviceControlEvent,
                    TRUE,
                    TRUE,
                    TRUE
                    );

                IoSetNextIrpStackLocation(Irp);

                Irp->IoStatus.Status = STATUS_SUCCESS;
                Irp->IoStatus.Information = 0;

                //
                // Override volume verifies on this stack location so that we
                // will be forced through the synchronization.  Once this
                // location goes away we get the old value back
                //

                SET_FLAG(nextStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);

                //
                // because this will release the remove lock (even though it
                // reacquires it in the completion routine) it is neccessary
                // to acquire another remove lock here.
                //

                ClassAcquireRemoveLock(DeviceObject, (PIRP) &uniqueAddress);

                //
                // send the request into CDROM's StartIo (which will
                // c

⌨️ 快捷键说明

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