windows-nt/Source/XPSP1/NT/multimedia/dshow/guidestore/property.cpp
2020-09-26 16:20:57 +08:00

1712 lines
33 KiB
C++

// prop.cpp : Implementation of CMetaPropertySet
#include "stdafx.h"
#include "Property.h"
#include "util.h"
HRESULT SaveObjectToField(VARIANT var, ADODB::Field *pfield)
{
HRESULT hr;
if ((var.vt != VT_UNKNOWN) && (var.vt != VT_DISPATCH))
return E_INVALIDARG;
CComPtr<IStream> pstream;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pstream);
if (FAILED(hr))
return hr;
CComQIPtr<IPersistStream> ppersiststream(var.punkVal);
if (ppersiststream != NULL)
{
// Write a tag to indicate IPersistStream was used.
char ch = Format_IPersistStream;
ULONG cb = sizeof(ch);
hr = pstream->Write(&ch, cb, &cb);
if (FAILED(hr))
return hr;
hr = OleSaveToStream(ppersiststream, pstream);
if (FAILED(hr))
return hr;
}
else
{
CComQIPtr<IPersistPropertyBag> ppersistpropbag(var.punkVal);
if (ppersistpropbag == NULL)
return E_INVALIDARG;
// Write a tag to indicate IPersistPropertyBag was used.
char ch = Format_IPersistPropertyBag;
ULONG cb = sizeof(ch);
hr = pstream->Write(&ch, cb, &cb);
if (FAILED(hr))
return hr;
hr = SaveToPropBagInStream(ppersistpropbag, pstream);
if (FAILED(hr))
return hr;
}
HANDLE hdata;
hr = GetHGlobalFromStream(pstream, &hdata);
if (FAILED(hr))
return hr;
long cb = GlobalSize(hdata);
SAFEARRAY *parray = SafeArrayCreateVector(VT_UI1, 0, cb);
if (parray == NULL)
return E_OUTOFMEMORY;
BYTE *pbDst;
hr = SafeArrayAccessData(parray, (void **) &pbDst);
if (FAILED(hr))
return hr;
BYTE *pbSrc = (BYTE *) GlobalLock(hdata);
memcpy(pbDst, pbSrc, cb);
GlobalUnlock(hdata);
SafeArrayUnaccessData(parray);
_variant_t varT;
varT.vt = VT_ARRAY | VT_UI1;
varT.parray = parray;
hr = pfield->AppendChunk(varT);
if (FAILED(hr))
return hr;
return S_OK;
}
HRESULT LoadObjectFromField(ADODB::Field *pfield, VARIANT *pvar)
{
HRESULT hr;
long cb;
hr = pfield->get_ActualSize(&cb);
if (FAILED(hr))
return hr;
_variant_t varData;
hr = pfield->GetChunk(cb, &varData);
if (FAILED(hr))
return hr;
if ((varData.vt & VT_ARRAY) == 0)
return E_FAIL;
BYTE *pbSrc;
hr = SafeArrayAccessData(varData.parray, (void **) &pbSrc);
if (FAILED(hr))
return hr;
HANDLE hdata;
BOOL fFree = FALSE;
hdata = GlobalHandle(pbSrc);
if (hdata == NULL)
{
hdata = GlobalAlloc(GHND, cb);
if (hdata == NULL)
{
SafeArrayUnaccessData(varData.parray);
return E_OUTOFMEMORY;
}
BYTE *pbDst = (BYTE *) GlobalLock(hdata);
memcpy(pbDst, pbSrc, cb);
fFree = TRUE;
}
else
{
BYTE *pbTest = (BYTE *) GlobalLock(hdata);
int i = 0;
if (pbTest != pbSrc)
i++;
GlobalUnlock(hdata);
}
CComPtr<IUnknown> punk;
{
CComPtr<IStream> pstream;
hr = CreateStreamOnHGlobal(hdata, fFree, &pstream);
if (FAILED(hr))
{
if (fFree)
GlobalFree(hdata);
return hr;
}
char ch;
ULONG cbT = sizeof(ch);
hr = pstream->Read(&ch, cbT, &cbT);
switch (ch)
{
case Format_IPersistStream:
hr = OleLoadFromStream(pstream, __uuidof(IUnknown), (void **) &punk);
break;
case Format_IPersistPropertyBag:
hr = LoadFromPropBagInStream(pstream, &punk);
break;
default:
return STG_E_DOCFILECORRUPT;
}
}
SafeArrayUnaccessData(varData.parray);
if (FAILED(hr))
return hr;
pvar->vt = VT_UNKNOWN;
pvar->punkVal = punk.Detach();
return S_OK;
}
HRESULT SeekPropsRS(ADODB::_RecordsetPtr prs, boolean fSQLServer,
long idObj, long idPropType, boolean fAnyProvider, long idProvider, long idLang)
{
_ASSERTE(idObj != 0);
HRESULT hr;
if (fAnyProvider && idProvider != NULL)
{
// First try to find the specified provider, only if it is not found
// do we look for any provider.
hr = SeekPropsRS(prs, fSQLServer, idObj, idPropType, FALSE, idProvider, idLang);
if (SUCCEEDED(hr))
return hr;
idProvider = NULL;
}
try
{
TCHAR szFind[32];
DeclarePerfTimerOff(perf, "SeekPropsRS");
#if 1
{
static bool fDump= FALSE;
if (fDump)
{
prs->MoveFirst();
while (!prs->EndOfFile)
{
long idObjCur = prs->Fields->Item["idObj"]->Value;
long idPropTypeCur = prs->Fields->Item["idPropType"]->Value;
TRACE("idObj = %d idPropType = %d\n", idObjCur, idPropTypeCur);
prs->MoveNext();
}
}
}
#endif
PerfTimerReset();
if (fSQLServer)
{
prs->MoveFirst();
wsprintf(szFind, _T("idObj = %d"), idObj);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
wsprintf(szFind, _T("idPropType = %d"), idPropType);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
}
else
{
// Create elements used in the array
_variant_t varCriteria[4];
varCriteria[0] = idObj;
varCriteria[1] = idPropType;
varCriteria[2] = idProvider;
varCriteria[3] = idLang;
const int nCrit = sizeof varCriteria /
sizeof varCriteria[0];
// Create SafeArray Bounds and initialize the array
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = nCrit;
SAFEARRAY *psa = SafeArrayCreate( VT_VARIANT, 1, rgsabound );
hr = S_OK;
// Set the values for each element of the array
for( long i = 0 ; i < nCrit && SUCCEEDED( hr );i++)
{
hr = SafeArrayPutElement(psa, &i,&varCriteria[i]);
}
// Initialize and fill the SafeArray
VARIANT var;
var.vt = VT_VARIANT | VT_ARRAY;
V_ARRAY(&var) = psa;
hr = prs->Seek(var,
fAnyProvider ? ADODB::adSeekAfterEQ : ADODB::adSeekFirstEQ);
if (FAILED(hr))
return hr;
if (prs->EndOfFile)
return E_INVALIDARG;
if (!fAnyProvider)
return S_OK;
}
while (TRUE)
{
if (prs->EndOfFile)
break;
long idObjCur = prs->Fields->Item["idObj"]->Value;
if (idObjCur != idObj)
break;
long idPropTypeCur = prs->Fields->Item["idPropType"]->Value;
if (idPropTypeCur != idPropType)
break;
long idLang2 = prs->Fields->Item["idLanguage"]->Value;
long idProvider2 = prs->Fields->Item["idProvider"]->Value;
if ((idLang == idLang2) && (fAnyProvider || (idProvider == idProvider2)))
{
PerfTimerDump("Successful seek");
return S_OK;
}
prs->MoveNext();
}
PerfTimerDump("Failed seek");
return E_INVALIDARG;
}
catch (_com_error & e)
{
TCHAR sz[1024];
wsprintf(sz, _T("Error: %s"), e.ErrorMessage());
return e.Error();
}
}
/////////////////////////////////////////////////////////////////////////////
// CMetaPropertySet
HRESULT CMetaPropertySet::Load()
{
HRESULT hr;
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropTypesRS(&prs);
if (FAILED(hr))
return hr;
if (!CreatePropTypes())
return E_OUTOFMEMORY;
prs->MoveFirst();
TCHAR szFind[20];
wsprintf(szFind, _T("idPropSet = %d"), m_id);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
while (!prs->EndOfFile)
{
CComPtr<CMetaPropertyType> pproptype;
long idPropSet = prs->Fields->Item["idPropSet"]->Value;
if (idPropSet != m_id)
break;
bstr_t bstrName = prs->Fields->Item["Name"]->Value;
long idPropType = prs->Fields->Item["idProp"]->Value;
long id = prs->Fields->Item["id"]->Value;
variant_t varNil;
hr = m_pproptypes->Cache(id, idPropType, bstrName, &pproptype);
prs->MoveNext();
}
return S_OK;
}
STDMETHODIMP CMetaPropertySet::get_Name(BSTR *pbstrName)
{
ENTER_API
{
ValidateOut(pbstrName);
*pbstrName = m_bstrName.copy();
return S_OK;
}
LEAVE_API
}
bool CMetaPropertySet::CreatePropTypes()
{
if (m_pproptypes == NULL)
{
CComPtr<CMetaPropertyTypes> pproptypes = NewComObject(CMetaPropertyTypes);
if (pproptypes == NULL)
return FALSE;
pproptypes->Init(m_pdb, this);
m_pproptypes = pproptypes;
}
return TRUE;
}
STDMETHODIMP CMetaPropertySet::get_MetaPropertyTypes(IMetaPropertyTypes **ppproptypes)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertyTypes>(ppproptypes, NULL);
if (!CreatePropTypes())
return E_OUTOFMEMORY;
(*ppproptypes = m_pproptypes)->AddRef();
return S_OK;
}
LEAVE_API
}
/////////////////////////////////////////////////////////////////////////////
// CMetaPropertySets
HRESULT CMetaPropertySets::Load()
{
HRESULT hr;
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropSetsRS(&prs);
if (FAILED(hr))
return hr;
prs->MoveFirst();
while (!prs->EndOfFile)
{
// Read in all the records
CComPtr<CMetaPropertySet> ppropset;
long id = prs->Fields->Item["id"]->Value;
bstr_t bstrName = prs->Fields->Item["Name"]->Value;
hr = Cache(id, bstrName, &ppropset);
if (SUCCEEDED(hr) && ppropset != NULL)
{
ppropset->Load();
}
prs->MoveNext();
}
return S_OK;
}
STDMETHODIMP CMetaPropertySets::get_Count(long *plCount)
{
ENTER_API
{
ValidateOut<long>(plCount);
*plCount = m_map.size();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertySets::get_Item(VARIANT varIndex, IMetaPropertySet **pppropset)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertySet>(pppropset, NULL);
if (varIndex.vt == VT_BSTR)
return get_ItemWithName(varIndex.bstrVal, pppropset);
_variant_t var(varIndex);
try
{
var.ChangeType(VT_I4);
}
catch (_com_error &)
{
return E_INVALIDARG;
}
long i = var.lVal;
if ((i < 0) || (i >= m_map.size()))
return E_INVALIDARG;
t_map::iterator it = m_map.begin();
while (i--)
it++;
*pppropset = (*it).second;
if (*pppropset != NULL)
(*pppropset)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertySets::get_ItemWithName(BSTR bstrName, IMetaPropertySet **pppropset)
{
ENTER_API
{
ValidateIn(bstrName);
ValidateOutPtr<IMetaPropertySet>(pppropset, NULL);
t_map::iterator it = m_map.find(bstrName);
if (it == m_map.end())
return E_INVALIDARG;
*pppropset = (*it).second;
(*pppropset)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertySets::get_Lookup(BSTR bstrName, IMetaPropertyType **ppproptype)
{
ENTER_API
{
HRESULT hr;
ValidateIn(bstrName);
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
if (bstrName == NULL)
return E_INVALIDARG;
wchar_t *szDot = wcschr(bstrName, L'.');
if (szDot == NULL)
return E_INVALIDARG;
_bstr_t bstrPropTypeName(szDot+1);
_bstr_t bstrPropSetName = SysAllocStringLen(bstrName, szDot - bstrName);
CComPtr<IMetaPropertySet> ppropset;
hr = get_AddNew(bstrPropSetName, &ppropset);
if (FAILED(hr))
return hr;
CComPtr<IMetaPropertyTypes> pproptypes;
hr = ppropset->get_MetaPropertyTypes(&pproptypes);
if (FAILED(hr))
return hr;
CComPtr<IMetaPropertyType> pproptype;
_variant_t varNil;
hr = pproptypes->get_AddNew(0, bstrPropTypeName, &pproptype);
if (FAILED(hr))
return hr;
*ppproptype = pproptype.Detach();
return S_OK;
}
LEAVE_API
}
HRESULT CMetaPropertySets::Cache(long id, BSTR bstrName, CMetaPropertySet **pppropset)
{
CComPtr<CMetaPropertySet> ppropset = NULL;
t_map::iterator it = m_map.find(bstrName);
if (it != m_map.end())
{
ppropset = (*it).second;
}
else
{
ppropset = NewComObject(CMetaPropertySet);
if (ppropset == NULL)
return E_OUTOFMEMORY;
ppropset->Init(m_pdb, id, bstrName);
BSTR bstrNameT = SysAllocString(bstrName);
if (bstrNameT == NULL)
return E_OUTOFMEMORY;
ppropset.CopyTo(&m_map[bstrNameT]);
}
*pppropset = ppropset.Detach();
return S_OK;
}
STDMETHODIMP CMetaPropertySets::get_AddNew(BSTR bstrName, IMetaPropertySet **pppropset)
{
ENTER_API
{
ValidateIn(bstrName);
ValidateOutPtr<IMetaPropertySet>(pppropset, NULL);
HRESULT hr;
hr = get_ItemWithName(bstrName, pppropset);
if (SUCCEEDED(hr))
return hr;
static long idCur = 1;
long id;
if (m_pdb == NULL)
id = idCur++;
else
{
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropSetsRS(&prs);
if (FAILED(hr))
return hr;
// Create a new record.
hr = prs->AddNew();
prs->Fields->Item["Name"]->Value = bstrName;
hr = prs->Update();
id = prs->Fields->Item["id"]->Value;
}
CMetaPropertySet *ppropset;
hr = Cache(id, bstrName, &ppropset);
*pppropset = ppropset;
return hr;
}
LEAVE_API
}
/////////////////////////////////////////////////////////////////////////////
// CMetaPropertyType
STDMETHODIMP CMetaPropertyType::get_MetaPropertySet(IMetaPropertySet **pppropset)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertySet>(pppropset, m_ppropset);
(*pppropset)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyType::get_ID(long *pid)
{
ENTER_API
{
ValidateOut<long>(pid, m_idPropType);
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyType::get_Name(BSTR *pbstrName)
{
ENTER_API
{
ValidateOut(pbstrName);
*pbstrName = m_bstrName.copy();
return S_OK;
}
LEAVE_API
}
HRESULT CMetaPropertyType::GetNew(long idProvider, long lang, VARIANT varValue, IMetaProperty **ppprop)
{
ENTER_API
{
ValidateOutPtr<IMetaProperty>(ppprop, NULL);
CComPtr<CMetaProperty> pprop = NewComObject(CMetaProperty);
if (pprop == NULL)
return E_OUTOFMEMORY;
pprop->Init(m_pdb, m_id, idProvider, lang, varValue);
*ppprop = pprop.Detach();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyType::get_Cond(BSTR bstrCond, long lang, VARIANT varValue, IMetaPropertyCondition **pppropcond)
{
ENTER_API
{
ValidateIn(bstrCond);
ValidateOutPtr<IMetaPropertyCondition>(pppropcond, NULL);
if (bstrCond == NULL)
return E_INVALIDARG;
HRESULT hr;
CComPtr<IMetaProperty> pprop;
hr = get_New(lang, varValue, &pprop);
if (FAILED(hr))
return hr;
return pprop->get_Cond(bstrCond, pppropcond);
}
LEAVE_API
}
/////////////////////////////////////////////////////////////////////////////
// CMetaPropertyTypes
STDMETHODIMP CMetaPropertyTypes::get_Count(long *plCount)
{
ENTER_API
{
ValidateOut<long>(plCount, m_map.size());
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyTypes::get_Item(VARIANT varIndex, IMetaPropertyType **ppproptype)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
if (varIndex.vt == VT_BSTR)
return get_ItemWithName(varIndex.bstrVal, ppproptype);
_variant_t var(varIndex);
try
{
var.ChangeType(VT_I4);
}
catch (_com_error &)
{
return E_INVALIDARG;
}
long i = var.lVal;
if ((i < 0) || (i >= m_map.size()))
return E_INVALIDARG;
t_map::iterator it = m_map.begin();
while (i--)
it++;
*ppproptype = (*it).second;
if (*ppproptype != NULL)
(*ppproptype)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyTypes::get_MetaPropertySet(IMetaPropertySet **pppropset)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertySet>(pppropset, m_ppropset);
if (*pppropset != NULL)
(*pppropset)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyTypes::get_ItemWithName(BSTR bstrName, IMetaPropertyType **ppproptype)
{
ENTER_API
{
ValidateIn(bstrName);
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
t_map::iterator it = m_map.find(bstrName);
if (it == m_map.end())
return E_INVALIDARG;
(*ppproptype = (*it).second)->AddRef();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyTypes::get_ItemWithID(long id, IMetaPropertyType **ppproptype)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
for (t_map::iterator it = m_map.begin(); it != m_map.end(); it++)
{
CComPtr<IMetaPropertyType> pproptype = (*it).second;
long idCur;
pproptype->get_ID(&idCur);
if (idCur == id)
{
*ppproptype = pproptype.Detach();
return S_OK;
}
}
return E_INVALIDARG;
}
LEAVE_API
}
HRESULT CMetaPropertyTypes::Cache(long id, long idPropType, BSTR bstrName,
CMetaPropertyType **ppproptype)
{
CComPtr<CMetaPropertyType> pproptype;
t_map::iterator it = m_map.find(bstrName);
if (it != m_map.end())
{
pproptype = (*it).second;
}
else
{
pproptype = NewComObject(CMetaPropertyType);
if (pproptype == NULL)
return E_OUTOFMEMORY;
pproptype->Init(m_pdb, m_ppropset, id, idPropType, bstrName);
BSTR bstrT = SysAllocString(bstrName);
pproptype.CopyTo(&m_map[bstrT]);
m_pdb->put_MetaPropertyType(id, pproptype);
}
*ppproptype = pproptype.Detach();
return S_OK;
}
STDMETHODIMP CMetaPropertyTypes::get_AddNew(long idProp, BSTR bstrName, IMetaPropertyType **ppproptype)
{
ENTER_API
{
ValidateIn(bstrName);
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
HRESULT hr;
hr = get_ItemWithName(bstrName, ppproptype);
if (SUCCEEDED(hr))
return hr;
CComPtr<CMetaPropertyType> pproptype;
static long idCur = 1;
long id;
if (m_pdb == NULL)
id = idCur++;
else
{
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropTypesRS(&prs);
if (FAILED(hr))
return hr;
// Create a new record.
hr = prs->AddNew();
prs->Fields->Item["idPropSet"]->Value = m_ppropset->GetID();
prs->Fields->Item["idProp"]->Value = idProp;
prs->Fields->Item["Name"]->Value = bstrName;
hr = prs->Update();
id = prs->Fields->Item["id"]->Value;
}
hr = Cache(id, idProp, bstrName, &pproptype);
if (FAILED(hr))
return hr;
*ppproptype = pproptype.Detach();
return S_OK;
}
LEAVE_API
}
/////////////////////////////////////////////////////////////////////////////
// CMetaProperty
STDMETHODIMP CMetaProperty::get_MetaPropertyType(IMetaPropertyType **ppproptype)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertyType>(ppproptype, NULL);
return m_pdb->get_MetaPropertyType(m_idPropType, ppproptype);
}
LEAVE_API
}
STDMETHODIMP CMetaProperty::get_Language(long *pidLang)
{
ENTER_API
{
ValidateOut<long>(pidLang, m_idLang);
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaProperty::get_Value(VARIANT *pvarValue)
{
ENTER_API
{
ValidateOut(pvarValue);
return VariantCopy(pvarValue, &m_varValue);
}
LEAVE_API
}
STDMETHODIMP CMetaProperty::put_Value(VARIANT varValue)
{
ENTER_API
{
// Changing the value, so must reset the provider.
m_idProvider = m_pdb->GetIDGuideDataProvider();
return PutValue(varValue);
}
LEAVE_API
}
STDMETHODIMP CMetaProperty::PutValue(VARIANT varValue)
{
HRESULT hr;
ADODB::_RecordsetPtr prs;
m_varValue = varValue;
hr = m_pdb->get_PropsIndexed(&prs);
if (FAILED(hr))
return hr;
hr = SeekPropsRS(prs, m_pdb->FSQLServer(), m_idObj,
m_idPropType, FALSE, m_idProvider, m_idLang);
if (FAILED(hr))
{
hr = AddNew(prs);
if (FAILED(hr))
return hr;
}
hr = SaveValue(prs);
if (FAILED(hr))
{
prs->CancelUpdate();
return hr;
}
hr = prs->Update();
if (FAILED(hr))
return hr;
m_pdb->Broadcast_ItemChanged(m_idObj);
return hr;
}
STDMETHODIMP CMetaProperty::get_QueryClause(long &i, TCHAR *szOp, _bstr_t *pbstr)
{
TCHAR *szFieldName;
TCHAR *szValue = NULL;
switch (m_varValue.vt)
{
default:
return E_INVALIDARG;
case VT_EMPTY:
return E_NOTIMPL; //Special case
case VT_I2:
case VT_I4:
{
szFieldName = _T("lValue");
int cb = 32;
szValue = new TCHAR [cb];
if (szValue == NULL)
return E_OUTOFMEMORY;
_sntprintf(szValue, cb, _T("%d"), (long) m_varValue);
}
break;
case VT_R4:
case VT_R8:
{
szFieldName = _T("fValue");
int cb = 32;
szValue = new TCHAR [cb];
if (szValue == NULL)
return E_OUTOFMEMORY;
_sntprintf(szValue, cb, _T("%.17f"), (double) m_varValue);
}
break;
case VT_DATE:
{
szFieldName = _T("fValue");
_variant_t varT;
::VariantChangeTypeEx(&varT, &m_varValue,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, VT_BSTR);
long cb = SysStringLen(varT.bstrVal) + 3;
szValue = new TCHAR [cb];
if (szValue == NULL)
return E_OUTOFMEMORY;
_sntprintf(szValue, cb, _T("#%s#"), (const TCHAR *) varT.bstrVal);
}
break;
case VT_BSTR:
{
_bstr_t bstr = m_varValue.bstrVal;
int cb = bstr.length() + 3; // Add on 2 quotes and null terminator
szValue = new TCHAR [cb];
if (szValue == NULL)
return E_OUTOFMEMORY;
if (bstr.length() < 255)
{
szFieldName = _T("sValue");
_sntprintf(szValue, cb, _T("\"%s\""),
(const TCHAR *) bstr);
}
else
{
delete [] szValue;
return E_INVALIDARG; //UNDONE: What to do?
}
}
break;
}
int cb = -1;
int cbBuf = 128;
TCHAR *sz = NULL;
while (cb < 0)
{
delete [] sz;
sz = new TCHAR [cbBuf];
if (sz == NULL)
return E_OUTOFMEMORY;
cb = _sntprintf(sz, cbBuf,
_T("(Props_%i.idPropType = %i) AND (Props_%i.%s %s %s)"),
i, m_idPropType, i, szFieldName, szOp, szValue);
cbBuf *= 2;
}
i++;
*pbstr = sz;
delete [] sz;
delete [] szValue;
return S_OK;
}
STDMETHODIMP CMetaProperty::get_Cond(BSTR bstrCond, IMetaPropertyCondition **pppropcond)
{
ENTER_API
{
ValidateIn(bstrCond);
ValidateOutPtr<IMetaPropertyCondition>(pppropcond, NULL);
if (bstrCond == NULL)
return E_INVALIDARG;
CComPtr<CMetaPropertyCondition1Prop> ppropcond = NULL;
if (wcscmp(bstrCond, L"=") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionEQ);
}
else if ((wcscmp(bstrCond, L"!=") == 0) || (wcscmp(bstrCond, L"<>") == 0))
{
ppropcond = NewComObject(CMetaPropertyConditionNE);
}
else if (_wcsicmp(bstrCond, L"LIKE") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionLike);
}
else if (_wcsicmp(bstrCond, L"NOT LIKE") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionNotLike);
}
else if (wcscmp(bstrCond, L"<") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionLT);
}
else if (wcscmp(bstrCond, L"<=") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionLE);
}
else if (wcscmp(bstrCond, L">") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionGT);
}
else if (wcscmp(bstrCond, L">=") == 0)
{
ppropcond = NewComObject(CMetaPropertyConditionGE);
}
else
{
return E_INVALIDARG;
}
if (ppropcond == NULL)
return E_OUTOFMEMORY;
ppropcond->Init(this);
*pppropcond = ppropcond.Detach();
return S_OK;
}
LEAVE_API
}
HRESULT CMetaProperty::AddNew(ADODB::_RecordsetPtr prs)
{
HRESULT hr;
// Create a new record.
hr = prs->AddNew();
if (FAILED(hr))
return hr;
prs->Fields->Item["idObj"]->Value = m_idObj;
prs->Fields->Item["idPropType"]->Value = m_idPropType;
prs->Fields->Item["idProvider"]->Value = m_idProvider;
prs->Fields->Item["idLanguage"]->Value = m_idLang;
return S_OK;
}
HRESULT CMetaProperty::SaveValue(ADODB::_RecordsetPtr prs)
{
HRESULT hr;
try
{
VARTYPE vt = m_varValue.vt;
IUnknown *punk;
switch (vt)
{
default:
return E_INVALIDARG;
case VT_EMPTY:
break;
case VT_I2:
case VT_I4:
prs->Fields->Item["lValue"]->Value = m_varValue;
break;
case VT_R4:
case VT_R8:
case VT_DATE:
prs->Fields->Item["fValue"]->Value = m_varValue;
break;
case VT_BSTR_BLOB:
case VT_BSTR:
prs->Fields->Item["sValue"]->Value = m_varValue;
break;
case VT_DISPATCH:
case VT_UNKNOWN:
#if 0
hr = SaveObjectToField(m_varValue, prs->Fields->Item["oValue"]);
if (FAILED(hr))
return hr;
#else
punk = m_varValue.punkVal;
goto SaveObj;
#endif
break;
case VT_BYREF | VT_UNKNOWN:
punk = *m_varValue.ppunkVal;
vt = VT_UNKNOWN;
SaveObj:
{
// Temporarily set to NULL
prs->Fields->Item["ValueType"]->Value = _variant_t((long) VT_UNKNOWN);
prs->Fields->Item["lValue"]->Value = _variant_t((long) NULL);
if (punk != NULL)
{
hr = prs->Update();
long idObj;
hr = m_pdb->SaveObject(punk, &idObj);
if (FAILED(hr))
return hr;
// Seek back and fix it up.
hr = SeekPropsRS(prs, m_pdb->FSQLServer(), m_idObj,
m_idPropType, FALSE, m_idProvider, m_idLang);
if (FAILED(hr))
return hr;
prs->Fields->Item["lValue"]->Value = idObj;
}
}
break;
}
prs->Fields->Item["ValueType"]->Value = _variant_t((long) vt);
}
catch (_com_error & e)
{
return e.Error();
}
return S_OK;
}
HRESULT CMetaProperty::LoadValue(ADODB::_RecordsetPtr prs)
{
HRESULT hr;
_variant_t varType = prs->Fields->Item["ValueType"]->Value;
try
{
varType.ChangeType(VT_I4);
}
catch (_com_error &)
{
return E_INVALIDARG;
}
switch (varType.lVal)
{
default:
return E_INVALIDARG;
case VT_EMPTY:
m_varValue.Clear();
break;
case VT_I2:
case VT_I4:
m_varValue = prs->Fields->Item["lValue"]->Value;
break;
case VT_R4:
case VT_R8:
case VT_DATE:
m_varValue = prs->Fields->Item["fValue"]->Value;
break;
case VT_BSTR_BLOB:
case VT_BSTR:
m_varValue = prs->Fields->Item["sValue"]->Value;
m_varValue.vt = varType.lVal;
break;
case VT_UNKNOWN:
#if 0
hr = LoadObjectFromField(prs->Fields->Item["oValue"], &m_varValue);
if (FAILED(hr))
return hr;
#else
{
CComPtr<IUnknown> punk;
long idObj = prs->Fields->Item["lValue"]->Value;
if (idObj != NULL)
{
hr = m_pdb->CacheObject(idObj, (long) 0, &punk);
if (FAILED(hr))
return hr;
}
m_varValue = punk;
}
#endif
break;
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMetaProperties
STDMETHODIMP CMetaProperties::get_Count(long *plCount)
{
ENTER_API
{
ValidateOut<long>(plCount, 0);
HRESULT hr;
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropsIndexed(&prs);
prs->MoveFirst();
TCHAR szFind[32];
wsprintf(szFind, _T("idObj = %d"), m_idObj);
hr = prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
if (FAILED(hr))
return S_OK;
if (m_idPropType != 0)
{
wsprintf(szFind, _T("idPropType = %d"), m_idPropType);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
if (prs->EndOfFile)
return S_OK;
}
// UNDONE: This is not the most efficient, but it's what works for now.
while (!prs->EndOfFile)
{
long idObj2 = prs->Fields->Item["idObj"]->Value;
if (m_idObj != idObj2)
break;
if (m_idPropType != 0)
{
long idPropType = prs->Fields->Item["idPropType"]->Value;
if (m_idPropType != idPropType)
break;
}
(*plCount)++;
hr = prs->MoveNext();
if (FAILED(hr))
return hr;
}
return S_OK;
}
LEAVE_API
}
HRESULT CMetaProperties::Load(long idPropType, ADODB::_RecordsetPtr prs, IMetaProperty **ppprop)
{
HRESULT hr;
CComPtr<IMetaPropertyType> pproptype;
CComPtr<IMetaProperty> pprop;
hr = m_pdb->get_MetaPropertyType(idPropType, &pproptype);
if (FAILED(hr))
return hr;
long idLang = prs->Fields->Item["idLanguage"]->Value;
long idProvider = prs->Fields->Item["idProvider"]->Value;
CComQIPtr<CMetaPropertyType> pproptypeT(pproptype);
_variant_t varValue;
hr = pproptypeT->GetNew(idProvider, idLang, varValue, &pprop);
if (FAILED(hr))
return hr;
CComQIPtr<CMetaProperty> ppropT(pprop);
ppropT->SetObjectID(m_idObj);
hr = ppropT->LoadValue(prs);
if (FAILED(hr))
return hr;
*ppprop = pprop.Detach();
return S_OK;
}
STDMETHODIMP CMetaProperties::get_Item(VARIANT varIndex, IMetaProperty **ppprop)
{
ENTER_API
{
ValidateOutPtr<IMetaProperty>(ppprop, NULL);
HRESULT hr;
if (varIndex.vt == VT_BSTR)
{
CComPtr<IMetaPropertyType> pproptype;
hr = m_pdb->get_MetaPropertyType(varIndex.bstrVal, &pproptype);
if (FAILED(hr))
return E_INVALIDARG;
hr = get_ItemWith(pproptype, 0, ppprop);
if (FAILED(hr))
{
CComPtr<IGuideDataProvider> pprovider;
m_pdb->get_GuideDataProvider(&pprovider);
_variant_t varNil;
hr = get_AddNew(pproptype, pprovider, 0, varNil, ppprop);
}
return hr;
}
_variant_t var(varIndex);
try
{
var.ChangeType(VT_I4);
}
catch (_com_error &)
{
return E_INVALIDARG;
}
if (var.lVal < 0)
return E_INVALIDARG;
ADODB::_RecordsetPtr prs;
hr = m_pdb->get_PropsIndexed(&prs);
prs->MoveFirst();
TCHAR szFind[32];
wsprintf(szFind, _T("idObj = %d"), m_idObj);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
if (prs->EndOfFile)
return E_INVALIDARG;
if (m_idPropType != 0)
{
wsprintf(szFind, _T("idPropType = %d"), m_idPropType);
prs->Find(_bstr_t(szFind), 0, ADODB::adSearchForward);
if (prs->EndOfFile)
return E_INVALIDARG;
}
if (var.lVal > 0)
{
hr = prs->Move(var.lVal);
if (FAILED(hr))
return hr;
}
if (prs->EndOfFile)
return E_INVALIDARG;
long idObj2 = prs->Fields->Item["idObj"]->Value;
if (m_idObj != idObj2)
return E_INVALIDARG;
long idPropType = prs->Fields->Item["idPropType"]->Value;
if (m_idPropType != 0 && (m_idPropType != idPropType))
return E_INVALIDARG;
return Load(idPropType, prs, ppprop);
}
LEAVE_API
}
HRESULT CMetaProperties::get_AddNew(IMetaPropertyType *pproptype,
IGuideDataProvider *pprovider, long lang, VARIANT varValue,
IMetaProperty **ppprop)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyType>(pproptype);
ValidateOutPtr<IMetaProperty>(ppprop, NULL);
HRESULT hr;
CComQIPtr<CMetaPropertyType> pproptypeT(pproptype);
long idProvider = 0;
if (pprovider != NULL)
pprovider->get_ID(&idProvider);
hr = pproptypeT->GetNew(idProvider, lang, varValue, ppprop);
if (FAILED(hr))
return hr;
return Add(*ppprop);
}
LEAVE_API
}
STDMETHODIMP CMetaProperties::get_AddNew(IMetaPropertyType *pproptype, long lang, VARIANT varValue, IMetaProperty **ppprop)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyType>(pproptype);
ValidateOutPtr<IMetaProperty>(ppprop, NULL);
HRESULT hr = pproptype->get_New(lang, varValue, ppprop);
if (FAILED(hr))
return hr;
return Add(*ppprop);
}
LEAVE_API
}
#if 0
STDMETHODIMP CMetaProperties::get_UpdateOrAddNew(IMetaPropertyType *pproptype, long lang, VARIANT varValue, IMetaProperty **ppprop)
{
HRESULT hr;
CComPtr<IMetaProperty> pprop;
hr = get_ItemWith(pproptype, lang, &pprop);
if (FAILED(hr))
return AddNew(pproptype, lang, varValue, ppprop);
hr = pprop->put_Value(varValue);
if (FAILED(hr))
return hr;
*ppprop = pprop.Detach();
return S_OK;
}
#endif
STDMETHODIMP CMetaProperties::Add(IMetaProperty *pprop)
{
HRESULT hr;
if (pprop == NULL)
return E_FAIL;
ADODB::_RecordsetPtr prs;
m_pdb->get_PropsRS(&prs);
CComQIPtr<CMetaProperty> ppropT(pprop);
hr = ppropT->SetObjectID(m_idObj);
if (FAILED(hr))
return hr;
hr = ppropT->AddNew(prs);
if (FAILED(hr))
return hr;
hr = ppropT->SaveValue(prs);
if (FAILED(hr))
{
prs->CancelUpdate();
return hr;
}
hr = prs->Update();
if (FAILED(hr))
return hr;
m_pdb->Broadcast_ItemChanged(m_idObj);
return hr;
}
STDMETHODIMP CMetaProperties::get_ItemWithTypeProviderLang(IMetaPropertyType *pproptype,
IGuideDataProvider *pprovider, long idLang, IMetaProperty **ppprop)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyType>(pproptype);
ValidateOutPtr<IMetaProperty>(ppprop, NULL);
long idProvider = 0;
if (pprovider != NULL)
pprovider->get_ID(&idProvider);
return get_ItemWithTypeProviderLang(pproptype, FALSE, idProvider, idLang, ppprop);
}
LEAVE_API
}
HRESULT CMetaProperties::get_ItemWithTypeProviderLang(IMetaPropertyType *pproptype,
boolean fAnyProvider, long idProvider, long idLang, IMetaProperty **ppprop)
{
HRESULT hr;
ADODB::_RecordsetPtr prs;
CComQIPtr<CMetaPropertyType> pproptypeT(pproptype);
long idPropType = pproptypeT->GetID();
hr = m_pdb->get_PropsIndexed(&prs);
hr = SeekPropsRS(prs, m_pdb->FSQLServer(), m_idObj,
idPropType, fAnyProvider, idProvider, idLang);
if (FAILED(hr))
return hr;
return Load(idPropType, prs, ppprop);
}
STDMETHODIMP CMetaProperties::get_ItemWith(IMetaPropertyType *pproptype, long idLang, IMetaProperty **ppprop)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyType>(pproptype);
ValidateOutPtr<IMetaProperty>(ppprop);
long idProvider = m_pdb->GetIDGuideDataProvider();
return get_ItemWithTypeProviderLang(pproptype, TRUE, idProvider, idLang, ppprop);
}
LEAVE_API
}
STDMETHODIMP CMetaProperties::get_ItemsWithMetaPropertyType(IMetaPropertyType *ptype, IMetaProperties **ppprops)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyType>(ptype);
ValidateOutPtr<IMetaProperties>(ppprops, NULL);
CComQIPtr<CMetaPropertyType> ptypeT(ptype);
if (ptypeT == NULL)
return E_POINTER;
long idPropType;
idPropType = ptypeT->GetID();
CComPtr<CMetaProperties> pprops = NewComObject(CMetaProperties);
if (pprops != NULL)
pprops->Init(m_idObj, idPropType, m_pdb);
*ppprops = pprops.Detach();
return S_OK;
}
LEAVE_API
}
/////////////////////////////////////////////////////////////////////////////
// CMetaPropertyCondition
STDMETHODIMP CMetaPropertyCondition::get_And(IMetaPropertyCondition *ppropcond2, IMetaPropertyCondition **pppropcond)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyCondition>(ppropcond2);
ValidateOutPtr<IMetaPropertyCondition>(pppropcond, NULL);
CComPtr<CMetaPropertyConditionAnd> ppropcond = NewComObject(CMetaPropertyConditionAnd);
if (ppropcond == NULL)
return E_OUTOFMEMORY;
ppropcond->Init(this, ppropcond2);
*pppropcond = ppropcond.Detach();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyCondition::get_Or(IMetaPropertyCondition *ppropcond2, IMetaPropertyCondition **pppropcond)
{
ENTER_API
{
ValidateInPtr<IMetaPropertyCondition>(ppropcond2);
ValidateOutPtr<IMetaPropertyCondition>(pppropcond, NULL);
CComPtr<CMetaPropertyConditionOr> ppropcond = NewComObject(CMetaPropertyConditionOr);
if (ppropcond == NULL)
return E_OUTOFMEMORY;
ppropcond->Init(this, ppropcond2);
*pppropcond = ppropcond.Detach();
return S_OK;
}
LEAVE_API
}
#if 0
STDMETHODIMP CMetaPropertyCondition::get_Not(IMetaPropertyCondition **pppropcond)
{
ENTER_API
{
ValidateOutPtr<IMetaPropertyCondition>(pppropcond, NULL);
CComPtr<CMetaPropertyConditionNot> ppropcond = NewComObject(CMetaPropertyConditionNot);
if (ppropcond == NULL)
return E_OUTOFMEMORY;
ppropcond->Init(this);
*pppropcond = ppropcond.Detach();
return S_OK;
}
LEAVE_API
}
STDMETHODIMP CMetaPropertyCondition::get_Test(IMetaProperties *pprops, BOOL *pfOk)
{
ENTER_API
{
ValidateInPtr<IMetaProperties>(pprops);
ValidateOut<BOOL>(pfOk, FALSE);
return S_OK;
}
LEAVE_API
}
#endif