IRP_MJ_WRITE (controladores de filtro y sistema de archivos)
Cuándo se envía
El Administrador de E/S o un controlador del sistema de archivos envía la solicitud IRP_MJ_WRITE. Esta solicitud se puede enviar, por ejemplo, cuando una aplicación en modo de usuario llama a una función Win32 como WriteFile o cuando un componente en modo kernel llama a ZwWriteFile.
Operación: controladores del sistema de archivos
El controlador del sistema de archivos debe extraer y descodificar el objeto de archivo para determinar los parámetros y el código de función secundaria.
En el caso de las solicitudes de escritura de MDL, el sistema de archivos debe comprobar el código de función secundaria para determinar qué operación se solicita. A continuación se muestran los códigos de función secundaria válidos, que solo se pueden usar para E/S de archivos almacenados en caché:
- IRP_MN_COMPLETE
- IRP_MN_COMPLETE_MDL
- IRP_MN_COMPLETE_MDL_DPC
- IRP_MN_COMPRESSED
- IRP_MN_DPC
- IRP_MN_MDL
- IRP_MN_MDL_DPC
- IRP_MN_NORMAL
Para obtener más información sobre cómo controlar este IRP, estudie el ejemplo FASTFAT que se incluye en el Kit para controladores de Windows (WDK).
Operación: controladores de filtro del sistema de archivos heredado
El controlador de filtro debe realizar cualquier procesamiento necesario y, en función de la naturaleza del filtro, realizar una de las siguientes acciones:
- Completar o generar un error en IRP, o bien
- Pasar el IRP al controlador siguiente inferior de la pila.
Parámetros
Un sistema de archivos o un controlador de filtro llama a IoGetCurrentIrpStackLocation para que el IRP especificado obtenga un puntero a su propia ubicación de pila en el IRP. En los parámetros siguientes, Irp apunta a IRP e IrpSp apunta a IO_STACK_LOCATION. El controlador puede usar la información establecida en los siguientes miembros del IRP y la ubicación de la pila de IRP para procesar una solicitud de creación:
DeviceObject es un puntero al objeto de dispositivo de destino.
Irp->AssociatedIrp.SystemBuffer apunta a un búfer proporcionado por el sistema que se usará como búfer intermedio del sistema, si la marca DO_BUFFERED_IO está establecida en DeviceObject->Flags. De lo contrario, este miembro se establece en NULL.
Irp->IoStatus apunta a una estructura IO_STATUS_BLOCK, que recibe el estado de finalización final e información sobre la operación solicitada. Si se produce un error en la solicitud IRP_MJ_WRITE, la rutina de distribución de escritura del sistema de archivos devuelve un valor NTSTATUS de error y el valor de Irp->IoStatus.Information no está definido y no se debe usar.
Irp->MdlAddress es la dirección de una lista de descriptores de memoria (MDL) que describe las páginas en las que se van a escribir los datos.
IrpSp->FileObject apunta al objeto de archivo asociado a DeviceObject. Si la marca FO_SYNCHRONOUS_IO está establecida en IrpSp->FileObject->Flags, significa que el objeto de archivo se abrió para E/S sincrónica.
El parámetro IrpSp->FileObject contiene un puntero al campo RelatedFileObject, que también es una estructura FILE_OBJECT. El campo RelatedFileObject de la estructura FILE_OBJECT no es válido durante el procesamiento de IRP_MJ_WRITE y no se debe usar.
IrpSp->Flags: si se establece la marca SL_FORCE_DIRECT_WRITE, los controladores en modo kernel pueden escribir en áreas de volumen en las que normalmente no pueden escribir debido al bloqueo directo de escritura. El bloqueo directo de escritura se implementó por motivos de seguridad en Windows Vista y sistemas operativos posteriores. Esta marca se comprueba tanto en la capa del sistema de archivos como en la capa de pila de almacenamiento. Para obtener más información sobre el bloqueo de escritura directa, consulte Bloqueo de operaciones de escritura directa en volúmenes y discos. La marca SL_FORCE_DIRECT_WRITE está disponible en Windows Vista y versiones posteriores de Windows.
IrpSp->MajorFunction se establece en IRP_MJ_WRITE.
IrpSp->MinorFunction especifica la operación que se solicita y contiene uno de los valores siguientes. Si no se especifica un código de función secundaria, la operación es una escritura estándar (equivalente a IRP_MN_NORMAL).
MinorFunction Descripción IRP_MN_NORMAL La solicitud de escritura es para una operación de escritura estándar. IRP_MN_DPC La solicitud de escritura procede de una rutina DPC. IRP_MN_MDL Devuelve una MDL que describe los datos almacenados en caché del archivo en Irp->MdlAddress; el llamador usa esta MDL para escribir datos directamente en la memoria caché. IRP_MN_COMPLETE No se utiliza por sí mismo; solo se produce en combinación con al menos IRP_MN_MDL. Vea la sección Comentarios. IRP_MN_COMPRESSED La solicitud de escritura es para un archivo comprimido IRP_MN_MDL_DPC La solicitud de escritura procede de una rutina DPC y devuelve una MDL que describe los datos almacenados en caché del archivo en Irp->MdlAddress IRP_MN_COMPLETE_MDL Indica que el autor de la llamada, que usó la MDL para escribir datos directamente en la memoria caché, terminó de usar MDL. IRP_MN_COMPLETE_MDL_DPC Indica que el autor de la llamada, que usó la MDL para escribir datos directamente en la memoria caché, terminó de usar mdl; la solicitud de escritura procede de una rutina DPC. IrpSp->Parameters.Write.ByteOffset es una variable LARGE_INTEGER que especifica el desplazamiento de bytes inicial dentro del archivo de los datos que se van a escribir.
En determinadas circunstancias, este parámetro puede contener un valor especial. Por ejemplo, cuando es true, la siguiente condición indica que se debe usar el final actual del archivo en lugar de un valor de desplazamiento de archivo explícito: IrpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE and IrpSp->Parameters.Write.ByteOffset.HighPart == -1
IrpSp->Parameters.Write.Key es el valor de clave asociado a un bloqueo de intervalo de bytes en el archivo de destino.
IrpSp->Parameters.Write.Length es la longitud en bytes de los datos que se van a escribir. Si la operación de escritura se realiza correctamente, el número de bytes escritos se devuelve en el miembro Information de la estructura IO_STATUS_BLOCK a la que apunta Irp->IoStatus.
Comentarios
Los sistemas de archivos redondeen las operaciones de escritura y lectura al final del archivo hasta un múltiplo del tamaño del sector del dispositivo de almacenamiento de archivos subyacente. Cuando los filtros procesan las operaciones de preproceso o preescritura, esos filtros que asignan y intercambian búferes deben redondear el tamaño de un búfer asignado a un múltiplo del tamaño de sector del dispositivo asociado. Si no lo hacen, la longitud de los datos transferidos desde el sistema de archivos subyacente supera la longitud asignada del búfer. Para obtener más información sobre el intercambio de búferes, consulte Muestra de minifilro swapBuffers.
Las viñetas siguientes describen una escritura estándar frente a una escritura MDL basada en IRP:
Para realizar una escritura estándar:
- El emisor construye un IRP con MajorFunction = IRP_MJ_WRITE, MinorFunction = IRP_MN_NORMAL (es decir, 0) y proporciona los datos para escribir en Irp-AssociatedIrp.SystemBuffer>.
- Cuando envían el IRP al sistema de archivos, los datos que se van a escribir ya están en el IRP. Por lo tanto, la escritura se completa cuando el sistema de archivos termina de procesar el IRP; por ejemplo, copiando los datos del búfer en la memoria caché para una escritura almacenada en caché.
Para realizar una escritura MDL basada en IRP:
- El emisor construye un IRP con MajorFunction = IRP_MJ_WRITE, MinorFunction = IRP_MN_MDL, pero no proporciona un búfer de datos. Envían este IRP al sistema de archivos.
- El sistema de archivos construye una MDL, la coloca en el IRP y completa el IRP.
- El emisor usa esa MDL para copiar datos directamente en la memoria caché del archivo.
- Cuando el emisor se realiza la copia de datos en la memoria caché, crean otro IRP con MajorFunction = IRP_MJ_WRITE, MinorFunction = (IRP_MN_MDL | IRP_MN_COMPLETE) y envíelo al sistema de archivos.
- El sistema de archivos libera mdL y la operación de escritura ahora está completa.