Lire les codes d'erreur Windows — la structure à trois couches Win32, HRESULT et NTSTATUS

· · Windows, Codes d'erreur, HRESULT, NTSTATUS, Win32 API, Dépannage, Débogage, Développement Windows

« L’écran de l’application a affiché l’erreur 0x80004005. Que cela veut-il dire ? » — Dans les consultations d’investigation d’incidents, ce genre de question est un classique. Quiconque a collé le nombre d’une boîte de dialogue d’erreur dans un moteur de recherche et s’est retrouvé face à un flot d’articles sans rapport — un échec Windows Update, un dossier partagé qui ne se connecte pas, une erreur d’exécution VBA, un échec de connexion à une base — et n’en a été que plus perdu n’est pas seul.

Cela arrive parce que 0x80004005 (E_FAIL) est un code générique dont le seul sens est « échec non spécifié ». Le même code sert dans d’innombrables situations, donc chercher uniquement le code n’atteint pas la cause. En revanche, un code comme 0x80070005 peut, si vous connaissez la structure, se décomposer en quelques secondes avant toute recherche en « numéro d’erreur Win32 5 = accès refusé, emballé en HRESULT ».

Les codes d’erreur Windows forment, pour des raisons historiques, trois couches — codes d’erreur Win32, HRESULT et NTSTATUS — et ils se convertissent d’une couche à l’autre. Une fois cette structure en tête, vous pouvez juger vous-même « quelle couche, quel acteur a renvoyé ce code » et « quel est le code essentiel », et le premier geste d’une investigation devient beaucoup plus rapide.

Destiné aux informaticiens de PME et aux développeurs d’applications Windows, cet article organise comment distinguer et décomposer les trois systèmes de codes d’erreur, le lien avec les exceptions .NET, et la recherche pratique avec err.exe et PowerShell — à partir de Microsoft Learn et de la spécification publiée [MS-ERREF] en août 2026.

1. D’abord la conclusion

  • Les codes d’erreur Windows sont surtout trois systèmes. Codes d’erreur Win32 (le petit décimal que GetLastError renvoie), HRESULT (le code 32 bits depuis COM, hex commençant par 0x8 ou décimal négatif), et NTSTATUS (codes de la couche noyau ; les erreurs commencent par 0xC).123
  • Décimal et hexadécimal sont deux notations du même code. « Erreur 5 », « 0x5 » et « les 16 bits bas de 0x80070005 » désignent tous ERROR_ACCESS_DENIED (accès refusé).1
  • 0x8007xxxx est « une erreur Win32 emballée ». C’est un code d’erreur Win32 stocké dans HRESULT FACILITY_WIN32 (7) ; convertissez les 16 bits bas en décimal et vous avez le code essentiel. C’est le motif le plus important pour lire les codes d’erreur.45
  • 0x80004005 (E_FAIL) n’est pas un code de cause. Il signifie « Unspecified failure » et ne porte pas plus d’information. Plutôt que de creuser ce code, cherchez le contexte d’origine et les journaux qui l’accompagnent.6
  • Un décimal négatif (-2147467259 et assimilés) est un HRESULT. Le bit de poids fort des 32 bits (le bit d’échec) est posé, donc un affichage signé est négatif. Convertissez-le en hexadécimal puis lisez-le.2
  • Une valeur à 8 chiffres commençant par 0xC est un NTSTATUS. 0xC0000005 (violation d’accès) et 0xC0000135 (DLL introuvable) apparaissent sans cesse dans le journal des événements et les dumps au moment d’un plantage. Ils n’ont rien à voir avec le numéro d’erreur Win32 5.7
  • Le même code change de sens avec le contexte. La cause de l’erreur 5 va de l’ACL à l’élévation, à l’antivirus, à un fichier tenu, et le « fichier introuvable » de l’erreur 2 est souvent une DLL dépendante. Lisez toujours le sens du code avec quelle API a échoué contre quoi.1
  • Les outils de conversion et de recherche sont standard. certutil -error et net helpmsg sont intégrés à Windows ; Win32Exception de PowerShell obtient le message ; sur une machine de développement, err.exe (Microsoft Error Lookup Tool) ; en analyse de dump, !error de WinDbg.8910
  • En .NET, un HRESULT est mappé à un type d’exception. Un HRESULT connu va au type correspondant (E_ACCESSDENIED → UnauthorizedAccessException, etc.) ; un inconnu devient COMException ; la valeur d’origine reste dans Exception.HResult.11

En une phrase, le motif d’une investigation de code d’erreur Windows est « aligner la notation sur l’hexadécimal → juger de quelle couche est le code → décomposer et extraire le code essentiel → le lire avec le contexte ».

2. Windows a trois systèmes de codes d’erreur

D’abord, la carte d’ensemble. Les codes d’erreur Windows se partagent surtout en trois systèmes, selon la couche qui les renvoie.

Système Principal acteur qui le renvoie Apparence typique Exemple représentatif
Code d’erreur Win32 API Win32 (GetLastError), code de sortie d’une commande Un petit décimal (0–15999) 5 = ERROR_ACCESS_DENIED
HRESULT Un composant COM, le shell, un installeur, de nombreux frameworks Hex à 8 chiffres commençant par 0x8, ou un décimal négatif 0x80004005 = E_FAIL
NTSTATUS Le noyau, un pilote, une API native (ntdll) Les erreurs sont un hex à 8 chiffres commençant par 0xC 0xC0000005 = STATUS_ACCESS_VIOLATION

Historiquement ils se sont empilés dans cet ordre : codes d’erreur Win32 héritiers des numéros MS-DOS, NTSTATUS que le noyau NT utilise en interne, et HRESULT conçu à l’arrivée de COM pour « empaqueter succès/échec et origine dans 32 bits ». Sur Windows actuel, un flux de conversion est quotidien : le noyau renvoie un NTSTATUS, le sous-système Win32 le convertit en code d’erreur Win32, et la couche COM l’emballe encore en HRESULT.124

Flux de conversion entre les trois systèmesLe sous-système Win32 convertit un NTSTATUS renvoyé par le noyau en code d'erreur Win32, et la couche COM l'emballe encore en HRESULTLe sous-système Win32 convertitLa couche COM emballeNoyau et pilotesNTSTATUS(erreurs 0xC…)Code d'erreur Win32(5 etc.)HRESULT(0x8007xxxx)

Figure 1 : Le flux de conversion entre couches. Un NTSTATUS du noyau devient une erreur Win32, puis est encore emballé en HRESULT.

2.1. Habituez-vous à lire décimal et hexadécimal l’un pour l’autre

