// ComponentData.cpp : implementation file // #include "stdafx.h" #include "ComponentData.h" #include "types.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifdef _DEBUG void DumpVariant(VARIANT& var) { USES_CONVERSION; switch(var.vt) { case VT_NULL: ATLTRACE(_T("VT_NULL")); break; case VT_EMPTY: ATLTRACE(_T("VT_EMPTY")); break; case VT_UI1: ATLTRACE(_T("VT_UI1: ")); ATLTRACE(_T("%u"), (int)var.bVal); break; case VT_I2: ATLTRACE(_T("VT_I2: ")); ATLTRACE(_T("%d"), (int)var.bVal); break; case VT_I4: ATLTRACE(_T("VT_I4: ")); ATLTRACE(_T("%d"), (int)var.bVal); break; case VT_R4: ATLTRACE(_T("VT_R4: ")); ATLTRACE(_T("%f"), (double)var.bVal); break; case VT_R8: ATLTRACE(_T("VT_R8: ")); ATLTRACE(_T("%f"), (double)var.bVal); break; case VT_BOOL: ATLTRACE(_T("VT_BOOL: ")); ATLTRACE(_T("%s"), var.boolVal ? _T("true") : _T("false")); break; case VT_ERROR: ATLTRACE(_T("VT_ERROR: ")); ATLTRACE(_T("%d"), var.scode); break; case VT_CY: ATLTRACE(_T("VT_CY: ")); ATLTRACE(_T("%d"), var.cyVal); break; case VT_DATE: ATLTRACE(_T("VT_DATE ")); break; case VT_BSTR: ATLTRACE(_T("VT_BSTR: ")); ATLTRACE(_T("%s"), OLE2T(var.bstrVal)); break; case VT_UNKNOWN: ATLTRACE(_T("VT_UNKNOWN: ")); break; default: ATLTRACE(_T("VT_ Other")); break; } } #define TRACEVARIANT(var) DumpVariant(var) #else #define TRACEVARIANT(var) ((void)0) #endif ///////////////////////////////////////////////////////////////////////////// // CComponentData CComponentData::CComponentData() { } CComponentData::~CComponentData() { } ///////////////////////////////////////////////////////////////////////////// // CComponentData message handlers HRESULT CComponentData::Initialize(const string & sKey) { // Need a registry key to read from if(sKey.empty()) return E_INVALIDARG; m_sKey = sKey; return S_OK; } ////////////////////////////////////////////////////////////////// // Does the actual saving to the Registry HRESULT CComponentData::Save(string sKey /* = "" */) { ATLTRACE(_T("DATA SAVE\n==========\n")); long lRet = 0; CRegKey regKey; // Set to Internal Key if sKey Is Empty if(sKey.empty()) sKey = m_sKey; // Try and open Our Key if((lRet = regKey.Create(HKEY_CURRENT_USER, sKey)) != ERROR_SUCCESS) return HRESULT_FROM_WIN32(lRet); // Now do actual saving // Only support number and String types for now DWORD dwData = 0; string_variant_map::iterator iter = m_mapValues.begin(); for( ;iter != m_mapValues.end(); iter++) { ATLTRACE(_T("Saving: %s -- Value: "), iter->first.c_str()); TRACEVARIANT(iter->second); ATLTRACE(_T("\n")); switch(iter->second.vt) { // Number Types case VT_UI1: case VT_I2: case VT_I4: case VT_R4: case VT_R8: case VT_CY: lRet = regKey.SetValue(iter->second.lVal, iter->first); // ASSERT(lRet == ERROR_SUCCESS); break; // It's a String case VT_BSTR: lRet = regKey.SetValue(string(iter->second.bstrVal), iter->first); // ASSERT(lRet == ERROR_SUCCESS); break; // Delete the Key if NULL or Empty value case VT_NULL: case VT_EMPTY: lRet = regKey.DeleteValue(iter->first); // ASSERT(lRet == ERROR_SUCCESS); break; default: break; } } return S_OK; } ////////////////////////////////////////////////////////////////// // Passes the caller a IUnknown to the the underlying IPropertyBag /*IUnknown* CComponentData::GetIUnknown(bool bAddRef) { // If asked not to increment then Release if(bAddRef) this->AddRef(); return GetUnknown(); } */ ////////////////////////////////////////////////////////////////// // Reads actual Value from Registry HRESULT CComponentData::Read(const string & sValName, VARIANT& varVal) { // First Lookup the Value in the current map string_variant_map::iterator iter = m_mapValues.find(sValName); if(iter != m_mapValues.end()) return ::VariantCopy(&varVal, &(iter->second)); // Make sure we are initialized with a key if(m_sKey == "") return E_UNEXPECTED; // Open Key CRegKey regDataKey; if(regDataKey.Create(HKEY_CURRENT_USER, m_sKey) == ERROR_SUCCESS) { // Get Size and Type of Registry Value DWORD dwType = NULL; DWORD dwSize; if(::RegQueryValueEx(regDataKey.m_hKey, sValName, 0, &dwType, NULL, &dwSize) == ERROR_SUCCESS) { // We Only Support DWORD and String switch(dwType) { case REG_DWORD: // Get DWORD Value DWORD dwData; dwSize = sizeof(DWORD); if(::RegQueryValueEx(regDataKey.m_hKey, sValName, 0, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) { // Make sure we have a clean variant ::VariantClear(&varVal); // Return a 4 byte Integer varVal.vt = VT_I4; varVal.lVal = dwData; regDataKey.Close(); return S_OK; } break; case REG_SZ: // Get String Value string sData; if(::RegQueryValueEx(regDataKey.m_hKey, sValName, 0, &dwType, (LPBYTE)sData.get_buffer(dwSize), &dwSize) == ERROR_SUCCESS) { // Have to Release before we can AllocSysString sData.release_buffer(); // Make sure we have a clean variant ::VariantClear(&varVal); // Return a BSTR (Client responsible for cleanup) varVal.vt = VT_BSTR; varVal.bstrVal = _bstr_t(sData); regDataKey.Close(); return S_OK; } break; } } regDataKey.Close(); return REGDB_E_KEYMISSING; } regDataKey.Close(); return REGDB_E_READREGDB; } ////////////////////////////////////////////////////////////////// // Saves the value passed to Internal Map where it stays until // saved by the function Save HRESULT CComponentData::Write(const string& sValName, const VARIANT & varVal) { HRESULT hr; CComVariant varCopy = varVal; // Check what we've got // We only support DWORD and String switch(varVal.vt) { case VT_UI1: case VT_I2: case VT_I4: case VT_R4: case VT_R8: case VT_CY: // First try and make a 4 byte integer out of it (DWORD) hr = VariantChangeType(&varCopy, &varCopy, 0, VT_I4); if(FAILED(hr)) return hr; case VT_BSTR: case VT_NULL: case VT_EMPTY: // Add Item to Variant Map m_mapValues.erase(sValName); m_mapValues.insert(make_pair(sValName, varCopy)); return S_OK; break; default: return E_INVALIDARG; break; } return S_OK; } ///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// // IPropertyBag STDMETHODIMP CComponentData::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog) { // TRACE("CComponentData::XPropertyBag::Read\n"); // Pass calls ATLTRACE(_T("Read: %s -- Value: "), (LPCTSTR)string(pszPropName)); HRESULT hr = Read(string(pszPropName), *pVar); TRACEVARIANT(*pVar); ATLTRACE(_T("\n")); return hr; } STDMETHODIMP CComponentData::Write(LPCOLESTR pszPropName, VARIANT* pVar) { // TRACE("CComponentData::XPropertyBag::Write\n"); // Pass calls ATLTRACE(_T("Write: %s -- Value: "), (LPCTSTR)string(pszPropName)); TRACEVARIANT(*pVar); ATLTRACE(_T("\n")); return Write(string(pszPropName), *pVar); } ////////////////////////////////////////////////////////////////// // Host specific Functions (returns default if error or can't find) int CComponentData::GetInt(const string& sKey, int nDefault) { CComVariant var; var.vt = VT_I4; var.lVal = nDefault; if(FAILED(Read(sKey, var))) return nDefault; else return var.lVal; } ////////////////////////////////////////////////////////////////// // Host specific Function bool CComponentData::WriteInt(const string& sKey, int nValue) { CComVariant var; var.vt = VT_I4; var.lVal = nValue; return SUCCEEDED(Write(sKey, var)); } bool CComponentData::Delete(const string& sKey) { CComVariant var; var.vt = VT_NULL; return SUCCEEDED(Write(sKey, var)); }