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

📄 fdopnp.c

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

Arguments:

    DeviceObject - The target device for the IRP
    Irp          - The IRP

Return Value:

    STATUS_SUCCESS              - on success,
    an appropriate error status - otherwise

--*/
{
    PFDO_EXTENSION              fdx               = DeviceObject->DeviceExtension;
    ULONG                          filterResourceMethod    = PPT_FORCE_USE_NO_IRQ;
    PIO_RESOURCE_REQUIREMENTS_LIST pResourceRequirementsIn;
    NTSTATUS                       status;


    //
    // DDK Rule: Add on the way down, modify on the way up. We are modifying
    //   the resource list so let the drivers beneath us handle this IRP first.
    //
    status    = PptPnpBounceAndCatchPnpIrp(fdx, Irp);
    if( !NT_SUCCESS(status) && (status != STATUS_NOT_SUPPORTED) ) {
        // Someone below us in the driver stack explicitly failed the IRP.
        goto targetExit;
    }


    //
    // Find the "real" resource requirments list, either the PnP list
    //   or the list created by another driver in the stack.
    //
    if ( Irp->IoStatus.Information == 0 ) {
        //
        // No one else has created a new resource list. Use the original 
        //   list from the PnP Manager.
        //
        PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation( Irp );
        pResourceRequirementsIn = IrpStack->Parameters.FilterResourceRequirements.IoResourceRequirementList;

        if (pResourceRequirementsIn == NULL) {
            //
            // NULL list, nothing to do.
            //
            goto targetExit;
        }

    } else {
        //
        // Another driver has created a new resource list. Use the list that they created.
        //
        pResourceRequirementsIn = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
    }


    //
    // Check the registry to find out the desired type of resource filtering.
    //
    // The following call sets the default value for filterResourceMethod 
    //   if the registry query fails.
    //
    PptRegGetDeviceParameterDword( fdx->PhysicalDeviceObject,
                                   (PWSTR)L"FilterResourceMethod",
                                   &filterResourceMethod );

    DD((PCE)fdx,DDT,"filterResourceMethod=%x\n",filterResourceMethod);


    //
    // Do filtering based on registry setting.
    //
    switch( filterResourceMethod ) {

    case PPT_FORCE_USE_NO_IRQ: 
        //
        // Registry setting dictates that we should refuse to accept IRQ resources.
        //
        // * This is the default behavior which means that we make the IRQ available 
        //     for legacy net and sound cards that may not work if they cannot get
        //     the IRQ.
        //
        // - If we find a resource alternative that does not contain an IRQ resource
        //     then we remove those resource alternatives that do contain IRQ 
        //     resources from the list of alternatives.
        //
        // - Otherwise we have to play hardball. Since all resource alternatives
        //     contain IRQ resources we simply "nuke" the IRQ resource descriptors
        //     by changing their resource Type from CmResourceTypeInterrupt to
        //     CmResourceTypeNull.
        //

        DD((PCE)fdx,DDT,"PPT_FORCE_USE_NO_IRQ\n");

        if( PptPnpFilterExistsNonIrqResourceList( pResourceRequirementsIn ) ) {

            DD((PCE)fdx,DDT,"Found Resource List with No IRQ - Filtering\n");
            PptPnpFilterRemoveIrqResourceLists( pResourceRequirementsIn );

        } else {

            DD((PCE)fdx,DDT,"Did not find Resource List with No IRQ - Nuking IRQ resource descriptors\n");
            PptPnpFilterNukeIrqResourceDescriptorsFromAllLists( pResourceRequirementsIn );

        }

        break;


    case PPT_TRY_USE_NO_IRQ: 
        //
        // Registry setting dictates that we should TRY to give up IRQ resources.
        //
        // - If we find a resource alternative that does not contain an IRQ resource
        //     then we remove those resource alternatives that do contain IRQ 
        //     resources from the list of alternatives.
        //
        // - Otherwise we do nothing.
        //

        DD((PCE)fdx,DDT,"PPT_TRY_USE_NO_IRQ\n");
        if( PptPnpFilterExistsNonIrqResourceList(pResourceRequirementsIn) ) {

            DD((PCE)fdx,DDT,"Found Resource List with No IRQ - Filtering\n");
            PptPnpFilterRemoveIrqResourceLists(pResourceRequirementsIn);

        } else {

            // leave the IO resource list as is
            DD((PCE)fdx,DDT,"Did not find Resource List with No IRQ - Do nothing\n");

        }
        break;


    case PPT_ACCEPT_IRQ: 
        //
        // Registry setting dictates that we should NOT filter out IRQ resources.
        //
        // - Do nothing.
        //
        DD((PCE)fdx,DDT,"PPT_ACCEPT_IRQ\n");
        break;


    default:
        //
        // Invalid registry setting. 
        //
        // - Do nothing.
        //
        // RMT dvdf - May be desirable to write an error log entry here.
        //
        DD((PCE)fdx,DDE,"ERROR:IGNORED: bad filterResourceMethod=%x\n", filterResourceMethod);
    }

targetExit:

    //
    // Preserve Irp->IoStatus.Information because it may point to a
    //   buffer and we don't want to cause a memory leak.
    //
    P4CompleteRequest( Irp, status, Irp->IoStatus.Information );

    PptReleaseRemoveLock(&fdx->RemoveLock, Irp);

    return status;
}


