Compartilhar via


Acessando buffers de usuário em uma rotina de retorno de chamada de pré-operação

A rotina de retorno de chamada de pré-operação de um driver de minifiltro deve tratar um buffer em uma operação de E/S baseada em IRP da seguinte maneira:

  • Verifique se existe um MDL para o buffer. O ponteiro MDL pode ser encontrado no parâmetro MdlAddress ou OutputMdlAddress no FLT_PARAMETERS da operação. Os drivers de minifiltro podem chamar FltDecodeParameters para consultar o ponteiro MDL.

    Um método para obter um MDL válido é procurar o sinalizador IRP_MN_MDL no membro MinorFunction do bloco de parâmetros de E/S, FLT_IO_PARAMETER_BLOCK, nos dados de retorno de chamada. O exemplo a seguir mostra como marcar para o sinalizador IRP_MN_MDL.

    NTSTATUS status;
    PMDL *ReadMdl = NULL;
    PVOID ReadAddress = NULL;
    
    if (FlagOn(CallbackData->Iopb->MinorFunction, IRP_MN_MDL))
    {
        ReadMdl = &CallbackData->Iopb->Parameters.Read.MdlAddress;
    }
    

    No entanto, o sinalizador IRP_MN_MDL pode ser definido apenas para operações de leitura e gravação. É melhor usar FltDecodeParameters para recuperar um MDL, pois a rotina verifica se há um MDL válido para qualquer operação. No exemplo a seguir, somente o parâmetro MDL é retornado se válido.

    NTSTATUS status;
    PMDL *ReadMdl = NULL;
    PVOID ReadAddress = NULL;
    
    status = FltDecodeParameters(CallbackData, &ReadMdl, NULL, NULL, NULL);
    
  • Se existir um MDL para o buffer, chame MmGetSystemAddressForMdlSafe para obter o endereço do sistema para o buffer e, em seguida, use esse endereço para acessar o buffer.

    Continuando do exemplo anterior, o código a seguir obtém o endereço do sistema.

    if (*ReadMdl != NULL)
    {
        ReadAddress = MmGetSystemAddressForMdlSafe(*ReadMdl, NormalPagePriority);
        if (ReadAddress == NULL)
        {
            CallbackData->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            CallbackData->IoStatus.Information = 0;
        }
    }
    
  • Se não houver MDL para o buffer, use o endereço de buffer para acessar o buffer. Para garantir que um endereço de buffer de espaço do usuário seja válido, o driver de minifiltro deve usar uma rotina como ProbeForRead ou ProbeForWrite, incluindo todas as referências de buffer em try/, exceto blocos.

Uma rotina de retorno de chamada de pré-operação deve tratar um buffer em uma operação de E/S rápida da seguinte maneira:

  • Use o endereço do buffer para acessar o buffer (porque uma operação de E/S rápida não pode ter um MDL).

  • Para garantir que um endereço de buffer de espaço do usuário seja válido, o driver de minifiltro deve usar uma rotina como ProbeForRead ou ProbeForWrite, incluindo todas as referências de buffer em try/, exceto blocos.

Para operações que podem ser de E/S rápidas ou baseadas em IRP, todas as referências de buffer devem ser colocadas entre tentativas/, exceto blocos. Embora você não precise incluir essas referências para operações baseadas em IRP que usam E/S em buffer, os blocos try/except são uma precaução segura.