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

📄 ioctl.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 2 页
字号:
//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  Copyright (C) Microsoft Corporation, 1998 - 1999
//
//  File:       ioctl.c
//
//--------------------------------------------------------------------------

#include "pch.h"

VOID
PptCleanRemovalRelationsList(PDEVICE_EXTENSION Extension) 
//
// Clean up any remaining list pool allocations.
//
// Called from IRP_MN_REMOVE handler
//
{
    PLIST_ENTRY                   listHead      = &Extension->RemovalRelationsList;
    PLIST_ENTRY                   thisListEntry = NULL;
    PREMOVAL_RELATIONS_LIST_ENTRY node          = NULL;

    ExAcquireFastMutex( &Extension->ExtensionFastMutex );

    while( !IsListEmpty( listHead ) ) {
        thisListEntry = RemoveHeadList( listHead );
        node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );
        PptDump2(PARPNP1, ("ioctl::PptCleanRemovalRelationsList - deleting entry for node=%x devobj=%x %wZ\n",
                               node, node->DeviceObject, &node->DeviceName));
        RtlFreeUnicodeString( &node->DeviceName );
        ExFreePool( node );
    }

    ExReleaseFastMutex( &Extension->ExtensionFastMutex );

    return;
}

NTSTATUS
PptAddPptRemovalRelation(PDEVICE_EXTENSION Extension, PPARPORT_REMOVAL_RELATIONS PptRemovalRelations) 
{
    PREMOVAL_RELATIONS_LIST_ENTRY node = ExAllocatePool(PagedPool, sizeof(REMOVAL_RELATIONS_LIST_ENTRY));
    PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - DeviceObject= %x %wZ\n", 
                       PptRemovalRelations->DeviceObject, PptRemovalRelations->DeviceName));

    if( !node ) {
        PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - can't get storage for node\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // initialize node
    node->DeviceObject = PptRemovalRelations->DeviceObject;
    node->Flags        = PptRemovalRelations->Flags;
    RtlZeroMemory( &node->DeviceName, sizeof(UNICODE_STRING) );
    node->DeviceName.Buffer = ExAllocatePool(PagedPool, PptRemovalRelations->DeviceName->MaximumLength);
    if( !(node->DeviceName.Buffer) ) {
        PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - can't get storage for UNICODE_STRING\n"));
        ExFreePool( node );
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    node->DeviceName.MaximumLength = PptRemovalRelations->DeviceName->MaximumLength;
    RtlCopyUnicodeString( &node->DeviceName, PptRemovalRelations->DeviceName);

    // add to list
    ExAcquireFastMutex( &Extension->ExtensionFastMutex );
    InsertTailList( &Extension->RemovalRelationsList, &node->ListEntry );
    ExReleaseFastMutex( &Extension->ExtensionFastMutex );
    return STATUS_SUCCESS;
}

NTSTATUS
PptRemovePptRemovalRelation(
    IN PDEVICE_EXTENSION          Extension, 
    IN PPARPORT_REMOVAL_RELATIONS PptRemovalRelations
)
/*++

  Search the list for the element specified. If found, remove it 
    from the list and free pool associated with the entry.

--*/
{
    PDEVICE_OBJECT                callerDevObj   = PptRemovalRelations->DeviceObject;
    PLIST_ENTRY                   listHead       = &Extension->RemovalRelationsList;
    PDEVICE_OBJECT                listDevObj     = NULL;
    PLIST_ENTRY                   thisListEntry  = NULL;
    PLIST_ENTRY                   firstListEntry = NULL;
    BOOLEAN                       found          = FALSE;
    BOOLEAN                       done           = FALSE;
    PREMOVAL_RELATIONS_LIST_ENTRY node           = NULL;

    PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Entry - DeviceObject= %x %wZ\n", 
                       PptRemovalRelations->DeviceObject, PptRemovalRelations->DeviceName) );
    
    ExAcquireFastMutex( &Extension->ExtensionFastMutex );
    if( IsListEmpty( listHead ) ) {
        PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Empty List\n"));
        ExReleaseFastMutex( &Extension->ExtensionFastMutex );
        return STATUS_SUCCESS;
    } else {
        PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Nonempty List - begin search\n"));
        ExReleaseFastMutex( &Extension->ExtensionFastMutex );    
    }

    ExAcquireFastMutex( &Extension->ExtensionFastMutex );
    while( !done ) {

        thisListEntry = RemoveHeadList( listHead );
        node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );

        if( node->DeviceObject == callerDevObj ) {
            // found it
            PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Found device= %x %wZ\n",
                               node->DeviceObject, &node->DeviceName));
            found = TRUE;
            done  = TRUE;
        } else if( firstListEntry == thisListEntry ) {
            // searched entire list and didn't find it
            PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Not Found\n"));
            done = TRUE;
        } else if( !firstListEntry ) {
            // this is first element in list - save as marker for loop termination
            PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Not Found - First Entry\n"));
            firstListEntry = thisListEntry;
        }

        if( !found ) {
            // return current element to end of list
            // PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - InsertTailList\n"));
            InsertTailList( listHead, &node->ListEntry );
        }
    }
    ExReleaseFastMutex( &Extension->ExtensionFastMutex );

    if( found ) {
        // found the matching entry - clean up allocations
        // PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Found - freeing pool\n"));
        RtlFreeUnicodeString( &node->DeviceName );
        ExFreePool( node );
    }          

    PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Returning\n"));
    return STATUS_SUCCESS; // always
}

