Поделиться через


Доступ к пользовательским буферам в процедуре обратного вызова перед выполнением операции

Подпрограмма обратного вызова драйвера минифильтра перед операцией должна обрабатывать буфер в операции ввода-вывода на основе IRP следующим образом:

  • Проверьте, существует ли MDL для буфера. Указатель MDL можно найти в параметре MdlAddress или OutputMdlAddress в FLT_PARAMETERS для операции. Драйверы мини-фильтра могут вызывать FltDecodeParameters для запроса указателя MDL.

    Одним из способов получения допустимого MDL является поиск флага IRP_MN_MDL в элементе MinorFunction блока параметров ввода-вывода FLT_IO_PARAMETER_BLOCK в данных обратного вызова. В следующем примере показано, как проверка для флага 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;
    }
    

    Однако флаг IRP_MN_MDL можно задать только для операций чтения и записи. Лучше всего использовать FltDecodeParameters для получения MDL, так как подпрограмма проверяет допустимое значение MDL для любой операции. В следующем примере возвращается только параметр MDL, если он действителен.

    NTSTATUS status;
    PMDL *ReadMdl = NULL;
    PVOID ReadAddress = NULL;
    
    status = FltDecodeParameters(CallbackData, &ReadMdl, NULL, NULL, NULL);
    
  • Если для буфера существует MDL, вызовите MmGetSystemAddressForMdlSafe , чтобы получить системный адрес буфера, а затем используйте этот адрес для доступа к буферу.

    Как и в предыдущем примере, следующий код получает системный адрес.

    if (*ReadMdl != NULL)
    {
        ReadAddress = MmGetSystemAddressForMdlSafe(*ReadMdl, NormalPagePriority);
        if (ReadAddress == NULL)
        {
            CallbackData->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            CallbackData->IoStatus.Information = 0;
        }
    }
    
  • Если для буфера отсутствует MDL, используйте адрес буфера для доступа к буферу. Чтобы убедиться, что адрес буфера пользовательского пространства является допустимым, драйвер минифильтра должен использовать подпрограмму , например ProbeForRead или ProbeForWrite, заключая все ссылки на буфер в try/, кроме блоков.

Подпрограмма обратного вызова перед операцией должна обрабатывать буфер в быстрой операции ввода-вывода следующим образом:

  • Используйте адрес буфера для доступа к буферу (так как быстрая операция ввода-вывода не может иметь MDL).

  • Чтобы убедиться, что адрес буфера пользовательского пространства является допустимым, драйвер минифильтра должен использовать подпрограмму , например ProbeForRead или ProbeForWrite, заключая все ссылки на буфер в try/, кроме блоков.

Для операций, которые могут быть быстрыми операциями ввода-вывода или IRP, все ссылки на буферы должны быть заключены в try/, за исключением блоков. Хотя вам не нужно заключать эти ссылки для операций на основе IRP, использующих буферизирующиеся операции ввода-вывода, блоки try/except являются безопасной мерой предосторожности.