/*** * comdef.h - Native C++ compiler COM support - main definitions header * * Copyright (c) Microsoft Corporation. All rights reserved. * ****/ #if _MSC_VER > 1000 #pragma once #endif #if !defined(_INC_COMDEF) #define _INC_COMDEF #if !defined(RC_INVOKED) #ifndef __cplusplus #error Native Compiler support only available in C++ compiler #endif #ifdef _M_CEE_PURE #error comdef.h header cannot be included under /clr:safe or /clr:pure #endif #ifdef WINAPI_FAMILY #include #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #define _COMDEF_NOT_WINAPI_FAMILY_DESKTOP_APP #endif /* !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ #if defined WINAPI_FAMILY_PHONE_APP && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) #define _COMDEF_WINAPI_FAMILY_PHONE_APP #endif /* defined WINAPI_FAMILY_PHONE_APP && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) */ #endif /* WINAPI_FAMILY */ #ifndef _COMDEF_WINAPI_FAMILY_PHONE_APP #include #include #endif /* _COMDEF_WINAPI_FAMILY_PHONE_APP */ #pragma warning(push) #pragma warning(disable: 4244) #pragma warning(disable: 4290) #ifdef _COMDEF_NOT_WINAPI_FAMILY_DESKTOP_APP #include #include #include inline void __stdcall _com_issue_error(HRESULT hr); class _com_error { protected: static wchar_t* AllocateString(const wchar_t* message) { wchar_t* value = nullptr; if (message != nullptr) { auto length = ::wcslen(message) + 1; // add 1 for null terminator value = new (std::nothrow) wchar_t[length]; if (value == nullptr) { _com_issue_error(E_OUTOFMEMORY); } ::wmemcpy(value, message, length); } return value; } public: _com_error(HRESULT hr, const wchar_t* message) : m_hr(hr), m_message(nullptr) { m_message = AllocateString(message); } _com_error(const _com_error& other) { m_hr = other.m_hr; m_message = AllocateString(other.m_message); } _com_error(_com_error&& other) { m_hr = other.m_hr; m_message = other.m_message; other.m_message = nullptr; } ~_com_error() throw() { delete [] m_message; } _com_error& operator=(const _com_error& other) { if (this != &other) { m_hr = other.m_hr; delete [] m_message; m_message = AllocateString(other.m_message); } return *this; } _com_error& operator=(_com_error&& other) { if (this != &other) { m_hr = other.m_hr; delete [] m_message; m_message = other.m_message; other.m_message = nullptr; } return *this; } HRESULT Error() const throw() { return m_hr; } const wchar_t* ErrorMessage() const throw() { if (m_message == nullptr) { wchar_t buffer[4096]; if (::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, m_hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, _countof(buffer), nullptr)) { m_message = AllocateString(buffer); } } return m_message; } protected: HRESULT m_hr; mutable wchar_t* m_message; }; inline void __declspec(noreturn) __stdcall _com_raise_error(HRESULT hr, const wchar_t* message) { size_t length = (message == nullptr) ? 0 : ::wcslen(message); if (UINT_MAX < length) { length = 0; } ::Windows::Foundation::Diagnostics::OriginateError(hr, static_cast(length), message); throw _com_error(hr, message); } typedef void (__stdcall *__errorPfnType)(HRESULT hr, const wchar_t* message); // throw exceptions by default __declspec(selectany) __errorPfnType __errorPfn = &_com_raise_error; inline void __stdcall _com_issue_errorex(HRESULT hr, const wchar_t* message) { __errorPfn(hr, message); } inline void __stdcall _com_issue_error(HRESULT hr) { __errorPfn(hr, nullptr); } inline void __stdcall _set_com_error_handler(void (__stdcall *pHandler)(HRESULT, const wchar_t*)) { __errorPfn = pHandler; } #else #include #ifdef _NATIVE_WCHAR_T_DEFINED # ifdef _DEBUG # pragma comment(lib, "comsuppwd.lib") # else # pragma comment(lib, "comsuppw.lib") # endif #else # ifdef _DEBUG # pragma comment(lib, "comsuppd.lib") # else # pragma comment(lib, "comsupp.lib") # endif #endif #pragma comment(lib, "user32.lib") #pragma comment(lib, "ole32.lib") #pragma comment(lib, "oleaut32.lib") class _com_error; void __declspec(noreturn) __stdcall _com_raise_error(HRESULT hr, IErrorInfo* perrinfo = 0) ; void __stdcall _set_com_error_handler(void (__stdcall *pHandler)(HRESULT hr, IErrorInfo* perrinfo)); void __stdcall _com_issue_error(HRESULT) ; void __stdcall _com_issue_errorex(HRESULT, IUnknown*, REFIID) ; HRESULT __stdcall _com_dispatch_propget(IDispatch*, DISPID, VARTYPE, void*) ; HRESULT __cdecl _com_dispatch_propput(IDispatch*, DISPID, VARTYPE, ...) ; HRESULT __cdecl _com_dispatch_method(IDispatch*, DISPID, WORD, VARTYPE, void*, const wchar_t*, ...) ; HRESULT __stdcall _com_dispatch_raw_propget(IDispatch*, DISPID, VARTYPE, void*) throw(); HRESULT __cdecl _com_dispatch_raw_propput(IDispatch*, DISPID, VARTYPE, ...) throw(); HRESULT __cdecl _com_dispatch_raw_method(IDispatch*, DISPID, WORD, VARTYPE, void*, const wchar_t*, ...) throw(); class _com_error { public: // Constructors // _com_error(HRESULT hr, IErrorInfo* perrinfo = NULL, bool fAddRef = false) throw(); _com_error(const _com_error& that) throw(); // Destructor // virtual ~_com_error() throw(); // Assignment operator // _com_error& operator=(const _com_error& that) throw(); // Accessors // HRESULT Error() const throw(); WORD WCode() const throw(); IErrorInfo * ErrorInfo() const throw(); // IErrorInfo method accessors // _bstr_t Description() const ; DWORD HelpContext() const throw(); _bstr_t HelpFile() const ; _bstr_t Source() const ; GUID GUID() const throw(); // FormatMessage accessors // const TCHAR * ErrorMessage() const throw(); // EXCEPINFO.wCode <-> HRESULT mappers // static HRESULT WCodeToHRESULT(WORD wCode) throw(); static WORD HRESULTToWCode(HRESULT hr) throw(); private: enum { WCODE_HRESULT_FIRST = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x200), WCODE_HRESULT_LAST = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF+1, 0) - 1 }; const HRESULT m_hresult; IErrorInfo * m_perrinfo; mutable TCHAR * m_pszMsg; }; inline _com_error::_com_error(HRESULT hr, IErrorInfo* perrinfo, bool fAddRef) throw() : m_hresult(hr), m_perrinfo(perrinfo), m_pszMsg(NULL) { if (m_perrinfo != NULL && fAddRef) { m_perrinfo->AddRef(); } } inline _com_error::_com_error(const _com_error& that) throw() : m_hresult(that.m_hresult), m_perrinfo(that.m_perrinfo), m_pszMsg(NULL) { if (m_perrinfo != NULL) { m_perrinfo->AddRef(); } } inline _com_error::~_com_error() throw() { if (m_perrinfo != NULL) { m_perrinfo->Release(); } if (m_pszMsg != NULL) { LocalFree((HLOCAL)m_pszMsg); } } inline _com_error& _com_error::operator=(const _com_error& that) throw() { if (this != &that) { this->_com_error::~_com_error(); this->_com_error::_com_error(that); } return *this; } inline HRESULT _com_error::Error() const throw() { return m_hresult; } inline WORD _com_error::WCode() const throw() { return HRESULTToWCode(m_hresult); } inline IErrorInfo * _com_error::ErrorInfo() const throw() { if (m_perrinfo != NULL) { m_perrinfo->AddRef(); } return m_perrinfo; } inline _bstr_t _com_error::Description() const { BSTR bstr = NULL; if (m_perrinfo != NULL) { if (FAILED(m_perrinfo->GetDescription(&bstr))) { bstr = NULL; } } return _bstr_t(bstr, false); } inline DWORD _com_error::HelpContext() const throw() { DWORD dwHelpContext = 0; if (m_perrinfo != NULL) { if (FAILED(m_perrinfo->GetHelpContext(&dwHelpContext))) { dwHelpContext = 0; } } return dwHelpContext; } inline _bstr_t _com_error::HelpFile() const { BSTR bstr = NULL; if (m_perrinfo != NULL) { if (FAILED(m_perrinfo->GetHelpFile(&bstr))) { bstr = NULL; } } return _bstr_t(bstr, false); } inline _bstr_t _com_error::Source() const { BSTR bstr = NULL; if (m_perrinfo != NULL) { if (FAILED(m_perrinfo->GetSource(&bstr))) { bstr = NULL; } } return _bstr_t(bstr, false); } inline _GUID _com_error::GUID() const throw() { _GUID guid; _COM_MEMCPY_S(&guid, sizeof(_GUID), &__uuidof(NULL), sizeof(_GUID)); if (m_perrinfo != NULL) { if (FAILED(m_perrinfo->GetGUID(&guid))) { _COM_MEMCPY_S(&guid, sizeof(_GUID), &__uuidof(NULL), sizeof(_GUID)); } } return guid; } inline const TCHAR * _com_error::ErrorMessage() const throw() { if (m_pszMsg == NULL) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_hresult, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&m_pszMsg, 0, NULL); if (m_pszMsg != NULL) { int nLen = lstrlen(m_pszMsg); if (nLen > 1 && m_pszMsg[nLen - 1] == '\n') { m_pszMsg[nLen - 1] = 0; if (m_pszMsg[nLen - 2] == '\r') { m_pszMsg[nLen - 2] = 0; } } } else { m_pszMsg = (LPTSTR)LocalAlloc(0, 32 * sizeof(TCHAR)); if (m_pszMsg != NULL) { WORD wCode = WCode(); if (wCode != 0) { _COM_PRINTF_S_1(m_pszMsg, 32, TEXT("IDispatch error #%d"), (int)wCode); } else { _COM_PRINTF_S_1(m_pszMsg, 32, TEXT("Unknown error 0x%0lX"), m_hresult); } } } } return m_pszMsg; } inline HRESULT _com_error::WCodeToHRESULT(WORD wCode) throw() { return wCode >= 0xFE00 ? WCODE_HRESULT_LAST : WCODE_HRESULT_FIRST + wCode; } inline WORD _com_error::HRESULTToWCode(HRESULT hr) throw() { return (hr >= WCODE_HRESULT_FIRST && hr <= WCODE_HRESULT_LAST) ? WORD(hr - WCODE_HRESULT_FIRST) : 0; } // // give missing types from dependent type libraries a chance // typedef int __missing_type__; #if !defined(_COM_SMARTPTR) #if !defined(_INC_COMIP) #include #endif #define _COM_SMARTPTR _com_ptr_t #define _COM_SMARTPTR_LEVEL2 _com_IIID #endif #if defined(_COM_SMARTPTR) #if !defined(_COM_SMARTPTR_TYPEDEF) #if defined(_COM_SMARTPTR_LEVEL2) #define _COM_SMARTPTR_TYPEDEF(Interface, IID) \ typedef _COM_SMARTPTR<_COM_SMARTPTR_LEVEL2 > \ Interface ## Ptr #else #define _COM_SMARTPTR_TYPEDEF(Interface, IID) \ typedef _COM_SMARTPTR \ Interface ## Ptr #endif #endif #endif #if !defined(_COM_NO_STANDARD_GUIDS_) // hard-coded smart pointer defs #if defined(__IFontDisp_INTERFACE_DEFINED__) __if_not_exists(Font) { struct Font : IFontDisp {}; } _COM_SMARTPTR_TYPEDEF(Font, __uuidof(IDispatch)); #endif #if defined(__IFontEventsDisp_INTERFACE_DEFINED__) __if_not_exists(FontEvents) { struct FontEvents : IFontEventsDisp {}; } _COM_SMARTPTR_TYPEDEF(FontEvents, __uuidof(IDispatch)); #endif #if defined(__IPictureDisp_INTERFACE_DEFINED__) __if_not_exists(Picture) { struct Picture : IPictureDisp {}; } _COM_SMARTPTR_TYPEDEF(Picture, __uuidof(IDispatch)); #endif #include "comdefsp.h" #endif /* _COM_NO_STANDARD_GUIDS_ */ #endif /* _COMDEF_NOT_WINAPI_FAMILY_DESKTOP_APP */ #pragma warning(pop) #endif /* RC_INVOKED */ #endif /* _INC_COMDEF */