ComHrErrの概要 - inoueshinichi/Wiki_Windows GitHub Wiki

参考

Windows ATL(COM) Error (HRESULT)

#include <atlbase.h>

名前 説明
S_OK 0x00000000 成功
E_UNEXPECTED 0x8000FFFF 予期しないエラー
E_NOTIMPL 0x80004001 未実装
E_OUTOFMEMORY 0x8007000E メモリ割り当ての失敗
E_INVALIDARG 0x80070057 1 つ以上の引数が無効
E_NOINTERFACE 0x80004002 インターフェースの未実装
E_POINTER 0x80004003 無効なポインタ
E_HANDLE 0x80070006 無効なハンドル
E_ABORT 0x80004004 中止
E_FAIL 0x80004005 不特定のエラー
E_ACCESSDENIED 0x80070005 アクセス拒否エラー

プログラム例

#pragma once
#include <framework.hpp>
#include <defs.hpp>
#include <format_string.hpp>

#include <cstdio>  // std::snprintf
#include <cstdlib> // std::abort
#include <vector>
#include <exception>
#include <iostream>
#include <sstream>
#include <string>

/**
 * @brief HRESULTに関して
 * https://learn.microsoft.com/ja-jp/cpp/windows/attributes/attribute-programming-faq?view=msvc-170
 *
 * HRESULT は単純なデータ型. 一般的にWidows-ATLによって戻り値としてよく使用される.
 * Windows API エラーから主なエラーコードを抜粋してCOM仕様に仕立ててある.
 */

namespace is
{
    /* Windows-COMに関する例外スロー */
#define IS_COM_HR_ERROR(hr, msg, ...)                              \
    throw ComHrException(hr, is::FormatString(msg, ##__VA_ARGS__), \
                    __func__, __FILE__, __LINE__);

#define IS_COM_HR_CHECK(hr, msg, ...)                                               \
    if (FAILED(hr))                                                                 \
    {                                                                               \
        IS_COM_HR_ERROR(hr, std::string("Failed `" #hr "`: ") + msg, ##__VA_ARGS__) \
    }

#define IS_COM_HR_FORCE_ASSERT(hr, msg, ...)                                      \
    if (FAILED(hr))                                                               \
    {                                                                             \
        std::cerr << "Aborting: " << is::FormatString(msg, ##__VA_ARGS__)         \
                  << " at " << __func__                                           \
                  << " in " << __FILE__                                           \
                  << ":" << __LINE__                                              \
                  << std::endl;                                                   \
        std::abort();                                                             \
    }

    inline std::string GetComHrErrorString(HRESULT hr)
    {
        /* ShiftJisでメッセージ作成 */
        int size = std::snprintf(nullptr, 0, "HRESULT of 0x%08X", static_cast<UINT>(hr));
        if (size < 0)
        {
            _tprintf(_T("Fatal error: std::snprintf() in GetAtlHrErrorString.\n"));
            std::abort();
        }

        /* バッファサイズを算出(文字列長 + null文字サイズ) */
        size_t bufSize = size + sizeof(char);

        /* バッファサイズ分メモリ確保 */
        std::vector<char> buf(bufSize);

        /* 文字列のフォーマット */
        std::snprintf(buf.data(), bufSize, "HRESULT of 0x%08X", static_cast<UINT>(hr));

        /* ShiftJisメッセージ */
        std::string msg(buf.data(), buf.data() + size);
        return msg;
    }

    /**
     * @brief Com HRESULT HANDLE Exception クラス
     *
     */
    class IS_WIN_API ComHrException : public std::exception
    {
    protected:
        ATL::CString mFullMsg; // 表示されるFullメッセージ
        std::string  mMsg;     // エラーメッセージ
        std::string  mFunc;    // エラーが発生した関数名
        std::string  mFile;    // エラーが発生したファイル名
        int mLine;             // エラーが発生した行番号

        HRESULT mHr; // WindowsのHRESULTハンドル
    public:
        ComHrException(HRESULT hr, const std::string &msg, const std::string &func, const std::string &file, int line)
            : mHr(hr), mMsg(msg), mFunc(func), mFile(file), mLine(line)
        {
            std::ostringstream oss;
            oss << GetComHrErrorString(mHr) << " in "
                << mFunc << ":" << mLine << std::endl;
            oss << mMsg << std::endl;

#if (defined(UNICODE) || defined(_UNICODE)) && !defined(_MBCS)
             mFullMsg =  is::CvtShiftJisToUtf16(oss.str()).c_str();
#else
             mFullMsg = oss.str().c_str();
#endif
        }

        virtual ~ComHrException() noexcept {}
        virtual const TCHAR * What() const noexcept { return mFullMsg.GetString(); }
        HRESULT GetHrError() const { return mHr; }
    };
}
  • Windowsがデフォルトで用意するATLエラー処理関数を使うと簡潔に処理できるはず.
⚠️ **GitHub.com Fallback** ⚠️