2025-11-28 00:35:46 +09:00

1199 lines
40 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Sample Provider
// (C) Copyright 1991 - 1999 Microsoft Corporation. All Rights Reserved.
//
// @doc
//
// @module UTILPROP.CPP | Properties utility object implementation
//
//
// Notes - there are two main methods in this module:
// - CUtilProps::GetPropertyInfo, a helper function for IDBInfo::GetPropertyInfo
// - CUtilProps::GetProperties, a helper function for IRowsetInfo::GetProperties
//
// Our property implementation is simplified considerably by the fact that we
// only support reading\getting the properties, we do not support
// writing\setting them. This makes sense because we are a simple provider,
// and our rowset object always creates all the interfaces it exposes. In
// other words, there are really no properties the consumer could set.
//
// The implementation is very simple - we keep a global table of the
// properties we support in s_rgprop. We search this table sequentially.
//
// Note that a full-featured provider would probably need to use a more
// sophisticated implementation. We keep the entire GUID for each property in
// our struct, which would become a waste of space if we had a lot more
// properties. Similarly, with large numbers of properties some sort of
// hashing would be better than the sequential search used here.
//
// Includes ------------------------------------------------------------------
#include "headers.h"
#include "sampver.h"
#define __T(x) L ## x
#define _TEXT(x) __T(x)
// Struct containing the properties we know about. The GUID and string fields are
// initialized in the constructor, because C++ makes it awkward to do so at declaration
// time. So, if you change this table, be sure to make parallel changes in CUtilProp::CUtilProp.
PROPSTRUCT s_rgprop[] =
{
/* 0 */ {DBPROP_IAccessor, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IAccessor"},
/* 1 */ {DBPROP_IColumnsInfo, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IColumnsInfo"},
/* 2 */ {DBPROP_IConvertType, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IConvertType"},
/* 3 */ {DBPROP_IRowset, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IRowset"},
/* 4 */ {DBPROP_IRowsetChange, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, TRUE, 0, NULL, L"IRowsetChange"},
/* 5 */ {DBPROP_IRowsetInfo, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IRowsetInfo"},
/* 6 */ {DBPROP_IRowsetIdentity, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IRowsetIdentity"},
/* 7 */ {DBPROP_CANHOLDROWS, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, TRUE, 0, NULL, L"Hold Rows"},
/* 8 */ {DBPROP_LITERALIDENTITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, TRUE, 0, NULL, L"Literal Row Identity"},
/* 9 */ {DBPROP_UPDATABILITY, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_I4, TRUE, DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE|DBPROPVAL_UP_INSERT, NULL,L"Updatability"},
/* 10*/ {DBPROP_IRow, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, FALSE, 0, NULL, L"IRow"},
/* 11*/ {DBPROP_IRowChange, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BOOL, FALSE, 0, NULL, L"IRowChange"},
/* 12*/ {DBPROP_IGetRow, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IGetRow"},
/* 13*/ {DBPROP_IGetSession, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"IGetSession"},
/* 14*/ {DBPROP_QUICKRESTART, DBPROPFLAGS_ROWSET | DBPROPFLAGS_READ, VT_BOOL, FALSE, 0, NULL, L"Quick Restart"},
/* 15*/ {DBPROP_SESS_AUTOCOMMITISOLEVELS, DBPROPFLAGS_SESSION | DBPROPFLAGS_READ, VT_I4, FALSE, 0, NULL, L"Autocommit Isolation Levels"},
/* 16*/ {DBPROP_ACTIVESESSIONS, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_I4, FALSE, 1, NULL, L"Active Sessions"},
/* 17*/ {DBPROP_PERSISTENTIDTYPE, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_I4, FALSE, DBPROPVAL_PT_GUID_PROPID, NULL, L"Persistent ID Type"},
/* 18*/ {DBPROP_PROVIDERFILENAME, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BSTR, FALSE, 0, L"SAMPPROV.DLL",L"Provider Name"},
/* 19*/ {DBPROP_PROVIDERFRIENDLYNAME, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BSTR, FALSE, 0, L"Microsoft OLE DB Sample Provider", L"Provider Friendly Name"},
/* 20*/ {DBPROP_PROVIDEROLEDBVER, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BSTR, FALSE, 0, L"02.00", L"OLE DB Version"},
/* 21*/ {DBPROP_PROVIDERVER, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BSTR, FALSE, 0, _TEXT(VER_PRODUCTVERSION_STR), L"Provider Version"},
/* 22*/ {DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_BOOL, TRUE, 0, NULL, L"Rowset Conversions on Command"},
/* 23*/ {DBPROP_OLEOBJECTS, DBPROPFLAGS_DATASOURCEINFO | DBPROPFLAGS_READ, VT_I4, FALSE, DBPROPVAL_OO_DIRECTBIND|DBPROPVAL_OO_ROWOBJECT|DBPROPVAL_OO_SINGLETON, NULL, L"OLE Object Support"},
/* 24*/ {DBPROP_INIT_DATASOURCE, DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_BSTR, FALSE, 0, L"", L"Data Source"},
#ifdef _WIN64
/* 25*/ {DBPROP_INIT_HWND, DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I8, FALSE, 0, NULL, L"Window Handle"},
#else
/* 25*/ {DBPROP_INIT_HWND, DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I4, FALSE, 0, NULL, L"Window Handle"},
#endif
/* 26*/ {DBPROP_INIT_PROMPT, DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE, VT_I2, FALSE, 4, NULL, L"Prompt"}
};
// Code ----------------------------------------------------------------------
// CUtilProp::CUtilProp ----------------------------------------------------------
//
// @mfunc Constructor for this class
//
// @rdesc NONE
//
CUtilProp::CUtilProp
(
void
) :
m_cwchNamePool(0), m_pwchNamePool(NULL)
{
memcpy(m_rgproperties, s_rgprop, sizeof(s_rgprop));
memset(m_wszFilePath,0,sizeof(m_wszFilePath));
return;
}
// CUtilProp::~CUtilProp ---------------------------------------------------------
//
// @mfunc Destructor for this class
//
// @rdesc NONE
//
CUtilProp:: ~CUtilProp
(
void
)
{
return;
}
// CUtilProp::GetPropIndex ----------------------------------------------------
//
// @mfunc Returns index of the given property in our global table of properties
//
// @rdesc BOOL
// @flag TRUE | found match, copied it to pulIndex out-param
// @flag FALSE | no match. In this case, pulIndex has no meaning
//
BOOL CUtilProp::GetPropIndex
(
DBPROPID dwPropertyID, //@parm IN | PROPID of desired property
ULONG * pulIndex //@parm OUT | index of desired property if return was TRUE
)
{
//
// asserts
//
assert(pulIndex);
for (ULONG cNumberOfProperties = 0;
cNumberOfProperties < NUMBER_OF_SUPPORTED_PROPERTIES;
cNumberOfProperties++)
{
if( dwPropertyID == m_rgproperties[cNumberOfProperties].dwPropertyID )
{
// found a match
*pulIndex = cNumberOfProperties;
return TRUE;
}
}
// found no matches
return FALSE;
}
// CUtilProp::LoadDBPROPINFO ----------------------------------------------------
//
// @mfunc Helper for GetPropertyInfo. Loads field of DBPROPINFO structure.
//
// @rdesc BOOL
// @flag TRUE | Method succeeded
// @flag FALSE | Method failed (couldn't allocate memory)
//
void CUtilProp::LoadDBPROPINFO
(
PROPSTRUCT * pPropStruct,
DBPROPINFO * pPropInfo
)
{
//
// asserts
//
assert(pPropStruct);
assert(pPropInfo);
//
// set the easy fields..
//
pPropInfo->pwszDescription = m_pwchNamePool;
pPropInfo->dwPropertyID = pPropStruct->dwPropertyID;
pPropInfo->dwFlags = pPropStruct->dwFlags;
pPropInfo->vtType = pPropStruct->vtType;
//
// init the variant
//
VariantInit(&pPropInfo->vValues);
//
// fill in the description
//
//if( pPropInfo->pwszDescription )
StringCchCopyExW(pPropInfo->pwszDescription, m_cwchNamePool, pPropStruct->pwstrDescBuffer, &m_pwchNamePool, &m_cwchNamePool, 0);
m_cwchNamePool --;
m_pwchNamePool ++; // move over the null terminator
return;
}
// CUtilProp::LoadDBPROP ----------------------------------------------------
//
// @mfunc Helper for GetProperties. Loads field of DBPROP structure.
//
// @rdesc HRESULT
// @flag TRUE | Method succeeded
// @flag FALSE | Method failed (couldn't allocate memory)
//
HRESULT CUtilProp::LoadDBPROP
(
PROPSTRUCT* pPropStruct,
DBPROP* pPropSupport
)
{
HRESULT hr = S_OK;
//
// asserts
//
assert(pPropStruct);
assert(pPropSupport);
//
// set the easy fields..
//
pPropSupport->dwPropertyID = pPropStruct->dwPropertyID;
pPropSupport->colid = DB_NULLID;
pPropSupport->dwStatus = DBPROPSTATUS_OK;
//
// init the variant
//
VariantInit(&pPropSupport->vValue);
//
// set pPropSupport->vValue based on Variant type
//
switch (pPropStruct->vtType)
{
case VT_BOOL:
V_VT(&pPropSupport->vValue) = VT_BOOL;
V_BOOL(&pPropSupport->vValue) =
(pPropStruct->boolVal ? VARIANT_TRUE : VARIANT_FALSE);
break;
case VT_I2:
V_VT(&pPropSupport->vValue) = VT_I2;
V_I2(&pPropSupport->vValue) = (SHORT)pPropStruct->longVal;
break;
case VT_I4:
V_VT(&pPropSupport->vValue) = VT_I4;
V_I4(&pPropSupport->vValue) = (LONG)pPropStruct->longVal;
break;
#ifdef _WIN64
case VT_I8:
V_VT(&pPropSupport->vValue) = VT_I8;
V_I8(&pPropSupport->vValue) = (LONGLONG)pPropStruct->longVal;
break;
#endif
case VT_BSTR:
V_VT(&pPropSupport->vValue) = VT_BSTR;
SAFE_SYSALLOC(V_BSTR(&pPropSupport->vValue), pPropStruct->pwstrVal);
break;
default:
assert( !"LoadDBPROP unknown variant type!\n\r" );
hr = E_FAIL;
break;
}
CLEANUP:
return hr;
}
//---------------------------------------------------------------------------
// CUtilProp::GetPropertiesArgChk
//
// @mfunc Initialize the buffers and check for E_INVALIDARG cases
//
// NOTE: This routine is used by RowsetInfo and IDBProperties
//
// @rdesc HRESULT indicating the status of the method
// @flag S_OK | Properties gathered
// @flag E_INVALIDARG | Invalid parameter values
//
HRESULT CUtilProp::GetPropertiesArgChk
(
DWORD dwBitMask, //@parm IN | Mask for object
const ULONG cPropertySets, //@parm IN | Number of property Sets
const DBPROPIDSET rgPropertySets[], //@parm IN | Property Classes and Ids
ULONG* pcProperties, //@parm OUT | Count of structs returned
DBPROPSET** prgProperties //@parm OUT | Array of Properties
)
{
//
// Initialize values
//
if( pcProperties )
*pcProperties = 0;
if( prgProperties )
*prgProperties = NULL;
//
// Check Arguments
//
if( (cPropertySets && !rgPropertySets) || !pcProperties || !prgProperties )
return E_INVALIDARG;
//
// New argument check for > 1 cPropertyIDs and NULL pointer for the array.
//
for(ULONG ul=0; ul < cPropertySets; ul++)
{
if( rgPropertySets[ul].cPropertyIDs && !rgPropertySets[ul].rgPropertyIDs )
return E_INVALIDARG;
//
// Check for propper formation of DBPROPSET_PROPERTIESINERROR
//
if( (dwBitMask & PROPSET_DSO || dwBitMask & PROPSET_ROWSET) &&
(rgPropertySets[ul].guidPropertySet == DBPROPSET_PROPERTIESINERROR) )
{
if( (cPropertySets > 1) ||
rgPropertySets[ul].cPropertyIDs ||
rgPropertySets[ul].rgPropertyIDs )
return E_INVALIDARG;
}
}
return S_OK;
}
// CUtilProp::IsValidValue -----------------------------------------
// @mfunc Validate that the variant contains legal values for it's particalur
// type and for the particular PROPID in this propset.
//
// @rdesc HRESULT indicating status
//
HRESULT CUtilProp::IsValidValue
(
DBPROP* pDBProp
)
{
//
// Switch on the vt type first.
//
switch (V_VT(&pDBProp->vValue))
{
case VT_BOOL:
if( V_BOOL(&pDBProp->vValue) != VARIANT_TRUE &&
V_BOOL(&pDBProp->vValue) != VARIANT_FALSE )
return S_FALSE;
break;
case VT_I2:
if( V_I2(&pDBProp->vValue) < 0 )
return S_FALSE;
//
// Switch on the property ID for VT_I2.
//
switch( pDBProp->dwPropertyID )
{
case DBPROP_INIT_PROMPT:
if( V_I2(&pDBProp->vValue) != DBPROMPT_PROMPT &&
V_I2(&pDBProp->vValue) != DBPROMPT_COMPLETE &&
V_I2(&pDBProp->vValue) != DBPROMPT_COMPLETEREQUIRED &&
V_I2(&pDBProp->vValue) != DBPROMPT_NOPROMPT )
return S_FALSE;
}
break;
case VT_I4:
if( V_I4(&pDBProp->vValue) < 0 )
return S_FALSE;
//
// Switch on the property ID for VT_I4.
//
switch( pDBProp->dwPropertyID )
{
case DBPROP_SESS_AUTOCOMMITISOLEVELS:
if( V_I4(&pDBProp->vValue) != 0 &&
V_I4(&pDBProp->vValue) != DBPROPVAL_TI_CHAOS &&
V_I4(&pDBProp->vValue) != DBPROPVAL_TI_READUNCOMMITTED &&
V_I4(&pDBProp->vValue) != DBPROPVAL_TI_READCOMMITTED &&
V_I4(&pDBProp->vValue) != DBPROPVAL_TI_REPEATABLEREAD &&
V_I4(&pDBProp->vValue) != DBPROPVAL_TI_SERIALIZABLE )
return S_FALSE;
}
break;
default:
break;
}
return S_OK;
}
// CUtilProp::GetPropertyInfo -----------------------------------------
//
// @mfunc Returns information about rowset and data source properties
// supported by the provider
//
// @rdesc HRESULT
// @flag S_OK | The method succeeded
// @flag E_INVALIDARG | pcPropertyIDSets or prgPropertyInfo was NULL
// @flag E_OUTOFMEMORY | Out of memory
//
STDMETHODIMP CUtilProp::GetPropertyInfo
(
BOOL fDSOInitialized, //@parm IN | if Initialized
ULONG cPropertyIDSets, //@parm IN | # properties
const DBPROPIDSET rgPropertyIDSets[], //@parm IN | Array of property sets
ULONG* pcPropertyInfoSets, //@parm OUT | # DBPROPSET structures
DBPROPINFOSET** prgPropertyInfoSets,//@parm OUT | DBPROPSET structures property
// | information returned
WCHAR** ppDescBuffer //@parm OUT | Property descriptions
)
{
HRESULT hr = S_OK;
BOOL fPropsinError = FALSE;
BOOL fPropsSucceed = FALSE;
BOOL fIsSpecialGUID = FALSE;
BOOL fIsNotSpecialGUID = FALSE;
ULONG cProps = 0;
ULONG cCount = 0;
ULONG ulPropertySets = 0;
ULONG cBuffer = NUMBER_OF_SUPPORTED_PROPERTIES;
DBPROPINFOSET* pPropInfoSet = NULL;
DBPROPINFO* pPropInfo = NULL;
WCHAR* pDescBuffer = NULL;
//
// Initialize values
//
if( pcPropertyInfoSets )
*pcPropertyInfoSets = 0;
if( prgPropertyInfoSets )
*prgPropertyInfoSets = NULL;
if( ppDescBuffer )
*ppDescBuffer = NULL;
//
// Check Arguments
//
if( ((cPropertyIDSets > 0) && !rgPropertyIDSets) ||
!pcPropertyInfoSets || !prgPropertyInfoSets )
return E_INVALIDARG;
//
// New argument check for > 1 cPropertyIDs and NULL pointer for the array.
//
for(ULONG ul=0; ul < cPropertyIDSets; ul++)
{
if( rgPropertyIDSets[ul].cPropertyIDs && !(rgPropertyIDSets[ul].rgPropertyIDs) )
return E_INVALIDARG;
if( DBPROPSET_VIEWALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_TRUSTEEALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_TABLEALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_SESSIONALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_ROWSETALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_INDEXALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_DBINITALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_DATASOURCEINFOALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_DATASOURCEALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_CONSTRAINTALL == rgPropertyIDSets[ul].guidPropertySet ||
DBPROPSET_COLUMNALL == rgPropertyIDSets[ul].guidPropertySet )
fIsSpecialGUID = TRUE;
else
fIsNotSpecialGUID = TRUE;
if( fIsSpecialGUID && fIsNotSpecialGUID )
return E_INVALIDARG;
// figure out the nuber of property descriptions
if( !rgPropertyIDSets[ul].cPropertyIDs )
cBuffer += NUMBER_OF_SUPPORTED_PROPERTIES;
else
cBuffer += rgPropertyIDSets[ul].cPropertyIDs;
}
// save the count of PropertyIDSets
cProps = cPropertyIDSets;
// If the consumer does not restrict the property sets
// by specify an array of property sets and a cPropertySets
// greater than 0, then we need to make sure we
// have some to return
if( cPropertyIDSets == 0 )
{
if( fDSOInitialized )
cProps = NUMBER_OF_SUPPORTED_PROPERTY_SETS;
else
cProps = 1;
}
// use task memory allocater to alloc a DBPROPINFOSET struct
SAFE_ALLOC(pPropInfoSet, DBPROPINFOSET, cProps);
memset(pPropInfoSet, 0, cProps * sizeof(DBPROPINFOSET));
// Alloc memory for ppDescBuffer
if( ppDescBuffer )
{
SAFE_ALLOC(pDescBuffer, WCHAR,
cProps * cBuffer * CCH_GETPROPERTYINFO_DESCRIP_BUFFER_SIZE);
memset(pDescBuffer, 0, (cProps * cBuffer * sizeof(WCHAR) *
CCH_GETPROPERTYINFO_DESCRIP_BUFFER_SIZE));
*ppDescBuffer = pDescBuffer;
m_pwchNamePool = pDescBuffer;
m_cwchNamePool = cProps * cBuffer * CCH_GETPROPERTYINFO_DESCRIP_BUFFER_SIZE;
}
// For each supported Property Set
for(ulPropertySets=0; ulPropertySets < cProps; ulPropertySets++)
{
BOOL fGetAllProps = FALSE;
// If no restrictions return all properties from the three supported property sets
if( cPropertyIDSets == 0 )
{
fGetAllProps = TRUE;
// only do this once
if( ulPropertySets == 0 )
{
pPropInfoSet[0].guidPropertySet = DBPROPSET_DBINIT;
pPropInfoSet[0].cPropertyInfos = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;
if( fDSOInitialized )
{
pPropInfoSet[1].guidPropertySet = DBPROPSET_DATASOURCEINFO;
pPropInfoSet[1].cPropertyInfos = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
pPropInfoSet[2].guidPropertySet = DBPROPSET_SESSION;
pPropInfoSet[2].cPropertyInfos = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
pPropInfoSet[3].guidPropertySet = DBPROPSET_ROWSET;
pPropInfoSet[3].cPropertyInfos = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
}
}
}
else
{
pPropInfoSet[ulPropertySets].guidPropertySet = rgPropertyIDSets[ulPropertySets].guidPropertySet;
pPropInfoSet[ulPropertySets].cPropertyInfos = rgPropertyIDSets[ulPropertySets].cPropertyIDs;
if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINITALL) ||
(rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT &&
rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0) )
{
fGetAllProps = TRUE;
pPropInfoSet[ulPropertySets].guidPropertySet = DBPROPSET_DBINIT;
pPropInfoSet[ulPropertySets].cPropertyInfos = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;
}
else if( fDSOInitialized )
{
if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFOALL) ||
((rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO) &&
(rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0)) )
{
fGetAllProps = TRUE;
pPropInfoSet[ulPropertySets].guidPropertySet = DBPROPSET_DATASOURCEINFO;
pPropInfoSet[ulPropertySets].cPropertyInfos = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
}
else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSIONALL) ||
((rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSION) &&
(rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0)) )
{
fGetAllProps = TRUE;
pPropInfoSet[ulPropertySets].guidPropertySet = DBPROPSET_SESSION;
pPropInfoSet[ulPropertySets].cPropertyInfos = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
}
else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSETALL) ||
((rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET) &&
(rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0)) )
{
fGetAllProps = TRUE;
pPropInfoSet[ulPropertySets].guidPropertySet = DBPROPSET_ROWSET;
pPropInfoSet[ulPropertySets].cPropertyInfos = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
}
else if( rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0 )
fPropsinError = TRUE;
}
else if( rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0 )
{
// Since we do not support it should return a error with 0 & NULL
fPropsinError = TRUE;
}
}
if( pPropInfoSet[ulPropertySets].cPropertyInfos )
{
// use task memory allocater to alloc array of DBPROPINFO structs
SAFE_ALLOC(pPropInfo, DBPROPINFO,
pPropInfoSet[ulPropertySets].cPropertyInfos);
memset(pPropInfo, 0,
pPropInfoSet[ulPropertySets].cPropertyInfos * sizeof(DBPROPINFO));
pPropInfoSet[ulPropertySets].rgPropertyInfos = &pPropInfo[0];
}
// for each prop in our table..
for (cCount=0; cCount < pPropInfoSet[ulPropertySets].cPropertyInfos; cCount++)
{
// init the Variant right up front
// that way we can VariantClear with no worried (if we need to)
VariantInit( &pPropInfo[cCount].vValues );
// set the description pointer
// pPropInfo[cCount].pwszDescription = pDescBuffer;
// Check supported property sets
if( fGetAllProps )
{
if( pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT )
{
// load up their DBPROPINFO from our table
fPropsSucceed = TRUE;
LoadDBPROPINFO(&m_rgproperties[START_OF_SUPPORTED_DBINIT_PROPERTIES + cCount],
&pPropInfo[cCount]);
}
else if( pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO )
{
// load up their DBPROPINFO from our table
fPropsSucceed = TRUE;
LoadDBPROPINFO(&m_rgproperties[START_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES + cCount],
&pPropInfo[cCount] );
}
else if( pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_SESSION )
{
// load up their DBPROPINFO from our table
fPropsSucceed = TRUE;
LoadDBPROPINFO(&m_rgproperties[START_OF_SUPPORTED_SESSION_PROPERTIES + cCount],
&pPropInfo[cCount] );
}
else
{
// load up their DBPROPINFO from our table
fPropsSucceed = TRUE;
LoadDBPROPINFO(&m_rgproperties[START_OF_SUPPORTED_ROWSET_PROPERTIES + cCount],
&pPropInfo[cCount] );
}
}
else
{
ULONG ulIndex;
pPropInfo[cCount].dwPropertyID = rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount];
pPropInfo[cCount].dwFlags = DBPROPFLAGS_NOTSUPPORTED;
if( (GetPropIndex(rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount], &ulIndex)) &&
(pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT ||
pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO && fDSOInitialized ||
pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_SESSION && fDSOInitialized ||
pPropInfoSet[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET && fDSOInitialized) )
{
fPropsSucceed = TRUE;
LoadDBPROPINFO( &m_rgproperties[ulIndex], &pPropInfo[cCount] );
}
else
{
fPropsinError = TRUE;
pPropInfo[cCount].pwszDescription = NULL;
}
}
// move the description pointer to the next
//if( pPropInfo[cCount].pwszDescription )
// pDescBuffer += (wcslen(pPropInfo[cCount].pwszDescription) + 1);
}
// Set local back to FALSE
fGetAllProps = FALSE;
}
// set count of properties and property information
*pcPropertyInfoSets = cProps;
*prgPropertyInfoSets = pPropInfoSet;
CLEANUP:
if( FAILED(hr) )
{
SAFE_FREE(pPropInfo);
SAFE_FREE(pPropInfoSet);
if( ppDescBuffer )
{
SAFE_FREE(*ppDescBuffer);
m_cwchNamePool = 0;
m_pwchNamePool = NULL;
}
}
if( fPropsSucceed && fPropsinError )
return DB_S_ERRORSOCCURRED;
else if( fPropsinError )
{
if( ppDescBuffer )
{
SAFE_FREE(*ppDescBuffer);
m_cwchNamePool = 0;
m_pwchNamePool = NULL;
}
return DB_E_ERRORSOCCURRED;
}
else
return hr;
}
// CUtilProp::GetProperties ----------------------------------------------------
//
// @mfunc Returns current settings of all properties supported by the DSO/rowset
//
// @rdesc HRESULT
// @flag S_OK | The method succeeded
// @flag E_INVALIDARG | pcProperties or prgPropertyInfo was NULL
// @flag E_OUTOFMEMORY | Out of memory
//
STDMETHODIMP CUtilProp::GetProperties
(
DWORD dwBitMask, //@parm IN | Mask if Initialized
ULONG cPropertyIDSets, //@parm IN | # of restiction property IDs
const DBPROPIDSET rgPropertyIDSets[], //@parm IN | restriction guids
ULONG* pcPropertySets, //@parm OUT | count of properties returned
DBPROPSET** prgPropertySets //@parm OUT | property information returned
)
{
HRESULT hr = S_OK;
BOOL fPropsinError = FALSE;
BOOL fPropsSucceed = FALSE;
ULONG cProps = 0;
ULONG cCount = 0;
ULONG ulPropertySets= 0;
DBPROP* pProp;
DBPROPSET* pPropSet;
// save the count of PropertyIDSets
cProps = cPropertyIDSets;
// If the consumer does not restrict the property sets
// by specify an array of property sets and a cPropertySets
// greater than 0, then we need to make sure we
// have some to return
if( cPropertyIDSets == 0 )
{
// only allow the DBINIT, DATASOURCE and DATASOURCEINFO if Initialized
if( dwBitMask & PROPSET_INIT )
cProps = 2;
else
cProps = 1;
}
// use task memory allocater to alloc a DBPROPSET struct
SAFE_ALLOC(pPropSet, DBPROPSET, cProps);
memset(pPropSet, 0, cProps * sizeof(DBPROPSET));
// For each supported Property Set
for (ulPropertySets=0; ulPropertySets < cProps; ulPropertySets++)
{
BOOL fGetAllProps = FALSE;
// If no restrictions return all properties from the three supported property sets
if( cPropertyIDSets == 0 )
{
fGetAllProps = TRUE;
// only do this once
if( ulPropertySets == 0 )
{
if( !(dwBitMask & PROPSET_SESSION) )
{
if( !(dwBitMask & PROPSET_ROWSET) )
{
pPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
pPropSet[0].cProperties = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;
if( dwBitMask & PROPSET_INIT )
{
pPropSet[1].guidPropertySet = DBPROPSET_DATASOURCEINFO;
pPropSet[1].cProperties = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
}
}
else
{
pPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
pPropSet[0].cProperties = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
}
}
else
{
pPropSet[0].guidPropertySet = DBPROPSET_SESSION;
pPropSet[0].cProperties = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
}
}
}
else
{
pPropSet[ulPropertySets].guidPropertySet = rgPropertyIDSets[ulPropertySets].guidPropertySet;
pPropSet[ulPropertySets].cProperties = rgPropertyIDSets[ulPropertySets].cPropertyIDs;
if( rgPropertyIDSets[ulPropertySets].cPropertyIDs == 0 )
{
fGetAllProps = TRUE;
if( rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT &&
dwBitMask & PROPSET_DSO )
{
pPropSet[ulPropertySets].cProperties = NUMBER_OF_SUPPORTED_DBINIT_PROPERTIES;
}
else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO) &&
((dwBitMask & PROPSET_DSOINIT) == PROPSET_DSOINIT) )
{
pPropSet[ulPropertySets].cProperties = NUMBER_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES;
}
else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSION) &&
(dwBitMask & PROPSET_SESSION))
{
pPropSet[ulPropertySets].cProperties = NUMBER_OF_SUPPORTED_SESSION_PROPERTIES;
}
else if( (rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET) &&
(dwBitMask & PROPSET_ROWSET))
{
pPropSet[ulPropertySets].cProperties = NUMBER_OF_SUPPORTED_ROWSET_PROPERTIES;
}
else if( rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_PROPERTIESINERROR )
{
if( dwBitMask & PROPSET_DSO ) {
pPropSet[ulPropertySets].guidPropertySet = DBPROPSET_DBINIT;
fPropsSucceed = TRUE;
}
else if( dwBitMask & PROPSET_ROWSET ) {
pPropSet[ulPropertySets].guidPropertySet = DBPROPSET_ROWSET;
fPropsSucceed = TRUE;
}
else
fPropsinError = TRUE;
}
else
{
fGetAllProps = FALSE;
fPropsinError = TRUE;
}
}
}
if( pPropSet[ulPropertySets].cProperties )
{
// use task memory allocater to alloc array of DBPROP structs
pProp = (DBPROP*) PROVIDER_ALLOC(sizeof( DBPROP ) *
pPropSet[ulPropertySets].cProperties);
if (!pProp)
{
for(ULONG ul=0; ul<ulPropertySets; ul++)
{
for(ULONG ul2=0; ul2<pPropSet[ul].cProperties; ul2++)
VariantClear( &pPropSet[ul].rgProperties[ul2].vValue );
SAFE_FREE( pPropSet[ul].rgProperties );
}
SAFE_FREE( pPropSet );
return ResultFromScode( E_OUTOFMEMORY );
}
pPropSet[ulPropertySets].rgProperties = &pProp[0];
memset( pProp, 0,
(pPropSet[ulPropertySets].cProperties * sizeof( DBPROP )));
}
// for each prop in our table..
for (cCount=0; cCount < pPropSet[ulPropertySets].cProperties; cCount++)
{
// init the Variant right up front
// that way we can VariantClear with no worried (if we need to)
VariantInit( &pProp[cCount].vValue );
// Check supported property sets
if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT &&
fGetAllProps )
{
fPropsSucceed = TRUE;
// load up their DBPROP from our table
hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_DBINIT_PROPERTIES + cCount],
&pProp[cCount] );
}
else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO &&
fGetAllProps )
{
fPropsSucceed = TRUE;
// load up their DBPROPINFO from our table
hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_DATASOURCEINFO_PROPERTIES + cCount],
&pProp[cCount] );
}
else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_SESSION &&
fGetAllProps )
{
fPropsSucceed = TRUE;
// load up their DBPROPINFO from our table
hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_SESSION_PROPERTIES + cCount],
&pProp[cCount] );
}
else if ( pPropSet[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET &&
fGetAllProps )
{
fPropsSucceed = TRUE;
// load up their DBPROPINFO from our table
hr = LoadDBPROP( &m_rgproperties[START_OF_SUPPORTED_ROWSET_PROPERTIES + cCount],
&pProp[cCount] );
}
else
{
ULONG ulIndex;
pProp[cCount].dwPropertyID = rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount];
pProp[cCount].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
if( (GetPropIndex(rgPropertyIDSets[ulPropertySets].rgPropertyIDs[cCount], &ulIndex)) &&
(((dwBitMask & PROPSET_DSO) &&
(rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DBINIT)) ||
(((dwBitMask & PROPSET_DSOINIT) == PROPSET_DSOINIT) &&
((rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCE) ||
(rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_DATASOURCEINFO))) ||
((dwBitMask & PROPSET_SESSION) &&
(rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_SESSION)) ||
((dwBitMask & PROPSET_ROWSET) &&
(rgPropertyIDSets[ulPropertySets].guidPropertySet == DBPROPSET_ROWSET))) )
{
fPropsSucceed = TRUE;
hr = LoadDBPROP( &m_rgproperties[ulIndex], &pProp[cCount] );
}
else
fPropsinError = TRUE;
}
}
// Set local back to FALSE
fGetAllProps = FALSE;
}
// set count of properties and property information
*pcPropertySets = cProps;
*prgPropertySets = pPropSet;
CLEANUP:
if( FAILED(hr) )
{
// clear all variants used so far..
for (ULONG ulFor=0; ulFor < cCount; ulFor++)
VariantClear(&pProp[ulFor].vValue);
// delete the pProp array, return failure
SAFE_FREE(pProp);
SAFE_FREE(pPropSet);
}
if ( (!fPropsSucceed && cPropertyIDSets) || (!fPropsSucceed && fPropsinError) )
return ResultFromScode( DB_E_ERRORSOCCURRED );
else if ( fPropsSucceed && fPropsinError )
return ResultFromScode( DB_S_ERRORSOCCURRED );
else
return ResultFromScode( hr );
}
// CUtilProp::SetPropertiesArgChk -------------------------------------------
//
// @mfunc Initialize the buffers and check for E_INVALIDARG cases
//
// @rdesc HRESULT indicating the status of the method
// @flag S_OK | Properties gathered
// @flag E_INVALIDARG | Invalid parameter values
//
HRESULT CUtilProp::SetPropertiesArgChk
(
const ULONG cPropertySets, //@parm IN | Count of structs returned
const DBPROPSET rgPropertySets[] //@parm IN | Array of Properties Sets
)
{
// Argument Checking
if( !rgPropertySets )
return ResultFromScode( E_INVALIDARG );
// New argument check for > 1 cPropertyIDs and NULL pointer for
// array of property ids.
for(ULONG ul=0; ul<cPropertySets; ul++)
{
if( rgPropertySets[ul].cProperties && !(rgPropertySets[ul].rgProperties) )
return ResultFromScode( E_INVALIDARG );
}
return ResultFromScode( S_OK );
}
// CUtilProp::SetProperties ----------------------------------------------------
//
// @mfunc Set current settings of properties supported by the DSO/rowset
//
// @rdesc HRESULT
// @flag S_OK | The method succeeded
// @flag E_INVALIDARG | pcProperties or prgPropertyInfo was NULL
// @flag E_OUTOFMEMORY | Out of memory
//
STDMETHODIMP CUtilProp::SetProperties
(
DWORD dwBitMask, //@parm IN Type of PropSet
ULONG cPropertyIDSets, //@parm IN # of DBPROPSET
DBPROPSET rgPropertyIDSets[] //@parm INOUT Array of property sets
)
{
ULONG cCountProps = 0;
ULONG cValidProps = 0;
ULONG ulIndex = 0;
// For each supported Property Set
for (ULONG cPropSets=0; cPropSets < cPropertyIDSets; cPropSets++)
{
// for each prop in the propset
for (ULONG cCnt=0; cCnt < rgPropertyIDSets[cPropSets].cProperties; cCnt++)
{
//Keep track of the number
cCountProps++;
// Check Check to see if valid
switch( dwBitMask )
{
case PROPSET_DSO:
if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DBINIT &&
GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
break;
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
continue;
case PROPSET_DSOINIT:
if( (rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DATASOURCEINFO ||
rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DATASOURCE) &&
GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
break;
if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_DBINIT )
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
continue;
case PROPSET_SESSION:
if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_SESSION &&
GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
break;
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
continue;
case PROPSET_ROWSET:
if( rgPropertyIDSets[cPropSets].guidPropertySet == DBPROPSET_ROWSET &&
GetPropIndex(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID, &ulIndex) )
break;
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
continue;
default:
assert("Unsupported dwBitMask");
}
// arg checking for the prop
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions != DBPROPOPTIONS_OPTIONAL &&
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions != DBPROPOPTIONS_REQUIRED )
{
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_BADOPTION;
continue;
}
if( (V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) != VT_EMPTY) &&
(V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) != m_rgproperties[ulIndex].vtType ||
IsValidValue(&rgPropertyIDSets[cPropSets].rgProperties[cCnt]) == S_FALSE) )
{
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_BADVALUE;
continue;
}
switch( V_VT(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) )
{
case VT_BOOL:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
m_rgproperties[ulIndex].boolVal = !!(V_BOOL(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue));
break;
}
if( !!(V_BOOL(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue)) == m_rgproperties[ulIndex].boolVal )
break;
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
continue;
case VT_I2:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
m_rgproperties[ulIndex].longVal = V_I2(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
break;
}
if( V_I2(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (SHORT)m_rgproperties[ulIndex].longVal )
break;
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
continue;
case VT_I4:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
m_rgproperties[ulIndex].longVal = V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
break;
}
if( (V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (LONG)m_rgproperties[ulIndex].longVal) ||
(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID == DBPROP_UPDATABILITY &&
V_I4(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) & m_rgproperties[ulIndex].longVal) )
break;
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
continue;
#ifdef _WIN64
case VT_I8:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
m_rgproperties[ulIndex].longVal = V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue);
break;
}
if( (V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) == (LONG)m_rgproperties[ulIndex].longVal) ||
(rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwPropertyID == DBPROP_UPDATABILITY &&
V_I8(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue) & m_rgproperties[ulIndex].longVal) )
break;
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
continue;
#endif
case VT_BSTR:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE ) {
if( m_rgproperties[ulIndex].dwPropertyID == DBPROP_INIT_DATASOURCE ) {
StringCchCopyW(m_wszFilePath,MAX_PATH,V_BSTR(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue));
m_rgproperties[ulIndex].pwstrVal = m_wszFilePath;
}
break;
}
if( !(wcscmp(V_BSTR(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue), m_rgproperties[ulIndex].pwstrVal)) )
break;
if( rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwOptions == DBPROPOPTIONS_OPTIONAL)
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSET;
else
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_NOTSETTABLE;
continue;
case VT_EMPTY:
if( m_rgproperties[ulIndex].dwFlags & DBPROPFLAGS_WRITE )
memcpy(&m_rgproperties[ulIndex], &s_rgprop[ulIndex], sizeof(PROPSTRUCT));
break;
}
// Initialize dwStatus
rgPropertyIDSets[cPropSets].rgProperties[cCnt].dwStatus = DBPROPSTATUS_OK;
cValidProps++;
}
}
// Figure out the retcode
if( cValidProps == cCountProps )
return ResultFromScode( S_OK );
else if( cValidProps )
return ResultFromScode( DB_S_ERRORSOCCURRED );
else
return ResultFromScode( DB_E_ERRORSOCCURRED );
}