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;
}