Vincoli sulle routine di invio

Nota

Per garantire affidabilità e prestazioni ottimali, usare i driver minifilter del file system con il supporto di Filter Manager anziché i driver di filtro del file system legacy. Per convertire il driver legacy in un driver minifilter, vedere Linee guida per la conversione dei driver di filtro legacy.

Le linee guida seguenti illustrano brevemente come i driver di filtro del file system legacy possono evitare errori di programmazione comuni nelle routine di invio.

Per informazioni sui tipi di IRP usati nel paging di I/O, vedere Dispatch Routine IRQL e Thread Context.

  • Le routine di invio nel percorso di I/O di paging non devono mai chiamare IoCallDriver in qualsiasi irQL maggiore di APC_LEVEL. Non è possibile eseguire il paging di I/O (o qualsiasi I/O) in DISPATCH_LEVEL perché il sistema usa le API per elaborare il completamento dell'I/O, in modo da non visualizzare mai l'operazione completata. Se una routine di invio genera IRQL, deve ridurla prima di chiamare IoCallDriver.

  • Non è necessariamente sicuro che una routine di invio chiami IoCallDriver in APC_LEVEL in tutte le situazioni. Vedere Dispatch Routine IRQL e Thread Context per determinare se è possibile essere in APC_LEVEL o deve essere in PASSIVE_LEVEL.

  • Le routine di invio nel percorso I/O di paging, ad esempio lettura e scrittura, non possono chiamare in modo sicuro le routine in modalità kernel che richiedono l'esecuzione dei chiamanti in irQL PASSIVE_LEVEL.

  • Le routine di invio presenti nel percorso di I/O del file di paging non possono chiamare in modo sicuro le routine in modalità kernel che richiedono l'esecuzione di un chiamante in irQL < DISPATCH_LEVEL.

  • Le routine di invio che non si trovano nel percorso di I/O di paging non devono mai chiamare IoCallDriver in qualsiasi irQL maggiore di PASSIVE_LEVEL. Se una routine di invio genera IRQL, deve ridurla prima di chiamare IoCallDriver.

Vincoli per l'elaborazione di IRP

  • Se i parametri IRP includono gli indirizzi dello spazio utente, questi indirizzi devono essere convalidati prima dell'uso. Per altre informazioni, vedere Errori in I/O memorizzati nel buffer.

  • Inoltre, se l'IRP contiene un buffer IOCTL o FSCTL inviato da una piattaforma a 32 bit a una piattaforma a 64 bit, il contenuto del buffer potrebbe essere thunk. Per altre informazioni, vedere Supporto di I/O a 32 bit nel driver a 64 bit.

  • A differenza dei file system, i driver di filtro del file system non devono mai chiamare FsRtlEnterFileSystem o FsRtlExitFileSystem , tranne prima di chiamare ExAcquireFastMutexUnsafe o ExAcquireResourceExclusiveLite. FsRtlEnterFileSystem e FsRtlExitFileSystem disabilitano le API kernel normali, necessarie per la maggior parte dei file system.

  • Non è possibile inviare altri INDIRIZZI DI rete da un percorso di I/O di paging. È possibile accodare un thread di lavoro che genera I/O, ma non è necessario attendere il completamento del thread di lavoro perché l'attesa causa deadlock.

Vincoli per il completamento degli indirizzi di accesso

  • I driver di filtro del file system devono usare solo valori di stato di esito positivo e di errore durante il completamento degli indirizzi IP.

  • Anche se STATUS_PENDING è un valore NTSTATUS riuscito, è un errore di programmazione per completare un'IRP con STATUS_PENDING.

  • Dopo una routine di invio chiama IoCompleteRequest, il puntatore IRP non è più valido e non può essere dereferenziato in modo sicuro.

Vincoli per l'impostazione di una routine di completamento

Per informazioni sulle routine di completamento dell'impostazione, vedere Uso di routine di completamento.

  • Quando una routine di invio chiama IoSetCompletionRoutine, può facoltativamente passare un puntatore di contesto a una struttura da usare per la routine di completamento da usare durante l'elaborazione dell'IRP specificato. Questa struttura deve essere allocata dal pool non a pagina, perché la routine di completamento può essere chiamata IRQL DISPATCH_LEVEL.

  • Se una routine di invio imposta una routine di completamento che può restituire STATUS_MORE_PROCESSING_REQUIRED, deve eseguire una delle operazioni seguenti per impedire a Gestione I/O di completare prematuramente l'IRP:

Vincoli per il passaggio di IRP in basso

  • Dopo una routine di invio chiama IoCallDriver, il puntatore IRP non è più valido e non può essere dereferenziato in modo sicuro, a meno che la routine di invio attenda la routine di completamento per segnalare che è stata chiamata.

  • Si tratta di un errore di programmazione per chiamare PoCallDriver da un driver di filtro del file system. (PoCallDriver viene usato per passare le richieste di IRP_MJ_POWER ai driver di livello inferiore. I driver di filtro del file system non ricevono mai richieste di IRP_MJ_POWER.

Vincoli per la restituzione dello stato

  • Tranne quando si completa un'IRP, una routine di invio che non imposta una routine di completamento deve sempre restituire il valore NTSTATUS restituito da IoCallDriver. A meno che questo valore non sia STATUS_PENDING, deve corrispondere al valore di Irp-IoStatus.Status> impostato dal driver che ha completato l'IRP.

  • Quando IoCallDriver restituisce STATUS_PENDING, la routine di invio deve restituire anche STATUS_PENDING, a meno che non attenda la routine di completamento per segnalare un evento.

  • Quando la routine di invio inserisce l'IRP in una coda di lavoro per l'elaborazione successiva, deve contrassegnare l'IRP in sospeso e restituire STATUS_PENDING.

  • Quando la routine di invio imposta una routine di completamento che potrebbe inviare l'IRP a una coda di lavoro per l'elaborazione successiva, deve contrassegnare l'IRP in sospeso e restituire STATUS_PENDING.

  • Una routine di invio che contrassegna un'istanza di IRP in sospeso deve restituire STATUS_PENDING.

  • Le operazioni di oplock non possono essere pennate (pubblicate in una coda di lavoro) e le routine di invio non possono restituire STATUS_PENDING per loro.

Vincoli per la registrazione di IRP in una coda di lavoro

  • Se una routine di invio invia indirizzi IP a una coda di lavoro, deve chiamare IoMarkIrpPending prima di pubblicare ogni IRP nella coda di lavoro. In caso contrario, l'IRP potrebbe essere dequeued, completato da un'altra routine driver e liberato dal sistema prima che la chiamata a IoMarkIrpPending si verifichi, causando così un arresto anomalo.