PreviousMode

Quando um aplicativo de modo de usuário chama a versão Nt ou Zw de uma rotina de serviços do sistema nativo, o mecanismo de chamada do sistema intercepta o thread de chamada para o modo kernel. Para indicar que os valores de parâmetro originados no modo de usuário, o manipulador de interceptidade para a chamada do sistema define o campo PreviousMode no objeto de thread do chamador como UserMode. A rotina de serviços do sistema nativo verifica o campo PreviousMode do thread de chamada para determinar se os parâmetros são de uma origem de modo de usuário.

Se um driver de modo kernel chamar uma rotina de serviços do sistema nativo e passar valores de parâmetro para a rotina que são de uma origem de modo kernel, o driver deverá garantir que o campo PreviousMode no objeto de thread atual seja definido como KernelMode.

Um driver de modo kernel pode ser executado no contexto de um thread arbitrário e o campo PreviousMode desse thread pode ser definido como UserMode. Nessa situação, um driver de modo kernel pode chamar a versão Zw de uma rotina de serviços do sistema nativo para informar a rotina de que os valores de parâmetro são de uma fonte de modo kernel confiável. A chamada Zw vai para uma função de wrapper fino que substitui o valor PreviousMode no objeto de thread atual. A função wrapper define PreviousMode como KernelMode e chama a versão Nt da rotina. No retorno da versão Nt da rotina, a função wrapper restaura o valor Original previousMode do objeto de thread e retorna.

Um driver de modo kernel pode chamar diretamente a versão Nt de uma rotina de serviços do sistema nativo. Quando um driver de modo kernel processa uma solicitação de E/S que pode ser originada no modo de usuário ou no modo kernel, o driver pode chamar a versão Nt da rotina para que o valor PreviousMode do thread atual permaneça inalterado durante a chamada. A rotina NtXxx verifica o valor PreviousMode do thread de chamada para determinar se os valores de parâmetro são de um aplicativo de modo de usuário ou um componente de modo kernel e os trata de acordo.

Um erro poderá ocorrer se um driver de modo kernel chamar uma rotina NtXxx e o valor PreviousMode no objeto de thread atual não indicar com precisão se os valores de parâmetro são de um modo de usuário ou de uma fonte de modo kernel.

Por exemplo, suponha que um driver de modo kernel está em execução no contexto de um thread arbitrário e que o valor PreviousMode desse thread está definido como UserMode. Se o driver passar um alça de arquivo de modo kernel para a rotina NtClose , essa rotina verificará o valor PreviousMode e decidirá que o handle deve ser um controle de modo de usuário. Quando NtClose não encontra o handle na tabela de alça do modo de usuário, ele retorna o código STATUS_INVALID_HANDLE erro. Enquanto isso, o driver vaza o alça do modo kernel, que nunca foi fechado.

Para outro exemplo, se os parâmetros de uma rotina NtXxx incluírem um buffer de entrada ou saída e se PreviousModeUserMode = , a rotina chamará a rotina ProbeForRead ou ProbeForWrite para validar o buffer. Se o buffer foi alocado na memória do sistema em vez de na memória do modo de usuário, a rotina ProbeForXxx gera uma exceção e a rotina NtXxx retorna o código STATUS_ACCESS_VIOLATION erro.

Se for necessário, um driver poderá chamar a rotina ExGetPreviousMode para obter o valor PreviousMode do objeto de thread atual. Ou o driver pode ler o campo RequestorMode da estrutura IRP que descreve a operação de E/S solicitada. O campo RequestorMode contém uma cópia do valor PreviousMode do thread que solicitou a operação.