NTSTATUS
PptFdoSurpriseRemoval(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp
    )
/*++dvdf6

Routine Description:

    This function handles PnP IRP_MN_SURPRISE_REMOVAL.

    Set flags accordingly in our extension, notify those 
      listening on our device interface GUID that 
      we have gone away, and pass the IRP down the
      driver stack.

Arguments:

    DeviceObject - The target device for the IRP
    Irp          - The IRP

Return Value:

    Status returned from IoCallDriver.

--*/
{
    PFDO_EXTENSION fdx = DeviceObject->DeviceExtension;

    //
    // Set flags in our extension to indicate that we have received 
    //   IRP_MN_SURPRISE_REMOVAL so that we can fail new requests 
    //   as appropriate.
    //
    ExAcquireFastMutex( &fdx->ExtensionFastMutex );
    PptSetFlags( fdx->PnpState, PPT_DEVICE_SURPRISE_REMOVED );
    ExReleaseFastMutex( &fdx->ExtensionFastMutex );

    //
    // Fail outstanding allocate/select requests for the port
    //
    {
        PIRP                nextIrp;
        KIRQL               cancelIrql;
        
        IoAcquireCancelSpinLock(&cancelIrql);
        
        while( !IsListEmpty( &fdx->WorkQueue ) ) {
                
            nextIrp = CONTAINING_RECORD( fdx->WorkQueue.Blink, IRP, Tail.Overlay.ListEntry );
            nextIrp->Cancel        = TRUE;
            nextIrp->CancelIrql    = cancelIrql;
            nextIrp->CancelRoutine = NULL;
            PptCancelRoutine( DeviceObject, nextIrp );
            
            // PptCancelRoutine() releases the cancel SpinLock so we need to reaquire
            IoAcquireCancelSpinLock( &cancelIrql );
        }
        
        IoReleaseCancelSpinLock( cancelIrql );
    }

    //
    // Tell those listening on our device interface GUID that we have
    //   gone away. Ignore status from the call since we can do
    //   nothing on failure.
    //
    IoSetDeviceInterfaceState( &fdx->DeviceInterface, FALSE );
    fdx->DeviceInterfaceState = FALSE;

    //
    // Succeed, pass the IRP down the stack, and release the RemoveLock.
    //
    Irp->IoStatus.Status = STATUS_SUCCESS;
    return PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
}

NTSTATUS
PptFdoDefaultPnpHandler(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP           Irp
    )
