/* This file is part of the source code for the DispHelper COM helper library. * DispHelper allows you to call COM objects with an extremely simple printf style syntax. * DispHelper can be used from C++ or even plain C. It works with most Windows compilers * including Dev-CPP, Visual C++ and LCC-WIN32. Including DispHelper in your project * couldn't be simpler as it is available in a compacted single file version. * * Included with DispHelper are over 20 samples that demonstrate using COM objects * including ADO, CDO, Outlook, Eudora, Excel, Word, Internet Explorer, MSHTML, * PocketSoap, Word Perfect, MS Agent, SAPI, MSXML, WIA, dexplorer and WMI. * * DispHelper is free open source software provided under the BSD license. * * Find out more and download DispHelper at: * http://sourceforge.net/projects/disphelper/ * http://disphelper.sourceforge.net/ */ #ifndef DISPHELPER_H_INCLUDED #define DISPHELPER_H_INCLUDED #include #include #ifdef __cplusplus extern "C" { #endif HRESULT dhCreateObject(LPCOLESTR szProgId, LPCWSTR szMachine, IDispatch ** ppDisp); HRESULT dhGetObject(LPCOLESTR szFile, LPCOLESTR szProgId, IDispatch ** ppDisp); HRESULT dhCreateObjectEx(LPCOLESTR szProgId, REFIID riid, DWORD dwClsContext, COSERVERINFO * pServerInfo, void ** ppv); HRESULT dhGetObjectEx(LPCOLESTR szFile, LPCOLESTR szProgId, REFIID riid, DWORD dwClsContext, LPVOID lpvReserved, void ** ppv); HRESULT dhCallMethod(IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhPutValue(IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhPutRef(IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhGetValue(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhInvoke(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhInvokeArray(int invokeType, VARIANT * pvResult, UINT cArgs, IDispatch * pDisp, LPCOLESTR szMember, VARIANT * pArgs); HRESULT dhCallMethodV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhPutValueV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhPutRefV(IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhGetValueV(LPCWSTR szIdentifier, void * pResult, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhAutoWrap(int invokeType, VARIANT * pvResult, IDispatch * pDisp, LPCOLESTR szMember, UINT cArgs, ...); HRESULT dhParseProperties(IDispatch * pDisp, LPCWSTR szProperties, UINT * lpcPropsSet); HRESULT dhEnumBegin(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, ...); HRESULT dhEnumBeginV(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMember, va_list * marker); HRESULT dhEnumNextObject(IEnumVARIANT * pEnum, IDispatch ** ppDisp); HRESULT dhEnumNextVariant(IEnumVARIANT * pEnum, VARIANT * pvResult); HRESULT dhInitializeImp(BOOL bInitializeCOM, BOOL bUnicode); void dhUninitialize(BOOL bUninitializeCOM); #define dhInitializeA(bInitializeCOM) dhInitializeImp(bInitializeCOM, FALSE) #define dhInitializeW(bInitializeCOM) dhInitializeImp(bInitializeCOM, TRUE) #ifdef UNICODE #define dhInitialize dhInitializeW #else #define dhInitialize dhInitializeA #endif #define AutoWrap dhAutoWrap #define DISPATCH_OBJ(objName) IDispatch * objName = NULL #define dhFreeString(string) SysFreeString((BSTR) string) #ifndef SAFE_RELEASE #ifdef __cplusplus #define SAFE_RELEASE(pObj) { if (pObj) { (pObj)->Release(); (pObj) = NULL; } } #else #define SAFE_RELEASE(pObj) { if (pObj) { (pObj)->lpVtbl->Release(pObj); (pObj) = NULL; } } #endif #endif #define SAFE_FREE_STRING(string) { dhFreeString(string); (string) = NULL; } /* ===================================================================== */ #ifndef DISPHELPER_NO_WITH #define WITH0(objName, pDisp, szMember) { \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember))) { #define WITH1(objName, pDisp, szMember, arg1) { \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1))) { #define WITH2(objName, pDisp, szMember, arg1, arg2) { \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2))) { #define WITH3(objName, pDisp, szMember, arg1, arg2, arg3) { \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3))) { #define WITH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3, arg4))) { #define WITH WITH0 #define ON_WITH_ERROR(objName) } else { #define END_WITH(objName) } SAFE_RELEASE(objName); } #endif /* ----- DISPHELPER_NO_WITH ----- */ /* ===================================================================== */ #ifndef DISPHELPER_NO_FOR_EACH #define FOR_EACH0(objName, pDisp, szMember) { \ IEnumVARIANT * xx_pEnum_xx = NULL; \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember))) { \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #define FOR_EACH1(objName, pDisp, szMember, arg1) { \ IEnumVARIANT * xx_pEnum_xx = NULL; \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1))) { \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #define FOR_EACH2(objName, pDisp, szMember, arg1, arg2) { \ IEnumVARIANT * xx_pEnum_xx = NULL; \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2))) { \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #define FOR_EACH3(objName, pDisp, szMember, arg1, arg2, arg3) { \ IEnumVARIANT * xx_pEnum_xx = NULL; \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3))) { \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #define FOR_EACH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \ IEnumVARIANT * xx_pEnum_xx = NULL; \ DISPATCH_OBJ(objName); \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3, arg4))) { \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #define FOR_EACH FOR_EACH0 #define ON_FOR_EACH_ERROR(objName) SAFE_RELEASE(objName); }} else {{ #define NEXT(objName) SAFE_RELEASE(objName); }} SAFE_RELEASE(objName); SAFE_RELEASE(xx_pEnum_xx); } #endif /* ----- DISPHELPER_NO_FOR_EACH ----- */ /* ===================================================================== */ #ifndef DISPHELPER_NO_EXCEPTIONS /* Structure to store a DispHelper exception */ typedef struct tagDH_EXCEPTION { LPCWSTR szInitialFunction; LPCWSTR szErrorFunction; HRESULT hr; WCHAR szMember[64]; WCHAR szCompleteMember[256]; UINT swCode; LPWSTR szDescription; LPWSTR szSource; LPWSTR szHelpFile; DWORD dwHelpContext; UINT iArgError; BOOL bDispatchError; #ifdef DISPHELPER_INTERNAL_BUILD BOOL bOld; #endif } DH_EXCEPTION, * PDH_EXCEPTION; typedef void (*DH_EXCEPTION_CALLBACK) (PDH_EXCEPTION); /* Structure to store exception options. */ typedef struct tagDH_EXCEPTION_OPTIONS { HWND hwnd; LPCWSTR szAppName; BOOL bShowExceptions; BOOL bDisableRecordExceptions; DH_EXCEPTION_CALLBACK pfnExceptionCallback; } DH_EXCEPTION_OPTIONS, * PDH_EXCEPTION_OPTIONS; /* Functions to manipulate global exception options */ HRESULT dhToggleExceptions(BOOL bShow); HRESULT dhSetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions); HRESULT dhGetExceptionOptions(PDH_EXCEPTION_OPTIONS pExceptionOptions); /* Functions to show an exception, format an exception into a string * and get a copy of the last exception */ HRESULT dhShowException(PDH_EXCEPTION pException); HRESULT dhGetLastException(PDH_EXCEPTION * pException); HRESULT dhFormatExceptionW(PDH_EXCEPTION pException, LPWSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont); HRESULT dhFormatExceptionA(PDH_EXCEPTION pException, LPSTR szBuffer, UINT cchBufferSize, BOOL bFixedFont); #ifdef UNICODE #define dhFormatException dhFormatExceptionW #else #define dhFormatException dhFormatExceptionA #endif #ifdef DISPHELPER_INTERNAL_BUILD void dhEnter(void); HRESULT dhExitEx(HRESULT hr, BOOL bDispatchError, LPCWSTR szMember, LPCWSTR szCompleteMember, EXCEPINFO * pExcepInfo, UINT iArgError, LPCWSTR szFunctionName); void dhCleanupThreadException(void); #define DH_ENTER(szFunctionName) static LPCWSTR xx_szFunctionName_xx = szFunctionName; \ dhEnter() #define DH_EXITEX(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError) \ dhExitEx(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError, xx_szFunctionName_xx) #define DH_EXIT(hr, szCompleteMember) DH_EXITEX(hr, FALSE, NULL, szCompleteMember, NULL, 0) #endif /* ----- DISPHELPER_INTERNAL_BUILD ----- */ #else /* ----- DISPHELPER_NO_EXCEPTIONS ----- */ /* These macros define out calls to selected exception functions */ #define dhToggleExceptions(bShow) (E_NOTIMPL) #define dhSetExceptionOptions(pExcepOptions) (E_NOTIMPL) #ifdef DISPHELPER_INTERNAL_BUILD #define DH_ENTER(szFunctionName) #define DH_EXITEX(hr, bDispatchError, szMember, szCompleteMember, pExcepInfo, iArgError) \ (((hr == DISP_E_EXCEPTION && pExcepInfo) ? \ (SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrSource), \ SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrDescription), \ SysFreeString(((EXCEPINFO *)(pExcepInfo))->bstrHelpFile), 0) : (0)), hr) #define DH_EXIT(hr, szCompleteMember)(hr) #endif #endif /* ----- DISPHELPER_NO_EXCEPTIONS ----- */ /* ===================================================================== */ #ifdef DISPHELPER_INTERNAL_BUILD #include #include #include /* Macro to include or lose debug code. */ #ifdef DEBUG #define DBG_CODE(code) code #else #define DBG_CODE(code) #endif /* Are we in unicode mode? */ extern BOOL dh_g_bIsUnicodeMode; /* Number of objects in an array */ #undef ARRAYSIZE #define ARRAYSIZE(arr) (sizeof(arr) / sizeof((arr)[0])) /* Maximum number of arguments for a member */ #define DH_MAX_ARGS 25 /* Maximum length of a member string */ #define DH_MAX_MEMBER 512 /* This macro is missing from Dev-Cpp/Mingw */ #ifndef V_UI4 #define V_UI4(X) V_UNION(X, ulVal) #endif /* Macro to notify programmer of invalid identifier in debug mode. */ #define DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier) \ DBG_CODE( { \ char buf[256]; \ sprintf(buf,"DEBUG: The format string or return identifier contained the invalid identifier '%c'.\n" \ "The valid identifiers are \"d/u/e/b/v/B/S/s/T/o/O/t/W/D/f/m\".\n" \ "Each %% character should be followed by a valid identifier.\n" \ "Identifiers are case sensitive.", (chIdentifier)); \ MessageBoxA(NULL, buf, "DEBUG: Invalid Format Identifier", MB_ICONSTOP); \ } ) #ifdef _MSC_VER #pragma warning(disable : 4706) /* Assignment in conditional expression */ #endif #ifndef DISPHELPER_NO_PRAGMA_LIB #ifdef __LCC__ #pragma lib #pragma lib #pragma lib #endif #endif #endif /* ----- DISPHELPER_INTERNAL_BUILD ----- */ #ifndef DISPHELPER_NO_PRAGMA_LIB #if defined(_MSC_VER) || defined(__BORLANDC__) #pragma comment(lib, "ole32.lib") #pragma comment(lib, "oleaut32.lib") #pragma comment(lib, "uuid.lib") #endif #endif #ifdef __cplusplus } #endif /* ===================================================================== */ #if defined(__cplusplus) && !defined(DISPHELPER_NO_CPP_EXTENSIONS) #include #include #ifdef _MSC_VER #pragma warning( disable : 4290 ) /* throw() specification ignored */ #endif #ifndef DISPHELPER_USE_MS_SMART_PTR template class CDhComPtr { public: CDhComPtr() throw() : m_pInterface (NULL) {} CDhComPtr(T* pInterface) throw() : m_pInterface (pInterface) { if (m_pInterface) m_pInterface->AddRef(); } CDhComPtr(const CDhComPtr& original) throw() : m_pInterface (original.m_pInterface) { if (m_pInterface) m_pInterface->AddRef(); } ~CDhComPtr() throw() { Dispose(); } void Dispose() throw() { if (m_pInterface) { m_pInterface->Release(); m_pInterface = NULL; } } T* Detach() throw() { T* temp = m_pInterface; m_pInterface = NULL; return temp; } inline operator T*() const throw() { return m_pInterface; } T** operator&() throw() { Dispose(); return &m_pInterface; } T* operator->() const throw(HRESULT) { if (!m_pInterface) throw E_POINTER; return m_pInterface; } CDhComPtr& operator=(T* pInterface) throw() { if (m_pInterface != pInterface) { T* pOldInterface = m_pInterface; m_pInterface = pInterface; if (m_pInterface) m_pInterface->AddRef(); if (pOldInterface) pOldInterface->Release(); } return *this; } CDhComPtr& operator=(const int null) throw(HRESULT) { if (null != 0) throw(E_POINTER); return operator=((T*) NULL); } CDhComPtr& operator=(const CDhComPtr& rhs) throw() { return operator=(rhs.m_pInterface); } private: T* m_pInterface; }; typedef CDhComPtr CDispPtr; typedef CDhComPtr CEnumPtr; typedef CDhComPtr CUnknownPtr; #else /* DISPHELPER_USE_MS_SMART_PTR */ #include typedef IDispatchPtr CDispPtr; typedef IEnumVARIANTPtr CEnumPtr; typedef IUnknownPtr CUnknownPtr; #endif /* DISPHELPER_USE_MS_SMART_PTR */ /* ===================================================================== */ template class CDhStringTemplate { public: CDhStringTemplate() throw() : m_strptr (NULL) {} CDhStringTemplate(const CDhStringTemplate& original) throw() { Copy(original.m_strptr); } CDhStringTemplate(const int null) throw(HRESULT) : m_strptr (NULL) { if (null != 0) throw(E_POINTER); } ~CDhStringTemplate() throw() { Dispose(); } void Dispose() throw() { dhFreeString(m_strptr); m_strptr = NULL; } T* Detach() throw() { T* temp = m_strptr; m_strptr = NULL; return temp; } T** operator&() throw() { Dispose(); return &m_strptr; } inline operator T*() const throw() { return m_strptr; } inline T& operator[](int nIndex) const throw() { return m_strptr[nIndex]; } CDhStringTemplate& operator=(const CDhStringTemplate& rhs) { if (m_strptr != rhs.m_strptr) { T* temp = m_strptr; Copy(rhs.m_strptr); dhFreeString(temp); } return *this; } CDhStringTemplate& operator=(const int null) throw(HRESULT) { if (null != 0) throw(E_POINTER); Dispose(); return *this; } private: void Copy(const T* rhs) { if (rhs == NULL) { m_strptr = NULL; } else if (sizeof(T) == sizeof(CHAR)) { m_strptr = (T*) SysAllocStringByteLen((LPCSTR) rhs, SysStringByteLen((BSTR) rhs)); } else { m_strptr = (T*) SysAllocStringLen((OLECHAR *) rhs, SysStringLen((BSTR) rhs)); } } T* m_strptr; }; typedef CDhStringTemplate CDhStringA; /* Ansi string - LPSTR */ typedef CDhStringTemplate CDhStringW; /* Unicode string - LPWSTR */ typedef CDhStringTemplate CDhStringB; /* Unicode bstring - BSTR */ typedef CDhStringTemplate CDhStringT; /* T string - LPTSTR */ typedef CDhStringTemplate CDhString; /* T string - LPTSTR */ inline std::ostream& operator<<(std::ostream& os, const CDhStringA& s) { return os << (s ? s : (char*) "(null)"); } //inline std::wostream& operator<<(std::wostream& os, const CDhStringW& s) //{ // return os << (s ? s : (wchar_t*) L"(null)"); //} /* ===================================================================== */ class CDhInitialize { public: CDhInitialize(const BOOL bInitCom = TRUE) throw() : m_bInitCom (bInitCom) { dhInitialize(m_bInitCom); } ~CDhInitialize() throw() { dhUninitialize(m_bInitCom); } private: BOOL m_bInitCom; }; /* ===================================================================== */ #ifndef DISPHELPER_NO_EXCEPTIONS class dhThrowFunctions { public: static void throw_string() throw(std::string) { CHAR szMessage[512]; dhFormatExceptionA(NULL, szMessage, sizeof(szMessage)/sizeof(szMessage[0]), TRUE); throw std::string(szMessage); } static void throw_wstring() throw(std::wstring) { WCHAR szMessage[512]; dhFormatExceptionW(NULL, szMessage, sizeof(szMessage)/sizeof(szMessage[0]), TRUE); throw std::wstring(szMessage); } static void throw_dhexception() throw(PDH_EXCEPTION) { PDH_EXCEPTION pException = NULL; dhGetLastException(&pException); throw pException; } }; #endif /* DISPHELPER_NO_EXCEPTIONS */ /* ===================================================================== */ #ifndef DISPHELPER_NO_EXCEPTIONS inline bool dhIfFailThrowString(HRESULT hr) throw(std::string) { if (FAILED(hr)) dhThrowFunctions::throw_string(); return true; } inline bool dhIfFailThrowWString(HRESULT hr) throw(std::wstring) { if (FAILED(hr)) dhThrowFunctions::throw_wstring(); return true; } inline bool dhIfFailThrowDhException(HRESULT hr) throw(PDH_EXCEPTION) { if (FAILED(hr)) dhThrowFunctions::throw_dhexception(); return true; } #define dhCheck dhIfFailThrowString #endif /* DISPHELPER_NO_EXCEPTIONS */ /* ===================================================================== */ #ifndef DISPHELPER_NO_WITH #undef WITH0 #define WITH0(objName, pDisp, szMember) { \ CDispPtr objName; \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember))) { #undef WITH1 #define WITH1(objName, pDisp, szMember, arg1) { \ CDispPtr objName; \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1))) { #undef WITH2 #define WITH2(objName, pDisp, szMember, arg1, arg2) { \ CDispPtr objName; \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2))) { #undef WITH3 #define WITH3(objName, pDisp, szMember, arg1, arg2, arg3) { \ CDispPtr objName; \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3))) { #undef WITH4 #define WITH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \ CDispPtr objName; \ if (SUCCEEDED(dhGetValue(L"%o", &objName, pDisp, szMember, arg1, arg2, arg3, arg4))) { #undef ON_WITH_ERROR #define ON_WITH_ERROR(objName) } else { #undef END_WITH #define END_WITH(objName) }} #define END_WITH_THROW(objName) } else { dhThrowFunctions::throw_string(); }} #endif /* DISPHELPER_NO_WITH */ /* ===================================================================== */ #ifndef DISPHELPER_NO_FOR_EACH #undef FOR_EACH0 #define FOR_EACH0(objName, pDisp, szMember) { \ CEnumPtr xx_pEnum_xx; \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember))) { \ CDispPtr objName; \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #undef FOR_EACH1 #define FOR_EACH1(objName, pDisp, szMember, arg1) { \ CEnumPtr xx_pEnum_xx; \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1))) { \ CDispPtr objName; \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #undef FOR_EACH2 #define FOR_EACH2(objName, pDisp, szMember, arg1, arg2) { \ CEnumPtr xx_pEnum_xx; \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2))) { \ CDispPtr objName; \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #undef FOR_EACH3 #define FOR_EACH3(objName, pDisp, szMember, arg1, arg2, arg3) { \ CEnumPtr xx_pEnum_xx; \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3))) { \ CDispPtr objName; \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #undef FOR_EACH4 #define FOR_EACH4(objName, pDisp, szMember, arg1, arg2, arg3, arg4) { \ CEnumPtr xx_pEnum_xx; \ if (SUCCEEDED(dhEnumBegin(&xx_pEnum_xx, pDisp, szMember, arg1, arg2, arg3, arg4))) { \ CDispPtr objName; \ while (dhEnumNextObject(xx_pEnum_xx, &objName) == NOERROR) { #undef ON_FOR_EACH_ERROR #define ON_FOR_EACH_ERROR(objName) }} else {{ #undef NEXT #define NEXT(objName) }}} #define NEXT_THROW(objName) }} else { dhThrowFunctions::throw_string(); }} #endif /* DISPHELPER_NO_FOR_EACH */ #ifdef _MSC_VER #pragma warning( default : 4290 ) #endif #endif /* defined(__cplusplus) && !defined(DISPHELPER_NO_CPP_EXTENSIONS) */ #endif /* ----- DISPHELPER_H_INCLUDED ----- */