📄 pdoioctl.c
字号:
}
break;
case IOCTL_IEEE1284_GET_MODE:
DD((PCE)Pdx,DDT,"IOCTL_IEEE1284_GET_MODE\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARCLASS_NEGOTIATION_MASK)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PPARCLASS_NEGOTIATION_MASK ppnmMask = (PPARCLASS_NEGOTIATION_MASK)Irp->AssociatedIrp.SystemBuffer;
ppnmMask->usReadMask = arpReverse[Pdx->IdxReverseProtocol].Protocol;
ppnmMask->usWriteMask = afpForward[Pdx->IdxForwardProtocol].Protocol;
Irp->IoStatus.Information = sizeof (PARCLASS_NEGOTIATION_MASK);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_GET_DEFAULT_MODES:
DD((PCE)Pdx,DDT,"IOCTL_IEEE1284_GET_MODE\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARCLASS_NEGOTIATION_MASK)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PPARCLASS_NEGOTIATION_MASK ppnmMask = (PPARCLASS_NEGOTIATION_MASK)Irp->AssociatedIrp.SystemBuffer;
ppnmMask->usReadMask = NONE;
ppnmMask->usWriteMask = CENTRONICS;
Irp->IoStatus.Information = sizeof (PARCLASS_NEGOTIATION_MASK);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_ECP_HOST_RECOVERY:
DD((PCE)Pdx,DDT,"IOCTL_PAR_ECP_HOST_RECOVERY\n");
{
BOOLEAN *isSupported;
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BOOLEAN) ) {
Status = STATUS_INVALID_PARAMETER;
} else {
isSupported = (BOOLEAN *)Irp->AssociatedIrp.SystemBuffer;
Pdx->bIsHostRecoverSupported = *isSupported;
Status = STATUS_SUCCESS;
}
}
break;
case IOCTL_PAR_PING:
DD((PCE)Pdx,DDT,"IOCTL_PAR_PING\n");
// No Parms to check!
Status = STATUS_PENDING;
break;
case IOCTL_PAR_GET_DEVICE_CAPS:
DD((PCE)Pdx,DDT,"IOCTL_PAR_GET_DEVICE_CAPS\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(Pdx->ProtocolModesSupported)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_IEEE1284_NEGOTIATE:
DD((PCE)Pdx,DDT,"IOCTL_IEEE1284_NEGOTIATE\n");
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARCLASS_NEGOTIATION_MASK) ||
IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARCLASS_NEGOTIATION_MASK) ) {
DD((PCE)Pdx,DDW,"ParDeviceControl: IOCTL_IEEE1284_NEGOTIATE STATUS_INVALID_PARAMETER\n");
Status = STATUS_INVALID_PARAMETER;
} else {
PPARCLASS_NEGOTIATION_MASK ppnmMask = (PPARCLASS_NEGOTIATION_MASK)Irp->AssociatedIrp.SystemBuffer;
if ((ppnmMask->usReadMask == arpReverse[Pdx->IdxReverseProtocol].Protocol) &&
(ppnmMask->usWriteMask == afpForward[Pdx->IdxForwardProtocol].Protocol)) {
Irp->IoStatus.Information = sizeof(PARCLASS_NEGOTIATION_MASK);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_PENDING;
}
}
break;
default :
DD((PCE)Pdx,DDT,"IOCTL default case\n");
Status = STATUS_INVALID_PARAMETER;
break;
}
if (Status == STATUS_PENDING) {
IoAcquireCancelSpinLock(&OldIrql);
if (Irp->Cancel) {
IoReleaseCancelSpinLock(OldIrql);
Status = STATUS_CANCELLED;
} else {
//
// This IRP takes more time, so it should be queued.
//
BOOLEAN needToSignalSemaphore = IsListEmpty( &Pdx->WorkQueue ) ? TRUE: FALSE;
IoMarkIrpPending(Irp);
#pragma warning( push )
#pragma warning( disable : 4054 4055 )
IoSetCancelRoutine(Irp, ParCancelRequest);
#pragma warning( pop )
InsertTailList(&Pdx->WorkQueue, &Irp->Tail.Overlay.ListEntry);
IoReleaseCancelSpinLock(OldIrql);
if( needToSignalSemaphore ) {
KeReleaseSemaphore(&Pdx->RequestSemaphore, 0, 1, FALSE);
}
}
}
if (Status != STATUS_PENDING) {
P4CompleteRequest( Irp, Status, Irp->IoStatus.Information );
}
return Status;
}
NTSTATUS
ParInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch for internal device control requests.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_SUCCESS - Success.
STATUS_PENDING - Request pending.
STATUS_BUFFER_TOO_SMALL - Buffer too small.
STATUS_INVALID_PARAMETER - Invalid io control request.
STATUS_DELETE_PENDING - This device object is being deleted
--*/
{
PIO_STACK_LOCATION IrpSp;
// PPAR_SET_INFORMATION SetInfo;
NTSTATUS Status;
// PSERIAL_TIMEOUTS SerialTimeouts;
PPDO_EXTENSION Pdx;
KIRQL OldIrql;
PPARCLASS_INFORMATION pParclassInfo;
Irp->IoStatus.Information = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Pdx = DeviceObject->DeviceExtension;
//
// bail out if a delete is pending for this device object
//
if(Pdx->DeviceStateFlags & PPT_DEVICE_DELETE_PENDING) {
P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
return STATUS_DELETE_PENDING;
}
//
// bail out if a remove is pending for our ParPort device object
//
if(Pdx->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
return STATUS_DELETE_PENDING;
}
//
// bail out if device has been removed
//
if(Pdx->DeviceStateFlags & (PPT_DEVICE_REMOVED|PPT_DEVICE_SURPRISE_REMOVED) ) {
P4CompleteRequest( Irp, STATUS_DEVICE_REMOVED, Irp->IoStatus.Information );
return STATUS_DEVICE_REMOVED;
}
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_INTERNAL_PARCLASS_CONNECT:
DD((PCE)Pdx,DDT,"IOCTL_INTERNAL_PARCLASS_CONNECT\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARCLASS_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PFDO_EXTENSION fdx = Pdx->Fdo->DeviceExtension;
PPARALLEL_PORT_INFORMATION portInfo = &fdx->PortInfo;
PPARALLEL_PNP_INFORMATION pnpInfo = &fdx->PnpInfo;
pParclassInfo = Irp->AssociatedIrp.SystemBuffer;
pParclassInfo->ParclassContext = Pdx;
pParclassInfo->Controller = portInfo->Controller;
pParclassInfo->SpanOfController = portInfo->SpanOfController;
pParclassInfo->EcrController = pnpInfo->EcpController;
pParclassInfo->HardwareCapabilities = pnpInfo->HardwareCapabilities;
pParclassInfo->FifoDepth = pnpInfo->FifoDepth;
pParclassInfo->FifoWidth = pnpInfo->FifoWidth;
pParclassInfo->DetermineIeeeModes = ParExportedDetermineIeeeModes;
pParclassInfo->TerminateIeeeMode = ParExportedTerminateIeeeMode;
pParclassInfo->NegotiateIeeeMode = ParExportedNegotiateIeeeMode;
pParclassInfo->IeeeFwdToRevMode = ParExportedIeeeFwdToRevMode;
pParclassInfo->IeeeRevToFwdMode = ParExportedIeeeRevToFwdMode;
pParclassInfo->ParallelRead = ParExportedParallelRead;
pParclassInfo->ParallelWrite = ParExportedParallelWrite;
Irp->IoStatus.Information = sizeof(PARCLASS_INFORMATION);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_INTERNAL_GET_PARPORT_FDO:
DD((PCE)Pdx,DDT,"IOCTL_INTERNAL_GET_PARPORT_FDO\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PDEVICE_OBJECT)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PDEVICE_OBJECT *pFdo = Irp->AssociatedIrp.SystemBuffer;
*pFdo = Pdx->Fdo;
Irp->IoStatus.Information = sizeof(PDEVICE_OBJECT);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_INTERNAL_PARCLASS_DISCONNECT:
Status = STATUS_SUCCESS;
break;
case IOCTL_INTERNAL_DISCONNECT_IDLE:
case IOCTL_INTERNAL_LOCK_PORT:
case IOCTL_INTERNAL_UNLOCK_PORT:
case IOCTL_INTERNAL_LOCK_PORT_NO_SELECT:
case IOCTL_INTERNAL_UNLOCK_PORT_NO_DESELECT:
case IOCTL_INTERNAL_PARDOT3_CONNECT:
case IOCTL_INTERNAL_PARDOT3_RESET:
Status = STATUS_PENDING;
break;
case IOCTL_INTERNAL_PARDOT3_DISCONNECT:
// immediately tell worker thread to stop signalling
Pdx->P12843DL.bEventActive = FALSE;
Status = STATUS_PENDING;
break;
case IOCTL_INTERNAL_PARDOT3_SIGNAL:
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PKEVENT) ) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_PENDING;
}
break;
default :
DD((PCE)Pdx,DDW,"IOCTL_INTERNAL... default case - invalid parameter\n");
Status = STATUS_INVALID_PARAMETER;
break;
}
if (Status == STATUS_PENDING) {
//
// This IRP takes more time, queue it for the worker thread
//
IoAcquireCancelSpinLock(&OldIrql);
if (Irp->Cancel) {
IoReleaseCancelSpinLock(OldIrql);
Status = STATUS_CANCELLED;
} else {
BOOLEAN needToSignalSemaphore = IsListEmpty( &Pdx->WorkQueue ) ? TRUE : FALSE;
IoMarkIrpPending(Irp);
#pragma warning( push )
#pragma warning( disable : 4054 4055 )
IoSetCancelRoutine(Irp, ParCancelRequest);
#pragma warning( pop )
InsertTailList(&Pdx->WorkQueue, &Irp->Tail.Overlay.ListEntry);
IoReleaseCancelSpinLock(OldIrql);
if( needToSignalSemaphore ) {
KeReleaseSemaphore(&Pdx->RequestSemaphore, 0, 1, FALSE);
}
}
}
if (Status != STATUS_PENDING) {
P4CompleteRequest( Irp, Status, Irp->IoStatus.Information );
}
return Status;
}
VOID
ParDeviceIo(
IN PPDO_EXTENSION Pdx
)
/*++
Routine Description:
This routine implements a DEVICE_IOCTL request with the extension's current irp.
Arguments:
Pdx - Supplies the device extension.
Return Value:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -