//+--------------------------------------------------------------------------- // // Function: VARIANTARGToIndex // // Synopsis: Converts a VARIANT to an index of type long. Sets the index to // -1 if the VARIANT type is bad or empty. // // Arguments: [pvarg] -- Variant to convert. // [plIndex -- Location to place index. // // Notes: Useful special case of VARIANTARGToCVar for reading array // indices. //---------------------------------------------------------------------------- HRESULT VARIANTARGToIndex(VARIANT* pvarg, long* plIndex) { HRESULT hr = S_OK; Assert(pvarg); *plIndex = -1; // Quick return for the common case if(V_VT(pvarg)==VT_I4 || V_VT(pvarg)==(VT_I4|VT_BYREF)) { *plIndex = (V_VT(pvarg)==VT_I4) ? V_I4(pvarg) : *V_I4REF(pvarg); return S_OK; } if (V_VT(pvarg)==VT_ERROR || V_VT(pvarg)==VT_EMPTY) { return S_OK; } // Must perform type corecion CVariant varNum; hr = VariantChangeTypeEx(&varNum, pvarg, LCID_SCRIPTING, 0, VT_I4); if(hr) { goto Cleanup; } Assert(V_VT(&varNum)==VT_I4 || V_VT(&varNum)==(VT_I4|VT_BYREF)); *plIndex = (V_VT(&varNum)==VT_I4) ? V_I4(&varNum) : *V_I4REF(&varNum); Cleanup: RRETURN(hr); }
HRESULT double_to_string(double n, jsstr_t **str) { const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0}; if(isnan(n)) { *str = jsstr_nan(); }else if(isinf(n)) { *str = jsstr_alloc(n<0 ? InfinityW : InfinityW+1); }else if(is_int32(n)) { *str = int_to_string(n); }else { VARIANT strv, v; HRESULT hres; /* FIXME: Don't use VariantChangeTypeEx */ V_VT(&v) = VT_R8; V_R8(&v) = n; V_VT(&strv) = VT_EMPTY; hres = VariantChangeTypeEx(&strv, &v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); if(FAILED(hres)) return hres; *str = jsstr_alloc(V_BSTR(&strv)); SysFreeString(V_BSTR(&strv)); } return *str ? S_OK : E_OUTOFMEMORY; }
/* ECMA-262 3rd Edition 9.8 */ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) { const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; const WCHAR nullW[] = {'n','u','l','l',0}; const WCHAR trueW[] = {'t','r','u','e',0}; const WCHAR falseW[] = {'f','a','l','s','e',0}; switch(V_VT(v)) { case VT_EMPTY: *str = SysAllocString(undefinedW); break; case VT_NULL: *str = SysAllocString(nullW); break; case VT_I4: *str = int_to_bstr(V_I4(v)); break; case VT_R8: { VARIANT strv; HRESULT hres; V_VT(&strv) = VT_EMPTY; hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); if(FAILED(hres)) return hres; *str = V_BSTR(&strv); return S_OK; } case VT_BSTR: *str = SysAllocString(V_BSTR(v)); break; case VT_DISPATCH: { VARIANT prim; HRESULT hres; hres = to_primitive(ctx, v, ei, &prim); if(FAILED(hres)) return hres; hres = to_string(ctx, &prim, ei, str); VariantClear(&prim); return hres; } case VT_BOOL: *str = SysAllocString(V_BOOL(v) ? trueW : falseW); break; default: FIXME("unsupported vt %d\n", V_VT(v)); return E_NOTIMPL; } return *str ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface); WCHAR *pwszValue; DWORD dwType, cbData; LONG res; VARTYPE vtDst = V_VT(pVar); HRESULT hr = S_OK; TRACE("(iface=%p, pwszPropName=%s, pVar=%p, pErrorLog=%p)\n", iface, debugstr_w(pwszPropName), pVar, pErrorLog); res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, NULL, &cbData); if (res != ERROR_SUCCESS) return E_INVALIDARG; pwszValue = shdocvw_alloc(cbData); if (!pwszValue) return E_OUTOFMEMORY; res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, (LPBYTE)pwszValue, &cbData); if (res != ERROR_SUCCESS) { shdocvw_free(pwszValue); return E_INVALIDARG; } V_VT(pVar) = VT_BSTR; V_BSTR(pVar) = SysAllocString(pwszValue); shdocvw_free(pwszValue); if (vtDst != VT_BSTR) { hr = VariantChangeTypeEx(pVar, pVar, LOCALE_SYSTEM_DEFAULT, 0, vtDst); if (FAILED(hr)) SysFreeString(V_BSTR(pVar)); } return hr; }
HRESULT __fastcall CAGCEventDef::ParseState_ProcessVar(CAGCEventDef::XParseData& data) { // Get the variable as a VT_BSTR variant UINT cch = data.m_pszVarEnd - data.m_pszVarBegin; CComVariant varKey; V_VT(&varKey) = VT_BSTR; V_BSTR(&varKey) = ::SysAllocStringLen(data.m_pszVarBegin, cch); if (!V_BSTR(&varKey)) { data.m_pfnNextState = NULL; return E_OUTOFMEMORY; } // Lookup the variable in the event's properties CComVariant varValue; HRESULT hr = data.m_pEvent->get_Property(&varKey, &varValue); if (FAILED(hr)) { data.m_pfnNextState = NULL; return hr; } // Just write the variable name as-is if it doesn't exist in the event if (VT_EMPTY == V_VT(&varValue)) { // Include the leading and trailing '%' characters --data.m_pszVarBegin; ++data.m_pszVarEnd; if (data.m_pParams) { cch = data.m_pszVarEnd - data.m_pszVarBegin; BSTR bstrValue = SysAllocStringLen(data.m_pszVarBegin, cch); if (!bstrValue) { data.m_pfnNextState = NULL; return E_OUTOFMEMORY; } data.m_pParams->push_back(bstrValue); } return ParseState_WriteVar(data); } // Convert the variant to a string if (VT_BSTR != V_VT(&varValue)) { VariantChangeTypeEx(&varValue, &varValue, GetThreadLocale(), VARIANT_LOCALBOOL | VARIANT_ALPHABOOL, VT_BSTR); if (VT_BSTR != V_VT(&varValue)) { data.m_pfnNextState = ParseState_Base; return S_OK; } } UINT cchValue = BSTRLen(V_BSTR(&varValue)); if (!cchValue) { if (data.m_pParams) { BSTR bstrValue = SysAllocString(L""); if (!bstrValue) { data.m_pfnNextState = NULL; return E_OUTOFMEMORY; } data.m_pParams->push_back(bstrValue); } data.m_pfnNextState = ParseState_Base; return S_OK; } // Write the value string data.m_pszVarBegin = V_BSTR(&varValue); data.m_pszVarEnd = data.m_pszVarBegin + cchValue; RETURN_FAILED(ParseState_WriteVar(data)); if (data.m_pParams) { data.m_pParams->push_back(V_BSTR(&varValue)); V_VT(&varValue) = VT_EMPTY; // Detaches the BSTR from the VARIANT } // Indicate success return S_OK; }
static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar) { HRESULT hr = S_OK; if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) { long len = RSTRING_LEN(val); void *pdest = NULL; SAFEARRAY *p = NULL; SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len); if (!psa) { rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector"); } hr = SafeArrayAccessData(psa, &pdest); if (SUCCEEDED(hr)) { memcpy(pdest, RSTRING_PTR(val), len); SafeArrayUnaccessData(psa); V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF); p = V_ARRAY(&(pvar->realvar)); if (p != NULL) { SafeArrayDestroy(p); } V_ARRAY(&(pvar->realvar)) = psa; if (vt & VT_BYREF) { V_VT(&(pvar->var)) = vt; V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } else { if (psa) SafeArrayDestroy(psa); } } else if (vt & VT_ARRAY) { if (val == Qnil) { V_VT(&(pvar->var)) = vt; if (vt & VT_BYREF) { V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } } else { hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); if (SUCCEEDED(hr)) { if (vt & VT_BYREF) { V_VT(&(pvar->var)) = vt; V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar))); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } } #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) { ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF)); ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF)); V_VT(&(pvar->var)) = vt; if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } #endif } else if ( (vt & ~VT_BYREF) == VT_ERROR) { ole_val2variant_err(val, &(pvar->realvar)); if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } } else { if (val == Qnil) { V_VT(&(pvar->var)) = vt; if (vt == (VT_BYREF | VT_VARIANT)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else { V_VT(&(pvar->realvar)) = vt & ~VT_BYREF; if (vt & VT_BYREF) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } } } else { ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF)); if (vt == (VT_BYREF | VT_VARIANT)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } else if (vt & VT_BYREF) { if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) { hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar), cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF)); } if (SUCCEEDED(hr)) { ole_set_byref(&(pvar->realvar), &(pvar->var), vt); } } else { if (vt == V_VT(&(pvar->realvar))) { hr = VariantCopy(&(pvar->var), &(pvar->realvar)); } else { hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), cWIN32OLE_lcid, 0, vt); } } } } if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to change type"); } }
HRESULT VariantChangeTypeSpecial(VARIANT* pvargDest, VARIANT* pVArg, VARTYPE vt, IServiceProvider* pSrvProvider/*=NULL*/, DWORD dwFlags/*=0*/) { HRESULT hr; IVariantChangeType* pVarChangeType = NULL; if(pSrvProvider) { hr = pSrvProvider->QueryService(SID_VariantConversion, IID_IVariantChangeType, (void**)&pVarChangeType); if(hr) { goto OldWay; } // Use script engine conversion routine. hr = pVarChangeType->ChangeType(pvargDest, pVArg, 0, vt); if(!hr) { goto Cleanup; // ChangeType suceeded we're done... } } // Fall back to our tried & trusted type coercions OldWay: hr = S_OK; if(vt==VT_BSTR && V_VT(pVArg)==VT_NULL) { // Converting a NULL to BSTR V_VT(pvargDest) = VT_BSTR; hr = FormsAllocString(_T("null"), &V_BSTR(pvargDest)); goto Cleanup; } else if(vt==VT_BSTR && V_VT(pVArg)==VT_EMPTY) { // Converting "undefined" to BSTR V_VT(pvargDest) = VT_BSTR; hr = FormsAllocString(_T("undefined"), &V_BSTR(pvargDest)); goto Cleanup; } else if(vt==VT_BOOL && V_VT(pVArg)==VT_BSTR) { // Converting from BSTR to BOOL // To match Navigator compatibility empty strings implies false when // assigned to a boolean type any other string implies true. V_VT(pvargDest) = VT_BOOL; V_BOOL(pvargDest) = FormsStringLen(V_BSTR(pVArg))==0 ? VARIANT_FALSE : VARIANT_TRUE; goto Cleanup; } else if(V_VT(pVArg)==VT_BOOL && vt==VT_BSTR) { // Converting from BOOL to BSTR // To match Nav we either get "true" or "false" V_VT(pvargDest) = VT_BSTR; hr = FormsAllocString( V_BOOL(pVArg)==VARIANT_TRUE?_T("true"):_T("false"), &V_BSTR(pvargDest)); goto Cleanup; } // If we're converting R4 or R8 to a string then we need special handling to // map Nan and +/-Inf. else if(vt==VT_BSTR && (V_VT(pVArg)==VT_R8||V_VT(pVArg)==VT_R4)) { double dblValue = V_VT(pVArg)==VT_R8 ? V_R8(pVArg) : (double)(V_R4(pVArg)); // Infinity or NAN? if(!isFinite(dblValue)) { if(isNAN(dblValue)) { // NAN hr = FormsAllocStringW(_T("NaN"), &(V_BSTR(pvargDest))); } else { // Infinity hr = FormsAllocStringW((dblValue<0)?_T("-Infinity"):_T("Infinity"), &(V_BSTR(pvargDest))); } } else { goto DefaultConvert; } // Any error from allocating string? if(hr) { goto Cleanup; } V_VT(pvargDest) = vt; goto Cleanup; } DefaultConvert: // Default VariantChangeTypeEx. // VARIANT_NOUSEROVERRIDE flag is undocumented flag that tells OLEAUT to convert to the lcid // given. Without it the conversion is done to user localeid hr = VariantChangeTypeEx(pvargDest, pVArg, LCID_SCRIPTING, dwFlags|VARIANT_NOUSEROVERRIDE, vt); if(hr == DISP_E_TYPEMISMATCH) { if(V_VT(pVArg) == VT_NULL) { hr = S_OK; switch(vt) { case VT_BOOL: V_BOOL(pvargDest) = VARIANT_FALSE; V_VT(pvargDest) = VT_BOOL; break; // For NS compatability - NS treats NULL args as 0 default: V_I4(pvargDest)=0; break; } } else if(V_VT(pVArg) == VT_DISPATCH) { // Nav compatability - return the string [object] or null V_VT(pvargDest) = VT_BSTR; hr = FormsAllocString((V_DISPATCH(pVArg))?_T("[object]"):_T("null"), &V_BSTR(pvargDest)); } else if(V_VT(pVArg)==VT_BSTR && (V_BSTR(pVArg) && ((V_BSTR(pVArg))[0]==_T('\0')) ||!V_BSTR(pVArg)) && (vt==VT_I4 || vt==VT_I2 || vt==VT_UI2||vt==VT_UI4 || vt==VT_I8||vt==VT_UI8 || vt==VT_INT || vt==VT_UINT)) { // Converting empty string to integer => Zero hr = S_OK; V_VT(pvargDest) = vt; V_I4(pvargDest) = 0; goto Cleanup; } } else if(hr==DISP_E_OVERFLOW && vt==VT_I4 && (V_VT(pVArg)==VT_R8 || V_VT(pVArg)==VT_R4)) { // Nav compatability - return MAXLONG on overflow V_VT(pvargDest) = VT_I4; V_I4(pvargDest) = MAXLONG; hr = S_OK; goto Cleanup; } // To match Navigator change any scientific notation E to e. if(!hr && (vt==VT_BSTR && (V_VT(pVArg)==VT_R8 || V_VT(pVArg)==VT_R4))) { TCHAR* pENotation; pENotation = _tcschr(V_BSTR(pvargDest), _T('E')); if(pENotation) { *pENotation = _T('e'); } } Cleanup: ReleaseInterface(pVarChangeType); RRETURN(hr); }
void CXTPCalendarCustomProperties::_Load(CXTPPropExchange* pPX) { if (!pPX || !pPX->IsLoading()) { ASSERT(FALSE); return; } m_mapProperties.RemoveAll(); CXTPPropExchangeSection secProps(pPX->GetSection(_T("CustomProperties"))); long nVersion; PX_Long(&secProps, _T("Version"), nVersion, XTP_CUSTOM_PROP_DATA_VER); if (nVersion != XTP_CUSTOM_PROP_DATA_VER) { TRACE(_T("ERROR! XTPCalendarCustomProperties: Unsupported data file version. (%d) \n"), nVersion); return; } CXTPPropExchangeEnumeratorPtr pEnumerator(secProps->GetEnumerator(_T("CustomProperty"))); POSITION posStorage = pEnumerator->GetPosition(); while (posStorage) { CString strName; COleVariant varValue; CXTPPropExchangeSection secProp(pEnumerator->GetNext(posStorage)); PX_String(&secProp, _T("Name"), strName); PX_Variant(&secProp, _T("Value"), varValue, COleVariant((long)0)); long lVt; PX_Long(&secProp, _T("VariantType"), lVt, VT_EMPTY); if (lVt != VT_EMPTY && varValue.vt != lVt) { LCID lcidID = pPX->m_lcidDateTime; if (lcidID == XTP_LOCALE_ISO8601) { lcidID = LOCALE_NEUTRAL; } COleVariant varValue2; HRESULT hr = VariantChangeTypeEx(&varValue2, &varValue, lcidID, 0, (VARTYPE)lVt); if (FAILED(hr)) { hr = VariantChangeType(&varValue2, &varValue, 0, (VARTYPE)lVt); } if (FAILED(hr)) { hr = VariantChangeType(&varValue2, &varValue, VARIANT_NOUSEROVERRIDE, (VARTYPE)lVt); } if (SUCCEEDED(hr)) { varValue = varValue2; } else if (varValue.vt == VT_BSTR && (lVt == VT_R4 || lVt == VT_R8 || lVt == VT_DATE)) { CString strValue = varValue.bstrVal; strValue.Replace(_T(','), _T('.')); double dblVal = atof(XTP_CT2CA(strValue)); if (lVt == VT_R4) { varValue = (float)dblVal; } else if (lVt == VT_R8) { varValue = (double)dblVal; } else if (lVt == VT_DATE) { varValue = COleDateTime((DATE)dblVal); } } else { ASSERT(FALSE); } } SetProperty(strName, varValue); } }
//--------------------------------------------------------------------------- HRESULT GetRegistryKeyValue( HKEY RootKey, const wchar_t * KeyName, const wchar_t * Name, VARIANT * Result) { HRESULT hr = E_FAIL; HKEY hkey; DWORD err; err = RegOpenKeyExW(RootKey,KeyName,0,KEY_READ,&hkey); if( err == ERROR_SUCCESS ){ DWORD ValueType, ValueSize, sLen; err = RegQueryValueExW(hkey,Name,NULL,&ValueType,NULL,&ValueSize); if( err == ERROR_SUCCESS ){ PBYTE pValueData = (PBYTE) malloc(ValueSize); if( pValueData == NULL ){ err = ERROR_NOT_ENOUGH_MEMORY; } else { err = RegQueryValueExW(hkey,Name,NULL,&ValueType,pValueData,&ValueSize); if( err == ERROR_SUCCESS ){ BSTR sValue = NULL; switch( ValueType ){ case REG_BINARY : break; case REG_DWORD : if( SUCCEEDED(VariantChangeTypeEx(Result,Result,0,0,VT_I4)) ){ V_I4(Result) = *(DWORD *) pValueData; hr = S_OK; } break; case REG_EXPAND_SZ : sLen = ExpandEnvironmentStringsW((LPCWSTR) pValueData,sValue,0); if( sLen == 0 ){ err = GetLastError(); } else { sValue = SysAllocStringLen(NULL,sLen - 1); if( sValue == NULL ){ err = ERROR_NOT_ENOUGH_MEMORY; } else { ExpandEnvironmentStringsW((LPCWSTR) pValueData,sValue,sLen); if( SUCCEEDED(VariantChangeTypeEx(Result,Result,0,0,VT_EMPTY)) ){ V_BSTR(Result) = sValue; V_VT(Result) = VT_BSTR; hr = S_OK; sValue = NULL; } SysFreeString(sValue); } } /*Val.resize(ExpandEnvironmentStringsW((LPCWSTR) pValueData,Val.c_str(),0) + 1); ExpandEnvironmentStringsW((LPCWSTR) pValueData,Val.c_str(),Val.strlen()); Val.resize(wcslen(Val.c_str()));*/ break; case REG_LINK : case REG_MULTI_SZ : case REG_NONE : case REG_RESOURCE_LIST : hr = E_FAIL; break; case REG_SZ : sLen = (DWORD) wcslen((LPCWSTR) pValueData); sValue = SysAllocStringLen(NULL,sLen); if( sValue == NULL ){ err = ERROR_NOT_ENOUGH_MEMORY; } else { if( SUCCEEDED(VariantChangeTypeEx(Result,Result,0,0,VT_EMPTY)) ){ V_BSTR(Result) = sValue; V_VT(Result) = VT_BSTR; hr = S_OK; sValue = NULL; } SysFreeString(sValue); } /*Val = (wchar_t *) pValueData;*/ break; } } free(pValueData); } } RegCloseKey(hkey); } SetLastError(err); return hr; }
HRESULT CTCPropBagOnRegKey::_WriteVariant(CRegKey& key, const _bstr_t& strValueName, VARIANT* pVar) { // Check for an array if (V_ISARRAY(pVar)) return WriteSafeArray(key, strValueName, pVar); // Write the value to the registry based on the VARIANT type switch (V_VT(pVar)) { // Empty variant is written as nothing case VT_EMPTY: key.DeleteValue(strValueName); key.RecurseDeleteKey(strValueName); break; // Integer types are written as a REG_DWORD value case VT_I1: case VT_I2: case VT_I4: case VT_UI1: case VT_UI2: case VT_ERROR: { // Coerce the value to a VT_UI4 VariantChangeTypeEx(pVar, pVar, GetThreadLocale(), m_wChangeTypeFlags, VT_UI4); // Fall thru to next case } case VT_UI4: { // Write the REG_DWORD value to the registry key.RecurseDeleteKey(strValueName); key.WriteDWord(strValueName, V_UI4(pVar)); break; } // BOOL's, float types and strings are written as a REG_SZ value case VT_R4: case VT_R8: case VT_CY: case VT_DATE: case VT_DECIMAL: case VT_BOOL: { // Coerce the value to a VT_BSTR VariantChangeTypeEx(pVar, pVar, GetThreadLocale(), m_wChangeTypeFlags, VT_BSTR); // Fall thru to next case } case VT_BSTR: { // Write the REG_SZ value to the registry key.RecurseDeleteKey(strValueName); key.WriteString(strValueName, V_BSTR(pVar)); break; } // Objects written as REG_BINARY, if they don't support IPersistPropertyBag case VT_UNKNOWN: case VT_DISPATCH: { // Attempt first to save the object property using IPersistPropertyBag key.DeleteValue(strValueName); key.RecurseDeleteKey(strValueName); CComObjectStack<CTCPropBagOnRegKey> bag; bag.Init(key, _bstr_t(), this); HRESULT hr = bag.SaveObject(strValueName, V_UNKNOWN(pVar), FALSE, TRUE); if (FAILED(hr)) { TRACE1("CTCPropBagOnRegKey::_WriteVariant: Saving object property \"%s\" as a binary value\n", strValueName); // Create a CArchive on a CMemFile CMemFile file; CArchive ar(&file, CArchive::store, 0); // Archive the variant to the CArchive and close it CComVariant v(pVar); ar << v; ar.Close(); // Write the REG_BINARY value to the registry int cbData = file.GetLength(); BYTE* pData = file.Detach(); key.RecurseDeleteKey(strValueName); key.WriteBinary(strValueName, pData, cbData); file.Attach(pData, cbData); } break; } default: TRACE1("CTCPropBagOnRegKey::_WriteVariant(\"%ls\"): ", strValueName); TRACE2("Unsupported variant type 0x%02X (%d)\n", UINT(V_VT(pVar)), UINT(V_VT(pVar))); return E_FAIL; } // Indicate success return S_OK; }
HRESULT CTCPropBagOnRegKey::_ReadVariant(CRegKey& key, const _bstr_t& strValueName, VARIANT* pVar, IErrorLog* pErrorLog) { // Create an empty CComVariant object CComVariant v; // Read the specified property from the registry DWORD nType = 0; int cbData = 0; if (key.QueryValue(strValueName, nType, cbData)) // Name is a value? { // Read property in registry value as a VARIANT HRESULT hr = _ReadVariantFromValue(key, strValueName, nType, cbData, v, pErrorLog); if (FAILED(hr)) return hr; } else if (key.Exists(strValueName)) // Name is a subkey? { // Read property on subkey as specified by subkey's VariantType value HRESULT hr = E_FAIL; if (IsSubkeySafeArray(key, strValueName)) hr = ReadSafeArray(key, strValueName, pVar, pErrorLog); else if (IsSubkeyObject(key, strValueName)) { // Read property on subkey as an object CComObjectStack<CTCPropBagOnRegKey> bag; bag.Init(key, _bstr_t(), this); V_VT(&v) = VT_UNKNOWN; hr = bag._CreateObject(strValueName, &V_UNKNOWN(&v), pErrorLog); } if (FAILED(hr)) return hr; } else { // Specified name does not exist TRACE1("CTCPropBagOnRegKey::_ReadVariant: Property \"%s\" does not exist\n", strValueName); return E_INVALIDARG; } // Coerce the value to the specified variant type switch (V_VT(pVar)) { // Leave value as-is if no VARIANT type was specified case VT_EMPTY: VariantCopy(pVar, v); break; // Coerce supported VARIANT types case VT_BOOL: case VT_I1: case VT_I2: case VT_I4: case VT_UI1: case VT_UI2: case VT_UI4: case VT_ERROR: case VT_R4: case VT_R8: case VT_DECIMAL: case VT_CY: case VT_DATE: case VT_BSTR: case VT_UNKNOWN: case VT_DISPATCH: case VT_ARRAY | VT_BOOL: case VT_ARRAY | VT_I1: case VT_ARRAY | VT_I2: case VT_ARRAY | VT_I4: case VT_ARRAY | VT_UI1: case VT_ARRAY | VT_UI2: case VT_ARRAY | VT_UI4: case VT_ARRAY | VT_ERROR: case VT_ARRAY | VT_R4: case VT_ARRAY | VT_R8: case VT_ARRAY | VT_DECIMAL: case VT_ARRAY | VT_CY: case VT_ARRAY | VT_DATE: case VT_ARRAY | VT_BSTR: case VT_ARRAY | VT_UNKNOWN: case VT_ARRAY | VT_DISPATCH: case VT_ARRAY | VT_VARIANT: { // Coerce the value to the specified VARIANT type VariantChangeTypeEx(pVar, v, GetThreadLocale(), m_wChangeTypeFlags, V_VT(pVar)); break; } // All other VARIANT types are unsupported default: { // Use local resources MCLibRes res; // Format a description string _bstr_t strDesc; strDesc.Format(IDS_FMT_UNSUPPORTED_VT, UINT(V_VT(pVar)), UINT(V_VT(pVar))); // Log the error USES_CONVERSION; return LogError("ReadVariant", strDesc, E_FAIL, T2COLE(strValueName), pErrorLog); } } // Indicate success return S_OK; }