Source code

Revision control

Copy as Markdown

Other Tools

// Windows/PropVariant.cpp↩
#include "StdAfx.h"
#include "../Common/Defs.h"
#include "PropVariant.h"
namespace NWindows {↩
namespace NCOM {↩
BSTR AllocBstrFromAscii(const char *s) throw()↩
{↩
if (!s)↩
return NULL;↩
UINT len = (UINT)strlen(s);↩
BSTR p = ::SysAllocStringLen(NULL, len);↩
if (p)↩
{↩
for (UINT i = 0; i <= len; i++)↩
p[i] = (Byte)s[i];↩
}↩
return p;↩
}↩
HRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()↩
{↩
p->bstrVal = ::SysAllocStringLen(NULL, numChars);↩
if (!p->bstrVal)↩
{↩
p->vt = VT_ERROR;↩
p->scode = E_OUTOFMEMORY;↩
return E_OUTOFMEMORY;↩
}↩
p->vt = VT_BSTR;↩
return S_OK;↩
}↩
HRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()↩
{↩
p->bstrVal = AllocBstrFromAscii(s);↩
if (p->bstrVal)↩
{↩
p->vt = VT_BSTR;↩
return S_OK;↩
}↩
p->vt = VT_ERROR;↩
p->scode = E_OUTOFMEMORY;↩
return E_OUTOFMEMORY;↩
}↩
CPropVariant::CPropVariant(const PROPVARIANT &varSrc)↩
{↩
vt = VT_EMPTY;↩
InternalCopy(&varSrc);↩
}↩
CPropVariant::CPropVariant(const CPropVariant &varSrc)↩
{↩
vt = VT_EMPTY;↩
InternalCopy(&varSrc);↩
}↩
CPropVariant::CPropVariant(BSTR bstrSrc)↩
{↩
vt = VT_EMPTY;↩
*this = bstrSrc;↩
}↩
CPropVariant::CPropVariant(LPCOLESTR lpszSrc)↩
{↩
vt = VT_EMPTY;↩
*this = lpszSrc;↩
}↩
CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)↩
{↩
InternalCopy(&varSrc);↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)↩
{↩
InternalCopy(&varSrc);↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(BSTR bstrSrc)↩
{↩
*this = (LPCOLESTR)bstrSrc;↩
return *this;↩
}↩
static const char * const kMemException = "out of memory";↩
CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)↩
{↩
InternalClear();↩
vt = VT_BSTR;↩
wReserved1 = 0;↩
bstrVal = ::SysAllocString(lpszSrc);↩
if (!bstrVal && lpszSrc)↩
{↩
throw kMemException;↩
// vt = VT_ERROR;↩
// scode = E_OUTOFMEMORY;↩
}↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(const UString &s)↩
{↩
InternalClear();↩
vt = VT_BSTR;↩
wReserved1 = 0;↩
bstrVal = ::SysAllocStringLen(s, s.Len());↩
if (!bstrVal)↩
throw kMemException;↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(const UString2 &s)↩
{↩
/*↩
if (s.IsEmpty())↩
*this = L"";↩
else↩
*/
{↩
InternalClear();↩
vt = VT_BSTR;↩
wReserved1 = 0;↩
bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());↩
if (!bstrVal)↩
throw kMemException;↩
/* SysAllocStringLen probably appends a null-terminating character for NULL string.↩
But it doesn't specified in MSDN.↩
But we suppose that it works↩
if (!s.GetRawPtr())↩
{↩
*bstrVal = 0;↩
}↩
*/
/* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)↩
pointers to this function causes an unexpected termination of the application.↩
Is it safe? Maybe we must chamnge the code for that case ? */
}↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(const char *s)↩
{↩
InternalClear();↩
vt = VT_BSTR;↩
wReserved1 = 0;↩
bstrVal = AllocBstrFromAscii(s);↩
if (!bstrVal)↩
{↩
throw kMemException;↩
// vt = VT_ERROR;↩
// scode = E_OUTOFMEMORY;↩
}↩
return *this;↩
}↩
CPropVariant& CPropVariant::operator=(bool bSrc) throw()↩
{↩
if (vt != VT_BOOL)↩
{↩
InternalClear();↩
vt = VT_BOOL;↩
}↩
boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;↩
return *this;↩
}↩
BSTR CPropVariant::AllocBstr(unsigned numChars)↩
{↩
if (vt != VT_EMPTY)↩
InternalClear();↩
vt = VT_BSTR;↩
wReserved1 = 0;↩
bstrVal = ::SysAllocStringLen(NULL, numChars);↩
if (!bstrVal)↩
{↩
throw kMemException;↩
// vt = VT_ERROR;↩
// scode = E_OUTOFMEMORY;↩
}↩
return bstrVal;↩
}↩
#define SET_PROP_FUNC(type, id, dest) \↩
CPropVariant& CPropVariant::operator=(type value) throw() \↩
{ if (vt != id) { InternalClear(); vt = id; } \↩
dest = value; return *this; }↩
SET_PROP_FUNC(Byte, VT_UI1, bVal)↩
// SET_PROP_FUNC(Int16, VT_I2, iVal)↩
SET_PROP_FUNC(Int32, VT_I4, lVal)↩
SET_PROP_FUNC(UInt32, VT_UI4, ulVal)↩
SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)↩
SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)↩
SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)↩
HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()↩
{↩
switch (prop->vt)↩
{↩
case VT_EMPTY:↩
case VT_UI1:↩
case VT_I1:↩
case VT_I2:↩
case VT_UI2:↩
case VT_BOOL:↩
case VT_I4:↩
case VT_UI4:↩
case VT_R4:↩
case VT_INT:↩
case VT_UINT:↩
case VT_ERROR:↩
case VT_FILETIME:↩
case VT_UI8:↩
case VT_R8:↩
case VT_CY:↩
case VT_DATE:↩
prop->vt = VT_EMPTY;↩
prop->wReserved1 = 0;↩
prop->wReserved2 = 0;↩
prop->wReserved3 = 0;↩
prop->uhVal.QuadPart = 0;↩
return S_OK;↩
}↩
return ::VariantClear((VARIANTARG *)prop);↩
// return ::PropVariantClear(prop);↩
// PropVariantClear can clear VT_BLOB.↩
}↩
HRESULT CPropVariant::Clear() throw()↩
{↩
if (vt == VT_EMPTY)↩
return S_OK;↩
return PropVariant_Clear(this);↩
}↩
HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()↩
{↩
::VariantClear((tagVARIANT *)this);↩
switch (pSrc->vt)↩
{↩
case VT_UI1:↩
case VT_I1:↩
case VT_I2:↩
case VT_UI2:↩
case VT_BOOL:↩
case VT_I4:↩
case VT_UI4:↩
case VT_R4:↩
case VT_INT:↩
case VT_UINT:↩
case VT_ERROR:↩
case VT_FILETIME:↩
case VT_UI8:↩
case VT_R8:↩
case VT_CY:↩
case VT_DATE:↩
memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));↩
return S_OK;↩
}↩
return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));↩
}↩
HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()↩
{↩
HRESULT hr = Clear();↩
if (FAILED(hr))↩
return hr;↩
memcpy(this, pSrc, sizeof(PROPVARIANT));↩
pSrc->vt = VT_EMPTY;↩
return S_OK;↩
}↩
HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()↩
{↩
if (pDest->vt != VT_EMPTY)↩
{↩
HRESULT hr = PropVariant_Clear(pDest);↩
if (FAILED(hr))↩
return hr;↩
}↩
memcpy(pDest, this, sizeof(PROPVARIANT));↩
vt = VT_EMPTY;↩
return S_OK;↩
}↩
HRESULT CPropVariant::InternalClear() throw()↩
{↩
if (vt == VT_EMPTY)↩
return S_OK;↩
HRESULT hr = Clear();↩
if (FAILED(hr))↩
{↩
vt = VT_ERROR;↩
scode = hr;↩
}↩
return hr;↩
}↩
void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)↩
{↩
HRESULT hr = Copy(pSrc);↩
if (FAILED(hr))↩
{↩
if (hr == E_OUTOFMEMORY)↩
throw kMemException;↩
vt = VT_ERROR;↩
scode = hr;↩
}↩
}↩
int CPropVariant::Compare(const CPropVariant &a) throw()↩
{↩
if (vt != a.vt)↩
return MyCompare(vt, a.vt);↩
switch (vt)↩
{↩
case VT_EMPTY: return 0;↩
// case VT_I1: return MyCompare(cVal, a.cVal);↩
case VT_UI1: return MyCompare(bVal, a.bVal);↩
case VT_I2: return MyCompare(iVal, a.iVal);↩
case VT_UI2: return MyCompare(uiVal, a.uiVal);↩
case VT_I4: return MyCompare(lVal, a.lVal);↩
case VT_UI4: return MyCompare(ulVal, a.ulVal);↩
// case VT_UINT: return MyCompare(uintVal, a.uintVal);↩
case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);↩
case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);↩
case VT_BOOL: return -MyCompare(boolVal, a.boolVal);↩
case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime);↩
case VT_BSTR: return 0; // Not implemented↩
default: return 0;↩
}↩
}↩
}}↩