« 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
GetLastErrorrenvoie), 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 -erroretnet helpmsgsont intégrés à Windows ;Win32Exceptionde PowerShell obtient le message ; sur une machine de développement, err.exe (Microsoft Error Lookup Tool) ; en analyse de dump,!errorde 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
flowchart TB
accTitle: Flux de conversion entre les trois systèmes
accDescr: Le sous-système Win32 convertit un NTSTATUS renvoyé par le noyau en code d'erreur Win32, et la couche COM l'emballe encore en HRESULT
kernel["Noyau et pilotes"] --> nt["NTSTATUS(erreurs 0xC…)"]
nt -->|Le sous-système Win32 convertit| win["Code d'erreur Win32(5 etc.)"]
win -->|La couche COM emballe| hr["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.
flowchart TB
accTitle: Trois apparences du même code
accDescr: L'erreur décimale 5, l'hex 0x5 et les 16 bits bas de 0x80070005 désignent tous le même ERROR_ACCESS_DENIED
d["Notation décimale: erreur 5"] --> same["ERROR_ACCESS_DENIED"]
h["Notation hex: 0x5"] --> same
l["Les 16 bits bas de 0x80070005"] --> same
same -.-> memo["Notation 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
- 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.
- 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.
sequenceDiagram
accTitle: Lire GetLastError juste après l'échec
accDescr: Aprè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'API
participant app as App
participant api as Win32 API
app->>api: Appel CreateFile
api-->>app: Valeur de retour d'échec
app->>api: GetLastError
api-->>app: Code 5
Note over app: Intercaler une autre API peut l'écraser
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.
flowchart TB
accTitle: Chercher un message à partir d'un code et le laisser dans le journal
accDescr: Passer 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 journal
code["Code d'erreur(ex.: 5)"] --> fm["Obtenir la chaîne avec FormatMessage"]
fm --> msg["Texte du message"]
msg --> log["Enregistrer dans le journal"]
log -.-> both["É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.
flowchart TB
accTitle: Les erreurs 998 et 5 sont des choses différentes
accDescr: 998 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é
nt["NTSTATUS 0xC0000005"] -->|Converti vers la couche Win32| e998["Erreur 998(ERROR_NOACCESS)"]
e998 -.-> m1["Le sens est une violation d'accès mémoire"]
e5["Erreur 5(accès refusé)"] -.-> m2["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.
flowchart TB
accTitle: La cause de l'erreur 5 est décidée par le contexte
accDescr: Mê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 quoi
e5["Erreur 5(accès refusé)"] --> c1["ACL insuffisant"]
e5 --> c2["Sans privilèges admin"]
e5 --> c3["Blocage produit de sécurité"]
e5 --> c4["Privilèges de service bas"]
c1 --> next["Procmon: cible en échec"]
c2 --> next
c3 --> next
c4 --> next
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.
flowchart TB
accTitle: Relation entre le bit S et un affichage négatif
accDescr: Un 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égatif
s["Bit S = 1(échec)"] --> hex["L'hex commence à 0x8 ou plus"]
hex --> neg["Un affichage signé est négatif"]
neg --> back["Face à 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.
flowchart TB
accTitle: Décomposition de 0x80004005 et 0x80070005
accDescr: 0x80004005 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é
a["0x80004005"] --> af["Facility=0(FACILITY_NULL)"]
af --> ac["Code=0x4005 → E_FAIL"]
ac --> ax["Échec non spécifié. Vers une investigation de contexte"]
b["0x80070005"] --> bf["Facility=7(FACILITY_WIN32)"]
bf --> bc["Code=0x0005 → 5"]
bc --> bx["ERROR_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 ».
flowchart TB
accTitle: Fonctionnement de HRESULT_FROM_WIN32
accDescr: Stocker le code d'erreur Win32 dans les 16 bits bas, poser Facility à 7 et le bit S à 1, et assembler un HRESULT 0x8007xxxx
win["Code d'erreur Win32(ex.: 5)"] --> low["Stocker dans les 16 bits bas"]
low --> fac["Poser Facility à 7"]
fac --> sbit["Poser le bit S à 1"]
sbit --> hr["0x80070005"]
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).
flowchart TB
accTitle: La façon de chercher change entre 0x8007 et 0x8004
accDescr: Un 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é
hr{"Facility est ?"} -->|7, WIN32| w["Convertir les 16 bits bas en décimal"]
hr -->|4, ITF| i["Le sens diffère selon qui l'a renvoyé"]
w --> ww["Le lire comme une erreur Win32"]
i --> ii["Le 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
flowchart TB
accTitle: Un NTSTATUS se lit par genre depuis le chiffre de tête
accDescr: Parce 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 à 0x3
head{"Le chiffre hex de tête est ?"} -->|0xC| e["Erreur"]
head -->|0x8| w["Avertissement"]
head -->|0x4| i["Information"]
head -->|0x0–0x3| s["Succès"]
w -.-> ex["Ex.: 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.
flowchart TB
accTitle: Distinguer un code d'exception d'un code STOP
accDescr: Lire 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ème
q{"Où le code est-il apparu ?"} -->|Code d'exception| nt["Le lire comme NTSTATUS"]
q -->|Code STOP| bc["Le chercher dans la table des bug-check"]
nt -.-> n1["Ex.: 0xC0000005"]
bc -.-> b1["Ex.: 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.
- 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
- Conversion vers un code d’erreur Win32 :
RtlNtStatusToDosErrorde 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.
flowchart TB
accTitle: Deux ponts de NTSTATUS vers les autres couches
accDescr: Un 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 RtlNtStatusToDosError
nt["NTSTATUS(0xC0000005)"] -->|Poser le bit N| hr["HRESULT(0xD0000005)"]
nt -->|RtlNtStatusToDosError| win["Erreur Win32 998(ERROR_NOACCESS)"]
win -.-> memo["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.
flowchart TB
accTitle: IErrorInfo qui complète HRESULT
accDescr: Il 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 ensemble
hr["HRESULT(32 bits seulement)"] --> lim["Il y a une limite à ce qui tient"]
lim --> ei["IErrorInfo porte la description"]
ei --> ce["_com_error les gère ensemble"]
ce -.-> dlg["Le 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
flowchart TB
accTitle: Mapping d'un HRESULT vers une exception .NET
accDescr: Un 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.HResult
hr["HRESULT d'échec"] --> known{"Un mapping connu ?"}
known -->|Yes| typed["Convertir vers le type d'exception"]
known -->|No| comex["Convertir vers COMException"]
typed --> keep["La valeur d'origine reste dans Exception.HResult"]
comex --> keep
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
flowchart TB
accTitle: Récupérer la dernière erreur en P/Invoke
accDescr: Spécifier SetLastError à true et récupérer avec Marshal.GetLastWin32Error est correct ; P/Invoquer GetLastError directement est inexact à cause d'un écrasement par le runtime
pi["Appeler une API Win32 via P/Invoke"] --> ok["Spécifier SetLastError=true"]
ok --> get["Récupérer avec GetLastWin32Error"]
pi --> ng["Une définition qui appelle GetLastError directement"]
ng --> bad["Le 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
flowchart TB
accTitle: Choisir les résultats de recherche d'err.exe par le contexte
accDescr: err.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 contexte
in["Saisir err 5"] --> scan["Parcourir de nombreux en-têtes"]
scan --> hits["Plusieurs définitions correspondent"]
hits --> pick["Choisir 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.
flowchart TB
accTitle: Comment choisir parmi les commandes standard
accDescr: Un 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 certutil
q{"Le code que vous avez est ?"} -->|Win32 décimal| net["net helpmsg"]
q -->|Inclut de l'hex| cert["certutil -error"]
net -.-> jp["Un message français revient"]
cert -.-> any["Accepte 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.
flowchart TB
accTitle: Flux pour confirmer un code d'exception dans WinDbg
accDescr: Dans 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 NTSTATUS
dump["Ouvrir le dump de plantage"] --> an["Exécuter !analyze -v"]
an --> exc["Le code d'exception s'affiche"]
exc --> chk["Confirmer 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.
- 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.
- Jugez de quelle couche est le code. Comme dans le tableau de jugement ci-dessous, les premiers chiffres le décident presque.
- Décomposez et extraire le code essentiel. Une opération mécanique : les 16 bits bas si 0x8007xxxx, enlever le bit N si 0xDxxxxxxx.
- Cherchez le nom et la définition avec un outil. Confirmez le nom de symbole et le message avec err.exe, certutil ou
!error. - 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 ».
flowchart TB
accTitle: Procédure pour investiguer un code d'erreur
accDescr: Le 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 contexte
fix["Normaliser en hex"] --> judge{"Chiffres de tête ?"}
judge -->|Décimal| d1["Lire comme erreur Win32"]
judge -->|0x8007| d2["16 bits bas → décimal"]
judge -->|0xC| d3["Lire comme NTSTATUS"]
judge -->|0xD| d4["Enlever le bit N et lire"]
d1 --> tool["Chercher nom/définition"]
d2 --> tool
d3 --> tool
d4 --> tool
tool --> ctx["Apparier 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
flowchart TB
accTitle: L'erreur 5 et 0xC0000005 ont des directions d'investigation différentes
accDescr: L'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 direction
a["Erreur Win32 5"] --> ad["Investiguer un problème de droits"]
b["NTSTATUS 0xC0000005"] --> bd["Investiguer un bogue de programme"]
a -.-> memo["Codes sans rapport de systèmes différents"]
b -.-> memo
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
- Lire un dump de plantage avec WinDbg + SOS — Guide pratique d’analyse après la collecte
- Introduction à la collecte des dumps de crash Windows - WER/ProcDump/WinDbg
- Où catch et la journalisation doivent-ils se situer dans la gestion des exceptions ?
- Guide pratique de Process Monitor (ProcMon) — identifier en 10 minutes un « paramètre non pris en compte » ou un ACCESS DENIED
- Introduction au journal des événements Windows et à ETW — placer les journaux de votre application métier sur les mécanismes standard de l’OS
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.
- Développement d’applications Windows
- Investigation de bugs et analyse des causes
- Conseil technique et revue de conception
- Nous contacter
Références
-
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
GetLastErrorrenvoie 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 -
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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
-
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 associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
L'API du pool de threads Win32 — de la concurrence sans créer de threads, via CreateThreadpoolWork
Vous semez des appels CreateThread partout dans votre code natif ? Cet article explique l'API du pool de threads Win32 refondue sous Vist...
Tubes nommés en pratique — l'IPC standard de Windows, de la conception à la sécurité
Guide pratique des tubes nommés, mécanisme standard de communication inter-processus sous Windows. Cet article organise, à partir des sou...
Les applications qui cassent à la reprise de veille — comment fonctionnent les événements d'alimentation Windows et comment construire des applications métier qui y survivent
Vous avez ouvert le portable et les connexions de l'application métier étaient mortes — la cause est une conception qui n'a jamais tenu c...
DllMain et le verrou du chargeur — la vraie raison pour laquelle on vous dit de « ne rien faire dans l'initialisation d'une DLL »
Pourquoi il ne faut pas appeler LoadLibrary ni synchroniser avec d'autres threads depuis DllMain. En s'appuyant sur les sources primaires...
Ce qu'est vraiment « Ne répond pas » — comment Windows décide qu'une application est bloquée, et comment concevoir des applications qui ne le sont pas
Le « Ne répond pas » de Windows est un mécanisme dans lequel l'OS juge qu'une fenêtre n'a pas récupéré de message pendant 5 secondes et l...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
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.