Files
mimis/cpp/jacob/include/atlcomcli.h
2011-02-07 07:43:34 +00:00

2875 lines
64 KiB
C++

// 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 <atlcore.h>
#include <ole2.h>
#include <olectl.h>
#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 T>
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 T>
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<T>* operator->() const throw()
{
ATLASSERT(p!=NULL);
return (_NoAddRefReleaseOnCComPtr<T>*)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<IUnknown> punk1;
CComPtr<IUnknown> 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 <class Q>
__checkReturn HRESULT QueryInterface(__deref_out_opt Q** pp) const throw()
{
ATLASSERT(pp != NULL);
return p->QueryInterface(__uuidof(Q), (void**)pp);
}
T* p;
};
template <class T>
class CComPtr : public CComPtrBase<T>
{
public:
CComPtr() throw()
{
}
CComPtr(int nNull) throw() :
CComPtrBase<T>(nNull)
{
}
CComPtr(T* lp) throw() :
CComPtrBase<T>(lp)
{
}
CComPtr(__in const CComPtr<T>& lp) throw() :
CComPtrBase<T>(lp.p)
{
}
T* operator=(__in_opt T* lp) throw()
{
if(*this!=lp)
{
return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
template <typename Q>
T* operator=(__in const CComPtr<Q>& lp) throw()
{
if( !IsEqualObject(lp) )
{
return static_cast<T*>(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T)));
}
return *this;
}
T* operator=(__in const CComPtr<T>& lp) throw()
{
if(*this!=lp)
{
return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
};
//specialization for IDispatch
template <>
class CComPtr<IDispatch> : public CComPtrBase<IDispatch>
{
public:
CComPtr() throw()
{
}
CComPtr(IDispatch* lp) throw() :
CComPtrBase<IDispatch>(lp)
{
}
CComPtr(const CComPtr<IDispatch>& lp) throw() :
CComPtrBase<IDispatch>(lp.p)
{
}
IDispatch* operator=(IDispatch* lp) throw()
{
if(*this!=lp)
{
return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
IDispatch* operator=(const CComPtr<IDispatch>& lp) throw()
{
if(*this!=lp)
{
return static_cast<IDispatch*>(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<LPOLESTR*>(&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 T, const IID* piid = &__uuidof(T)>
class CComQIPtr : public CComPtr<T>
{
public:
CComQIPtr() throw()
{
}
CComQIPtr(__in T* lp) throw() :
CComPtr<T>(lp)
{
}
CComQIPtr(__in const CComQIPtr<T,piid>& lp) throw() :
CComPtr<T>(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<T*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
T* operator=(__in const CComQIPtr<T,piid>& lp) throw()
{
if(*this!=lp)
{
return static_cast<T*>(AtlComPtrAssign((IUnknown**)&p, lp.p));
}
return *this;
}
T* operator=(__in IUnknown* lp) throw()
{
if(*this!=lp)
{
return static_cast<T*>(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid));
}
return *this;
}
};
//Specialization to make it work
template<>
class CComQIPtr<IUnknown, &IID_IUnknown> : public CComPtr<IUnknown>
{
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<IUnknown,&IID_IUnknown>& lp) throw() :
CComPtr<IUnknown>(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<IUnknown,&IID_IUnknown>& lp) throw()
{
if(*this!=lp)
{
return AtlComPtrAssign((IUnknown**)&p, lp.p);
}
return *this;
}
};
typedef CComQIPtr<IDispatch, &__uuidof(IDispatch)> 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<char> 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<WCHAR> 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<UINT>(nRet), static_cast<UINT>(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<char> 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<WCHAR> 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<UINT>(nRet), static_cast<UINT>(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<HRESULT>(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<HRESULT>(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<HRESULT>(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<void*>(&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<void*>(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<void*>(&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<LONGLONG>(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 <CComBSTR> > vect;
template <class T>
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<VARIANT *>(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<HRESULT>(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<HRESULT>(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<HRESULT>(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<VARIANT*>(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<VARIANT*>(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<IPersistStream> 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<LONGLONG>(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<IPersistStream> 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<VARIANT*>((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<IDispatch>::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__