Gestione di una richiesta di IRP_MN_QUERY_STOP_DEVICE (Windows 2000 e versioni successive)

Una richiesta di IRP_MN_QUERY_STOP_DEVICE viene gestita prima dal driver principale nello stack di dispositivi e quindi da ogni driver inferiore successivo. Un driver gestisce i runtime di integrazione di arresto nella routine DispatchPnP .

In risposta a un IRP_MN_QUERY_STOP_DEVICE, un driver deve eseguire le operazioni seguenti:

  1. Determinare se il dispositivo può essere arrestato e le relative risorse hardware rilasciate, senza effetti negativi.

    Un driver deve avere esito negativo di un IRP di arresto di query se una delle condizioni seguenti è vera:

    • Un driver è stato informato (tramite IRP_MN_DEVICE_USAGE_NOTIFICATION) che il dispositivo si trova nel percorso di un file di paging, ibernazione o dump di arresto anomalo del sistema.

    • Non è possibile rilasciare le risorse hardware del dispositivo.

    Un driver potrebbe non riuscire con un IRP di arresto di query se è vero quanto segue:

    • Il driver non deve eliminare le richieste di I/O e non dispone di un meccanismo per l'accodamento dei runtime di integrazione.

      Mentre il dispositivo si trova nello stato arrestato, un driver deve contenere i runtime di integrazione che richiedono l'accesso al dispositivo. Se un driver non accoda i runtime di integrazione, non deve consentire l'arresto del dispositivo e pertanto deve non riuscire un IRP di arresto della query.

      L'eccezione a questa regola è un dispositivo autorizzato a eliminare le operazioni di I/O. I driver per un dispositivo di questo tipo possono avere esito positivo e arrestare le richieste senza accodare i runtime di integrazione.

  2. Se il dispositivo non può essere arrestato, l'IRP di arresto della query non riesce.

    Impostare Irp-IoStatus.Status> su uno stato di errore appropriato, chiamare IoCompleteRequest con IO_NO_INCREMENT e restituire dalla routine DispatchPnP del driver. Non passare l'IRP al driver inferiore successivo.

  3. Se il dispositivo può essere arrestato e i provider di integrazione delle code dei driver, impostare il flag di HOLD_NEW_REQUESTS nell'estensione del dispositivo in modo che gli IRP successivi vengano accodati (vedere Holding Incoming IRPs When A Device Is Paused(Mantenere i runtime di integrazione in ingresso quando un dispositivo viene sospeso).

    In alternativa, i driver per un dispositivo possono posticipare completamente la sospensione del dispositivo fino a quando i driver non ricevono la richiesta di IRP_MN_STOP_DEVICE successiva. Tali driver, tuttavia, devono accodare tutte le richieste che impedirebbero di terminare immediatamente l'IRP di arresto all'arrivo. Finché il dispositivo non viene riavviato, tali driver devono accodamento delle richieste, ad esempio:

    • IRP_MN_DEVICE_USAGE_NOTIFICATION richieste ,ad esempio per inserire un file di paging nel dispositivo.

    • Richieste di trasferimenti isocroni.

    • Creare richieste che impediscano il successo dei driver a un'interruzione di IRP.

  4. Se il dispositivo non può avere un IRP in corso ha esito negativo, assicurarsi che tutte le richieste in sospeso passate ad altre routine del driver e ai driver inferiori siano state completate.

    Un modo per ottenere questo risultato da un driver consiste nell'usare un conteggio dei riferimenti e un evento per assicurarsi che tutte le richieste siano state completate:

    • Nella routine AddDevice il driver definisce un conteggio dei riferimenti di I/O nell'estensione del dispositivo e inizializza il conteggio su uno.

    • Inoltre, nella routine AddDevice , il driver crea un evento con KeInitializeEvent e inizializza l'evento allo stato Not-Signaled con KeClearEvent.

    • Ogni volta che elabora un IRP, il driver incrementa il conteggio dei riferimenti con InterlockedIncrement.

    • Ogni volta che completa una richiesta, il driver decrementa il conteggio dei riferimenti con InterlockedDecrement.

      Il driver decrementa il conteggio dei riferimenti nella routine IoCompletion , se la richiesta ne ha una o subito dopo la chiamata a IoCallDriver se il driver non usa alcuna routine IoCompletion per la richiesta.

    • Quando il driver riceve un IRP_MN_QUERY_STOP_DEVICE, decrementa il conteggio dei riferimenti con InterlockedDecrement. Se non sono presenti richieste in sospeso, il conteggio dei riferimenti viene ridotto a zero.

    • Quando il conteggio dei riferimenti raggiunge zero, il driver imposta l'evento con KeSetEvent segnalando che il codice di arresto della query può continuare.

    In alternativa alla procedura precedente, un driver può serializzare il IRP_MN_QUERY_STOP_DEVICE IRP dietro qualsiasi IRP in corso.

  5. Eseguire qualsiasi altro passaggio necessario per impostare il dispositivo nello stato di arresto in sospeso.

    Dopo che un driver ha esito positivo, è necessario che sia pronto per l'esito positivo di un IRP_MN_STOP_DEVICE.

  6. Completare l'IRP.

    In una funzione o in un driver di filtro:

    • Impostare Irp-IoStatus.Status> su STATUS_SUCCESS.

    • Configurare la posizione successiva dello stack con IoSkipCurrentIrpStackLocation e passare l'IRP al driver inferiore successivo con IoCallDriver.

    • Propagare lo stato da IoCallDriver come stato restituito dalla routine DispatchPnP .

    • Non completare l'IRP.

    In un autista di autobus:

    • Impostare Irp-IoStatus.Status> su STATUS_SUCCESS.

      Se, tuttavia, i dispositivi nel bus usano risorse hardware, rivalutare i requisiti delle risorse del bus e dei dispositivi figlio. Se uno dei requisiti è stato modificato, restituire STATUS_RESOURCE_REQUIREMENTS_CHANGED anziché STATUS_SUCCESS. Questo stato indica l'esito positivo, ma richiede che il gestore PnP esegui una query sulle risorse prima di inviare l'IRP di arresto.

    • Completare IRP (IoCompleteRequest) con IO_NO_INCREMENT.

    • Tornare dalla routine DispatchPnP .

Se un driver nello stack di dispositivi non riesce il IRP_MN_QUERY_STOP_DEVICE, il gestore PnP invia un IRP_MN_CANCEL_STOP_DEVICE allo stack di dispositivi. Ciò impedisce ai driver di richiedere una routine IoCompletion per un IRP di arresto di query per rilevare se un driver inferiore non è riuscito a usare IRP.