PreviousMode

Quando un'applicazione in modalità utente chiama la versione Nt o Zw di una routine dei servizi di sistema nativa, il meccanismo di chiamata trappola il thread chiamante alla modalità kernel. Per indicare che i valori dei parametri hanno avuto origine in modalità utente, il gestore trap per la chiamata di sistema imposta il campo PreviousModenell'oggetto thread del chiamante a UserMode. La routine dei servizi di sistema nativi controlla il campo PreviousMode del thread chiamante per determinare se i parametri provengono da un'origine in modalità utente.

Se un driver in modalità kernel chiama una routine dei servizi di sistema nativa e passa i valori dei parametri alla routine proveniente da un'origine in modalità kernel, il driver deve assicurarsi che il campo PreviousMode nell'oggetto thread corrente sia impostato su KernelMode.

Un driver in modalità kernel può essere eseguito nel contesto di un thread arbitrario e il campo PreviousMode di questo thread potrebbe essere impostato su UserMode. In questa situazione, un driver in modalità kernel può chiamare la versione Zw di una routine dei servizi di sistema nativa per informare la routine che i valori dei parametri provengono da un'origine attendibile e in modalità kernel. La chiamata Zw passa a una funzione wrapper sottile che esegue l'override del valore PreviousMode nell'oggetto thread corrente. La funzione wrapper imposta PreviousMode su KernelMode e chiama la versione Nt della routine. Al ritorno dalla versione Nt della routine, la funzione wrapper ripristina il valore precedente PreviousMode dell'oggetto thread e restituisce.

Un driver in modalità kernel può chiamare direttamente la versione Nt di una routine dei servizi di sistema nativa. Quando un driver in modalità kernel elabora una richiesta di I/O che può avere origine in modalità utente o in modalità kernel, il driver può chiamare la versione Nt della routine in modo che il valore PreviousMode del thread corrente rimanga invariato durante la chiamata. La routine NtXxx controlla il valore PreviousMode del thread chiamante per determinare se i valori dei parametri provengono da un'applicazione in modalità utente o da un componente in modalità kernel e li tratta di conseguenza.

Un errore può verificarsi se un driver in modalità kernel chiama una routine NtXxx e il valore PreviousMode nell'oggetto thread corrente non indica in modo accurato se i valori dei parametri provengono da un'origine in modalità utente o in modalità kernel.

Si supponga, ad esempio, che un driver in modalità kernel sia in esecuzione nel contesto di un thread arbitrario e che il valore PreviousMode per questo thread sia impostato su UserMode. Se il driver passa un handle di file in modalità kernel alla routine NtClose , questa routine controlla il valore PreviousMode e decide che l'handle deve essere un handle in modalità utente. Quando NtClose non trova l'handle nella tabella handle in modalità utente, restituisce il codice di errore STATUS_INVALID_HANDLE. Nel frattempo, il driver perde l'handle in modalità kernel, che non è mai stato chiuso.

Per un altro esempio, se i parametri per una routine NtXxx includono un buffer di input o di output e sePreviousMode UserMode = , la routine chiama la routine ProbeForRead o ProbeForWrite per convalidare il buffer. Se il buffer è stato allocato nella memoria di sistema anziché nella memoria in modalità utente, la routine ProbeForXxx genera un'eccezione e la routine NtXxx restituisce il codice di errore STATUS_ACCESS_VIOLATION.

Se necessario, un driver può chiamare la routine ExGetPreviousMode per ottenere il valore PreviousMode dall'oggetto thread corrente. In alternativa, il driver può leggere il campo RequestorMode dalla struttura IRP che descrive l'operazione di I/O richiesta. Il campo RequestorMode contiene una copia del valore PreviousMode dal thread che ha richiesto l'operazione.