///////////////////////////////////////////////////////////////////////////////////// // CRGSBag.cpp : Implementation for Read Only property bag on .RGS script fragment // Copyright (c) Microsoft Corporation 2000. #include "stdafx.h" #include "rgsbag.h" using namespace ::ATL::ATL; CRGSBag::CRGSBag(LPCTSTR szRGS, CRegObject& croi, int& cchEaten) : CRegParser(&croi) { TCHAR szToken[MAX_VALUE]; HRESULT hr = S_OK; LPTSTR szReg = NULL; hr = PreProcessBuffer(szRGS, &szReg); if (FAILED(hr)) { THROWCOM(hr); } #if defined(_DEBUG) && defined(DEBUG_REGISTRATION) OutputDebugString(szReg); //would call ATLTRACE but szReg is > 512 bytes OutputDebugString(_T("\n")); #endif //_DEBUG szToken[0] = 0; m_pchCur = szReg; cchEaten = 0; try { while (NULL != *m_pchCur && chRightBracket != *szToken) { if (FAILED(hr = NextToken(szToken))) { break; } if (chLeftBracket != *szToken) { ATLTRACE2(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s\n"), szToken); hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN); THROWCOM(hr); } hr = BuildMapFromFragment(szToken); if (FAILED(hr)) { THROWCOM(hr); } } if (NULL != *m_pchCur) { m_pchCur = CharNext(m_pchCur); // eat the } } cchEaten = m_pchCur - szReg; if (szReg) { CoTaskMemFree(szReg); szReg = NULL; } } catch(ComException &e) { if (szReg) { CoTaskMemFree(szReg); szReg = NULL; } throw; } } HRESULT CRGSBag::BuildMapFromFragment(LPTSTR pszToken) { HRESULT hr = S_OK; if (FAILED(hr = NextToken(pszToken))) return hr; while (*pszToken != chRightBracket) // Continue till we see a } { TCHAR szValueName[MAX_VALUE]; CComVariant v; if (!lstrcmpi(pszToken, szValToken)) // need to add a value to hkParent { if (FAILED(hr = NextToken(szValueName))) break; if (FAILED(hr = NextToken(pszToken))) break; if (*pszToken != chEquals) return GenerateError(E_ATL_EXPECTING_EQUAL); hr = GetValue(v); if (FAILED(hr)) { return hr; } } else { if (StrChr(pszToken, chDirSep) != NULL) return GenerateError(E_ATL_COMPOUND_KEY); lstrcpyn(szValueName, pszToken, sizeof(szValueName) / sizeof(TCHAR)); hr = GetObject(v); if (FAILED(hr)) { return hr; } } m_mapBag[szValueName] = v; if (FAILED(hr = NextToken(pszToken))) break; } return hr; } HRESULT CRGSBag::GetObject(CComVariant& val) { ASSERT(val.vt == VT_EMPTY || val.vt == VT_NULL); val.vt = VT_UNKNOWN; val.punkVal = NULL; HRESULT hr; TCHAR szToken[MAX_VALUE]; if (FAILED(hr = NextToken(szToken))) return hr; if (*szToken != chEquals) { return GenerateError(E_ATL_EXPECTING_EQUAL); } // currently we're just expecting a guid here with no type specifier(s'') // we should really take genuine .rgs syntax and report an error if it isn't a string if (FAILED(hr = NextToken(szToken))) { return GenerateError(CO_E_CLASSSTRING); } USES_CONVERSION; GUID2 clsid(T2COLE(szToken)); PUnknown pobj(clsid, NULL, CLSCTX_INPROC_SERVER); if (!pobj) { return REGDB_E_CLASSNOTREG; } hr = LoadPersistedObject (pobj, *m_pRegObj, &m_pchCur); if (FAILED(hr)) { hr = LoadPersistedObject (pobj, *m_pRegObj, &m_pchCur); if (FAILED(hr)) { return hr; } } val.punkVal = pobj; (val.punkVal)->AddRef(); return NOERROR; } HRESULT CRGSBag::GetValue(CComVariant &val) { USES_CONVERSION; HRESULT hr; VARTYPE vt; LONG lRes = ERROR_SUCCESS; UINT nIDRes = 0; TCHAR* pszToken = new TCHAR[MAX_TYPE]; if (!pszToken) { return E_OUTOFMEMORY; } if (FAILED(hr = NextToken(pszToken))) { delete[] pszToken; return hr; } if (!VTFromRegType(pszToken, vt)) { ATLTRACE2(atlTraceRegistrar, 0, _T("%s Type not supported\n"), pszToken); delete[] pszToken; return GenerateError(E_ATL_TYPE_NOT_SUPPORTED); } if (FAILED(hr = NextToken(pszToken))) { delete[] pszToken; return hr; } switch (vt) { case VT_BSTR: val.vt = VT_BSTR; ASSERT(val.bstrVal == NULL); val.bstrVal = ::SysAllocString(T2OLE(pszToken)); break; case VT_UI4: #ifdef _WIN64 ATLASSERT(FALSE); val.ulVal = 0; #pragma message( "Still need win64 version of VarUI4FromStr()." ) #else VarUI4FromStr(T2OLE(pszToken), 0, 0, &val.ulVal); #endif val.vt = VT_UI4; break; case VT_UI1: { int cbValue = lstrlen(pszToken); if (cbValue & 0x00000001) { ATLTRACE2(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries\n")); delete[] pszToken; return E_FAIL; } int cbValDiv2 = cbValue/2; int cbLen = cbValDiv2 * sizeof(BYTE); BYTE* rgBinary = new BYTE[cbLen]; if (!rgBinary) { delete[] pszToken; return E_OUTOFMEMORY; } memset(rgBinary, 0, cbValDiv2); if (rgBinary == NULL) { delete[] rgBinary; delete[] pszToken; return E_FAIL; } for (int irg = 0; irg < cbValue; irg++) rgBinary[(irg/2)] |= (ChToByte(pszToken[irg])) << (4*(1 - (irg & 0x00000001))); val.vt = VT_BSTR; val.bstrVal = ::SysAllocStringByteLen(reinterpret_cast(rgBinary), cbLen); delete[] rgBinary; break; } } delete[] pszToken; return S_OK; } // end of file - crgsbag.cpp