Cómo interpretar los códigos de error de Windows — la estructura de tres capas de Win32, HRESULT y NTSTATUS

· Actualizado el: · · Windows, Códigos de error, HRESULT, NTSTATUS, Win32 API, Investigación de fallos, Depuración, Desarrollo en Windows

«En la pantalla de la aplicación apareció un error 0x80004005. ¿Qué significa?» — en las consultas de investigación de fallos, este tipo de pregunta es muy habitual. Si se introduce directamente en un buscador el número que aparece en el cuadro de diálogo de error, suelen aparecer en masa artículos completamente ajenos al caso —fallos de Windows Update, no poder conectar con una carpeta compartida, errores en tiempo de ejecución de VBA, fallos de conexión a bases de datos…— y no son pocas las personas que han terminado más confundidas que antes.

Esto ocurre porque 0x80004005 (E_FAIL) es un código genérico que solo significa «error de detalle desconocido». Como el mismo código se usa en un sinfín de situaciones, buscar solo el código nunca lleva hasta la causa. En cambio, un código como 0x80070005 se puede descomponer en pocos segundos —antes incluso de buscar nada— si se conoce la estructura: «es el error 5 de Win32, es decir, acceso denegado, envuelto de nuevo en un HRESULT».

Por razones históricas, los códigos de error de Windows forman capas en tres sistemas —los códigos de error Win32, HRESULT y NTSTATUS— que además se convierten entre sí de una capa a otra. Una vez que se tiene esta estructura clara en la cabeza, es posible determinar por cuenta propia «de qué capa y de quién procede este código» y «cuál es el código esencial», lo que acelera enormemente el arranque de cualquier investigación.

Este artículo está dirigido al personal de sistemas de pequeñas y medianas empresas y a desarrolladores de aplicaciones Windows, y organiza —con base en Microsoft Learn y en la especificación pública [MS-ERREF] vigentes en agosto de 2026— cómo distinguir y descomponer los tres sistemas de códigos de error, su relación con las excepciones de .NET, y las formas prácticas de investigarlos con err.exe y PowerShell.

1. Conclusión principal

  • Los códigos de error de Windows se dividen principalmente en tres sistemas.Están el código de error Win32 (el número decimal pequeño que devuelve GetLastError), el HRESULT (el código de 32 bits usado desde la era COM, en hexadecimal comenzando por 0x8 o como número decimal negativo) y el NTSTATUS (el código de la capa del núcleo, cuyos errores comienzan por 0xC). 123
  • El decimal y el hexadecimal son solo dos notaciones del mismo código.«Error 5», «0x5» y «los 16 bits bajos de 0x80070005» apuntan todos a ERROR_ACCESS_DENIED (acceso denegado). 1
  • 0x8007xxxx es «un error Win32 envuelto de nuevo».Es un código de error Win32 almacenado en el FACILITY_WIN32 (7) de un HRESULT, y basta con convertir los 16 bits bajos a decimal para conocer el código esencial. Este es el patrón más importante para interpretar códigos de error. 45
  • 0x80004005 (E_FAIL) no es un código de causa.Su significado es «error no especificado» y no aporta más información que esa. En lugar de profundizar en este código, conviene buscar el contexto de origen y los registros que lo acompañan. 6
  • Un número decimal negativo (como -2147467259) es un HRESULT.Como está activo el bit más significativo de los 32 bits (el bit de fallo), al mostrarlo con signo resulta negativo. Conviértalo a hexadecimal antes de leerlo. 2
  • Un valor de 8 cifras que empieza por 0xC es un NTSTATUS.0xC0000005 (violación de acceso) o 0xC0000135 (DLL no encontrada) aparecen con frecuencia en el Visor de eventos o en los volcados al producirse un bloqueo. No tienen relación alguna con el error 5 de Win32. 7
  • Incluso el mismo código cambia de significado según el contexto.Las causas del error 5 son diversas —listas de control de acceso (ACL), elevación de privilegios, software antivirus, bloqueo por otro proceso, etc.—, y no es raro que el «archivo no encontrado» del error 2 se refiera en realidad a una DLL dependiente. Lea siempre juntos el significado del código y qué API falló sobre qué recurso. 1
  • Las herramientas de conversión y búsqueda ya vienen incluidas de serie.certutil -error y net helpmsg son estándar en Windows, Win32Exception de PowerShell permite obtener el mensaje, en un equipo de desarrollo se puede usar err.exe (Microsoft Error Lookup Tool), y para analizar volcados está el comando !error de WinDbg. 8910
  • En .NET, el HRESULT se asigna a un tipo de excepción.Un HRESULT conocido se convierte en su tipo de excepción correspondiente (por ejemplo, E_ACCESSDENIED → UnauthorizedAccessException), y uno desconocido se convierte en COMException; en ambos casos, el valor original queda en Exception.HResult. 11

Resumido en una frase, el método para investigar códigos de error de Windows es: «uniformar la notación a hexadecimal → determinar de qué capa procede el código → descomponerlo para extraer el código esencial → leerlo junto con el contexto».

2. Windows tiene tres sistemas de códigos de error

Empecemos con el mapa general. Los códigos de error de Windows se dividen principalmente en los siguientes tres sistemas, según la capa que los devuelve.

Sistema Principal origen Aspecto típico Ejemplo representativo
Código de error Win32 API de Win32 (GetLastError), código de salida de comandos Número decimal pequeño (0-15999) 5 = ERROR_ACCESS_DENIED
HRESULT Componentes COM, el shell, instaladores, muchos frameworks Hexadecimal de 8 cifras que empieza por 0x8, o número decimal negativo 0x80004005 = E_FAIL
NTSTATUS El núcleo, controladores, la API nativa (ntdll) Los errores son hexadecimales de 8 cifras que empiezan por 0xC 0xC0000005 = STATUS_ACCESS_VIOLATION

Históricamente, estas capas se han ido acumulando en este orden: primero el código de error Win32, que heredó los números de error de MS-DOS; después el NTSTATUS, que usa internamente el núcleo de NT; y por último el HRESULT, diseñado al introducirse COM para «empaquetar en 32 bits el éxito/fallo y el origen». En el Windows actual, es habitual el siguiente flujo de conversión: el núcleo devuelve un NTSTATUS, el subsistema Win32 lo convierte en un código de error Win32, y la capa COM lo vuelve a envolver en un HRESULT. 124

Flujo de conversión entre los tres sistemasEl NTSTATUS devuelto por el núcleo se convierte en código de error Win32 por el subsistema Win32, y la capa COM lo envuelve de nuevo en un HRESULTEl subsistema Win32 lo convierteLa capa COM lo envuelveNúcleo y controladoresNTSTATUS(errores 0xC…)Código de error Win32(p. ej., 5)HRESULT(0x8007xxxx)

Figura 1: Flujo de conversión entre capas. El NTSTATUS del núcleo se convierte en error Win32 y luego se envuelve de nuevo en un HRESULT.

2.1. Acostúmbrese a convertir entre decimal y hexadecimal