Avant de distinguer les trois systèmes, il faut absorber le flottement de notation. Le même code s’affiche en décimal ou en hexadécimal selon la situation.

  • « Erreur 5 », « code d’erreur : 0x5 » → le même ERROR_ACCESS_DENIED
  • « Erreur 1223 », « 0x4C1 » → le même ERROR_CANCELLED
  • « 0x80070005 », « -2147024891 » → le même HRESULT

Dans PowerShell, la conversion tient en une ligne.

# Decimal → hex
'0x{0:X8}' -f 1223          # 0x000004C1
'0x{0:X8}' -f -2147024891   # 0x80070005 (negative = HRESULT to hex)

# Hex → decimal
0x4C1                        # 1223

Quand vous voyez un décimal négatif qui commence par « -214… », convertissez-le par réflexe en hexadécimal. Cela seul coupe beaucoup d’égarements à l’entrée d’une investigation.

Trois apparences du même codeL'erreur décimale 5, l'hex 0x5 et les 16 bits bas de 0x80070005 désignent tous le même ERROR_ACCESS_DENIEDNotation décimale: erreur 5ERROR_ACCESS_DENIEDNotation hex: 0x5Les 16 bits bas de 0x80070005Notation différente, même code

Figure 2 : Décimal, hexadécimal et les 16 bits bas d’un HRESULT ne sont que des notations différentes du même code.

3. Codes d’erreur Win32 — GetLastError et FORMAT_MESSAGE

3.1. Comportement de base de GetLastError

Beaucoup d’API Win32 comme CreateFile et RegOpenKeyEx indiquent l’échec par la valeur de retour (FALSE, NULL, INVALID_HANDLE_VALUE, etc.) et stockent le code détaillé dans un « last-error code » tenu par thread. L’appelant le récupère avec GetLastError immédiatement après avoir confirmé l’échec.13

Deux précautions pratiques.13

  1. Lisez-le immédiatement après l’échec. Si vous intercalez un autre appel d’API (une fonction de journalisation, par exemple), cet appel peut écraser le last-error code.
  2. Ne vous fiez pas à la valeur en cas de succès. Certaines API remettent le last-error code à 0 en cas de succès ; d’autres n’y touchent pas. La règle est de confirmer l’échec par la valeur de retour puis de lire.
Lire GetLastError juste après l'échecAprès confirmation de l'échec par la valeur de retour, récupérer le last-error code avec GetLastError tout de suite, sans intercaler un autre appel d'APIWin32 APIAppWin32 APIAppIntercaler une autre API peut l'écraserAppel CreateFileValeur de retour d'échecGetLastErrorCode 5

Figure 3 : Lisez le last-error code immédiatement après l’échec. Intercaler un autre appel d’API peut l’écraser.

Pour obtenir une chaîne de message à partir d’un code, utilisez FormatMessage avec le drapeau FORMAT_MESSAGE_FROM_SYSTEM.1

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

void PrintLastError(const wchar_t* apiName)
{
    DWORD code = GetLastError();   // Call immediately after failure (do not insert another 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);
}

Laisser à la fois le décimal, l’hexadécimal et le texte du message dans le journal de votre application, comme ici, accélère d’un cran une investigation ultérieure.

Chercher un message à partir d'un code et le laisser dans le journalPasser le drapeau FORMAT_MESSAGE_FROM_SYSTEM à FormatMessage pour obtenir la chaîne de message du code d'erreur, et laisser décimal, hexadécimal et texte dans le journalCode d'erreur(ex.: 5)Obtenir la chaîne avec FormatMessageTexte du messageEnregistrer dans le journalÉcrire décimal, hex et texte ensemble

Figure 4 : Convertissez un code d’erreur en chaîne de message avec FormatMessage, et laissez décimal, hexadécimal et texte ensemble dans le journal.

3.2. Codes représentatifs qui reviennent sans cesse sur le terrain

Les codes d’erreur Win32 sont définis dans la plage 0–15999, et Microsoft Learn en a la liste complète.1 Parmi eux, les visages que vous rencontrez encore et encore en investigation d’incident sont les suivants.

Décimal Hex Symbole Sens
2 0x2 ERROR_FILE_NOT_FOUND Le fichier spécifié est introuvable
3 0x3 ERROR_PATH_NOT_FOUND Le chemin spécifié est introuvable
5 0x5 ERROR_ACCESS_DENIED L’accès a été refusé
32 0x20 ERROR_SHARING_VIOLATION Un autre processus l’utilise, l’accès est impossible
87 0x57 ERROR_INVALID_PARAMETER Le paramètre est incorrect
122 0x7A ERROR_INSUFFICIENT_BUFFER Le tampon passé est trop petit
998 0x3E6 ERROR_NOACCESS Accès invalide à un emplacement mémoire
1223 0x4C1 ERROR_CANCELLED L’opération a été annulée par l’utilisateur

Parmi ceux-ci, 998 (ERROR_NOACCESS) n’est pas « accès refusé » mais l’expression Win32 d’une violation d’accès mémoire, la forme du NTSTATUS STATUS_ACCESS_VIOLATION abordé plus loin après conversion vers la couche Win32. Attention à la confusion avec le numéro 5. Aussi, 1223 (ERROR_CANCELLED) est un code qui apparaît quand l’utilisateur choisit « Non » sur une boîte d’élévation UAC, par exemple — davantage « c’a été annulé » qu’une erreur.

Les erreurs 998 et 5 sont des choses différentes998 est une violation d'accès mémoire, une violation d'accès NTSTATUS convertie vers la couche Win32, et diffère de 5 qui représente un accès refuséConverti vers la couche Win32NTSTATUS 0xC0000005Erreur 998(ERROR_NOACCESS)Le sens est une violation d'accès mémoireErreur 5(accès refusé)Un problème de droits. Différent de 998

Figure 5 : L’erreur 998 est une violation d’accès NTSTATUS convertie vers la couche Win32, une chose différente de l’accès refusé 5.

3.3. Le même code change de sens avec le contexte

Plus important que mémoriser le tableau des codes représentatifs est le sens que un code d’erreur ne vous dit que « le genre d’échec ».

  • Erreur 5 (accès refusé) : les candidats de cause vont largement — ACL NTFS insuffisant, écriture d’une zone protégée sans privilèges d’administrateur, blocage par antivirus ou AppLocker, privilèges insuffisants d’un compte de service, etc.
  • Erreur 2 (fichier introuvable) : ce n’est pas nécessairement le fichier que l’utilisateur a spécifié. Une DLL dépendante que l’EXE a essayé de charger implicitement, un fichier de paramètres vu au mauvais endroit à cause de la redirection du registre (32 bits/64 bits), un chemin dont l’expansion de variable d’environnement a échoué — « quel fichier » est introuvable n’est pas visible depuis le code.
  • Erreur 32 (violation de partage) : « quel processus le tient » est la vraie question, mais le code ne vous le dit pas.
