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

Historial de revisiones (primera versión, publicada el 20 Aug 2026)
Primera publicación
Citar este artículo(DOI (archivo registrado): 10.5281/zenodo.22176035)

Los DOI siguientes remiten a versiones ya archivadas y pueden diferir del texto actual. Para citar el texto actual, utilice la URL de esta página.

Go Komura (2026). Cómo interpretar los códigos de error de Windows — la estructura de tres capas de Win32, HRESULT y NTSTATUS. KomuraSoft LLC. https://comcomponent.com/es/blog/windows-error-codes-win32-hresult-ntstatus/

DOI (archivo registrado)
10.5281/zenodo.22176035
DOI (última versión registrada)
10.5281/zenodo.22176036

«En la pantalla de la aplicación apareció un error 0x80004005. ¿Qué significa?» — en las investigaciones de fallos, esta consulta es habitual. Si busca el número tal cual, aparecen remedios de situaciones sin relación: Windows Update, carpetas compartidas, VBA, conexiones a bases de datos.

Los resultados se dispersan porque 0x80004005 (E_FAIL) es un código genérico que solo significa «error de detalle desconocido». En cambio, 0x80070005 se puede descomponer en «error 5 de Win32 = acceso denegado, vuelto a envolver como HRESULT». Códigos de aspecto parecido no llevan la misma cantidad de información.

Windows tiene tres sistemas —códigos de error Win32, HRESULT y NTSTATUS— y el código se convierte al cruzar de capa. Para acelerar la investigación, más que memorizar números, resulta más eficaz distinguir «quién lo devolvió, en qué capa» y «cuál era el código antes de volver a envolverlo».

Este artículo es una guía práctica para el personal de sistemas de pymes y para desarrolladores de aplicaciones Windows. A partir de Microsoft Learn y de la especificación pública [MS-ERREF] vigentes en agosto de 2026, encadena cómo distinguir los tres sistemas, cómo descomponer un HRESULT, su relación con las excepciones de .NET y cómo investigarlos con err.exe y PowerShell.

1. La conclusión primero

Lo primero que hay que fijar son estos tres puntos.

  1. Uniforme la notación e identifique el sistema de códigos. Los códigos de error Win32, HRESULT y NTSTATUS son sistemas distintos. El decimal y el hexadecimal son notaciones distintas del mismo valor, y un HRESULT a veces se muestra como un número negativo con signo. Primero alinee el valor a 8 cifras hexadecimales y léalo junto con la API que lo devolvió y el lugar donde apareció.123
  2. Descomponga 0x8007xxxx; con E_FAIL, pase a investigar el contexto. 0x80070005 es un HRESULT de FACILITY_WIN32 (7), y sus 16 bits bajos son 5 = ERROR_ACCESS_DENIED. En cambio, 0x80004005 (E_FAIL) es un «error no especificado», y el código solo no basta para acotar la causa.456
  3. Investigue juntos el significado del código y la operación y el objeto que fallaron. El mismo error 5 tiene causas diversas: ACL, elevación de privilegios, software de seguridad, etc. El objeto de un error 2 puede ser una DLL dependiente, y un archivo retenido por otro proceso puede aparecer como error 32. Cuando tenga el nombre, pase a los registros y a Process Monitor para ver «qué API falló sobre qué».1

Como herramientas, combine certutil -error y net helpmsg de Windows, Win32Exception de PowerShell, err.exe en el equipo de desarrollo y !error de WinDbg durante el análisis de un volcado.789 Aunque el error ya se haya convertido en una excepción de .NET, el HRESULT original se puede seguir desde Exception.HResult.10

Dónde leer, según el objetivo

Lo que quiere saber Sección a leer
Identificar el código que tiene delante e investigarlo enseguida Uniforme la notación en el capítulo 2 y pase a los comandos del capítulo 7 y al procedimiento del capítulo 8
Dejar bien registrados los fallos de las API de Win32 GetLastError y FormatMessage del capítulo 3, y P/Invoke de la sección 6.3
Entender la relación entre 0x80004005, 0x80070005 y las excepciones de .NET La descomposición de HRESULT del capítulo 4 y COM y .NET del capítulo 6
Investigar códigos de bloqueo como 0xC0000005 NTSTATUS y códigos STOP del capítulo 5, y WinDbg de la sección 7.4
Evitar las confusiones habituales de una investigación Los errores de lectura del capítulo 9

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

En el diagrama, una línea continua marca una relación que siempre se cumple y una línea discontinua una relación condicional (las condiciones están en la explicación de cada relación en la página de detalle). La lista completa de relaciones (18 en total, con evidencia y grado de certeza) y las definiciones de los conceptos principales están reunidas en la página de detalle del mapa de conocimiento (en japonés). Datos: JSON-LD / Turtle

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

Empecemos por el panorama. Aunque el número sea el mismo, la lectura cambia según el sistema al que pertenezca el valor. Si se alinean quién lo devuelve habitualmente y el aspecto típico, queda así.

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

El «aspecto» de esta tabla es una pista para buscar el sistema. Úselo como primera hipótesis, igual que la tabla de decisión del capítulo 8, y contrástelo con la API o el componente que lo devolvió.

Históricamente se han ido acumulando el código de error Win32, que heredó los números de MS-DOS; el NTSTATUS interno del kernel de NT; y el HRESULT, diseñado al introducir COM para empaquetar en 32 bits el éxito o el fallo y el origen.

En el Windows actual, la conversión NTSTATUS del kernel → código de error Win32 → HRESULT de la capa COM ocurre a diario. El fundamento de la investigación es volver a seguir el código visto en la capa superior hacia la capa inferior.114

Flujo de conversión entre los tres sistemasEl NTSTATUS que devuelve el kernel lo convierte el subsistema Win32 en un código de error Win32, y la capa COM lo vuelve a envolver como HRESULTEl subsistema Win32 lo convierteLa capa COM lo vuelve a envolverKernel y controladoresNTSTATUS (los errores son 0xC…)Código de error Win32 (5, etc.)HRESULT (0x8007xxxx)

Figura 1: Flujo de conversión entre capas. El NTSTATUS del kernel se convierte en un error Win32 y luego se vuelve a envolver como HRESULT.

2.1. Acostúmbrese a leer decimal y hexadecimal

Antes de investigar el sistema, quite las variaciones de notación. El mismo código se muestra en decimal, en hexadecimal y como un negativo con signo.

Valor mostrado El mismo valor en otra notación Significado
Error 5 0x5 ERROR_ACCESS_DENIED
Error 1223 0x4C1 ERROR_CANCELLED
0x80070005 -2147024891 El mismo HRESULT

En PowerShell se puede leer de una línea a otra así.

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

# Hexadecimal → decimal
0x4C1                        # 1223

Si ve un decimal negativo que empieza por «-214…», conviértalo de inmediato a hexadecimal. Solo con eso se reduce mucho el desvío a la entrada de la investigación.

Tres aspectos del mismo códigoEl error 5 en decimal, 0x5 en hexadecimal 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; el código es el mismo

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

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

3.1. Comportamiento básico de GetLastError

Confirme el valor de retorno y, después, guarde el último error

Muchas API de Win32, como CreateFile, indican el fallo con el valor de retorno (FALSE, NULL, INVALID_HANDLE_VALUE, etc.) y dejan el detalle en el «código de último error» por subproceso. Con estas API, obténgalo con GetLastError justo después de confirmar el fallo.12

Aun así, confirme el método de obtención en cada API. Por ejemplo, RegOpenKeyEx devuelve el propio código de error como valor de retorno, no el último error. Trátelo aparte de los ejemplos que usan GetLastError.13

Al usar GetLastError, hay dos precauciones.12

  1. Léalo justo después del fallo. Si en medio inserta otra llamada a una API (una función de registro, por ejemplo), esa llamada puede sobrescribir el código de último error.
  2. No se fíe del valor en caso de éxito. Hay API que ponen a 0 el código de último error al acertar y otras que no lo tocan. El principio es leerlo después de confirmar el fallo con el valor de retorno.
GetLastError se lee justo después del falloTras confirmar el fallo con el valor de retorno, obtener el código de último error con GetLastError sin insertar otra llamada a una APIWin32 APIAplicaciónWin32 APIAplicaciónSi se inserta otra API, se puede sobrescribirLlamada a CreateFileValor de retorno de falloGetLastErrorCódigo 5

Figura 3: El código de último error se lee justo después del fallo. Si se inserta otra llamada a una API, se puede sobrescribir.

Deje el código guardado en el registro junto con el mensaje

Para obtener la cadena de mensaje a partir del código, use FormatMessage con el indicador FORMAT_MESSAGE_FROM_SYSTEM. El orden es guardar primero el código y convertirlo a cadena después.1

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

void PrintLastError(const wchar_t* apiName)
{
    DWORD code = GetLastError();   // Llamar justo después del fallo (sin insertar otra 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 el registro de una aplicación propia, dejar así el decimal, el hexadecimal y el texto del mensaje acelera la investigación posterior.

Obtener el mensaje a partir del código y dejarlo en el registroCon el indicador FORMAT_MESSAGE_FROM_SYSTEM de FormatMessage se obtiene la cadena de mensaje del código de error, y en el registro se dejan el decimal, el hexadecimal y el textoCódigo de error (ejemplo: 5)Obtener la cadena con FormatMessageTexto del mensajeRegistrar en el logAnotar decimal, hexadecimal y texto

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

3.2. Códigos representativos que aparecen una y otra vez en el terreno

Los códigos de error Win32 se definen en el rango 0 a 15999, y Microsoft Learn tiene la lista completa.1 En las investigaciones de fallos, los que se encuentran una y otra vez son estos.

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 pasado es demasiado pequeño
998 0x3E6 ERROR_NOACCESS Acceso no válido a una ubicación de memoria
1223 0x4C1 ERROR_CANCELLED El usuario canceló la operación

Lo que aquí se confunde con facilidad es el 5 y el 998. 998 (ERROR_NOACCESS) no es «acceso denegado», sino la expresión Win32 de una violación de acceso a memoria. Corresponde a la forma que toma STATUS_ACCESS_VIOLATION de NTSTATUS, que se trata más adelante, al convertirse a la capa Win32.

Además, 1223 (ERROR_CANCELLED) aparece, por ejemplo, cuando en el cuadro de elevación de UAC se elige «No». No lo tome simplemente como una avería: léalo como un código que indica que la operación «se interrumpió».

El error 998 y el 5 son cosas distintas998 es una violación de acceso a memoria, la conversión a la capa Win32 de la violación de acceso de NTSTATUS, y no significa lo mismo que el 5, que es acceso denegadoConversión a la capa Win32NTSTATUS 0xC0000005Error 998 (ERROR_NOACCESS)El significado es violación de acceso a memoriaError 5 (acceso denegado)Problema de permisos. Distinto del 998

Figura 5: El error 998 es la forma convertida a la capa Win32 de la violación de acceso de NTSTATUS, y no es lo mismo que el 5 de acceso denegado.

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

Memorizar los códigos representativos no basta para identificar la causa. El código enseña solo «el tipo de fallo»; más allá queda el objeto que hay que investigar.

Código Lo que cambia según el contexto Qué comprobar a continuación
Error 5 (acceso denegado) ACL de NTFS insuficiente, escritura en una zona protegida sin privilegios de administrador, bloqueo de antivirus o AppLocker, privilegios insuficientes de la cuenta de servicio, etc. Qué API vio denegado el acceso a qué objeto
Error 2 (archivo no encontrado) No tiene por qué ser el archivo indicado: una DLL dependiente cargada de forma implícita, un archivo de configuración visto en otro sitio por la redirección del Registro 32/64 bits, una ruta cuya expansión de variables de entorno falló, etc. «Qué archivo» no se encontró
Error 32 (violación de uso compartido) Otro proceso está usando el objeto «Qué proceso» lo tiene retenido
La causa del error 5 la decide el contextoAunque sea el mismo acceso denegado, hay varios candidatos de causa, como ACL insuficiente o falta de privilegios de administrador, y hace falta identificar qué API falló sobre quéError 5 (acceso denegado)ACL insuficienteSin privilegios de administradorBloqueo del software de seguridadPrivilegios de servicio insuficientesIdentificar el objeto que falló con Procmon

Figura 6: El código solo enseña «el tipo de fallo». El error 5 tiene varios candidatos de causa, y hace falta identificar el objeto.

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

4. HRESULT — leer la estructura empaquetada en 32 bits

4.1. Disposición de los bits

HRESULT es un formato que empaqueta en un solo valor de 32 bits el éxito o el fallo, el origen y el código de detalle. Si primero mira el bit S para éxito o fallo, Facility para el origen y Code para el detalle, los ejemplos de descomposición posteriores se siguen mejor. La disposición de la especificación pública [MS-ERREF] es la siguiente.2

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

Si el bit S más significativo es 1, es decir, un HRESULT cuya notación hexadecimal empieza por 0x8 o más es un fallo. Mostrarlo como entero de 32 bits con signo da un negativo: esa es la verdadera identidad del «-214…» anterior.

Relación entre el bit S y la presentación negativaUn HRESULT de fallo tiene el bit S más significativo en 1, así que en hexadecimal empieza por 0x8 o más, y al mostrarlo como entero de 32 bits con signo resulta negativoBit S = 1 (fallo)En hexadecimal empieza por 0x8 o másEn presentación con signo resulta negativoSi ve un negativo, conviértalo a hexadecimal y léalo

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

Facility es una pista de qué documentación consultar a continuación

Los valores representativos de Facility son los siguientes. 7 se lee como reenvoltura de un error Win32; 4, como una definición por interfaz.5

Facility Valor Aspecto hexadecimal Significado
FACILITY_NULL 0 0x8000xxxx Códigos comunes amplios (E_FAIL, E_UNEXPECTED, etc.)
FACILITY_RPC 1 0x8001xxxx Proveniente de RPC
FACILITY_ITF 4 0x8004xxxx Error de una definición de interfaz (el significado depende de la interfaz)
FACILITY_WIN32 7 0x8007xxxx Reenvoltura de un código de error Win32
FACILITY_WINDOWS 8 0x8008xxxx Interfaces adicionales definidas por Microsoft

4.2. Descomponga 0x80004005 y 0x80070005

Compare dos códigos de aspecto parecido separándolos en S, Facility y Code.

Elemento a leer 0x80004005 0x80070005
S 1 (fallo) 1 (fallo)
Facility 0 (FACILITY_NULL) 7 (FACILITY_WIN32)
Code 0x4005 0x0005 = 5
Definición E_FAIL: error no especificado E_ACCESSDENIED: acceso denegado
Siguiente investigación Investigar el componente que lo devolvió y los registros que lo acompañan Investigarlo como error Win32 5: la operación y el objeto denegados

0x80004005, con el código solo, no acota la causa. Facility es (0x80004005 >> 16) & 0x7FF = 0, el código genérico E_FAIL de FACILITY_NULL. No tiene más detalle que «Unspecified failure» (error no especificado), así que, una vez descompuesto, mueva el eje de la investigación a «qué componente lo devolvió» y a «si el registro de eventos o el registro de la aplicación de la misma hora tienen detalle».6

0x80070005 se puede seguir hasta el error Win32 5. Facility = 7, Code = 5, así que se ve que es ERROR_ACCESS_DENIED vuelto a envolver como HRESULT. El alias E_ACCESSDENIED es el mismo valor.6

Aunque ambos sean un «fallo», la cantidad de información que se obtiene al descomponerlos es distinta. No dé por sentado que E_FAIL es acceso denegado; elija la siguiente investigación según el valor que volvió.

Descomposición de 0x80004005 y 0x800700050x80004005 es el código genérico E_FAIL de FACILITY_NULL, no tiene detalle y hay que pasar a investigar el contexto; 0x80070005 es FACILITY_WIN32 y se ve que es la reenvoltura del error Win32 5, acceso denegado0x80004005Facility = 0 (FACILITY_NULL)Code = 0x4005 → E_FAILError no especificado. Pasar al contexto0x80070005Facility = 7 (FACILITY_WIN32)Code = 0x0005 → 5ERROR_ACCESS_DENIED

Figura 8: Aunque ambos sean un «fallo», al descomponerlos la cantidad de información es distinta. 0x80070005 se puede seguir hasta el error Win32 5.

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

Volver a envolver un fallo Win32 como HRESULT

Para comunicar un error Win32 de una capa inferior a un método COM o al runtime de .NET que devuelve HRESULT, winerror.h tiene HRESULT_FROM_WIN32. En los ejemplos de códigos de fallo siguientes, pone el error Win32 en los 16 bits bajos, 7 en Facility y 1 en el bit S.4

Funcionamiento de HRESULT_FROM_WIN32Almacena el código de error Win32 en los 16 bits bajos, pone 7 en Facility y 1 en el bit S, y arma un HRESULT 0x8007xxxxCódigo de error Win32 (ejemplo: 5)Almacenar en los 16 bits bajosPoner 7 en FacilityPoner 1 en el bit S0x80070005

Figura 9: HRESULT_FROM_WIN32 almacena el error Win32 en los 16 bits bajos y pone 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 al revés, extraiga los 16 bits bajos

Para leer el error Win32 original a partir de 0x8007xxxx, extraiga los 16 bits bajos en 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 y WinHTTP (serie 12000) también están definidos en el espacio de códigos de error Win321, así que un 0x8007xxxx de red se descompone con el mismo procedimiento. Memorizar en el cuerpo «si ve 0x8007, pase las 4 cifras bajas a decimal» es la habilidad práctica que más conviene llevarse de este artículo.

Con 0x8004xxxx, pase a la documentación del componente que lo devolvió

No aplique la misma lectura tal cual a 0x8004xxxx (FACILITY_ITF). Aquí quien define el significado cambia según la interfaz, así que el mismo valor de 32 bits puede significar algo distinto si quien lo devolvió es otro.5

Un 0x8004xxxx poco familiar no se decide solo con una búsqueda genérica: búsquelo en la documentación del componente que lo devolvió (biblioteca, SDK de controlador, producto de servidor).

La forma de investigar cambia entre 0x8007 y 0x8004Un 0x8007xxxx de FACILITY_WIN32 se lee con una descomposición mecánica de los 16 bits bajos, pero un 0x8004xxxx de FACILITY_ITF tiene un sujeto que define el significado distinto por interfaz, así que se investiga en la documentación del componente que lo devolvióWIN32, 7ITF, 4¿Cuál es Facility?Pasar a decimal los 16 bits bajosEl significado cambia según quien lo devolvióLeerlo como error Win32Investigarlo en la documentación de quien lo devolvió

Figura 10: 0x8007xxxx se puede descomponer de forma mecánica; 0x8004xxxx se investiga en la documentación del componente que lo devolvió.

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

5.1. Disposición y Severity

NTSTATUS es el código de 32 bits que usan el kernel, los controladores de dispositivo y la API nativa de ntdll, y su disposición se parece a HRESULT sin ser la misma.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 Facilidad (12 bits)
15–0 Code Código de detalle

La gran diferencia con HRESULT es que la gravedad tiene 2 bits y hay cuatro tipos: éxito, información, advertencia y error. Por la primera cifra hexadecimal, por ejemplo, 0xC… es error (11), 0x8… es advertencia (10), 0x4… es información (01) y 0x0 a 0x3… es éxito.

Por eso no decida que es un fallo HRESULT solo porque empiece por 0x8. El NTSTATUS 0x80000003 (STATUS_BREAKPOINT) es una excepción de punto de interrupción, y su gravedad no es «error» sino «advertencia».314

NTSTATUS se lee por la primera cifraComo la gravedad tiene 2 bits, un NTSTATUS se distingue así: si la primera cifra hexadecimal es 0xC, error; 0x8, advertencia; 0x4, información; de 0x0 a 0x3, éxito0xC0x80x40x0 a 0x3¿Cuál es la primera cifra hexadecimal?ErrorAdvertenciaInformaciónÉxitoEjemplo: 0x80000003 es advertencia

Figura 11: NTSTATUS se lee por la primera cifra hexadecimal. 0x80000003 es «advertencia, no error».

5.2. Dónde se encuentra — códigos de excepción, códigos STOP y el registro de eventos

Los sitios en los que se encuentra un NTSTATUS se ven separados en código de excepción, código STOP y Process Monitor.

El código de excepción de un bloqueo de aplicación

El «código de excepción: 0xc0000005» que queda en «Application Error (identificador de evento 1000)» del registro de eventos es un NTSTATUS. Entre los valores representativos que se ven en un bloqueo o en un fallo de arranque están estos.14

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 arrancar
0xC00000FD STATUS_STACK_OVERFLOW Desbordamiento de pila
0xC0000374 STATUS_HEAP_CORRUPTION Corrupción del montón

El código STOP de una pantalla azul es otro sistema

El código STOP (código de comprobación de errores) se parece a simple vista, pero es un sistema de números propio, distinto de NTSTATUS, como 0x0000009F (DRIVER_POWER_STATE_FAILURE). Use la referencia dedicada.15

Separe «si es 0xC0000005, NTSTATUS; si es STOP 0x9F, código de comprobación de errores» y no busque un código STOP en la tabla de NTSTATUS.

En Process Monitor aparece en la columna Result

NAME NOT FOUND o ACCESS DENIED en la columna Result de Procmon son los nombres de presentación del NTSTATUS que devolvió el kernel (STATUS_OBJECT_NAME_NOT_FOUND o STATUS_ACCESS_DENIED). Aquí se puede observar el fallo de E/S de archivo con el vocabulario de NTSTATUS y confirmar la correspondencia de capas: ese valor se convierte en un error Win32 y llega a la aplicación.

Distinguir un código de excepción de un código STOPEl código de excepción del registro de eventos se lee como NTSTATUS, y el código STOP de una pantalla azul se busca en la referencia dedicada de códigos de comprobación de errores, que es otro sistemaCódigo de excepciónCódigo STOP¿Dónde apareció el código?Leerlo como NTSTATUSBuscarlo en la tabla de códigos de comprobación de erroresEjemplo: 0xC0000005Ejemplo: 0x0000009F

Figura 12: El código de excepción del registro de eventos es NTSTATUS; el código STOP de una pantalla azul es otro sistema. No se equivoque de tabla.

La investigación que sigue al código de excepción —es decir, capturar y analizar un volcado de memoria— se trata en «Introducción a la recolección de volcados de memoria de Windows» y «WinDbg + SOS para leer volcados de memoria».

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

Hay dos vías para pasar de NTSTATUS a otro sistema. Separe el mapeo a HRESULT de la conversión a error Win32.

Vía Qué hace Ejemplo
Mapeo al espacio HRESULT Pone el bit N (0x10000000) con HRESULT_FROM_NT 0xC0000005 → 0xD0000005
Conversión a error Win32 Convierte al número correspondiente con RtlNtStatusToDosError STATUS_ACCESS_VIOLATION → ERROR_NOACCESS (998)

En el mapeo a HRESULT, se pone el bit N y se lleva el valor NTSTATUS al espacio HRESULT. Por tanto, el procedimiento es si un HRESULT empieza por 0xD, quite el bit N y léalo como NTSTATUS.2

En la conversión a error Win32 se usa RtlNtStatusToDosError de ntdll. Un valor sin correspondencia se convierte en ERROR_MR_MID_NOT_FOUND.11 0xC0000005 se convierte en 998, y STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034) en ERROR_FILE_NOT_FOUND (2). El vocabulario rico del lado del kernel a veces se redondea a una clasificación más gruesa en la capa Win32, así que lea por separado el antes y el después de la conversión.

