Suporte a clientes Kernel-Mode em drivers UMDF 1.x

Aviso

O UMDF 2 é a versão mais recente do UMDF e substitui o UMDF 1. Todos os novos drivers UMDF devem ser gravados usando UMDF 2. Nenhum novo recurso está sendo adicionado ao UMDF 1 e há suporte limitado para UMDF 1 em versões mais recentes do Windows 10. Drivers universais do Windows devem usar UMDF 2.

Os exemplos umdf 1 arquivados podem ser encontrados no Windows 11, versão 22H2 – Atualização de exemplos de driver de maio de 2022.

Para obter mais informações, consulte Introdução com UMDF.

As versões 1.9 e posteriores do UMDF permitem que os drivers UMDF ofereçam suporte a clientes no modo kernel. Um cliente no modo kernel pode ser um dos seguintes:

  • Um driver no modo kernel que existe acima de um driver UMDF na pilha de driver de um dispositivo.

  • Um driver de modo kernel para uma pilha de dispositivos, que dá suporte a um dispositivo, abre um identificador para outro dispositivo e a pilha de driver do último dispositivo contém um driver UMDF.

Em outras palavras, um driver UMDF que dá suporte a clientes no modo kernel pode receber solicitações de E/S de um driver no modo kernel. O driver do modo kernel pode encaminhar solicitações de E/S recebidas de um aplicativo no modo de usuário ou pode criar novas solicitações de E/S e enviá-las para o driver de modo de usuário.

Para determinar se o driver UMDF deve dar suporte a clientes no modo kernel, você deve entender a pilha de driver à qual o driver será adicionado e onde, nessa pilha, o driver residirá. Você também deve determinar se um driver de outra pilha pode enviar solicitações de E/S para o dispositivo do driver.

O driver deverá dar suporte a clientes no modo kernel se:

  • Um driver no modo kernel pode estar localizado diretamente acima do driver UMDF em uma pilha de driver. Por exemplo, um driver de filtro no modo kernel pode residir diretamente acima de um driver de função baseado em UMDF.

  • Um driver no modo kernel de outra pilha pode enviar solicitações de E/S para o dispositivo do driver. Por exemplo, seu driver pode criar um link simbólico que um driver de modo kernel em outra pilha pode usar para abrir um identificador para o dispositivo do driver. O driver do modo kernel pode enviar solicitações de E/S para o dispositivo.

Como dar suporte a clientes no modo kernel em um driver UMDF

Um driver UMDF poderá receber solicitações de E/S de um driver no modo kernel somente se o driver UMDF tiver habilitado o suporte para clientes no modo kernel. Além disso, se uma instalação de dispositivo tentar carregar drivers no modo kernel acima de um driver UMDF na pilha de driver do dispositivo, a estrutura permitirá que os drivers carreguem somente se o driver UMDF tiver habilitado o suporte para clientes no modo kernel.

Para habilitar o suporte de um driver UMDF para clientes no modo kernel, o arquivo INF do driver UMDF deve incluir uma diretiva UmdfKernelModeClientPolicy em seu INF DDInstall. Seção WDF . Se o arquivo INF do driver UMDF não incluir essa diretiva, o UMDF não permitirá que um driver de modo kernel instalado acima do driver UMDF seja executado.

A estrutura fornece dois métodos úteis para drivers que dão suporte a clientes no modo kernel. Um driver pode chamar o método IWDFIoRequest2::GetRequestorMode para determinar se uma solicitação de E/S veio do modo kernel ou do modo de usuário. Se a solicitação de E/S veio do modo de usuário, o driver pode chamar IWDFIoRequest2::IsFromUserModeDriver para determinar se a solicitação veio de um aplicativo ou de outro driver de modo de usuário.

Restrições em drivers no modo kernel

