PreviousMode

Quando um aplicativo de modo de usuário chama a versão Nt ou Zw de uma rotina de serviços de 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 se originaram no modo de usuário, o manipulador de interceptação para a chamada do sistema define o campo PreviousMode no objeto 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 do 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 no modo kernel, o driver deverá verificar se o campo PreviousMode no objeto de thread atual está 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 confiável no modo kernel. A chamada Zw vai para uma função wrapper fina 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 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 se originar 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 não ativado 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 de um componente de modo kernel e os trata adequadamente.

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 origem no modo kernel.

Por exemplo, suponha que um driver de modo kernel esteja em execução no contexto de um thread arbitrário e que o valor PreviousMode para esse thread esteja definido como UserMode. Se o driver passar um identificador de arquivo no modo kernel para a rotina NtClose , essa rotina verificará o valor PreviousMode e decidirá que o identificador deve ser um identificador de modo de usuário. Quando o NtClose não encontra o identificador na tabela de identificadores do modo de usuário, ele retorna o código de erro STATUS_INVALID_HANDLE. Enquanto isso, o driver vaza o identificador 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 PreviousMode = UserMode, 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 de erro STATUS_ACCESS_VIOLATION.

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.