Compartilhar via


IRP_MJ_WRITE (FS e drivers de filtro)

Quando é enviado

O gerenciador de E/S ou um driver do sistema de arquivos envia a solicitação IRP_MJ_WRITE. Essa solicitação pode ser enviada, por exemplo, quando um aplicativo de modo de usuário chama uma função Win32, como WriteFile ou quando um componente de modo kernel chama ZwWriteFile.

Operação: drivers do sistema de arquivos

O driver do sistema de arquivos deve extrair e decodificar o objeto do arquivo para determinar os parâmetros e o código de função secundária.

Para solicitações de gravação na MDL, o sistema de arquivos deve verificar o código de função secundária a fim de determinar qual operação está sendo solicitada. Veja a seguir os códigos de função secundária válidos, que só podem ser utilizados para E/S de arquivo armazenado em cache:

  • 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 obter mais informações sobre como lidar com esse IRP, analise o exemplo de FASTFAT incluído no Kit de Driver do Windows (WDK).

Operação: drivers de filtro do sistema de arquivos herdados

O driver de filtro deve executar todo processamento necessário e, dependendo da natureza do filtro, também deve executar uma destas ações:

  • concluir ou reprovar o IRP;
  • enviar o IRP para o próximo driver de nível inferior na pilha.

Parâmetros

Um sistema de arquivos ou driver de filtro chama IoGetCurrentIrpStackLocation para o IRP fornecido a fim de obter um ponteiro para seu próprio local de pilha no IRP. Nos parâmetros a seguir, Irp aponta para IRP e IrpSp aponta para IO_STACK_LOCATION. O driver pode utilizar as informações que estão definidas nos membros do IRP a seguir e o local da pilha do IRP para processar uma solicitação de criação:

  • DeviceObject é um ponteiro para o objeto do dispositivo de destino.

  • Irp->AssociatedIrp.SystemBuffer aponta para um buffer fornecido pelo sistema que será usado como um buffer de sistema intermediário, se o sinalizador DO_BUFFERED_IO estiver definido em DeviceObject->Flags. Caso contrário, esse membro será definido como NULL.

  • Irp->IoStatus aponta para uma estrutura IO_STATUS_BLOCK que recebe o status de conclusão final e as informações sobre a operação solicitada. Se a solicitação IRP_MJ_WRITE falhar, a rotina de despacho de gravação do sistema de arquivos retornará um valor de erro NTSTATUS e o valor de Irp->IoStatus.Information será indefinido e não deverá ser usado.

  • Irp->MdlAddress é o endereço de uma lista de descritores de memória (MDL) que descreve as páginas em que os dados devem ser gravados.

  • IrpSp->FileObject aponta para o objeto do arquivo associado a DeviceObject. Se o sinalizador FO_SYNCHRONOUS_IO estiver definido em IrpSp->FileObject->Flags, o objeto do arquivo terá sido aberto para E/S síncrona.

    O parâmetro IrpSp->FileObject contém um ponteiro para o campo RelatedFileObject, que também é uma estrutura FILE_OBJECT. O campo RelatedFileObject da estrutura FILE_OBJECT não é válido durante o processamento de IRP_MJ_WRITE e não deve ser utilizado.

  • IrpSp->Flags: se o sinalizador SL_FORCE_DIRECT_WRITE estiver definido, os drivers do modo kernel poderão gravar em áreas de volumes em que normalmente não podem gravar devido ao bloqueio de gravação direta. O bloqueio de gravação direta foi implementado por motivos de segurança no Windows Vista e nos sistemas operacionais posteriores. Esse sinalizador é verificado tanto na camada do sistema de arquivos quanto na camada da pilha de armazenamento. Para obter mais informações sobre o bloqueio de gravação direta, consulte Bloqueio de operações de gravação direta em volumes e discos. O sinalizador SL_FORCE_DIRECT_WRITE está disponível no Windows Vista e nas versões posteriores do Windows.

  • IrpSp->MajorFunction é definido como IRP_MJ_WRITE.

  • IrpSp->MinorFunction especifica a operação que está sendo solicitada e também contém um dos valores a seguir. Se não for especificado nenhum código de função secundária, a operação será uma gravação padrão (equivalente a IRP_MN_NORMAL).

    MinorFunction Descrição
    IRP_MN_NORMAL A solicitação de gravação é destinada a uma operação de gravação padrão.
    IRP_MN_DPC A solicitação de gravação é proveniente de uma rotina de DPC.
    IRP_MN_MDL Retorna uma MDL que descreve os dados do arquivo armazenados em cache em Irp->MdlAddress. O autor da chamada usa essa MDL para gravar dados diretamente no cache.
    IRP_MN_COMPLETE Não é usado por si só; só ocorre em combinação com pelo menos IRP_MN_MDL. Consulte Observações.
    IRP_MN_COMPRESSED A solicitação de gravação é destinada a um arquivo compactado.
    IRP_MN_MDL_DPC A solicitação de gravação é proveniente de uma rotina de DPC e retorna uma MDL que descreve os dados do arquivo armazenados em cache em Irp->MdlAddress.
    IRP_MN_COMPLETE_MDL Indica que o chamador, que usou o MDL para gravar dados diretamente no cache, concluiu o uso do MDL
    IRP_MN_COMPLETE_MDL_DPC Indica que o chamador, que usou o MDL para gravar dados diretamente no cache, terminou de usar o MDL; a solicitação de gravação é de uma rotina DPC
  • IrpSp->Parameters.Write.ByteOffset é uma variável LARGE_INTEGER que define o deslocamento do byte inicial no arquivo dos dados que serão gravados.

    Esse parâmetro pode conter um valor especial dependendo das circunstâncias. Por exemplo, quando for “true”, a seguinte condição indicará que o final atual do arquivo deverá ser utilizado em vez de um valor de deslocamento de arquivo explícito: IrpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE e IrpSp->Parameters.Write.ByteOffset.HighPart == -1

  • IrpSp->Parameters.Write.Key é o valor de chave associado a um bloqueio de intervalo de bytes no arquivo de destino.

  • IrpSp->Parameters.Write.Length é o comprimento em bytes dos dados que serão gravados. Se a operação de gravação for bem-sucedida, será retornada a quantidade de bytes gravados no membro Information da estrutura IO_STATUS_BLOCK apontada por Irp->IoStatus.

Comentários

Os sistemas de arquivos arredondam as operações de gravação e leitura no final do arquivo para um múltiplo do tamanho do setor do dispositivo de armazenamento de arquivos subjacente. Quando os filtros processam operações de pré-leitura ou pré-gravação, esses filtros que alocam e trocam buffers precisam arredondar o tamanho de um buffer alocado para um múltiplo do tamanho do setor do dispositivo associado. Caso contrário, o comprimento dos dados transferidos do sistema de arquivos subjacente excede o comprimento alocado do buffer. Para obter mais informações sobre como trocar buffers, confira um exemplo do minifiltro swapBuffers.

Os marcadores a seguir descrevem uma gravação padrão versus uma gravação MDL baseada em IRP:

  • Para executar uma gravação padrão:

    1. O emissor constrói um IRP com MajorFunction = IRP_MJ_WRITE, MinorFunction = IRP_MN_NORMAL (ou seja, 0) e fornece os dados para gravar em Irp-AssociatedIrp.SystemBuffer>.
    2. Quando eles enviam o IRP para o sistema de arquivos, os dados a serem gravados já estão no IRP. Assim, a gravação é concluída quando o sistema de arquivos termina de processar o IRP; por exemplo, copiando os dados do buffer para o cache para uma gravação em cache.
  • Para executar uma gravação MDL baseada em IRP:

    1. O emissor constrói um IRP com MajorFunction = IRP_MJ_WRITE, MinorFunction = IRP_MN_MDL, mas não fornece um buffer de dados. Eles enviam esse IRP para o sistema de arquivos.
    2. O sistema de arquivos constrói um MDL, coloca-o no IRP e conclui o IRP.
    3. O emissor usa esse MDL para copiar dados diretamente para o cache do arquivo.
    4. Quando o emissor termina de copiar dados para o cache, ele constrói outro IRP com MajorFunction = IRP_MJ_WRITE, MinorFunction = (IRP_MN_MDL | IRP_MN_COMPLETE) e enviá-lo para o sistema de arquivos.
    5. O sistema de arquivos libera o MDL e a operação de gravação agora está concluída.

Confira também

CcMdlWriteComplete

CcPrepareMdlWrite

FLT_IO_PARAMETER_BLOCK

IO_STACK_LOCATION

IO_STATUS_BLOCK

IoGetCurrentIrpStackLocation

IRP

IRP_MJ_READ

IRP_MJ_WRITE (referência de kernel do WDK)

ZwWriteFile