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

📄 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 页
字号:

                    status = CdRomSetRpc0Settings(DeviceObject,
                                                  rpcKey->PreferredDriveRegionCode);

                    if (!NT_SUCCESS(status)) {
                        TraceLog((CdromDebugWarning,
                                    "DvdDeviceControl (%p) => Could not "
                                    "set region code (%x)\n",
                                    DeviceObject, status
                                    ));
                    } else {

                        TraceLog((CdromDebugTrace,
                                    "DvdDeviceControl (%p) => New region set "
                                    " for RPC1 drive\n", DeviceObject));

                        //
                        // if it worked, our extension is already updated.
                        // release the mutex
                        //

                        DebugPrint ((4, "DvdDeviceControl (%p) => DVD current "
                                     "region bitmap  0x%x\n", DeviceObject,
                                     cdData->Rpc0SystemRegion));
                        DebugPrint ((4, "DvdDeviceControl (%p) => DVD region "
                                     " reset Count     0x%x\n", DeviceObject,
                                     cdData->Rpc0SystemRegionResetCount));
                    }

                }

                KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE);
                break;
            } // end of key->KeyType == DvdSetRpcKey
        } // end of Rpc0Device hacks

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

    case IOCTL_DVD_READ_KEY: {

        PDVD_COPY_PROTECT_KEY keyParameters = Irp->AssociatedIrp.SystemBuffer;
        ULONG keyLength;

        TraceLog((CdromDebugTrace,
                    "DvdDeviceControl: [%p] IOCTL_DVD_READ_KEY\n", Irp));

        if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) {
            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: License Failure\n"));
            status = STATUS_COPY_PROTECTION_FAILURE;
            break;
        }

        if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) {
            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: PickRegion() from READ_KEY\n"));
            CdRomPickDvdRegion(DeviceObject);
        }


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

            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: EstablishDriveKey - challenge "
                        "key buffer too small\n"));

            status = STATUS_INVALID_PARAMETER;
            break;

        }

        switch(keyParameters->KeyType) {

            case DvdChallengeKey: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_CHALLENGE_KEY_LENGTH);
                keyLength = DVD_CHALLENGE_KEY_LENGTH;
                break;
            }
            case DvdBusKey1:
            case DvdBusKey2: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_BUS_KEY_LENGTH);
                keyLength = DVD_BUS_KEY_LENGTH;
                break;
            }
            case DvdTitleKey: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_TITLE_KEY_LENGTH);
                keyLength = DVD_TITLE_KEY_LENGTH;
                break;
            }
            case DvdAsf: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_ASF_LENGTH);
                keyLength = DVD_ASF_LENGTH;
                break;
            }
            case DvdDiskKey: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_DISK_KEY_LENGTH);
                keyLength = DVD_DISK_KEY_LENGTH;
                break;
            }
            case DvdGetRpcKey: {
                C_ASSERT(sizeof(DVD_COPY_PROTECT_KEY) <= DVD_RPC_KEY_LENGTH);
                keyLength = DVD_RPC_KEY_LENGTH;
                break;
            }
            default: {
                keyLength = sizeof(DVD_COPY_PROTECT_KEY);
                break;
            }
        }

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

            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: EstablishDriveKey - output "
                        "buffer too small\n"));
            status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information = keyLength;
            break;
        }
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength &
            fdoExtension->AdapterDescriptor->AlignmentMask) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }

        if (keyParameters->KeyType == DvdGetRpcKey) {

            CdRomPickDvdRegion(DeviceObject);
        }

        if ((keyParameters->KeyType == DvdGetRpcKey) &&
            (cdData->DvdRpc0Device)) {

            PDVD_RPC_KEY rpcKey;
            rpcKey = (PDVD_RPC_KEY)keyParameters->KeyData;
            RtlZeroMemory (rpcKey, sizeof (*rpcKey));

            KeWaitForMutexObject(
                &cdData->Rpc0RegionMutex,
                UserRequest,
                KernelMode,
                FALSE,
                NULL
                );

            //
            // make up the data
            //
            rpcKey->UserResetsAvailable = cdData->Rpc0SystemRegionResetCount;
            rpcKey->ManufacturerResetsAvailable = 0;
            if (cdData->Rpc0SystemRegion == 0xff) {
                rpcKey->TypeCode = 0;
            } else {
                rpcKey->TypeCode = 1;
            }
            rpcKey->RegionMask = (UCHAR) cdData->Rpc0SystemRegion;
            rpcKey->RpcScheme = 1;

            KeReleaseMutex(
                &cdData->Rpc0RegionMutex,
                FALSE
                );

            Irp->IoStatus.Information = DVD_RPC_KEY_LENGTH;
            status = STATUS_SUCCESS;
            break;

        } else if (keyParameters->KeyType == DvdDiskKey) {

            PDVD_COPY_PROTECT_KEY keyHeader;
            PDVD_READ_STRUCTURE readStructureRequest;

            //
            // Special case - build a request to get the dvd structure
            // so we can get the disk key.
            //

            //
            // save the key header so we can restore the interesting
            // parts later
            //

            keyHeader = ExAllocatePoolWithTag(NonPagedPool,
                                              sizeof(DVD_COPY_PROTECT_KEY),
                                              DVD_TAG_READ_KEY);

            if(keyHeader == NULL) {

                //
                // Can't save the context so return an error
                //

                TraceLog((CdromDebugWarning,
                            "DvdDeviceControl - READ_KEY: unable to "
                            "allocate context\n"));
                status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            RtlCopyMemory(keyHeader,
                          Irp->AssociatedIrp.SystemBuffer,
                          sizeof(DVD_COPY_PROTECT_KEY));

            IoCopyCurrentIrpStackLocationToNext(Irp);

            nextStack = IoGetNextIrpStackLocation(Irp);

            nextStack->Parameters.DeviceIoControl.IoControlCode =
                IOCTL_DVD_READ_STRUCTURE;

            readStructureRequest = Irp->AssociatedIrp.SystemBuffer;
            readStructureRequest->Format = DvdDiskKeyDescriptor;
            readStructureRequest->BlockByteOffset.QuadPart = 0;
            readStructureRequest->LayerNumber = 0;
            readStructureRequest->SessionId = keyHeader->SessionId;

            nextStack->Parameters.DeviceIoControl.InputBufferLength =
                sizeof(DVD_READ_STRUCTURE);

            nextStack->Parameters.DeviceIoControl.OutputBufferLength =
                sizeof(READ_DVD_STRUCTURES_HEADER) + sizeof(DVD_DISK_KEY_DESCRIPTOR);

            IoSetCompletionRoutine(Irp,
                                   CdRomDvdReadDiskKeyCompletion,
                                   (PVOID) keyHeader,
                                   TRUE,
                                   TRUE,
                                   TRUE);

            {
                UCHAR uniqueAddress;
                ClassAcquireRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
                ClassReleaseRemoveLock(DeviceObject, Irp);

                IoMarkIrpPending(Irp);
                IoCallDriver(commonExtension->DeviceObject, Irp);
                status = STATUS_PENDING;

                ClassReleaseRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
            }

            return STATUS_PENDING;

        } else {

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

        }
        return STATUS_PENDING;
    }

    case IOCTL_DVD_END_SESSION: {

        PDVD_SESSION_ID sessionId = Irp->AssociatedIrp.SystemBuffer;

        TraceLog((CdromDebugTrace,
                    "DvdDeviceControl: [%p] END_SESSION\n", Irp));

        if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) {
            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: License Failure\n"));
            status = STATUS_COPY_PROTECTION_FAILURE;
            break;
        }

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

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

        IoMarkIrpPending(Irp);

        if(*sessionId == DVD_END_ALL_SESSIONS) {

            status = CdRomDvdEndAllSessionsCompletion(DeviceObject, Irp, NULL);

            if(status == STATUS_SUCCESS) {

                //
                // Just complete the request - it was never issued to the
                // lower device
                //

                break;

            } else {

                return STATUS_PENDING;

            }
        }

        IoStartPacket(DeviceObject, Irp, NULL, NULL);

        return STATUS_PENDING;
    }

    case IOCTL_DVD_GET_REGION: {

        PDVD_COPY_PROTECT_KEY copyProtectKey;
        ULONG keyLength;
        IO_STATUS_BLOCK ioStatus = {0};
        PDVD_DESCRIPTOR_HEADER dvdHeader;
        PDVD_COPYRIGHT_DESCRIPTOR copyRightDescriptor;
        PDVD_REGION dvdRegion;
        PDVD_READ_STRUCTURE readStructure;
        PDVD_RPC_KEY rpcKey;

        TraceLog((CdromDebugTrace,
                    "DvdDeviceControl: [%p] IOCTL_DVD_GET_REGION\n", Irp));

        if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) {
            TraceLog((CdromDebugWarning,
                        "DvdDeviceControl: License Failure\n"));
            status = STATUS_COPY_PROTECTION_FAILURE;
            break;
        }

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

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

        //
        // figure out how much data buffer we need
        //

        keyLength = max(sizeof(DVD_DESCRIPTOR_HEADER) +
                            sizeof(DVD_COPYRIGHT_DESCRIPTOR),
                        sizeof(DVD_READ_STRUCTURE)
                        );
        keyLength = max(keyLength,
                        DVD_RPC_KEY_LENGTH
                        );

        //
        // round the size to nearest ULONGLONG -- why?
        // could this be to deal with device alignment issues?
        //

        keyLength += sizeof(ULONGLONG) - (keyLength & (sizeof(ULONGLONG) - 1));

        readStructure = ExAllocatePoolWithTag(NonPagedPool,
                                              keyLength,
                                              DVD_TAG_READ_KEY);
        if (readStructure == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        RtlZeroMemory (readStructure, keyLength);
        readStructure->Format = DvdCopyrightDescriptor;

        //
        // Build a request for READ_STRUCTURE
        //

        ClassSendDeviceIoControlSynchronous(
            IOCTL_DVD_READ_STRUCTURE,
            DeviceObject,
            readStructure,
            keyLength,
            sizeof(DVD_DESCRIPTOR_HEADER) +
                sizeof(DVD_COPYRIGHT_DESCRIPTOR),
            FALSE,
            &ioStatus);

        status = ioStatus.Status;

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

        //
        // we got the copyright descriptor, so now get the region if possible
        //

        dvdHeader = (PDVD_DESCRIPTOR_HEADER) readStructure;
        copyRightDescriptor = (PDVD_COPYRIGHT_DESCRIPTOR) dvdHeader->Data;

⌨️ 快捷键说明

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