Antes de distinguir entre los tres sistemas, hay que absorber la variación de notación, ya que un mismo código puede mostrarse tanto en decimal como en hexadecimal según la situación.

  • «Error 5» y «Código de error: 0x5» → el mismo ERROR_ACCESS_DENIED
  • «Error 1223» y «0x4C1» → el mismo ERROR_CANCELLED
  • «0x80070005» y «-2147024891» → el mismo HRESULT

Con PowerShell, esta conversión se resuelve en una sola línea.

# Decimal → hexadecimal
'0x{0:X8}' -f 1223          # 0x000004C1
'0x{0:X8}' -f -2147024891   # 0x80070005 (negativo = HRESULT en hexadecimal)

# Hexadecimal → decimal
0x4C1                        # 1223

En cuanto vea un número decimal negativo que empiece por «-214…», conviértalo a hexadecimal por reflejo.Solo con eso se reduce enormemente la posibilidad de perderse nada más empezar la investigación.

Tres aspectos del mismo códigoEl decimal error 5, el hexadecimal 0x5 y los 16 bits bajos de 0x80070005 apuntan todos al mismo ERROR_ACCESS_DENIEDNotación decimal «error 5»ERROR_ACCESS_DENIEDNotación hexadecimal «0x5»16 bits bajos de 0x80070005Solo cambia la notación; es el mismo código

Figura 2: El decimal, el hexadecimal y los 16 bits bajos de un HRESULT no son más que distintas notaciones del mismo código.

3. Códigos de error Win32 — GetLastError y FormatMessage

3.1. Funcionamiento básico de GetLastError

Muchas API de Win32, como CreateFile o RegOpenKeyEx, indican el fallo mediante su valor de retorno (FALSE, NULL, INVALID_HANDLE_VALUE, etc.) y almacenan el código de error detallado en el «código de error final», mantenido por cada subproceso (thread). Quien realiza la llamada debe obtenerlo con GetLastError inmediatamente después de comprobar el fallo. 13

Aquí hay dos advertencias prácticas. 13

  1. Léalo justo después del fallo.Si intercala otra llamada a una API (como una función de registro de logs) entre medias, esa llamada puede sobrescribir el código de error final.
  2. No confíe en el valor cuando la llamada tiene éxito.Algunas API ponen a 0 el código de error final al tener éxito, mientras que otras no lo tocan. La regla es confirmar primero el fallo mediante el valor de retorno y solo entonces leer el código.
GetLastError se lee justo tras el falloTras confirmar el fallo por el valor de retorno, se obtiene el código de error final con GetLastError de inmediato, sin intercalar otras llamadas a la APIAPI de Win32AplicaciónAPI de Win32AplicaciónSi se intercala otra API, el valor puede sobrescribirseLlamada a CreateFileValor de retorno de falloGetLastErrorCódigo 5

Figura 3: El código de error final se lee justo después del fallo. Si se intercala otra llamada a la API, puede sobrescribirse.

Para obtener la cadena de mensaje a partir del código, se usa FormatMessage con el indicador FORMAT_MESSAGE_FROM_SYSTEM. 1

#include <windows.h>
#include <stdio.h>

void PrintLastError(const wchar_t* apiName)
{
    DWORD code = GetLastError();   // Llamar justo tras el fallo (sin intercalar otras API)
    wchar_t message[512] = L"";
    FormatMessageW(
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr, code, 0, message, 512, nullptr);
    wprintf(L"%s failed: %lu (0x%08lX) %s", apiName, code, code, message);
}

En los registros de sus propias aplicaciones, dejar constancia así tanto del valor decimal como del hexadecimal junto con el texto del mensaje acelera considerablemente las investigaciones posteriores.

Obtener el mensaje a partir del código y registrarlo en el logSe especifica el indicador FORMAT_MESSAGE_FROM_SYSTEM en FormatMessage para obtener la cadena de mensaje del código de error, y en el log se deja constancia del decimal, el hexadecimal y el texto del mensajeCódigo de error(p. ej., 5)Obtener cadena con FormatMessageTexto del mensajeRegistrar en el logAnotar decimal, hexadecimal y texto juntos

Figura 4: El código de error se convierte en cadena de mensaje con FormatMessage, y en el log se anotan juntos el decimal, el hexadecimal y el texto.

3.2. Códigos representativos frecuentes en el trabajo diario

Los códigos de error Win32 están definidos en el rango de 0 a 15999, y Microsoft Learn ofrece el listado completo. 1 Entre ellos, los que se encuentran una y otra vez en la investigación de fallos son los siguientes.

Decimal Hexadecimal Símbolo Significado
2 0x2 ERROR_FILE_NOT_FOUND No se encuentra el archivo especificado
3 0x3 ERROR_PATH_NOT_FOUND No se encuentra la ruta especificada
5 0x5 ERROR_ACCESS_DENIED Acceso denegado
32 0x20 ERROR_SHARING_VIOLATION No se puede acceder porque otro proceso lo está usando
87 0x57 ERROR_INVALID_PARAMETER El parámetro no es correcto
122 0x7A ERROR_INSUFFICIENT_BUFFER El búfer proporcionado es demasiado pequeño
998 0x3E6 ERROR_NOACCESS Acceso no válido a una posición de memoria
1223 0x4C1 ERROR_CANCELLED El usuario canceló la operación

De estos, el 998 (ERROR_NOACCESS) no es «acceso denegado», sino la representación en Win32 de una violación de acceso a memoria: es la forma que toma en la capa Win32 el STATUS_ACCESS_VIOLATION de NTSTATUS que se explica más adelante. Tenga cuidado de no confundirlo con el error 5. Por su parte, el 1223 (ERROR_CANCELLED) es un código que aparece, por ejemplo, cuando el usuario elige «No» en el cuadro de diálogo de elevación de UAC, y que indica más bien que la operación «se canceló» que un error propiamente dicho.

Los errores 998 y 5 son cosas distintasEl 998 es la violación de acceso a memoria que resulta de convertir a la capa Win32 la violación de acceso de NTSTATUS, y su significado difiere del 5, que representa acceso denegadoSe convierte a la capa Win32NTSTATUS 0xC0000005Error 998(ERROR_NOACCESS)Significa violación de acceso a memoriaError 5(acceso denegado)Es un problema de permisos, distinto del 998

Figura 5: El error 998 es la forma que toma en la capa Win32 la violación de acceso de NTSTATUS, y es distinto del 5, que representa acceso denegado.

3.3. El mismo código cambia de significado según el contexto

Más importante que memorizar la tabla de códigos representativos es asimilar la idea de que el código de error solo indica «el tipo de fallo».

  • Error 5 (acceso denegado): Las causas posibles son muy variadas: permisos NTFS insuficientes, intento de escritura en una zona protegida sin privilegios de administrador, bloqueo por parte de software antivirus o AppLocker, permisos insuficientes de la cuenta de servicio, etc.
  • Error 2 (archivo no encontrado): No necesariamente se trata del archivo indicado por el usuario. Puede ser una DLL dependiente que el ejecutable intentaba cargar implícitamente, un archivo de configuración que apuntaba a otra ubicación por la redirección del Registro (32/64 bits), o una ruta cuya expansión de variable de entorno falló. El código por sí solo no dice «qué archivo» falta.
  • Error 32 (violación de uso compartido): La pregunta clave es «qué proceso lo tiene abierto», pero el código no lo dice.
La causa del error 5 depende del contextoAun tratándose del mismo acceso denegado hay varias causas posibles como falta de ACL o de privilegios de administrador y es necesario identificar sobre qué falló cada APIError 5(acceso denegado)ACL insuficienteSin privilegios de administradorBloqueo del antivirusPermisos de servicio insuficientesIdentificar el objetivo con Procmon

Figura 6: El código solo indica el «tipo de fallo». El error 5 tiene varias causas posibles y hace falta identificar el objetivo afectado.

La herramienta que permite observar en la práctica «qué API, sobre qué nombre de objeto, devolvió qué resultado» es Process Monitor. Su uso se trata en detalle en «Guía práctica de Process Monitor (ProcMon)». Considere que investigar el significado del código de error e identificar el objeto que falló son las dos ruedas de un mismo vehículo.

4. HRESULT — cómo leer la estructura empaquetada en 32 bits

4.1. Disposición de bits

HRESULT es un formato que empaqueta en un único valor de 32 bits el éxito/fallo, el origen y el código detallado. La especificación pública [MS-ERREF] lo define con la siguiente disposición. 2

Posición de bit Nombre Significado
31 S Gravedad. 0 = éxito, 1 = fallo
30 R Reservado (parte de la gravedad al mapear desde NTSTATUS)
29 C Bit Customer. Si es 1, el código lo definió una entidad distinta de Microsoft
28 N Si es 1, se trata de un valor NTSTATUS mapeado al espacio de HRESULT
27 X Reservado (0)
26–16 Facility Código de facility que indica el origen (11 bits)
15–0 Code Código detallado dentro de la facility (16 bits)

Cuando el bit S más significativo es 1, es decir, cuando un HRESULT empieza en hexadecimal por 0x8 o más, significa fallo. Al mostrarlo como entero de 32 bits con signo, resulta negativo: esta es la verdadera identidad del «-214…» mencionado antes.

Relación entre el bit S y la representación negativaUn HRESULT de fallo tiene el bit S más significativo en 1 por lo que en hexadecimal empieza por 0x8 o más y al mostrarse como entero de 32 bits con signo resulta negativoBit S = 1(fallo)En hexadecimal empieza por 0x8 o másCon signo, se muestra como negativoAl ver un negativo, conviértalo a hexadecimal

Figura 7: Un HRESULT de fallo tiene el bit S en 1, por lo que empieza por 0x8 o más y se muestra como negativo con signo.

Los valores representativos de Facility son los siguientes. 5

Facility Valor Aspecto en hexadecimal Significado
FACILITY_NULL 0 0x8000xxxx Códigos comunes de uso general (E_FAIL, E_UNEXPECTED, etc.)
FACILITY_RPC 1 0x8001xxxx Procedentes de RPC
FACILITY_ITF 4 0x8004xxxx Errores definidos por la interfaz (el significado depende de cada interfaz)
FACILITY_WIN32 7 0x8007xxxx Un código de error Win32 envuelto de nuevo
FACILITY_WINDOWS 8 0x8008xxxx Interfaces adicionales definidas por Microsoft

4.2. Descomponiendo 0x80004005 y 0x80070005

Vamos a descomponerlo en la práctica.

Caso de 0x80004005: S = 1 (fallo), Facility = (0x80004005 » 16) & 0x7FF = 0 (FACILITY_NULL), Code = 0x4005. Es un código genérico de FACILITY_NULL, cuya definición es E_FAIL, «error no especificado» (Unspecified failure). 6 Es decir, este código solo significa «un fallo cuyo detalle no se puede reportar». Al ver 0x80004005, lo correcto es dejar ahí la profundización en el código en sí y trasladar el eje de la investigación a «qué componente lo devolvió» y «si hay detalles en el Visor de eventos o en el registro de la aplicación en ese mismo momento».

Caso de 0x80070005: S = 1, Facility = 7 (FACILITY_WIN32), Code = 0x0005 = 5. Se comprueba que es el error 5 de Win32 (ERROR_ACCESS_DENIED) envuelto de nuevo en un HRESULT. El alias E_ACCESSDENIED corresponde en realidad a este mismo valor. 6

Aunque ambos hablan de «acceso denegado», 0x80070005 es el envoltorio de un fallo concreto ocurrido en la capa Win32, y su cantidad de información es completamente distinta de la de 0x80004005.

Descomposición de 0x80004005 y 0x800700050x80004005 es el código genérico E_FAIL de FACILITY_NULL sin detalle por lo que hay que pasar a la investigación de contexto y 0x80070005 es de FACILITY_WIN32 y se identifica como el envoltorio del error Win32 5 de acceso denegado0x80004005Facility=0(FACILITY_NULL)Code=0x4005 → E_FAILFallo no especificado. Pasar al contexto0x80070005Facility=7(FACILITY_WIN32)Code=0x0005 → 5ERROR_ACCESS_DENIED

Figura 8: Aunque ambos son «fallos», al descomponerlos su información difiere. 0x80070005 permite rastrear hasta el error Win32 5.

4.3. El patrón más importante: 0x8007xxxx = HRESULT_FROM_WIN32

Para transmitir a la capa superior que devuelve HRESULT (métodos COM o el runtime de .NET) el fallo de una capa inferior que solo puede devolver un código de error Win32, winerror.h incluye la macro HRESULT_FROM_WIN32. 4 Su funcionamiento consiste en «colocar el código de error Win32 en los 16 bits bajos, asignar FACILITY_WIN32 (7) a Facility y poner el bit S en 1».

Funcionamiento de HRESULT_FROM_WIN32Se almacena el código de error Win32 en los 16 bits bajos se asigna 7 a Facility y 1 al bit S para construir el HRESULT 0x8007xxxxCódigo de error Win32(p. ej., 5)Almacenar en los 16 bits bajosAsignar 7 a FacilityPoner el bit S en 10x80070005

Figura 9: HRESULT_FROM_WIN32 almacena el error Win32 en los 16 bits bajos y activa Facility=7 y el bit S.

ERROR_ACCESS_DENIED (5)        --HRESULT_FROM_WIN32-->  0x80070005
ERROR_SHARING_VIOLATION (32)   --HRESULT_FROM_WIN32-->  0x80070020
ERROR_INVALID_PARAMETER (87)   --HRESULT_FROM_WIN32-->  0x80070057 (= E_INVALIDARG)
ERROR_OUTOFMEMORY (14)         --HRESULT_FROM_WIN32-->  0x8007000E (= E_OUTOFMEMORY)

Para leerlo en sentido inverso, se extraen los 16 bits bajos con PowerShell.

0x80070005 -band 0xFFFF   # 5 → ERROR_ACCESS_DENIED
0x80072EE7 -band 0xFFFF   # 12007 → ERROR_INTERNET_NAME_NOT_RESOLVED (WinINet)

