Funzione FsRtlCancellableWaitForSingleObject (ntifs.h)
La routine FsRtlCancellableWaitForSingleObject esegue un'operazione di attesa annullabile (un'attesa che può essere terminata) su un oggetto dispatcher.
Sintassi
NTSTATUS FsRtlCancellableWaitForSingleObject(
[in] PVOID Object,
[in, optional] PLARGE_INTEGER Timeout,
[in, optional] PIRP Irp
);
Parametri
[in] Object
Puntatore a un oggetto dispatcher inizializzato (evento, mutex, semaforo, thread o timer) per il quale il chiamante fornisce la risorsa di archiviazione.
[in, optional] Timeout
Puntatore a un valore di timeout facoltativo. Questo parametro specifica il tempo assoluto o relativo, in unità di 100 nanosecondi, in cui l'attesa deve essere completata.
Se Timeout punta a un valore zero (ovvero *Timeout == 0), la routine restituisce senza attendere. Se il chiamante fornisce un puntatore NULL (ovvero Timeout == NULL), la routine attende per un periodo illimitato fino a quando l'oggetto non viene impostato sullo stato segnalato.
Un valore di timeout positivo specifica un'ora assoluta, rispetto al 1° gennaio 1601. Un valore timeout negativo specifica un intervallo relativo all'ora corrente. Le ore di scadenza assolute tengono traccia delle modifiche apportate all'ora di sistema. Le scadenze relative non sono interessate dalle modifiche all'ora di sistema.
Se si specifica Timeout , l'attesa verrà soddisfatta automaticamente se l'oggetto non è impostato sullo stato segnalato alla scadenza dell'intervallo specificato.
Un valore di timeout pari a zero (ovvero *Timeout == 0) consente di testare un set di condizioni di attesa e di eseguire in modo condizionale eventuali azioni aggiuntive se l'attesa può essere soddisfatta immediatamente, come nell'acquisizione di un mutex.
[in, optional] Irp
Puntatore all'IRP originale che corrisponde all'operazione di I/O rilasciata dall'utente e che può essere annullata dall'utente. Il chiamante deve assicurarsi che L'IRP rimanga valido per la durata di questa routine e che l'IRP non abbia un set di routine di annullamento( ad esempio, IoSetCancelRoutine non deve essere stato chiamato su IRP). Si noti che l'IRP deve essere mantenuto dal chiamante, non può essere passato a un driver di livello inferiore.
Valore restituito
FsRtlCancellableWaitForSingleObject può restituire uno dei valori seguenti:
Codice restituito | Descrizione |
---|---|
STATUS_SUCCESS | L'oggetto dispatcher specificato dal parametro Object ha soddisfatto l'attesa. |
STATUS_TIMEOUT | Si è verificato un timeout prima che l'oggetto sia stato impostato su uno stato segnalato. Questo valore può essere restituito quando non è possibile soddisfare immediatamente il set specificato di condizioni di attesa e Timeout è impostato su zero. |
STATUS_ABANDONED_WAIT_0 | Il chiamante ha tentato di attendere un mutex abbandonato. |
STATUS_CANCELLED | L'attesa è stata interrotta da una richiesta di annullamento in sospeso sul provider di risorse IRP specificato. Si noti che questo valore viene restituito solo se un IRP valido viene passato a FsRtl DisabilitableWaitForSingleObject e l'IRP è stato annullato da CancelSynchronousIo. |
STATUS_THREAD_IS_TERMINATING | L'attesa è stata interrotta perché il thread è stato terminato da un'applicazione o dall'utente. |
Il valore restituito indica solo lo stato dell'attesa. Se applicabile, lo stato effettivo della richiesta di I/O deve essere ottenuto direttamente da un altro IRP generato nel processo di gestione dell'IRP in modalità utente originale.
Si noti che la macro NT_SUCCESS restituisce FALSE ("errore") per i valori di stato STATUS_CANCELLED e STATUS_THREAD_IS_TERMINATING e TRUE ("operazione riuscita") per tutti gli altri valori di stato.
Commenti
La routine FsRtlCancellableWaitForSingleObject esegue un'operazione di attesa annullabile su un oggetto dispatcher. Se il thread viene terminato dall'utente o dall'applicazione o se CancelSynchronousIo invia una richiesta di annullamento su un IRP (IRP sincrono) threaded associato al thread, l'attesa viene annullata.
La routine FsRtl DisabilitableWaitForSingleObject è stata progettata per il supporto delle linee guida per il completamento/annullamento di I/O a partire da Windows Vista. L'obiettivo di queste linee guida è consentire agli utenti (o alle applicazioni) di terminare rapidamente le applicazioni. A sua volta, richiede che le applicazioni abbiano la possibilità di terminare rapidamente i thread che eseguono operazioni di I/O e qualsiasi operazione di I/O corrente. Questa routine consente ai thread utente di bloccare (ovvero attendere) nel kernel per il completamento di I/O, un oggetto dispatcher o una variabile di sincronizzazione in modo da consentire l'annullamento dell'attesa. Questa routine consente inoltre di terminare l'attesa del thread se il thread viene terminato da un utente o da un'applicazione.
Ad esempio, un redirector potrebbe dover creare uno o più provider di integrazione secondari per elaborare un IRP in modalità utente e attendere in modo sincrono il completamento dei runtime di integrazione secondari. Un modo per eseguire questa operazione consiste nel configurare un evento che verrà segnalato dalla routine di completamento dell'IRP secondario e quindi attendere che l'evento venga segnalato. Quindi, per eseguire un'operazione di attesa annullabile, FsRtl DisabilitableWaitForSingleObject viene chiamato passaggio dell'evento associato all'IRP secondario, nonché l'IRP in modalità utente originale. L'attesa del thread per la segnalazione dell'evento viene annullata se si verifica un evento di terminazione in sospeso o se l'IRP in modalità utente originale viene annullato.
Si noti che l'interruzione dell'attesa non annulla automaticamente tutte le operazioni di I/O rilasciate dal chiamante, che devono essere gestite separatamente dal chiamante.
Una considerazione speciale si applica quando il parametro Object passato a FsRtl DisabilitableWaitForSingleObject è un mutex. Se l'oggetto dispatcher in attesa è un mutex, il recapito APC corrisponde a quello di tutti gli altri oggetti dispatcher durante l'attesa. Tuttavia, dopo che FsRtl DisabilitableWaitForSingleObjects restituisce con STATUS_SUCCESS e il thread contiene effettivamente il mutex, vengono recapitate solo API speciali in modalità kernel. Il recapito di tutti gli altri APN, sia in modalità kernel che in modalità utente, è disabilitato. Questa restrizione per il recapito delle API persiste fino al rilascio del mutex.
Un mutex può essere acquisito in modo ricorsivo solo volte MINLONG. Se questo limite viene superato, la routine genera un'eccezione STATUS_MUTANT_LIMIT_EXCEEDED.
Di seguito è riportato un esempio di come usare FsRtlCancellableWaitForSingleObject a supporto delle linee guida per il completamento/annullamento di I/O.
//
// sample calling routine
//
NTSTATUS ProcessIrpFromUserMode( PIRP pOriginalIrp, ... )
{
NTSTATUS Status;
NTSTATUS WaitStatus;
KEVENT Event;
LARGE_INTEGERTimeout;
PIRP pAdditionalIrp;
BOOLEAN Cancelled;
//
// Allocate the additional IRP here:
//
KeInitializeEvent( &Event,
SynchronizationEvent,
FALSE );
pContext->pEvent = &Event; // Driver specific context structure.
IoSetCompletionRoutine( pAdditionalIrp,
FunctionCompletionRoutine,
pContext,
TRUE,
TRUE,
TRUE);
Status = IoCallDriver( pDeviceObject, pAdditionalIrp );
if (Status == STATUS_PENDING) {
//
// Initialize Timeout variable here. If no timeout is needed, pass NULL for
// that parameter instead.
//
WaitStatus = FsRtlCancellableWaitForSingleObject( &Event,
&Timeout,
pOriginalIrp );
if ((WaitStatus == STATUS_CANCELLED) || (WaitStatus == STATUS_THREAD_IS_TERMINATING)) {
//
// Thread is terminating. IRP was canceled.
// Cancel the additional IRP passed to the lower level driver, cleanup, and return quickly.
//
Cancelled = IoCancelIrp( pAdditionalIrp );
if (!Cancelled || KeReadStateEvent( &Event ) == 0) {
//
// Wait for the IRP to complete.
// If cancel was posted successfully on the IRP, this shouldn't take a long time.
//
(VOID) KeWaitForSingleObject( &Event,
Executive,
KernelMode, // WaitMode
FALSE, // Alertable
(PLARGE_INTEGER) NULL );
}
} else if (WaitStatus == STATUS_TIMEOUT) {
//
// Wait timed out. The IRP was canceled or the API
// waited for the I/O to complete.
//
} else {
ASSERT( WaitStatus == STATUS_SUCCESS );
//
// The wait completed without timeout
// or being canceled.
//
}
}
//
// IRP is valid and needs to be handled here.
// pAdditionalIrp->IoStatus.Status contains the status of the IRP.
// Finally, pOriginal IRP needs to be completed appropriately as well.
//
}
//
// Sample completion routine:
//
NTSTATUS
FunctionCompletionRoutine(
IN PDEVICE_OBJECT pDeviceObject,
INOUT PIRP pAdditionalIrp,
IN PVOID pContext)
{
if (pAdditionalIrp->PendingReturned) {
KeSetEvent( pContext->pEvent, 0, FALSE );
}
//
// Discontinue I/O completion.
// Dispatch routine will deal with IRP.
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
FsRtlCancellableWaitForSingleObject deve essere chiamato in IRQL PASSIVE_LEVEL se il parametro Irp facoltativo punta a un IRP valido. Se il parametro Irp non viene usato, la routine può essere chiamata in IRQL minore o uguale a APC_LEVEL. Le API del kernel normali possono essere disabilitate dal chiamante, se necessario, chiamando le routine KeEnterCriticalRegion o FsRtlEnterFileSystem . Tuttavia, le API speciali del kernel non devono essere disabilitate.
FsRtlCancellableWaitForSingleObject eseguirà l'asserzione nelle build di debug se IRQL è maggiore o uguale a APC_LEVEL e il parametro Irp facoltativo punta a un IRP valido.
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows Vista |
Piattaforma di destinazione | Universale |
Intestazione | ntifs.h (include Ntifs.h) |
Libreria | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | Vedere la sezione Osservazioni. |
Regole di conformità DDI | HwStorPortProhibitedDDDIs(storport), SpNoWait(storport) |