Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Na entrada, uma rotina de IoCompletion recebe um ponteiro Context. Quando uma rotina de despacho chama IoSetCompletionRoutine, ela pode fornecer um ponteiro Context. Esse ponteiro pode fazer referência a qualquer informação de contexto determinada pelo driver que a rotina IoCompletion requer para processar um IRP. A área de contexto não pode ser paginável porque a rotina IoCompletion pode ser chamada em IRQL = DISPATCH_LEVEL.
Considere as seguintes diretrizes de implementação para rotinas IoCompletion:
Uma rotina de IoCompletion pode verificar o bloco de status de E/S do IRP para determinar o resultado da operação de E/S.
Se a rotina de expedição alocar o IRP de entrada usando IoAllocateIrp ou IoBuildAsynchronousFsdRequest, a rotina IoCompletion deverá chamar IoFreeIrp para liberar esse IRP, preferencialmente antes de concluir o IRP original.
A rotina IoCompletion deve liberar os recursos relacionados ao IRP que a rotina de expedição alocou para o IRP alocado pelo driver, preferencialmente antes de liberar o IRP correspondente.
Por exemplo, se a rotina de expedição alocar um MDL com IoAllocateMdl e chamar IoBuildPartialMdl para um IRP de transferência parcial alocado, a rotina IoCompletion deverá liberar o MDL com IoFreeMdl. Se ele alocar recursos para manter o estado sobre o IRP original, deve liberar esses recursos, de preferência antes de chamar IoCompleteRequest com o IRP original, e definitivamente antes de retornar o controle.
Em geral, antes de liberar ou concluir um IRP, a rotina IoCompletion deve liberar todos os recursos por IRP alocados pela rotina de expedição. Caso contrário, o driver deve manter o estado sobre os recursos a serem liberados antes que sua rotina IoCompletion retorne o controle após concluir a solicitação original.
Se a rotina IoCompletion não puder concluir o IRP original com STATUS_SUCCESS, ela deverá definir o bloco de status de E/S no IRP original para o valor retornado no IRP alocado pelo driver que fez com que a rotina IoCompletion falhasse na solicitação original.
Se a rotina IoCompletion concluir a solicitação original com STATUS_PENDING, ela deverá chamar IoMarkIrpPending com o IRP original antes de chamar IoCompleteRequest.
Se a rotina IoCompletion precisar falhar o IRP original com um erro STATUS_XXX, ela poderá registrar um erro no log. No entanto, é responsabilidade do driver de dispositivo subjacente registrar todos os erros de E/S do dispositivo que ocorrem, portanto, as rotinas de IoCompletion geralmente não registram erros.
Quando a rotina IoCompletion processa e libera o IRP alocado pelo driver, ela deve retornar o controle com STATUS_MORE_PROCESSING_REQUIRED.
Retornar STATUS_MORE_PROCESSING_REQUIRED da rotina IoCompletion adia o processamento de conclusão por parte do gerente de E/S para um IRP que foi alocado e liberado pelo driver. Uma segunda chamada para IoCompleteRequest faz com que o gerente de E/S retome a chamar as rotinas de conclusão do IRP, começando com a rotina de conclusão imediatamente acima da rotina que retornou STATUS_MORE_PROCESSING_REQUIRED.
Se a rotina IoCompletion reutilizar um IRP de entrada para enviar uma ou mais solicitações para drivers inferiores ou se a rotina repetir operações com falha, ela deverá atualizar qualquer contexto que a rotina IoCompletion mantenha sobre cada reutilização ou repetição do IRP. Em seguida, ele pode configurar novamente a localização na pilha de E/S do driver imediatamente inferior, chamar IoSetCompletionRoutine com seu próprio ponto de entrada e chamar IoCallDriver para processar o IRP.
A rotina IoCompletion não deve chamar IoMarkIrpPending em cada reutilização ou repetição do IRP.
A rotina de despacho já marcou o IRP original como pendente. Até que todos os drivers na cadeia concluam o IRP original com IoCompleteRequest, ele permanece pendente.
Antes de tentar novamente uma solicitação, a rotina IoCompletion deve redefinir o bloco de status de E/S com STATUS_SUCCESS para Status e zero para Informações, possivelmente depois de salvar as informações de erro retornadas.
Para cada tentativa, a rotina IoCompletion geralmente diminui uma contagem de tentativas configurada pela rotina de despacho. Normalmente, a rotina IoCompletion deve chamar IoCompleteRequest para falhar no IRP quando algum número limitado de tentativas tiver falhado.
A rotina IoCompletion deve retornar STATUS_MORE_PROCESSING_REQUIRED depois que chamar IoSetCompletionRoutine e IoCallDriver com um IRP que ela está reutilizando ou tentando novamente.
Retornar STATUS_MORE_PROCESSING_REQUIRED da rotina IoCompletion adia o processamento de conclusão do gerenciador de E/S de um IRP reutilizado ou repetido.
Se a rotina IoCompletion não puder concluir o IRP original com STATUS_SUCCESS, ela deverá deixar o bloco de status de entrada/saída conforme retornado por drivers inferiores, para que seja reutilizado ou repetido na operação que gera a falha no IRP pela rotina IoCompletion.
Se a rotina IoCompletion concluir a solicitação original com STATUS_PENDING, ela deverá chamar IoMarkIrpPending com o IRP original antes de chamar IoCompleteRequest.
Se a rotina IoCompletion precisar falhar no IRP original com um erro STATUS_XXX, a rotina poderá registrar um erro no log. No entanto, é responsabilidade do driver de dispositivo subjacente registrar todos os erros de E/S do dispositivo que ocorrem, portanto, as rotinas de IoCompletion geralmente não registram erros.
Qualquer driver que define uma rotina IoCompletion em um IRP e, em seguida, passa o IRP para um driver de nível inferior deve verificar o sinalizador IRP-PendingReturned> na rotina IoCompletion. Se o sinalizador estiver definido, a rotina IoCompletion deverá chamar IoMarkIrpPending com o IRP. No entanto, um driver que encaminha o IRP e aguarda em um evento não deve marcar o IRP como pendente. Em vez disso, a rotina IoCompletion deve sinalizar o evento e retornar STATUS_MORE_PROCESSING_REQUIRED.
A rotina IoCompletion deve liberar todos os recursos da rotina de expedição alocada para processar o IRP original, preferencialmente antes que a rotina IoCompletion chame IoCompleteRequest com o IRP original e, definitivamente, antes que a rotina IoCompletion retorne o controle de concluir o IRP original.
Se qualquer driver de nível superior definir sua rotina IoCompletion no IRP original, a rotina IoCompletion do driver não será chamada até que as rotinas de IoCompletion de todos os drivers de nível inferior sejam chamadas.
Fornecendo um aumento de prioridade em chamadas para IoCompleteRequest
Se um driver de dispositivo de nível mais baixo puder concluir um IRP em sua rotina de despacho, ele chamará IoCompleteRequest com um PriorityBoost de IO_NO_INCREMENT. Nenhum aumento de prioridade em tempo de execução é necessário porque o driver pode assumir que o requerente original não aguardou a conclusão de sua operação de E/S.
Caso contrário, o driver de nível mais baixo fornece um valor específico do tipo de dispositivo e definido pelo sistema que eleva a prioridade de execução do solicitante para compensar o tempo que o solicitante aguardou pela solicitação de E/S do dispositivo. Consulte Wdm.h ou Ntddk.h para obter os valores de aumento.
Os drivers de nível superior aplicam o mesmo PriorityBoost que seus respectivos drivers de dispositivo subjacentes quando chamam IoCompleteRequest.
Efeito de chamar IoCompleteRequest
Quando um driver chama IoCompleteRequest, o gerenciador de E/S preenche o local da pilha de E/S do driver com zeros antes de chamar o próximo driver de nível superior, se houver, que configurou uma rotina IoCompletion para ser chamada para o IRP.
A rotina de IoCompletion de um driver de nível superior pode verificar apenas o bloco de status de E/S do IRP para determinar como todos os drivers inferiores lidaram com a solicitação.
O chamador de IoCompleteRequest não deve tentar acessar o IRP recém-concluído. Essa tentativa é um erro de programação que causa uma falha no sistema.