Partilhar via


Resolução de problemas de instalações de dispositivos com o Depurador de Kernel (KD)

A partir do Windows Vista, quando o gerenciador Plug and Play (PnP) deteta um novo dispositivo no sistema, o sistema operacional inicia o processo de host de instalação do dispositivo (DrvInst.exe) para procurar e instalar um driver para o dispositivo.

Como a instalação do dispositivo ocorre dentro desse processo de modo de usuário, geralmente é mais fácil usar um depurador de modo de usuário, conforme descrito em Depurando instalações de dispositivo com um depurador de modo de usuário. Em alguns casos, no entanto, pode ser útil usar o depurador do kernel (KD) para monitorar o processo de instalação do dispositivo no modo de usuário.

Por exemplo, usando o KD ao depurar a instalação do dispositivo no modo de usuário, você pode fazer o seguinte:

  • Depure simultaneamente um problema de modo kernel usando !devnode, !devobj, !drvobj, !irp e outras extensões KD.

  • Monitore outros processos em modo de utilizador sem gerir múltiplos depuradores, utilizando as extensões do KD !process ou .process /p.

Para obter mais informações sobre o KD e outras ferramentas de depuração, consulte Depuração do Windows.

O valor do registo DebugInstall especifica o tipo de suporte à depuração de instalação de dispositivo habilitado no sistema. Para obter mais informações sobre esse valor do Registro, consulte Habilitando o suporte para depuração de instalações de dispositivos.

Quando o valor do registo DebugInstall é definido como 1, DrvInst.exe verificará primeiro se o depurador do kernel está habilitado e anexado atualmente antes de aceder ao depurador. Depois que essa pausa é feita, os pontos de interrupção podem ser definidos nos módulos de modo de usuário do processo atual. Por exemplo:

kd> .reload /user
kd> bp /p @$proc setupapi!SetupDiCallClassInstaller

Isso define um ponto de interrupção na rotina SETUPAPI! SetupDiCallClassInstaller apenas para o processo atual.

Para o desenvolvedor de um pacote de driver, geralmente é mais desejável depurar as ações de um instalador de classe ou coinstalador DLL durante a instalação de um dispositivo. No entanto, quando DrvInst.exe entra no depurador, quaisquer instaladores de classe ou DLLs co-instaladoras do pacote do driver não terão sido carregados. Embora os depuradores em modo utilizador permitam definir uma exceção de depuração quando um módulo em modo utilizador é carregado no processo com o comando "sx e ld", o depurador do kernel só suporta módulos em modo kernel com esse comando.

O exemplo de código a seguir mostra como um "Debugger Command Program" monitora o carregamento de um instalador de classe específica ou coinstalador no processo atual. Neste exemplo, o programa de comando do depurador definirá um ponto de paragem no ponto de entrada principal (CoInstallerProc) do co-instalador Mycoinst.dll:

file: Z:\bpcoinst.txt

r $t1 = 0
!for_each_module .if ($spat("@#ModuleName", "mycoinst*") = 0) {r $t1 = 1}
.if (not @$t1 = 0) {.echo mycoinst is loaded, set bp on mycoinst!CoInstallerProc } .else {.echo mycoinst not loaded}
.if (not @$t1 = 0) {.reload mycoinst.dll}
.if (not @$t1 = 0) {bp[0x20] /p @$proc mycoinst!CoInstallerProc } .else {bc[0x20]}

Quando executado, o programa de comando do depurador verificará se Mycoinst.dll está presente na lista de módulos carregados no processo atual. Depois que essa DLL do co-instalador for carregada, o depurador definirá um ponto de paragem (com um ID de ponto de paragem bem conhecido) na função de ponto de entrada CoInstallerProc.

A partir da interrupção de depuração iniciada pelo processo de host DrvInst.exe, deves primeiro definir um ponto de interrupção no endereço de retorno da chamada onde DrvInst.exe entrou no debugger do kernel. Este ponto de interrupção eliminará todos os pontos de interrupção definidos durante a instalação do dispositivo e continuará a execução:

DRVINST.EXE: Entering debugger during PnP device installation.
Device instance = "X\Y\Z" ...

Break instruction exception - code 80000003 (first chance)
010117b7 cc               int     3

kd> bp[0x13] /p @$proc @$ra "bc *;g"

Em seguida, você deve definir alguns pontos de interrupção dentro do processo para permitir que os comandos no programa de comando do depurador sejam executados no momento apropriado durante a instalação do dispositivo.

Para garantir que o ponto de interrupção para o instalador de classe ou para o ponto de entrada da DLL do coinstalador seja definido antes que a função seja invocada para a instalação do dispositivo, o programa de comando do depurador deve ser executado sempre que uma nova DLL for carregada no processo atual, isto é, após a chamada para LoadLibraryExW retornar.

kd> .reload
kd> bp[0x10] /p @$proc kernel32!LoadLibraryExW "gu;$$><Z:\\bpcoinst.txt;g"

Em vez de executar o programa em cada chamada LoadLibraryEx dentro do processo (bp[0x10]), o desenvolvedor pode restringi-lo para executar somente quando o instalador de classe e as DLLs do coinstalador são carregadas no processo. Como SetupDiCallClassInstaller é a rotina que invoca instaladores de classe e coinstaladores registrados para um dispositivo, essas DLLs serão carregadas no processo durante essa chamada.

Como nenhuma suposição deve ser feita sobre quando essas DLLs serão descarregadas do processo de host DrvInst.exe , você deve certificar-se de que os pontos de interrupção podem lidar com a localização dos pontos de entrada DLL durante quaisquer chamadas feitas para SetupDiCallClassInstaller a partir do processo de host DrvInst.exe .

kd> bd[0x10]
kd> bp[0x11] /p @$proc setupapi!SetupDiCallClassInstaller "be[0x10];bp[0x12] /p @$proc @$ra \"bd[0x10];bc[0x12];g\";g"
kd> g

O ponto de interrupção para executar o programa de comando do depurador (bp[0x10]) está inicialmente desativado. Ele é ativado sempre que SetupDiCallClassInstaller é invocado (bp[0x11]) e a execução continua. O programa de comando do depurador (bp[0x10]) é novamente desativado quando SetupDiCallClassInstaller retorna definindo um ponto de interrupção no endereço de retorno da própria rotina (bp[0x12]).

Lembre-se de que o ponto de interrupção que desativa o programa de comando do depurador também se limpa e continua a execução até que SetupDiCallClassInstaller seja chamado novamente ou até que o programa de instalação seja concluído e todos os pontos de interrupção sejam limpos (bp[0x13]).

Quando a execução começa depois que os pontos de interrupção acima são definidos, o processo será interrompido em cada chamada para mycoinst! CoInstallerProc. Isso permite que você depure a execução da DLL do instalador de classe ou coinstalador durante a instalação do dispositivo principal.

O período de tempo padrão para a conclusão de um processo de instalação é de 5 minutos. Se o processo não for concluído dentro do período de tempo dado, o sistema assume que o processo parou de responder e é encerrado.

A restrição de tempo limite padrão colocada em instalações de dispositivos ainda está em vigor enquanto o processo está sendo depurado através do depurador do kernel. Como a execução de todos os programas no sistema é interrompida quando estão sob depuração, a quantidade de tempo gasto pelo processo de instalação é rastreada da mesma forma que seria em um sistema que não está sob depuração.