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

📄 ioctl.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 2 页
字号:

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