Como en el segundo ejemplo, los errores de WinINet o WinHTTP (los del rango 12000) también están definidos dentro del espacio de códigos de error Win32 1, así que los 0x8007xxxx relacionados con redes también se pueden descomponer con el mismo procedimiento. Interiorizar el reflejo de «al ver 0x8007, convertir las últimas cuatro cifras a decimal» es la habilidad práctica principal que le proponemos llevarse de este artículo.

Por otro lado, con 0x8004xxxx (FACILITY_ITF) hay una advertencia inversa. Como en los códigos de FACILITY_ITF la entidad que define el significado varía según la interfaz, un mismo valor de 32 bits puede significar cosas distintas si lo devuelve un origen diferente. 5 Ante un 0x8004xxxx poco familiar, en lugar de una búsqueda genérica, consulte la documentación del componente que lo devolvió (la biblioteca, el SDK del controlador o el producto servidor correspondiente).

La forma de investigar cambia entre 0x8007 y 0x8004El 0x8007xxxx de FACILITY_WIN32 se lee con la descomposición mecánica de los 16 bits bajos mientras que el 0x8004xxxx de FACILITY_ITF tiene un significado definido de forma distinta según la interfaz por lo que hay que consultar la documentación del componente que lo devolvió7, WIN324, ITF¿Cuál es Facility?Convertir los 16 bits bajos a decimalEl significado varía según quien lo devuelveLeerlo como error Win32Consultar la documentación del origen

Figura 10: 0x8007xxxx se puede descomponer mecánicamente, pero 0x8004xxxx hay que consultarlo en la documentación del componente que lo devolvió.

5. NTSTATUS — códigos de la capa del núcleo y el mundo de los bloqueos

5.1. Disposición y Severity (gravedad)

NTSTATUS es un código de 32 bits usado por el núcleo, los controladores de dispositivo y la API nativa de ntdll, y su disposición se parece a la del HRESULT sin ser idéntica. 3

Posición de bit Nombre Significado
31–30 Sev Gravedad. 00 = éxito, 01 = información, 10 = advertencia, 11 = error
29 C Bit Customer
28 N Reservado (0, para permitir el mapeo a HRESULT)
27–16 Facility Facility (12 bits)
15–0 Code Código detallado

Como la gravedad ocupa 2 bits, el tipo se puede leer con la primera cifra hexadecimal. 0xC… es error (11), 0x8… es advertencia (10), 0x4… es información (01), y 0x0 a 0x3… es éxito. El ejemplo representativo de «advertencia, no error» es la excepción de punto de interrupción 0x80000003 (STATUS_BREAKPOINT). 37

NTSTATUS se distingue por su primera cifraComo la gravedad ocupa 2 bits en NTSTATUS la primera cifra hexadecimal indica error si es 0xC advertencia si es 0x8 información si es 0x4 y éxito si es 0x0 a 0x30xC0x80x40x0 a 0x3¿Cuál es la primera cifra hexadecimal?ErrorAdvertenciaInformaciónÉxitoP. ej.: 0x80000003 es una advertencia

Figura 11: NTSTATUS se distingue por su primera cifra hexadecimal. 0x80000003 es «una advertencia, no un error».

5.2. Dónde aparece — código de excepción, código STOP y el registro de eventos

Las situaciones en las que el personal de sistemas o los desarrolladores se encuentran con un NTSTATUS son, principalmente, las relacionadas con bloqueos de aplicaciones.

  • El código de excepción de un bloqueo de aplicación: El «código de excepción: 0xc0000005» que se registra en «Application Error (ID de evento 1000)» del Visor de eventos es un NTSTATUS. Los valores representativos son los siguientes. 7
Valor Símbolo Significado
0xC0000005 STATUS_ACCESS_VIOLATION Violación de acceso (acceso incorrecto a memoria)
0xC0000135 STATUS_DLL_NOT_FOUND No se encuentra una DLL necesaria y no se puede iniciar
0xC00000FD STATUS_STACK_OVERFLOW Desbordamiento de pila
0xC0000374 STATUS_HEAP_CORRUPTION Daño en el montón (heap)
  • El código STOP de la pantalla azul: A primera vista se parece, pero el código STOP (bug check code), como 0x0000009F (DRIVER_POWER_STATE_FAILURE), pertenece a un sistema de numeración propio distinto del de NTSTATUS, con su propia referencia dedicada. 14 Basta con recordar la distinción: «0xC0000005 es NTSTATUS; STOP 0x9F es un código de comprobación de errores (bug check) y no debe buscarse en la tabla de NTSTATUS».
  • La columna Result de Process Monitor: NAME NOT FOUND o ACCESS DENIED, que aparecen en la columna Result de Procmon, son los nombres visibles de los NTSTATUS devueltos por el núcleo (STATUS_OBJECT_NAME_NOT_FOUND o STATUS_ACCESS_DENIED). Es también el lugar donde se puede sentir en carne propia la correspondencia entre capas: se observa el fallo de E/S de archivos en el vocabulario de NTSTATUS, y ese valor se convierte en un error Win32 antes de llegar a la aplicación.
Distinguir el código de excepción del código STOPEl código de excepción del Visor de eventos se lee como NTSTATUS y el código STOP de la pantalla azul se consulta en la referencia dedicada de códigos de comprobación de errores de otro sistemaCódigo de excepciónCódigo STOP¿Dónde apareció el código?Leerlo como NTSTATUSConsultar la tabla de bug check codesP. ej.: 0xC0000005P. ej.: 0x0000009F

Figura 12: El código de excepción del Visor de eventos es NTSTATUS, y el código STOP de la pantalla azul pertenece a otro sistema. No confunda la tabla en la que consultarlos.

Para la investigación posterior al código de excepción, es decir, la captura y el análisis de volcados de memoria (crash dumps), consulte «Introducción a la captura de volcados de memoria en Windows» y «Leer volcados de memoria con WinDbg + SOS».

5.3. Relación con HRESULT — el bit N y RtlNtStatusToDosError

El puente entre NTSTATUS y las otras dos capas se puede establecer de dos maneras.

  1. Mapeo al espacio de HRESULT: Al activar el bit N (0x10000000) de HRESULT, se puede llevar el valor NTSTATUS directamente al espacio de HRESULT (la macro HRESULT_FROM_NT de winerror.h). Por ejemplo, al mapear 0xC0000005 se obtiene 0xD0000005. El procedimiento correcto es: al ver un HRESULT que empieza por 0xD, quitar el bit N y leerlo como NTSTATUS. 2
  2. Conversión a código de error Win32: RtlNtStatusToDosError, de ntdll, convierte un NTSTATUS en su código de error Win32 correspondiente. Los valores sin correspondencia definida se convierten en ERROR_MR_MID_NOT_FOUND. 12 Por ejemplo, STATUS_ACCESS_VIOLATION (0xC0000005) se convierte en ERROR_NOACCESS (998), y STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034) se convierte en ERROR_FILE_NOT_FOUND (2). También conviene recordar que el rico vocabulario del núcleo a veces se reduce a categorías más gruesas en la capa Win32.
