2013-10-23 7 views
13

Ich mache einige Programmierung in Win32 + WTL, und ich bin verwirrt mit den verfügbaren Arten von Fehlern.Fehler in Windows - DWORD (GetLastError) vs HRESULT vs LSTATUS

Im Allgemeinen möchte ich nach einem Fehler suchen und es an AtlGetErrorDescription einspeisen (die FormatMessage aufruft).

Meine Fragen sind: von GetLastError

  • DWORD, kehrte:

    1. Was ist der Unterschied zwischen ist.

    2. HRESULT, zurückgegeben von z.B. der CAtlFile Wrapper, der HRESULT_FROM_WIN32 verwendet, um von DWORD zu konvertieren.
    3. LSTATUS, zurückgegeben von z.B. RegCreateKeyEx.
  • Welche Arten von Fehlern kann ich an FormatMessage liefern? Seine Signatur zeigt an, dass es HRESULT akzeptiert, aber es gibt viele Beispiele, bei denen der Rückgabewert GetLastError direkt an FormatMessage übergeben wird.

  • Antwort

    20

    Sie spiegeln nur verschiedene APIs in Windows verwendet:

    • GetLastError() gibt einen winapi Fehlercode. Eine einfache Zahl beginnend bei 1. Sie werden normalerweise aus einem zugrunde liegenden nativen API-Fehlercode gemappt. Wie ERROR_FILE_NOT_FOUND wird von dem STATUS_OBJECT_NAME_NOT_FOUND Dateisystem-Treiber-Fehlercode zugeordnet. Winapi-Fehlercodes werden in der Header-Datei WinError.h SDK deklariert. Sie können darauf zählen, eine beschreibende Zeichenfolge von FormatMessage() mit der Option FORMAT_MESSAGE_FROM_SYSTEM abzurufen.

    • Ein HRESULT ist ein COM-Fehlercode. Es besteht aus drei grundlegenden Teilen, die hohen Bits zeigen den Schweregrad an, die mittleren Bits kodieren die Einrichtung, die die Quelle des Fehlers anzeigt, die niedrigen 16 Bits kodieren eine Fehlernummer. Das Makro HRESULT_FROM_WIN32() ist ein Hilfsmakro, um einen WinAPI-Fehlercode einem COM-Fehlercode zuzuordnen. Es setzt nur den Schweregrad auf "fail", der Einrichtungscode auf 7 (winapi) und kopiert den Fehlercode in die niedrigen Bits. Es gibt viele mögliche COM-Fehlercodes und nur einige von ihnen sind in eine Zeichenfolge von FormatMessage() konvertierbar. Sie sollten die ISupportErrorInfo-Schnittstelle verwenden, um zu fragen, ob der COM-Server eine Beschreibung des Fehlers über IErrorInfo bereitstellen kann.

    • LSTATUS ist obskur, RegCreateEx gibt tatsächlich LONG zurück, nur der Winapi-Fehlercode. Es erscheint in einigen Shell-Wrapper-Funktionen wie SHGetValue(). Es ist mir oft sehr unklar, warum das Shell-Team das tut, was es tut.

    • Nicht in Ihrer Frage erwähnt, aber beachtenswert sind die Fehlercodes, die von der nativen API erzeugt werden. Sie sind im ntstatus.h SDK-Header dokumentiert. Der Winapi soll die native API umhüllen, aber diese Fehlercodes sehen manchmal, besonders in Ausnahmen, manchmal die Kanten ab. Die meisten Programmierer haben den Ausnahmecode 0xc0000005 (STATUS_ACCESS_VIOLATION) gesehen. 0xc00000fd stimmt mit dem Namen dieser Site überein. FormatMessage() kann die allgemeinen in eine Zeichenfolge konvertieren, sofern es sich nicht um einen benutzerdefinierten Fehlercode handelte, der von einem Treiber generiert wurde. Es gibt mehrere APIs, die diese Art von Fehlercodes verwenden, obwohl sie im Benutzermodus ausgeführt werden.Gängige Beispiele sind WIC und Media Foundation, ansonsten ohne einen starken Hinweis, warum sie es so bevorzugen. Um eine Zeichenfolge für einen solchen Fehlercode abzurufen, muss FormatMessage mit der Option FORMAT_MESSAGE_FROM_HMODULE verwendet werden.

    +2

    Vielen Dank für die ausführliche Antwort. Bedeutet das, dass 'FormatMessage' sowohl 'GetLastError()' als auch 'HRESULT_FROM_WIN32 (GetLastError())' 'behandeln kann? Auch verstehe ich nicht, warum manchmal ATL-Wrapper den WINAPI-Fehlercode (z. B. "CRegKey") und manchmal den "HRESULT" -Code (z. B. "CAtlFile") zurückgeben. Ist es in Ordnung, entweder das Ergebnis in einem DWORD zu behalten und den Fehler, falls vorhanden, an "FormatMessage" zu übergeben? – Paul

    +0

    ATL ist stark auf COM ausgerichtet, so dass COM-Fehlercodes nicht ungewöhnlich sind. Aber ja, es ist nicht konsequent darüber. Gehen Sie einfach zum Rückgabetyp, um den Unterschied zu sehen. Und ja, es ist nicht so, dass Sie ein anderes Oracle als FormatMessage() haben, um Ihnen eine Zeichenfolge zu geben. –

    +0

    Sie haben noch nicht geantwortet, ob 'FormatMessage' beide Arten von Fehlermeldungen akzeptiert. Ich schätze, ich probiere es einfach aus :) Eine weitere Unannehmlichkeit ist, dass sie verschiedene Möglichkeiten haben, Erfolg/Misserfolg anzuzeigen - '== ERROR_SUCCESS' vs' SUCCEEDED'. Also gibt es vielleicht keinen anderen Weg, als bei einem der beiden zu bleiben - und weil AFAIK es nicht möglich ist, 'HRESULT' in den WINAPI-Fehlercode zu konvertieren, würde ich wohl' HRESULT' verwenden müssen. Das ist ziemlich nervtötend, da ich 'HRESULT_FROM_WIN32' ziemlich oft verwenden müsste. – Paul