Resumo das rotinas de expedição de leitura/gravação
Tenha os seguintes pontos em mente ao implementar uma rotina DispatchRead, DispatchWrite ou DispatchReadWrite :
É responsabilidade do driver de nível mais alto em uma cadeia de drivers em camadas marcar os parâmetros dos IRPs de leitura/gravação de entrada para validade antes de configurar o local da pilha de E/S do próximo driver de nível inferior em um IRP.
Os drivers intermediários e de nível mais baixo geralmente podem contar com o driver de nível mais alto em sua cadeia para passar solicitações de transferência com parâmetros válidos. No entanto, qualquer driver pode executar verificações de integridade nos parâmetros em seu local de pilha de E/S de um IRP, e cada driver de dispositivo deve marcar os parâmetros para condições que podem violar quaisquer restrições impostas por seu dispositivo.
Se uma rotina DispatchReadWrite concluir um IRP com um erro, ele deverá definir o membro Status do local da pilha de E/S com um valor apropriado do tipo NTSTATUS, definir o membro Information como zero e chamar IoCompleteRequest com o IRP e um PriorityBoost de IO_NO_INCREMENT.
Se um driver usa E/S em buffer, talvez seja necessário definir uma estrutura para conter dados a serem transferidos e talvez seja necessário armazenar em buffer algumas dessas estruturas internamente.
Se um driver usa E/S direta, talvez seja necessário marcar se o MDL em Irp-MdlAddress> descreve um buffer que contém muitos dados (ou muitas quebras de página) para o dispositivo subjacente manipular em uma única operação de transferência. Nesse caso, o driver deve dividir a solicitação de transferência original em uma sequência de operações de transferência menores.
Um driver de classe estreitamente acoplado pode dividir essa solicitação em sua rotina DispatchReadWrite para seu driver de porta subjacente. Drivers de classe SCSI, especialmente para dispositivos de armazenamento em massa, são necessários para fazer isso. Para obter mais informações sobre os requisitos para drivers SCSI, consulte Drivers de armazenamento.
A rotina DispatchReadWrite de um driver de dispositivo de nível inferior deve adiar a divisão de uma solicitação de transferência grande em transferências parciais até que outra rotina de driver desquemente o IRP para configurar o dispositivo para a transferência.
Se um driver de dispositivo de nível inferior enfileirar um IRP de leitura/gravação para processamento adicional por suas próprias rotinas, ele deverá chamar IoMarkIrpPending antes de enfileirar o IRP. A rotina DispatchReadWrite também deve retornar o controle com STATUS_PENDING nessas circunstâncias.
Se a rotina DispatchReadWrite passar um IRP para drivers inferiores, ele deverá configurar o local da pilha de E/S para o driver mais baixo no IRP. Se o driver de nível superior também define uma rotina IoCompletion no IRP antes de passá-lo com IoCallDriver depende do design do driver e daqueles em camadas sob ele.
No entanto, um driver de nível superior deve chamar IoSetCompletionRoutine antes de chamar IoCallDriver se alocar recursos, como IRPs ou memória. Sua rotina IoCompletion deve liberar todos os recursos alocados por driver quando drivers inferiores tiverem concluído a solicitação, mas antes que a rotina IoCompletion chame IoCompleteRequest com o IRP original.
Se um driver de nível superior alocar IRPs para drivers inferiores que podem incluir um driver de dispositivo de mídia removível subjacente, o driver de alocação deverá estabelecer o contexto de thread em cada IRP alocado.