⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdoioctl.c

📁 鼠标Windows驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

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 + -