/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */
#ifndef _INC_COMDEF
#define _INC_COMDEF

#include <_mingw.h>

#ifndef RC_INVOKED

#ifndef __cplusplus
#error Native Compiler support only available in C++ compiler
#endif

#include <ole2.h>
#include <olectl.h>
#include <comutil.h>

#ifndef WINAPI
#define WINAPI __stdcall
#endif

#ifdef __cplusplus

class _com_error;
void WINAPI _com_raise_error(HRESULT hr,IErrorInfo *perrinfo = 0);
void WINAPI _set_com_error_handler(void (WINAPI *pHandler)(HRESULT hr,IErrorInfo *perrinfo));
void WINAPI _com_issue_error(HRESULT);
void WINAPI _com_issue_errorex(HRESULT,IUnknown*,REFIID);
HRESULT WINAPI _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 WINAPI _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:
  _com_error(HRESULT hr,IErrorInfo *perrinfo = NULL,bool fAddRef = false) throw();
  _com_error(const _com_error &that) throw();
  virtual ~_com_error() throw();
  _com_error &operator=(const _com_error &that) throw();
  HRESULT Error() const throw();
  WORD WCode() const throw();
  IErrorInfo *ErrorInfo() const throw();
  _bstr_t Description() const;
  DWORD HelpContext() const throw();
  _bstr_t HelpFile() const;
  _bstr_t Source() const;
  GUID GUID() const throw();
  const TCHAR *ErrorMessage() const throw();
  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) m_perrinfo->GetDescription(&bstr);
  return _bstr_t(bstr,false);
}

inline DWORD _com_error::HelpContext() const throw() {
  DWORD dwHelpContext = 0;
  if(m_perrinfo!=NULL) m_perrinfo->GetHelpContext(&dwHelpContext);
  return dwHelpContext;
}

inline _bstr_t _com_error::HelpFile() const {
  BSTR bstr = NULL;
  if(m_perrinfo!=NULL)  m_perrinfo->GetHelpFile(&bstr);
  return _bstr_t(bstr,false);
}

inline _bstr_t _com_error::Source() const {
  BSTR bstr = NULL;
  if(m_perrinfo!=NULL) m_perrinfo->GetSource(&bstr);
  return _bstr_t(bstr,false);
}

inline _GUID _com_error::GUID() const throw() {
  _GUID guid;
  memset (&guid, 0, sizeof (_GUID));
  if(m_perrinfo!=NULL) m_perrinfo->GetGUID(&guid);
  return guid;
}

inline const TCHAR *_com_error::ErrorMessage() const throw() {
  if(!m_pszMsg) {
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,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"),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; }

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_) && USE___UUIDOF != 0
#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
#endif

#endif /* __cplusplus */

#endif