Dos puentes de NTSTATUS hacia otras capasNTSTATUS pasa a otras capas por dos vías: mapearlo al espacio HRESULT poniendo el bit N, o convertirlo a un código de error Win32 con RtlNtStatusToDosErrorPoner el bit NRtlNtStatusToDosErrorNTSTATUS (0xC0000005)HRESULT (0xD0000005)Error Win32 998 (ERROR_NOACCESS)Si no hay correspondencia, ERROR_MR_MID_NOT_FOUND

Figura 13: El puente de NTSTATUS es de dos tipos. Si empieza por 0xD, quite el bit N y léalo como NTSTATUS.

6. COM y .NET — cómo se mapea un código de error a una excepción

6.1. El estilo de COM — HRESULT + IErrorInfo

Los métodos COM, por principio, devuelven un HRESULT. Aun así, la información que cabe en un código de 32 bits tiene límite.

El complemento es IErrorInfo. Puede transmitir por separado la cadena de descripción del error y el origen, y en C++ la clase _com_error con soporte del compilador trata juntos el HRESULT y IErrorInfo. En las aplicaciones cuyo cuadro de diálogo muestra «código + texto de descripción», a menudo este mecanismo es el que transporta el texto.

IErrorInfo complementa el HRESULTLa información que cabe en un HRESULT de 32 bits tiene límite, así que la cadena de descripción del error y el origen se transmiten por separado con IErrorInfo, y en C++ la clase _com_error trata ambos juntosHRESULT (solo 32 bits)La información que cabe tiene límiteIErrorInfo transporta el texto de descripción_com_error los trata juntosCódigo + texto de descripción del cuadro de diálogo

