// This is a part of the Active Template Library. // Copyright (C) Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Active Template Library Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Active Template Library product. #ifndef __ATLCOMCLI_H__ #define __ATLCOMCLI_H__ #pragma once #include #include #include #pragma warning (push) #pragma warning (disable: 4127) // conditional expression constant #pragma warning (disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions #pragma pack(push,_ATL_PACKING) namespace ATL { ///////////////////////////////////////////////////////////////////////////// // Error to HRESULT helpers ATL_NOINLINE inline HRESULT AtlHresultFromLastError() throw() { DWORD dwErr = ::GetLastError(); return HRESULT_FROM_WIN32(dwErr); } ATL_NOINLINE inline HRESULT AtlHresultFromWin32(__in DWORD nError) throw() { return( HRESULT_FROM_WIN32( nError ) ); } ///////////////////////////////////////////////////////////////////////////// // Smart Pointer helpers ATLAPI_(IUnknown*) AtlComPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp); ATLAPI_(IUnknown*) AtlComQIPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp, REFIID riid); #ifndef _ATL_DLL ATLINLINE ATLAPI_(IUnknown*) AtlComPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp) { if (pp == NULL) return NULL; if (lp != NULL) lp->AddRef(); if (*pp) (*pp)->Release(); *pp = lp; return lp; } ATLINLINE ATLAPI_(IUnknown*) AtlComQIPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp, REFIID riid) { if (pp == NULL) return NULL; IUnknown* pTemp = *pp; *pp = NULL; if (lp != NULL) lp->QueryInterface(riid, (void**)pp); if (pTemp) pTemp->Release(); return *pp; } #endif // _ATL_DLL ///////////////////////////////////////////////////////////////////////////// // COM Smart pointers template class _NoAddRefReleaseOnCComPtr : public T { private: STDMETHOD_(ULONG, AddRef)()=0; STDMETHOD_(ULONG, Release)()=0; }; inline __checkReturn HRESULT AtlSetChildSite(__inout IUnknown* punkChild, __in_opt IUnknown* punkParent) { if (punkChild == NULL) return E_POINTER; HRESULT hr; IObjectWithSite* pChildSite = NULL; hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&pChildSite); if (SUCCEEDED(hr) && pChildSite != NULL) { hr = pChildSite->SetSite(punkParent); pChildSite->Release(); } return hr; } //CComPtrBase provides the basis for all other smart pointers //The other smartpointers add their own constructors and operators template class CComPtrBase { protected: CComPtrBase() throw() { p = NULL; } CComPtrBase(__in int nNull) throw() { ATLASSERT(nNull == 0); (void)nNull; p = NULL; } CComPtrBase(__in_opt T* lp) throw() { p = lp; if (p != NULL) p->AddRef(); } public: typedef T _PtrClass; ~CComPtrBase() throw() { if (p) p->Release(); } operator T*() const throw() { return p; } T& operator*() const { ATLENSURE(p!=NULL); return *p; } //The assert on operator& usually indicates a bug. If this is really //what is needed, however, take the address of the p member explicitly. T** operator&() throw() { ATLASSERT(p==NULL); return &p; } _NoAddRefReleaseOnCComPtr* operator->() const throw() { ATLASSERT(p!=NULL); return (_NoAddRefReleaseOnCComPtr*)p; } bool operator!() const throw() { return (p == NULL); } bool operator<(__in_opt T* pT) const throw() { return p < pT; } bool operator!=(__in_opt T* pT) const { return !operator==(pT); } bool operator==(__in_opt T* pT) const throw() { return p == pT; } // Release the interface and set to NULL void Release() throw() { T* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } // Compare two objects for equivalence bool IsEqualObject(__in_opt IUnknown* pOther) throw() { if (p == NULL && pOther == NULL) return true; // They are both NULL objects if (p == NULL || pOther == NULL) return false; // One is NULL the other is not CComPtr punk1; CComPtr punk2; p->QueryInterface(__uuidof(IUnknown), (void**)&punk1); pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2); return punk1 == punk2; } // Attach to an existing interface (does not AddRef) void Attach(__in T* p2) throw() { if (p) p->Release(); p = p2; } // Detach the interface (does not Release) T* Detach() throw() { T* pt = p; p = NULL; return pt; } __checkReturn HRESULT CopyTo(__deref_out_opt T** ppT) throw() { ATLASSERT(ppT != NULL); if (ppT == NULL) return E_POINTER; *ppT = p; if (p) p->AddRef(); return S_OK; } __checkReturn HRESULT SetSite(__in_opt IUnknown* punkParent) throw() { return AtlSetChildSite(p, punkParent); } __checkReturn HRESULT Advise(__in IUnknown* pUnk, __in const IID& iid, __out LPDWORD pdw) throw() { return AtlAdvise(p, pUnk, iid, pdw); } __checkReturn HRESULT CoCreateInstance(__in REFCLSID rclsid, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() { ATLASSERT(p == NULL); return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); } __checkReturn HRESULT CoCreateInstance(__in LPCOLESTR szProgID, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() { CLSID clsid; HRESULT hr = CLSIDFromProgID(szProgID, &clsid); ATLASSERT(p == NULL); if (SUCCEEDED(hr)) hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); return hr; } template __checkReturn HRESULT QueryInterface(__deref_out_opt Q** pp) const throw() { ATLASSERT(pp != NULL); return p->QueryInterface(__uuidof(Q), (void**)pp); } T* p; }; template class CComPtr : public CComPtrBase { public: CComPtr() throw() { } CComPtr(int nNull) throw() : CComPtrBase(nNull) { } CComPtr(T* lp) throw() : CComPtrBase(lp) { } CComPtr(__in const CComPtr& lp) throw() : CComPtrBase(lp.p) { } T* operator=(__in_opt T* lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); } return *this; } template T* operator=(__in const CComPtr& lp) throw() { if( !IsEqualObject(lp) ) { return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T))); } return *this; } T* operator=(__in const CComPtr& lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); } return *this; } }; //specialization for IDispatch template <> class CComPtr : public CComPtrBase { public: CComPtr() throw() { } CComPtr(IDispatch* lp) throw() : CComPtrBase(lp) { } CComPtr(const CComPtr& lp) throw() : CComPtrBase(lp.p) { } IDispatch* operator=(IDispatch* lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); } return *this; } IDispatch* operator=(const CComPtr& lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); } return *this; } // IDispatch specific stuff __checkReturn HRESULT GetPropertyByName(__in LPCOLESTR lpsz, __out VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = GetProperty(dwDispID, pVar); return hr; } __checkReturn HRESULT GetProperty(__in DISPID dwDispID, __out VARIANT* pVar) throw() { return GetProperty(p, dwDispID, pVar); } __checkReturn HRESULT PutPropertyByName(__in LPCOLESTR lpsz, __in VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar); DISPID dwDispID; HRESULT hr = GetIDOfName(lpsz, &dwDispID); if (SUCCEEDED(hr)) hr = PutProperty(dwDispID, pVar); return hr; } __checkReturn HRESULT PutProperty(__in DISPID dwDispID, __in VARIANT* pVar) throw() { return PutProperty(p, dwDispID, pVar); } __checkReturn HRESULT GetIDOfName(__in LPCOLESTR lpsz, __out DISPID* pdispid) throw() { return p->GetIDsOfNames(IID_NULL, const_cast(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid); } // Invoke a method by DISPID with no parameters __checkReturn HRESULT Invoke0(__in DISPID dispid, __out_opt VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { NULL, NULL, 0, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with no parameters __checkReturn HRESULT Invoke0(__in LPCOLESTR lpszName, __out_opt VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke0(dispid, pvarRet); return hr; } // Invoke a method by DISPID with a single parameter __checkReturn HRESULT Invoke1(__in DISPID dispid, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with a single parameter __checkReturn HRESULT Invoke1(__in LPCOLESTR lpszName, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke1(dispid, pvarParam1, pvarRet); return hr; } // Invoke a method by DISPID with two parameters __checkReturn HRESULT Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw(); // Invoke a method by name with two parameters __checkReturn HRESULT Invoke2(__in LPCOLESTR lpszName, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); return hr; } // Invoke a method by DISPID with N parameters __checkReturn HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() { DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } // Invoke a method by name with Nparameters __checkReturn HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() { HRESULT hr; DISPID dispid; hr = GetIDOfName(lpszName, &dispid); if (SUCCEEDED(hr)) hr = InvokeN(dispid, pvarParams, nParams, pvarRet); return hr; } static __checkReturn HRESULT PutProperty(__inout IDispatch* p, __in DISPID dwDispID, __in VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar != NULL); if (pVar == NULL) return E_POINTER; if(p == NULL) return E_INVALIDARG; ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty\n")); DISPPARAMS dispparams = {NULL, NULL, 1, 1}; dispparams.rgvarg = pVar; DISPID dispidPut = DISPID_PROPERTYPUT; dispparams.rgdispidNamedArgs = &dispidPut; if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) { HRESULT hr = p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &dispparams, NULL, NULL, NULL); if (SUCCEEDED(hr)) return hr; } return p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); } static __checkReturn HRESULT GetProperty(__in IDispatch* p, __in DISPID dwDispID, __out VARIANT* pVar) throw() { ATLASSERT(p); ATLASSERT(pVar != NULL); if (pVar == NULL) return E_POINTER; if(p == NULL) return E_INVALIDARG; ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty\n")); DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; return p->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, pVar, NULL, NULL); } }; template class CComQIPtr : public CComPtr { public: CComQIPtr() throw() { } CComQIPtr(__in T* lp) throw() : CComPtr(lp) { } CComQIPtr(__in const CComQIPtr& lp) throw() : CComPtr(lp.p) { } CComQIPtr(__in_opt IUnknown* lp) throw() { if (lp != NULL) lp->QueryInterface(*piid, (void **)&p); } T* operator=(__in T* lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); } return *this; } T* operator=(__in const CComQIPtr& lp) throw() { if(*this!=lp) { return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); } return *this; } T* operator=(__in IUnknown* lp) throw() { if(*this!=lp) { return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid)); } return *this; } }; //Specialization to make it work template<> class CComQIPtr : public CComPtr { public: CComQIPtr() throw() { } CComQIPtr(__in IUnknown* lp) throw() { //Actually do a QI to get identity if (lp != NULL) lp->QueryInterface(__uuidof(IUnknown), (void **)&p); } CComQIPtr(__in const CComQIPtr& lp) throw() : CComPtr(lp.p) { } IUnknown* operator=(__in IUnknown* lp) throw() { if(*this!=lp) { //Actually do a QI to get identity return AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown)); } return *this; } IUnknown* operator=(__in const CComQIPtr& lp) throw() { if(*this!=lp) { return AtlComPtrAssign((IUnknown**)&p, lp.p); } return *this; } }; typedef CComQIPtr CComDispatchDriver; #define com_cast ATL::CComQIPtr #ifndef _ATL_STREAM_MAX_SIZE #define _ATL_STREAM_MAX_SIZE 0x100000 #endif ///////////////////////////////////////////////////////////////////////////// // CComBSTR class CComBSTR { public: BSTR m_str; CComBSTR() throw() { m_str = NULL; } CComBSTR(__in int nSize) { if (nSize == 0) m_str = NULL; else { m_str = ::SysAllocStringLen(NULL, nSize); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } } CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCOLESTR sz) { if (nSize == 0) { m_str = NULL; } else { m_str = ::SysAllocStringLen(sz, nSize); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } } CComBSTR(__in_opt LPCOLESTR pSrc) { if (pSrc == NULL) { m_str = NULL; } else { m_str = ::SysAllocString(pSrc); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } } CComBSTR(__in const CComBSTR& src) { m_str = src.Copy(); if (!!src && !*this) { AtlThrow(E_OUTOFMEMORY); } } CComBSTR(__in REFGUID guid) { OLECHAR szGUID[64]; ::StringFromGUID2(guid, szGUID, 64); m_str = ::SysAllocString(szGUID); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } CComBSTR& operator=(__in const CComBSTR& src) { if (m_str != src.m_str) { ::SysFreeString(m_str); m_str = src.Copy(); if (!!src && !*this) { AtlThrow(E_OUTOFMEMORY); } } return *this; } CComBSTR& operator=(__in_opt LPCOLESTR pSrc) { if (pSrc != m_str) { ::SysFreeString(m_str); if (pSrc != NULL) { m_str = ::SysAllocString(pSrc); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } else { m_str = NULL; } } return *this; } ~CComBSTR() throw(); unsigned int Length() const throw() { return ::SysStringLen(m_str); } unsigned int ByteLength() const throw() { return ::SysStringByteLen(m_str); } operator BSTR() const throw() { return m_str; } #ifndef ATL_CCOMBSTR_ADDRESS_OF_ASSERT // Temp disable CComBSTR::operator& Assert #define ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT #endif BSTR* operator&() throw() { #ifndef ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "We are deliberately checking if this has already been allocated") ATLASSERT(!*this); #pragma prefast(pop) #pragma warning(pop) #endif return &m_str; } BSTR Copy() const throw() { if (!*this) { return NULL; } return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str)); } __checkReturn HRESULT CopyTo(__inout_opt BSTR* pbstr) throw() { ATLASSERT(pbstr != NULL); if (pbstr == NULL) { return E_POINTER; } *pbstr = Copy(); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "We are checking allocation semantics here") if ((*pbstr == NULL) && (m_str != NULL)) { return E_OUTOFMEMORY; } #pragma prefast(pop) #pragma warning(pop) return S_OK; } // copy BSTR to VARIANT __checkReturn HRESULT CopyTo(__out_opt VARIANT *pvarDest) throw() { ATLASSERT(pvarDest != NULL); HRESULT hRes = E_POINTER; if (pvarDest != NULL) { pvarDest->vt = VT_BSTR; pvarDest->bstrVal = Copy(); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "We are checking allocation semantics here") if (pvarDest->bstrVal == NULL && m_str != NULL) { hRes = E_OUTOFMEMORY; } #pragma prefast(pop) #pragma warning(pop) else { hRes = S_OK; } } return hRes; } void Attach(__in BSTR src) throw() { if (m_str != src) { ::SysFreeString(m_str); m_str = src; } } BSTR Detach() throw() { BSTR s = m_str; m_str = NULL; return s; } void Empty() throw() { ::SysFreeString(m_str); m_str = NULL; } bool operator!() const throw() { #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") return (m_str == NULL); #pragma prefast(pop) #pragma warning(pop) } __checkReturn HRESULT Append(__in const CComBSTR& bstrSrc) throw() { return AppendBSTR(bstrSrc.m_str); } __checkReturn HRESULT Append(__in_opt LPCOLESTR lpsz) throw() { return Append(lpsz, UINT(ocslen(lpsz))); } // a BSTR is just a LPCOLESTR so we need a special version to signify // that we are appending a BSTR __checkReturn HRESULT AppendBSTR(__in_opt BSTR p) throw() { if (::SysStringLen(p) == 0) { return S_OK; } BSTR bstrNew = NULL; HRESULT hr; hr = VarBstrCat(m_str, p, &bstrNew); if (SUCCEEDED(hr)) { ::SysFreeString(m_str); m_str = bstrNew; } return hr; } __checkReturn HRESULT Append(__in_ecount_opt(nLen) LPCOLESTR lpsz, __in int nLen) throw() { #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") if (lpsz == NULL || (m_str != NULL && nLen == 0)) #pragma prefast(pop) #pragma warning(pop) return S_OK; int n1 = Length(); if (n1+nLen < n1) return E_OUTOFMEMORY; BSTR b; b = ::SysAllocStringLen(NULL, n1+nLen); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") if (b == NULL) #pragma prefast(pop) #pragma warning(pop) return E_OUTOFMEMORY; if(::SysStringLen(m_str) > 0) { Checked::memcpy_s(b, (n1+nLen)*sizeof(OLECHAR), m_str, n1*sizeof(OLECHAR)); } Checked::memcpy_s(b+n1, nLen*sizeof(OLECHAR), lpsz, nLen*sizeof(OLECHAR)); b[n1+nLen] = NULL; SysFreeString(m_str); m_str = b; return S_OK; } __checkReturn HRESULT Append(__in char ch) throw() { OLECHAR chO = ch; return( Append( &chO, 1 ) ); } __checkReturn HRESULT Append(__in wchar_t ch) throw() { return( Append( &ch, 1 ) ); } __checkReturn HRESULT AppendBytes(__in_ecount_opt(nLen) const char* lpsz, __in int nLen) throw() { if (lpsz == NULL || nLen == 0) return S_OK; int n1 = ByteLength(); if (n1+nLen < n1) return E_OUTOFMEMORY; BSTR b; b = ::SysAllocStringByteLen(NULL, n1+nLen); if (b == NULL) { return E_OUTOFMEMORY; } Checked::memcpy_s(b, n1+nLen, m_str, n1); Checked::memcpy_s(((char*)b)+n1, nLen, lpsz, nLen); *((OLECHAR*)(((char*)b)+n1+nLen)) = NULL; SysFreeString(m_str); m_str = b; return S_OK; } __checkReturn HRESULT AssignBSTR(const BSTR bstrSrc) throw() { HRESULT hr = S_OK; if (m_str != bstrSrc) { ::SysFreeString(m_str); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") if (bstrSrc != NULL) #pragma prefast(pop) #pragma warning(pop) { m_str = ::SysAllocStringByteLen((char*)bstrSrc, ::SysStringByteLen(bstrSrc)); if (!*this) { hr = E_OUTOFMEMORY; } } else { m_str = NULL; } } return hr; } __checkReturn HRESULT ToLower() throw() { if (::SysStringLen(m_str) > 0) { #ifdef _UNICODE // Convert in place CharLowerBuff(m_str, Length()); #else // Cannot use conversion macros due to possible embedded NULLs UINT _acp = _AtlGetConversionACP(); int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); CTempBuffer pszA; ATLTRY(pszA.Allocate(_convert)); if (pszA == NULL) return E_OUTOFMEMORY; int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); if (nRet == 0) { ATLASSERT(0); return AtlHresultFromLastError(); } CharLowerBuff(pszA, nRet); _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); CTempBuffer pszW; ATLTRY(pszW.Allocate(_convert)); if (pszW == NULL) return E_OUTOFMEMORY; nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); if (nRet <= 0) { ATLASSERT(0); return AtlHresultFromLastError(); } UINT nBytes=0; HRESULT hr=S_OK; if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) { return hr; } BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); if (b == NULL) return E_OUTOFMEMORY; SysFreeString(m_str); m_str = b; #endif } return S_OK; } __checkReturn HRESULT ToUpper() throw() { if (::SysStringLen(m_str) > 0) { #ifdef _UNICODE // Convert in place CharUpperBuff(m_str, Length()); #else // Cannot use conversion macros due to possible embedded NULLs UINT _acp = _AtlGetConversionACP(); int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); CTempBuffer pszA; ATLTRY(pszA.Allocate(_convert)); if (pszA == NULL) return E_OUTOFMEMORY; int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); if (nRet == 0) { ATLASSERT(0); return AtlHresultFromLastError(); } CharUpperBuff(pszA, nRet); _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); CTempBuffer pszW; ATLTRY(pszW.Allocate(_convert)); if (pszW == NULL) return E_OUTOFMEMORY; nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); if (nRet <= 0) { ATLASSERT(0); return AtlHresultFromLastError(); } UINT nBytes=0; HRESULT hr=S_OK; if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) { return hr; } BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); if (b == NULL) return E_OUTOFMEMORY; SysFreeString(m_str); m_str = b; #endif } return S_OK; } bool LoadString(__in HINSTANCE hInst, __in UINT nID) throw() { ::SysFreeString(m_str); m_str = NULL; return LoadStringResource(hInst, nID, m_str); } bool LoadString(__in UINT nID) throw() { ::SysFreeString(m_str); m_str = NULL; return LoadStringResource(nID, m_str); } CComBSTR& operator+=(__in const CComBSTR& bstrSrc) { HRESULT hr; hr = AppendBSTR(bstrSrc.m_str); if (FAILED(hr)) AtlThrow(hr); return *this; } CComBSTR& operator+=(__in_opt LPCOLESTR pszSrc) { HRESULT hr; hr = Append(pszSrc); if (FAILED(hr)) AtlThrow(hr); return *this; } bool operator<(const CComBSTR& bstrSrc) const throw() { return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_LT); } bool operator<(__in_z LPCOLESTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator<(bstr2); } bool operator<(__in_z LPOLESTR pszSrc) const { return operator<((LPCOLESTR)pszSrc); } bool operator>(const CComBSTR& bstrSrc) const throw() { return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_GT); } bool operator>(__in_z LPCOLESTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator>(bstr2); } bool operator>(__in_z LPOLESTR pszSrc) const { return operator>((LPCOLESTR)pszSrc); } bool operator!=(const CComBSTR& bstrSrc) const throw() { return !operator==(bstrSrc); } bool operator!=(__in_z LPCOLESTR pszSrc) const { return !operator==(pszSrc); } bool operator!=(int nNull) const throw() { return !operator==(nNull); } bool operator!=(__in_z LPOLESTR pszSrc) const { return operator!=((LPCOLESTR)pszSrc); } bool operator==(const CComBSTR& bstrSrc) const throw() { return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); } bool operator==(__in_z LPCOLESTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator==(bstr2); } bool operator==(__in_z LPOLESTR pszSrc) const { return operator==((LPCOLESTR)pszSrc); } bool operator==(int nNull) const throw() { ATLASSERT(nNull == NULL); (void)nNull; return (!*this); } CComBSTR(__in LPCSTR pSrc) { if (pSrc != NULL) { m_str = A2WBSTR(pSrc); if (!*this) { AtlThrow(E_OUTOFMEMORY); } } else { m_str = NULL; } } CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCSTR sz) { if (nSize != 0 && sz == NULL) { m_str = ::SysAllocStringLen(NULL, nSize); if (!*this) { AtlThrow(E_OUTOFMEMORY); } return; } m_str = A2WBSTR(sz, nSize); if (!*this && nSize != 0) { AtlThrow(E_OUTOFMEMORY); } } __checkReturn HRESULT Append(__in LPCSTR lpsz) throw() { if (lpsz == NULL) return S_OK; CComBSTR bstrTemp; ATLTRY(bstrTemp = lpsz); if (!bstrTemp) { return E_OUTOFMEMORY; } return Append(bstrTemp); } CComBSTR& operator=(__in LPCSTR pSrc) { ::SysFreeString(m_str); m_str = A2WBSTR(pSrc); if (!*this && pSrc != NULL) { AtlThrow(E_OUTOFMEMORY); } return *this; } bool operator<(__in_z LPCSTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator<(bstr2); } bool operator>(__in_z LPCSTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator>(bstr2); } bool operator!=(__in_z LPCSTR pszSrc) const { return !operator==(pszSrc); } bool operator==(__in_z LPCSTR pszSrc) const { CComBSTR bstr2(pszSrc); return operator==(bstr2); } __checkReturn HRESULT WriteToStream(__inout IStream* pStream) throw() { ATLASSERT(pStream != NULL); if(pStream == NULL) return E_INVALIDARG; ULONG cb; ULONG cbStrLen = CComBSTR::GetStreamSize(m_str) - sizeof(ULONG); HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb); if (FAILED(hr)) return hr; return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK; } __checkReturn HRESULT ReadFromStream(__inout IStream* pStream) throw() { ATLASSERT(pStream != NULL); if(pStream == NULL) { return E_INVALIDARG; } ATLASSERT(!*this); // should be empty Empty(); HRESULT hrSeek; ULARGE_INTEGER nBegOffset; { LARGE_INTEGER nZeroOffset; nZeroOffset.QuadPart = 0L; hrSeek = pStream->Seek(nZeroOffset, STREAM_SEEK_CUR, &nBegOffset); } ULONG cbRead = 0; ULONG cbStrLen = 0; HRESULT hr = pStream->Read(reinterpret_cast(&cbStrLen), sizeof(cbStrLen), &cbRead); if (SUCCEEDED(hr)) { // invalid data sizes if (sizeof(cbStrLen) != cbRead) { ATLTRACE(atlTraceCOM, 0, _T("Input stream is corrupted.")); hr = E_FAIL; } // check for NULL bstr else if (cbStrLen == 0) { } // security checks when system hang for huge stream of data else if (cbStrLen > _ATL_STREAM_MAX_SIZE) { ATLTRACE(atlTraceCOM, 0, _T("String exceeded the maximum allowed size see _ATL_STREAM_MAX_SIZE.")); hr = E_ACCESSDENIED; } else { //subtract size for terminating NULL which we wrote out cbStrLen -= sizeof(OLECHAR); m_str = ::SysAllocStringByteLen(NULL, cbStrLen); if (!*this) { hr = E_OUTOFMEMORY; } else { hr = pStream->Read(reinterpret_cast(m_str), cbStrLen, &cbRead); if (SUCCEEDED(hr)) { if (cbRead != cbStrLen) { ATLTRACE(atlTraceCOM, 0, _T("Length of string data is different than expected.")); hr = E_FAIL; } else { OLECHAR ch; hr = pStream->Read(reinterpret_cast(&ch), sizeof(OLECHAR), &cbRead); if (SUCCEEDED(hr)) { if (cbRead != sizeof(OLECHAR)) { ATLTRACE(atlTraceCOM, 0, _T("Cannot read NULL terminator from stream.")); hr = E_FAIL; } else { //check if string is properly terminated with NULL ATLASSERT(ch == L'\0'); } } } } if (FAILED(hr)) { ::SysFreeString(m_str); m_str = NULL; } } } } // If SysAllocStringByteLen or IStream::Read failed, reset seek // pointer to start of BSTR size. if (FAILED(hr) && SUCCEEDED(hrSeek)) { LARGE_INTEGER nOffset; nOffset.QuadPart = static_cast(nBegOffset.QuadPart); pStream->Seek(nOffset, STREAM_SEEK_SET, NULL); } return hr; } static bool LoadStringResource(__in HINSTANCE hInstance, __in UINT uID, __deref_out_opt BSTR& bstrText) throw() { const ATLSTRINGRESOURCEIMAGE* pImage; #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") ATLASSERT(bstrText == NULL); #pragma prefast(pop) #pragma warning(pop) pImage = AtlGetStringResourceImage(hInstance, uID); if (pImage != NULL) { bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); } #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") return (bstrText != NULL) ? true : false; #pragma prefast(pop) #pragma warning(pop) } static bool LoadStringResource(__in UINT uID, __deref_out_opt BSTR& bstrText) throw() { const ATLSTRINGRESOURCEIMAGE* pImage; #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") ATLASSERT(bstrText == NULL); #pragma prefast(pop) #pragma warning(pop) pImage = AtlGetStringResourceImage(uID); if (pImage != NULL) { bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); } #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") return (bstrText != NULL) ? true : false; #pragma prefast(pop) #pragma warning(pop) } // each character in BSTR is copied to each element in SAFEARRAY __success(return>=0) HRESULT BSTRToArray(__deref_out LPSAFEARRAY *ppArray) throw() { return VectorFromBstr(m_str, ppArray); } // first character of each element in SAFEARRAY is copied to BSTR __checkReturn HRESULT ArrayToBSTR(__in const SAFEARRAY *pSrc) throw() { ::SysFreeString(m_str); return BstrFromVector((LPSAFEARRAY)pSrc, &m_str); } static ULONG GetStreamSize(BSTR bstr) { ULONG ulSize=sizeof(ULONG); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") if (bstr != NULL) #pragma prefast(pop) #pragma warning(pop) { ulSize += SysStringByteLen(bstr) + sizeof(OLECHAR); } return ulSize; } }; inline CComBSTR::~CComBSTR() throw() { ::SysFreeString(m_str); } inline void SysFreeStringHelper(__in CComBSTR& bstr) { bstr.Empty(); } inline void SysFreeStringHelper(BSTR bstr) { ::SysFreeString(bstr); } inline __checkReturn HRESULT SysAllocStringHelper(__out_opt CComBSTR& bstrDest,BSTR bstrSrc) { bstrDest=bstrSrc; return !bstrDest ? E_OUTOFMEMORY : S_OK; } inline __checkReturn HRESULT SysAllocStringHelper(__out_opt BSTR& bstrDest,BSTR bstrSrc) { bstrDest=::SysAllocString(bstrSrc); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "The semantics of this function are about allocation, not content") return bstrDest==NULL ? E_OUTOFMEMORY : S_OK; #pragma prefast(pop) #pragma warning(pop) } ///////////////////////////////////////////////////////////// // Class to Adapt CComBSTR and CComPtr for use with STL containers // the syntax to use it is // std::vector< CAdapt > vect; template class CAdapt { public: CAdapt() { } CAdapt(__in const T& rSrc) : m_T( rSrc ) { } CAdapt(__in const CAdapt& rSrCA) : m_T( rSrCA.m_T ) { } CAdapt& operator=(__in const T& rSrc) { m_T = rSrc; return *this; } bool operator<(__in const T& rSrc) const { return m_T < rSrc; } bool operator==(__in const T& rSrc) const { return m_T == rSrc; } operator T&() { return m_T; } operator const T&() const { return m_T; } T m_T; }; ///////////////////////////////////////////////////////////////////////////// // CComVariant #define ATL_VARIANT_TRUE VARIANT_BOOL( -1 ) #define ATL_VARIANT_FALSE VARIANT_BOOL( 0 ) template< typename T > class CVarTypeInfo { // static const VARTYPE VT; // VARTYPE corresponding to type T // static T VARIANT::* const pmField; // Pointer-to-member of corresponding field in VARIANT struct }; template<> class CVarTypeInfo< char > { public: static const VARTYPE VT = VT_I1; static char VARIANT::* const pmField; }; __declspec( selectany ) char VARIANT::* const CVarTypeInfo< char >::pmField = &VARIANT::cVal; template<> class CVarTypeInfo< unsigned char > { public: static const VARTYPE VT = VT_UI1; static unsigned char VARIANT::* const pmField; }; __declspec( selectany ) unsigned char VARIANT::* const CVarTypeInfo< unsigned char >::pmField = &VARIANT::bVal; template<> class CVarTypeInfo< char* > { public: static const VARTYPE VT = VT_I1|VT_BYREF; static char* VARIANT::* const pmField; }; __declspec( selectany ) char* VARIANT::* const CVarTypeInfo< char* >::pmField = &VARIANT::pcVal; template<> class CVarTypeInfo< unsigned char* > { public: static const VARTYPE VT = VT_UI1|VT_BYREF; static unsigned char* VARIANT::* const pmField; }; __declspec( selectany ) unsigned char* VARIANT::* const CVarTypeInfo< unsigned char* >::pmField = &VARIANT::pbVal; template<> class CVarTypeInfo< short > { public: static const VARTYPE VT = VT_I2; static short VARIANT::* const pmField; }; __declspec( selectany ) short VARIANT::* const CVarTypeInfo< short >::pmField = &VARIANT::iVal; template<> class CVarTypeInfo< short* > { public: static const VARTYPE VT = VT_I2|VT_BYREF; static short* VARIANT::* const pmField; }; __declspec( selectany ) short* VARIANT::* const CVarTypeInfo< short* >::pmField = &VARIANT::piVal; template<> class CVarTypeInfo< unsigned short > { public: static const VARTYPE VT = VT_UI2; static unsigned short VARIANT::* const pmField; }; __declspec( selectany ) unsigned short VARIANT::* const CVarTypeInfo< unsigned short >::pmField = &VARIANT::uiVal; #ifdef _NATIVE_WCHAR_T_DEFINED // Only treat unsigned short* as VT_UI2|VT_BYREF if BSTR isn't the same as unsigned short* template<> class CVarTypeInfo< unsigned short* > { public: static const VARTYPE VT = VT_UI2|VT_BYREF; static unsigned short* VARIANT::* const pmField; }; __declspec( selectany ) unsigned short* VARIANT::* const CVarTypeInfo< unsigned short* >::pmField = &VARIANT::puiVal; #endif // _NATIVE_WCHAR_T_DEFINED template<> class CVarTypeInfo< int > { public: static const VARTYPE VT = VT_I4; static int VARIANT::* const pmField; }; __declspec( selectany ) int VARIANT::* const CVarTypeInfo< int >::pmField = &VARIANT::intVal; template<> class CVarTypeInfo< int* > { public: static const VARTYPE VT = VT_I4|VT_BYREF; static int* VARIANT::* const pmField; }; __declspec( selectany ) int* VARIANT::* const CVarTypeInfo< int* >::pmField = &VARIANT::pintVal; template<> class CVarTypeInfo< unsigned int > { public: static const VARTYPE VT = VT_UI4; static unsigned int VARIANT::* const pmField; }; __declspec( selectany ) unsigned int VARIANT::* const CVarTypeInfo< unsigned int >::pmField = &VARIANT::uintVal; template<> class CVarTypeInfo< unsigned int* > { public: static const VARTYPE VT = VT_UI4|VT_BYREF; static unsigned int* VARIANT::* const pmField; }; __declspec( selectany ) unsigned int* VARIANT::* const CVarTypeInfo< unsigned int* >::pmField = &VARIANT::puintVal; template<> class CVarTypeInfo< long > { public: static const VARTYPE VT = VT_I4; static long VARIANT::* const pmField; }; __declspec( selectany ) long VARIANT::* const CVarTypeInfo< long >::pmField = &VARIANT::lVal; template<> class CVarTypeInfo< long* > { public: static const VARTYPE VT = VT_I4|VT_BYREF; static long* VARIANT::* const pmField; }; __declspec( selectany ) long* VARIANT::* const CVarTypeInfo< long* >::pmField = &VARIANT::plVal; template<> class CVarTypeInfo< unsigned long > { public: static const VARTYPE VT = VT_UI4; static unsigned long VARIANT::* const pmField; }; __declspec( selectany ) unsigned long VARIANT::* const CVarTypeInfo< unsigned long >::pmField = &VARIANT::ulVal; template<> class CVarTypeInfo< unsigned long* > { public: static const VARTYPE VT = VT_UI4|VT_BYREF; static unsigned long* VARIANT::* const pmField; }; __declspec( selectany ) unsigned long* VARIANT::* const CVarTypeInfo< unsigned long* >::pmField = &VARIANT::pulVal; template<> class CVarTypeInfo< __int64 > { public: static const VARTYPE VT = VT_I8; static __int64 VARIANT::* const pmField; }; __declspec( selectany ) __int64 VARIANT::* const CVarTypeInfo< __int64 >::pmField = &VARIANT::llVal; template<> class CVarTypeInfo< __int64* > { public: static const VARTYPE VT = VT_I8|VT_BYREF; static __int64* VARIANT::* const pmField; }; __declspec( selectany ) __int64* VARIANT::* const CVarTypeInfo< __int64* >::pmField = &VARIANT::pllVal; template<> class CVarTypeInfo< unsigned __int64 > { public: static const VARTYPE VT = VT_UI8; static unsigned __int64 VARIANT::* const pmField; }; __declspec( selectany ) unsigned __int64 VARIANT::* const CVarTypeInfo< unsigned __int64 >::pmField = &VARIANT::ullVal; template<> class CVarTypeInfo< unsigned __int64* > { public: static const VARTYPE VT = VT_UI8|VT_BYREF; static unsigned __int64* VARIANT::* const pmField; }; __declspec( selectany ) unsigned __int64* VARIANT::* const CVarTypeInfo< unsigned __int64* >::pmField = &VARIANT::pullVal; template<> class CVarTypeInfo< float > { public: static const VARTYPE VT = VT_R4; static float VARIANT::* const pmField; }; __declspec( selectany ) float VARIANT::* const CVarTypeInfo< float >::pmField = &VARIANT::fltVal; template<> class CVarTypeInfo< float* > { public: static const VARTYPE VT = VT_R4|VT_BYREF; static float* VARIANT::* const pmField; }; __declspec( selectany ) float* VARIANT::* const CVarTypeInfo< float* >::pmField = &VARIANT::pfltVal; template<> class CVarTypeInfo< double > { public: static const VARTYPE VT = VT_R8; static double VARIANT::* const pmField; }; __declspec( selectany ) double VARIANT::* const CVarTypeInfo< double >::pmField = &VARIANT::dblVal; template<> class CVarTypeInfo< double* > { public: static const VARTYPE VT = VT_R8|VT_BYREF; static double* VARIANT::* const pmField; }; __declspec( selectany ) double* VARIANT::* const CVarTypeInfo< double* >::pmField = &VARIANT::pdblVal; template<> class CVarTypeInfo< VARIANT > { public: static const VARTYPE VT = VT_VARIANT; }; template<> class CVarTypeInfo< BSTR > { public: static const VARTYPE VT = VT_BSTR; static BSTR VARIANT::* const pmField; }; __declspec( selectany ) BSTR VARIANT::* const CVarTypeInfo< BSTR >::pmField = &VARIANT::bstrVal; template<> class CVarTypeInfo< BSTR* > { public: static const VARTYPE VT = VT_BSTR|VT_BYREF; static BSTR* VARIANT::* const pmField; }; __declspec( selectany ) BSTR* VARIANT::* const CVarTypeInfo< BSTR* >::pmField = &VARIANT::pbstrVal; template<> class CVarTypeInfo< IUnknown* > { public: static const VARTYPE VT = VT_UNKNOWN; static IUnknown* VARIANT::* const pmField; }; __declspec( selectany ) IUnknown* VARIANT::* const CVarTypeInfo< IUnknown* >::pmField = &VARIANT::punkVal; template<> class CVarTypeInfo< IUnknown** > { public: static const VARTYPE VT = VT_UNKNOWN|VT_BYREF; static IUnknown** VARIANT::* const pmField; }; __declspec( selectany ) IUnknown** VARIANT::* const CVarTypeInfo< IUnknown** >::pmField = &VARIANT::ppunkVal; template<> class CVarTypeInfo< IDispatch* > { public: static const VARTYPE VT = VT_DISPATCH; static IDispatch* VARIANT::* const pmField; }; __declspec( selectany ) IDispatch* VARIANT::* const CVarTypeInfo< IDispatch* >::pmField = &VARIANT::pdispVal; template<> class CVarTypeInfo< IDispatch** > { public: static const VARTYPE VT = VT_DISPATCH|VT_BYREF; static IDispatch** VARIANT::* const pmField; }; __declspec( selectany ) IDispatch** VARIANT::* const CVarTypeInfo< IDispatch** >::pmField = &VARIANT::ppdispVal; template<> class CVarTypeInfo< CY > { public: static const VARTYPE VT = VT_CY; static CY VARIANT::* const pmField; }; __declspec( selectany ) CY VARIANT::* const CVarTypeInfo< CY >::pmField = &VARIANT::cyVal; template<> class CVarTypeInfo< CY* > { public: static const VARTYPE VT = VT_CY|VT_BYREF; static CY* VARIANT::* const pmField; }; __declspec( selectany ) CY* VARIANT::* const CVarTypeInfo< CY* >::pmField = &VARIANT::pcyVal; class CComVariant : public tagVARIANT { // Constructors public: CComVariant() throw() { ::VariantInit(this); } ~CComVariant() throw() { Clear(); } CComVariant(__in const VARIANT& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CComVariant(__in const CComVariant& varSrc) { vt = VT_EMPTY; InternalCopy(&varSrc); } CComVariant(__in LPCOLESTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CComVariant(__in LPCSTR lpszSrc) { vt = VT_EMPTY; *this = lpszSrc; } CComVariant(__in bool bSrc) { vt = VT_BOOL; boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; } CComVariant(__in int nSrc, __in VARTYPE vtSrc = VT_I4) throw() { ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_INT); vt = vtSrc; intVal = nSrc; } CComVariant(__in BYTE nSrc) throw() { vt = VT_UI1; bVal = nSrc; } CComVariant(__in short nSrc) throw() { vt = VT_I2; iVal = nSrc; } CComVariant(__in long nSrc, __in VARTYPE vtSrc = VT_I4) throw() { ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR); vt = vtSrc; lVal = nSrc; } CComVariant(__in float fltSrc) throw() { vt = VT_R4; fltVal = fltSrc; } CComVariant(__in double dblSrc, __in VARTYPE vtSrc = VT_R8) throw() { ATLASSERT(vtSrc == VT_R8 || vtSrc == VT_DATE); vt = vtSrc; dblVal = dblSrc; } #if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) CComVariant(__in LONGLONG nSrc) throw() { vt = VT_I8; llVal = nSrc; } CComVariant(__in ULONGLONG nSrc) throw() { vt = VT_UI8; ullVal = nSrc; } #endif CComVariant(CY __in cySrc) throw() { vt = VT_CY; cyVal.Hi = cySrc.Hi; cyVal.Lo = cySrc.Lo; } CComVariant(__in_opt IDispatch* pSrc) throw() { vt = VT_DISPATCH; pdispVal = pSrc; // Need to AddRef as VariantClear will Release if (pdispVal != NULL) pdispVal->AddRef(); } CComVariant(__in_opt IUnknown* pSrc) throw() { vt = VT_UNKNOWN; punkVal = pSrc; // Need to AddRef as VariantClear will Release if (punkVal != NULL) punkVal->AddRef(); } CComVariant(__in char cSrc) throw() { vt = VT_I1; cVal = cSrc; } CComVariant(__in unsigned short nSrc) throw() { vt = VT_UI2; uiVal = nSrc; } CComVariant(__in unsigned long nSrc) throw() { vt = VT_UI4; ulVal = nSrc; } CComVariant(__in unsigned int nSrc, __in VARTYPE vtSrc = VT_UI4) throw() { ATLASSERT(vtSrc == VT_UI4 || vtSrc == VT_UINT); vt = vtSrc; uintVal= nSrc; } CComVariant(__in const CComBSTR& bstrSrc) { vt = VT_EMPTY; *this = bstrSrc; } CComVariant(__in_opt const SAFEARRAY *pSrc) { LPSAFEARRAY pCopy; if (pSrc != NULL) { HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); if (SUCCEEDED(hRes) && pCopy != NULL) { ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); vt |= VT_ARRAY; parray = pCopy; } else { vt = VT_ERROR; scode = hRes; #ifndef _ATL_NO_VARIANT_THROW ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); #endif } } else { vt = VT_EMPTY; } } // Assignment Operators public: CComVariant& operator=(__in const CComVariant& varSrc) { if(this!=&varSrc) { InternalCopy(&varSrc); } return *this; } CComVariant& operator=(__in const VARIANT& varSrc) { if(static_cast(this)!=&varSrc) { InternalCopy(&varSrc); } return *this; } CComVariant& operator=(__in const CComBSTR& bstrSrc) { Clear(); vt = VT_BSTR; bstrVal = bstrSrc.Copy(); #pragma warning(push) #pragma warning(disable:4068) #pragma prefast(push) #pragma prefast(disable:325, "We are checking allocation semantics here") if (bstrVal == NULL && bstrSrc.m_str != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; #ifndef _ATL_NO_VARIANT_THROW ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); #endif } #pragma prefast(pop) #pragma warning(pop) return *this; } CComVariant& operator=(__in LPCOLESTR lpszSrc) { Clear(); vt = VT_BSTR; bstrVal = ::SysAllocString(lpszSrc); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; #ifndef _ATL_NO_VARIANT_THROW ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); #endif } return *this; } CComVariant& operator=(__in LPCSTR lpszSrc) { USES_CONVERSION_EX; Clear(); vt = VT_BSTR; bstrVal = ::SysAllocString(A2COLE_EX(lpszSrc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD)); if (bstrVal == NULL && lpszSrc != NULL) { vt = VT_ERROR; scode = E_OUTOFMEMORY; #ifndef _ATL_NO_VARIANT_THROW ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); #endif } return *this; } CComVariant& operator=(__in bool bSrc) { if (vt != VT_BOOL) { Clear(); vt = VT_BOOL; } boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; return *this; } CComVariant& operator=(__in int nSrc) throw() { if (vt != VT_I4) { Clear(); vt = VT_I4; } intVal = nSrc; return *this; } CComVariant& operator=(__in BYTE nSrc) throw() { if (vt != VT_UI1) { Clear(); vt = VT_UI1; } bVal = nSrc; return *this; } CComVariant& operator=(__in short nSrc) throw() { if (vt != VT_I2) { Clear(); vt = VT_I2; } iVal = nSrc; return *this; } CComVariant& operator=(__in long nSrc) throw() { if (vt != VT_I4) { Clear(); vt = VT_I4; } lVal = nSrc; return *this; } CComVariant& operator=(__in float fltSrc) throw() { if (vt != VT_R4) { Clear(); vt = VT_R4; } fltVal = fltSrc; return *this; } CComVariant& operator=(__in double dblSrc) throw() { if (vt != VT_R8) { Clear(); vt = VT_R8; } dblVal = dblSrc; return *this; } CComVariant& operator=(__in CY cySrc) throw() { if (vt != VT_CY) { Clear(); vt = VT_CY; } cyVal.Hi = cySrc.Hi; cyVal.Lo = cySrc.Lo; return *this; } CComVariant& operator=(__in_opt IDispatch* pSrc) throw() { Clear(); vt = VT_DISPATCH; pdispVal = pSrc; // Need to AddRef as VariantClear will Release if (pdispVal != NULL) pdispVal->AddRef(); return *this; } CComVariant& operator=(__in_opt IUnknown* pSrc) throw() { Clear(); vt = VT_UNKNOWN; punkVal = pSrc; // Need to AddRef as VariantClear will Release if (punkVal != NULL) punkVal->AddRef(); return *this; } CComVariant& operator=(__in char cSrc) throw() { if (vt != VT_I1) { Clear(); vt = VT_I1; } cVal = cSrc; return *this; } CComVariant& operator=(__in unsigned short nSrc) throw() { if (vt != VT_UI2) { Clear(); vt = VT_UI2; } uiVal = nSrc; return *this; } CComVariant& operator=(__in unsigned long nSrc) throw() { if (vt != VT_UI4) { Clear(); vt = VT_UI4; } ulVal = nSrc; return *this; } CComVariant& operator=(__in unsigned int nSrc) throw() { if (vt != VT_UI4) { Clear(); vt = VT_UI4; } uintVal= nSrc; return *this; } CComVariant& operator=(__in_opt BYTE* pbSrc) throw() { if (vt != (VT_UI1|VT_BYREF)) { Clear(); vt = VT_UI1|VT_BYREF; } pbVal = pbSrc; return *this; } CComVariant& operator=(__in_opt short* pnSrc) throw() { if (vt != (VT_I2|VT_BYREF)) { Clear(); vt = VT_I2|VT_BYREF; } piVal = pnSrc; return *this; } #ifdef _NATIVE_WCHAR_T_DEFINED CComVariant& operator=(__in_opt USHORT* pnSrc) throw() { if (vt != (VT_UI2|VT_BYREF)) { Clear(); vt = VT_UI2|VT_BYREF; } puiVal = pnSrc; return *this; } #endif CComVariant& operator=(__in_opt int* pnSrc) throw() { if (vt != (VT_I4|VT_BYREF)) { Clear(); vt = VT_I4|VT_BYREF; } pintVal = pnSrc; return *this; } CComVariant& operator=(__in_opt UINT* pnSrc) throw() { if (vt != (VT_UI4|VT_BYREF)) { Clear(); vt = VT_UI4|VT_BYREF; } puintVal = pnSrc; return *this; } CComVariant& operator=(__in_opt long* pnSrc) throw() { if (vt != (VT_I4|VT_BYREF)) { Clear(); vt = VT_I4|VT_BYREF; } plVal = pnSrc; return *this; } CComVariant& operator=(__in_opt ULONG* pnSrc) throw() { if (vt != (VT_UI4|VT_BYREF)) { Clear(); vt = VT_UI4|VT_BYREF; } pulVal = pnSrc; return *this; } #if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) CComVariant& operator=(__in LONGLONG nSrc) throw() { if (vt != VT_I8) { Clear(); vt = VT_I8; } llVal = nSrc; return *this; } CComVariant& operator=(__in_opt LONGLONG* pnSrc) throw() { if (vt != (VT_I8|VT_BYREF)) { Clear(); vt = VT_I8|VT_BYREF; } pllVal = pnSrc; return *this; } CComVariant& operator=(__in ULONGLONG nSrc) throw() { if (vt != VT_UI8) { Clear(); vt = VT_UI8; } ullVal = nSrc; return *this; } CComVariant& operator=(__in_opt ULONGLONG* pnSrc) throw() { if (vt != (VT_UI8|VT_BYREF)) { Clear(); vt = VT_UI8|VT_BYREF; } pullVal = pnSrc; return *this; } #endif #pragma warning(push) #pragma warning(disable: 28110) CComVariant& operator=(__in_opt float* pfSrc) throw() { if (vt != (VT_R4|VT_BYREF)) { Clear(); vt = VT_R4|VT_BYREF; } pfltVal = pfSrc; return *this; } CComVariant& operator=(__in_opt double* pfSrc) throw() { if (vt != (VT_R8|VT_BYREF)) { Clear(); vt = VT_R8|VT_BYREF; } pdblVal = pfSrc; return *this; } #pragma warning(pop) CComVariant& operator=(__in_opt const SAFEARRAY *pSrc) { Clear(); LPSAFEARRAY pCopy; if (pSrc != NULL) { HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); if (SUCCEEDED(hRes) && pCopy != NULL) { ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); vt |= VT_ARRAY; parray = pCopy; } else { vt = VT_ERROR; scode = hRes; #ifndef _ATL_NO_VARIANT_THROW ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); #endif } } return *this; } // Comparison Operators public: bool operator==(__in const VARIANT& varSrc) const throw() { // For backwards compatibility if (vt == VT_NULL && varSrc.vt == VT_NULL) { return true; } // Variants not equal if types don't match if (vt != varSrc.vt) { return false; } return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); } bool operator!=(__in const VARIANT& varSrc) const throw() { return !operator==(varSrc); } bool operator<(__in const VARIANT& varSrc) const throw() { if (vt == VT_NULL && varSrc.vt == VT_NULL) return false; return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_LT); } bool operator>(__in const VARIANT& varSrc) const throw() { if (vt == VT_NULL && varSrc.vt == VT_NULL) return false; return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_GT); } // Operations public: HRESULT Clear() { return ::VariantClear(this); } HRESULT ClearToZero() { HRESULT hr = ::VariantClear(this); if( FAILED(hr) ) { return hr; } memset(this ,0 ,sizeof(tagVARIANT)); vt = VT_EMPTY; return hr; } HRESULT Copy(__in const VARIANT* pSrc) { return ::VariantCopy(this, const_cast(pSrc)); } // copy VARIANT to BSTR HRESULT CopyTo(__out BSTR *pstrDest) { ATLASSERT(pstrDest != NULL && vt == VT_BSTR); HRESULT hRes = E_POINTER; if (pstrDest != NULL && vt == VT_BSTR) { *pstrDest = ::SysAllocStringByteLen((char*)bstrVal, ::SysStringByteLen(bstrVal)); if (*pstrDest == NULL) hRes = E_OUTOFMEMORY; else hRes = S_OK; } else if (vt != VT_BSTR) hRes = DISP_E_TYPEMISMATCH; return hRes; } HRESULT Attach(__in VARIANT* pSrc) { if(pSrc == NULL) return E_INVALIDARG; // Clear out the variant HRESULT hr = Clear(); if (!FAILED(hr)) { // Copy the contents and give control to CComVariant Checked::memcpy_s(this, sizeof(CComVariant), pSrc, sizeof(VARIANT)); pSrc->vt = VT_EMPTY; hr = S_OK; } return hr; } HRESULT Detach(__out VARIANT* pDest) { ATLASSERT(pDest != NULL); if(pDest == NULL) return E_POINTER; // Clear out the variant HRESULT hr = ::VariantClear(pDest); if (!FAILED(hr)) { // Copy the contents and remove control from CComVariant Checked::memcpy_s(pDest, sizeof(VARIANT), this, sizeof(VARIANT)); vt = VT_EMPTY; hr = S_OK; } return hr; } HRESULT ChangeType(__in VARTYPE vtNew, __in_opt const VARIANT* pSrc = NULL) { VARIANT* pVar = const_cast(pSrc); // Convert in place if pSrc is NULL if (pVar == NULL) pVar = this; // Do nothing if doing in place convert and vts not different return ::VariantChangeType(this, pVar, 0, vtNew); } template< typename T > void SetByRef( __in T* pT ) throw() { Clear(); vt = CVarTypeInfo< T >::VT|VT_BYREF; byref = pT; } HRESULT WriteToStream(__inout IStream* pStream); HRESULT WriteToStream(__inout IStream* pStream, VARTYPE vtWrite) { if (vtWrite != VT_EMPTY && vtWrite != vt) { CComVariant varConv; HRESULT hr = varConv.ChangeType(vtWrite, this); if (FAILED(hr)) { return hr; } return varConv.WriteToStream(pStream); } return WriteToStream(pStream); } HRESULT ReadFromStream(__inout IStream* pStream, VARTYPE vtExpected = VT_EMPTY); // Return the size in bytes of the current contents ULONG GetSize() const; // Implementation public: HRESULT InternalClear() { HRESULT hr = Clear(); ATLASSERT(SUCCEEDED(hr)); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; #ifndef _ATL_NO_VARIANT_THROW AtlThrow(hr); #endif } return hr; } void InternalCopy(__in const VARIANT* pSrc) { HRESULT hr = Copy(pSrc); if (FAILED(hr)) { vt = VT_ERROR; scode = hr; #ifndef _ATL_NO_VARIANT_THROW AtlThrow(hr); #endif } } }; #pragma warning(push) #pragma warning(disable: 4702) inline HRESULT CComVariant::WriteToStream(__inout IStream* pStream) { if(pStream == NULL) return E_INVALIDARG; HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL); if (FAILED(hr)) return hr; int cbWrite = 0; switch (vt) { case VT_UNKNOWN: case VT_DISPATCH: { CComPtr spStream; if (punkVal != NULL) { hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); if (FAILED(hr)) { hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); if (FAILED(hr)) return hr; } } if (spStream != NULL) return OleSaveToStream(spStream, pStream); return WriteClassStm(pStream, CLSID_NULL); } case VT_UI1: case VT_I1: cbWrite = sizeof(BYTE); break; case VT_I2: case VT_UI2: case VT_BOOL: cbWrite = sizeof(short); break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: cbWrite = sizeof(long); break; case VT_I8: case VT_UI8: cbWrite = sizeof(LONGLONG); break; case VT_R8: case VT_CY: case VT_DATE: cbWrite = sizeof(double); break; default: break; } if (cbWrite != 0) return pStream->Write((void*) &bVal, cbWrite, NULL); CComBSTR bstrWrite; CComVariant varBSTR; if (vt != VT_BSTR) { hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR); if (FAILED(hr)) return hr; bstrWrite.Attach(varBSTR.bstrVal); } else bstrWrite.Attach(bstrVal); hr = bstrWrite.WriteToStream(pStream); bstrWrite.Detach(); return hr; } #pragma warning(pop) // C4702 inline HRESULT CComVariant::ReadFromStream(__inout IStream* pStream, VARTYPE vtExpected /* = VT_EMPTY */ ) { ATLASSERT(pStream != NULL); if(pStream == NULL) return E_INVALIDARG; HRESULT hr; hr = VariantClear(this); if (FAILED(hr)) return hr; VARTYPE vtRead = VT_EMPTY; ULONG cbRead = 0; hr = pStream->Read(&vtRead, sizeof(VARTYPE), &cbRead); if (hr == S_FALSE || (cbRead != sizeof(VARTYPE) && hr == S_OK)) hr = E_FAIL; if (FAILED(hr)) return hr; if (vtExpected != VT_EMPTY && vtRead != vtExpected) return E_FAIL; vt = vtRead; cbRead = 0; switch (vtRead) { case VT_UNKNOWN: case VT_DISPATCH: { punkVal = NULL; hr = OleLoadFromStream(pStream, (vtRead == VT_UNKNOWN) ? __uuidof(IUnknown) : __uuidof(IDispatch), (void**)&punkVal); // If IPictureDisp or IFontDisp property is not set, // OleLoadFromStream() will return REGDB_E_CLASSNOTREG. if (hr == REGDB_E_CLASSNOTREG) hr = S_OK; return hr; } case VT_UI1: case VT_I1: cbRead = sizeof(BYTE); break; case VT_I2: case VT_UI2: case VT_BOOL: cbRead = sizeof(short); break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: cbRead = sizeof(long); break; case VT_I8: case VT_UI8: cbRead = sizeof(LONGLONG); break; case VT_R8: case VT_CY: case VT_DATE: cbRead = sizeof(double); break; default: break; } if (cbRead != 0) { hr = pStream->Read((void*) &bVal, cbRead, NULL); if (hr == S_FALSE) hr = E_FAIL; return hr; } CComBSTR bstrRead; hr = bstrRead.ReadFromStream(pStream); if (FAILED(hr)) { // If CComBSTR::ReadFromStream failed, reset seek pointer to start of // variant type. LARGE_INTEGER nOffset; nOffset.QuadPart = -(static_cast(sizeof(VARTYPE))); pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); vt = VT_EMPTY; return hr; } vt = VT_BSTR; bstrVal = bstrRead.Detach(); if (vtRead != VT_BSTR) hr = ChangeType(vtRead); return hr; } inline ULONG CComVariant::GetSize() const { ULONG nSize = sizeof(VARTYPE); HRESULT hr; switch (vt) { case VT_UNKNOWN: case VT_DISPATCH: { CComPtr spStream; if (punkVal != NULL) { hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); if (FAILED(hr)) { hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); if (FAILED(hr)) break; } } if (spStream != NULL) { ULARGE_INTEGER nPersistSize; nPersistSize.QuadPart = 0; spStream->GetSizeMax(&nPersistSize); nSize += nPersistSize.LowPart + sizeof(CLSID); } else nSize += sizeof(CLSID); } break; case VT_UI1: case VT_I1: nSize += sizeof(BYTE); break; case VT_I2: case VT_UI2: case VT_BOOL: nSize += sizeof(short); break; case VT_I4: case VT_UI4: case VT_R4: case VT_INT: case VT_UINT: case VT_ERROR: nSize += sizeof(long); break; case VT_I8: case VT_UI8: nSize += sizeof(LONGLONG); break; case VT_R8: case VT_CY: case VT_DATE: nSize += sizeof(double); break; default: break; } if (nSize == sizeof(VARTYPE)) { VARTYPE vtTmp = vt; BSTR bstr = NULL; CComVariant varBSTR; if (vtTmp != VT_BSTR) { hr = VariantChangeType(&varBSTR, const_cast((const VARIANT*)this), VARIANT_NOVALUEPROP, VT_BSTR); if (SUCCEEDED(hr)) { bstr = varBSTR.bstrVal; vtTmp = VT_BSTR; } } else { bstr = bstrVal; } if (vtTmp == VT_BSTR) { // Add the size of the length + string (in bytes) + NULL terminator. nSize += CComBSTR::GetStreamSize(bstr); } } return nSize; } __checkReturn inline HRESULT CComPtr::Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet) throw() { if(pvarParam1 == NULL || pvarParam2 == NULL) return E_INVALIDARG; CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0}; return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); } } // namespace ATL #pragma pack(pop) #pragma warning (pop) #ifndef _ATL_NO_AUTOMATIC_NAMESPACE using namespace ATL; #endif //!_ATL_NO_AUTOMATIC_NAMESPACE #endif // __ATLCOMCLI_H__