|
|
#include "oleds.hxx"
#if (!defined(BUILD_FOR_NT40))
// ---------------- C D B P R O P E R T I E S C O D E ----------------------
//-----------------------------------------------------------------------------
// CDBProperties::CDBProperties
//
// @mfunc
// CDBProperties constructor.
//
// @rdesc NONE
//-----------------------------------------------------------------------------
CDBProperties::CDBProperties(): _cPropSets(0), _aPropSets(0), _cPropInfoSets(0), _aPropInfoSets(0) { }
//-----------------------------------------------------------------------------
// CDBProperties::~CDBProperties
//
// @mfunc
// CDBProperties destructor. Release storage used by CDBProperties.
//
// @rdesc NONE
//-----------------------------------------------------------------------------
CDBProperties::~CDBProperties() { ULONG iSet, iProp, iSetInfo;
for (iSet=0; iSet<_cPropSets; ++iSet) { for (iProp=0; iProp <_aPropSets[iSet].cProperties; ++iProp) VariantClear(&(_aPropSets[iSet].rgProperties[iProp].vValue)); delete [] _aPropSets[iSet].rgProperties; } delete [] _aPropSets;
for (iSet=0; iSet<_cPropInfoSets; ++iSet) { delete [] _aPropInfoSets[iSet].rgPropertyInfos; } delete [] _aPropInfoSets; }
//-----------------------------------------------------------------------------
// CDBProperties::GetPropertySet
//
// @mfunc Looks up a property set by its GUID.
//
// @rdesc Pointer to desired property set, or 0 if not found.
//-----------------------------------------------------------------------------
DBPROPSET* CDBProperties::GetPropertySet(const GUID& guid) const { DBPROPSET* pPropSet = 0; // the answer, assume not found
// linear search
ULONG iPropSet; for (iPropSet=0; iPropSet<_cPropSets; ++iPropSet) { if (IsEqualGUID(guid, _aPropSets[iPropSet].guidPropertySet)) { pPropSet = &_aPropSets[iPropSet]; break; } }
return ( pPropSet ); }
//-----------------------------------------------------------------------------
// CDBProperties::GetPropertyInfoSet
//
// @mfunc Looks up a property info set by its GUID.
//
// @rdesc Pointer to desired property info set, or 0 if not found.
//-----------------------------------------------------------------------------
DBPROPINFOSET* CDBProperties::GetPropertyInfoSet(const GUID& guid) const { DBPROPINFOSET* pPropInfoSet = 0; // the answer, assume not found
// linear search
ULONG iPropSet; for (iPropSet=0; iPropSet<_cPropInfoSets; ++iPropSet) { if (IsEqualGUID(guid, _aPropInfoSets[iPropSet].guidPropertySet)) { pPropInfoSet = &_aPropInfoSets[iPropSet]; break; } }
return ( pPropInfoSet ); }
//-----------------------------------------------------------------------------
// CDBProperties::CopyPropertySet
//
// @mfunc Makes a copy of a property set, given its GUID.
//
// @rdesc
// @flag S_OK | copying succeeded,
// @flag E_FAIL | no property set for given GUID,
// @flag E_OUTOFMEMORY | copying failed because of memory allocation.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::CopyPropertySet(const GUID& guid, DBPROPSET* pPropSetDst) const { ADsAssert(pPropSetDst && "must supply a PropSet pointer");
HRESULT hr = S_OK; const DBPROPSET* pPropSetSrc = GetPropertySet(guid); ULONG iProp;
if (pPropSetSrc == 0) // not found
{ hr = E_FAIL; goto Cleanup; }
// start with shallow copy
*pPropSetDst = *pPropSetSrc;
// allocate property array
pPropSetDst->rgProperties = (DBPROP*) CoTaskMemAlloc(pPropSetSrc->cProperties * sizeof(DBPROP)); if (pPropSetDst->rgProperties == 0) { pPropSetDst->cProperties = 0; // defensive
hr = E_OUTOFMEMORY; goto Cleanup; }
memcpy( pPropSetDst->rgProperties, pPropSetSrc->rgProperties, pPropSetSrc->cProperties*sizeof(DBPROP));
// copy the property array
for (iProp=0; iProp<pPropSetSrc->cProperties; ++iProp) { VariantInit(&(pPropSetDst->rgProperties[iProp].vValue)); if(FAILED(hr = VariantCopy(&(pPropSetDst->rgProperties[iProp].vValue), (VARIANT *)&(pPropSetSrc->rgProperties[iProp].vValue)))) { while(iProp) { iProp--; VariantClear(&(pPropSetDst->rgProperties[iProp].vValue)); } CoTaskMemFree(pPropSetDst->rgProperties); pPropSetDst->rgProperties = NULL; pPropSetDst->cProperties = 0; // defensive
goto Cleanup; } }
Cleanup: RRETURN ( hr ); }
//-----------------------------------------------------------------------------
// CDBProperties::CopyPropertyInfoSet
//
// @mfunc Makes a copy of a property info set, given its GUID.
//
// @rdesc
// @flag S_OK | copying succeeded,
// @flag E_FAIL | no property set for given GUID,
// @flag E_OUTOFMEMORY | copying failed because of memory allocation.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::CopyPropertyInfoSet ( const GUID& guid, DBPROPINFOSET* pPropInfoSetDst, WCHAR** ppDescBuffer, ULONG_PTR* pcchDescBuffer, ULONG_PTR* pichCurrent ) const { ADsAssert(pPropInfoSetDst && "must supply a PropSet pointer");
HRESULT hr = S_OK; const DBPROPINFOSET* pPropInfoSetSrc = GetPropertyInfoSet(guid);
if (pPropInfoSetSrc == 0) // not found
{ hr = E_FAIL; goto Cleanup; }
// start with shallow copy
*pPropInfoSetDst = *pPropInfoSetSrc;
// allocate property array
pPropInfoSetDst->rgPropertyInfos = (DBPROPINFO *) CoTaskMemAlloc( pPropInfoSetSrc->cPropertyInfos * sizeof(DBPROPINFO));
if (pPropInfoSetDst->rgPropertyInfos == 0) { pPropInfoSetDst->cPropertyInfos = 0; // defensive
hr = E_OUTOFMEMORY; goto Cleanup; }
memcpy( pPropInfoSetDst->rgPropertyInfos, pPropInfoSetSrc->rgPropertyInfos, pPropInfoSetSrc->cPropertyInfos*sizeof(DBPROPINFO));
if(FAILED(hr =CopyPropertyDescriptions( pPropInfoSetDst, ppDescBuffer, pcchDescBuffer, pichCurrent))) { CoTaskMemFree(pPropInfoSetDst->rgPropertyInfos); pPropInfoSetDst->rgPropertyInfos = NULL; pPropInfoSetDst->cPropertyInfos = 0; // defensive
hr = E_OUTOFMEMORY; }
Cleanup: RRETURN ( hr ); }
//-----------------------------------------------------------------------------
// CDBProperties::GetProperty
//
// @mfunc Looks up a property by its property set GUID and ID.
//
// @rdesc Pointer to DBPROP for the property, or 0 if not found.
//-----------------------------------------------------------------------------
const DBPROP* CDBProperties::GetProperty(const GUID& guid, DBPROPID dwId) const { ULONG iProp; const DBPROPSET* pPropSet = GetPropertySet(guid); const DBPROP* pProp = 0; // the answer, assume not found
if (pPropSet == 0) // no properties for desired property set
goto Cleanup;
// look up the desired property in the property set
for (iProp=0; iProp<pPropSet->cProperties; ++iProp) { if (dwId == pPropSet->rgProperties[iProp].dwPropertyID) { pProp = & pPropSet->rgProperties[iProp]; break; } }
Cleanup: return ( pProp ); }
//-----------------------------------------------------------------------------
// CDBProperties::GetPropertyInfo
//
// @mfunc Looks up a property info by its property set GUID and ID.
//
// @rdesc Pointer to DBPROPINFO for the property info, or 0 if not found.
//-----------------------------------------------------------------------------
const DBPROPINFO UNALIGNED* CDBProperties::GetPropertyInfo(const GUID& guid, DBPROPID dwId) const { ULONG iPropInfo; const DBPROPINFOSET* pPropInfoSet = GetPropertyInfoSet(guid); const DBPROPINFO UNALIGNED* pPropInfo = 0; // the answer, assume not found
if (pPropInfoSet == 0) // no properties for desired property set
goto Cleanup;
// look up the desired property in the property set
for (iPropInfo=0; iPropInfo <pPropInfoSet->cPropertyInfos; ++iPropInfo) { if (dwId == pPropInfoSet->rgPropertyInfos[iPropInfo].dwPropertyID) { pPropInfo = & pPropInfoSet->rgPropertyInfos[iPropInfo]; break; } }
Cleanup: return ( pPropInfo ); }
//-----------------------------------------------------------------------------
// CDBProperties::SetProperty
//
// @mfunc Adds a new property, or resets an existing one
// This overloaded function is same as the other except that the
// last parameter is of type PWSTR [mgorti]
//
// @rdesc
// @flag S_OK | property added/reset,
// @flag E_OUTOFMEMORY | no memory for new property set or new property.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::SetProperty(const GUID& guid, const DBPROP& prop, BOOL fAddNew, PWSTR pwszDesc) { HRESULT hr; DBPROP *pProp; // pointer to array entry for new property
ULONG iProp; DBPROPSET* pPropSet = GetPropertySet(guid);
if (pPropSet == 0) // no properties yet in desired property set
{ if(!fAddNew) { hr = E_FAIL; goto Cleanup; }
// get a new property set array
DBPROPSET * aNewPropSets = new DBPROPSET[_cPropSets + 1]; if (aNewPropSets == 0) { hr = E_OUTOFMEMORY; goto Cleanup; } memcpy(aNewPropSets, _aPropSets, _cPropSets *sizeof(DBPROPSET));
// add the new property set
pPropSet = & aNewPropSets[_cPropSets]; pPropSet->guidPropertySet = guid; pPropSet->cProperties = 0; pPropSet->rgProperties = 0;
// release the old array, install the new one
delete [] _aPropSets; _aPropSets = aNewPropSets; ++ _cPropSets; }
// look for the desired property.
if(!fAddNew) { pProp = 0; for (iProp=0; iProp<pPropSet->cProperties; ++iProp) { if (pPropSet->rgProperties[iProp].dwPropertyID == prop.dwPropertyID) { pProp = &pPropSet->rgProperties[iProp]; break; } } if (pProp == 0) { hr = E_FAIL; goto Cleanup; } }
// if it's a new property, add it. OLE-DB doesn't provide for any "unused"
// portion in the array of DBPROPS, so we must reallocate the array every
// time we add a property.
else { ULONG cPropLeftOver;
// allocate new property array
cPropLeftOver = C_PROP_INCR - (pPropSet->cProperties + C_PROP_INCR - 1)%C_PROP_INCR - 1; if(cPropLeftOver) { pProp = &pPropSet->rgProperties[pPropSet->cProperties]; } else { DBPROP* aNewProperties = new DBPROP[pPropSet->cProperties + C_PROP_INCR]; if (aNewProperties == 0) { hr = E_OUTOFMEMORY; goto Cleanup; }
// copy old array into new
memcpy( aNewProperties, pPropSet->rgProperties, pPropSet->cProperties *sizeof(DBPROP));
// prepare to use new property entry
pProp = & aNewProperties[pPropSet->cProperties];
// release old array, install new
delete [] pPropSet->rgProperties; pPropSet->rgProperties = aNewProperties; } ++ pPropSet->cProperties; }
// copy the property into my array
if(!fAddNew) { DBPROP propSave;
propSave = *pProp; *pProp = prop; VariantInit(&(pProp->vValue)); if(FAILED(hr = VariantCopy( &(pProp->vValue), (VARIANT *)&(prop.vValue)))) { *pProp = propSave; goto Cleanup; } } else { DBPROPINFO propinfo;
*pProp = prop; propinfo.pwszDescription = pwszDesc; propinfo.dwPropertyID = prop.dwPropertyID; propinfo.dwFlags = DBPROPFLAGS_READ; if(guid == DBPROPSET_DBINIT) propinfo.dwFlags |= DBPROPFLAGS_DBINIT; else if(guid == DBPROPSET_DATASOURCEINFO) propinfo.dwFlags |= DBPROPFLAGS_DATASOURCEINFO; else propinfo.dwFlags |= DBPROPFLAGS_ROWSET; propinfo.vtType = V_VT(&(prop.vValue)); VariantInit(&(propinfo.vValues)); if(FAILED(hr = SetPropertyInfo(guid, propinfo))) goto Cleanup; }
hr = S_OK;
Cleanup: RRETURN ( hr ); }
//-----------------------------------------------------------------------------
// CDBProperties::SetPropertyInfo
//
// @mfunc Adds a new property info, or resets an existing one.
//
// @rdesc
// @flag S_OK | property info added/reset,
// @flag E_OUTOFMEMORY | no memory for new property info set
// or new property info.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::SetPropertyInfo(const GUID& guid, const DBPROPINFO& propinfo) { HRESULT hr; PDBPROPINFO pPropInfo; // pointer to array entry for new property
ULONG iPropInfo; DBPROPINFOSET* pPropInfoSet = GetPropertyInfoSet(guid);
if (pPropInfoSet == 0) // no properties yet in desired property set
{
// get a new property set array
DBPROPINFOSET * aNewPropInfoSets = new DBPROPINFOSET[_cPropInfoSets + 1];
if (aNewPropInfoSets == 0) { hr = E_OUTOFMEMORY; goto Cleanup; }
memcpy( aNewPropInfoSets, _aPropInfoSets, _cPropInfoSets *sizeof(DBPROPINFOSET));
// add the new property set
pPropInfoSet = & aNewPropInfoSets[_cPropInfoSets]; pPropInfoSet->guidPropertySet = guid; pPropInfoSet->cPropertyInfos = 0; pPropInfoSet->rgPropertyInfos = 0;
// release the old array, install the new one
delete [] _aPropInfoSets; _aPropInfoSets = aNewPropInfoSets; ++ _cPropInfoSets; }
// look for the desired property.
pPropInfo = 0; for (iPropInfo=0; iPropInfo<pPropInfoSet->cPropertyInfos; ++iPropInfo) { if (pPropInfoSet->rgPropertyInfos[iPropInfo].dwPropertyID == propinfo.dwPropertyID) { pPropInfo = &pPropInfoSet->rgPropertyInfos[iPropInfo]; break; } }
// if it's a new property, add it. OLE-DB doesn't provide for any "unused"
// portion in the array of DBPROPS, so we must reallocate the array every
// time we add a property.
if (pPropInfo == 0) { ULONG cPropLeftOver;
// allocate new property array
cPropLeftOver = C_PROP_INCR - (pPropInfoSet->cPropertyInfos + C_PROP_INCR - 1)%C_PROP_INCR - 1;
if(cPropLeftOver) { pPropInfo = &pPropInfoSet->rgPropertyInfos[pPropInfoSet->cPropertyInfos]; } else { DBPROPINFO* aNewPropertyInfos = new DBPROPINFO[pPropInfoSet->cPropertyInfos + C_PROP_INCR];
if (aNewPropertyInfos == 0) { hr = E_OUTOFMEMORY; goto Cleanup; }
// copy old array into new
memcpy( aNewPropertyInfos, pPropInfoSet->rgPropertyInfos, pPropInfoSet->cPropertyInfos *sizeof(DBPROPINFO));
// prepare to use new property entry
pPropInfo = & aNewPropertyInfos[pPropInfoSet->cPropertyInfos];
// release old array, install new
delete [] pPropInfoSet->rgPropertyInfos; pPropInfoSet->rgPropertyInfos = aNewPropertyInfos; } ++ pPropInfoSet->cPropertyInfos; }
// copy the property into my array
*pPropInfo = propinfo;
hr = S_OK;
Cleanup: RRETURN ( hr ); }
//-----------------------------------------------------------------------------
// CDBProperties::LoadDescription
//
// @mfunc Loads a localized string from the localization DLL.
//
// @rdesc Count of characters returned in the buffer.
//-----------------------------------------------------------------------------
int CDBProperties::LoadDescription ( ULONG ids, //@parm IN | String ID
PWSTR pwszBuff, //@parm OUT | Temporary buffer
ULONG cchBuff //@parm IN | Count of characters buffer can hold
) const { return ( 0 ); // return( LoadStringW(g_hinstDll, ids, pwszBuff, cchBuff) );
}
//-----------------------------------------------------------------------------
// CDBProperties::CopyPropertyDescriptions
//
// @mfunc Copies into a buffer descriptions of properties in a given set.
//
// @rdesc
// @flag S_OK | copying of property descriptions succeeded,
// @flag E_OUTOFMEMORY | buffer for property descriptions could not
// be allocated/extended.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::CopyPropertyDescriptions ( DBPROPINFOSET* pPropInfoSet, WCHAR** ppDescBuffer, ULONG_PTR* pcchDescBuffer, ULONG_PTR* pichCurrent ) const { LONG iprop, cchLeft, cchNew; int cchCopied; WCHAR *pwszTmp;
if(ppDescBuffer) { cchLeft = (LONG)*pcchDescBuffer - (LONG)*pichCurrent; for(iprop =0; (ULONG)iprop <pPropInfoSet->cPropertyInfos; iprop++) { if(pPropInfoSet->rgPropertyInfos[iprop].dwFlags == DBPROPFLAGS_NOTSUPPORTED) continue;
if(cchLeft < (LONG)CCHAR_MAX_PROP_STR_LENGTH) { cchNew = CCHAR_AVERAGE_PROP_STR_LENGTH * (pPropInfoSet->cPropertyInfos - iprop - 1) + CCHAR_MAX_PROP_STR_LENGTH + *pcchDescBuffer - cchLeft;
pwszTmp = (WCHAR *)CoTaskMemAlloc(cchNew *sizeof(WCHAR)); if(pwszTmp == NULL) RRETURN ( E_OUTOFMEMORY );
if(*ppDescBuffer) { memcpy( pwszTmp, *ppDescBuffer, (*pcchDescBuffer -cchLeft)*sizeof(WCHAR));
CoTaskMemFree(*ppDescBuffer); } cchLeft += cchNew -(LONG)*pcchDescBuffer; *ppDescBuffer = pwszTmp; *pcchDescBuffer = cchNew; }
//?? Do we need to load these strings from resources ??
//$TODO$ Raid #86943 Copy property descriptions from source to destination buffer.
cchCopied = wcslen(pPropInfoSet->rgPropertyInfos[iprop].pwszDescription); wcscpy((WCHAR *)(*ppDescBuffer) + *pichCurrent, pPropInfoSet->rgPropertyInfos[iprop].pwszDescription); pPropInfoSet->rgPropertyInfos[iprop].pwszDescription = (WCHAR *)(*pichCurrent);
*pichCurrent += (cchCopied +1); cchLeft -= (cchCopied +1); } } else { // We need to NULL out the pwszDescription values:
//
for(iprop =0; (ULONG)iprop <pPropInfoSet->cPropertyInfos; iprop++) { pPropInfoSet->rgPropertyInfos[iprop].pwszDescription = NULL; } }
RRETURN ( NOERROR ); }
//-----------------------------------------------------------------------------
// CDBProperties::CheckAndInitPropArgs
//
// @mfunc Helper function used while getting property sets.
// Used to check and get information about property sets.
// Tells if the caller is requesting
// special sets or the set of properties in error.
//
// @rdesc
// @flag S_OK | check succeeded,
// @flag E_INVALIDARG | one of the arguments is invalid.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::CheckAndInitPropArgs ( ULONG cPropertySets, // IN | Number of property sets
const DBPROPIDSET rgPropertySets[], // IN | Property Sets
ULONG *pcPropertySets, // OUT | Count of structs returned
void **prgPropertySets,// OUT | Array of Properties
BOOL *pfPropInError, BOOL *pfPropSpecial ) { LONG ipropset; ULONG cpropsetSpecial;
// Initialize
if( pcPropertySets ) *pcPropertySets = 0; if( prgPropertySets ) *prgPropertySets = NULL; if(pfPropInError) *pfPropInError = FALSE; if(pfPropSpecial) *pfPropSpecial = FALSE;
// Check Arguments, on failure post HRESULT to error queue
if( ((cPropertySets > 0) && !rgPropertySets) || !pcPropertySets || !prgPropertySets ) RRETURN ( E_INVALIDARG );
// New argument check for > 1 cPropertyIDs and NULL pointer for
// array of property ids.
for(ipropset=0, cpropsetSpecial = 0; (ULONG)ipropset<cPropertySets; ipropset++) { if( rgPropertySets[ipropset].cPropertyIDs && !(rgPropertySets[ipropset].rgPropertyIDs) ) RRETURN (E_INVALIDARG);
//when passing property set DBPROPSET_PROPERTIESINERROR,
//this is the only set the caller can ask. Also, the
//count of propertyIDs and the propertyID array must be
//NULL in this case.
if( rgPropertySets[ipropset].guidPropertySet == DBPROPSET_PROPERTIESINERROR ) { if(pfPropInError) { if(cPropertySets >1 || rgPropertySets[ipropset].cPropertyIDs || rgPropertySets[ipropset].rgPropertyIDs) RRETURN (E_INVALIDARG); else *pfPropInError = TRUE; } } //Count the number of special property sets being asked.
else if( rgPropertySets[ipropset].guidPropertySet == DBPROPSET_DATASOURCEALL || rgPropertySets[ipropset].guidPropertySet == DBPROPSET_DATASOURCEINFOALL || rgPropertySets[ipropset].guidPropertySet == DBPROPSET_DBINITALL || rgPropertySets[ipropset].guidPropertySet == DBPROPSET_SESSIONALL || rgPropertySets[ipropset].guidPropertySet == DBPROPSET_ROWSETALL) cpropsetSpecial++; }
//When requesting special property sets, all of them
//must be special or none.
if(cpropsetSpecial) { if(pfPropSpecial) *pfPropSpecial = TRUE; if(cpropsetSpecial < cPropertySets) RRETURN (E_INVALIDARG); } else if(pfPropSpecial) *pfPropSpecial = FALSE;
RRETURN ( NOERROR ); }
//-----------------------------------------------------------------------------
// CDBProperties::VerifySetPropertiesArgs
//
// @mfunc Helper function used in IDBProperties::SetProperties. Validates
// arguments passed to IDBProperties::SetProperties.
//
// @rdesc
// @flag S_OK | Validation succeeded.
// @flag E_INVALIDARG | Validation failed - one of the arguments
// is in error.
//-----------------------------------------------------------------------------
HRESULT CDBProperties::VerifySetPropertiesArgs ( ULONG cPropertySets, //@parm IN | Count of properties
DBPROPSET rgPropertySets[] //@parm IN | Properties
) { ULONG ipropset;
if(cPropertySets && rgPropertySets == NULL) RRETURN (E_INVALIDARG);
for(ipropset =0; ipropset <cPropertySets; ipropset++) if( rgPropertySets[ipropset].cProperties && rgPropertySets[ipropset].rgProperties == NULL) RRETURN (E_INVALIDARG);
RRETURN ( NOERROR ); }
//-----------------------------------------------------------------------------
// VariantsEqual
//
// @mfunc Tests two variants holding property values for equality.
//
// @rdesc
// @flag TRUE | values equal,
// @flag FALSE | values unequal.
//-----------------------------------------------------------------------------
BOOL VariantsEqual ( VARIANT *pvar1, VARIANT *pvar2 ) { if(V_VT(pvar1) != V_VT(pvar1)) return ( FALSE ); else if(V_VT(pvar1) == VT_I2) return (V_I2(pvar1) == V_I2(pvar2)); else if(V_VT(pvar1) == VT_BOOL) return (V_BOOL(pvar1) == V_BOOL(pvar2)); else if(V_VT(pvar1) == VT_BSTR) { if(V_BSTR(pvar1) == NULL || V_BSTR(pvar2) == NULL) return (V_BSTR(pvar1) == V_BSTR(pvar2)); else return (wcscmp(V_BSTR(pvar1), V_BSTR(pvar2)) == 0); } else return (V_I4(pvar1) == V_I4(pvar2)); }
#endif
|