Figura 14: La cadena de descripción que no cabe en un HRESULT de 32 bits la transporta por separado IErrorInfo.

6.2. El estilo de .NET — de HRESULT a un tipo de excepción

El runtime de .NET, al recibir un fallo HRESULT en la interoperabilidad COM, lo convierte en una excepción. Un HRESULT conocido se mapea al tipo de excepción correspondiente; uno desconocido se convierte en COMException.10

Mapeo de HRESULT a una excepción de .NETUn HRESULT de fallo recibido en la interoperabilidad COM se convierte en el tipo de excepción correspondiente si hay un mapeo conocido, o en COMException si no, y en ambos casos el valor original se conserva en Exception.HResultSíNoHRESULT de fallo¿Hay un mapeo conocido?Convertir al tipo de excepción correspondienteConvertir a COMExceptionEl valor original se conserva en Exception.HResult

Figura 15: .NET mapea el HRESULT a un tipo de excepción, y en cualquiera el valor original queda 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 mapeo definido COMException (el valor original en la propiedad ErrorCode)

Use el HRESULT original para ramificar el tratamiento de excepciones

En cualquier excepción, el HRESULT original se conserva en Exception.HResult. Si, por ejemplo, en E/S de archivo «quiere reintentar solo cuando hay violación de uso compartido», puede usar este valor como condición. El ejemplo siguiente es la parte que captura solo 0x80070020, que representa una violación de uso compartido.

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 retiene el archivo: esperar un poco y reintentar, etc.
}

6.3. P/Invoke y GetLastError

Si llama a una API de Win32 directamente con P/Invoke, ponga juntas la declaración y la forma de obtener el error.

  1. Especifique SetLastError = true en DllImport (o LibraryImport).
  2. Justo después de confirmar el fallo, obténgalo con Marshal.GetLastWin32Error. Desde .NET 6 también se puede usar el equivalente GetLastPInvokeError.16

Evite definir GetLastError como P/Invoke y llamarlo. Las llamadas internas del runtime pueden sobrescribir el valor, y a veces no se obtiene la causa correcta del fallo.16

Obtención del último error en P/InvokeLo correcto es poner SetLastError en true y obtenerlo con Marshal.GetLastWin32Error; si se hace P/Invoke directo de GetLastError, el runtime lo sobrescribe y queda inexactoLlamar a una API de Win32 con P/InvokeEspecificar SetLastError=trueObtenerlo con GetLastWin32ErrorDefinición que llama a GetLastError directamenteEl runtime lo sobrescribe y queda inexacto

Figura 16: En P/Invoke use juntos SetLastError=true y Marshal.GetLastWin32Error. La llamada directa a GetLastError es inexacta.