La cause de l'erreur 5 est décidée par le contexteMême un accès refusé identique a plusieurs causes candidates comme un ACL insuffisant ou l'absence de privilèges d'administrateur, et il faut identifier quelle API a échoué contre quoiErreur 5(accès refusé)ACL insuffisantSans privilèges adminBlocage produit de sécuritéPrivilèges de service basProcmon: cible en échec

Figure 6 : Un code ne dit que « le genre d’échec ». L’erreur 5 a plusieurs causes candidates, et identifier la cible est requis.

L’outil qui mesure « quelle API, contre quel nom d’objet, a renvoyé quel résultat » est Process Monitor. Son usage est détaillé dans « Guide pratique de Process Monitor (ProcMon) ». Chercher le sens d’un code d’erreur et identifier la cible qui a échoué sont les deux roues du même chariot.

4. HRESULT — Lire la structure empaquetée dans 32 bits

4.1. Disposition des bits

HRESULT est un format qui empaquete succès/échec, origine et code de détail dans une seule valeur 32 bits. La spécification publiée [MS-ERREF] le définit avec la disposition suivante.2

Position de bit Nom Sens
31 S Severity. 0 = succès, 1 = échec
30 R Réservé (partie de la sévérité lors du mapping NTSTATUS)
29 C Bit Customer. 1 signifie un code défini par quelqu’un d’autre que Microsoft
28 N 1 signifie une valeur NTSTATUS mappée dans l’espace HRESULT
27 X Réservé (0)
26–16 Facility Un code de facility qui indique l’origine (11 bits)
15–0 Code Un code de détail dans la facility (16 bits)

Le bit S de poids fort est 1, c’est-à-dire qu’un HRESULT dont la notation hex commence à 0x8 ou au-dessus est un échec. L’afficher comme entier 32 bits signé le rend négatif — c’est l’identité du « -214… » mentionné plus haut.

Relation entre le bit S et un affichage négatifUn HRESULT d'échec a le bit S de poids fort à 1, donc en hex il commence à 0x8 ou au-dessus, et en entier 32 bits signé il est négatifBit S = 1(échec)L'hex commence à 0x8 ou plusUn affichage signé est négatifFace à un négatif, convertir en hex et lire

Figure 7 : Un HRESULT d’échec commence à 0x8 ou au-dessus parce que le bit S est 1, et un affichage signé est négatif.

Les valeurs Facility représentatives sont les suivantes.5

Facility Valeur Apparence hex Sens
FACILITY_NULL 0 0x8000xxxx Codes largement communs (E_FAIL, E_UNEXPECTED, etc.)
FACILITY_RPC 1 0x8001xxxx Origine RPC
FACILITY_ITF 4 0x8004xxxx Une erreur définie par l’interface (le sens dépend de l’interface)
FACILITY_WIN32 7 0x8007xxxx Un code d’erreur Win32 emballé
FACILITY_WINDOWS 8 0x8008xxxx Interfaces Microsoft supplémentaires

4.2. Décomposer 0x80004005 et 0x80070005

Décomposons-les réellement.

Pour 0x80004005 : S=1 (échec), Facility=(0x80004005 » 16) & 0x7FF = 0 (FACILITY_NULL), Code=0x4005. Un code FACILITY_NULL générique, défini comme E_FAIL « Unspecified failure ».6 Autrement dit ce code ne porte que le sens « un échec qui ne peut pas rapporter de détail ». Face à 0x80004005, arrêtez de creuser le code lui-même, et déplacez le poids de l’investigation vers « quel composant l’a renvoyé » et « y a-t-il du détail dans le journal des événements ou le journal de l’application au même moment ».

Pour 0x80070005 : S=1, Facility=7 (FACILITY_WIN32), Code=0x0005=5. Vous voyez que c’est le numéro d’erreur Win32 5 (ERROR_ACCESS_DENIED) emballé en HRESULT. L’alias E_ACCESSDENIED est, en substance, cette valeur.6

Même pour le même « accès refusé », 0x80070005 est l’emballage d’un échec concret survenu à la couche Win32, et la quantité d’information est complètement différente de 0x80004005.

Décomposition de 0x80004005 et 0x800700050x80004005 est le code FACILITY_NULL générique E_FAIL, sans détail, et doit passer à une investigation de contexte ; 0x80070005 est FACILITY_WIN32 et se lit comme l'emballage du numéro d'erreur Win32 5, accès refusé0x80004005Facility=0(FACILITY_NULL)Code=0x4005 → E_FAILÉchec non spécifié. Vers une investigation de contexte0x80070005Facility=7(FACILITY_WIN32)Code=0x0005 → 5ERROR_ACCESS_DENIED

Figure 8 : Même « échec » n’a pas la même quantité d’information une fois décomposé. 0x80070005 se marche jusqu’au numéro d’erreur Win32 5.

4.3. Le motif le plus important : 0x8007xxxx = HRESULT_FROM_WIN32

Pour transmettre un échec d’une couche inférieure qui ne peut renvoyer qu’un code d’erreur Win32 à une couche supérieure qui renvoie HRESULT (une méthode COM ou le runtime .NET), winerror.h fournit la macro HRESULT_FROM_WIN32.4 Le comportement est « stocker le code d’erreur Win32 dans les 16 bits bas, poser Facility à FACILITY_WIN32 (7), et poser le bit S à 1 ».

Fonctionnement de HRESULT_FROM_WIN32Stocker le code d'erreur Win32 dans les 16 bits bas, poser Facility à 7 et le bit S à 1, et assembler un HRESULT 0x8007xxxxCode d'erreur Win32(ex.: 5)Stocker dans les 16 bits basPoser Facility à 7Poser le bit S à 10x80070005

Figure 9 : HRESULT_FROM_WIN32 stocke l’erreur Win32 dans les 16 bits bas et pose Facility=7 et le 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)

Pour lire dans l’autre sens, prenez les 16 bits bas dans PowerShell.

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

Comme dans le second exemple, les erreurs WinINet et WinHTTP (les 12000) sont aussi définies dans l’espace des codes d’erreur Win321, donc un 0x8007xxxx réseau se décompose avec la même procédure. Mettre dans la mémoire musculaire « quand vous voyez 0x8007, convertissez les 4 chiffres bas en décimal » est la compétence pratique numéro un que cet article voudrait que vous emportiez.

Il y a la mise en garde inverse pour 0x8004xxxx (FACILITY_ITF). Un code FACILITY_ITF a un acteur différent qui définit le sens par interface, donc la même valeur 32 bits peut signifier autre chose si l’acteur qui l’a renvoyée est différent.5 Pour un 0x8004xxxx peu familier, cherchez-le non dans une recherche générique mais dans la documentation du composant qui l’a renvoyé (une bibliothèque, un SDK de pilote, un produit serveur).

La façon de chercher change entre 0x8007 et 0x8004Un 0x8007xxxx FACILITY_WIN32 se lit en décomposant mécaniquement les 16 bits bas, mais un 0x8004xxxx FACILITY_ITF a un acteur différent qui définit le sens par interface, donc cherchez-le dans les documents du composant qui l'a renvoyé7, WIN324, ITFFacility est ?Convertir les 16 bits bas en décimalLe sens diffère selon qui l'a renvoyéLe lire comme une erreur Win32Le chercher dans les documents de l'émetteur

Figure 10 : 0x8007xxxx se décompose mécaniquement ; 0x8004xxxx se cherche dans les documents du composant émetteur.

5. NTSTATUS — Codes de la couche noyau et le monde des plantages

5.1. Disposition et Severity

NTSTATUS est un code 32 bits utilisé par le noyau, les pilotes de périphérique et les API natives ntdll, et sa disposition ressemble à HRESULT sans être la même.3

Position de bit Nom Sens
31–30 Sev Severity. 00 = succès, 01 = information, 10 = avertissement, 11 = erreur
29 C Bit Customer
28 N Réservé (0, pour qu’un map vers HRESULT soit possible)
27–16 Facility Facility (12 bits)
15–0 Code Code de détail

Parce que la sévérité est sur 2 bits, vous pouvez lire le genre depuis le chiffre hex de tête. 0xC… est une erreur (11), 0x8… un avertissement (10), 0x4… une information (01), 0x0–0x3… un succès. L’exception de point d’arrêt 0x80000003 (STATUS_BREAKPOINT) est un exemple représentatif de « un avertissement, pas une erreur ».37

Un NTSTATUS se lit par genre depuis le chiffre de têteParce que la sévérité est sur 2 bits, un NTSTATUS se lit comme erreur si le chiffre hex de tête est 0xC, avertissement si 0x8, information si 0x4, et succès si 0x0 à 0x30xC0x80x40x0–0x3Le chiffre hex de tête est ?ErreurAvertissementInformationSuccèsEx.: 0x80000003 est un avertissement

Figure 11 : Un NTSTATUS se lit par genre depuis le chiffre hex de tête. 0x80000003 est « un avertissement, pas une erreur ».

5.2. Où vous le rencontrez — codes d’exception, codes STOP et journal des événements

Les situations où informaticiens et développeurs rencontrent NTSTATUS sont surtout liées aux plantages.

  • Un code d’exception de plantage d’application : le « Exception code: 0xc0000005 » enregistré dans « Erreur d’application (ID d’événement 1000) » du journal des événements est un NTSTATUS. Les valeurs représentatives sont les suivantes.7
Valeur Symbole Sens
0xC0000005 STATUS_ACCESS_VIOLATION Violation d’accès (accès mémoire illégal)
0xC0000135 STATUS_DLL_NOT_FOUND Une DLL requise est introuvable, le démarrage est impossible
0xC00000FD STATUS_STACK_OVERFLOW Débordement de pile
0xC0000374 STATUS_HEAP_CORRUPTION Corruption du tas
  • Un code STOP d’écran bleu : ils se ressemblent au premier regard, mais un code STOP (bug check code) est un système de numérotation à part, distinct de NTSTATUS, comme 0x0000009F (DRIVER_POWER_STATE_FAILURE), et a une référence dédiée.14 Retenir seulement la distinction « 0xC0000005 est NTSTATUS ; STOP 0x9F est un bug check code et il ne faut pas le chercher dans une table NTSTATUS » suffit.
  • La colonne Result de Process Monitor : NAME NOT FOUND et ACCESS DENIED dans la colonne Result de Procmon sont les noms d’affichage du NTSTATUS renvoyé par le noyau (STATUS_OBJECT_NAME_NOT_FOUND, STATUS_ACCESS_DENIED). C’est aussi un endroit où vous pouvez sentir la correspondance des couches : observer un échec d’E/S fichier dans le vocabulaire NTSTATUS, puis cet échec converti en erreur Win32 et arrivant à l’application.
Distinguer un code d'exception d'un code STOPLire un code d'exception du journal des événements comme NTSTATUS ; chercher un code STOP d'écran bleu dans la référence dédiée des bug-check codes, un autre systèmeCode d'exceptionCode STOPOù le code est-il apparu ?Le lire comme NTSTATUSLe chercher dans la table des bug-checkEx.: 0xC0000005Ex.: 0x0000009F

Figure 12 : Un code d’exception du journal des événements est un NTSTATUS ; un code STOP d’écran bleu est un autre système. Ne les cherchez pas dans la mauvaise table.

L’investigation au-delà du code d’exception, c’est-à-dire capturer et analyser un dump de plantage, est couverte dans « Introduction à la collecte des dumps de crash Windows » et « Lire un dump de plantage avec WinDbg + SOS ».

5.3. La relation avec HRESULT — le bit N et RtlNtStatusToDosError

Le pont entre NTSTATUS et les deux autres couches a deux chemins.

  1. Un map dans l’espace HRESULT : poser le bit N HRESULT (0x10000000) amène une valeur NTSTATUS telle quelle dans l’espace HRESULT (la macro HRESULT_FROM_NT de winerror.h). Mapper 0xC0000005 devient 0xD0000005, par exemple. Quand vous voyez un HRESULT qui commence par 0xD, la procédure correcte est d’enlever le bit N et de le lire comme NTSTATUS.2
  2. Conversion vers un code d’erreur Win32 : RtlNtStatusToDosError de ntdll convertit un NTSTATUS vers le code d’erreur Win32 correspondant. Une valeur sans correspondance définie devient ERROR_MR_MID_NOT_FOUND.12 Par exemple STATUS_ACCESS_VIOLATION (0xC0000005) est converti en ERROR_NOACCESS (998), et STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034) en ERROR_FILE_NOT_FOUND (2). Il est aussi utile de retenir que le vocabulaire riche du noyau est parfois arrondi à une distinction plus grossière à la couche Win32.
Deux ponts de NTSTATUS vers les autres couchesUn NTSTATUS passe aux autres couches de deux façons : mappé dans l'espace HRESULT en posant le bit N, et converti en code d'erreur Win32 par RtlNtStatusToDosErrorPoser le bit NRtlNtStatusToDosErrorNTSTATUS(0xC0000005)HRESULT(0xD0000005)Erreur Win32 998(ERROR_NOACCESS)ERROR_MR_MID_NOT_FOUND si aucune correspondance