/*++dvdf8

Routine Description:

    This function is the default handler for PnP IRPs. 
      All PnP IRPs that are not explicitly handled by another 
      routine (via an entry in the PptPnpDispatchFunctionTable[]) are
      handled by this routine.

     - Pass the IRP down the stack to the device below us in the
         driver stack and release our device RemoveLock. 

Arguments:

    DeviceObject - The target device for the IRP
    Irp          - The IRP

Return Value:

    STATUS_SUCCESS              - on success,
    an appropriate error status - otherwise

--*/
{
    return PptPnpPassThroughPnpIrpAndReleaseRemoveLock(DeviceObject->DeviceExtension, Irp);
}


PDRIVER_DISPATCH 
PptFdoPnpDispatchTable[] =
{ 
    PptFdoStartDevice,                // IRP_MN_START_DEVICE                 0x00
    PptFdoQueryRemove,                // IRP_MN_QUERY_REMOVE_DEVICE          0x01
    PptFdoRemoveDevice,               // IRP_MN_REMOVE_DEVICE                0x02
    PptFdoCancelRemove,               // IRP_MN_CANCEL_REMOVE_DEVICE         0x03
    PptFdoStopDevice,                 // IRP_MN_STOP_DEVICE                  0x04
    PptFdoQueryStop,                  // IRP_MN_QUERY_STOP_DEVICE            0x05
    PptFdoCancelStop,                 // IRP_MN_CANCEL_STOP_DEVICE           0x06
    PptFdoQueryDeviceRelations,       // IRP_MN_QUERY_DEVICE_RELATIONS       0x07
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_INTERFACE              0x08
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_CAPABILITIES           0x09
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_RESOURCES              0x0A
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_RESOURCE_REQUIREMENTS  0x0B
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_DEVICE_TEXT            0x0C
    PptFdoFilterResourceRequirements, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
    PptFdoDefaultPnpHandler,          // no such PnP request                 0x0E
    PptFdoDefaultPnpHandler,          // IRP_MN_READ_CONFIG                  0x0F
    PptFdoDefaultPnpHandler,          // IRP_MN_WRITE_CONFIG                 0x10
    PptFdoDefaultPnpHandler,          // IRP_MN_EJECT                        0x11
    PptFdoDefaultPnpHandler,          // IRP_MN_SET_LOCK                     0x12
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_ID                     0x13
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_PNP_DEVICE_STATE       0x14
    PptFdoDefaultPnpHandler,          // IRP_MN_QUERY_BUS_INFORMATION        0x15
    PptFdoDefaultPnpHandler,          // IRP_MN_DEVICE_USAGE_NOTIFICATION    0x16
    PptFdoSurpriseRemoval,            // IRP_MN_SURPRISE_REMOVAL             0x17
    PptFdoDefaultPnpHandler           // IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
};


NTSTATUS 
PptFdoPnp(
    IN PDEVICE_OBJECT Fdo,
    IN PIRP           Irp
    ) 
{ 
    PFDO_EXTENSION      fdx     = Fdo->DeviceExtension;
    PIO_STACK_LOCATION  irpSp   = IoGetCurrentIrpStackLocation( Irp );
    NTSTATUS            status;

    // diagnostic
    PptFdoDumpPnpIrpInfo( Fdo, Irp );

    //
    // Acquire RemoveLock to prevent DeviceObject from being REMOVED
    //   while we are using it. If we are unable to acquire the RemoveLock
    //   then the DeviceObject has already been REMOVED.
    //
    status = PptAcquireRemoveLock( &fdx->RemoveLock, Irp);
    if( STATUS_SUCCESS != status ) {
        return P4CompleteRequest( Irp, STATUS_DELETE_PENDING, Irp->IoStatus.Information );
    }


    //
    // RemoveLock is held. Forward the request to the appropriate handler.
    //
    // Note that the handler must release the RemoveLock prior to returning
    //   control to this function.
    //
    
    if( irpSp->MinorFunction < arraysize(PptFdoPnpDispatchTable) ) {
        return PptFdoPnpDispatchTable[ irpSp->MinorFunction ]( Fdo, Irp );
    } else {
        return PptFdoDefaultPnpHandler( Fdo, Irp );
    }
}

⌨️ 快捷键说明

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