#include "pch.h"
#include "TCPropBagOnRegKey.h"
#include <..\TCAtl\ObjectMap.h>
TC_OBJECT_EXTERN_IMPL(CTCPropBagOnRegKey)
const _bstr_t CTCPropBagOnRegKey::m_szVariantType (OLESTR(".vt"));
const _bstr_t CTCPropBagOnRegKey::m_szServer (OLESTR(".server"));
const _bstr_t CTCPropBagOnRegKey::m_szProgID (OLESTR(".progid"));
const _bstr_t CTCPropBagOnRegKey::m_szCLSID (OLESTR(".clsid"));
const _bstr_t CTCPropBagOnRegKey::m_szLowerBound (OLESTR(".lBound"));
const _bstr_t CTCPropBagOnRegKey::m_szElementCount (OLESTR(".elements"));
const _bstr_t CTCPropBagOnRegKey::m_szElementFmt (OLESTR("%d"));
const USHORT CTCPropBagOnRegKey::m_wChangeTypeFlags =
VARIANT_NOVALUEPROP | VARIANT_ALPHABOOL | VARIANT_LOCALBOOL;
CTCPropBagOnRegKey::CTCPropBagOnRegKey() :
m_pParent(NULL),
m_bOwnKey(false)
{
}
void CTCPropBagOnRegKey::FinalRelease()
{
ClosePrevious();
}
_bstr_t CTCPropBagOnRegKey::_GetSubkey()
{
XLock lock(this);
_bstr_t str;
if (m_pParent)
{
str = m_pParent->_GetSubkey();
if (str.length())
str += L"\\";
}
return str += m_strSubkey;
}
_bstr_t CTCPropBagOnRegKey::_GetServer(const _bstr_t& strName)
{
CRegKey subkey;
if (!strName.length())
subkey = m_key;
else if (!m_key.Exists(strName) || !subkey.Open(m_key, strName))
return _bstr_t();
_bstr_t strServer;
if (!subkey._GetString(m_szServer, strServer))
strServer.Empty();
return strServer;
}
HRESULT CTCPropBagOnRegKey::_SetServer(const _bstr_t& strName,
const _bstr_t& strServer)
{
CRegKey subkey;
if (!strName.length())
subkey = m_key;
else if (!m_key.Exists(strName) || !subkey.Open(m_key, strName))
return HRESULT_FROM_WIN32(GetLastError());
subkey.WriteString(m_szServer, strServer);
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_GetObjectCLSID(const _bstr_t& strName,
CLSID& clsid)
{
CRegKey subkey;
_bstr_t strObjectID;
return _GetObjectCLSID(strName, clsid, subkey, strObjectID, NULL);
}
HRESULT CTCPropBagOnRegKey::_CreateObject(const _bstr_t& strName,
IUnknown** ppunkObj, IErrorLog* pErrorLog, IUnknown* punkOuter)
{
_bstr_t strServer(GetServer(strName));
if (!strServer.length())
return CreateLocalObject(strName, ppunkObj, pErrorLog, punkOuter);
return CreateRemoteObject(strServer, strName, ppunkObj, pErrorLog);
}
HRESULT CTCPropBagOnRegKey::_CreateLocalObject(const _bstr_t& strName,
IUnknown** ppunkObj, IErrorLog* pErrorLog, IUnknown* punkOuter)
{
CLSID clsid;
CRegKey subkey;
_bstr_t strObjectID;
HRESULT hr = GetObjectCLSID(strName, clsid, subkey, strObjectID,
pErrorLog);
if (FAILED(hr))
return hr;
DWORD dwCtx = CLSCTX_ALL | CLSCTX_REMOTE_SERVER;
IPersistPropertyBagPtr pppb;
void** ppv = reinterpret_cast<void**>(&pppb);
hr = CoCreateInstance(clsid, punkOuter, dwCtx, __uuidof(pppb), ppv);
if (E_INVALIDARG == hr)
{
dwCtx &= ~CLSCTX_REMOTE_SERVER;
hr = CoCreateInstance(clsid, punkOuter, dwCtx, __uuidof(pppb), ppv);
}
if (FAILED(hr))
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_FAIL_CREATE_CLSID, strObjectID);
USES_CONVERSION;
return LogError("CreateObject", strDesc, hr, T2COLE(strName), pErrorLog);
}
CComObjectStack<CTCPropBagOnRegKey> bag;
bag.Init(subkey, strName, this);
hr = pppb->Load(&bag, pErrorLog);
if (FAILED(hr))
return hr;
*ppunkObj = pppb.Detach();
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_CreateRemoteObject(const _bstr_t& strServer,
const _bstr_t& strName, IUnknown** ppunkObj, IErrorLog* pErrorLog)
{
MCOle32_dll& libOle32 = GetOle32Lib();
if (!libOle32.Exists_CoCreateInstanceEx())
return !strServer.length() ?
CreateLocalObject(strName, ppunkObj, pErrorLog) : E_UNEXPECTED;
CLSID clsid;
CRegKey subkey;
_bstr_t strObjectID;
HRESULT hr = GetObjectCLSID(strName, clsid, subkey, strObjectID,
pErrorLog);
if (FAILED(hr))
return hr;
USES_CONVERSION;
_bstr_t bstrServer(strServer);
COSERVERINFO csi = {0, bstrServer, NULL, 0};
MULTI_QI mqi = {&IID_IPersistPropertyBag, NULL, 0};
DWORD dwCtx = CLSCTX_ALL | CLSCTX_REMOTE_SERVER;
hr = libOle32.CoCreateInstanceEx(clsid, NULL, dwCtx, &csi, 1, &mqi);
if (FAILED(hr))
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_FAIL_CREATE_CLSID, strObjectID);
USES_CONVERSION;
return LogError("CreateObject", strDesc, hr, T2COLE(strName), pErrorLog);
}
IPersistPropertyBagPtr pppb((IPersistPropertyBag*)mqi.pItf, false);
CComObjectStack<CTCPropBagOnRegKey> bag;
bag.Init(subkey, strName, this);
hr = pppb->Load(&bag, pErrorLog);
if (FAILED(hr))
return hr;
*ppunkObj = pppb.Detach();
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_LoadObject(const _bstr_t& strName,
IUnknown* punkObj, IErrorLog* pErrorLog)
{
if (IsBadReadPtr(punkObj))
return E_POINTER;
if (NULL != pErrorLog && IsBadReadPtr(pErrorLog))
return E_POINTER;
CRegKey subkey;
if (!strName.length())
subkey = m_key;
else if (!m_key.Exists(strName) || !subkey.Open(m_key, strName))
return HRESULT_FROM_WIN32(GetLastError());
IPersistPropertyBagPtr pppb;
HRESULT hr = punkObj->QueryInterface(__uuidof(pppb), (void**)&pppb);
if (FAILED(hr))
return hr;
CComObjectStack<CTCPropBagOnRegKey> bag;
bag.Init(subkey, strName, this);
hr = pppb->Load(&bag, pErrorLog);
return hr;
}
HRESULT CTCPropBagOnRegKey::_SaveObject(const _bstr_t& strName,
IUnknown* punkObj, BOOL bClearDirty, BOOL bSaveAllProperties)
{
if (IsBadReadPtr(punkObj))
return E_POINTER;
CRegKey subkey;
if (!strName.length())
subkey = m_key;
else
{
m_key.DeleteValue(strName);
m_key.RecurseDeleteKey(strName);
if (!subkey.Open(m_key, strName))
return HRESULT_FROM_WIN32(GetLastError());
}
IPersistPropertyBagPtr pppb;
HRESULT hr = punkObj->QueryInterface(__uuidof(pppb), (void**)&pppb);
if (FAILED(hr))
return hr;
CLSID clsid;
hr = pppb->GetClassID(&clsid);
if (FAILED(hr))
return hr;
LPOLESTR pszProgID = NULL;
if (SUCCEEDED(ProgIDFromCLSID(clsid, &pszProgID)))
{
subkey.WriteString(m_szProgID, pszProgID);
CoTaskMemFree(pszProgID);
}
else
{
OLECHAR szClassID[64];
StringFromGUID2(clsid, szClassID, sizeofArray(szClassID));
subkey.WriteString(m_szCLSID, szClassID);
}
subkey.WriteDWord(m_szVariantType, DWORD(VarTypeFromUnknown(punkObj)));
CComObjectStack<CTCPropBagOnRegKey> bag;
bag.Init(subkey, strName, this);
hr = pppb->Save(&bag, bClearDirty, bSaveAllProperties);
return hr;
}
MCOle32_dll& CTCPropBagOnRegKey::_GetOle32Lib()
{
static MCOle32_dll libOle32;
return libOle32;
}
HRESULT CTCPropBagOnRegKey::_GetObjectCLSID(const _bstr_t& strName,
CLSID& clsid, CRegKey& subkey, _bstr_t& strObjectID, IErrorLog* pErrorLog)
{
USES_CONVERSION;
clsid = CLSID_NULL;
subkey.Close();
strObjectID.Empty();
if (!strName.length())
subkey = m_key;
else if (!m_key.Exists(strName) || !subkey.Open(m_key, strName))
return HRESULT_FROM_WIN32(GetLastError());
MCLibRes res;
HRESULT hr;
_bstr_t strDesc;
if (subkey.GetString(m_szCLSID, strObjectID))
{
LPOLESTR pszObjectID = const_cast<LPOLESTR>(T2COLE(strObjectID));
hr = CLSIDFromString(pszObjectID, &clsid);
if (SUCCEEDED(hr))
return hr;
strDesc.Format(IDS_FMT_FAIL_CONVERT_CLSID, strObjectID);
}
else if (subkey.GetString(m_szProgID, strObjectID))
{
hr = CLSIDFromProgID(T2COLE(strObjectID), &clsid);
if (SUCCEEDED(hr))
return hr;
strDesc.Format(IDS_FMT_FAIL_CONVERT_CLSID, strObjectID);
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
strDesc.LoadString(IDS_FAIL_READ_CLSID);
}
return LogError("GetObjectCLSID", strDesc, hr, T2COLE(strName), pErrorLog);
}
HRESULT CTCPropBagOnRegKey::_ReadVariantFromValue(CRegKey& key,
const _bstr_t& strPropName, DWORD nType, int cbData, CComVariant& v,
IErrorLog* pErrorLog)
{
switch (nType)
{
case REG_DWORD:
{
key.GetDWord(strPropName, (DWORD&)V_UI4(&v));
v.vt = VT_UI4;
break;
}
case REG_SZ:
{
_bstr_t strValue;
key.GetString(strPropName, strValue);
v = strValue;
break;
}
case REG_BINARY:
{
BYTE* pData = new BYTE[cbData];
key.GetBinary(strPropName, pData, cbData);
CMemFile file(pData, cbData);
CArchive ar(&file, CArchive::load, 0);
ar >> v;
ar.Close();
delete [] file.Detach();
break;
}
default:
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_UNSUPPORTED_REGTYPE, nType);
USES_CONVERSION;
return LogError("ReadVariantFromValue", strDesc, E_FAIL,
T2COLE(strPropName), pErrorLog);
}
}
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_LogError(const _bstr_t& strFn,
const _bstr_t& strDesc, HRESULT hr, LPCOLESTR pszPropName,
IErrorLog* pErrorLog)
{
_bstr_t strSrc, strSubkey(GetSubkey());
if (!strSubkey.length())
strSrc.Format(_T("CTCPropBagOnRegKey::_%s(\"%ls\")"), strFn,
pszPropName);
else
strSrc.Format(_T("CTCPropBagOnRegKey::_%s(\"%s\\%ls\")"), strFn,
strSubkey, pszPropName);
TRACE2("%s: %s\n", strSrc, strDesc);
if (NULL != pErrorLog)
{
BSTR bstrSrc = strSrc.AllocSysString();
BSTR bstrDesc = strDesc.AllocSysString();
EXCEPINFO ei = {0, 0, bstrSrc, bstrDesc, NULL, 0, NULL, NULL, hr};
HRESULT hrAdd = pErrorLog->AddError(pszPropName, &ei);
SysFreeString(bstrDesc);
SysFreeString(bstrSrc);
if (FAILED(hrAdd))
{
TRACE1("%s: pErrorLog->AddError() failed!\n", strSrc);
AfxThrowOleException(hrAdd);
}
}
return hr;
}
VARTYPE CTCPropBagOnRegKey::_GetSubkeyVarType(CRegKey& key,
const _bstr_t& strPropName)
{
ASSERT(key.Exists(strPropName));
CRegKey subkey;
if (!subkey.Open(key, strPropName))
return VT_EMPTY;
DWORD dwVT;
if (!subkey.GetDWord(m_szVariantType, dwVT))
return VT_EMPTY;
return VARTYPE(dwVT);
}
HRESULT CTCPropBagOnRegKey::_ReadSafeArray(CRegKey& key,
const _bstr_t& strPropName, VARIANT* pVar, IErrorLog* pErrorLog)
{
CRegKey subkey;
VERIFY(subkey.Open(key, strPropName));
VARTYPE vt = GetSubkeyVarType(key, strPropName);
ASSERT(vt & VT_ARRAY);
vt &= ~VT_ARRAY;
switch (vt)
{
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_VARIANT:
break;
default:
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_UNSUP_ARRAY_VARTYPE, strPropName, vt, vt);
USES_CONVERSION;
return LogError("ReadSafeArray", strDesc, E_UNEXPECTED,
T2COLE(strPropName), pErrorLog);
}
}
DWORD dwElements = 0;
if (!subkey.GetDWord(m_szElementCount, dwElements))
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_VALUE_NOT_EXIST, m_szElementCount, strPropName);
USES_CONVERSION;
return LogError("ReadSafeArray", strDesc, E_UNEXPECTED,
T2COLE(strPropName), pErrorLog);
}
LONG lLBound = 0;
subkey.GetDWord(m_szLowerBound, (DWORD&)lLBound);
_bstr_t strText;
CComVariant var;
CArray<CComVariant, CComVariant&> arrayTemp;
for (DWORD i = 0; i < dwElements; i++)
{
V_VT(&var) = vt;
strText.Format(m_szElementFmt, i);
HRESULT hr = ReadVariant(subkey, strText, var, pErrorLog);
if (FAILED(hr))
return hr;
arrayTemp.Add(var);
}
SAFEARRAY* psa = SafeArrayCreateVector(vt, lLBound, dwElements);
if (NULL == psa)
{
MCLibRes res;
_bstr_t strDesc(LPCSTR(IDS_FAIL_SAFEARRAY_CREATE));
USES_CONVERSION;
return LogError("ReadSafeArray", strDesc, E_OUTOFMEMORY,
T2COLE(strPropName), pErrorLog);
}
for (long iElement = 0; iElement < arrayTemp.GetSize(); iElement++)
{
CComVariant& v = arrayTemp[iElement];
void* pvData;
switch (vt)
{
case VT_VARIANT:
pvData = &v;
break;
case VT_UNKNOWN:
case VT_DISPATCH:
case VT_BSTR:
pvData = V_BSTR(&v);
break;
default:
pvData = &V_NONE(&v);
}
HRESULT hr = SafeArrayPutElement(psa, &iElement, pvData);
if (FAILED(hr))
{
MCLibRes res;
_bstr_t strDesc(LPCSTR(IDS_FAIL_SAFEARRAY_PUT));
USES_CONVERSION;
return LogError("ReadSafeArray", strDesc, hr, T2COLE(strPropName),
pErrorLog);
}
}
V_VT(pVar) = vt | VT_ARRAY;
V_ARRAY(pVar) = psa;
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_WriteSafeArray(CRegKey& key,
const _bstr_t& strPropName, VARIANT* pVar)
{
ASSERT(V_ISARRAY(pVar));
ASSERT(lstrlen(strPropName));
SAFEARRAY* psa = V_ARRAY(pVar);
if (IsBadReadPtr(psa))
return E_POINTER;
if (1 != SafeArrayGetDim(psa))
return E_INVALIDARG;
UINT cbElement = SafeArrayGetElemsize(psa);
VARTYPE vt = V_VT(pVar) & ~VT_ARRAY;
switch (vt)
{
case VT_BOOL:
if (sizeof(V_BOOL(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_I1:
if (sizeof(V_I1(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_I2:
if (sizeof(V_I2(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_I4:
if (sizeof(V_I4(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_UI1:
if (sizeof(V_UI1(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_UI2:
if (sizeof(V_UI2(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_UI4:
if (sizeof(V_UI4(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_ERROR:
if (sizeof(V_ERROR(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_R4:
if (sizeof(V_R4(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_R8:
if (sizeof(V_R8(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_DECIMAL:
if (sizeof(V_DECIMAL(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_CY:
if (sizeof(V_CY(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_DATE:
if (sizeof(V_DATE(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_BSTR:
if (sizeof(V_BSTR(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_UNKNOWN:
if (sizeof(V_UNKNOWN(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_DISPATCH:
if (sizeof(V_DISPATCH(pVar)) != cbElement)
return E_UNEXPECTED;
break;
case VT_VARIANT:
if (sizeof(V_VARIANTREF(pVar)) != cbElement)
return E_UNEXPECTED;
break;
default:
return E_UNEXPECTED;
}
HRESULT hr;
LONG lUBound = 0, lLBound = 0;
if (FAILED(hr = SafeArrayGetUBound(psa, 1, &lUBound)))
return hr;
if (FAILED(hr = SafeArrayGetLBound(psa, 1, &lLBound)))
return hr;
UINT nElements = lUBound - lLBound + 1;
key.DeleteValue(strPropName);
key.RecurseDeleteKey(strPropName);
CRegKey subkey;
if (!subkey.Open(key, strPropName))
return HRESULT_FROM_WIN32(GetLastError());
BYTE* pElement = NULL;
if (FAILED(hr = SafeArrayAccessData(psa, (void**)&pElement)))
return hr;
subkey.WriteDWord(m_szVariantType, DWORD(V_VT(pVar)));
subkey.WriteDWord(m_szElementCount, DWORD(nElements));
if (lLBound)
subkey.WriteDWord(m_szLowerBound, DWORD(lLBound));
_bstr_t strText;
if (VT_VARIANT == vt)
{
for (UINT i = 0; i < nElements; i++, pElement += cbElement)
{
strText.Format(m_szElementFmt, i);
if (FAILED(hr = WriteVariant(subkey, strText, (VARIANT*)pElement)))
{
TRACE1("CTCPropBagOnRegKey::_WriteSafeArray(\"%s\", pVar): ",
strPropName);
TRACE2("WriteVariant(subkey, \"%s\", &var) returned 0x%08X\n",
strText, hr);
}
}
}
else
{
VARIANT var;
V_VT(&var) = vt;
for (UINT i = 0; i < nElements; i++, pElement += cbElement)
{
memcpy(&V_NONE(&var), pElement, cbElement);
strText.Format(m_szElementFmt, i);
if (FAILED(hr = WriteVariant(subkey, strText, &var)))
{
TRACE1("CTCPropBagOnRegKey::_WriteSafeArray(\"%s\", pVar): ",
strPropName);
TRACE2("WriteVariant(subkey, \"%s\", &var) returned 0x%08X\n",
strText, hr);
}
}
}
VERIFY(SUCCEEDED(SafeArrayUnaccessData(psa)));
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_ReadVariant(CRegKey& key,
const _bstr_t& strValueName, VARIANT* pVar, IErrorLog* pErrorLog)
{
CComVariant v;
DWORD nType = 0;
int cbData = 0;
if (key.QueryValue(strValueName, nType, cbData)) {
HRESULT hr = _ReadVariantFromValue(key, strValueName, nType, cbData, v,
pErrorLog);
if (FAILED(hr))
return hr;
}
else if (key.Exists(strValueName)) {
HRESULT hr = E_FAIL;
if (IsSubkeySafeArray(key, strValueName))
hr = ReadSafeArray(key, strValueName, pVar, pErrorLog);
else if (IsSubkeyObject(key, strValueName))
{
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
{
TRACE1("CTCPropBagOnRegKey::_ReadVariant: Property \"%s\" does not exist\n",
strValueName);
return E_INVALIDARG;
}
switch (V_VT(pVar))
{
case VT_EMPTY:
VariantCopy(pVar, v);
break;
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:
{
VariantChangeTypeEx(pVar, v, GetThreadLocale(), m_wChangeTypeFlags,
V_VT(pVar));
break;
}
default:
{
MCLibRes res;
_bstr_t strDesc;
strDesc.Format(IDS_FMT_UNSUPPORTED_VT, UINT(V_VT(pVar)),
UINT(V_VT(pVar)));
USES_CONVERSION;
return LogError("ReadVariant", strDesc, E_FAIL, T2COLE(strValueName),
pErrorLog);
}
}
return S_OK;
}
HRESULT CTCPropBagOnRegKey::_WriteVariant(CRegKey& key,
const _bstr_t& strValueName, VARIANT* pVar)
{
if (V_ISARRAY(pVar))
return WriteSafeArray(key, strValueName, pVar);
switch (V_VT(pVar))
{
case VT_EMPTY:
key.DeleteValue(strValueName);
key.RecurseDeleteKey(strValueName);
break;
case VT_I1:
case VT_I2:
case VT_I4:
case VT_UI1:
case VT_UI2:
case VT_ERROR:
{
VariantChangeTypeEx(pVar, pVar, GetThreadLocale(), m_wChangeTypeFlags,
VT_UI4);
}
case VT_UI4:
{
key.RecurseDeleteKey(strValueName);
key.WriteDWord(strValueName, V_UI4(pVar));
break;
}
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_DECIMAL:
case VT_BOOL:
{
VariantChangeTypeEx(pVar, pVar, GetThreadLocale(), m_wChangeTypeFlags,
VT_BSTR);
}
case VT_BSTR:
{
key.RecurseDeleteKey(strValueName);
key.WriteString(strValueName, V_BSTR(pVar));
break;
}
case VT_UNKNOWN:
case VT_DISPATCH:
{
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);
CMemFile file;
CArchive ar(&file, CArchive::store, 0);
CComVariant v(pVar);
ar << v;
ar.Close();
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;
}
return S_OK;
}
VARTYPE CTCPropBagOnRegKey::_VarTypeFromUnknown(IUnknown* punk)
{
try
{
VARTYPE vt = VT_UNKNOWN;
IDispatch* pdisp = NULL;
if (SUCCEEDED(punk->QueryInterface(IID_IDispatch, (void**)&pdisp)))
{
if (pdisp == punk)
vt = VT_DISPATCH;
pdisp->Release();
}
return vt;
}
catch (...)
{
return VT_EMPTY;
}
}
HKEY CTCPropBagOnRegKey::RootKeyFromString(BSTR bstrRegKey, DWORD* cchEaten)
{
struct XRootKeys
{
LPCOLESTR pszName;
DWORD cchName;
HKEY hkey;
};
const static XRootKeys s_table[] =
{
{L"HKCR\\" , 5, HKEY_CLASSES_ROOT },
{L"HKCU\\" , 5, HKEY_CURRENT_USER },
{L"HKLM\\" , 5, HKEY_LOCAL_MACHINE },
{L"HKCC\\" , 5, HKEY_CURRENT_CONFIG },
{L"HKPD\\" , 5, HKEY_PERFORMANCE_DATA},
{L"HKDD\\" , 5, HKEY_DYN_DATA },
{L"HKEY_CLASSES_ROOT\\" , 18, HKEY_CLASSES_ROOT },
{L"HKEY_CURRENT_USER\\" , 18, HKEY_CURRENT_USER },
{L"HKEY_LOCAL_MACHINE\\" , 19, HKEY_LOCAL_MACHINE },
{L"HKEY_CURRENT_CONFIG\\" , 20, HKEY_CURRENT_CONFIG },
{L"HKEY_PERFORMANCE_DATA\\", 22, HKEY_PERFORMANCE_DATA},
{L"HKEY_DYN_DATA\\" , 14, HKEY_DYN_DATA },
};
const static long s_cEntries = sizeofArray(s_table);
if (BSTRLen(bstrRegKey))
{
for (long i = 0; i < s_cEntries; ++i)
{
if (!wcsnicmp(s_table[i].pszName, bstrRegKey, s_table[i].cchName))
{
*cchName = s_table[i].cchName;
return s_table[i].hkey;
}
}
}
*cchName = 0;
return NULL;
}
LONG CTCPropBagOnRegKey::KeyExists(HKEY hkey, const _bstr_t& strKeyName)
{
HKEY hkeyTemp;
LONG lr = IsWinNT() ?
RegOpenKeyExW(hkey, strKeyName, 0, KEY_READ, &hkeyTemp) :
RegOpenKeyExA(hkey, strKeyName, 0, KEY_READ, &hkeyTemp);
if (ERROR_SUCCESS == lr)
{
RegCloseKey(hkeyTemp);
return true;
}
return false;
}
LONG CTCPropBagOnRegKey::QueryString(HKEY hkey, const _bstr_t& strValueName,
_bstr_t& strOut)
{
bool bIsWinNT = IsWinNT();
DWORD cbData;
LONG lr = bIsWinNT ?
RegQueryValueExW(hkey, strValueName, NULL, NULL, NULL, &cbData) :
RegQueryValueExA(hkey, strValueName, NULL, NULL, NULL, &cbData);
LP
}
STDMETHODIMP CTCPropBagOnRegKey::CreateKey(BSTR bstrRegKey,
VARIANT_BOOL bReadOnly)
{
DWORD cchEaten;
HKEY hkeyRoot = RootKeyFromString(bstrRegKey, &cchEaten);
if (!hkeyRoot)
{
ZError("CTCPropBagOnRegKey::CreateKey(): Invalid registry key name specified.");
return E_INVALIDARG;
}
bstrRegKey += cchEaten;
REGSAM regsam = bReadOnly ? KEY_READ : KEY_ALL_ACCESS;
long lr;
HKEY hkeyOpen = NULL;
DWORD dw;
if (IsWinNT()) {
lr = RegCreateKeyExW(hkeyRoot, bstrRegKey, 0, REG_NONE,
REG_OPTION_NON_VOLATILE, regsam, NULL, &hkeyOpen, &dw);
}
else
{
USES_CONVERSION;
lr = RegCreateKeyEx(hkeyRoot, OLE2CT(bstrRegKey), 0, REG_NONE,
REG_OPTION_NON_VOLATILE, regsam, NULL, &hkeyOpen, &dw);
}
if (ERROR_SUCCESS != lr)
return HRESULT_FROM_WIN32(lr);
XLock lock(this);
ClosePrevious();
m_key.Attach(hkeyOpen);
m_bOwnKey = true;
return S_OK;
}
STDMETHODIMP CTCPropBagOnRegKey::OpenKey(BSTR bstrRegKey,
VARIANT_BOOL bReadOnly)
{
DWORD cchEaten;
HKEY hkeyRoot = RootKeyFromString(bstrRegKey, &cchEaten);
if (!hkeyRoot)
{
ZError("CTCPropBagOnRegKey::CreateKey(): Invalid registry key name specified.");
return E_INVALIDARG;
}
bstrRegKey += cchEaten;
REGSAM regsam = bReadOnly ? KEY_READ : KEY_ALL_ACCESS;
long lr;
HKEY hkeyOpen = NULL;
DWORD dw;
if (IsWinNT()) {
lr = RegOpenKeyExW(hkeyRoot, bstrRegKey, 0, regsam, &hkeyOpen);
}
else
{
USES_CONVERSION;
lr = RegOpenKeyEx(hkeyRoot, OLE2CT(bstrRegKey), 0, regsam, &hkeyOpen);
}
if (ERROR_SUCCESS != lr)
return HRESULT_FROM_WIN32(lr);
XLock lock(this);
ClosePrevious();
m_key.Attach(hkeyOpen);
m_bOwnKey = true;
return S_OK;
}
STDMETHODIMP CTCPropBagOnRegKey::CreateObject(IUnknown** ppunkObj)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->CreateObject(_bstr_t(), ppunkObj);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::CreateObject()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::CreateLocalObject(IUnknown** ppunkObj)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->CreateLocalObject(_bstr_t(), ppunkObj);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::CreateLocalObject()",
RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::CreateRemoteObject(BSTR bstrServer,
IUnknown** ppunkObj)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->CreateRemoteObject(_bstr_t(bstrServer), _bstr_t(),
ppunkObj);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::CreateRemoteObject()",
RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::LoadObject(IUnknown* punkObj)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->LoadObject(_bstr_t(), punkObj);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::LoadObject()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::SaveObject(IUnknown* punkObj,
VARIANT_BOOL bClearDirty, VARIANT_BOOL bSaveAllProperties)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->SaveObject(_bstr_t(), punkObj);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::SaveObject()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::put_Server(BSTR bstrServer)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return m_pBag->SetServer(_bstr_t(), _bstr_t(bstrServer));
}
TC_CATCH_ALL("CTCPropBagOnRegKey::put_Server()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::get_Server(BSTR* pbstrServer)
{
try
{
CLEAROUT(pbstrServer, (BSTR)NULL);
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
*pbstrServer = m_pBag->GetServer(_bstr_t()).AllocSysString();
return S_OK;
}
TC_CATCH_ALL("CTCPropBagOnRegKey::get_Server()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::get_ObjectCLSID(BSTR* pbstrCLSID)
{
try
{
CLEAROUT(pbstrCLSID, (BSTR)NULL);
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
CLSID clsid;
RETURN_FAILED(m_pBag->GetObjectCLSID(_bstr_t(), clsid));
*pbstrCLSID = BSTRFromGUID(clsid).copy();
return S_OK;
}
TC_CATCH_ALL("CTCPropBagOnRegKey::get_ObjectCLSID()",
RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::Read(LPCOLESTR pszPropName,
VARIANT* pVar, IErrorLog* pErrorLog)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return ((IPropertyBag*)m_pBag)->Read(pszPropName, pVar, pErrorLog);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::Read()", RPC_E_SERVERFAULT)
}
STDMETHODIMP CTCPropBagOnRegKey::Write(LPCOLESTR pszPropName,
VARIANT* pVar)
{
try
{
XLock lock(this);
if (!m_pBag)
return E_UNEXPECTED;
return ((IPropertyBag*)m_pBag)->Write(pszPropName, pVar);
}
TC_CATCH_ALL("CTCPropBagOnRegKey::Write()", RPC_E_SERVERFAULT)
}