示例#1
0
//+---------------------------------------------------------------------------
//
//  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;
}
示例#3
0
/* 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;
}
示例#4
0
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;    
}
示例#5
0
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;
}
示例#6
0
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");
    }
}
示例#7
0
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;
}