502 lines
13 KiB
C++
502 lines
13 KiB
C++
/***
|
|
* 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 <winapifamily.h>
|
|
#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 <ole2.h>
|
|
|
|
#include <comutil.h>
|
|
#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 <roerrorapi.h>
|
|
#include <new.h>
|
|
#include <wchar.h>
|
|
|
|
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<unsigned int>(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 <olectl.h>
|
|
|
|
#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 <comip.h>
|
|
#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, &IID> > \
|
|
Interface ## Ptr
|
|
#else
|
|
#define _COM_SMARTPTR_TYPEDEF(Interface, IID) \
|
|
typedef _COM_SMARTPTR<Interface, &IID> \
|
|
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 */
|