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.