Setting and Getting Provider Properties
The data source object is the first object created when a consumer instantiates an OLE DB data provider by calling CoCreateInstance or through some other technique.
The data source object provides the starting point for communications between the provider and consumer. For example, a consumer can call CoCreateInstance and request an IDBInitialize interface pointer to instantiate a data source object. The provider's developer must generate a CLSID (class ID) and store the ID in the Microsoft® Windows® Registry. The consumer can use this CLSID with CoCreateInstance to instantiate the data source object. To facilitate this operation, providers should add their application or library information to the Windows Registry upon installation on a new system. The sample provider setup program registers the sample provider in the Windows Registry.
The data source object is also responsible for setting and returning information about the properties supported by the provider and exposing the list of supported keywords and literals. This functionality is supported through the mandatory IDBProperties interface and the optional IDBInfo interface. The IDBProperties interface contains three methods:
GetProperties returns the list of properties currently set on the data source object.
GetPropertyInfo returns information about supported rowset and data source properties.
SetProperties sets the properties on the data source object.
The IDBInfo interface contains two methods:
GetKeywords returns a list of supported keywords.
GetLiteralInfo returns information about literals used in text commands.
In the sample provider implementation, no command interfaces are implemented, so GetKeywords returns NULL. GetLiteralInfo is not implemented and returns E_NOTIMPL. GetProperties, GetPropertyInfo, and SetProperties are handled by passing the calls to the utility object that manages properties, which is found in UtilProp.cpp. The structure containing the properties known to the sample provider, which is also found in UtilProp.cpp, follows.
// 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"}
};
The source code for GetPropertyInfo, which passes property information back to the provider, follows.
// Code ----------------------------------------------------------------------
// CUtilProp::CUtilProp ----------------------------------------------------------
//
// @mfunc Constructor for this class
//
// @rdesc NONE
//
CUtilProp::CUtilProp
(
void
)
{
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->dwPropertyID = pPropStruct->dwPropertyID;
pPropInfo->dwFlags = pPropStruct->dwFlags;
pPropInfo->vtType = pPropStruct->vtType;
//
// init the variant
//
VariantInit(&pPropInfo->vValues);
//
// fill in the description
//
if( pPropInfo->pwszDescription )
wcscpy_s(pPropInfo->pwszDescription, _countof(pPropInfo->pwszDescription ), pPropStruct->pwstrDescBuffer);
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;
}
The source code for GetProperties, which returns the current settings of all supported properties, follows. Immediately following the creation of the data source object, none of the properties are set. Properties are set by the SetProperties method.
// 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 );
}
The source code for SetProperties, which sets the values of all supported properties, follows. The consumer must set properties on the provider before initializing the data source object. In most providers, these properties provide information such as a database location, database name, user ID, and password. The sample provider requires only one value: a valid directory path to the data file.
// 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 ) {
wcsncpy_s(m_wszFilePath, _countof(m_wszFilePath), V_BSTR(&rgPropertyIDSets[cPropSets].rgProperties[cCnt].vValue), MAX_PATH -1);
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 );
}