📄 ioctl.c
字号:
#if DBG
// debug print statements moved here (following release of spin lock)
// because NT conversion tables used to convert UNICODE to
// ANSI for debug printing are paged and thus DbgPrint's bugcheck at
// IRQL > APC level
if(Status == STATUS_SUCCESS) {
PptDump2(PARDUMP_PORT_ALLOC_FREE,
("%wZ %S ALLOCATE\n", &Extension->DeviceName, Extension->PnpInfo.PortName) );
} else if(Status == STATUS_PENDING) {
PptDump2(PARDUMP_PORT_ALLOC_FREE,
("%wZ %S Allocate request queued\n", &Extension->DeviceName, Extension->PnpInfo.PortName) );
}
#endif
break;
case IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO\n") );
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARALLEL_PORT_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Irp->IoStatus.Information = sizeof(PARALLEL_PORT_INFORMATION);
PortInfo = Irp->AssociatedIrp.SystemBuffer;
*PortInfo = Extension->PortInfo;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_INTERNAL_RELEASE_PARALLEL_PORT_INFO:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_RELEASE_PARALLEL_PORT_INFO\n") );
Status = STATUS_SUCCESS;
break;
case IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_GET_PARALLEL_PNP_INFO\n") );
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARALLEL_PNP_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Irp->IoStatus.Information = sizeof(PARALLEL_PNP_INFORMATION);
PnpInfo = Irp->AssociatedIrp.SystemBuffer;
*PnpInfo = Extension->PnpInfo;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_INTERNAL_GET_MORE_PARALLEL_PORT_INFO:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_GET_MORE_PARALLEL_PORT_INFO\n") );
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(MORE_PARALLEL_PORT_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Irp->IoStatus.Information = sizeof(MORE_PARALLEL_PORT_INFORMATION);
MorePortInfo = Irp->AssociatedIrp.SystemBuffer;
MorePortInfo->InterfaceType = Extension->InterfaceType;
MorePortInfo->BusNumber = Extension->BusNumber;
MorePortInfo->InterruptLevel = Extension->InterruptLevel;
MorePortInfo->InterruptVector = Extension->InterruptVector;
MorePortInfo->InterruptAffinity = Extension->InterruptAffinity;
MorePortInfo->InterruptMode = Extension->InterruptMode;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT\n") );
{
//
// Verify that this interface has been explicitly enabled via the registry flag, otherwise
// FAIL the request with STATUS_UNSUCCESSFUL
//
ULONG EnableConnectInterruptIoctl = 0;
PptRegGetDeviceParameterDword( Extension->PhysicalDeviceObject,
(PWSTR)L"EnableConnectInterruptIoctl",
&EnableConnectInterruptIoctl );
PptDump2(PARIOCTL, ("ioctl::PptDispatchDeviceControl: IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT"
" - EnableConnectInterruptIoctl = %x\n", EnableConnectInterruptIoctl) );
if( 0 == EnableConnectInterruptIoctl ) {
PptDump2(PARIOCTL, ("ioctl::PptDispatchDeviceControl: IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT - DISABLED\n") );
Status = STATUS_UNSUCCESSFUL;
goto targetExit;
} else {
PptDump2(PARIOCTL, ("ioctl::PptDispatchDeviceControl: IOCTL_INTERNAL_PARALLEL_CONNECT_INTERRUPT - ENABLED\n") );
}
}
//
// This interface has been explicitly enabled via the registry flag, process request.
//
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_INTERRUPT_SERVICE_ROUTINE) ||
IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PARALLEL_INTERRUPT_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
IsrInfo = Irp->AssociatedIrp.SystemBuffer;
InterruptInfo = Irp->AssociatedIrp.SystemBuffer;
IoAcquireCancelSpinLock(&CancelIrql);
if (Extension->InterruptRefCount) {
++Extension->InterruptRefCount;
IoReleaseCancelSpinLock(CancelIrql);
Status = STATUS_SUCCESS;
} else {
IoReleaseCancelSpinLock(CancelIrql);
Status = PptConnectInterrupt(Extension);
if (NT_SUCCESS(Status)) {
IoAcquireCancelSpinLock(&CancelIrql);
++Extension->InterruptRefCount;
IoReleaseCancelSpinLock(CancelIrql);
}
}
if (NT_SUCCESS(Status)) {
IsrListEntry = ExAllocatePool(NonPagedPool,
sizeof(ISR_LIST_ENTRY));
if (IsrListEntry) {
IsrListEntry->ServiceRoutine =
IsrInfo->InterruptServiceRoutine;
IsrListEntry->ServiceContext =
IsrInfo->InterruptServiceContext;
IsrListEntry->DeferredPortCheckRoutine =
IsrInfo->DeferredPortCheckRoutine;
IsrListEntry->CheckContext =
IsrInfo->DeferredPortCheckContext;
// Put the ISR_LIST_ENTRY onto the ISR list.
ListContext.List = &Extension->IsrList;
ListContext.NewEntry = &IsrListEntry->ListEntry;
KeSynchronizeExecution(Extension->InterruptObject,
PptSynchronizedQueue,
&ListContext);
InterruptInfo->InterruptObject =
Extension->InterruptObject;
InterruptInfo->TryAllocatePortAtInterruptLevel =
PptTryAllocatePortAtInterruptLevel;
InterruptInfo->FreePortFromInterruptLevel =
PptFreePortFromInterruptLevel;
InterruptInfo->Context =
Extension;
Irp->IoStatus.Information =
sizeof(PARALLEL_INTERRUPT_INFORMATION);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
break;
case IOCTL_INTERNAL_PARALLEL_DISCONNECT_INTERRUPT:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_PARALLEL_DISCONNECT_INTERRUPT\n") );
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_INTERRUPT_SERVICE_ROUTINE)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
IsrInfo = Irp->AssociatedIrp.SystemBuffer;
// Take the ISR out of the ISR list.
IoAcquireCancelSpinLock(&CancelIrql);
if (Extension->InterruptRefCount) {
IoReleaseCancelSpinLock(CancelIrql);
DisconnectContext.Extension = Extension;
DisconnectContext.IsrInfo = IsrInfo;
if (KeSynchronizeExecution(Extension->InterruptObject,
PptSynchronizedDisconnect,
&DisconnectContext)) {
Status = STATUS_SUCCESS;
IoAcquireCancelSpinLock(&CancelIrql);
if (--Extension->InterruptRefCount == 0) {
DisconnectInterrupt = TRUE;
} else {
DisconnectInterrupt = FALSE;
}
IoReleaseCancelSpinLock(CancelIrql);
} else {
Status = STATUS_INVALID_PARAMETER;
DisconnectInterrupt = FALSE;
}
} else {
IoReleaseCancelSpinLock(CancelIrql);
DisconnectInterrupt = FALSE;
Status = STATUS_INVALID_PARAMETER;
}
//
// Disconnect the interrupt if appropriate.
//
if (DisconnectInterrupt) {
PptDisconnectInterrupt(Extension);
}
}
break;
///////////////////////////////////////////////////////////////////////////////////
case IOCTL_INTERNAL_PARALLEL_SET_CHIP_MODE:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_PARALLEL_SET_CHIP_MODE\n") );
//
// Port already acquired?
//
// Make sure right parameters are sent in
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_CHIP_MODE) ) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PptDumpV( ("Calling function to set the chip mode by either the filter or us\n") );
Status = PptSetChipMode (Extension,
((PPARALLEL_CHIP_MODE)Irp->AssociatedIrp.SystemBuffer)->ModeFlags );
} // end check input buffer
break;
case IOCTL_INTERNAL_PARALLEL_CLEAR_CHIP_MODE:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_PARALLEL_CLEAR_CHIP_MODE\n") );
//
// Port already acquired?
//
// Make sure right parameters are sent in
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_CHIP_MODE) ){
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PptDumpV( ("Calling function to clear the mode set by parport or the chip filter\n") );
Status = PptClearChipMode (Extension,
((PPARALLEL_CHIP_MODE)Irp->AssociatedIrp.SystemBuffer)->ModeFlags);
} // end check input buffer
break;
case IOCTL_INTERNAL_INIT_1284_3_BUS:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_INIT_1284_3_BUS\n") );
///////////////////////////////////////////////////////////////////////////////
// Test code
// Initialize the 1284.3 bus
// Port is locked out already?
Extension->PnpInfo.Ieee1284_3DeviceCount = PptInitiate1284_3( Extension );
Status = STATUS_SUCCESS;
break;
// Takes a flat namespace Id for the device, also acquires the port
case IOCTL_INTERNAL_SELECT_DEVICE:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_SELECT_DEVICE\n") );
// validate input buffer size
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_1284_COMMAND) ){
PptDumpV( ("Dot3 SELECT_DEVICE IRP %S - FAIL - buffer too small\n",
Extension->PnpInfo.PortName) );
Status = STATUS_BUFFER_TOO_SMALL;
} else {
// check to see if irp has been cancelled
if ( Irp->Cancel ) {
Status = STATUS_CANCELLED;
} else {
// Call Function to try to select device
Status = PptTrySelectDevice( Extension, Irp->AssociatedIrp.SystemBuffer );
IoAcquireCancelSpinLock(&CancelIrql);
if ( Status == STATUS_PENDING ) {
PptSetCancelRoutine(Irp, PptCancelRoutine);
IoMarkIrpPending(Irp);
InsertTailList(&Extension->WorkQueue,
&Irp->Tail.Overlay.ListEntry);
PptDump2( PARINFO, ("DOT3 SELECT_DEVICE IRP - Port BUSY - request queued\n") );
}
IoReleaseCancelSpinLock(CancelIrql);
}
} // endif - buffer too small
break;
// Deselects the current device, also releases the port
case IOCTL_INTERNAL_DESELECT_DEVICE:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): IOCTL_INTERNAL_DESELECT_DEVICE\n") );
// validate input buffer size
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PARALLEL_1284_COMMAND) ){
PptDumpV( ("DOT3 DESELECT_DEVICE %S - FAIL - buffer too small\n",
Extension->PnpInfo.PortName) );
Status = STATUS_BUFFER_TOO_SMALL;
} else {
// Call Function to deselect the Device
Status = PptDeselectDevice( Extension, Irp->AssociatedIrp.SystemBuffer );
} // endif - buffer too small
break;
/////////////////////////////////////////////////////////////////////////////////
default:
PptDump2(PARIOCTL, ("PptDispatchDeviceControl(): default case - STATUS_INVALID_PARAMETER\n") );
Status = STATUS_INVALID_PARAMETER;
break;
}
targetExit:
if (Status != STATUS_PENDING) {
Irp->IoStatus.Status = Status;
PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
PptCompleteRequest(Irp, IO_NO_INCREMENT);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -