Depurando instalações de dispositivo com o depurador de kernel (KD)
A partir do Windows Vista, quando o gerenciador de Plug and Play (PnP) detecta um novo dispositivo no sistema, o sistema operacional inicia o processo de host de instalação do dispositivo (DrvInst.exe) para pesquisar 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 no modo de usuário. Em alguns casos, no entanto, pode ser útil usar o KD (depurador de kernel) para monitorar o processo de instalação do dispositivo no modo de usuário.
Por exemplo, usando kd durante a depuração da instalação do dispositivo no modo de usuário, você pode fazer o seguinte:
Depure simultaneamente um problema no modo kernel usando !devnode, !devobj, !drvobj, !irp e outras extensões KD.
Monitore outros processos de modo de usuário sem gerenciar vários depuradores usando as extensões KD !process ou .process /p.
Para obter mais informações sobre kd e outras ferramentas de depuração, consulte Depuração do Windows.
O valor de Registro DebugInstall especifica o tipo de suporte de depuração de instalação do 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 dispositivo.
Quando o valor do Registro DebugInstall for definido como 1, DrvInst.exe primeiro marcar que o depurador de kernel esteja habilitado e anexado no momento antes de entrar no depurador. Depois que essa interrupção for feita, os pontos de interrupção poderão ser definidos nos módulos do 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 SETUPAPI de rotina! SetupDiCallClassInstaller somente 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 DLL do co-instalador durante a instalação de um dispositivo. No entanto, quando DrvInst.exe entrar no depurador, as DLLs do instalador de classe ou do co-instalador do pacote de driver não serão carregadas. Embora os depuradores de modo de usuário ofereçam suporte à capacidade de definir uma exceção de depurador quando um módulo de modo de usuário é carregado no processo com o comando "sx e ld", o depurador de kernel dá suporte apenas a módulos de modo kernel com esse comando.
O exemplo de código a seguir mostra como um "Programa de Comando do Depurador" monitora o carregamento de um instalador de classe específico ou um co-instalador no processo atual. Neste exemplo, o programa de comando do depurador definirá um ponto de interrupção no ponto de entrada main (CoInstallerProc) do co-instalador doMycoinst.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 marcar a lista de módulos carregados no processo atual para Mycoinst.dll. Depois que essa DLL do co-instalador for carregada, o depurador definirá um ponto de interrupção (com uma ID de ponto de interrupção conhecida) na função de ponto de entrada CoInstallerProc.
A partir da interrupção de depuração iniciada pelo processo de host DrvInst.exe , primeiro você deve definir um ponto de interrupção no endereço de retorno da chamada em queDrvInst.exe invadiu o depurador do kernel. Esse ponto de interrupção limpará 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 o ponto de entrada de DLL do co-instalador seja definido antes que a função seja invocada para instalação do dispositivo, o programa de comando do depurador deve ser executado sempre que uma nova DLL for carregada no processo atual, ou seja, depois que uma 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 a ser executado somente quando o instalador de classe e as DLLs do co-instalador são carregados no processo. Como SetupDiCallClassInstaller é a rotina que invoca instaladores de classe e co-instaladores 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 verificar se os pontos de interrupção podem lidar com a localização dos pontos de entrada de DLL durante todas as chamadas feitas para SetupDiCallClassInstaller 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 desabilitado. Ele é habilitado sempre que SetupDiCallClassInstaller é invocado (bp[0x11]) e a execução continua. O programa de comando do depurador (bp[0x10]) é desabilitado novamente quando SetupDiCallClassInstaller retorna definindo um ponto de interrupção no endereço de retorno dessa própria rotina (bp[0x12]).
Lembre-se de que o ponto de interrupção que desabilita 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çar depois que os pontos de interrupção acima forem definidos, o processo será interrompido em cada chamada para mycoinst! CoInstallerProc. Isso permite depurar a execução do instalador de classe ou da DLL do co-instalador durante a instalação do dispositivo principal.
O período de tempo padrão para que um processo de instalação seja concluído é de 5 minutos. Se o processo não for concluído dentro do período determinado, o sistema assumirá que o processo parou de responder e foi encerrado.
A restrição de tempo limite padrão colocada nas instalações do dispositivo ainda está em vigor enquanto o processo está sendo depurado por meio do depurador de kernel. Como a execução de todos os programas no sistema é interrompida enquanto é dividida no depurador, o tempo gasto pelo processo de instalação é acompanhado da mesma forma que em um sistema que não está sendo depurado.