1370b324cSopenharmony_ci// Windows/PropVariant.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../Common/Defs.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "PropVariant.h" 8370b324cSopenharmony_ci 9370b324cSopenharmony_cinamespace NWindows { 10370b324cSopenharmony_cinamespace NCOM { 11370b324cSopenharmony_ci 12370b324cSopenharmony_ciBSTR AllocBstrFromAscii(const char *s) throw() 13370b324cSopenharmony_ci{ 14370b324cSopenharmony_ci if (!s) 15370b324cSopenharmony_ci return NULL; 16370b324cSopenharmony_ci UINT len = (UINT)strlen(s); 17370b324cSopenharmony_ci BSTR p = ::SysAllocStringLen(NULL, len); 18370b324cSopenharmony_ci if (p) 19370b324cSopenharmony_ci { 20370b324cSopenharmony_ci for (UINT i = 0; i <= len; i++) 21370b324cSopenharmony_ci p[i] = (Byte)s[i]; 22370b324cSopenharmony_ci } 23370b324cSopenharmony_ci return p; 24370b324cSopenharmony_ci} 25370b324cSopenharmony_ci 26370b324cSopenharmony_ciHRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw() 27370b324cSopenharmony_ci{ 28370b324cSopenharmony_ci p->bstrVal = ::SysAllocStringLen(NULL, numChars); 29370b324cSopenharmony_ci if (!p->bstrVal) 30370b324cSopenharmony_ci { 31370b324cSopenharmony_ci p->vt = VT_ERROR; 32370b324cSopenharmony_ci p->scode = E_OUTOFMEMORY; 33370b324cSopenharmony_ci return E_OUTOFMEMORY; 34370b324cSopenharmony_ci } 35370b324cSopenharmony_ci p->vt = VT_BSTR; 36370b324cSopenharmony_ci return S_OK; 37370b324cSopenharmony_ci} 38370b324cSopenharmony_ci 39370b324cSopenharmony_ciHRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw() 40370b324cSopenharmony_ci{ 41370b324cSopenharmony_ci p->bstrVal = AllocBstrFromAscii(s); 42370b324cSopenharmony_ci if (p->bstrVal) 43370b324cSopenharmony_ci { 44370b324cSopenharmony_ci p->vt = VT_BSTR; 45370b324cSopenharmony_ci return S_OK; 46370b324cSopenharmony_ci } 47370b324cSopenharmony_ci p->vt = VT_ERROR; 48370b324cSopenharmony_ci p->scode = E_OUTOFMEMORY; 49370b324cSopenharmony_ci return E_OUTOFMEMORY; 50370b324cSopenharmony_ci} 51370b324cSopenharmony_ci 52370b324cSopenharmony_ciCPropVariant::CPropVariant(const PROPVARIANT &varSrc) 53370b324cSopenharmony_ci{ 54370b324cSopenharmony_ci vt = VT_EMPTY; 55370b324cSopenharmony_ci InternalCopy(&varSrc); 56370b324cSopenharmony_ci} 57370b324cSopenharmony_ci 58370b324cSopenharmony_ciCPropVariant::CPropVariant(const CPropVariant &varSrc) 59370b324cSopenharmony_ci{ 60370b324cSopenharmony_ci vt = VT_EMPTY; 61370b324cSopenharmony_ci InternalCopy(&varSrc); 62370b324cSopenharmony_ci} 63370b324cSopenharmony_ci 64370b324cSopenharmony_ciCPropVariant::CPropVariant(BSTR bstrSrc) 65370b324cSopenharmony_ci{ 66370b324cSopenharmony_ci vt = VT_EMPTY; 67370b324cSopenharmony_ci *this = bstrSrc; 68370b324cSopenharmony_ci} 69370b324cSopenharmony_ci 70370b324cSopenharmony_ciCPropVariant::CPropVariant(LPCOLESTR lpszSrc) 71370b324cSopenharmony_ci{ 72370b324cSopenharmony_ci vt = VT_EMPTY; 73370b324cSopenharmony_ci *this = lpszSrc; 74370b324cSopenharmony_ci} 75370b324cSopenharmony_ci 76370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) 77370b324cSopenharmony_ci{ 78370b324cSopenharmony_ci InternalCopy(&varSrc); 79370b324cSopenharmony_ci return *this; 80370b324cSopenharmony_ci} 81370b324cSopenharmony_ci 82370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) 83370b324cSopenharmony_ci{ 84370b324cSopenharmony_ci InternalCopy(&varSrc); 85370b324cSopenharmony_ci return *this; 86370b324cSopenharmony_ci} 87370b324cSopenharmony_ci 88370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(BSTR bstrSrc) 89370b324cSopenharmony_ci{ 90370b324cSopenharmony_ci *this = (LPCOLESTR)bstrSrc; 91370b324cSopenharmony_ci return *this; 92370b324cSopenharmony_ci} 93370b324cSopenharmony_ci 94370b324cSopenharmony_cistatic const char * const kMemException = "out of memory"; 95370b324cSopenharmony_ci 96370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) 97370b324cSopenharmony_ci{ 98370b324cSopenharmony_ci InternalClear(); 99370b324cSopenharmony_ci vt = VT_BSTR; 100370b324cSopenharmony_ci wReserved1 = 0; 101370b324cSopenharmony_ci bstrVal = ::SysAllocString(lpszSrc); 102370b324cSopenharmony_ci if (!bstrVal && lpszSrc) 103370b324cSopenharmony_ci { 104370b324cSopenharmony_ci throw kMemException; 105370b324cSopenharmony_ci // vt = VT_ERROR; 106370b324cSopenharmony_ci // scode = E_OUTOFMEMORY; 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci return *this; 109370b324cSopenharmony_ci} 110370b324cSopenharmony_ci 111370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const UString &s) 112370b324cSopenharmony_ci{ 113370b324cSopenharmony_ci InternalClear(); 114370b324cSopenharmony_ci vt = VT_BSTR; 115370b324cSopenharmony_ci wReserved1 = 0; 116370b324cSopenharmony_ci bstrVal = ::SysAllocStringLen(s, s.Len()); 117370b324cSopenharmony_ci if (!bstrVal) 118370b324cSopenharmony_ci throw kMemException; 119370b324cSopenharmony_ci return *this; 120370b324cSopenharmony_ci} 121370b324cSopenharmony_ci 122370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const UString2 &s) 123370b324cSopenharmony_ci{ 124370b324cSopenharmony_ci /* 125370b324cSopenharmony_ci if (s.IsEmpty()) 126370b324cSopenharmony_ci *this = L""; 127370b324cSopenharmony_ci else 128370b324cSopenharmony_ci */ 129370b324cSopenharmony_ci { 130370b324cSopenharmony_ci InternalClear(); 131370b324cSopenharmony_ci vt = VT_BSTR; 132370b324cSopenharmony_ci wReserved1 = 0; 133370b324cSopenharmony_ci bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len()); 134370b324cSopenharmony_ci if (!bstrVal) 135370b324cSopenharmony_ci throw kMemException; 136370b324cSopenharmony_ci /* SysAllocStringLen probably appends a null-terminating character for NULL string. 137370b324cSopenharmony_ci But it doesn't specified in MSDN. 138370b324cSopenharmony_ci But we suppose that it works 139370b324cSopenharmony_ci 140370b324cSopenharmony_ci if (!s.GetRawPtr()) 141370b324cSopenharmony_ci { 142370b324cSopenharmony_ci *bstrVal = 0; 143370b324cSopenharmony_ci } 144370b324cSopenharmony_ci */ 145370b324cSopenharmony_ci 146370b324cSopenharmony_ci /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL) 147370b324cSopenharmony_ci pointers to this function causes an unexpected termination of the application. 148370b324cSopenharmony_ci Is it safe? Maybe we must chamnge the code for that case ? */ 149370b324cSopenharmony_ci } 150370b324cSopenharmony_ci return *this; 151370b324cSopenharmony_ci} 152370b324cSopenharmony_ci 153370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(const char *s) 154370b324cSopenharmony_ci{ 155370b324cSopenharmony_ci InternalClear(); 156370b324cSopenharmony_ci vt = VT_BSTR; 157370b324cSopenharmony_ci wReserved1 = 0; 158370b324cSopenharmony_ci bstrVal = AllocBstrFromAscii(s); 159370b324cSopenharmony_ci if (!bstrVal) 160370b324cSopenharmony_ci { 161370b324cSopenharmony_ci throw kMemException; 162370b324cSopenharmony_ci // vt = VT_ERROR; 163370b324cSopenharmony_ci // scode = E_OUTOFMEMORY; 164370b324cSopenharmony_ci } 165370b324cSopenharmony_ci return *this; 166370b324cSopenharmony_ci} 167370b324cSopenharmony_ci 168370b324cSopenharmony_ciCPropVariant& CPropVariant::operator=(bool bSrc) throw() 169370b324cSopenharmony_ci{ 170370b324cSopenharmony_ci if (vt != VT_BOOL) 171370b324cSopenharmony_ci { 172370b324cSopenharmony_ci InternalClear(); 173370b324cSopenharmony_ci vt = VT_BOOL; 174370b324cSopenharmony_ci } 175370b324cSopenharmony_ci boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; 176370b324cSopenharmony_ci return *this; 177370b324cSopenharmony_ci} 178370b324cSopenharmony_ci 179370b324cSopenharmony_ciBSTR CPropVariant::AllocBstr(unsigned numChars) 180370b324cSopenharmony_ci{ 181370b324cSopenharmony_ci if (vt != VT_EMPTY) 182370b324cSopenharmony_ci InternalClear(); 183370b324cSopenharmony_ci vt = VT_BSTR; 184370b324cSopenharmony_ci wReserved1 = 0; 185370b324cSopenharmony_ci bstrVal = ::SysAllocStringLen(NULL, numChars); 186370b324cSopenharmony_ci if (!bstrVal) 187370b324cSopenharmony_ci { 188370b324cSopenharmony_ci throw kMemException; 189370b324cSopenharmony_ci // vt = VT_ERROR; 190370b324cSopenharmony_ci // scode = E_OUTOFMEMORY; 191370b324cSopenharmony_ci } 192370b324cSopenharmony_ci return bstrVal; 193370b324cSopenharmony_ci} 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci#define SET_PROP_id_dest(id, dest) \ 196370b324cSopenharmony_ci if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0; 197370b324cSopenharmony_ci 198370b324cSopenharmony_civoid CPropVariant::Set_Int32(Int32 value) throw() 199370b324cSopenharmony_ci{ 200370b324cSopenharmony_ci SET_PROP_id_dest(VT_I4, lVal) 201370b324cSopenharmony_ci} 202370b324cSopenharmony_ci 203370b324cSopenharmony_civoid CPropVariant::Set_Int64(Int64 value) throw() 204370b324cSopenharmony_ci{ 205370b324cSopenharmony_ci SET_PROP_id_dest(VT_I8, hVal.QuadPart) 206370b324cSopenharmony_ci} 207370b324cSopenharmony_ci 208370b324cSopenharmony_ci#define SET_PROP_FUNC(type, id, dest) \ 209370b324cSopenharmony_ci CPropVariant& CPropVariant::operator=(type value) throw() \ 210370b324cSopenharmony_ci { SET_PROP_id_dest(id, dest) return *this; } 211370b324cSopenharmony_ci 212370b324cSopenharmony_ciSET_PROP_FUNC(Byte, VT_UI1, bVal) 213370b324cSopenharmony_ci// SET_PROP_FUNC(Int16, VT_I2, iVal) 214370b324cSopenharmony_ci// SET_PROP_FUNC(Int32, VT_I4, lVal) 215370b324cSopenharmony_ciSET_PROP_FUNC(UInt32, VT_UI4, ulVal) 216370b324cSopenharmony_ciSET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) 217370b324cSopenharmony_ci// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) 218370b324cSopenharmony_ciSET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) 219370b324cSopenharmony_ci 220370b324cSopenharmony_ci#define CASE_SIMPLE_VT_VALUES \ 221370b324cSopenharmony_ci case VT_EMPTY: \ 222370b324cSopenharmony_ci case VT_BOOL: \ 223370b324cSopenharmony_ci case VT_FILETIME: \ 224370b324cSopenharmony_ci case VT_UI8: \ 225370b324cSopenharmony_ci case VT_UI4: \ 226370b324cSopenharmony_ci case VT_UI2: \ 227370b324cSopenharmony_ci case VT_UI1: \ 228370b324cSopenharmony_ci case VT_I8: \ 229370b324cSopenharmony_ci case VT_I4: \ 230370b324cSopenharmony_ci case VT_I2: \ 231370b324cSopenharmony_ci case VT_I1: \ 232370b324cSopenharmony_ci case VT_UINT: \ 233370b324cSopenharmony_ci case VT_INT: \ 234370b324cSopenharmony_ci case VT_NULL: \ 235370b324cSopenharmony_ci case VT_ERROR: \ 236370b324cSopenharmony_ci case VT_R4: \ 237370b324cSopenharmony_ci case VT_R8: \ 238370b324cSopenharmony_ci case VT_CY: \ 239370b324cSopenharmony_ci case VT_DATE: \ 240370b324cSopenharmony_ci 241370b324cSopenharmony_ci 242370b324cSopenharmony_ci/* 243370b324cSopenharmony_ci ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME) 244370b324cSopenharmony_ci So we handle VT_FILETIME and another simple types directly 245370b324cSopenharmony_ci we call system functions for VT_BSTR and for unknown typed 246370b324cSopenharmony_ci*/ 247370b324cSopenharmony_ci 248370b324cSopenharmony_ciCPropVariant::~CPropVariant() throw() 249370b324cSopenharmony_ci{ 250370b324cSopenharmony_ci switch ((unsigned)vt) 251370b324cSopenharmony_ci { 252370b324cSopenharmony_ci CASE_SIMPLE_VT_VALUES 253370b324cSopenharmony_ci // vt = VT_EMPTY; // it's optional 254370b324cSopenharmony_ci return; 255370b324cSopenharmony_ci } 256370b324cSopenharmony_ci ::VariantClear((tagVARIANT *)this); 257370b324cSopenharmony_ci} 258370b324cSopenharmony_ci 259370b324cSopenharmony_ciHRESULT PropVariant_Clear(PROPVARIANT *prop) throw() 260370b324cSopenharmony_ci{ 261370b324cSopenharmony_ci switch ((unsigned)prop->vt) 262370b324cSopenharmony_ci { 263370b324cSopenharmony_ci CASE_SIMPLE_VT_VALUES 264370b324cSopenharmony_ci prop->vt = VT_EMPTY; 265370b324cSopenharmony_ci break; 266370b324cSopenharmony_ci default: 267370b324cSopenharmony_ci { 268370b324cSopenharmony_ci const HRESULT res = ::VariantClear((VARIANTARG *)prop); 269370b324cSopenharmony_ci if (res != S_OK || prop->vt != VT_EMPTY) 270370b324cSopenharmony_ci return res; 271370b324cSopenharmony_ci break; 272370b324cSopenharmony_ci } 273370b324cSopenharmony_ci } 274370b324cSopenharmony_ci prop->wReserved1 = 0; 275370b324cSopenharmony_ci prop->wReserved2 = 0; 276370b324cSopenharmony_ci prop->wReserved3 = 0; 277370b324cSopenharmony_ci prop->uhVal.QuadPart = 0; 278370b324cSopenharmony_ci return S_OK; 279370b324cSopenharmony_ci} 280370b324cSopenharmony_ci 281370b324cSopenharmony_ciHRESULT CPropVariant::Clear() throw() 282370b324cSopenharmony_ci{ 283370b324cSopenharmony_ci if (vt == VT_EMPTY) 284370b324cSopenharmony_ci { 285370b324cSopenharmony_ci wReserved1 = 0; 286370b324cSopenharmony_ci return S_OK; 287370b324cSopenharmony_ci } 288370b324cSopenharmony_ci return PropVariant_Clear(this); 289370b324cSopenharmony_ci} 290370b324cSopenharmony_ci 291370b324cSopenharmony_ciHRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() 292370b324cSopenharmony_ci{ 293370b324cSopenharmony_ci Clear(); 294370b324cSopenharmony_ci switch ((unsigned)pSrc->vt) 295370b324cSopenharmony_ci { 296370b324cSopenharmony_ci CASE_SIMPLE_VT_VALUES 297370b324cSopenharmony_ci memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); 298370b324cSopenharmony_ci return S_OK; 299370b324cSopenharmony_ci } 300370b324cSopenharmony_ci return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc)); 301370b324cSopenharmony_ci} 302370b324cSopenharmony_ci 303370b324cSopenharmony_ci 304370b324cSopenharmony_ciHRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() 305370b324cSopenharmony_ci{ 306370b324cSopenharmony_ci const HRESULT hr = Clear(); 307370b324cSopenharmony_ci if (FAILED(hr)) 308370b324cSopenharmony_ci return hr; 309370b324cSopenharmony_ci // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); 310370b324cSopenharmony_ci *(PROPVARIANT *)this = *pSrc; 311370b324cSopenharmony_ci pSrc->vt = VT_EMPTY; 312370b324cSopenharmony_ci pSrc->wReserved1 = 0; 313370b324cSopenharmony_ci return S_OK; 314370b324cSopenharmony_ci} 315370b324cSopenharmony_ci 316370b324cSopenharmony_ciHRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw() 317370b324cSopenharmony_ci{ 318370b324cSopenharmony_ci if (pDest->vt != VT_EMPTY) 319370b324cSopenharmony_ci { 320370b324cSopenharmony_ci const HRESULT hr = PropVariant_Clear(pDest); 321370b324cSopenharmony_ci if (FAILED(hr)) 322370b324cSopenharmony_ci return hr; 323370b324cSopenharmony_ci } 324370b324cSopenharmony_ci // memcpy(pDest, this, sizeof(PROPVARIANT)); 325370b324cSopenharmony_ci *pDest = *(PROPVARIANT *)this; 326370b324cSopenharmony_ci vt = VT_EMPTY; 327370b324cSopenharmony_ci wReserved1 = 0; 328370b324cSopenharmony_ci return S_OK; 329370b324cSopenharmony_ci} 330370b324cSopenharmony_ci 331370b324cSopenharmony_ciHRESULT CPropVariant::InternalClear() throw() 332370b324cSopenharmony_ci{ 333370b324cSopenharmony_ci if (vt == VT_EMPTY) 334370b324cSopenharmony_ci { 335370b324cSopenharmony_ci wReserved1 = 0; 336370b324cSopenharmony_ci return S_OK; 337370b324cSopenharmony_ci } 338370b324cSopenharmony_ci const HRESULT hr = Clear(); 339370b324cSopenharmony_ci if (FAILED(hr)) 340370b324cSopenharmony_ci { 341370b324cSopenharmony_ci vt = VT_ERROR; 342370b324cSopenharmony_ci scode = hr; 343370b324cSopenharmony_ci } 344370b324cSopenharmony_ci return hr; 345370b324cSopenharmony_ci} 346370b324cSopenharmony_ci 347370b324cSopenharmony_civoid CPropVariant::InternalCopy(const PROPVARIANT *pSrc) 348370b324cSopenharmony_ci{ 349370b324cSopenharmony_ci const HRESULT hr = Copy(pSrc); 350370b324cSopenharmony_ci if (FAILED(hr)) 351370b324cSopenharmony_ci { 352370b324cSopenharmony_ci if (hr == E_OUTOFMEMORY) 353370b324cSopenharmony_ci throw kMemException; 354370b324cSopenharmony_ci vt = VT_ERROR; 355370b324cSopenharmony_ci scode = hr; 356370b324cSopenharmony_ci } 357370b324cSopenharmony_ci} 358370b324cSopenharmony_ci 359370b324cSopenharmony_ci 360370b324cSopenharmony_ciint CPropVariant::Compare(const CPropVariant &a) throw() 361370b324cSopenharmony_ci{ 362370b324cSopenharmony_ci if (vt != a.vt) 363370b324cSopenharmony_ci return MyCompare(vt, a.vt); 364370b324cSopenharmony_ci switch ((unsigned)vt) 365370b324cSopenharmony_ci { 366370b324cSopenharmony_ci case VT_EMPTY: return 0; 367370b324cSopenharmony_ci // case VT_I1: return MyCompare(cVal, a.cVal); 368370b324cSopenharmony_ci case VT_UI1: return MyCompare(bVal, a.bVal); 369370b324cSopenharmony_ci case VT_I2: return MyCompare(iVal, a.iVal); 370370b324cSopenharmony_ci case VT_UI2: return MyCompare(uiVal, a.uiVal); 371370b324cSopenharmony_ci case VT_I4: return MyCompare(lVal, a.lVal); 372370b324cSopenharmony_ci case VT_UI4: return MyCompare(ulVal, a.ulVal); 373370b324cSopenharmony_ci // case VT_UINT: return MyCompare(uintVal, a.uintVal); 374370b324cSopenharmony_ci case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); 375370b324cSopenharmony_ci case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); 376370b324cSopenharmony_ci case VT_BOOL: return -MyCompare(boolVal, a.boolVal); 377370b324cSopenharmony_ci case VT_FILETIME: 378370b324cSopenharmony_ci { 379370b324cSopenharmony_ci const int res = CompareFileTime(&filetime, &a.filetime); 380370b324cSopenharmony_ci if (res != 0) 381370b324cSopenharmony_ci return res; 382370b324cSopenharmony_ci const unsigned v1 = Get_Ns100(); 383370b324cSopenharmony_ci const unsigned v2 = a.Get_Ns100(); 384370b324cSopenharmony_ci return MyCompare(v1, v2); 385370b324cSopenharmony_ci } 386370b324cSopenharmony_ci case VT_BSTR: return 0; // Not implemented 387370b324cSopenharmony_ci default: return 0; 388370b324cSopenharmony_ci } 389370b324cSopenharmony_ci} 390370b324cSopenharmony_ci 391370b324cSopenharmony_ci}} 392