//-------------------------------------------------------------------- // 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 1 cPropertyIDs and NULL pointer for // array of property ids. for(ULONG ul=0; ul