Figure 13 : Il y a deux ponts NTSTATUS. Un départ 0xD se lit comme NTSTATUS après avoir enlevé le bit N.

6. COM et .NET — Comment un code d’erreur est mappé à une exception

6.1. Le style COM — HRESULT + IErrorInfo

Une méthode COM renvoie fondamentalement HRESULT, mais il y a une limite à ce qui peut tenir dans 32 bits, donc en complément le mécanisme IErrorInfo peut transmettre une chaîne de description d’erreur et l’origine séparément. En C++, la classe _com_error prise en charge par le compilateur gère HRESULT et IErrorInfo ensemble. Une application dont la boîte d’erreur montre « code + description » transporte souvent la description par ce mécanisme.

IErrorInfo qui complète HRESULTIl y a une limite à ce qui tient dans un HRESULT 32 bits, donc une chaîne de description d'erreur et l'origine sont transmises séparément avec IErrorInfo, et en C++ la classe _com_error gère les deux ensembleHRESULT(32 bits seulement)Il y a une limite à ce qui tientIErrorInfo porte la description_com_error les gère ensembleLe code + description de la boîte

Figure 14 : Une chaîne de description qui ne tient pas dans un HRESULT 32 bits est portée séparément par IErrorInfo.

6.2. Le style .NET — d’un HRESULT à un type d’exception

Quand le runtime .NET reçoit un échec HRESULT en interop COM, il le convertit en exception. Un HRESULT connu est mappé au type d’exception correspondant ; un inconnu devient COMException.11

Mapping d'un HRESULT vers une exception .NETUn HRESULT d'échec reçu en interop COM est converti vers le type d'exception correspondant s'il est connu, ou vers COMException s'il est inconnu, et dans les deux cas la valeur d'origine est gardée dans Exception.HResultYesNoHRESULT d'échecUn mapping connu ?Convertir vers le type d'exceptionConvertir vers COMExceptionLa valeur d'origine reste dans Exception.HResult

Figure 15 : .NET mappe un HRESULT vers un type d’exception, et la valeur d’origine reste dans Exception.HResult sur chaque exception.

HRESULT Type d’exception .NET
E_ACCESSDENIED (0x80070005) UnauthorizedAccessException
E_OUTOFMEMORY (0x8007000E) OutOfMemoryException
E_INVALIDARG (0x80070057) ArgumentException
E_NOTIMPL (0x80004001) NotImplementedException
Une valeur sans mapping défini COMException (la valeur d’origine dans la propriété ErrorCode)

Sur chaque exception, le HRESULT d’origine est gardé dans la propriété Exception.HResult. Une branche dans la gestion d’exception d’E/S fichier comme « réessayer seulement sur une violation de partage » peut s’écrire avec cette valeur.

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)
    // Another process is holding the file — wait a little and retry, for example
}

6.3. P/Invoke et GetLastError

Quand vous appelez une API Win32 directement via P/Invoke, spécifiez SetLastError = true sur DllImport (ou LibraryImport), puis récupérez avec Marshal.GetLastWin32Error (depuis .NET 6, l’équivalent GetLastPInvokeError). Définir GetLastError lui-même en P/Invoke et l’appeler est inexact, parce qu’un appel d’API à l’intérieur du runtime peut écraser la valeur.15

Récupérer la dernière erreur en P/InvokeSpécifier SetLastError à true et récupérer avec Marshal.GetLastWin32Error est correct ; P/Invoquer GetLastError directement est inexact à cause d'un écrasement par le runtimeAppeler une API Win32 via P/InvokeSpécifier SetLastError=trueRécupérer avec GetLastWin32ErrorUne définition qui appelle GetLastError directementLe runtime l'écrase et c'est inexact

Figure 16 : En P/Invoke, utilisez SetLastError=true et Marshal.GetLastWin32Error comme un ensemble. Appeler GetLastError directement est inexact.

[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);

// Receive the return value as SafeFileHandle, not IntPtr, and close it reliably with using
// (leaving it as IntPtr leaks a kernel handle)
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();              // Example: 5
    var message = new Win32Exception(code).Message;       // Example: Access is denied.
    logger.LogError("CreateFileW failed: {Code} (0x{Code:X8}) {Message}",
        code, code, message);
}

Win32Exception cherche la chaîne de message de l’OS à partir d’un code d’erreur Win32, donc vous pouvez l’utiliser tel quel pour laisser à la fois le code et le message dans un journal. La question de conception — à quelle couche attraper une exception et comment la laisser dans un journal — est couverte dans « Où catch et la journalisation doivent-ils se situer dans la gestion des exceptions ? ».

7. Outils de conversion et d’investigation en pratique — Une référence à copier-coller

7.1. err.exe (Microsoft Error Lookup Tool)

Un outil autonome de recherche d’erreurs distribué par Microsoft. Il parcourt un grand nombre de fichiers d’en-tête comme winerror.h et ntstatus.h et liste définitions et messages qui correspondent au code spécifié.8

err 0x80070005
err 5
err 0xC0000005

Un même nombre peut toucher dans plusieurs en-têtes (par exemple « 5 » correspond à des définitions en divers endroits outre Win32 ERROR_ACCESS_DENIED), donc lequel des candidats est plausible doit être choisi par le contexte. Le nom de fichier de téléchargement est versionné (Err_6.4.5.exe au moment de la rédaction), et notez aussi que les définitions de codes reposent sur les en-têtes au moment où elles ont été empaquetées.8

Choisir les résultats de recherche d'err.exe par le contexteerr.exe parcourt un grand nombre de fichiers d'en-tête et liste les définitions correspondantes, donc quand plusieurs candidats apparaissent pour le même nombre, choisissez lequel est plausible par le contexteSaisir err 5Parcourir de nombreux en-têtesPlusieurs définitions correspondentChoisir un candidat plausible par le contexte

Figure 17 : err.exe est une recherche transversale aux en-têtes, donc plusieurs candidats peuvent apparaître, et le plausible se choisit par le contexte.

7.2. Commandes intégrées à Windows

Ce que vous pouvez utiliser sans installation supplémentaire, ce sont certutil et net helpmsg. L’option -error de certutil affiche le texte de message qui correspond à un code d’erreur, et accepte soit un HRESULT hexadécimal soit un décimal.9

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

net helpmsg est pour un code d’erreur Win32 en décimal seulement, mais dans un environnement français le message revient en français, donc vous pouvez l’utiliser tel quel pour une explication à l’utilisateur.

Comment choisir parmi les commandes standardUn code d'erreur Win32 décimal se cherche avec net helpmsg ; un code qui inclut de l'hex, y compris HRESULT, se cherche avec l'option -error de certutilWin32 décimalInclut de l'hexLe code que vous avez est ?net helpmsgcertutil -errorUn message français revientAccepte hex et décimal

Figure 18 : Comment choisir parmi les commandes standard. Une erreur Win32 décimale est net helpmsg ; s’il y a de l’hex, certutil -error.

7.3. Une collection de one-liners PowerShell

# Win32 error code → OS message string
[System.ComponentModel.Win32Exception]::new(5).Message
# → Access is denied.

# Negative decimal → hex notation (confirm the identity of an HRESULT)
'0x{0:X8}' -f -2147467259     # 0x80004005

# 0x8007xxxx → the Win32 error code in the low 16 bits
0x80070005 -band 0xFFFF        # 5

# HRESULT → confirm the exception .NET maps
[System.Runtime.InteropServices.Marshal]::GetExceptionForHR(-2147024891)
# → UnauthorizedAccessException (0x80070005)

# Win32 error code → HRESULT (reproduce the wrap)
'0x{0:X8}' -f (0x80070000 -bor 32)   # 0x80070020

7.4. !error de WinDbg

Pour chercher un code pendant l’analyse de dump, l’extension !error de WinDbg est rapide. Par défaut elle interprète comme un code d’erreur Win32 ; passez 1 comme second argument et elle interprète comme NTSTATUS.10

0:000> !error 5
Error code: (Win32) 0x5 (5) - Access is denied.

0:000> !error 0xc0000005 1
Error code: (NTSTATUS) 0xc0000005 - <Access violation>

Dans un dump de plantage, !analyze -v affiche automatiquement le code d’exception (NTSTATUS), donc le flux est de confirmer le sens à partir de là avec !error <code> 1.

Flux pour confirmer un code d'exception dans WinDbgDans un dump de plantage la commande analyze affiche automatiquement le code d'exception ; passez ce code à l'extension error avec un second argument 1 et confirmez le sens comme NTSTATUSOuvrir le dump de plantageExécuter !analyze -vLe code d'exception s'afficheConfirmer le sens avec !error code 1

Figure 19 : En analyse de dump, cherchez le code d’exception que !analyze -v a affiché avec !error et le drapeau 1.

8. Une procédure d’investigation — Du jugement de couche à l’appariement au contexte

Assemblez les connaissances jusqu’ici en une procédure pour investiguer réellement un code d’erreur.

  1. Normalisez la notation. S’il s’agit d’un décimal négatif, convertissez-le en hex à 8 chiffres. Complétez de zéros un hex plus court que 8 chiffres et lisez-le.
  2. Jugez de quelle couche est le code. Comme dans le tableau de jugement ci-dessous, les premiers chiffres le décident presque.
  3. Décomposez et extraire le code essentiel. Une opération mécanique : les 16 bits bas si 0x8007xxxx, enlever le bit N si 0xDxxxxxxx.
  4. Cherchez le nom et la définition avec un outil. Confirmez le nom de symbole et le message avec err.exe, certutil ou !error.
  5. Appariez-le au contexte. Identifiez quelle application, quelle opération, quelle API, a échoué contre quoi, depuis le journal de l’application, le journal des événements et Procmon. Le code est « le genre d’échec » ; le contexte est « le lieu de la cause ».
Procédure pour investiguer un code d'erreurLe motif d'investigation d'aligner la notation sur l'hex, juger la couche depuis les premiers chiffres, décomposer et extraire le code essentiel, chercher le nom et la définition avec un outil, puis apparier au contexteDécimal0x80070xC0xDNormaliser en hexChiffres de tête ?Lire comme erreur Win3216 bits bas → décimalLire comme NTSTATUSEnlever le bit N et lireChercher nom/définitionApparier le contexte(Procmon)

Figure 20 : Le motif d’investigation. Normalisez la notation, jugez la couche et décomposez, cherchez le nom, puis appariez au contexte.

Apparence Premier candidat Comment décomposer et convertir
Un décimal de 1 à 5 chiffres (5, 1223, etc.) Code d’erreur Win32 Tel quel vers net helpmsg ou err.exe
Un décimal négatif (-2147024891, etc.) HRESULT Convertir en hex à 8 chiffres, puis le jugement des lignes suivantes
0x8007xxxx HRESULT (FACILITY_WIN32) Convertir les 16 bits bas en décimal et lire comme Win32
0x8004xxxx HRESULT (FACILITY_ITF) Le chercher dans la documentation du composant émetteur
0x8000xxxx HRESULT (FACILITY_NULL) Un code générique comme E_FAIL. Déplacer le poids vers une investigation de contexte
0xCxxxxxxx NTSTATUS (erreur) !error <code> 1 ; convertir en Win32 et lire si besoin
0xDxxxxxxx Un map HRESULT d’un NTSTATUS Enlever le bit N (0x10000000) et lire comme NTSTATUS
Une facility propre comme 0x8024xxxx Un HRESULT spécifique à un domaine Identifier le domaine depuis la valeur Facility et aller aux documents dédiés (0x8024… est Windows Update)2

Ce qui est surtout efficace à l’étape 5 « apparier au contexte » est la colonne Result de Process Monitor. Même si l’application ne montre que « 0x80070002 », Procmon vous dit en une ligne « quel processus, contre quel chemin, s’est vu renvoyer NAME NOT FOUND ». Pour chercher du côté du journal des événements, voir aussi « Introduction au journal des événements Windows et à ETW ».

9. Lectures erronées courantes — Des motifs qui envoient une investigation par le long chemin

Enfin, des motifs de lecture erronée qui apparaissent dans de vraies consultations.

Lecture erronée 1 : Penser que 0x80004005 est « un code qui indique une cause spécifique »

E_FAIL est « Unspecified failure », et la même valeur apparaît dans Windows Update, le réseau et les bases de données. Essayer chaque remédiation qui apparaît quand vous cherchez sur ce code est presque certainement le long chemin. Resserrez non depuis le code mais depuis « quelle application, quelle opération, d’autres journaux au même moment ».6

Lecture erronée 2 : Ne pas remarquer qu’un décimal négatif est un HRESULT

Un cas de chercher tel quel un journal qui dit « Error -2147467259 occurred », ou d’être perdu par « une erreur moins ? ». Face à un négatif, convertissez-le en hexadécimal. Cela seul vous dit que c’est 0x80004005 (E_FAIL), et se connecte à la connaissance de la lecture erronée 1.

Lecture erronée 3 : Chercher les 8 chiffres entiers de 0x8007xxxx et ne pas regarder l’erreur Win32 sous-jacente

L’essence de 0x80070005 est « 5 = accès refusé ». Penser à « ce que l’erreur Win32 5 signifie dans le contexte de cette opération » après avoir extrait les 16 bits bas atteint le cœur plus vite que de chercher sur les 8 chiffres entiers.

Lecture erronée 4 : Supposer « le même code = la même cause »

Si vous avez une fois eu « l’erreur 5 était causée par l’antivirus », vous tendez à sauter à la même remédiation à la prochaine erreur 5. Même avec le même code, si l’API qui a échoué et la ressource cible diffèrent, la cause est une autre chose. Confirmer le sens du code et identifier la cible avec Procmon ou similaire sont un ensemble, à chaque fois.

Lecture erronée 5 : Confondre l’erreur Win32 5 avec 0xC0000005, et un code STOP avec NTSTATUS

Traiter ERROR_ACCESS_DENIED et STATUS_ACCESS_VIOLATION comme les mêmes à cause du lien « 5 » envoie l’investigation dans des directions complètement différentes — un problème de droits contre un bogue de programme. Aussi, un code STOP d’écran bleu est un autre système que NTSTATUS, donc chercher 0x9F dans une table NTSTATUS ne produit pas de réponse utile.14

L'erreur 5 et 0xC0000005 ont des directions d'investigation différentesL'erreur Win32 5 doit s'investiguer comme un problème de droits, et NTSTATUS 0xC0000005 comme un bogue de programme ; les traiter comme les mêmes envoie l'investigation dans une autre directionErreur Win32 5Investiguer un problème de droitsNTSTATUS 0xC0000005Investiguer un bogue de programmeCodes sans rapport de systèmes différents

Figure 21 : Ne les traitez pas comme les mêmes à cause du lien « 5 ». L’erreur 5 va vers un problème de droits ; 0xC0000005 vers un bogue de programme.

10. Résumé

  • Les codes d’erreur Windows sont une structure à trois couches de codes d’erreur Win32, HRESULT et NTSTATUS. Jugez d’abord quelle couche, quel acteur a renvoyé le code.
  • Le flottement de notation (décimal / hex / négatif) peut s’aligner mécaniquement. Convertissez un négatif en hex à 8 chiffres puis lisez-le.
  • HRESULT est une structure de bits S/R/C/N/X + Facility (11 bits) + Code (16 bits), et 0x8007xxxx est le motif le plus important, une erreur Win32 emballée. Convertissez les 16 bits bas en décimal et extraire le code essentiel.
  • Un code générique comme 0x80004005 (E_FAIL) n’indique pas une cause. Le jugement d’arrêter de creuser le code et de passer à une investigation de contexte est possible précisément parce que vous connaissez la structure.
  • Vous rencontrez NTSTATUS comme code d’exception de plantage ou dans la colonne Result de Procmon. 0xC0000005 est une violation d’accès, sans rapport avec l’erreur Win32 5. Un code STOP est encore un autre système.
  • En .NET, un HRESULT est mappé à un type d’exception, et la valeur d’origine reste dans Exception.HResult. En P/Invoke, utilisez SetLastError=true et Marshal.GetLastWin32Error comme un ensemble.
  • Les outils de recherche sont certutil -error et net helpmsg (standard), err.exe (une machine de développement), les one-liners PowerShell, et !error de WinDbg.
  • La procédure est « normaliser la notation → juger la couche → décomposer → chercher le nom → apparier au contexte ». Ce qu’un code vous dit est le genre d’échec ; le lieu de la cause est ce que le contexte vous dit.

La prochaine fois que vous rencontrez un code d’erreur peu familier, regardez les premiers chiffres avant de le coller dans la boîte de recherche. Les 4 chiffres bas si 0x8007, NTSTATUS si 0xC, convertir en hex si négatif — cette décomposition de 10 secondes décide largement le temps d’investigation qui suit.

Articles connexes

Domaines de conseil associés

KomuraSoft LLC prend en charge l’investigation d’incidents qui part d’un code d’erreur — « je ne sais pas ce que ce code d’erreur signifie », « 0x80070005 n’apparaît que dans un environnement précis » —, la conception de la gestion d’erreurs pour des applications qui mélangent Win32 API, COM et .NET, et l’identification des causes avec des dumps de plantage et Process Monitor. Une consultation à partir d’une seule capture d’écran d’une boîte d’erreur convient.

Références

  1. Microsoft Learn, Debug system error codes. Index de la liste des codes d’erreur système Win32 (0–15999) ; obtention du message d’un code que GetLastError renvoie avec FormatMessage et le drapeau FORMAT_MESSAGE_FROM_SYSTEM ; le fait que les erreurs WinINet/WinHTTP (les 12000) sont définies dans cet espace ; et les méthodes d’investigation avec Microsoft Error Lookup Tool et la commande !err.  2 3 4 5 6

  2. Microsoft Open Specifications, [MS-ERREF]: HRESULT. La disposition des bits HRESULT (bits S, R, C, N et X, Facility 11 bits, Code 16 bits) ; le fait que le bit N indique une valeur NTSTATUS mappée dans l’espace HRESULT ; et la liste des codes de facility dont FACILITY_WINDOWS_UPDATE (36).  2 3 4 5

  3. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS. La disposition des bits NTSTATUS (Sev 2 bits, bit C, bit N, Facility 12 bits, Code 16 bits) ; et le fait que la sévérité se partage en quatre genres : succès (00), information (01), avertissement (10) et erreur (11).  2 3

  4. Microsoft Learn, HRESULT_FROM_WIN32 macro. La définition de la macro winerror.h qui mappe un code d’erreur système Win32 vers une valeur HRESULT.  2 3

  5. Microsoft Learn, Structure of COM Error Codes. Le rôle du bit de sévérité HRESULT et du champ facility ; les valeurs de FACILITY_NULL, FACILITY_RPC, FACILITY_ITF, FACILITY_WIN32 et FACILITY_WINDOWS ; et le fait qu’un code FACILITY_ITF a son sens défini par interface et que la même valeur peut signifier autre chose.  2 3

  6. Microsoft Learn, Common HRESULT values. Le fait que E_FAIL (0x80004005) est « Unspecified failure » ; et les définitions de valeurs HRESULT fréquentes comme E_ACCESSDENIED (0x80070005), E_INVALIDARG (0x80070057) et E_OUTOFMEMORY (0x8007000E).  2 3 4

  7. Microsoft Open Specifications, [MS-ERREF]: NTSTATUS values. La liste des valeurs NTSTATUS dont STATUS_ACCESS_VIOLATION (0xC0000005), STATUS_DLL_NOT_FOUND (0xC0000135), STATUS_STACK_OVERFLOW (0xC00000FD), STATUS_HEAP_CORRUPTION (0xC0000374) et STATUS_BREAKPOINT (0x80000003).  2 3

  8. Microsoft Learn, The Microsoft Error Lookup Tool. Le fait que c’est un outil autonome qui affiche le texte de message associé à un code d’état hexadécimal à travers divers fichiers d’en-tête comme Winerror.h ; que le nom de fichier de téléchargement est Err_6.4.5.exe ; et qu’il faut noter que les définitions empaquetées datent du moment de la compilation.  2 3

  9. Microsoft Learn, certutil. Le fait que l’option -error de certutil affiche le texte de message associé à un code d’erreur, et qu’une notation d’erreur qui inclut un nom de symbole est utilisée sous une forme comme 0x80070002 (WIN32: 2 ERROR_FILE_NOT_FOUND).  2

  10. Microsoft Learn, !error. Le fait que l’extension !error de WinDbg décode et affiche des valeurs d’erreur Win32, Winsock, NTSTATUS et NetAPI ; et que spécifier 1 comme drapeau interprète comme NTSTATUS.  2

  11. Microsoft Learn, How to: Map HRESULTs and exceptions. Le mécanisme de mapping mutuel entre HRESULT COM et exceptions .NET ; la table de correspondance comme E_NOTIMPL → NotImplementedException ; le fait qu’un HRESULT sans mapping explicite est converti en COMException ; et que Message, Source et assimilés de l’exception sont initialisés depuis les informations IErrorInfo.  2

  12. Microsoft Learn, RtlNtStatusToDosError function (winternl.h). Le fait que c’est une fonction qui convertit un code NTSTATUS vers le code d’erreur système Win32 correspondant ; qu’ERROR_MR_MID_NOT_FOUND est renvoyé quand aucune correspondance n’est définie ; et qu’une fonction de conversion inverse n’existe pas.  2

  13. Microsoft Learn, Last-Error Code. Le fait que le last-error code est tenu par thread ; qu’il doit être récupéré avec GetLastError immédiatement après l’échec ; que des API qui écrasent le code à 0 en cas de succès et des API qui n’y touchent pas se mélangent ; et que le bit 29 est réservé aux codes définis par l’application.  2

  14. Microsoft Learn, Bug check code reference. La liste des bug check codes (codes STOP) affichés sur un écran bleu, et comment afficher des informations sur un code avec l’extension !analyze de WinDbg. Qu’il s’agit d’un système de numérotation à part, distinct de NTSTATUS, se confirme depuis la liste.  2

  15. Microsoft Learn, Marshal.GetLastWin32Error Method. Le fait que c’est une façon de récupérer le last-error code d’un appel P/Invoke qui a posé le drapeau SetLastError ; que P/Invoquer GetLastError directement n’est pas fiable à cause d’un écrasement par un appel d’API à l’intérieur du runtime ; et que depuis .NET 6 GetLastPInvokeError est recommandé. 

Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.

Ces pages replacent le sujet dans un contexte plus large de services et de décisions.

Cet article est directement lié aux services suivants.

Questions fréquentes

Questions souvent posées lors d’une consultation sur le sujet de cet article.

Que signifie l'erreur 0x80004005 ?
0x80004005 est le HRESULT E_FAIL, et il signifie « Unspecified failure » (échec non spécifié). Autrement dit, il indique seulement qu'« un échec s'est produit sans pouvoir en rapporter la raison détaillée » ; ce n'est pas un code qui représente la cause elle-même. Le même 0x80004005 apparaît dans des endroits sans rapport — réseau, Windows Update, VBA, pilote de base de données — pour cette raison. Face à ce code, ne creusez pas le sens du code ; resserrez la cause à partir du contexte (quelle application, quelle opération) et des autres informations d'erreur laissées dans le journal des événements ou un journal détaillé.
Qu'est-ce qu'un code d'erreur négatif comme -2147467259 ?
C'est un HRESULT 32 bits affiché en décimal signé. Un HRESULT met le bit de poids fort à 1 en cas d'échec, donc en entier signé il est toujours négatif. Dans PowerShell, '0x{0:X8}' -f -2147467259 le reconvertit en hexadécimal (ici 0x80004005 = E_FAIL). Quand un journal ou un message de script montre un négatif commençant par -214…, le premier geste standard est de le convertir en hexadécimal puis de le rechercher.
Quel est le moyen le plus simple de chercher le sens d'un code d'erreur ?
Sans installation supplémentaire, utilisez net helpmsg 5 à l'invite de commandes (erreur Win32 en décimal) et certutil -error 0x80070005. certutil accepte aussi un HRESULT hexadécimal et affiche le nom de symbole et le texte du message. Dans PowerShell, [System.ComponentModel.Win32Exception]::new(5).Message obtient le message localisé. Sur une machine de développement, gardez l'outil officiel Microsoft err.exe (Microsoft Error Lookup Tool) ; il cherche dans Win32, HRESULT et NTSTATUS et liste les définitions correspondantes d'un coup.
Quel genre d'erreur est 0xC0000005 ?
C'est le NTSTATUS STATUS_ACCESS_VIOLATION, c'est-à-dire une violation d'accès (accès mémoire illégal). C'est le code le plus souvent vu comme « Exception code » dans le journal des événements ou dans un dump de plantage, et il indique un bogue de programme : déréférencement d'un pointeur invalide ou accès à de la mémoire déjà libérée. Il ressemble par le nom à l'erreur Win32 5 (ERROR_ACCESS_DENIED = accès refusé), mais c'est un code sans rapport d'un autre système ; ne les confondez pas. Le moyen fiable d'identifier la cause est de capturer un dump de plantage et de l'analyser dans WinDbg.
Pourquoi la cause est-elle différente à chaque fois, même avec le même code d'erreur ?
Parce qu'un code d'erreur ne représente que « quel genre d'échec », et que « ce qui a échoué et pourquoi » est décidé par le contexte d'appel. L'erreur 5 (accès refusé), par exemple, est le même code pour des causes totalement différentes — ACL NTFS insuffisant, privilèges d'administrateur manquants, blocage antivirus, etc. Dans une situation voisine, si un autre processus a encore le fichier ouvert, vous obtenez un autre code (erreur 32 = violation de partage), et lire le code correctement change où vous cherchez. L'erreur 2 (fichier introuvable) n'est souvent pas le fichier principal mais une DLL dépendante ou un fichier de paramètres. Une fois le sens du code trouvé, confirmer quelle API a échoué contre quelle ressource avec Process Monitor ou similaire est le chemin court vers la cause.

Profil de l’auteur

Page de présentation de l’auteur de l’article.

Go Komura

Représentant de KomuraSoft LLC

Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.

Retour au blog