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