Dos puentes de NTSTATUS hacia las otras capasNTSTATUS pasa a las otras capas por dos vías, activando el bit N para mapear al espacio de HRESULT o convirtiendo con RtlNtStatusToDosError al código de error Win32Activar el bit NRtlNtStatusToDosErrorNTSTATUS(0xC0000005)HRESULT(0xD0000005)Error Win32 998(ERROR_NOACCESS)Sin correspondencia definida: ERROR_MR_MID_NOT_FOUND

Figura 13: NTSTATUS tiene dos puentes. Ante un valor que empieza por 0xD, quite el bit N y léalo como NTSTATUS.

6. COM y .NET — cómo se asignan los códigos de error a las excepciones

6.1. El enfoque de COM — HRESULT + IErrorInfo

Los métodos COM devuelven básicamente un HRESULT, pero como la información que cabe en 32 bits es limitada, existe el mecanismo complementario IErrorInfo para transmitir por separado el texto explicativo del error y su origen. En C++, la clase _com_error, con soporte del compilador, gestiona conjuntamente el HRESULT y el IErrorInfo. Las aplicaciones cuyo cuadro de diálogo de error muestra «código + texto explicativo» suelen transportar ese texto mediante este mecanismo.

IErrorInfo complementa al HRESULTComo la información que cabe en un HRESULT de 32 bits es limitada el texto explicativo del error y su origen se transmiten por separado con IErrorInfo y en C++ la clase _com_error los gestiona juntosHRESULT(solo 32 bits)La información que cabe es limitadaIErrorInfo transporta el texto explicativo_com_error los gestiona juntosCódigo + texto explicativo en el diálogo

Figura 14: El texto explicativo que no cabe en los 32 bits del HRESULT lo transporta por separado IErrorInfo.

6.2. El enfoque de .NET — de HRESULT al tipo de excepción

El runtime de .NET, al recibir un fallo de HRESULT mediante la interoperabilidad COM, lo convierte en una excepción. Un HRESULT conocido se asigna a su tipo de excepción correspondiente, y uno desconocido se convierte en COMException. 11

Mapeo de HRESULT a excepciones de .NETEl HRESULT de fallo recibido mediante interoperabilidad COM se convierte en su tipo de excepción correspondiente si es conocido o en COMException si no lo es y en ambos casos el valor original se conserva en Exception.HResultNoHRESULT de fallo¿Existe una correspondencia conocida?Convertir al tipo de excepción correspondienteConvertir a COMExceptionEl valor original se conserva en Exception.HResult

Figura 15: .NET asigna el HRESULT a un tipo de excepción, y en cualquiera de ellas el valor original se conserva en Exception.HResult.

HRESULT Tipo de excepción de .NET
E_ACCESSDENIED (0x80070005) UnauthorizedAccessException
E_OUTOFMEMORY (0x8007000E) OutOfMemoryException
E_INVALIDARG (0x80070057) ArgumentException
E_NOTIMPL (0x80004001) NotImplementedException
Valor sin correspondencia definida COMException (el valor original queda en la propiedad ErrorCode)

En cualquier excepción, el HRESULT original se conserva en la propiedad Exception.HResult. Una bifurcación como «reintentar solo cuando se trate de una violación de uso compartido» en el manejo de excepciones de E/S de archivos se puede escribir usando este valor.

try
{
    using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException ex) when (ex.HResult == unchecked((int)0x80070020))
{
    // 0x80070020 = HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION)
    // Otro proceso tiene el archivo abierto — esperar un momento y reintentar, por ejemplo
}

6.3. P/Invoke y GetLastError

Cuando se llama directamente a una API de Win32 mediante P/Invoke, hay que especificar SetLastError = true en DllImport (o LibraryImport) y obtener el código con Marshal.GetLastWin32Error (en .NET 6 en adelante, el equivalente GetLastPInvokeError). Definir y llamar a GetLastError directamente mediante P/Invoke es impreciso, porque las llamadas internas del runtime a otras API pueden sobrescribir el valor. 15

Obtener el error final con P/InvokeLo correcto es poner SetLastError en true y obtenerlo con Marshal.GetLastWin32Error mientras que llamar directamente a GetLastError mediante P/Invoke resulta impreciso por la sobrescritura del runtimeLlamar a una API de Win32 con P/InvokeEspecificar SetLastError=trueObtener con GetLastWin32ErrorDefinición que llama directamente a GetLastErrorEl runtime lo sobrescribe: impreciso

Figura 16: En P/Invoke se usan juntos SetLastError=true y Marshal.GetLastWin32Error. Llamar directamente a GetLastError es impreciso.

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFileW(string fileName, uint access, uint share,
    IntPtr security, uint disposition, uint flags, IntPtr template);

// Recibir el valor de retorno como SafeFileHandle, no como IntPtr, y cerrarlo con seguridad mediante using
// (si se deja como IntPtr, el identificador del núcleo puede filtrarse)
using var handle = CreateFileW(@"C:\ProgramData\MyApp\config.dat",
    0x80000000 /*GENERIC_READ*/, 0, IntPtr.Zero, 3 /*OPEN_EXISTING*/, 0, IntPtr.Zero);
if (handle.IsInvalid)
{
    int code = Marshal.GetLastWin32Error();              // P. ej.: 5
    var message = new Win32Exception(code).Message;       // P. ej.: Acceso denegado.
    logger.LogError("CreateFileW failed: {Code} (0x{Code:X8}) {Message}",
        code, code, message);
}

Win32Exception obtiene la cadena de mensaje del sistema operativo a partir del código de error Win32, por lo que se puede usar tal cual para dejar en el log tanto el código como el mensaje. El diseño de en qué capa capturar (catch) la excepción y cómo registrarla en el log se trata en «Dónde deben ir el catch y el log en el manejo de excepciones».

7. Herramientas prácticas de conversión e investigación — referencia rápida para copiar y pegar

7.1. err.exe (Microsoft Error Lookup Tool)

Es una herramienta de búsqueda de errores distribuida por Microsoft como un único archivo ejecutable. Recorre numerosos archivos de cabecera, como winerror.h o ntstatus.h, y enumera las definiciones y mensajes que coinciden con el código indicado. 8

err 0x80070005
err 5
err 0xC0000005

Un mismo número puede coincidir en varias cabeceras a la vez (por ejemplo, «5» coincide, además de con ERROR_ACCESS_DENIED de Win32, con definiciones de otros lugares), así que hay que elegir según el contexto cuál de los candidatos es el correcto. Tenga en cuenta también que el nombre del archivo de descarga incluye la versión (en el momento de escribir este artículo, Err_6.4.5.exe) y que las definiciones de los códigos se basan en las cabeceras vigentes en el momento en que se empaquetó. 8