[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 using
// (si se deja como IntPtr, se fuga el identificador del kernel)
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();              // Ejemplo: 5
    var message = new Win32Exception(code).Message;       // Ejemplo: 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 de un código de error Win32, así que se puede usar tal cual para dejar en el registro tanto el código como el mensaje. El diseño de en qué capa capturar la excepción y cómo dejarla en el registro se trata en «Dónde deben ir el catch y el log en el manejo de excepciones».

7. Práctica de las herramientas de conversión e investigación — consulta rápida para copiar y pegar

Primero elija la herramienta según el entorno que tiene y el objetivo. En las secciones siguientes hay ejemplos que se pueden usar tal cual.

Situación Herramienta Qué se puede investigar
Comprobar sin instalar nada adicional certutil -error, net helpmsg Nombre y mensaje correspondientes al código (sección 7.2)
Investigar definiciones atravesando varios sistemas err.exe Candidatos de definición en los encabezados (sección 7.1)
Convertir o descomponer un valor PowerShell Conversión decimal/hexadecimal, 16 bits bajos, mapeo a una excepción de .NET (sección 7.3)
Confirmar el significado durante el análisis de un volcado !error de WinDbg Interpretación como Win32 o NTSTATUS (sección 7.4)

7.1. err.exe (Microsoft Error Lookup Tool)

Es la herramienta de búsqueda de errores que Microsoft distribuye como un ejecutable independiente. Atraviesa muchos archivos de encabezado, como winerror.h y ntstatus.h, y enumera las definiciones y mensajes que coinciden con el código indicado.7

err 0x80070005
err 5
err 0xC0000005

Al ver el resultado, fíjese en dos puntos.

  • Entre varios candidatos, elija el que encaja con el contexto. Por ejemplo, «5» también coincide con definiciones distintas de ERROR_ACCESS_DENIED de Win32. No dé por sentado que el nombre encontrado es la causa.
  • Confirme el momento de las definiciones incluidas. El nombre del archivo de descarga lleva versión (en el momento de escribir esto, Err_6.4.5.exe), y las definiciones de los códigos se basan en los encabezados del momento en que se empaquetó.7
El resultado de err.exe se elige según el contextoerr.exe atraviesa muchos archivos de encabezado y enumera las definiciones coincidentes, así que si el mismo número da varios candidatos hay que elegir cuál es válido según el contextoEscribir err 5Búsqueda transversal en muchos encabezadosCoinciden varias definicionesElegir el candidato válido según el contexto

Figura 17: err.exe hace una búsqueda transversal de encabezados, así que a veces salen varios candidatos; el válido se elige según el contexto.

7.2. Comandos estándar de Windows

Los que se pueden usar sin instalar nada adicional son certutil y net helpmsg. La opción -error de certutil muestra el texto de mensaje correspondiente a un código de error y acepta tanto un HRESULT hexadecimal como un decimal.8

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

net helpmsg es solo para códigos de error Win32 en decimal. En un entorno en japonés el mensaje vuelve en japonés, así que también se puede usar para explicárselo al usuario. Para investigar un HRESULT hexadecimal, elija certutil -error como en el ejemplo anterior.

Uso diferenciado de los comandos estándarUn código de error Win32 en decimal se investiga con net helpmsg, y un código que incluye un HRESULT hexadecimal se investiga con la opción -error de certutilWin32 en decimalIncluye hexadecimal¿Qué código tiene delante?net helpmsgcertutil -errorDevuelve el mensaje en japonésAcepta hexadecimal y decimal

Figura 18: Uso diferenciado de los comandos estándar. Un 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

Consulta rápida de conversión de notación, obtención del mensaje Win32, descomposición de HRESULT y mapeo a una excepción de .NET. Después de confirmar el significado del código, la investigación de la operación y el objeto que fallaron sigue siendo aparte.

# 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 identidad del HRESULT)
'0x{0:X8}' -f -2147467259     # 0x80004005

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

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

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

7.4. !error de WinDbg

Para investigar un código durante el análisis de un volcado, la extensión !error de WinDbg es rápida. Por defecto lo interpreta como código de error Win32; si se añade 1 como segundo argumento, como NTSTATUS.9

0:000> !error 5
Error code: (Win32) 0x5 (5) - Acceso denegado.

0:000> !error 0xc0000005 1
Error code: (NTSTATUS) 0xc0000005 - <violación de acceso>

En un volcado de memoria, !analyze -v muestra automáticamente el código de excepción (NTSTATUS), así que el flujo es confirmar el significado desde ahí con !error <código> 1.

Flujo para confirmar un código de excepción en WinDbgEn un volcado de memoria, el comando analyze muestra automáticamente el código de excepción, y ese código se pasa a la extensión error con 1 como segundo argumento para confirmar el 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 un volcado, se toma el código de excepción que muestra !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

En una investigación real, avance estas cinco etapas en orden. El punto es no terminar al consultar el nombre: al final confirme también la operación y el objeto que fallaron.

  1. Uniforme la notación. Si es un decimal negativo, conviértalo a 8 cifras hexadecimales. Un hexadecimal de menos de 8 cifras se lee rellenando con ceros.
  2. Determine de qué capa es el código. Con la tabla siguiente, acote la primera hipótesis a partir de las primeras cifras y contrástela con la API que lo devolvió y el lugar donde apareció.
  3. Descompóngalo para extraer el código esencial. Si es un HRESULT 0x8007xxxx, los 16 bits bajos; si es un HRESULT 0xDxxxxxxx, quite el bit N y léalo.
  4. Consulte el nombre y la definición con una herramienta. Confirme el nombre simbólico y el mensaje con err.exe, certutil, !error, etc.
  5. Contrástelo con el contexto. Identifique, con el registro de la aplicación, el registro de eventos o Procmon, en qué aplicación, con qué operación, qué API falló sobre qué. El código es «el tipo de fallo»; el contexto es «el lugar de la causa».
Procedimiento de investigación de un código de errorEl patrón de investigación es uniformar la notación a hexadecimal, determinar la capa por las primeras cifras, descomponer para extraer el código esencial, consultar el nombre y la definición con una herramienta y contrastarlo con el contextoNotación decimal0x80070xC0xDUniformar la notación (los negativos, a 8 cifras hexadecimales)¿Cuáles son las primeras cifras?Leerlo como error Win32Pasar 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 patrón de investigación. Uniforme la notación, identifique la capa, descomponga, consulte el nombre y después contrástelo con el contexto.

Aspecto Primera hipótesis Método de descomposición o conversión
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 Pasar a 8 cifras hexadecimales y aplicar las filas siguientes
0x8007xxxx HRESULT (FACILITY_WIN32) Pasar a decimal los 16 bits bajos y leerlo como Win32
0x8004xxxx HRESULT (FACILITY_ITF) Investigarlo en la documentación del componente que lo devolvió
0x8000xxxx HRESULT (FACILITY_NULL) Código genérico como E_FAIL. Mover el eje a la investigación de contexto
0xCxxxxxxx NTSTATUS (error) !error <código> 1; si hace falta, convertirlo 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 pasar a la documentación dedicada (0x8024… es Windows Update)2

Ejemplo concreto del paso 5: de 0x80070002 al camino que no se encuentra

Aunque en la aplicación solo aparezca «0x80070002», al mirar la columna Result de Procmon se ve «qué proceso, sobre qué ruta, recibió NAME NOT FOUND». Es la observación para pasar de la descomposición del código a identificar el objeto que de verdad falló.

Para investigar el lado del registro de eventos, consulte también «Introducción al registro de eventos de Windows y ETW».

9. Errores de lectura habituales — patrones que alargan la investigación

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

Error de lectura 1: pensar que 0x80004005 es «un código que indica una causa concreta»

E_FAIL es «error no especificado», y el mismo valor aparece en Windows Update, en la red y en una base de datos. Probar al azar los remedios que salen al buscar este código es, casi con certeza, un rodeo. No acote a partir del código, sino a partir de «qué aplicación, qué operación y los demás registros de la misma hora».6

Error de lectura 2: no darse cuenta de que un decimal negativo es un HRESULT

El caso de buscar tal cual un registro del tipo «se produjo el error -2147467259» o de confundirse con «¿un error negativo?». Si ve un negativo, conviértalo a hexadecimal. Solo con eso se ve que es 0x80004005 (E_FAIL) y se conecta con el conocimiento del error de lectura 1.

Error de lectura 3: investigar 0x8007xxxx como las 8 cifras enteras y no mirar el error Win32 de los bits bajos

La esencia de 0x80070005 es «5 = acceso denegado». Más que buscar las 8 cifras enteras, llega antes al núcleo extraer los 16 bits bajos y pensar «qué significa el error 5 de Win32 en el contexto de esta operación».

Error de lectura 4: creer que «el mismo código = la misma causa»

Si en el pasado «el error 5 lo causó el antivirus», en el siguiente error 5 es fácil saltar al mismo remedio. Aunque el código sea el mismo, si la API que falló y el recurso objetivo son distintos, la causa es otra. Confirme el significado del código e identifique el objeto con Procmon u otra herramienta, siempre juntos.

Error de lectura 5: confundir el error 5 de Win32 con 0xC0000005, y un código STOP con NTSTATUS

Si por el «5» se identifican ERROR_ACCESS_DENIED y STATUS_ACCESS_VIOLATION, la investigación se desvía hacia direcciones totalmente distintas: un problema de permisos y un error de programación. Además, el código STOP de una pantalla azul es otro sistema distinto de NTSTATUS, así que buscar 0x9F en la tabla de NTSTATUS no da una respuesta con sentido.15

El error 5 y 0xC0000005 tienen direcciones de investigación distintasEl error 5 de Win32 se investiga como un problema de permisos, y el 0xC0000005 de NTSTATUS como un error de programación; si se identifican, la investigación se desvíaError 5 de Win32Investigar un problema de permisosNTSTATUS 0xC0000005Investigar un error de programaciónCódigos sin relación, de sistemas distintos

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

10. Resumen

Primero distinga el sistema. Los códigos de error principales de Windows son tres sistemas: código de error Win32, HRESULT y NTSTATUS. Uniforme las variaciones de notación decimal, hexadecimal y negativa, y confirme de qué capa y de quién procede. NTSTATUS se encuentra como código de excepción de un bloqueo o en la columna Result de Procmon, pero el error 5 de Win32 y 0xC0000005 son cosas distintas, y el código STOP es aún otro sistema.

Después lea la estructura y extraiga la información necesaria. HRESULT se compone de los bits S/R/C/N/X, 11 bits de Facility y 16 bits de Code. El patrón más importante es 0x8007xxxx, del que se lee el error Win32 en los 16 bits bajos. En la interoperabilidad COM, el HRESULT se mapea a un tipo de excepción de .NET y el valor original queda en Exception.HResult. En P/Invoke use juntos SetLastError=true y Marshal.GetLastWin32Error.

Al final, contrástelo con el contexto. E_FAIL (0x80004005) no es un código que indique una causa. Cuando al descomponerlo vea que la información no aumenta, deje de profundizar en el código y pase a la operación, el objeto y los registros de la misma hora. Combine las herramientas certutil y net helpmsg, err.exe, PowerShell y !error de WinDbg.

El patrón de investigación es «uniformar la notación → identificar la capa → descomponer → consultar el nombre → contrastar con el contexto». El código enseña solo el tipo de fallo. La próxima vez que encuentre un número poco familiar, antes de pegarlo en el cuadro de búsqueda compruebe las primeras cifras y de dónde sale. Esa primera descomposición decide dónde investigar después.

Artículos relacionados

Áreas de consulta relacionadas

En KomuraSoft LLC nos ocupamos de investigaciones de fallos que parten de un código de error —«no entiendo el significado de este código», «0x80070005 solo aparece en un entorno concreto»—, del diseño del tratamiento de errores en aplicaciones donde conviven Win32 API, COM y .NET, y de identificar la causa con un volcado de memoria o Process Monitor. También puede consultar a partir de una sola captura del cuadro de diálogo de error.

Referencias

  1. Microsoft Learn, Debug system error codes. Sobre el índice de la lista de códigos de error del sistema Win32 (0 a 15999), la obtención del mensaje del código que devuelve GetLastError con FormatMessage y el indicador FORMAT_MESSAGE_FROM_SYSTEM, la definición de los errores de WinINet/WinHTTP (serie 12000) en este espacio, y los métodos de investigación con Microsoft Error Lookup Tool y el comando !err. ↩ ↩2 ↩3 ↩4 ↩5

  2. Microsoft Open Specifications, [MS-ERREF]: HRESULT. Sobre la disposición de bits de HRESULT (bits S, R, C, N y X, 11 bits de Facility, 16 bits de Code), cómo el bit N indica que un valor NTSTATUS se mapeó al espacio HRESULT, y la lista de códigos de facilidad, incluida FACILITY_WINDOWS_UPDATE (36). ↩ ↩2 ↩3 ↩4

  3. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS. Sobre la disposición de bits de NTSTATUS (2 bits de Sev, bit C, bit N, 12 bits de Facility, 16 bits de Code) y cómo 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 de facilidad de HRESULT, los valores de FACILITY_NULL, FACILITY_RPC, FACILITY_ITF, FACILITY_WIN32 y FACILITY_WINDOWS, y cómo el significado de un código de FACILITY_ITF se define por interfaz y el mismo valor puede significar algo distinto. ↩ ↩2 ↩3

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

  7. Microsoft Learn, The Microsoft Error Lookup Tool. Sobre cómo es una herramienta independiente que muestra el texto de mensaje asociado a un código de estado hexadecimal atravesando varios archivos de encabezado como Winerror.h, cómo el nombre del archivo de descarga es Err_6.4.5.exe, y la precaución de que las definiciones incluidas son las del momento de la compilación. ↩ ↩2 ↩3

  8. Microsoft Learn, certutil. Sobre cómo la opción -error de certutil muestra el texto de mensaje asociado a un código de error, y cómo se usa una notación de error que incluye el nombre simbólico, como 0x80070002 (WIN32: 2 ERROR_FILE_NOT_FOUND). ↩ ↩2

  9. Microsoft Learn, !error. Sobre cómo la extensión !error de WinDbg descodifica y muestra valores de error de Win32, Winsock, NTSTATUS y NetAPI, y cómo al especificar 1 en el indicador lo interpreta como NTSTATUS. ↩ ↩2

  10. Microsoft Learn, How to: Map HRESULTs and exceptions. Sobre el mecanismo de mapeo mutuo entre HRESULT de COM y excepciones de .NET, la tabla de correspondencias como E_NOTIMPL → NotImplementedException, cómo un HRESULT sin mapeo explícito se convierte en COMException, y cómo Message, Source, etc. de la excepción se inicializan a partir de la información de IErrorInfo. ↩ ↩2

  11. Microsoft Learn, RtlNtStatusToDosError function (winternl.h). Sobre cómo es la función que convierte un código NTSTATUS al código de error del sistema Win32 correspondiente, cómo si no hay correspondencia definida se devuelve ERROR_MR_MID_NOT_FOUND, y cómo no existe una función de conversión inversa. ↩ ↩2

  12. Microsoft Learn, Last-Error Code. Sobre cómo el código de último error se conserva por subproceso, cómo hay que obtenerlo con GetLastError justo después del fallo, cómo conviven API que ponen el código a 0 al acertar y API que no lo hacen, y cómo el bit 29 está reservado para códigos definidos por la aplicación. ↩ ↩2

  13. Microsoft Learn, RegOpenKeyExW function. Sobre cómo al acertar devuelve ERROR_SUCCESS y al fallar devuelve como valor de retorno un código de error distinto de cero definido en Winerror.h. ↩

  14. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS values. Sobre la lista de valores NTSTATUS, incluidos STATUS_ACCESS_VIOLATION (0xC0000005), STATUS_DLL_NOT_FOUND (0xC0000135), STATUS_STACK_OVERFLOW (0xC00000FD), STATUS_HEAP_CORRUPTION (0xC0000374) y STATUS_BREAKPOINT (0x80000003). ↩ ↩2

  15. Microsoft Learn, Bug check code reference. Sobre la lista de códigos de comprobación de errores (códigos STOP) que se muestran en una pantalla azul y cómo mostrar información del código con la extensión !analyze de WinDbg. En la lista se confirma que es un sistema de números propio, distinto de NTSTATUS. ↩ ↩2

  16. Microsoft Learn, Marshal.GetLastWin32Error Method. Sobre cómo obtener el código de último error de una llamada P/Invoke con el indicador SetLastError, cómo hacer P/Invoke directo de GetLastError no es de fiar porque las llamadas internas del runtime lo sobrescriben, y cómo desde .NET 6 se recomienda GetLastPInvokeError. ↩ ↩2

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, y su significado es «error no especificado» (Unspecified failure). Es decir, solo indica que se produjo un error cuya causa detallada no se puede notificar; no es un código que represente la causa en sí. Por eso el mismo 0x80004005 aparece en contextos sin relación: redes, Windows Update, VBA, controladores de bases de datos, etc. Si ve este código, no profundice 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 que quede en el registro 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, recupera 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 instalar nada adicional, en el símbolo del sistema puede usar net helpmsg 5 (para un código de error Win32 en decimal) y certutil -error 0x80070005. certutil también acepta un HRESULT en hexadecimal y muestra el nombre simbólico y el texto del mensaje. En PowerShell, [System.ComponentModel.Win32Exception]::new(5).Message obtiene 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 busca 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 como «código de excepción» en el registro de eventos o en un volcado de memoria cuando se bloquea 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, así que no los confunda. 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 del software antivirus y muchas otras causas distintas que dan el mismo código. En una situación parecida, si otro proceso tiene el archivo abierto aparece un código distinto (error 32 = violación de uso compartido), y leer bien el código cambia dónde hay que 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