📄 ioctl.c
字号:
}
case IOCTL_CDROM_STOP_AUDIO: {
//
// Stop play.
//
TraceLog((CdromDebugTrace,
"CdRomDeviceControl: Stop audio\n"));
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject, Irp, NULL, NULL);
return STATUS_PENDING;
}
case IOCTL_STORAGE_CHECK_VERIFY:
case IOCTL_DISK_CHECK_VERIFY:
case IOCTL_CDROM_CHECK_VERIFY: {
TraceLog((CdromDebugTrace,
"CdRomDeviceControl: [%p] Check Verify\n", Irp));
if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) &&
(irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) {
TraceLog((CdromDebugWarning,
"CdRomDeviceControl: Check Verify: media count "
"buffer too small\n"));
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(ULONG);
break;
}
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject, Irp, NULL, NULL);
return STATUS_PENDING;
}
case IOCTL_DVD_READ_STRUCTURE: {
TraceLog((CdromDebugTrace,
"DvdDeviceControl: [%p] IOCTL_DVD_READ_STRUCTURE\n", Irp));
if (cdData->DvdRpc0Device && cdData->DvdRpc0LicenseFailure) {
TraceLog((CdromDebugWarning,
"DvdDeviceControl: License Failure\n"));
status = STATUS_COPY_PROTECTION_FAILURE;
break;
}
if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) {
//
// if currently in-progress, this will just return.
// prevents looping by doing that interlockedExchange()
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl: PickRegion() from "
"READ_STRUCTURE\n"));
CdRomPickDvdRegion(DeviceObject);
}
if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(DVD_READ_STRUCTURE)) {
TraceLog((CdromDebugWarning,
"DvdDeviceControl - READ_STRUCTURE: input buffer "
"length too small (was %d should be %d)\n",
irpStack->Parameters.DeviceIoControl.InputBufferLength,
sizeof(DVD_READ_STRUCTURE)));
status = STATUS_INVALID_PARAMETER;
break;
}
if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(READ_DVD_STRUCTURES_HEADER)) {
TraceLog((CdromDebugWarning,
"DvdDeviceControl - READ_STRUCTURE: output buffer "
"cannot hold header information\n"));
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(READ_DVD_STRUCTURES_HEADER);
break;
}
if(irpStack->Parameters.DeviceIoControl.OutputBufferLength >
MAXUSHORT) {
//
// key length must fit in two bytes
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl - READ_STRUCTURE: output buffer "
"too large\n"));
status = STATUS_INVALID_PARAMETER;
break;
}
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength &
fdoExtension->AdapterDescriptor->AlignmentMask) {
status = STATUS_INVALID_PARAMETER;
break;
}
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject, Irp, NULL, NULL);
return STATUS_PENDING;
}
case IOCTL_DVD_START_SESSION: {
TraceLog((CdromDebugTrace,
"DvdDeviceControl: [%p] IOCTL_DVD_START_SESSION\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_SESSION_ID)) {
TraceLog((CdromDebugWarning,
"DvdDeviceControl: DVD_START_SESSION - output "
"buffer too small\n"));
status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(DVD_SESSION_ID);
break;
}
IoMarkIrpPending(Irp);
IoStartPacket(DeviceObject, Irp, NULL, NULL);
return STATUS_PENDING;
}
case IOCTL_DVD_SEND_KEY:
case IOCTL_DVD_SEND_KEY2: {
PDVD_COPY_PROTECT_KEY key = Irp->AssociatedIrp.SystemBuffer;
ULONG keyLength;
TraceLog((CdromDebugTrace,
"DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY\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_COPY_PROTECT_KEY)) ||
(irpStack->Parameters.DeviceIoControl.InputBufferLength !=
key->KeyLength)) {
//
// Key is too small to have a header or the key length doesn't
// match the input buffer length. Key must be invalid
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY - "
"key is too small or does not match KeyLength\n",
Irp));
status = STATUS_INVALID_PARAMETER;
break;
}
//
// allow only certain key type (non-destructive) to go through
// IOCTL_DVD_SEND_KEY (which only requires READ access to the device)
//
if (ioctlCode == IOCTL_DVD_SEND_KEY) {
if ((key->KeyType != DvdChallengeKey) &&
(key->KeyType != DvdBusKey2) &&
(key->KeyType != DvdInvalidateAGID)) {
status = STATUS_INVALID_PARAMETER;
break;
}
} else {
if ((key->KeyType != DvdChallengeKey) &&
(key->KeyType != DvdBusKey1) &&
(key->KeyType != DvdBusKey2) &&
(key->KeyType != DvdTitleKey) &&
(key->KeyType != DvdAsf) &&
(key->KeyType != DvdSetRpcKey) &&
(key->KeyType != DvdGetRpcKey) &&
(key->KeyType != DvdDiskKey) &&
(key->KeyType != DvdInvalidateAGID)) {
status = STATUS_INVALID_PARAMETER;
break;
}
}
if (cdData->DvdRpc0Device) {
if (key->KeyType == DvdSetRpcKey) {
PDVD_SET_RPC_KEY rpcKey = (PDVD_SET_RPC_KEY) key->KeyData;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
DVD_SET_RPC_KEY_LENGTH) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// we have a request to set region code
// on a RPC0 device which doesn't support
// region coding.
//
// we have to fake it.
//
KeWaitForMutexObject(
&cdData->Rpc0RegionMutex,
UserRequest,
KernelMode,
FALSE,
NULL
);
if (cdData->DvdRpc0Device && cdData->Rpc0RetryRegistryCallback) {
//
// if currently in-progress, this will just return.
// prevents looping by doing that interlockedExchange()
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl: PickRegion() from "
"SEND_KEY\n"));
CdRomPickDvdRegion(DeviceObject);
}
if (cdData->Rpc0SystemRegion == rpcKey->PreferredDriveRegionCode) {
//
// nothing to change
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl (%p) => not changing "
"regions -- requesting current region\n",
DeviceObject));
status = STATUS_SUCCESS;
} else if (cdData->Rpc0SystemRegionResetCount == 0) {
//
// not allowed to change it again
//
TraceLog((CdromDebugWarning,
"DvdDeviceControl (%p) => no more region "
"changes are allowed for this device\n",
DeviceObject));
status = STATUS_CSS_RESETS_EXHAUSTED;
} else {
ULONG i;
UCHAR mask;
ULONG bufferLen;
PDVD_READ_STRUCTURE dvdReadStructure;
PDVD_COPYRIGHT_DESCRIPTOR dvdCopyRight;
IO_STATUS_BLOCK ioStatus = {0};
UCHAR mediaRegionData;
mask = ~rpcKey->PreferredDriveRegionCode;
if (CountOfSetBitsUChar(mask) != 1) {
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
//
// this test will always be TRUE except during initial
// automatic selection of the first region.
//
if (cdData->Rpc0SystemRegion != 0xff) {
//
// make sure we have a media in the drive with the same
// region code if the drive is already has a region set
//
TraceLog((CdromDebugTrace,
"DvdDeviceControl (%p) => Checking "
"media region\n",
DeviceObject));
bufferLen = max(sizeof(DVD_DESCRIPTOR_HEADER) +
sizeof(DVD_COPYRIGHT_DESCRIPTOR),
sizeof(DVD_READ_STRUCTURE)
);
dvdReadStructure = (PDVD_READ_STRUCTURE)
ExAllocatePoolWithTag(PagedPool,
bufferLen,
DVD_TAG_RPC2_CHECK);
if (dvdReadStructure == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE);
break;
}
dvdCopyRight = (PDVD_COPYRIGHT_DESCRIPTOR)
((PDVD_DESCRIPTOR_HEADER) dvdReadStructure)->Data;
//
// check to see if we have a DVD device
//
RtlZeroMemory (dvdReadStructure, bufferLen);
dvdReadStructure->Format = DvdCopyrightDescriptor;
//
// Build a request for READ_KEY
//
ClassSendDeviceIoControlSynchronous(
IOCTL_DVD_READ_STRUCTURE,
DeviceObject,
dvdReadStructure,
sizeof(DVD_READ_STRUCTURE),
sizeof(DVD_DESCRIPTOR_HEADER) +
sizeof(DVD_COPYRIGHT_DESCRIPTOR),
FALSE,
&ioStatus);
//
// this is just to prevent bugs from creeping in
// if status is not set later in development
//
status = ioStatus.Status;
//
// handle errors
//
if (!NT_SUCCESS(status)) {
KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE);
ExFreePool(dvdReadStructure);
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
//
// save the mediaRegionData before freeing the
// allocated memory
//
mediaRegionData =
dvdCopyRight->RegionManagementInformation;
ExFreePool(dvdReadStructure);
TraceLog((CdromDebugWarning,
"DvdDeviceControl (%p) => new mask is %x"
" MediaRegionData is %x\n", DeviceObject,
rpcKey->PreferredDriveRegionCode,
mediaRegionData));
//
// the media region must match the requested region
// for RPC0 drives for initial region selection
//
if (((UCHAR)~(mediaRegionData | rpcKey->PreferredDriveRegionCode)) == 0) {
KeReleaseMutex(&cdData->Rpc0RegionMutex,FALSE);
status = STATUS_CSS_REGION_MISMATCH;
break;
}
}
//
// now try to set the region
//
TraceLog((CdromDebugTrace,
"DvdDeviceControl (%p) => Soft-Setting "
"region of RPC1 device to %x\n",
DeviceObject,
rpcKey->PreferredDriveRegionCode
));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -