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

📄 pnp.c

📁 USB 过滤驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
        // status to STATUS_SUCCESS (default is STATUS_NOT_SUPPORTED)
        // before passing it down the driver stack
        //
        irp->IoStatus.Status = STATUS_SUCCESS;

        break;
#endif // HANDLE_DEVICE_USAGE

    case IRP_MN_QUERY_DEVICE_RELATIONS:
    default:
        break;


    }

    if (justReturnStatus){
        /*
         *  We've already sent this IRP down the stack.
         */
    }
    else if (completeIrpHere){
        irp->IoStatus.Status = status;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }
    else {
        IoCopyCurrentIrpStackLocationToNext(irp);
        status = IoCallDriver(devExt->topDevObj, irp);
    }

    return status;
}

#ifdef HANDLE_DEVICE_USAGE
NTSTATUS
VA_DeviceUsageNotification(struct DEVICE_EXTENSION *devExt, PIRP irp)
{
    PIO_STACK_LOCATION irpSp;
    NTSTATUS status;
    BOOLEAN fSetPagable = FALSE;  // whether we set the PAGABLE bit
                                  /// before we passed-on this IRP

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation(irp);

    DBGOUT(( "DEVICE_USAGE_NOTIFICATION (Type==%d , InPath==%d)"
             , irpSp->Parameters.UsageNotification.Type
             , irpSp->Parameters.UsageNotification.InPath
          ));
    DBGOUT(( "    [devExt=0x%08X fltrDevObj=0x%08X]", devExt, devExt->filterDevObj ));

    //
    // Wait on the paging path event (to prevent several instances of
    // this IRP from being processed at once)
    //
    status = KeWaitForSingleObject( &devExt->deviceUsageNotificationEvent
                                    , Executive    // wait reason
                                    , KernelMode
                                    , FALSE        // not alertable
                                    , NULL         // no timeout
                                  );


    /*
     * IMPORTANT NOTE: When to modify our DO_POWER_PAGABLE bit depends
     * on whether it needs to be set or cleared.  If the IRP indicates
     * our PAGABLE bit should be set, then we must set it _before_
     * forwarding the IRP down the driver stack (and possibly clear it
     * afterward, if lower drivers fail the IRP).  But if the IRP
     * indicates that our PAGABLE bit should be cleared, then we must
     * first forward the IRP to lower drivers, and then clear our bit
     * only if the lower drivers return STATUS_SUCCESS.
     */

    //
    // If removing last paging file from this device...
    //
    if(    irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging
        && !irpSp->Parameters.UsageNotification.InPath
        && devExt->pagingFileCount == 1       )
    {
        //
        // Set DO_POWER_PAGABLE bit (if it was set at startup).
        // If lower drivers fail this IRP, we'll clear it later.
        //
        DBGOUT(( "Removing last paging file..." ));

        if( devExt->initialFlags & DO_POWER_PAGABLE )
        {
            DBGOUT(( "...so RE-setting PAGABLE bit" ));
            devExt->filterDevObj->Flags |= DO_POWER_PAGABLE;
            fSetPagable = TRUE;
        }
        else
        {
            DBGOUT(( "...but PAGABLE bit wasn't set initially, so not setting it now." ));
        }

    }


    //
    // Forward the irp synchronously
    //
    IoCopyCurrentIrpStackLocationToNext( irp );
    status = CallNextDriverSync( devExt, irp );


    //
    // Now deal with the failure and success cases.
    //
    if( ! NT_SUCCESS(status) )
    {
        //
        // Lower drivers failed the IRP, so _undo_ any changes we
        // made before passing-on the IRP to those drivers.
        //
        if( fSetPagable )
        {
            DBGOUT(( "IRP was failed, so UN-setting PAGABLE bit" ));
            devExt->filterDevObj->Flags &= ~DO_POWER_PAGABLE;
        }
    }
    else
    {
        //
        // Lower drivers returned SUCCESS, so we can do everything
        // that must be done in response to this IRP...
        //

        switch( irpSp->Parameters.UsageNotification.Type )
        {
        case DeviceUsageTypeHibernation:

            // Adjust counter
            IoAdjustPagingPathCount( &devExt->hibernationFileCount,
                                     irpSp->Parameters.UsageNotification.InPath );
            DBGOUT(( "Num. Hibernation files is now %d", devExt->hibernationFileCount ));
            ASSERT( devExt->hibernationFileCount >= 0 );
            break;

        case DeviceUsageTypeDumpFile:

            // Adjust counter
            IoAdjustPagingPathCount( &devExt->crashdumpFileCount,
                                     irpSp->Parameters.UsageNotification.InPath );
            DBGOUT(( "Num. Crashdump files is now %d", devExt->crashdumpFileCount ));
            ASSERT( devExt->crashdumpFileCount >= 0 );
            break;

        case DeviceUsageTypePaging:

            // Adjust counter
            IoAdjustPagingPathCount( &devExt->pagingFileCount,
                                     irpSp->Parameters.UsageNotification.InPath );
            DBGOUT(( "Num. Paging files is now %d", devExt->pagingFileCount ));
            ASSERT( devExt->pagingFileCount >= 0 );

            //
            // If we've just switched between being pageable<->nonpageable...
            //
            if(    irpSp->Parameters.UsageNotification.InPath
                && devExt->pagingFileCount == 1  )
            {
                //
                // Just added a paging file, so clear the PAGABLE
                // flag, and lock-down the code for all routines
                // that could be called at IRQL >= DISPATCH_LEVEL
                // (so that they're _non-pageable_).
                //
                DBGOUT(( "Just added first paging file..." ));
                DBGOUT(( "...so clearing PAGABLE bit" ));
                devExt->filterDevObj->Flags &= ~DO_POWER_PAGABLE;

                DBGOUT(( "LOCKing some driver code (non-pageable) (b/c paging path)" ));
                devExt->pagingPathUnlockHandle = MmLockPagableCodeSection( VA_Power );  // some func that's inside the code section that we want to lock
                ASSERT( NULL != devExt->pagingPathUnlockHandle );
            }
            else if (    !irpSp->Parameters.UsageNotification.InPath
                      && devExt->pagingFileCount == 0  )
            {
                //
                // Just removed the last paging file, but we
                // already set the PAGABLE flag (if necessary)
                // before forwarding IRP, so just remove the
                // _paging-path_ lock from this driver. (NOTE:
                // initial-condition lock might still be in place,
                // but that's what we want.)
                //
                DBGOUT(( "UNLOCKing some driver code (pageable) (b/c paging path)" ));
                ASSERT( NULL != devExt->pagingPathUnlockHandle );
                MmUnlockPagableImageSection( devExt->pagingPathUnlockHandle );
                devExt->pagingPathUnlockHandle = NULL;
            }
            break;

        default:
            ASSERT( FALSE );  // should never get here (b/c checked for invalid Type earlier)

        } //END: switch on Type of special-file


        //
        // Invalidate state, so that certain flags will get updated
        //
        IoInvalidateDeviceState( devExt->physicalDevObj );

    }//END: handling of irp success/failure cases


    //
    // Set event so that the next DEVICE_USAGE_NOTIFICATION IRP that
    // comes along can be processed.
    //
    KeSetEvent( &devExt->deviceUsageNotificationEvent
                , IO_NO_INCREMENT
                , FALSE
              );

    //
    // Complete the irp
    //
    IoCompleteRequest( irp, IO_NO_INCREMENT );
    return status;
}
#endif // HANDLE_DEVICE_USAGE



NTSTATUS GetDeviceCapabilities(struct DEVICE_EXTENSION *devExt)
/*++

Routine Description:

    Function retrieves the DEVICE_CAPABILITIES descriptor from the device

Arguments:

    devExt - device extension for targetted device object

Return Value:

    NT status code

--*/
{
    NTSTATUS status;
    PIRP irp;

    PAGED_CODE();

    irp = IoAllocateIrp(devExt->topDevObj->StackSize, FALSE);
    if (irp){
        PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(irp);

        // must initialize DeviceCapabilities before sending...
        RtlZeroMemory(  &devExt->deviceCapabilities,
                        sizeof(DEVICE_CAPABILITIES));
        devExt->deviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
        devExt->deviceCapabilities.Version = 1;
        devExt->deviceCapabilities.Address = -1;
        devExt->deviceCapabilities.UINumber = -1;

        // setup irp stack location...
        nextSp->MajorFunction = IRP_MJ_PNP;
        nextSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
        nextSp->Parameters.DeviceCapabilities.Capabilities =
                        &devExt->deviceCapabilities;

        /*
         *  For any IRP you create, you must set the default status
         *  to STATUS_NOT_SUPPORTED before sending it.
         */
        irp->IoStatus.Status = STATUS_NOT_SUPPORTED;

        status = CallNextDriverSync(devExt, irp);

        IoFreeIrp(irp);
    }
    else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    ASSERT(NT_SUCCESS(status));
    return status;
}

⌨️ 快捷键说明

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