Elegir entre los resultados de err.exe según el contextoComo err.exe recorre numerosas cabeceras y enumera las definiciones coincidentes cuando un mismo número da varios candidatos hay que elegir el adecuado según el contextoSe escribe err 5Búsqueda cruzada en numerosas cabecerasCoinciden varias definicionesElegir el candidato adecuado según el contexto

Figura 17: Como err.exe busca en varias cabeceras a la vez, pueden aparecer varios candidatos, y el adecuado se elige según el contexto.

7.2. Comandos estándar de Windows

Sin necesidad de instalar nada adicional, se pueden usar certutil y net helpmsg. La opción -error de certutil muestra el texto del mensaje correspondiente al código de error, y acepta tanto HRESULT en hexadecimal como valores en decimal. 9

certutil -error 0x80070005
certutil -error 5
net helpmsg 5

net helpmsg es exclusivo para códigos de error Win32 en decimal, pero como en un entorno en el idioma configurado del sistema devuelve el mensaje en ese mismo idioma, se puede usar tal cual para explicárselo al usuario.

Uso diferenciado de los comandos estándarEl código de error Win32 en decimal se investiga con net helpmsg y el código que incluye un HRESULT en hexadecimal se investiga con la opción -error de certutilWin32 en decimalIncluye hexadecimal¿Qué tipo de código tiene?net helpmsgcertutil -errorDevuelve el mensaje en el idioma del sistemaAcepta tanto hexadecimal como decimal

Figura 18: Uso diferenciado de los comandos estándar. El error Win32 en decimal, con net helpmsg; si incluye hexadecimal, con certutil -error.

7.3. Colección de comandos de una línea en PowerShell

# Código de error Win32 → cadena de mensaje del sistema operativo
[System.ComponentModel.Win32Exception]::new(5).Message
# → Acceso denegado.

# Decimal negativo → notación hexadecimal (confirmar la verdadera identidad del HRESULT)
'0x{0:X8}' -f -2147467259     # 0x80004005

# 0x8007xxxx → código de error Win32 en los 16 bits bajos
0x80070005 -band 0xFFFF        # 5

# HRESULT → confirmar la excepción que asigna .NET
[System.Runtime.InteropServices.Marshal]::GetExceptionForHR(-2147024891)
# → UnauthorizedAccessException (0x80070005)

# Código de error Win32 → HRESULT (reproducir el reenvoltorio)
'0x{0:X8}' -f (0x80070000 -bor 32)   # 0x80070020

7.4. El comando !error de WinDbg

Si necesita comprobar un código durante el análisis de un volcado, la extensión !error de WinDbg es la vía más rápida. Por defecto lo interpreta como código de error Win32, y si se añade 1 como segundo argumento, lo interpreta como NTSTATUS. 10

0:000> !error 5
Error code: (Win32) 0x5 (5) - アクセスが拒否されました。

0:000> !error 0xc0000005 1
Error code: (NTSTATUS) 0xc0000005 - <アクセス違反>

En el análisis de volcados, !analyze -v muestra automáticamente el código de excepción (NTSTATUS); a partir de ahí, el flujo consiste en confirmar su significado con !error <código> 1.

Flujo de comprobación del código de excepción en WinDbgEn el análisis de volcados el comando analyze muestra automáticamente el código de excepción y ese código se pasa a la extensión error con el segundo argumento 1 para confirmar su significado como NTSTATUSAbrir el volcado de memoriaEjecutar !analyze -vSe muestra el código de excepciónConfirmar el significado con !error código 1

Figura 19: En el análisis de volcados, se toma el código de excepción mostrado por !analyze -v y se investiga con !error añadiendo el indicador 1.

8. Procedimiento de investigación — de identificar la capa a contrastar con el contexto

A partir de lo visto hasta ahora, vamos a construir el procedimiento real para investigar un código de error.

  1. Uniformar la notación.Si es un decimal negativo, conviértalo a hexadecimal de 8 cifras. Un hexadecimal de menos de 8 cifras se lee rellenando con ceros a la izquierda.
  2. Determinar de qué capa procede el código.Como muestra la tabla de criterios de más abajo, casi siempre se decide por las primeras cifras.
  3. Descomponerlo para extraer el código esencial.Es una operación mecánica: los 16 bits bajos si es 0x8007xxxx, o quitar el bit N si es 0xDxxxxxxx.
  4. Consultar el nombre y la definición con una herramienta.Confirme el nombre simbólico y el mensaje con err.exe, certutil o !error.
  5. Contrastarlo con el contexto.Identifique, mediante el log de la aplicación, el Visor de eventos o Procmon, en qué aplicación, con qué operación, qué API falló y sobre qué recurso. El código indica «el tipo de fallo»; el contexto indica «dónde está la causa».
Procedimiento de investigación de un código de errorSe uniforma la notación a hexadecimal se determina la capa por las primeras cifras se descompone para extraer el código esencial se consulta el nombre y la definición con una herramienta y por último se contrasta con el contextoNotación decimal0x80070xC0xDUniformar la notación(negativos a hex de 8 cifras)¿Cuáles son las primeras cifras?Leerlo como error Win32Convertir a decimal los 16 bits bajosLeerlo como NTSTATUSQuitar el bit N y leerloConsultar el nombre y la definición con una herramientaContrastarlo con el contexto(Procmon, etc.)

Figura 20: El método de investigación. Se uniforma la notación, se determina la capa, se descompone, se consulta el nombre y por último se contrasta con el contexto.

Aspecto Primera hipótesis Método de descomposición o conversión
Número decimal de 1 a 5 cifras (5, 1223, etc.) Código de error Win32 Tal cual, a net helpmsg o err.exe
Decimal negativo (-2147024891, etc.) HRESULT Convertir a hexadecimal de 8 cifras y pasar a la fila siguiente
0x8007xxxx HRESULT (FACILITY_WIN32) Convertir a decimal los 16 bits bajos y leerlo como Win32
0x8004xxxx HRESULT (FACILITY_ITF) Consultarlo en la documentación del componente que lo devolvió
0x8000xxxx HRESULT (FACILITY_NULL) Código genérico como E_FAIL. Trasladar el eje a la investigación de contexto
0xCxxxxxxx NTSTATUS (error) !error <código> 1; si es necesario, convertir a Win32 y leerlo
0xDxxxxxxx Mapeo de NTSTATUS a HRESULT Quitar el bit N (0x10000000) y leerlo como NTSTATUS
0x8024xxxx u otro Facility propio HRESULT específico de un área funcional Identificar el área a partir del valor de Facility y consultar el documento dedicado (0x8024… es Windows Update) 2

En el paso 5, «contrastar con el contexto», la columna Result de Process Monitor resulta especialmente eficaz. Aunque en la aplicación solo aparezca «0x80070002», al mirarlo en Procmon se puede ver en una sola línea «qué proceso, sobre qué ruta, recibió NAME NOT FOUND». Para investigar el lado del Visor de eventos, consulte también «Introducción al Visor de eventos y ETW de Windows».

9. Errores de interpretación comunes — patrones que alargan la investigación

Por último, veamos los patrones de interpretación errónea que aparecen en consultas reales.

Error de interpretación 1: creer que 0x80004005 indica una causa específica

E_FAIL es «un error no especificado», y el mismo valor aparece tanto en Windows Update como en redes o en bases de datos. Probar al azar las soluciones que aparecen al buscar este código es, casi con toda seguridad, un rodeo. En lugar de partir del código, acote la búsqueda a partir de «qué aplicación, qué operación y qué otros registros hay en ese mismo momento». 6

Error de interpretación 2: no notar que un número negativo en decimal es un HRESULT

Se trata de casos en los que se busca directamente un registro como «Se produjo el error -2147467259» o en los que uno se confunde pensando «¿un error negativo?». Al ver un número negativo, conviértalo a hexadecimal. Con eso basta para reconocer que es 0x80004005 (E_FAIL) y conectarlo con lo visto en el error de interpretación 1.

Error de interpretación 3: investigar las ocho cifras de 0x8007xxxx sin fijarse en el error Win32 de los bits bajos

La esencia de 0x80070005 es «5 = acceso denegado». En vez de buscar las ocho cifras completas, extraer los 16 bits bajos y pensar «qué significa el error 5 de Win32 en el contexto de esta operación» llega al núcleo del problema mucho más rápido.

Error de interpretación 4: suponer que «mismo código = misma causa»

Si en el pasado tuvo la experiencia de que «el error 5 se debía al software antivirus», es fácil que la próxima vez, ante el mismo error 5, salte directamente a la misma solución. Aunque el código sea el mismo, si la API que falló y el recurso afectado son distintos, la causa también es distinta. Confirme siempre juntos el significado del código y la identificación del objeto afectado mediante Procmon u otra herramienta similar, cada vez.

Error de interpretación 5: confundir el error 5 de Win32 con 0xC0000005 y los códigos STOP con NTSTATUS

Si por la coincidencia del «5» se identifican ERROR_ACCESS_DENIED y STATUS_ACCESS_VIOLATION como lo mismo, la investigación se desvía hacia direcciones completamente distintas: un problema de permisos frente a un error de programación. Además, como el código STOP de la pantalla azul pertenece a un sistema distinto del de NTSTATUS, buscar 0x9F en la tabla de NTSTATUS no da ninguna respuesta útil. 14

El error 5 y 0xC0000005 se investigan en direcciones distintasEl error 5 de Win32 debe investigarse como un problema de permisos y el 0xC0000005 de NTSTATUS como un error de programación por lo que identificarlos como lo mismo desvía la investigación en una dirección equivocadaError 5 de Win32Investigar como problema de permisosNTSTATUS 0xC0000005Investigar como error de programaciónCódigos sin relación de sistemas distintos

Figura 21: No los identifique solo porque comparten el «5». El error 5 apunta a un problema de permisos, y 0xC0000005, a un error de programación.

10. Resumen

  • Los códigos de error de Windows tienen una estructura de tres capas: código de error Win32, HRESULT y NTSTATUS. Determine primero de qué capa y de quién procede el código.
  • La variación de notación (decimal, hexadecimal, negativo) se puede uniformar de forma mecánica. Convierta los negativos a hexadecimal de 8 cifras antes de leerlos.
  • HRESULT tiene una estructura de bits S/R/C/N/X + Facility (11 bits) + Code (16 bits), y 0x8007xxxx es el patrón más importante: un error Win32 envuelto de nuevo. Convierta a decimal los 16 bits bajos para extraer el código esencial.
  • Un código genérico como 0x80004005 (E_FAIL) no indica la causa. Solo si se conoce la estructura se puede tomar la decisión de dejar de profundizar en el código y pasar a investigar el contexto.
  • NTSTATUS aparece en el código de excepción de un bloqueo o en la columna Result de Procmon. 0xC0000005 es una violación de acceso, sin relación con el error 5 de Win32. El código STOP pertenece, además, a otro sistema distinto.
  • En .NET, el HRESULT se asigna a un tipo de excepción, y el valor original se conserva en Exception.HResult. En P/Invoke se usan juntos SetLastError=true y Marshal.GetLastWin32Error.
  • Las herramientas de investigación son certutil -error y net helpmsg (estándar), err.exe (equipo de desarrollo), comandos de una línea en PowerShell y !error de WinDbg.
  • El procedimiento es «uniformar la notación → determinar la capa → descomponer → consultar el nombre → contrastar con el contexto». El código solo indica el tipo de fallo; el lugar de la causa lo indica el contexto.

La próxima vez que se encuentre con un código de error poco familiar, antes de pegarlo en el buscador, mire primero sus primeras cifras. Si es 0x8007, las últimas cuatro; si es 0xC, es NTSTATUS; si es negativo, conviértalo a hexadecimal — esta descomposición de diez segundos determina en gran medida el tiempo de investigación que le seguirá.

Artículos relacionados

Áreas de consultoría relacionadas

KomuraSoft LLC se ocupa de investigaciones de fallos que parten de un código de error —como «no entiendo qué significa este código» o «0x80070005 solo aparece en un entorno concreto»—, del diseño del manejo de errores en aplicaciones donde conviven Win32 API, COM y .NET, y de la identificación de causas con volcados de memoria y Process Monitor. Puede consultarnos incluso a partir de una sola captura de pantalla del cuadro de diálogo de error.

