Forçar solicitações de E/S pendentes
A opção Forçar Solicitações de E/S Pendentes retorna aleatoriamente STATUS_PENDING em resposta às chamadas de um driver para IoCallDriver. Essa opção testa a lógica do driver para responder a STATUS_PENDING valores retornados de IoCallDriver.
Essa opção tem suporte apenas no Windows Vista e em versões posteriores do sistema operacional Windows.
Cuidado Não use essa opção em um driver, a menos que você tenha conhecimento detalhado da operação do driver e tenha verificado que o driver foi projetado para lidar com STATUS_PENDING retornar valores de todas as suas chamadas para IoCallDriver. Executar essa opção em um driver que não foi projetado para lidar com STATUS_PENDING de todas as chamadas pode resultar em falhas, corrupção de memória e comportamento incomum do sistema que pode ser difícil de depurar ou corrigir.
Drivers de nível superior em uma pilha de driver chamam IoCallDriver para passar um IRP para baixo para drivers de nível inferior na pilha de driver. A rotina de expedição do driver no driver de nível inferior que recebe o IRP pode concluir o IRP imediatamente ou retornar STATUS_PENDING e concluir o IRP posteriormente.
Normalmente, o chamador deve estar preparado para lidar com qualquer resultado. No entanto, como a maioria das rotinas de expedição lida com o IRP imediatamente, a lógica de STATUS_PENDING no chamador não é frequentemente exercida e erros lógicos graves podem não ser detectados. A opção Forçar Solicitações de E/S Pendente intercepta chamadas para IoCallDriver e retorna STATUS_PENDING para testar a lógica usada com pouca frequência do driver de chamada.
Antes de executar esse teste, examine o design do driver e o código-fonte e confirme se o driver se destina a lidar com STATUS_PENDING de todas as chamadas do IoCallDriver .
Muitos drivers não foram projetados para lidar com STATUS_PENDING em todas as chamadas para IoCallDriver. Eles podem estar enviando o IRP para um driver conhecido específico que tem a garantia de concluir o IRP imediatamente. Enviar STATUS_PENDING para um driver que não o manipula pode causar falhas de driver e sistema e corrupção de memória.
O driver de nível superior que chama IoCallDriver deve lidar com um valor retornado STATUS_PENDING da seguinte maneira:
Antes de chamar IoCallDriver, o driver deve chamar IoBuildSynchronousFsdRequest para organizar o processamento síncrono do IRP.
Se IoCallDriver retornar STATUS_PENDING, o driver deverá aguardar a conclusão do IRP chamando KeWaitForSingleObject no evento especificado.
O driver deve prever que o IRP possa ser liberado antes que o Gerenciador de E/S sinalize o evento.
Depois de chamar IoCallDriver, o chamador não pode referenciar o IRP.
A opção Forçar Solicitação de E/S Pendente detecta os seguintes erros no driver que chama IoCallDriver e recebe um valor retornado STATUS_PENDING:
O driver não chama IoBuildSynchronousFsdRequest para organizar o processamento síncrono.
O driver não chama KeWaitForSingleObject.
O driver faz referência a um valor na estrutura IRP depois de chamar IoCallDriver. Depois de chamar IoCallDriver, o driver de nível superior não poderá acessar o IRP, a menos que tenha definido uma rotina de conclusão e, em seguida, somente quando todos os drivers de nível inferior tiverem concluído o IRP. Se o IRP for liberado, o driver falhará.
O driver chama uma função relacionada incorretamente. Por exemplo, o driver chama KeWaitForSingleObject e passa um identificador para o evento (como o parâmetro Object ), em vez de passar um ponteiro para um objeto de evento.
O driver aguarda o evento errado. Por exemplo, o driver chama IoSetCompletionRoutine, mas aguarda um evento interno que é sinalizado por sua própria rotina de conclusão, em vez de aguardar o evento IRP que é sinalizado pelo Gerenciador de E/S quando o IRP é concluído.
A partir do Windows 7, a opção Forçar Solicitações de E/S Pendentes é mais eficaz em forçar o exercício dos caminhos de código STATUS_PENDING em drivers verificados. Em versões anteriores do Windows, o Verificador de Driver forçou uma conclusão de IRP a ser atrasada somente quando o primeiro IoCompleteRequest para esse IRP for executado. Isso significa que a eficácia da verificação do Driver1 pode ser reduzida pelo comportamento do Driver2 da mesma pilha de dispositivos. O Driver2 pode aguardar de forma síncrona para a conclusão antes de retornar de sua rotina de expedição para Driver1. O atraso forçado da conclusão do IRP ocorre precisamente antes que a solicitação de E/S seja desenrolada novamente no driver verificado no caminho de conclusão. Isso significa que o caminho de código STATUS_PENDING do driver verificado é realmente exercido e o driver verificado percebe um atraso na conclusão.
Para ativar o Force Pending E/S Requests, você também deve ativar a Verificação de E/S. Você pode ativar a opção Forçar Solicitações de E/S Pendentes para um ou mais drivers usando o Gerenciador de Verificador de Driver ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionando opções do verificador de driver.
A opção Forçar Solicitações de E/S Pendentes tem suporte apenas no Windows Vista e em versões posteriores do Windows.
Na linha de comando
Para ativar Forçar Solicitações de E/S Pendentes, use um valor de sinalizador de 0x210 ou adicione 0x210 ao valor do sinalizador. Esse valor ativa a Verificação de E/S (0x10) e força solicitações de E/S pendentes (0x200).
Por exemplo:
verifier /flags 0x210 /driver MyDriver.sys
A opção estará ativa após a próxima inicialização.
Se você tentar ativar apenas solicitações de E/S pendentes (verificadores /sinalizadores 0x200), o Verificador de Driver habilitará automaticamente as Solicitações de E/S Pendentes (0x200) e a Verificação de E/S pendentes.
Você também pode ativar e desativar Solicitações de E/S Pendentes de Força sem reinicializar o computador adicionando o parâmetro /volatile ao comando . Por exemplo:
verifier /volatile /flags 0x210 /adddriver MyDriver.sys
Essa configuração é efetiva imediatamente, mas é perdida quando você desliga ou reinicializa o computador. Para obter detalhes, consulte Usando configurações voláteis.
Usando o Gerenciador de Verificador de Driver
- Iniciar o Gerenciador de Verificador de Driver. Digite Verificador em uma janela do Prompt de Comando.
- Selecione Criar configurações personalizadas (para desenvolvedores de código) e clique em Avançar.
- Selecione Selecionar configurações individuais em uma lista completa.
- Selecione Verificação de E/S e force solicitações de E/S pendentes.
Se você selecionar apenas Forçar Solicitações de E/S Pendentes, o Gerenciador de Verificador de Driver lembrará que a Verificação de E/S é necessária e oferece para habilitá-la para você.
Para exibir os resultados do teste Forçar Solicitações de E/S Pendentes, use a extensão do depurador !verifier com um valor de sinalizador de 0x40.
Para obter informações sobre !verifier, consulte o tópico !verifier na documentação Ferramentas de Depuração para Windows .
Se o computador de teste falhar como resultado do teste Forçar Solicitações de E/S Pendentes, você poderá usar o comando !verifier 40 para encontrar a causa. Em um rastreamento de pilha atual, localize o endereço do IRP que foi usado recentemente pelo driver. Por exemplo, se você usar o comando kP , que exibe o quadro de pilha de um thread, poderá encontrar o endereço IRP entre os parâmetros de função do rastreamento de pilha atual. Em seguida, execute !verifier 40 e procure o endereço do IRP. Os rastreamentos de pilha pendentes de força mais recentes aparecem na parte superior da tela.
Por exemplo, o seguinte rastreamento de pilha de Pci.sys mostra sua resposta a Forçar Solicitações de E/S Pendentes. O teste não revela erros na lógica de Pci.sys.
kd> !verifier 40
# Size of the log is 0x40
========================================================
IRP: 8f84ef00 - forced pending from stack trace:
817b21e4 nt!IovpLocalCompletionRoutine+0xb2
81422478 nt!IopfCompleteRequest+0x15c
817b2838 nt!IovCompleteRequest+0x9c
84d747df acpi!ACPIBusIrpDeviceUsageNotification+0xf5
84d2d36c acpi!ACPIDispatchIrp+0xe8
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
817c6a9d nt!ViFilterDispatchPnp+0xe9
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
84fed489 pci!PciCallDownIrpStack+0xbf
84fde1cb pci!PciDispatchPnpPower+0xdf
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
817c6a9d nt!ViFilterDispatchPnp+0xe9
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
84ff2ff5 pci!PciSendPnpIrp+0xbd
84fec820 pci!PciDevice_DeviceUsageNotification+0x6e
84fde1f8 pci!PciDispatchPnpPower+0x10c
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
84d76ce2 acpi!ACPIFilterIrpDeviceUsageNotification+0x96
84d2d36c acpi!ACPIDispatchIrp+0xe8
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
84f7f16c PCIIDEX!PortWdmForwardIrpSynchronous+0x8e
84f7b2b3 PCIIDEX!GenPnpFdoUsageNotification+0xcb
84f7d301 PCIIDEX!PciIdeDispatchPnp+0x45
817b258f nt!IovCallDriver+0x19d
8142218e nt!IofCallDriver+0x1c
O rastreamento de pilha mostra que Acpi.sys estava tentando concluir IRP 8f84ef00. O Verificador de Driver forçou uma conclusão adiada, então Acpi.sys retornou STATUS_PENDING para pci! PciCallDownIrpStack. Se essa chamada tivesse causado uma falha, o proprietário do driver precisaria examinar o código-fonte para pci! PciCallDownIrpStack e revise-o para lidar com o STATUS_PENDING corretamente.