diff options
Diffstat (limited to 'shared/com_error.h')
-rw-r--r-- | shared/com_error.h | 178 |
1 files changed, 157 insertions, 21 deletions
diff --git a/shared/com_error.h b/shared/com_error.h index 39f26555..e3d51d4b 100644 --- a/shared/com_error.h +++ b/shared/com_error.h @@ -9,31 +9,22 @@ #include <string> #include <cstdio> -#include <comdef.h> +#include <windows.h> +#undef min +#undef max namespace util { std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr); +std::wstring formatWin32Msg(DWORD dwMessageId); //return empty string on error + + + -class ComException -{ -public: - ComException(const std::wstring& message, HRESULT hr = NO_ERROR) - : message_(message), hr_(hr) {} - std::wstring show() const - { - return hr_ != NO_ERROR ? generateErrorMsg(message_, hr_) : message_; - } -private: - ComException(const ComException&); - ComException& operator=(const ComException&); - const std::wstring message_; - const HRESULT hr_; -}; @@ -56,6 +47,144 @@ private: //################# implementation ##################### +std::wstring formatWin32Msg(DWORD dwMessageId) //return empty string on error +{ + std::wstring output; + LPWSTR buffer = NULL; + if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_MAX_WIDTH_MASK | + FORMAT_MESSAGE_IGNORE_INSERTS | //important: without this flag ::FormatMessage() will fail if message contains placeholders + FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwMessageId, 0, reinterpret_cast<LPWSTR>(&buffer), 0, NULL) != 0) + { + if (buffer) //just to be sure + { + output = buffer; + ::LocalFree(buffer); + } + } + return output; +} + +namespace +{ +std::wstring formatFacility(HRESULT hr) +{ + switch (HRESULT_FACILITY(hr)) + { + case FACILITY_XPS: + return L"XPS"; + case FACILITY_WINRM: + return L"Windows Resource Manager"; + case FACILITY_WINDOWSUPDATE: + return L"Windows Update"; + case FACILITY_WINDOWS_DEFENDER: + return L"Windows Defender Component"; + case FACILITY_WINDOWS_CE: + return L"Windows CE"; + case FACILITY_WINDOWS: + return L"Windows Subsystem"; + case FACILITY_USERMODE_VOLMGR: + return L"User Mode Volume Manager"; + case FACILITY_USERMODE_VIRTUALIZATION: + return L"User Mode Virtualization Subsystem"; + case FACILITY_USERMODE_VHD: + return L"User Mode Virtual Hard Disk Support"; + case FACILITY_URT: + return L".NET CLR"; + case FACILITY_UMI: + return L"Ubiquitous Memoryintrospection Service"; + case FACILITY_UI: + return L"UI"; + case FACILITY_TPM_SOFTWARE: + return L"Trusted Platform Module Applications"; + case FACILITY_TPM_SERVICES: + return L"Trusted Platform Module Services"; + case FACILITY_SXS: + return L"Side-by-side Servicing"; + case FACILITY_STORAGE: + return L"OLE Storage"; + case FACILITY_STATE_MANAGEMENT: + return L"State Management Services"; + case FACILITY_SCARD: + return L"Smart-card Subsystem"; + case FACILITY_SHELL: + return L"User Shell"; + case FACILITY_SETUPAPI: + return L"Setup API"; + case FACILITY_SECURITY: + return L"Security API Layer"; + case FACILITY_SDIAG: + return L"System Diagnostics"; + case FACILITY_RPC: + return L"RPC Subsystem"; + case FACILITY_RAS: + return L"RAS"; + case FACILITY_PLA: + return L"Performance Logs and Alerts"; + case FACILITY_OPC: + return L"Open Connectivity Service"; + case FACILITY_WIN32: + return L"Win32"; + case FACILITY_CONTROL: + return L"Control Mechanism"; + case FACILITY_WEBSERVICES: + return L"Web Services"; + case FACILITY_NDIS: + return L"Network Driver Interface"; + case FACILITY_METADIRECTORY: + return L"Microsoft Identity Server"; + case FACILITY_MSMQ: + return L"Microsoft Message Queue"; + case FACILITY_MEDIASERVER: + return L"Windows Media Server"; + case FACILITY_MBN: + return L"MBN"; + case FACILITY_INTERNET: + return L"Wininet"; + case FACILITY_ITF: + return L"COM/OLE Interface Management"; + case FACILITY_USERMODE_HYPERVISOR: + return L"Usermode Hypervisor Components"; + case FACILITY_HTTP: + return L"HTTP Support"; + case FACILITY_GRAPHICS: + return L"Graphics Drivers"; + case FACILITY_FWP: + return L"Firewall Platform"; + case FACILITY_FVE: + return L"Full volume encryption"; + case FACILITY_USERMODE_FILTER_MANAGER: + return L"User Mode Filter Manager"; + case FACILITY_DPLAY: + return L"Direct Play"; + case FACILITY_DISPATCH: + return L"COM Dispatch"; + case FACILITY_DIRECTORYSERVICE: + return L"Active Directory"; + case FACILITY_CONFIGURATION: + return L"Configuration Services"; + case FACILITY_COMPLUS: + return L"COM+"; + case FACILITY_USERMODE_COMMONLOG: + return L"Common Logging Support"; + case FACILITY_CMI: + return L"Configuration Management Infrastructure"; + case FACILITY_CERT: + return L"Certificate"; + case FACILITY_BCD: + return L"Boot Configuration Database"; + case FACILITY_BACKGROUNDCOPY: + return L"Background Copy Control"; + case FACILITY_ACS: + return L"Audit Collection Service"; + case FACILITY_AAF: + return L"Microsoft Agent"; + default: + return L"Unknown"; + } +} +} + inline std::wstring numberToHexString(long number) { @@ -69,11 +198,18 @@ inline std::wstring generateErrorMsg(const std::wstring& input, HRESULT hr) { std::wstring output(input); - output += L" ("; - output += numberToHexString(hr); - output += L": "; - output += _com_error(hr).ErrorMessage(); - output += L")"; + output += L"\n"; + output += L"HRESULT: " + numberToHexString(hr) + L",\n"; + + //don't use _com_error(hr).ErrorMessage(), this is nothing more than a call to ::FormatMessage() + std::wstring win32Msg = formatWin32Msg(hr); + if (!win32Msg.empty()) //empty string on error + output += win32Msg; + else + { + output += L"Facility: " + formatFacility(hr) + L",\n"; + output += L"Win32 Error: " + formatWin32Msg(HRESULT_CODE(hr)); //interpet hr as a Win32 code; this is often useful + } return output; } } |