Referencias

  1. Microsoft Learn, Debug system error codes. Sobre el índice al listado de códigos de error del sistema Win32 (0 a 15999), la obtención del mensaje del código devuelto por GetLastError mediante FormatMessage con el indicador FORMAT_MESSAGE_FROM_SYSTEM, el hecho de que los errores de WinINet/WinHTTP (rango 12000) están definidos en este mismo espacio, y los métodos de investigación con la Microsoft Error Lookup Tool o el comando !err.  2 3 4 5 6

  2. Microsoft Open Specifications, [MS-ERREF]: HRESULT. Sobre la disposición de bits del HRESULT (bits S, R, C, N, X; Facility de 11 bits; Code de 16 bits), el hecho de que el bit N indica que un valor NTSTATUS se ha mapeado al espacio de HRESULT, y el listado de códigos de facility, incluido FACILITY_WINDOWS_UPDATE (36).  2 3 4 5

  3. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS. Sobre la disposición de bits del NTSTATUS (Sev de 2 bits, bit C, bit N, Facility de 12 bits, Code de 16 bits) y el hecho de que la gravedad se divide en cuatro tipos: éxito (00), información (01), advertencia (10) y error (11).  2 3

  4. Microsoft Learn, HRESULT_FROM_WIN32 macro. Sobre la definición de la macro de winerror.h que mapea un código de error del sistema Win32 a un valor HRESULT.  2 3

  5. Microsoft Learn, Structure of COM Error Codes. Sobre el papel del bit de gravedad y del campo Facility del HRESULT, los valores de FACILITY_NULL, FACILITY_RPC, FACILITY_ITF, FACILITY_WIN32 y FACILITY_WINDOWS, y el hecho de que el significado de los códigos de FACILITY_ITF se define por interfaz, por lo que un mismo valor puede significar cosas distintas.  2 3

  6. Microsoft Learn, Common HRESULT values. Sobre el hecho de que E_FAIL (0x80004005) es «Unspecified failure» (error no especificado), y las definiciones de valores de HRESULT frecuentes como E_ACCESSDENIED (0x80070005), E_INVALIDARG (0x80070057) y E_OUTOFMEMORY (0x8007000E).  2 3 4

  7. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS values. Sobre el listado de valores de NTSTATUS, entre ellos STATUS_ACCESS_VIOLATION (0xC0000005), STATUS_DLL_NOT_FOUND (0xC0000135), STATUS_STACK_OVERFLOW (0xC00000FD), STATUS_HEAP_CORRUPTION (0xC0000374) y STATUS_BREAKPOINT (0x80000003).  2 3

  8. Microsoft Learn, The Microsoft Error Lookup Tool. Sobre el hecho de que es una herramienta independiente que muestra el texto del mensaje asociado a un código de estado en hexadecimal, recorriendo diversos archivos de cabecera como Winerror.h; que el nombre del archivo de descarga es Err_6.4.5.exe; y la advertencia de que las definiciones incluidas corresponden al momento en que se compiló.  2 3

  9. Microsoft Learn, certutil. Sobre el hecho de que la opción -error de certutil muestra el texto del mensaje asociado a un código de error, y que se emplea una notación de error con el nombre simbólico incluido, con un formato como 0x80070002 (WIN32: 2 ERROR_FILE_NOT_FOUND).  2

  10. Microsoft Learn, !error. Sobre el hecho de que la extensión !error de WinDbg decodifica y muestra valores de error de Win32, Winsock, NTSTATUS y NetAPI, y que al especificar el indicador 1 se interpreta como NTSTATUS.  2

  11. Microsoft Learn, How to: Map HRESULTs and exceptions. Sobre el mecanismo de correspondencia mutua entre el HRESULT de COM y las excepciones de .NET, la tabla de correspondencias como E_NOTIMPL → NotImplementedException, el hecho de que un HRESULT sin correspondencia explícita se convierte en COMException, y que propiedades de la excepción como Message o Source se inicializan a partir de la información de IErrorInfo.  2

  12. Microsoft Learn, RtlNtStatusToDosError function (winternl.h). Sobre el hecho de que es una función que convierte un código NTSTATUS en su código de error del sistema Win32 correspondiente, que devuelve ERROR_MR_MID_NOT_FOUND cuando no hay correspondencia definida, y que no existe una función que realice la conversión inversa.  2

  13. Microsoft Learn, Last-Error Code. Sobre el hecho de que el código de error final se mantiene por cada subproceso, que debe obtenerse con GetLastError justo tras el fallo, que coexisten API que ponen el código a 0 al tener éxito y otras que no lo hacen, y que el bit 29 está reservado para códigos definidos por la aplicación.  2

  14. Microsoft Learn, Bug check code reference. Sobre el listado de códigos de comprobación de errores (bug check codes, o códigos STOP) que se muestran en la pantalla azul, y el método para mostrar la información del código con la extensión !analyze de WinDbg. En el listado se puede confirmar que se trata de un sistema de numeración propio, distinto del de NTSTATUS.  2

  15. Microsoft Learn, Marshal.GetLastWin32Error Method. Sobre el método para obtener el código de error final de una llamada P/Invoke con el indicador SetLastError activado, el hecho de que llamar directamente a GetLastError mediante P/Invoke no es fiable por la sobrescritura debida a llamadas internas del runtime, y que a partir de .NET 6 se recomienda GetLastPInvokeError. 

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Qué significa el error 0x80004005?
0x80004005 es el E_FAIL de HRESULT, cuyo significado es «error no especificado» (Unspecified failure). Es decir, solo indica que se produjo un error cuya causa detallada no se puede reportar, no un código que represente la causa en sí. Por eso el mismo 0x80004005 aparece en contextos completamente distintos: redes, Windows Update, VBA, controladores de bases de datos, etc. Si se encuentra con este código, en lugar de profundizar en su significado, acote la causa a partir del contexto —en qué aplicación y en qué operación apareció— y de otra información de error registrada en el Visor de eventos o en registros detallados.
¿Qué es un código de error negativo como -2147467259?
Es un HRESULT de 32 bits mostrado como un número decimal con signo. Como el bit más significativo de un HRESULT se pone en 1 cuando falla, al mostrarlo como entero con signo siempre resulta negativo. Si ejecuta '0x{0:X8}' -f -2147467259 en PowerShell, puede recuperar la notación hexadecimal (en este ejemplo, 0x80004005 = E_FAIL). La regla práctica es: al ver en un registro o en el mensaje de error de un script un número negativo que empieza por -214…, conviértalo primero a hexadecimal antes de investigar.
¿Cuál es la forma más sencilla de averiguar el significado de un código de error?
Sin necesidad de instalar nada adicional, puede usar en el símbolo del sistema net helpmsg 5 (para códigos de error Win32 en decimal) y certutil -error 0x80070005. certutil también acepta HRESULT en hexadecimal y muestra el nombre simbólico junto con el texto del mensaje. En PowerShell, [System.ComponentModel.Win32Exception]::new(5).Message le permite obtener el mensaje en el idioma del sistema. En un equipo de desarrollo conviene tener a mano la herramienta oficial de Microsoft err.exe (Microsoft Error Lookup Tool), que permite buscar de una sola vez las definiciones correspondientes en Win32, HRESULT y NTSTATUS.
¿Qué error es 0xC0000005?
Es STATUS_ACCESS_VIOLATION de NTSTATUS, es decir, una violación de acceso (un acceso incorrecto a memoria). Es el código que aparece con más frecuencia en el «código de excepción» del Visor de eventos o en los volcados de memoria cuando falla una aplicación, e indica un error de programación como una referencia a un puntero no válido o el acceso a memoria ya liberada. Su nombre se parece al error 5 de Win32 (ERROR_ACCESS_DENIED = acceso denegado), pero son códigos de sistemas distintos y sin relación entre sí, así que no deben confundirse. Para determinar la causa, lo más fiable es capturar un volcado de memoria (crash dump) y analizarlo con WinDbg.
¿Por qué el mismo código de error tiene, cada vez, una causa distinta?
Porque el código de error solo indica «qué tipo de fallo» ocurrió; «qué falló y por qué» lo determina el contexto de la llamada. Por ejemplo, el error 5 (acceso denegado) puede producirse por falta de permisos NTFS, falta de privilegios de administrador, bloqueo por parte del software antivirus, y muchas otras causas completamente distintas que dan lugar al mismo código. En una situación parecida, si otro proceso tiene el archivo abierto, aparecerá un código distinto (error 32 = violación de uso compartido), y saber distinguir correctamente los códigos cambia dónde debe buscar. Tampoco es raro que el error 2 (archivo no encontrado) se deba no al archivo principal, sino a una DLL dependiente o a un archivo de configuración. Una vez averiguado el significado del código, el atajo para identificar la causa es confirmar, por ejemplo con Process Monitor, qué API falló sobre qué recurso.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog