Escribir un controlador Hola mundo Windows (KMDF)
En este tema se describe cómo escribir un controlador universal Windows muy pequeño mediante Kernel-Mode Driver Framework (KMDF) y, a continuación, implementar e instalar el controlador en un equipo independiente.
Para empezar, asegúrese de que tiene Microsoft Visual Studio ,el SDKde Windows y Windows Driver Kit (WDK) instalados.
Las herramientas de depuración Windows se incluyen al instalar wdk.
Creación y compilación de un controlador
Abra Microsoft Visual Studio. En el menú Archivo, elija Nuevo Project.
En el cuadro de diálogo Crear un nuevo proyecto, seleccione C++ en la lista desplegable izquierda, elija Windows en la lista desplegable central y elija Controlador en la lista desplegable de la derecha.
Seleccione Kernel Mode Driver(Controlador de modo kernel), Empty (KMDF) (Controlador de modo kernel, vacío [KMDF]) en la lista de tipos de proyecto. Seleccione Next (Siguiente).
En el cuadro de diálogo Configurar el nuevo proyecto, escriba "KmdfHelloWorld" en el Project nombre.
Nota
Al crear un nuevo controlador KMDF o UMDF, debe seleccionar un nombre de controlador con 32 caracteres o menos. Este límite de longitud se define en wdfglobals.h.
En el campo Ubicación, escriba el directorio donde desea crear el nuevo proyecto.
Active Colocar la solución y el proyecto en el mismo directorio y seleccione Crear.
Visual Studio crea un proyecto y una solución. Puede verlos en la ventana Explorador de soluciones. (Si la Explorador de soluciones no está visible, elija Explorador de soluciones en el menú Ver). La solución tiene un proyecto de controlador denominado KmdfHelloWorld.
En la Explorador de soluciones, mantenga presionado (o haga clic con el botón derecho) en el proyecto KmdfHelloWorld y elija Administrador de configuración. Elija una configuración y una plataforma para el proyecto de controlador. Por ejemplo, elija Depurar y x64.
En la Explorador de soluciones, vuelva a seleccionar y mantenga presionado (o haga clic con el botón derecho) en el proyecto KmdfHelloWorld, elija Agregar y, a continuación, seleccione Nuevo elemento.
En el cuadro de diálogo Agregar nuevo elemento, seleccione Archivo de C++. En Nombre,escriba "Driver.c".
Nota
La extensión de nombre de archivo es .c,no .cpp.
Seleccione Agregar. El archivo Driver.c se agrega en Archivos de origen, como se muestra aquí.
Escritura del primer código de controlador
Ahora que ha creado el proyecto de Hola mundo vacío y ha agregado el archivo de código fuente Driver.c, escribirá el código más básico necesario para que el controlador se ejecute mediante la implementación de dos funciones básicas de devolución de llamada de eventos.
En Driver.c, empiece por incluir estos encabezados:
#include <ntddk.h> #include <wdf.h>Sugerencia
Si no puede agregar , abra Configuración
Ntddk.hNtddk.hDirectorios de incluir adicionales y agregue , reemplazando por el directorio adecuado en la instalación deC:\Program Files (x86)\Windows Kits\10\Include\<build#>\km<build#>WDK.Ntddk.h contiene definiciones de kernel Windows núcleo para todos los controladores, mientras que Wdf.h contiene definiciones de controladores basadas en Windows Driver Framework (WDF).
A continuación, proporcione declaraciones para las dos devoluciones de llamada que usará:
DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;Use el código siguiente para escribir driverEntry:
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { // NTSTATUS variable to record success or failure NTSTATUS status = STATUS_SUCCESS; // Allocate the driver configuration object WDF_DRIVER_CONFIG config; // Print "Hello World" for DriverEntry KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" )); // Initialize the driver configuration object to register the // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd WDF_DRIVER_CONFIG_INIT(&config, KmdfHelloWorldEvtDeviceAdd ); // Finally, create the driver object status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE ); return status; }DriverEntry es el punto de entrada para todos los controladores, como es para muchas aplicaciones en modo de usuario. El trabajo de DriverEntry es inicializar estructuras y recursos para todo el controlador. En este ejemplo, ha impreso "Hola mundo" para DriverEntry,ha configurado el objeto de controlador para registrar el punto de entrada de la devolución de llamada EvtDeviceAdd y, a continuación, ha creado el objeto de controlador y ha devuelto.
El objeto de controlador actúa como el objeto primario para todos los demás objetos de marco que puede crear en el controlador, que incluyen objetos de dispositivo, colas de E/S, temporizadores, bloqueos por número, etc. Para obtener más información sobre los objetos de marco de trabajo, vea Introduction to Framework Objects.
Sugerencia
Para DriverEntry,se recomienda encarecidamente mantener el nombre como "DriverEntry" para ayudar con el análisis y la depuración de código.
A continuación, use el código siguiente para escribir kmdfHelloWorldEvtDeviceAdd:
NTSTATUS KmdfHelloWorldEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) { // We're not using the driver object, // so we need to mark it as unreferenced UNREFERENCED_PARAMETER(Driver); NTSTATUS status; // Allocate the device object WDFDEVICE hDevice; // Print "Hello World" KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" )); // Create the device object status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &hDevice ); return status; }El sistema invoca EvtDeviceAdd cuando detecta que el dispositivo ha llegado. Su trabajo es inicializar estructuras y recursos para ese dispositivo. En este ejemplo, simplemente ha impreso un mensaje "Hola mundo" para EvtDeviceAdd,ha creado el objeto de dispositivo y ha devuelto. En otros controladores que escriba, puede crear colas de E/S para el hardware, configurar un espacio de almacenamiento de contexto de dispositivo para información específica del dispositivo o realizar otras tareas necesarias para preparar el dispositivo.
Sugerencia
Para que el dispositivo agregue la devolución de llamada, observe cómo la ha llamado con el nombre del controlador como prefijo (KmdfHelloWorldEvtDeviceAdd). Por lo general, se recomienda asignar un nombre a las funciones del controlador de esta manera para diferenciarlas de las funciones de otros controladores. DriverEntry es el único al que debe nombrar exactamente eso.
El archivo Driver.c completo ahora tiene el siguiente aspecto:
#include <ntddk.h> #include <wdf.h> DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd; NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { // NTSTATUS variable to record success or failure NTSTATUS status = STATUS_SUCCESS; // Allocate the driver configuration object WDF_DRIVER_CONFIG config; // Print "Hello World" for DriverEntry KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" )); // Initialize the driver configuration object to register the // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd WDF_DRIVER_CONFIG_INIT(&config, KmdfHelloWorldEvtDeviceAdd ); // Finally, create the driver object status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE ); return status; } NTSTATUS KmdfHelloWorldEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) { // We're not using the driver object, // so we need to mark it as unreferenced UNREFERENCED_PARAMETER(Driver); NTSTATUS status; // Allocate the device object WDFDEVICE hDevice; // Print "Hello World" KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" )); // Create the device object status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &hDevice ); return status; }Guarde Driver.c.
En este ejemplo se muestra un concepto fundamental de los controladores: son una "colección de devoluciones de llamada" que, una vez inicializadas, se sentan y esperan a que el sistema los llame cuando necesite algo. Podría ser un nuevo evento de llegada del dispositivo, una solicitud de E/S de una aplicación en modo de usuario, un evento de apagado del sistema, una solicitud de otro controlador o un evento de eliminación por sorpresa cuando un usuario desconecta el dispositivo inesperadamente. Afortunadamente, para decir "Hola mundo", solo tenía que preocuparse por la creación de controladores y dispositivos.
A continuación, compilará el controlador.
Compilación del controlador
En la Explorador de soluciones, mantenga presionado (o haga clic con el botón derecho) en la solución "KmdfHelloWorld" (1 proyecto) y elija Administrador de configuración. Elija una configuración y una plataforma para el proyecto de controlador. Para este ejercicio, elegimos Depurar y x64.
En la Explorador de soluciones, mantenga presionado (o haga clic con el botón derecho) KmdfHelloWorld y elija Propiedades. En Wpp Tracing All Options (Todas las opcionesde seguimiento de Wpp), establezca Run Wpp tracing (Ejecutar seguimiento de Wpp)en No. Seleccione Apply (Aplicar) y, después, OK (Aceptar).
Para compilar el controlador, elija Compilar solución en el menú Compilar. Visual Studio muestra el progreso de la compilación en la ventana Salida. (Si la ventana Salida no está visible, elija Salida en el menú Ver). Cuando haya comprobado que la solución se ha creado correctamente, puede cerrar Visual Studio.
Para ver el controlador creado, en Explorador de archivos, vaya a la carpeta KmdfHelloWorld y, a continuación, a C:\KmdfHelloWorld\x64\Debug\KmdfHelloWorld. La carpeta incluye:
- KmdfHelloWorld.sys: el archivo de controlador en modo kernel
- KmdfHelloWorld.inf: un archivo de información que Windows al instalar el controlador
- KmdfHelloWorld.cat: un archivo de catálogo que el instalador usa para comprobar la firma de prueba del controlador
Sugerencia
Si ve al compilar el controlador, cambie la configuración del proyecto DriverVer set to a date in the future de controlador para que Inf2Cat establece /uselocaltime . Para ello, use Propiedades de configuración- Inf2Cat- > General- Usar hora > local. Ahora, Stampinf e Inf2Cat usan la hora local.
Implementación del controlador
Normalmente, al probar y depurar un controlador, el depurador y el controlador se ejecutan en equipos independientes. El equipo que ejecuta el depurador se denomina equipo hosty el equipo que ejecuta el controlador se denomina equipo de destino. El equipo de destino también se denomina equipo de prueba.
Hasta ahora, ha usado Visual Studio para compilar un controlador en el equipo host. Ahora debe configurar un equipo de destino.
Siga las instrucciones de Aprovisionamiento de un equipo para la implementación y prueba de controladores (WDK 10).
Sugerencia
Cuando siga los pasos para aprovisionar el equipo de destino automáticamente mediante un cable de red, tome nota del puerto y la clave. Los usará más adelante en el paso de depuración. En este ejemplo, usaremos 50000 como puerto y 1.2.3.4 como clave.
En escenarios de depuración de controladores reales, se recomienda usar una clave generada por KDNET. Para obtener más información sobre cómo usar KDNET para generar una clave aleatoria, vea el tema Controladores de depuración: laboratorio paso a paso (modo kernel de Sysvad).
En el equipo host, abra la solución en Visual Studio. Puede hacer doble clic en el archivo de solución, KmdfHelloWorld.sln, en la carpeta KmdfHelloWorld.
En la Explorador de soluciones, mantenga presionado (o haga clic con el botón derecho) el proyecto KmdfHelloWorld y elija Propiedades.
En la ventana Páginas de propiedades kmdfHelloWorld, vaya a Propiedades de configuración Implementación de instalación del controlador , como se muestra aquí.
Active Quitar versiones anteriores del controlador antes de la implementación.
En Nombre del dispositivo dedestino , seleccione el nombre del equipo que configuró para pruebas y depuración. En este ejercicio, usamos un equipo denominado MyTestComputer.
Seleccione Hardware ID Driver Update(Actualización del controlador de id. de hardware) y escriba el identificador de hardware del controlador. Para este ejercicio, el identificador de hardware es Root\KmdfHelloWorld. Seleccione Aceptar.
Nota
En este ejercicio, el identificador de hardware no identifica un fragmento de hardware real. Identifica un dispositivo imaginario al que se le dará un lugar en el árbol de dispositivos como elemento secundario del nodo raíz. Para hardware real, no seleccione Actualización del controlador de identificador de hardware; en su lugar, seleccione Instalar y comprobar. Verá el identificador de hardware en el archivo de información del controlador (INF). En la Explorador de soluciones, vaya a KmdfHelloWorld Driver Filesy haga doble clic en KmdfHelloWorld.inf. El identificador de hardware se encuentra en [Standard.NT$ARCH$].
[Standard.NT$ARCH$] %KmdfHelloWorld.DeviceDesc%=KmdfHelloWorld_Device, Root\KmdfHelloWorldEn el menú Compilar, elija Implementar solución. Visual Studio copia automáticamente los archivos necesarios para instalar y ejecutar el controlador en el equipo de destino. Esto puede tardar un par de minutos.
Al implementar un controlador, los archivos de controlador se copian en la carpeta %Systemdrive%\drivertest\drivers del equipo de prueba. Si algo sale mal durante la implementación, puede comprobar si los archivos se copian en el equipo de prueba. Compruebe que los archivos .inf, .cat, test cert y .sys, y cualquier otro archivo necesario, están presentes en la carpeta %systemdrive%\drivertest\drivers.
Para obtener más información sobre la implementación de controladores, vea Implementación de un controlador en un equipo de prueba.
Instalación del controlador
Con el Hola mundo implementado en el equipo de destino, ahora instalará el controlador. Cuando aprovisionó previamente el equipo de destino con Visual Studio mediante la opción automática, Visual Studio configurar el equipo de destino para ejecutar controladores firmados de prueba como parte del proceso de aprovisionamiento. Ahora solo tiene que instalar el controlador mediante la herramienta DevCon.
En el equipo host, vaya a la carpeta Herramientas de la instalación de WDK y busque la herramienta DevCon. Por ejemplo, busque en la carpeta siguiente:
C:\Archivos de programa (x86)\Windows Kits\10\Tools\x64\devcon.exe
Copie la herramienta DevCon en el equipo remoto.
En el equipo de destino, instale el controlador; para ello, vaya a la carpeta que contiene los archivos de controlador y ejecute la herramienta DevCon.
Esta es la sintaxis general de la herramienta devcon que usará para instalar el controlador:
Devcon install INF file hardware ID (Id. de hardware de archivo INF de instalación de devcon) ><>
El archivo INF necesario para instalar este controlador es KmdfHelloWorld.inf. El archivo INF contiene el identificador de hardware para instalar el binario del controlador, KmdfHelloWorld.sys. Recuerde que el identificador de hardware, ubicado en el archivo INF, es Root\KmdfHelloWorld.
Abra una ventana del símbolo del sistema como administrador. Vaya a la carpeta que contiene el controlador .sys archivo y escriba este comando:
devcon install kmdfhelloworld.inf root\kmdfhelloworld
Si recibe un mensaje de error sobre que devcon no se reconoce, intente agregar la ruta de acceso a la herramienta devcon. Por ejemplo, si lo copió en una carpeta del equipo de destino denominada C:\Tools, intente usar el siguiente comando:
c:\tools\devcon install kmdfhelloworld.inf root\kmdfhelloworld
Aparecerá un cuadro de diálogo que indica que el controlador de prueba es un controlador sin signo. Seleccione Instalar este controlador de todos modos para continuar.

Depuración del controlador
Ahora que ha instalado el controlador KmdfHelloWorld en el equipo de destino, adjuntará un depurador de forma remota desde el equipo host.
En el equipo host, abra una ventana del símbolo del sistema como administrador. Cambie al directorio WinDbg.exe. Usaremos la versión x64 de WinDbg.exe del kit de controladores de Windows (WDK) que se instaló como parte de la instalación del kit de Windows. Esta es la ruta de acceso predeterminada a WinDbg.exe:
C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x64
Inicie WinDbg para conectarse a una sesión de depuración de kernel en el equipo de destino mediante el comando siguiente. El valor del puerto y la clave debe ser el mismo que el que usó para aprovisionar el equipo de destino. Usaremos 50000 para el puerto y 1.2.3.4 para la clave, los valores que usamos durante el paso de implementación. La marca k indica que se trata de una sesión de depuración de kernel.
WinDbg -k net:port=50000,key=1.2.3.4
En el menú Depurar, elija Interrumpir. El depurador del equipo host se interrumpirá en el equipo de destino. En la ventana Comando del depurador, puede ver el símbolo del sistema de depuración del kernel: kd .
En este momento, puede experimentar con el depurador si escribe comandos en el símbolo del sistema kd. Por ejemplo, podría probar estos comandos:
Para que el equipo de destino vuelva a ejecutarse, elija Ir en el menú Depurar o presione "g" y, a continuación, presione "Entrar".
Para detener la sesión de depuración, elija Desaso poder depurar en el menú Depurar.
Importante
Asegúrese de usar el comando "ir" para permitir que el equipo de destino vuelva a ejecutarse antes de salir del depurador, o el equipo de destino seguirá sin responder a la entrada del mouse y el teclado porque sigue hablando con el depurador.
Para obtener un tutorial detallado paso a paso del proceso de depuración de controladores, vea Depurar controladores universales: laboratorio paso a paso (modo kernel de eco).
Para obtener más información sobre la depuración remota, vea Depuración remota mediante WinDbg.
Temas relacionados
Desarrollo, prueba e implementación de controladores
Herramientas de depuración para Windows
Depurar controladores universales: laboratorio paso a paso (modo kernel de eco)