VOID
PptDumpRemovalRelationsList(PDEVICE_EXTENSION Extension) 
{
    PLIST_ENTRY                   listHead       = &Extension->RemovalRelationsList;
    PLIST_ENTRY                   thisListEntry  = NULL;
    PLIST_ENTRY                   firstListEntry = NULL;
    BOOLEAN                       done           = FALSE;
    PREMOVAL_RELATIONS_LIST_ENTRY node           = NULL;

    PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList\n"));

    
    ExAcquireFastMutex( &Extension->ExtensionFastMutex );
    if( IsListEmpty( listHead ) ) {
        PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Empty List\n"));
        ExReleaseFastMutex( &Extension->ExtensionFastMutex );
        return;
    } else {
        PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Nonempty List - begin scan/dump\n"));
    }

    while( !done ) {

        thisListEntry = RemoveHeadList( listHead );
        node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );

        if( firstListEntry == thisListEntry ) {
            // done - push back onto front of list
            InsertHeadList( listHead, &node->ListEntry );            
            done = TRUE;
            PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Done\n"));
        } else {
            // dump node info
            PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - entry= %x %wZ\n", node->DeviceObject, &node->DeviceName));
            InsertTailList( listHead, &node->ListEntry );
        }

        if( !firstListEntry ) {
            // save first element - use for loop termination
            firstListEntry = thisListEntry;
        }
    }
    ExReleaseFastMutex( &Extension->ExtensionFastMutex );
    return;
}

VOID
PptDumpPptRemovalRelationsStruct(PPARPORT_REMOVAL_RELATIONS PptRemovalRelations) 
{
#if DBG
    ASSERT( PptRemovalRelations );
    ASSERT( PptRemovalRelations->DeviceName );
    PptDump2(PARPNP1, ("ioctl::PptDumpPptRemovalRelationsStruct - DevObj  = %x\n", PptRemovalRelations->DeviceObject));
    PptDump2(PARPNP1, ("ioctl::PptDumpPptRemovalRelationsStruct - DevName = %wZ\n", PptRemovalRelations->DeviceName));
#else
    UNREFERENCED_PARAMETER( PptRemovalRelations );
#endif
    return;
}

NTSTATUS
PptDispatchInternalDeviceControl(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )

/*++
      
Routine Description:
      
    This routine is the dispatch routine for IRP_MJ_INTERNAL_DEVICE_CONTROL.
      
Arguments:
      
    DeviceObject    - Supplies the device object.
      
    Irp             - Supplies the I/O request packet.
      
Return Value:
      
    STATUS_SUCCESS              - Success.
    STATUS_UNSUCCESSFUL         - The request was unsuccessful.
    STATUS_PENDING              - The request is pending.
    STATUS_INVALID_PARAMETER    - Invalid parameter.
    STATUS_CANCELLED            - The request was cancelled.
    STATUS_BUFFER_TOO_SMALL     - The supplied buffer is too small.
    STATUS_INVALID_DEVICE_STATE - The current chip mode is invalid to change to asked mode
    
--*/
    