Um driver UMDF poderá processar solicitações de E/S de um driver no modo kernel somente se o driver do modo kernel atender aos seguintes requisitos:

  • O driver de modo kernel deve estar em execução em IRQL = PASSIVE_LEVEL ao enviar a solicitação de E/S.

  • A menos que o driver tenha definido a diretiva INF UmdfFileObjectPolicy como AllowNullAndUnknownFileObjects, cada solicitação de E/S que um driver de modo kernel envia a um driver de modo de usuário deve ter um objeto de arquivo associado. A estrutura deve ter sido notificada anteriormente de que o gerenciador de E/S criou o objeto de arquivo. (Essa notificação faz com que a estrutura chame a função de retorno de chamada IQueueCallbackCreate::OnCreateFile do driver de modo de usuário, mas essa função de retorno de chamada é opcional.)

  • A solicitação de E/S não pode conter um código de função IRP_MJ_INTERNAL_DEVICE_CONTROL .

  • Os buffers da solicitação de E/S não devem conter ponteiros para informações adicionais, pois o driver de modo de usuário não pode desreferenciar os ponteiros.

  • Se a solicitação de E/S contiver um código de controle de E/S que especifica o método de acesso ao buffer "nenhum", o driver de modo kernel deverá enviar a solicitação de E/S no contexto de processo do aplicativo que criou a solicitação de E/S. Para obter mais informações sobre como dar suporte ao método "nem" em um driver de base UMDF, consulte Using Neither Buffered I/O nem Direct I/O in UMDF Drivers.

  • O driver UMDF pode modificar os dados de saída de uma solicitação de E/S, no modo de usuário. Portanto, o driver do modo kernel deve validar todos os dados de saída recebidos do driver de modo de usuário.

  • O cliente do modo kernel normalmente deve validar o valor informações que um driver UMDF passa para IWDFIoRequest::CompleteWithInformation. Se o cliente for um driver KMDF, ele poderá chamar WdfRequestGetCompletionParams para obter essas informações em uma estrutura IO_STATUS_BLOCK.

    Normalmente, a estrutura não valida o valor de informações que um driver UMDF passa para IWDFIoRequest::CompleteWithInformation. (Esse parâmetro geralmente especifica o número de bytes transferidos.) A estrutura valida o valor das informações somente para buffers de saída e somente para o método de acesso a dados de E/S em buffer . (Por exemplo, a estrutura verifica se o número de bytes transferidos não excede o tamanho do buffer de saída de uma operação de leitura, se o método de acesso tiver E/S em buffer.)

Manipulando valores de retorno status em um driver UMDF 1.x

Passar valores de retorno status do modo de usuário para o modo kernel requer atenção especial, da seguinte maneira:

  • Os drivers UMDF versão 1 normalmente recebem valores retornados do tipo HRESULT, enquanto os drivers de modo kernel baseados em KMDF e WDM normalmente recebem valores do tipo NTSTATUS. Se um UMDF 1. X Driver conclui uma solicitação de E/S e, se o driver tiver um cliente no modo kernel, a chamada do driver para IWDFIoRequest::Complete ou IWDFIoRequest::CompleteWithInformation deverá especificar um valor HRESULT que o driver gera de um valor NTSTATUS. Em geral, UMDF 1. X drivers devem usar a macro HRESULT_FROM_NT (definida em Winerror.h) para retornar status para um cliente no modo kernel. O exemplo a seguir mostra como usar essa macro ao concluir uma solicitação.

    hr = HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW)
    request->Complete(HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW);
    return hr;
    

    Para retornar um valor HRESULT específico para um cliente no modo kernel, os seguintes retornos de chamada devem usar a macro HRESULT_FROM_NT:

    Para usar os valores NTSTATUS definidos em ntstatus.h, um UMDF 1. x driver deve incluir essas duas linhas antes de incluir quaisquer cabeçalhos adicionais.

    #define UMDF_USING_NTSTATUS
    #include <ntstatus.h>
    

    Não use a macro HRESULT_FROM_NT para converter STATUS_SUCCESS de um valor NTSTATUS em um valor HRESULT. Basta retornar S_OK, conforme mostrado no exemplo a seguir.

    request->Complete(S_OK);
    
  • A estrutura conclui algumas solicitações de E/S em nome de drivers UMDF. Às vezes, a estrutura não converte valores retornados do tipo HRESULT em valores NTSTATUS equivalentes, portanto, a estrutura pode passar um status de conclusão do tipo HRESULT para um cliente no modo kernel.

    Devido a essa situação, os clientes do modo kernel não devem usar a macro NT_ERROR ao testar a conclusão de uma solicitação de E/S status, pois a macro NT_ERROR não retorna TRUE para valores de erro HRESULT. Os drivers no modo kernel devem usar a macro NT_SUCCESS ao testar a conclusão de uma solicitação de E/S status.

Suporte ao cliente no modo kernel em versões anteriores do UMDF

Para versões UMDF anteriores à versão 1.9, o arquivo INF de um driver pode incluir uma diretiva INF AddReg para criar um valor de registro UpperDriverOk de tamanho REG_DWORD sob a subchave WUDF da chave de hardware do dispositivo.

Se o valor do Registro UpperDriverOk for definido como um número diferente de zero, a estrutura permitirá que os drivers do modo kernel sejam carregados acima do driver de modo de usuário. Os drivers de modo kernel podem encaminhar solicitações de E/S de aplicativos de modo de usuário para o driver UMDF, mas os drivers de modo kernel não podem enviar solicitações de E/S criadas no modo kernel para o driver UMDF.

Para as versões 1.9 e posteriores do UMDF, o valor do registro UpperDriverOk é obsoleto e tem suporte apenas para drivers existentes. Novos drivers devem usar a diretiva UmdfKernelModeClientPolicy .