Depuración de instalaciones de dispositivos con el depurador de kernel (KD)
A partir de Windows Vista, cuando el administrador de Plug and Play (PnP) detecta un nuevo dispositivo en el sistema, el sistema operativo inicia el proceso de host de instalación del dispositivo (DrvInst.exe) para buscar e instalar un controlador para el dispositivo.
Dado que la instalación del dispositivo se produce dentro de este proceso en modo de usuario, normalmente es más fácil usar un depurador en modo de usuario, como se describe en Depuración de instalaciones de dispositivos con un depurador en modo usuario. Sin embargo, en algunos casos, puede resultar útil usar el depurador de kernel (KD) para supervisar el proceso de instalación del dispositivo en modo de usuario.
Por ejemplo, mediante el uso de KD durante la depuración de la instalación del dispositivo en modo de usuario, puede hacer lo siguiente:
Depure simultáneamente un problema en modo kernel mediante !devnode, !devobj, !drvobj, !irp y otras extensiones de KD.
Supervise otros procesos en modo de usuario sin administrar varios depuradores mediante el uso de las extensiones de KD !process o .process /p.
Para obtener más información sobre KD y otras herramientas de depuración, vea Depuración de Windows.
El valor del Registro DebugInstall especifica el tipo de compatibilidad con la depuración de la instalación de dispositivos habilitada en el sistema. Para obtener más información sobre este valor del Registro, consulte Habilitación de la compatibilidad con las instalaciones de dispositivos de depuración.
Cuando el valor del Registro DebugInstall se establece en 1, DrvInst.exe comprobará primero que el depurador de kernel está habilitado y conectado actualmente antes de que se divida en el depurador. Una vez realizada esta interrupción, los puntos de interrupción se pueden establecer en los módulos en modo de usuario del proceso actual. Por ejemplo:
kd> .reload /user
kd> bp /p @$proc setupapi!SetupDiCallClassInstaller
Esto establece un punto de interrupción en la rutina SETUPAPI! SetupDiCallClassInstaller solo para el proceso actual.
Para el desarrollador de un paquete de controladores, normalmente es más conveniente depurar las acciones de un instalador de clase o dll de coinstalador durante la instalación de un dispositivo. Sin embargo, cuando DrvInst.exe se divide en el depurador, no se cargará ningún instalador de clase ni dll de coinsercionador del paquete de controladores. Aunque los depuradores en modo de usuario admiten la capacidad de establecer una excepción del depurador cuando se carga un módulo en modo de usuario en el proceso con el comando "sx e ld", el depurador de kernel solo admite módulos en modo kernel con ese comando.
En el ejemplo de código siguiente se muestra cómo un "Programa de comandos del depurador" supervisa la carga de un instalador de clase específico o coinsercionador en el proceso actual. En este ejemplo, el programa de comandos del depurador establecerá un punto de interrupción en el punto de entrada principal (CoInstallerProc) del Mycoinst.dll coinstalador:
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]}
Cuando se ejecute, el programa de comandos del depurador comprobará la lista de módulos cargados en el proceso actual para Mycoinst.dll. Una vez cargado este archivo DLL de coinstalador, el depurador establecerá un punto de interrupción (con un identificador de punto de interrupción conocido) en la función de punto de entrada CoInstallerProc.
A partir de la interrupción de depuración iniciada por el proceso de host deDrvInst.exe , primero debe establecer un punto de interrupción en la dirección de devolución de la llamada en la que DrvInst.exe rompió en el depurador de kernel. Este punto de interrupción borrará todos los puntos de interrupción establecidos durante la instalación del dispositivo y continuará la ejecución:
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"
A continuación, debe establecer algunos puntos de interrupción dentro del proceso para permitir que los comandos del programa de comandos del depurador se ejecuten en el momento adecuado durante la instalación del dispositivo.
Para asegurarse de que el punto de interrupción del instalador de clase o el punto de entrada dll de coinstalador esté establecido antes de invocar la función para la instalación del dispositivo, el programa de comandos del depurador se debe ejecutar cada vez que se cargue un archivo DLL nuevo en el proceso actual, es decir, después de una llamada a LoadLibraryExW devuelve:
kd> .reload
kd> bp[0x10] /p @$proc kernel32!LoadLibraryExW "gu;$$><Z:\\bpcoinst.txt;g"
En lugar de ejecutar el programa en cada llamada a LoadLibraryEx dentro del proceso (bp[0x10]), el desarrollador puede restringirlo para que se ejecute solo cuando el instalador de clase y los archivos DLL de coinserción se cargan en el proceso. Dado que SetupDiCallClassInstaller es la rutina que invoca instaladores de clase y coinstaladores registrados para un dispositivo, estos archivos DLL se cargarán en el proceso durante esa llamada.
Dado que no se deben realizar suposiciones sobre cuándo se descargarán estos archivos DLL desde el proceso de host deDrvInst.exe , debe asegurarse de que los puntos de interrupción pueden controlar la búsqueda de los puntos de entrada dll durante las llamadas realizadas a SetupDiCallClassInstaller desde el proceso de host deDrvInst.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
El punto de interrupción para ejecutar el programa de comandos del depurador (bp[0x10]) está deshabilitado inicialmente. Se habilita siempre que se invoca SetupDiCallClassInstaller (bp[0x11]) y la ejecución continúa. El programa de comandos del depurador (bp[0x10]) vuelve a deshabilitarse cuando SetupDiCallClassInstaller vuelve estableciendo un punto de interrupción en la dirección de retorno de esa rutina (bp[0x12]).
Tenga en cuenta que el punto de interrupción que deshabilita el programa de comandos del depurador también se borra y continúa la ejecución hasta que se llama a SetupDiCallClassInstaller de nuevo o hasta que se completa el programa de instalación y se borran todos los puntos de interrupción (bp[0x13]).
Cuando se inicia la ejecución después de establecer los puntos de interrupción anteriores, el proceso se interrumpirá en cada llamada a mycoinst! CoInstallerProc. Esto le permite depurar la ejecución del instalador de clase o del archivo DLL de coinstalador durante la instalación del dispositivo principal.
El período de tiempo predeterminado para que se complete un proceso de instalación es de 5 minutos. Si el proceso no se completa dentro del período de tiempo determinado, el sistema asume que el proceso ha dejado de responder y que finaliza.
La restricción de tiempo de espera predeterminada colocada en las instalaciones de dispositivos sigue en vigor mientras el proceso se está depurando a través del depurador de kernel. Dado que la ejecución de todos los programas del sistema se detiene mientras se divide en el depurador, se realiza un seguimiento de la cantidad de tiempo que tarda el proceso de instalación en el mismo modo que en un sistema que no se está depurando.