{
    PIO_STACK_LOCATION                  IrpSp;
    PDEVICE_EXTENSION                   Extension = DeviceObject->DeviceExtension;
    NTSTATUS                            Status;
    PPARALLEL_PORT_INFORMATION          PortInfo;
    PPARALLEL_PNP_INFORMATION           PnpInfo;
    PMORE_PARALLEL_PORT_INFORMATION     MorePortInfo;
    KIRQL                               CancelIrql;
    SYNCHRONIZED_COUNT_CONTEXT          SyncContext;
    PPARALLEL_INTERRUPT_SERVICE_ROUTINE IsrInfo;
    PPARALLEL_INTERRUPT_INFORMATION     InterruptInfo;
    PISR_LIST_ENTRY                     IsrListEntry;
    SYNCHRONIZED_LIST_CONTEXT           ListContext;
    SYNCHRONIZED_DISCONNECT_CONTEXT     DisconnectContext;
    BOOLEAN                             DisconnectInterrupt;


    PptDump2(PARENTRY, ("ioctl::PptDispatchInternalDeviceControl - Irp= %x , UserEvent= %x\n", Irp, Irp->UserEvent));
    if(Irp->UserEvent) {
        ASSERT_EVENT(Irp->UserEvent);
    }

    //
    // Verify that our device has not been SUPRISE_REMOVED. Generally
    //   only parallel ports on hot-plug busses (e.g., PCMCIA) and
    //   parallel ports in docking stations will be surprise removed.
    //
    // dvdf - RMT - It would probably be a good idea to also check
    //   here if we are in a "paused" state (stop-pending, stopped, or
    //   remove-pending) and queue the request until we either return to
    //   a fully functional state or are removed.
    //
    if( Extension->DeviceStateFlags & PPT_DEVICE_SURPRISE_REMOVED ) {
        PptDumpV( ("IRP_MJ_CREATE - FAIL - %S, DEVICE_SURPRISE_REMOVED\n", Extension->PnpInfo.PortName) );
        return PptFailRequest( Irp, STATUS_DELETE_PENDING );
    }


    //
    // Try to acquire RemoveLock to prevent the device object from going
    //   away while we're using it.
    //
    Status = PptAcquireRemoveLockOrFailIrp( DeviceObject, Irp );
    if ( !NT_SUCCESS(Status) ) {
        PptDumpV( ("IRP_MJ_CREATE - FAIL - unable to acquire RemoveLock\n") );
        return Status;
    }

    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    
    Irp->IoStatus.Information = 0;
    

    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
        
    case IOCTL_INTERNAL_REGISTER_FOR_REMOVAL_RELATIONS:

        PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - Enter\n") );

        if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARPORT_REMOVAL_RELATIONS) ) {
            PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - BUFFER_TOO_SMALL\n") );
            Status = STATUS_BUFFER_TOO_SMALL;
        } else {
            PPARPORT_REMOVAL_RELATIONS removalRelations = Irp->AssociatedIrp.SystemBuffer;
            PptDumpPptRemovalRelationsStruct( removalRelations );
            PptDumpRemovalRelationsList(Extension);
            PptAddPptRemovalRelation(Extension, removalRelations);
            PptDumpRemovalRelationsList(Extension);
            PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - SUCCESS\n") );
            Status = STATUS_SUCCESS;
        }

        Irp->IoStatus.Status = Status;
        PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
        PptCompleteRequest(Irp, IO_NO_INCREMENT);
        return Status;

    case IOCTL_INTERNAL_UNREGISTER_FOR_REMOVAL_RELATIONS:

        PptDump2(PARPNP1, ("ioctl:: - UnregisterForRemovalRelations - Enter\n") );
        
        if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARPORT_REMOVAL_RELATIONS) ) {
            PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - BUFFER_TOO_SMALL\n") );
            Status = STATUS_BUFFER_TOO_SMALL;
        } else {
            PPARPORT_REMOVAL_RELATIONS removalRelations = Irp->AssociatedIrp.SystemBuffer;
            PptDumpPptRemovalRelationsStruct(Irp->AssociatedIrp.SystemBuffer);
            PptDumpRemovalRelationsList(Extension);
            PptRemovePptRemovalRelation(Extension, removalRelations);
            PptDumpRemovalRelationsList(Extension);
            PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - SUCCESS\n") );
            Status = STATUS_SUCCESS;
        }

        Irp->IoStatus.Status = Status;
        PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
        PptCompleteRequest(Irp, IO_NO_INCREMENT);
        return Status;

    case IOCTL_INTERNAL_PARALLEL_PORT_FREE:

        PptFreePort(Extension);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
        PptCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;

    case IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE:
        
        IoAcquireCancelSpinLock(&CancelIrql);
        
        if (Irp->Cancel) {
            
            Status = STATUS_CANCELLED;
            
        } else {
            
            SyncContext.Count = &Extension->WorkQueueCount;
            
            if (Extension->InterruptRefCount) {
                
                KeSynchronizeExecution(Extension->InterruptObject,
                                       PptSynchronizedIncrement,
                                       &SyncContext);
            } else {
                
                PptSynchronizedIncrement(&SyncContext);
            }
            
            if (SyncContext.NewCount) {
                
                // someone else currently has the port, queue request
                PptSetCancelRoutine(Irp, PptCancelRoutine);
                IoMarkIrpPending(Irp);
                InsertTailList(&Extension->WorkQueue,
                               &Irp->Tail.Overlay.ListEntry);
                Status = STATUS_PENDING;

            } else {
                // port aquired
                Extension->WmiPortAllocFreeCounts.PortAllocates++;
                Status = STATUS_SUCCESS;
            }
        }
        
        IoReleaseCancelSpinLock(CancelIrql);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -