Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1112 lines
40 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 2000.
//
// File: proprst.cxx
//
// Contents: This object handles rowset/command properties
//
// Classes: CMRowsetProps : public CUtlProps
//
// History: 10-28-97 danleg Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#define DBINITCONSTANTS
#include <propglob.hxx>
#undef DBINITCONSTANTS
#include <ocidl.h>
#include <ntverp.h>
#include <proprst.hxx>
#include <rstprop.hxx>
#include "propinfr.h"
#include "proptbl.hxx"
//
// Constants
//
static const LCID InvalidLCID = 0xFFFFFFFF;
//
// This array describes all the known rowset properties
//
const SPropDescription CMRowsetProps::aPropDescriptions[] = {
{ DBPROP_ABORTPRESERVE, FALSE, eNotSupported, -1 },
{ DBPROP_APPENDONLY, FALSE, eNotSupported, -1 },
{ DBPROP_BLOCKINGSTORAGEOBJECTS, FALSE, eDefaultFalse, -1 },
{ DBPROP_BOOKMARKS, TRUE, eLocatable, eid_PROPVAL_BOOKMARKS },
{ DBPROP_BOOKMARKSKIPPED, FALSE, eDefaultFalse, -1 },
{ DBPROP_BOOKMARKTYPE, FALSE, eNumeric, -1 },
{ DBPROP_CACHEDEFERRED, FALSE, eColumnProp, -1 },
{ DBPROP_CANFETCHBACKWARDS, FALSE, eLocatable, -1 },
{ DBPROP_CANHOLDROWS, TRUE, eHoldRows, eid_PROPVAL_CANHOLDROWS },
{ DBPROP_CANSCROLLBACKWARDS, FALSE, eLocatable, -1 },
{ DBPROP_CHANGEINSERTEDROWS, FALSE, eNotSupported, -1 },
{ DBPROP_COLUMNRESTRICT, FALSE, eDefaultFalse, -1 },
// { DBPROP_CHAPTERED, FALSE, eChaptered, -1 },
{ DBPROP_COMMANDTIMEOUT, TRUE, eNumeric, eid_PROPVAL_COMMANDTIMEOUT },
{ DBPROP_COMMITPRESERVE, FALSE, eNotSupported, -1 },
{ DBPROP_DEFERRED, FALSE, eColumnProp, -1 },
{ DBPROP_DELAYSTORAGEOBJECTS, FALSE, eNotSupported, -1 },
{ DBPROP_IMMOBILEROWS, FALSE, eNotSupported, -1 },
{ DBPROP_LITERALBOOKMARKS, FALSE, eDefaultFalse, -1 },
{ DBPROP_LITERALIDENTITY, FALSE, eLocatable, -1 },
{ DBPROP_MAXOPENROWS, FALSE, eNumeric, -1 },
{ DBPROP_MAXPENDINGROWS, FALSE, eNotSupported, -1 },
{ DBPROP_MAXROWS, TRUE, eNumeric, eid_PROPVAL_MAXROWS },
{ DBPROP_FIRSTROWS, TRUE, eFirstRows, eid_PROPVAL_FIRSTROWS },
{ DBPROP_MAYWRITECOLUMN, FALSE, eColumnProp, -1 },
{ DBPROP_MEMORYUSAGE, TRUE, eNumeric, eid_PROPVAL_MEMORYUSAGE },
// { DBPROP_MULTICHAPTERED, FALSE, eChaptered, -1 },
// { DBPROP_MULTIPLEACCESSORS, FALSE, eDefaultTrue, -1 },
// { DBPROP_MULTIPLERESULTSETS, FALSE, eNotSupported, -1 },
// { DBPROP_NOTIFICATIONGRANULARITY, FALSE, eNumeric, -1 },
{ DBPROP_NOTIFICATIONPHASES, FALSE, eNumeric, -1 },
{ DBPROP_NOTIFYROWSETRELEASE, FALSE, eNumeric, -1 },
{ DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE,FALSE, eNumeric, -1 },
// 9 additional notification properties, all unsupported
{ DBPROP_ORDEREDBOOKMARKS, FALSE, eLocatable, -1 },
{ DBPROP_OTHERINSERT, FALSE, eAsynchronous, -1 },
{ DBPROP_OTHERUPDATEDELETE, FALSE, eAsynchronous, -1 },
{ DBPROP_OWNINSERT, FALSE, eNotSupported, -1 },
{ DBPROP_OWNUPDATEDELETE, FALSE, eNotSupported, -1 },
{ DBPROP_QUICKRESTART, FALSE, eLocatable, -1 },
{ DBPROP_REENTRANTEVENTS, FALSE, eDefaultFalse, -1 },
{ DBPROP_REMOVEDELETED, FALSE, eDefaultTrue, -1 },
{ DBPROP_REPORTMULTIPLECHANGES, FALSE, eNotSupported, -1 },
{ DBPROP_RETURNPENDINGINSERTS, FALSE, eNotSupported, -1 },
{ DBPROP_ROWRESTRICT, FALSE, eDefaultTrue, -1 },
{ DBPROP_ROWTHREADMODEL, FALSE, eNumeric, -1 },
{ DBPROP_SERVERCURSOR, FALSE, eDefaultTrue, -1 },
{ DBPROP_STRONGIDENTITY, FALSE, eLocatable, -1 },
{ DBPROP_TRANSACTEDOBJECT, FALSE, eColumnProp, -1 },
{ DBPROP_UPDATABILITY, FALSE, eNumeric, -1 },
{ DBPROP_ROWSET_ASYNCH, TRUE, eNumeric, eid_PROPVAL_ROWSET_ASYNCH },
//
// Supported interfaces
//
{ DBPROP_IAccessor, FALSE, eDefaultTrue, -1 },
{ DBPROP_IColumnsInfo, FALSE, eDefaultTrue, -1 },
{ DBPROP_IColumnsRowset, FALSE, eNotSupported, -1 },
{ DBPROP_IConnectionPointContainer, FALSE, eDefaultTrue, -1 },
{ DBPROP_IConvertType, FALSE, eDefaultTrue, -1 },
{ DBPROP_IRowset, FALSE, eDefaultTrue, -1 },
{ DBPROP_IRowsetIdentity, TRUE, eLocatable, eid_PROPVAL_IRowsetIdentity },
{ DBPROP_IRowsetInfo, FALSE, eDefaultTrue, -1 },
{ DBPROP_IRowsetLocate, TRUE, eLocatable, eid_PROPVAL_IRowsetLocate },
{ DBPROP_IRowsetScroll, TRUE, eScrollable, eid_PROPVAL_IRowsetScroll },
{ DBPROP_IRowsetExactScroll, TRUE, eScrollable, eid_PROPVAL_IRowsetExactScroll },
{ DBPROP_IDBAsynchStatus, TRUE, eAsynchronous, eid_PROPVAL_IDBAsynchStatus },
{ DBPROP_IRowsetAsynch, TRUE, eAsynchronous, eid_PROPVAL_IRowsetAsynch }, // deprecated
{ DBPROP_IRowsetWatchAll, TRUE, eWatchable, eid_PROPVAL_IRowsetWatchAll },
{ DBPROP_IRowsetWatchRegion, TRUE, eWatchable, eid_PROPVAL_IRowsetWatchRegion },
{ DBPROP_ISupportErrorInfo, FALSE, eDefaultTrue, -1 },
{ DBPROP_IChapteredRowset, FALSE, eChaptered, -1 },
};
const ULONG CMRowsetProps::cPropDescriptions =
sizeof CMRowsetProps::aPropDescriptions /
sizeof CMRowsetProps::aPropDescriptions[0];
//
// This array gives the Index Server property extensions
//
const SPropDescription CMRowsetProps::aQueryExtPropDescriptions[] = {
{ DBPROP_USECONTENTINDEX, TRUE, eUseCI, eid_PROPVAL_USECONTENTINDEX },
{ DBPROP_DEFERNONINDEXEDTRIMMING, TRUE, eDeferTrimming, eid_PROPVAL_DEFERNONINDEXEDTRIMMING },
{ DBPROP_USEEXTENDEDDBTYPES, TRUE, eExtendedTypes, eid_PROPVAL_USEEXTENDEDDBTYPES },
};
const ULONG CMRowsetProps::cQueryExtPropDescriptions =
sizeof CMRowsetProps::aQueryExtPropDescriptions /
sizeof CMRowsetProps::aQueryExtPropDescriptions[0];
//
// This is used by CMRowsetProps.
//
static const UPROPSET s_rgRowsetPropSets[] =
{
&DBPROPSET_ROWSET, NUMELEM(s_rgdbPropRowset), s_rgdbPropRowset, 0,
&DBPROPSET_MSIDXS_ROWSET_EXT, NUMELEM(s_rgdbPropMSIDXSExt), s_rgdbPropMSIDXSExt, 0,
&DBPROPSET_QUERY_EXT, NUMELEM(s_rgdbPropQueryExt), s_rgdbPropQueryExt, 0,
};
//
// CMRowsetProps methods
//
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::CMRowsetProps, public
//
// Synopsis: Constructor
//
// History: 11-12-97 danleg Created from Monarch
//
//----------------------------------------------------------------------------
CMRowsetProps::CMRowsetProps
(
LCID lcidInit
)
: CUtlProps(ARGCHK_PROPERTIESINERROR),
_dwBooleanOptions ( 0)
{
if ( lcidInit )
_lcidInit = lcidInit;
else
_lcidInit = GetSystemDefaultLCID();
FInit();
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::CMRowsetProps, public
//
// Synopsis: Copy Constructor
//
// History: 11-12-97 danleg Created from Monarch
//
//----------------------------------------------------------------------------
CMRowsetProps::CMRowsetProps
(
const CMRowsetProps & propSrc
)
: CUtlProps(ARGCHK_PROPERTIESINERROR)
{
FInit( (CUtlProps*) &propSrc );
_lcidInit = propSrc._lcidInit;
_dwBooleanOptions = propSrc._dwBooleanOptions;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::SetChaptered, public
//
// Arguments: [fSet] - set or unset this property
//
// Synopsis:
//
// History: 02-20-98 danleg Created
//
//----------------------------------------------------------------------------
DWORD CMRowsetProps::SetChaptered( BOOL fSet )
{
SetValBool( CMRowsetProps::eid_DBPROPSET_ROWSET,
CMRowsetProps::eid_PROPVAL_IChapteredRowset,
fSet ? VARIANT_TRUE : VARIANT_FALSE );
if ( fSet )
_dwBooleanOptions |= eChaptered;
else
_dwBooleanOptions &= ~eChaptered;
return _dwBooleanOptions;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::SetFirstRows, public
//
// Arguments: [ulFirstRows] - value of first rows
//
// Synopsis: Sets the FirstRows property
//
// History: 07-11-2000 KitmanH Created
//
//----------------------------------------------------------------------------
void CMRowsetProps::SetFirstRows( ULONG ulFirstRows )
{
SetValLong( CMRowsetProps::eid_DBPROPSET_ROWSET,
CMRowsetProps::eid_PROPVAL_FIRSTROWS,
ulFirstRows );
_dwBooleanOptions |= eFirstRows;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::SetImpliedProperties, public
//
// Arguments: [riidRowset] - iid requested
// [cRowsets] - indication on whethere this is a chaptered
// rowset
// Synopsis: This routine does not set any properties in the property table.
//
// History: 02-20-98 danleg Created
//
//----------------------------------------------------------------------------
DWORD CMRowsetProps::SetImpliedProperties
(
REFIID riidRowset,
ULONG cRowsets
)
{
SPropDescription const * pPropDesc = FindInterfaceDescription( riidRowset );
if ( pPropDesc == 0 )
THROW( CException(E_NOINTERFACE) );
if ( pPropDesc->fSettable )
{
Win4Assert( pPropDesc->dwIndicator >= eSequential &&
pPropDesc->dwIndicator <= eWatchable );
_dwBooleanOptions |= pPropDesc->dwIndicator;
// make sure that the eid_ in aPropDescriptions is in the range
Win4Assert( pPropDesc->uIndex < eid_PROPVAL_ROWSET_NUM );
//
// Set this property in the CMRowsetProps cache so we can later return it.
//
SetValBool( eid_DBPROPSET_ROWSET, pPropDesc->uIndex, VARIANT_TRUE );
}
else if ( pPropDesc->dwIndicator != eDefaultTrue &&
!(pPropDesc->dwIndicator & _dwBooleanOptions) )
{
THROW( CException(E_NOINTERFACE) );
}
else
{
Win4Assert( pPropDesc->dwProp == DBPROP_IRowset ||
riidRowset == IID_IRowsetIdentity ||
riidRowset == IID_IRowsetInfo ||
riidRowset == IID_IColumnsInfo ||
riidRowset == IID_IConvertType ||
riidRowset == IID_IAccessor ||
riidRowset == IID_IConnectionPointContainer );
_dwBooleanOptions |= eSequential;
}
if ( cRowsets > 1 )
_dwBooleanOptions |= eChaptered;
//
// Interface indicators are arranged in a hierarchy from most general
// to most specialized. Arrange that all more general interfaces are
// included in the properties.
//
for ( unsigned i = eWatchable; i > eSequential;
i = (i >> 1) )
{
if ( _dwBooleanOptions & i )
_dwBooleanOptions |= (i >> 1);
}
Win4Assert( _dwBooleanOptions & eSequential );
//
// Scrollable
// IRowsetScroll or IRowsetExactScroll were set. IRowsetLocate is implied.
//
if ( _dwBooleanOptions & eScrollable )
{
// IRowsetScroll is user settable. Make sure that it wasn't explicitly unset.
if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll) )
{
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll, VARIANT_TRUE );
SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll, DBPROPOPTIONS_REQUIRED );
}
// IRowsetLocate is settable. Make sure it wasn't explicitly unset.
if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
{
DWORD dwOption = GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll);
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate, VARIANT_TRUE );
SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate, dwOption );
}
}
//
// Locatable
//
if ( _dwBooleanOptions & eLocatable )
{
// these are not user settable
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANFETCHBACKWARDS, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANSCROLLBACKWARDS, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_LITERALIDENTITY, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_ORDEREDBOOKMARKS, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_QUICKRESTART, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_STRONGIDENTITY, VARIANT_TRUE );
// eLocateable (IRowsetLocate or IRowsetIdentity are set). IRowsetLocate implies BOOKMARKS
if ( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
{
// BOOKMARKs is settable. Make sure it hasn't already been set to FALSE/REQUIRED
if ( DBPROPOPTIONS_REQUIRED != GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
{
DWORD dwOption = GetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS, VARIANT_TRUE );
SetPropOption( eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS, dwOption );
}
}
}
else
{
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANFETCHBACKWARDS, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_CANSCROLLBACKWARDS, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_LITERALIDENTITY, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_ORDEREDBOOKMARKS, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_QUICKRESTART, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_STRONGIDENTITY, VARIANT_FALSE );
}
//
// Asynchronous
//
if ( _dwBooleanOptions & eAsynchronous )
{
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERINSERT, VARIANT_TRUE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERUPDATEDELETE, VARIANT_TRUE );
}
else
{
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERINSERT, VARIANT_FALSE );
SetValBool( eid_DBPROPSET_ROWSET, eid_PROPVAL_OTHERUPDATEDELETE, VARIANT_FALSE );
}
return _dwBooleanOptions;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::FindPropertyDescription, private
//
// Synopsis: Return description of a propery.
//
// Arguments: [rgPropDesc] - array of property descriptions for propset
// [cPropDesc] - count of property descriptions in rgPropDesc
// [dwPropId] - ID of the property description desired
//
// Returns: pointer to SPropDescription or NULL
//
// History: 19 Nov 95 AlanW Created
//
//----------------------------------------------------------------------------
SPropDescription const * CMRowsetProps::FindPropertyDescription(
SPropDescription const * rgPropDesc,
unsigned cPropDesc,
DBPROPID dwPropId )
{
SPropDescription const * pPropDesc = rgPropDesc;
for (unsigned i=0; i < cPropDesc; i++, pPropDesc++)
{
if (pPropDesc->dwProp == dwPropId)
return pPropDesc;
}
return 0;
}
const struct SIidLookup {
const GUID * riid;
DBPROPID dwPropId;
} aIidLookup[] = {
{ &IID_IAccessor, DBPROP_IAccessor },
{ &IID_IColumnsInfo, DBPROP_IColumnsInfo },
{ &IID_IColumnsRowset, DBPROP_IColumnsRowset },
{ &IID_IConnectionPointContainer, DBPROP_IConnectionPointContainer },
{ &IID_IConvertType, DBPROP_IConvertType },
// { &IID_ICopyColumn, DBPROP_ICopyColumn },
{ &IID_IRowset, DBPROP_IRowset },
{ &IID_IRowsetIdentity, DBPROP_IRowsetIdentity },
{ &IID_IRowsetInfo, DBPROP_IRowsetInfo },
{ &IID_IRowsetLocate, DBPROP_IRowsetLocate },
{ &IID_IRowsetScroll, DBPROP_IRowsetScroll },
{ &IID_IRowsetExactScroll, DBPROP_IRowsetExactScroll }, // deprecated
{ &IID_IDBAsynchStatus, DBPROP_IDBAsynchStatus },
{ &IID_IRowsetAsynch, DBPROP_IRowsetAsynch }, // deprecated
{ &IID_IRowsetWatchAll, DBPROP_IRowsetWatchAll },
{ &IID_IRowsetWatchRegion, DBPROP_IRowsetWatchRegion },
{ &IID_IUnknown, DBPROP_IRowset },
{ &IID_NULL, DBPROP_IRowset },
};
const unsigned cIidLookup = sizeof aIidLookup / sizeof aIidLookup[0];
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::FindInterfaceDescription, private
//
// Synopsis: Return property description corresponding to an interface
//
// Arguments: [riid] - REFIID of interface to be looked up
//
// Returns: pointer to SPropDescription or NULL
//
// History: 26 Sep 96 AlanW Created
//
//----------------------------------------------------------------------------
SPropDescription const * CMRowsetProps::FindInterfaceDescription(
REFIID riid )
{
for (unsigned i=0; i < cIidLookup; i++)
{
if (riid == *aIidLookup[i].riid)
return FindPropertyDescription( aPropDescriptions,
cPropDescriptions,
aIidLookup[i].dwPropId );
}
return 0;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::UpdateBooleanOptions, private
//
// Synopsis: Update _dwBooleanOptions to reflect newly set properties.
// Look for conflicting properties and mark them as such.
//
// History: 03-02-98 danleg Created
//
//----------------------------------------------------------------------------
void CMRowsetProps::UpdateBooleanOptions
(
const ULONG cPropertySets,
const DBPROPSET rgPropertySets[]
)
{
SCODE sc = S_OK;
DWORD dwSetOptions = 0;
DWORD dwUnsetOptions = 0;
DWORD dwOption = 0;
//
// table for boolean options
//
for ( unsigned i=0; i<cPropertySets; i++ )
{
SPropDescription const * pPropDesc = 0;
unsigned cPropDesc = 0;
unsigned cProp = rgPropertySets[i].cProperties;
DBPROP * pProp = rgPropertySets[i].rgProperties;
if ( DBPROPSET_ROWSET == rgPropertySets[i].guidPropertySet )
{
pPropDesc = aPropDescriptions;
cPropDesc = cPropDescriptions;
}
else if ( DBPROPSET_QUERY_EXT == rgPropertySets[i].guidPropertySet )
{
pPropDesc = aQueryExtPropDescriptions;
cPropDesc = cQueryExtPropDescriptions;
}
else
{
// no properties here of interest to boolean options
continue;
}
for ( unsigned j=0; j<cProp; j++, pProp++ )
{
if ( DBPROPSTATUS_OK == pProp->dwStatus )
{
//
// determine the flag to set for this property
//
SPropDescription const * pFoundDesc =
FindPropertyDescription ( pPropDesc,
cPropDesc,
pProp->dwPropertyID );
if ( 0 != pFoundDesc )
{
// Setting read-only props to their default value succeeds
if ( !pFoundDesc->fSettable )
continue;
dwOption = pFoundDesc->dwIndicator;
//
// Settable properties with special option flags
//
switch ( pProp->dwPropertyID )
{
case DBPROP_COMMANDTIMEOUT:
case DBPROP_MAXROWS:
case DBPROP_MEMORYUSAGE:
continue;
case DBPROP_FIRSTROWS:
dwOption = eFirstRows;
break;
case DBPROP_ROWSET_ASYNCH:
dwOption = eAsynchronous;
break;
default:
// no other settable props that need special handling
break;
}
//
// determine if the property was set or unset
//
switch ( V_VT(&(pProp->vValue)) )
{
case VT_BOOL:
if ( VARIANT_FALSE == V_BOOL(&(pProp->vValue)) )
dwUnsetOptions |= dwOption;
else
dwSetOptions |= dwOption;
break;
case VT_I4:
if ( DBPROPSET_ROWSET == rgPropertySets[i].guidPropertySet &&
( DBPROP_ROWSET_ASYNCH == pProp->dwPropertyID ||
DBPROP_FIRSTROWS == pProp->dwPropertyID ) )
{
if ( 0 == V_I4(&(pProp->vValue)) )
dwUnsetOptions |= dwOption;
else
dwSetOptions |= dwOption;
}
break;
case VT_EMPTY:
// assume to mean unset
dwUnsetOptions |= dwOption;
break;
default:
break;
}
}
else
{
// This should never get hit since the property was set successfully.
Win4Assert( ! "_rgdbPropRowset and aPropDescriptions are out of sync." );
}
}
}
}
Win4Assert( (dwSetOptions & dwUnsetOptions) == 0 );
if ( dwSetOptions & eScrollable )
{
dwUnsetOptions |= eSequential;
}
else if ( dwSetOptions & eSequential )
{
dwUnsetOptions |= eScrollable;
}
//
// If IRowsetLocate and/or BOOKMARKS were explicitly set, and
// IRowsetIdentity is being unset, don't take of the eLocatable bit
//
if ( dwUnsetOptions & eLocatable )
{
if ( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) ||
VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
dwUnsetOptions &= ~eLocatable;
}
_dwBooleanOptions &= ~dwUnsetOptions;
_dwBooleanOptions |= dwSetOptions;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::SetProperties, public
//
// Synopsis:
//
// History: 02-15-98 danleg Created
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::SetProperties
(
const ULONG cPropertySets,
const DBPROPSET rgPropertySets[]
)
{
SCODE sc = S_OK;
ULONG cPropSets = cPropertySets;
sc = CUtlProps::SetProperties( cPropertySets, rgPropertySets );
if ( FAILED(sc) )
return sc;
//
// Some or all of the properties were set successfully.
// Update _dwBooleanOptions.
//
UpdateBooleanOptions( cPropertySets, rgPropertySets );
return sc;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::ArePropsInError, public
//
// Synopsis: Update _dwBooleanOptions to reflect newly set properties.
// Look for conflicting properties and mark them as such.
//
// History: 03-02-98 danleg Created
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::ArePropsInError
(
CMRowsetProps & rProps
)
{
unsigned cErrors = 0;
//
// DBPROP_IRowsetScroll --> DBPROP_IRowsetLocate
//
if( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET,eid_PROPVAL_IRowsetScroll) &&
DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetScroll) )
{
// IRowsetLocate should also be set to TRUE/REQUIRED
if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) &&
DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
{
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetScroll );
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetLocate );
cErrors++;
}
// BOOKMARKS should also be set to TRUE/REQUIRED
if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) &&
DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
{
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_BOOKMARKS );
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetScroll );
cErrors++;
}
}
//
// DBPROP_IRowsteLocate --> DBPROP_BOOKMARKS
//
if( VARIANT_TRUE == GetValBool(eid_DBPROPSET_ROWSET,eid_PROPVAL_IRowsetLocate) &&
DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_IRowsetLocate) )
{
// BOOKMARKS should also be set to TRUE/REQUIRED
if ( VARIANT_FALSE == GetValBool(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) &&
DBPROPOPTIONS_REQUIRED == GetPropOption(eid_DBPROPSET_ROWSET, eid_PROPVAL_BOOKMARKS) )
{
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_BOOKMARKS );
rProps.SetPropertyInError( eid_DBPROPSET_ROWSET, eid_PROP_IRowsetLocate );
cErrors++;
}
}
return ( cErrors ) ? DB_E_ERRORSOCCURRED
: S_OK;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::InitAvailUPropsets, private
//
// Synopsis: Provide property set information to the base class
//
// History: 11-12-97 danleg Created from Monarch
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::InitAvailUPropSets
(
ULONG* pcUPropSet,
UPROPSET** ppUPropSet,
ULONG* pcElemPerSupported
)
{
Win4Assert( pcUPropSet && ppUPropSet);
Win4Assert( NUMELEM(s_rgdbPropRowset) == eid_ROWSET_PROPS_NUM );
Win4Assert( NUMELEM(s_rgdbPropQueryExt) == eid_QUERYEXT_PROPS_NUM );
Win4Assert( NUMELEM(s_rgdbPropMSIDXSExt) == eid_MSIDXS_PROPS_NUM );
*pcUPropSet = NUMELEM(s_rgRowsetPropSets);
*ppUPropSet = (UPROPSET*)s_rgRowsetPropSets;
*pcElemPerSupported = DWORDSNEEDEDPERSET;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::InitUPropSetsSupported, private
//
// Synopsis: Build the required supported property bitmask for the property
// set supported by this class
//
// History: 11-12-97 danleg Created from Monarch
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::InitUPropSetsSupported
(
DWORD* rgdwSupported
)
{
Win4Assert( rgdwSupported );
// Initialize the bitmask to indicate all properties are supported
RtlFillMemory( rgdwSupported,
DWORDSNEEDEDPERSET * NUMELEM(s_rgRowsetPropSets) * sizeof(DWORD),
0xFF );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::GetDefaultValue, private
//
// Synopsis: Retrieve the initial value for a propid.
// DEVNOTE: Using the index from 0 to (GetCountofAvailPropSets-1)
// and an index of 0 to (GetCountofAvailPropidsInPropset-1)
// within that propertyset, return the correct information.
// NOTE: pVar should be initialized prior to this routine.
//
// History: 11-12-97 danleg Created from Monarch
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::GetDefaultValue
(
ULONG iCurSet,
DBPROPID dwPropId,
DWORD* pdwOption,
VARIANT* pvValue
)
{
Win4Assert( V_VT(pvValue) == VT_EMPTY );
switch( iCurSet )
{
case eid_DBPROPSET_ROWSET:
*pdwOption = DBPROPOPTIONS_REQUIRED;
switch ( dwPropId )
{
// default TRUE values, non-writable
case DBPROP_IAccessor:
case DBPROP_IColumnsInfo:
case DBPROP_IConnectionPointContainer:
case DBPROP_IConvertType:
case DBPROP_IRowset:
case DBPROP_IRowsetInfo:
case DBPROP_ISupportErrorInfo:
case DBPROP_REMOVEDELETED:
case DBPROP_ROWRESTRICT:
case DBPROP_SERVERCURSOR:
V_VT( pvValue ) = VT_BOOL;
V_BOOL( pvValue ) = VARIANT_TRUE;
break;
case DBPROP_IChapteredRowset:
V_VT( pvValue ) = VT_BOOL;
V_BOOL( pvValue ) = VARIANT_FALSE;
break;
// default FALSE non-writable
case DBPROP_BLOCKINGSTORAGEOBJECTS:
case DBPROP_BOOKMARKSKIPPED:
case DBPROP_CANFETCHBACKWARDS:
case DBPROP_CANSCROLLBACKWARDS:
case DBPROP_COLUMNRESTRICT:
case DBPROP_LITERALBOOKMARKS:
case DBPROP_LITERALIDENTITY:
case DBPROP_ORDEREDBOOKMARKS:
case DBPROP_OTHERINSERT:
case DBPROP_OTHERUPDATEDELETE:
case DBPROP_REENTRANTEVENTS:
case DBPROP_STRONGIDENTITY:
case DBPROP_QUICKRESTART:
V_VT( pvValue ) = VT_BOOL;
V_BOOL( pvValue ) = VARIANT_FALSE;
break;
// default FALSE, writable
case DBPROP_BOOKMARKS:
case DBPROP_CANHOLDROWS:
case DBPROP_IDBAsynchStatus:
case DBPROP_IRowsetAsynch:
case DBPROP_IRowsetExactScroll:
case DBPROP_IRowsetIdentity:
case DBPROP_IRowsetScroll:
case DBPROP_IRowsetWatchAll:
case DBPROP_IRowsetWatchRegion:
case DBPROP_IRowsetLocate:
*pdwOption = DBPROPOPTIONS_OPTIONAL;
V_VT( pvValue ) = VT_BOOL;
V_BOOL( pvValue ) = VARIANT_FALSE;
break;
case DBPROP_BOOKMARKTYPE:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = DBPROPVAL_BMK_NUMERIC;
break;
case DBPROP_COMMANDTIMEOUT:
case DBPROP_MAXOPENROWS:
case DBPROP_MAXROWS:
case DBPROP_FIRSTROWS:
case DBPROP_MEMORYUSAGE:
case DBPROP_ROWSET_ASYNCH:
case DBPROP_UPDATABILITY:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = 0;
break;
case DBPROP_ROWTHREADMODEL:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = DBPROPVAL_RT_FREETHREAD;
break;
case DBPROP_NOTIFICATIONPHASES:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = DBPROPVAL_NP_OKTODO |
DBPROPVAL_NP_ABOUTTODO |
DBPROPVAL_NP_FAILEDTODO |
DBPROPVAL_NP_DIDEVENT;
break;
case DBPROP_NOTIFYROWSETRELEASE:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = 0;
break;
case DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE:
V_VT( pvValue ) = VT_I4;
V_I4( pvValue ) = DBPROPVAL_NP_OKTODO |
DBPROPVAL_NP_ABOUTTODO;
break;
case DBPROP_CACHEDEFERRED:
case DBPROP_DEFERRED:
default:
// one of the unsupported properties
VariantClear( pvValue );
break;
}
break;
case eid_DBPROPSET_QUERY_EXT:
*pdwOption = DBPROPOPTIONS_REQUIRED;
//
// All three properties under this property set are BOOL/FALSE by default
//
V_VT( pvValue ) = VT_BOOL;
V_BOOL( pvValue ) = VARIANT_FALSE;
break;
case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
*pdwOption = DBPROPOPTIONS_REQUIRED;
switch( dwPropId )
{
case MSIDXSPROP_ROWSETQUERYSTATUS:
V_VT(pvValue) = VT_I4;
V_I4(pvValue) = 0;
break;
case MSIDXSPROP_COMMAND_LOCALE_STRING:
*pdwOption = DBPROPOPTIONS_OPTIONAL;
V_VT(pvValue) = VT_BSTR;
WCHAR awcLocale[100];
GetStringFromLCID(_lcidInit, awcLocale );
V_BSTR(pvValue) = SysAllocString( awcLocale );
if ( 0 == V_BSTR(pvValue) )
return E_OUTOFMEMORY;
break;
case MSIDXSPROP_QUERY_RESTRICTION:
V_VT(pvValue) = VT_BSTR;
V_BSTR(pvValue) = SysAllocString(L"");
if ( 0 == V_BSTR(pvValue) )
return E_OUTOFMEMORY;
break;
default:
//Indicate that value is unknown
VariantClear(pvValue);
break;
}
break;
default:
// Invalid Property Set
Win4Assert( ! "Invalid property set in GetDefaultValue.");
return E_FAIL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Method: CMRowsetProps::IsValidValue, private
//
// Synopsis: Validate that the variant contains legal values for its
// particular type and for the particular PROPID in this propset.
// Devnote: This routine has to apply to writable properties only.
//
// History: 11-12-97 danleg Created from Monarch
// 02-01-98 danleg Added support for DBPROPSET_ROWSET
// and DBPROPSET_QUERYEXT
//
//----------------------------------------------------------------------------
SCODE CMRowsetProps::IsValidValue
(
ULONG iCurSet,
DBPROP* pDBProp
)
{
switch ( V_VT(&(pDBProp->vValue)) )
{
case VT_BOOL:
if ( !( VARIANT_TRUE == V_BOOL(&(pDBProp->vValue)) ||
VARIANT_FALSE == V_BOOL(&(pDBProp->vValue)) ) )
return S_FALSE;
break;
case VT_I4:
switch ( iCurSet )
{
case eid_DBPROPSET_ROWSET:
switch ( pDBProp->dwPropertyID )
{
case DBPROP_BOOKMARKTYPE:
if ( !(DBPROPVAL_BMK_NUMERIC == V_I4(&(pDBProp->vValue)) ||
DBPROPVAL_BMK_KEY == V_I4(&(pDBProp->vValue)) ) )
return S_FALSE;
break;
case DBPROP_ROWSET_ASYNCH:
switch ( V_I4(&(pDBProp->vValue)) )
{
case ( DBPROPVAL_ASYNCH_SEQUENTIALPOPULATION |
DBPROPVAL_ASYNCH_RANDOMPOPULATION ):
case DBPROPVAL_ASYNCH_RANDOMPOPULATION:
case 0: // means sequential init and population
break;
case DBPROPVAL_ASYNCH_INITIALIZE:
case DBPROPVAL_ASYNCH_SEQUENTIALPOPULATION:
default:
return S_FALSE;
}
break;
case DBPROP_ROWTHREADMODEL:
// this is a r/o property, set to FREETHREAD by default.
switch ( V_I4(&(pDBProp->vValue)) )
{
case DBPROPVAL_RT_FREETHREAD:
case DBPROPVAL_RT_APTMTTHREAD:
case DBPROPVAL_RT_SINGLETHREAD:
break;
default:
return S_FALSE;
}
break;
case DBPROP_MEMORYUSAGE:
if ( 0 > V_I4(&(pDBProp->vValue)) ||
99 < V_I4(&(pDBProp->vValue)) )
return S_FALSE;
break;
case DBPROP_COMMANDTIMEOUT:
case DBPROP_MAXROWS:
case DBPROP_FIRSTROWS:
if ( 0 > V_I4(&(pDBProp->vValue)) )
return S_FALSE;
break;
case DBPROP_UPDATABILITY:
// this is the only other supported VT_I4 property
break;
default:
// no other VT_I4 properties in DBPROPSET_ROWSET
return S_FALSE;
}
break;
case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
if ( MSIDXSPROP_ROWSETQUERYSTATUS != pDBProp->dwPropertyID )
return S_FALSE;
break;
default:
return S_FALSE;
}
break; // VT_I4
case VT_BSTR:
switch ( iCurSet )
{
case eid_DBPROPSET_MSIDXS_ROWSET_EXT:
switch ( pDBProp->dwPropertyID )
{
case MSIDXSPROP_COMMAND_LOCALE_STRING:
if ( 0 == V_BSTR(&(pDBProp->vValue)) ||
InvalidLCID == GetLCIDFromString(V_BSTR(&(pDBProp->vValue))) )
return S_FALSE;
break;
case MSIDXSPROP_QUERY_RESTRICTION:
// any bstr is valid
break;
default:
// there are no other bstr properties in this property set
return S_FALSE;
}
break;
default:
// the other two prop sets don't have any VT_BSTR properties
return S_FALSE;
}
break;
case VT_EMPTY:
// always valid
break;
default:
// no other types are supported
return S_FALSE;
}
return S_OK; // Is valid
}