//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1998. // // File: StdQSpec.cxx // // Contents: IQuery for file-based queries // // Classes: CQuerySpec // // History: 30 Jun 1995 AlanW Created // //---------------------------------------------------------------------------- #include #pragma hdrstop extern long gulcInstances; #include #include #include #include #include #include #include #include #include "stdqspec.hxx" //+------------------------------------------------------------------------- // // Member: CQuerySpec::QueryInternalQuery, protected // // Synopsis: Instantiates internal query, using current parameters. // // Returns: Pointer to internal query object. // // History: 03-Mar-1997 KyleP Created // 14-May-1997 mohamedn hidden core/fs property sets // //-------------------------------------------------------------------------- PIInternalQuery * CQuerySpec::QueryInternalQuery() { // // get a pointer to the PIInternalQuery interface // XInterface xIDbProps(new CDbProperties); if ( xIDbProps.IsNull() ) THROW( CException( E_OUTOFMEMORY ) ); CGetCmdProps getCmdProps( (ICommand *)this); SCODE sc; PIInternalQuery * pQuery; ULONG cardinality = getCmdProps.GetCardinality(); if ( cardinality <= 1 ) { getCmdProps.PopulateDbProps( xIDbProps.GetPointer() ); sc = EvalQuery( &pQuery, xIDbProps.GetReference(), _xDocStore.GetPointer()); } else { Win4Assert( !_xDocStore.GetPointer() ); sc = EvalDistributedQuery( &pQuery, getCmdProps ); } if ( FAILED( sc ) ) QUIETTHROW( CException( sc ) ); Win4Assert( 0 != pQuery ); return pQuery; } //QueryInternalQuery //+------------------------------------------------------------------------- // // Member: CQuerySpec::CQuerySpec, public // // Synopsis: Constructor of a CQuerySpec // // Arguments: [pOuterUnk] - Outer unknown // [ppMyUnk] - OUT: filled in with pointer to non-delegated // IUnknown on return // [pDocStore] - Known DocStore // // History: 22-Apr-97 KrishnaN Created // //-------------------------------------------------------------------------- CQuerySpec::CQuerySpec ( IUnknown * pOuterUnk, IUnknown ** ppMyUnk, ICiCDocStore * pDocStore ) : CRootQuerySpec(pOuterUnk, ppMyUnk) { // // Squirrel away DocStore. // pDocStore->AddRef(); _xDocStore.Set(pDocStore); InitScopePropertySets(); } //CQuerySpec //+------------------------------------------------------------------------- // // Member: CQuerySpec::InitScopePropertySets, private // // Synopsis: Initializes internal data structs // // Arguments: none // // History: 06-04-97 mohamedn Created // //-------------------------------------------------------------------------- void CQuerySpec::InitScopePropertySets() { RtlZeroMemory( _aPropSet, sizeof (_aPropSet) ); _aCoreProps.Init ( INITIAL_PROPERTIES_COUNT ); _aFsClientProps.Init( INITIAL_PROPERTIES_COUNT ); _aPropSet[0].guidPropertySet = DBPROPSET_CIFRMWRKCOREEXT; _aPropSet[0].rgProperties = _aCoreProps.GetPointer(); _aPropSet[1].guidPropertySet = DBPROPSET_FSCIFRMWRKEXT; _aPropSet[1].rgProperties = _aFsClientProps.GetPointer(); } //InitScopePropertySets //+--------------------------------------------------------------------------- // // Method: CQuerySpec::SetProperties, public // // Synopsis: Set rowset scope properties // // Arguments: [cPropertySets] - number of property sets // [rgPropertySets] - array of property sets // // Returns: SCODE - result code indicating error return status. One of // S_OK, DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED. Any // other errors are thrown. // // History: 01-Mar-97 KyleP Created // 14-May-97 mohamedn hidden core/fs property set details // 12-Dec-97 danleg ReleaseInternalQuery if setting scope props // //---------------------------------------------------------------------------- SCODE STDMETHODCALLTYPE CQuerySpec::SetProperties( ULONG cPropertySets, DBPROPSET rgPropertySets[] ) { _DBErrorObj.ClearErrorInfo(); // // First, get parent properties. // SCODE scParent = CRootQuerySpec::SetProperties( cPropertySets, rgPropertySets ); // // Any non-understood error is a bail. Return the error/successes from the parent. // if ( scParent != DB_S_ERRORSOCCURRED && scParent != DB_E_ERRORSOCCURRED ) return scParent; BOOL fFoundErrors = FALSE; SCODE sc = S_OK; // // Set properties not handled by parent // TRANSLATE_EXCEPTIONS; TRY { DBPROPSET *pDbPropset = rgPropertySets; BOOL fScopeProps = FALSE; for ( unsigned i = 0; i < cPropertySets; i++, pDbPropset++ ) { if ( DBPROPSET_FSCIFRMWRKEXT == pDbPropset->guidPropertySet || DBPROPSET_CIFRMWRKCOREEXT == pDbPropset->guidPropertySet ) { SetPropertyset( pDbPropset ); fScopeProps = TRUE; } else { // // keep track of any errors occured in base class. // DBPROP * pProp = pDbPropset->rgProperties; ULONG cProps = pDbPropset->cProperties; for ( unsigned j = 0; j < cProps; j++ ) { if ( DBPROPSTATUS_OK != pProp[j].dwStatus ) fFoundErrors = TRUE; } } } // // If we found any scope properties, release the // internal query object. // if ( fScopeProps ) { ReleaseInternalQuery(); } } CATCH( CException, e ) { scParent = GetOleError( e ); fFoundErrors = TRUE; } END_CATCH; UNTRANSLATE_EXCEPTIONS; if ( fFoundErrors ) { if ( S_OK != scParent ) { _DBErrorObj.PostHResult( scParent, IID_ICommandProperties ); return scParent; } else { _DBErrorObj.PostHResult( DB_S_ERRORSOCCURRED, IID_ICommandProperties ); return DB_S_ERRORSOCCURRED; } } else return S_OK; } //SetProperties //+--------------------------------------------------------------------------- // // Method: CQuerySpec::SetPropertyset, private // // Synopsis: Sets non-rowset properties // // Arguments: [pPropertyset] - pointer to property set (to be set). // // Returns: none - THROWS upon failure. // // History: 05-14-97 mohamedn created // //---------------------------------------------------------------------------- void CQuerySpec::SetPropertyset( DBPROPSET *pPropertySet ) { DBPROP * pProp = pPropertySet->rgProperties; ULONG cProps= pPropertySet->cProperties; // // un-error property dwStatus set by parent // for ( unsigned j = 0; j < cProps; j++ ) { switch ( pProp[j].dwStatus ) { case DBPROPSTATUS_NOTSUPPORTED: pProp[j].dwStatus = DBPROPSTATUS_OK; break; case DBPROPSTATUS_OK: break; default: vqDebugOut(( DEB_ERROR, "Unexpected pProp[j].dwStatus: j=%x, dwStatus=%x \n",j,pProp[j].dwStatus )); } } // // identify destination propset // for ( unsigned k = 0; k < SCOPE_PROPSET_COUNT; k++ ) { if ( _aPropSet[k].guidPropertySet == pPropertySet->guidPropertySet ) break; } if ( k == SCOPE_PROPSET_COUNT ) { Win4Assert( !"Should never be hit" ); THROW( CException(DB_E_ERRORSOCCURRED)); } // // update property set // UpdatePropertySet( _aPropSet[k], *pPropertySet ); } //SetPropertyset //+--------------------------------------------------------------------------- // // Method: CQuerySpec::UpdatePropertySet, private // // Synopsis: Sets non-rowset properties // // Arguments: [destPropSet] - destination property set // [srcPropSet] - source property set // // Returns: none - THROWS upon failure. // // History: 06-04-97 mohamedn created // //---------------------------------------------------------------------------- void CQuerySpec::UpdatePropertySet(DBPROPSET &destPropSet, DBPROPSET &srcPropSet ) { CDbProp * pDestProp = (CDbProp *)destPropSet.rgProperties; CDbProp * pSrcProp = (CDbProp *)srcPropSet.rgProperties; ULONG cErrors = 0; for ( unsigned i = 0; i < srcPropSet.cProperties; i++ ) { for ( unsigned j = 0; j < destPropSet.cProperties; j++ ) { if ( pDestProp[j].dwPropertyID == pSrcProp[i].dwPropertyID ) { if ( !pDestProp[j].Copy(pSrcProp[i]) ) THROW( CException(E_OUTOFMEMORY) ); break; } } if ( j == destPropSet.cProperties ) { // // new PropID // if ( destPropSet.guidPropertySet == DBPROPSET_CIFRMWRKCOREEXT && j >= _aCoreProps.Count() ) { _aCoreProps.GrowToSize( srcPropSet.cProperties ); _aPropSet[0].rgProperties = _aCoreProps.GetPointer(); pDestProp = (CDbProp *)destPropSet.rgProperties; } else if ( destPropSet.guidPropertySet == DBPROPSET_FSCIFRMWRKEXT && j >= _aFsClientProps.Count() ) { _aFsClientProps.GrowToSize( srcPropSet.cProperties ); _aPropSet[1].rgProperties = _aFsClientProps.GetPointer(); pDestProp = (CDbProp *)destPropSet.rgProperties; } Win4Assert( pDestProp[j].dwPropertyID == 0 ); Win4Assert( pDestProp[j].dwStatus == 0 ); if ( !pDestProp[j].Copy(pSrcProp[i]) ) THROW( CException(E_OUTOFMEMORY) ); destPropSet.cProperties++; } } if ( cErrors == srcPropSet.cProperties ) THROW (CException( DB_E_ERRORSOCCURRED ) ); if ( cErrors > 0 ) THROW (CException( DB_S_ERRORSOCCURRED ) ); } //UpdatePropertySet //+--------------------------------------------------------------------------- // // Method: CQuerySpec::GetProperties, public // // Synopsis: Get rowset properties // // Arguments: [cPropertySetIDs] - number of desired property set IDs or 0 // [rgPropertySetIDs] - array of desired property set IDs or NULL // [pcPropertySets] - number of property sets returned // [prgPropertySets] - array of returned property sets // // Returns: SCODE - result code indicating error return status. One of // S_OK, DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED. Any // other errors are thrown. // // History: 01-Mar-97 KyleP Created // 14-May-97 mohamedn hidden core/fs property set details // //---------------------------------------------------------------------------- SCODE STDMETHODCALLTYPE CQuerySpec::GetProperties( ULONG const cPropertySetIDs, DBPROPIDSET const rgPropertySetIDs[], ULONG * pcPropertySets, DBPROPSET ** prgPropertySets) { _DBErrorObj.ClearErrorInfo(); BOOL fAddScopeProperties = FALSE; ULONG cPropSetIDs = cPropertySetIDs; XArray aPropIDSets; CDbPropIDSet * pPropIDSet = (CDbPropIDSet *)rgPropertySetIDs; ULONG cAllocPropSets = cPropertySetIDs; // // Don't give back the scope properties for "all properties". If the // magic number 3141592653 is given in, all properties including the // scope properties are returned. // if ( 3141592653 == cPropertySetIDs ) { fAddScopeProperties = TRUE; cPropSetIDs = 0; // // We want all properties, including scope properties. The base // implementation doesn't know about scope properties // SCODE sc = S_OK; TRY { aPropIDSets.Init( 5 ); } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH; if ( FAILED( sc ) ) return sc; aPropIDSets[0].guidPropertySet = DBPROPSET_ROWSET; aPropIDSets[0].cPropertyIDs = 0; aPropIDSets[1].guidPropertySet = DBPROPSET_MSIDXS_ROWSET_EXT; aPropIDSets[1].cPropertyIDs = 0; aPropIDSets[2].guidPropertySet = DBPROPSET_QUERY_EXT; aPropIDSets[2].cPropertyIDs = 0; aPropIDSets[3].guidPropertySet = DBPROPSET_CIFRMWRKCOREEXT; aPropIDSets[3].cPropertyIDs = 0; aPropIDSets[4].guidPropertySet = DBPROPSET_FSCIFRMWRKEXT; aPropIDSets[4].cPropertyIDs = 0; cAllocPropSets = aPropIDSets.Count(); pPropIDSet = aPropIDSets.GetPointer(); } SCODE scParent = CRootQuerySpec::GetProperties( cAllocPropSets, pPropIDSet, pcPropertySets, prgPropertySets ); // // Any non-understood error is a bail. S_OK here means all properties were // handled by parent. Just return unless *all* props were requested. // if ( scParent != DB_S_ERRORSOCCURRED && scParent != DB_E_ERRORSOCCURRED ) { if ( scParent != S_OK || 0 != cPropSetIDs ) return scParent; } SCODE sc = S_OK; BOOL fFoundErrors = FALSE; TRANSLATE_EXCEPTIONS; TRY { // // Find query properties. // if ( 0 == cPropSetIDs && fAddScopeProperties ) { // // Case 1: All properties were requested. Append scope onto // appropriate property set. // for ( unsigned i = 0; i < SCOPE_PROPSET_COUNT; i++ ) { DBPROPIDSET dbPropIdSet; ZeroMemory((void *) &dbPropIdSet, sizeof DBPROPIDSET ); dbPropIdSet.guidPropertySet = _aPropSet[i].guidPropertySet; // // scan dest array of propsets (set by base) for matching guid. // for ( unsigned j = 0; j < *pcPropertySets; j++ ) { if ( dbPropIdSet.guidPropertySet == (*prgPropertySets)[j].guidPropertySet ) { GetPropValues( dbPropIdSet, (*prgPropertySets)[j], fFoundErrors ); break; } } // // PropSet not found // if ( j == *pcPropertySets ) { fFoundErrors = TRUE; Win4Assert( !"CRowsetProperties doesn't support requested propset." ); Win4Assert( !"base & derived classes are out of sync!"); } } } else { // // Case 2: Specific properties were requested. // for ( unsigned i = 0; i < cPropSetIDs; i++ ) { // // scan dest array of propsets (set by base) for matching guid. // for ( unsigned j = 0; j < *pcPropertySets; j++ ) { if ( (*prgPropertySets)[j].guidPropertySet == rgPropertySetIDs[i].guidPropertySet ) { GetPropValues( rgPropertySetIDs[i], (*prgPropertySets)[j], fFoundErrors ); break; } } // // PropSet not found // if ( j == *pcPropertySets ) { fFoundErrors = TRUE; Win4Assert( !"Unexpected PropertySet requested" ); } } } } CATCH( CException, e ) { sc = e.GetErrorCode(); } END_CATCH UNTRANSLATE_EXCEPTIONS; if ( FAILED(sc) && sc != DB_E_ERRORSOCCURRED ) { for ( unsigned i = 0; i < *pcPropertySets; i++ ) { DBPROP * rgProperties = (*prgPropertySets)[i].rgProperties; unsigned cProperties = (*prgPropertySets)[i].cProperties; for ( unsigned j = 0; j < cProperties; j++ ) VariantClear( &(rgProperties[j].vValue) ); CoTaskMemFree( rgProperties ); } CoTaskMemFree( *prgPropertySets ); *prgPropertySets = 0; } if ( fFoundErrors ) { if ( scParent != S_OK ) { _DBErrorObj.PostHResult( scParent, IID_ICommandProperties ); return scParent; } else { _DBErrorObj.PostHResult( DB_S_ERRORSOCCURRED, IID_ICommandProperties ); return DB_S_ERRORSOCCURRED; } } return sc; } //GetProperties //+------------------------------------------------------------------------- // // Member: CQuerySpec::GetPropValues, private // // Synopsis: Gets values of properties in a property set. // // Arguments: [rgPropertySetIDs] [in] - array of propIDs to get // [rgPropertySet] [out] - reference to property set to fill // [fFoundErrors] [out] - TRUE if any errors are found, but not thrown. // // Returns: Throws in case of failure // // History: 04-15-97 mohamedn created // //-------------------------------------------------------------------------- void CQuerySpec::GetPropValues( DBPROPIDSET const & rgPropertySetIDs, DBPROPSET & rgPropertySet, BOOL & fFoundErrors) { Win4Assert( rgPropertySet.guidPropertySet == rgPropertySetIDs.guidPropertySet ); // // Locate private property set source // for ( unsigned i = 0; i < SCOPE_PROPSET_COUNT; i++ ) { if ( rgPropertySet.guidPropertySet == _aPropSet[i].guidPropertySet ) { break; // found source property set } } // // If not one of the scope propsets, return // if ( SCOPE_PROPSET_COUNT == i ) { fFoundErrors = TRUE; return; } DBPROPSET & srcPropSet = _aPropSet[i]; DBPROP * psrcDbProp = srcPropSet.rgProperties; ULONG cPropsFound= 0; ULONG cDbProps = rgPropertySetIDs.cPropertyIDs ? rgPropertySetIDs.cPropertyIDs : srcPropSet.cProperties; XArrayOLEInPlace aDbProps( cDbProps ); // // scan private property set for reqeusted propId values // if ( 0 == rgPropertySetIDs.cPropertyIDs ) { // // return all properties // for ( i = 0; i < srcPropSet.cProperties; i++ ) { if ( !aDbProps[i].Copy( psrcDbProp[i] ) ) THROW( CException(E_OUTOFMEMORY) ); Win4Assert( aDbProps[i].dwStatus == DBPROPSTATUS_OK ); } cPropsFound = i; } else { // // specific properties within this prop set are requested // for ( unsigned iPropsRequested = 0; iPropsRequested < rgPropertySetIDs.cPropertyIDs; iPropsRequested++ ) { for ( unsigned iPropSrc = 0; iPropSrc < srcPropSet.cProperties; iPropSrc++ ) { if ( rgPropertySetIDs.rgPropertyIDs[iPropsRequested] == psrcDbProp[iPropSrc].dwPropertyID ) { if ( !aDbProps[iPropsRequested].Copy( psrcDbProp[iPropSrc] ) ) THROW( CException(E_OUTOFMEMORY) ); Win4Assert( aDbProps[iPropsRequested].dwStatus == DBPROPSTATUS_OK ); break; } } // // if requested propID not found // if ( iPropSrc == srcPropSet.cProperties ) { // // Property ID not set // aDbProps[iPropsRequested].dwPropertyID = rgPropertySetIDs.rgPropertyIDs[iPropsRequested]; aDbProps[iPropsRequested].dwStatus = DBPROPSTATUS_NOTSET; fFoundErrors = TRUE; } } cPropsFound = iPropsRequested; } // // free rgProperties allocated by base class, assign new one. // CoTaskMemFree( rgPropertySet.rgProperties ); rgPropertySet.rgProperties = aDbProps.Acquire(); rgPropertySet.cProperties = cPropsFound; } //GetPropValues