📄 pdoioctl.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1998 - 1999
File Name:
ioctl.c
Contained in Module:
parallel.sys
Abstract:
This file contains functions associated with ParClass IOCTL processing.
- The three main entry points in this file are:
- ParDeviceControl() - Dispatch function for non-internal IOCTLs
- ParInternalDeviceControl() - Dispatch function for internal IOCTLs
- ParDeviceIo() - Worker thread entry point for handling all
IOCTLs not completed in a dispatch function
- Helper/Utility function naming conventions:
- ParpIoctlDispatch...() - private helper function called by dispatch function
- ParpIoctlThread...() - private helper function called by worker thread
Authors:
Anthony V. Ercolano 1-Aug-1992
Norbert P. Kusters 22-Oct-1993
Douglas G. Fritz 24-Jul-1998
Revision History :
--*/
#include "pch.h"
VOID
ParpIoctlThreadLockPort(
IN PPDO_EXTENSION Pdx
)
{
NTSTATUS status;
PIRP irp = Pdx->CurrentOpIrp;
DD((PCE)Pdx,DDT,"ParpIoctlThreadLockPort - enter\n");
if( ParSelectDevice(Pdx,TRUE) ) {
DD((PCE)Pdx,DDT,"ParpIoctlThreadLockPort - SUCCESS\n");
Pdx->AllocatedByLockPort = TRUE;
status = STATUS_SUCCESS;
} else {
DD((PCE)Pdx,DDW,"ParpIoctlThreadLockPort - FAIL\n");
Pdx->AllocatedByLockPort = FALSE;
status = STATUS_UNSUCCESSFUL;
}
irp->IoStatus.Status = status;
}
VOID
ParpIoctlThreadUnlockPort(
IN PPDO_EXTENSION Pdx
)
{
PIRP irp = Pdx->CurrentOpIrp;
Pdx->AllocatedByLockPort = FALSE;
DD((PCE)Pdx,DDT,"ParpIoctlThreadUnlockPort - enter\n");
if( ParDeselectDevice(Pdx, FALSE) ) {
DD((PCE)Pdx,DDT,"ParpIoctlThreadUnlockPort - SUCCESS\n");
} else {
DD((PCE)Pdx,DDW,"ParpIoctlThreadUnlockPort - FAIL - nothing we can do\n");
}
irp->IoStatus.Status = STATUS_SUCCESS;
}
NTSTATUS
ParDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch for 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
--*/
{
PPDO_EXTENSION Pdx = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
PPAR_SET_INFORMATION SetInfo;
NTSTATUS Status;
PSERIAL_TIMEOUTS SerialTimeouts;
KIRQL OldIrql;
Irp->IoStatus.Information = 0;
//
// bail out if a delete is pending for this device object
//
if(Pdx->DeviceStateFlags & PPT_DEVICE_DELETE_PENDING) {
return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, 0 );
}
//
// bail out if a remove is pending for our ParPort device object
//
if(Pdx->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, 0 );
}
//
// bail out if device has been removed
//
if(Pdx->DeviceStateFlags & (PPT_DEVICE_REMOVED|PPT_DEVICE_SURPRISE_REMOVED) ) {
return P4CompleteRequest( Irp, STATUS_DEVICE_REMOVED, 0 );
}
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_PAR_QUERY_LOCATION:
DD((PCE)Pdx,DDT,"IOCTL_PAR_QUERY_LOCATION\n");
{
ULONG outBufLen = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
ULONG locationLen = strlen(Pdx->Location);
if( outBufLen < locationLen+1 ) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PCHAR buffer = (PCHAR)Irp->AssociatedIrp.SystemBuffer;
RtlCopyMemory( buffer, Pdx->Location, locationLen + 1 );
Irp->IoStatus.Information = locationLen + 1;
Status = STATUS_SUCCESS;
}
}
break;
case IOCTL_PAR_SET_INFORMATION:
DD((PCE)Pdx,DDT,"IOCTL_PAR_SET_INFORMATION\n");
SetInfo = Irp->AssociatedIrp.SystemBuffer;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PAR_SET_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else if (SetInfo->Init != PARALLEL_INIT) {
Status = STATUS_INVALID_PARAMETER;
} else {
//
// This is a parallel reset
//
Status = STATUS_PENDING;
}
break;
case IOCTL_PAR_QUERY_INFORMATION :
DD((PCE)Pdx,DDT,"IOCTL_PAR_QUERY_INFORMATION\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PAR_QUERY_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_SERIAL_SET_TIMEOUTS:
DD((PCE)Pdx,DDT,"IOCTL_SERIAL_SET_TIMEOUTS\n");
SerialTimeouts = Irp->AssociatedIrp.SystemBuffer;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_TIMEOUTS)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else if (SerialTimeouts->WriteTotalTimeoutConstant < 2000) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_SERIAL_GET_TIMEOUTS:
DD((PCE)Pdx,DDT,"IOCTL_SERIAL_GET_TIMEOUTS\n");
SerialTimeouts = Irp->AssociatedIrp.SystemBuffer;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_TIMEOUTS)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
//
// We don't need to synchronize the read.
//
RtlZeroMemory(SerialTimeouts, sizeof(SERIAL_TIMEOUTS));
SerialTimeouts->WriteTotalTimeoutConstant =
1000 * Pdx->TimerStart;
Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_QUERY_DEVICE_ID:
case IOCTL_PAR_QUERY_RAW_DEVICE_ID:
DD((PCE)Pdx,DDT,"IOCTL_PAR_QUERY_[RAW_]DEVICE_ID\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_PAR_QUERY_DEVICE_ID_SIZE:
DD((PCE)Pdx,DDT,"IOCTL_PAR_QUERY_DEVICE_ID_SIZE\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PAR_DEVICE_ID_SIZE_INFORMATION)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_PAR_IS_PORT_FREE:
DD((PCE)Pdx,DDT,"IOCTL_PAR_IS_PORT_FREE\n");
if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(BOOLEAN) ) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
if( Pdx->bAllocated ) {
// if we have the port then it is not free
*((PBOOLEAN)Irp->AssociatedIrp.SystemBuffer) = FALSE;
} else {
// determine if the port is free by trying to allocate and free it
// - our alloc/free will only succeed if no one else has the port
BOOLEAN tryAllocSuccess = Pdx->TryAllocatePort( Pdx->PortContext );
if( tryAllocSuccess ) {
// we were able to allocate the port, free it and report that the port is free
Pdx->FreePort( Pdx->PortContext );
*((PBOOLEAN)Irp->AssociatedIrp.SystemBuffer) = TRUE;
} else {
// we were unable to allocate the port, someone else must be using the port
*((PBOOLEAN)Irp->AssociatedIrp.SystemBuffer) = FALSE;
}
}
Irp->IoStatus.Information = sizeof(BOOLEAN);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_GET_READ_ADDRESS:
DD((PCE)Pdx,DDT,"IOCTL_PAR_GET_READ_ADDRESS\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(Pdx->ReverseInterfaceAddress)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
*((PUCHAR) Irp->AssociatedIrp.SystemBuffer) = Pdx->ReverseInterfaceAddress;
Irp->IoStatus.Information = sizeof(Pdx->ReverseInterfaceAddress);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_GET_WRITE_ADDRESS:
DD((PCE)Pdx,DDT,"IOCTL_PAR_GET_WRITE_ADDRESS\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(Pdx->ForwardInterfaceAddress)) {
Status = STATUS_BUFFER_TOO_SMALL;
} else {
*((PUCHAR) Irp->AssociatedIrp.SystemBuffer) = Pdx->ForwardInterfaceAddress;
Irp->IoStatus.Information = sizeof(Pdx->ForwardInterfaceAddress);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_PAR_SET_READ_ADDRESS:
DD((PCE)Pdx,DDT," IOCTL_PAR_SET_READ_ADDRESS\n");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(Pdx->ReverseInterfaceAddress)) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_PENDING;
}
break;
case IOCTL_PAR_SET_WRITE_ADDRESS:
DD((PCE)Pdx,DDT," IOCTL_PAR_SET_WRITE_ADDRESS\n");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(Pdx->ForwardInterfaceAddress)) {
Status = STATUS_INVALID_PARAMETER;
} else {
Status = STATUS_PENDING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -