📄 ioctl.c
字号:
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 + -