Compartir a través de


Acceso a los búferes de usuario en una rutina de devolución de llamada de preoperación

Una rutina de devolución de llamada de preoperación del controlador minifiltro debe tratar un búfer en una operación de E/S basada en IRP de la siguiente manera:

  • Compruebe si existe una MDL para el búfer. El puntero MDL se puede encontrar en el parámetro MdlAddress o OutputMdlAddress del FLT_PARAMETERS para la operación. Los controladores de minifiltro pueden llamar a FltDecodeParameters para consultar el puntero MDL.

    Un método para obtener una MDL válida es buscar la marca de IRP_MN_MDL en el miembro MinorFunction del bloque de parámetros de E/S, FLT_IO_PARAMETER_BLOCK, en los datos de devolución de llamada. En el ejemplo siguiente se muestra cómo comprobar la marca 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;
    }
    

    Sin embargo, la marca de IRP_MN_MDL solo se puede establecer para las operaciones de lectura y escritura. Es mejor usar FltDecodeParameters para recuperar una MDL, ya que la rutina comprueba si hay una MDL válida para cualquier operación. En el ejemplo siguiente, solo se devuelve el parámetro MDL si es válido.

    NTSTATUS status;
    PMDL *ReadMdl = NULL;
    PVOID ReadAddress = NULL;
    
    status = FltDecodeParameters(CallbackData, &ReadMdl, NULL, NULL, NULL);
    
  • Si existe una MDL para el búfer, llame a MmGetSystemAddressForMdlSafe para obtener la dirección del sistema del búfer y, a continuación, use esta dirección para acceder al búfer.

    Siguiendo con el ejemplo anterior, el código siguiente obtiene la dirección del sistema.

    if (*ReadMdl != NULL)
    {
        ReadAddress = MmGetSystemAddressForMdlSafe(*ReadMdl, NormalPagePriority);
        if (ReadAddress == NULL)
        {
            CallbackData->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            CallbackData->IoStatus.Information = 0;
        }
    }
    
  • Si no hay ninguna MDL para el búfer, use la dirección del búfer para acceder al búfer. Para asegurarse de que una dirección de búfer de espacio de usuario es válida, el controlador de minifiltro debe usar una rutina como ProbeForRead o ProbeForWrite, encerrando todas las referencias de búfer en try/excepto bloques.

Una rutina de devolución de llamada de preoperación debe tratar un búfer en una operación de E/S rápida como se indica a continuación:

  • Use la dirección del búfer para acceder al búfer (porque una operación de E/S rápida no puede tener una MDL).

  • Para asegurarse de que una dirección de búfer de espacio de usuario es válida, el controlador de minifiltro debe usar una rutina como ProbeForRead o ProbeForWrite, encerrando todas las referencias de búfer en try/excepto bloques.

En el caso de las operaciones que pueden estar basadas en E/S rápidas o IRP, todas las referencias de búfer deben incluirse en try/excepto bloques. Aunque no es necesario incluir estas referencias para las operaciones basadas en IRP que usan E/S almacenadas en búfer, el intento/excepto los bloques son una precaución segura.