//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: cmdprutl.cxx // // Contents: A wrapper for scope properties around ICommand // // History: 5-10-97 mohamedn created // //---------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include static GUID const guidQueryCorePropset = DBPROPSET_CIFRMWRKCORE_EXT; static GUID const guidCiFsExt = DBPROPSET_FSCIFRMWRK_EXT; static const cFsCiProps = 4; static const cInitProps = 2; static const cScopePropSets = 2; // // utility functions // extern WCHAR **GetWCharFromVariant ( DBPROP & dbProp, ULONG *cElements ); extern DWORD * GetDepthsFromVariant( DBPROP & dbProp, ULONG *cElements, ULONG mask ); //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::CGetCmdProps // // Synopsis: Constructor - Initializes all, calls GetProperties(). // // History: 5-10-97 mohamedn created // //---------------------------------------------------------------------------- CGetCmdProps::CGetCmdProps( ICommand * pICommand ) :_fGuidValid(FALSE), _aDepths(0), _aPaths(0), _aCatalogs(0), _aMachines(0), _cDepths(0), _cScopes(0), _cCatalogs(0), _cMachines(0), _cGuids(0), _type(CiNormal), _cPropertySets(0), _cCardinality(0xffffffff) { RtlZeroMemory( &_clientGuid, sizeof GUID ); SCODE sc = pICommand->QueryInterface( IID_ICommandProperties, _xICmdProp.GetQIPointer() ); if ( FAILED(sc) ) THROW( CException(sc) ); // // Populate our internal data structs // GetProperties(); SetCardinalityValue(); } //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::GetProperties // // Synopsis: Retrieves all the properties from ICommandProperties interface. // // Arguments: none // // Returns: Throws upon failure. // // History: 5-10-97 mohamedn created // //---------------------------------------------------------------------------- // // Hack #214: IID_ICommandProperties is intercepted by service layers, which // don't like us passing in the magic code to fetch hidden scope // properties. But the controlling unknown doesn't recognize // IID_IKyleProp and sends it right to us. Implementation is // identical to ICommandProperties. // GUID IID_IKyleProp = { 0xb4237bc2, 0xe09f, 0x11d1, 0x80, 0xc0, 0x00, 0xc0, 0x4f, 0xa3, 0x54, 0xba }; void CGetCmdProps::GetProperties() { // get all properties including scope props XInterface xTemp; SCODE sc = _xICmdProp->QueryInterface( IID_IKyleProp, xTemp.GetQIPointer() ); const ULONG cPropIdSets = 3141592653; DBPROPSET * pDbPropSet; ULONG cPropertySets; if ( SUCCEEDED(sc) ) sc = xTemp->GetProperties( cPropIdSets, 0, &cPropertySets, &pDbPropSet ); if ( FAILED(sc) ) { // On this failure, you have to free the properties returned! Win4Assert( DB_E_ERRORSOCCURRED != sc ); ciDebugOut(( DEB_ERROR, "Failed to do GetProperties (0x%X)\n", sc )); THROW( CException( sc ) ); } _xPropSet.Set( cPropertySets, (CDbPropSet *) pDbPropSet ); _cPropertySets = cPropertySets; for ( ULONG i = 0; i < cPropertySets; i++ ) ProcessPropSet( pDbPropSet[i] ); } //GetProperties //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::SetCardinalityValue // // Synopsis: validates and sets the Cardinality value // // Arguments: none // // Returns: none - throws upon failure. // // History: 5-12-97 mohamedn moved from CQuerySpec // //---------------------------------------------------------------------------- void CGetCmdProps::SetCardinalityValue() { // // Final cardinality check... // if ( _cDepths != _cScopes || (_cScopes != _cCatalogs && _cCatalogs != 1) || _cCatalogs != _cMachines ) { ciDebugOut(( DEB_ERROR, "CQuerySpec::QueryInternalQuery -- Cardinality mismatch\n" )); THROW( CException( CI_E_CARDINALITY_MISMATCH ) ); } // The query is distributed if multiple machines or multiple catalogs // are present. Multiple scopes on one catalog/machine are handled // by a non-distributed query. BOOL fDistributed = FALSE; if (_cCatalogs > 1) { for ( unsigned i = 0; !fDistributed && i < _cScopes-1; i++ ) { if ( ( _wcsicmp( _aMachines[i], _aMachines[i+1] ) ) || ( _wcsicmp( _aCatalogs[i], _aCatalogs[i+1] ) ) ) { fDistributed = TRUE; } } } // Win4Assert( !" Break here to set single/distributed query" ); if ( fDistributed ) { Win4Assert( _cCatalogs > 1 ); _cCardinality = _cCatalogs; // distributed case } else if ( 0 == _cCatalogs ) { _cCardinality = 0; // local case } else { _cCardinality = 1; // single machine case. } } //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::PopulateDbProps // // Synopsis: Creates a new IDBProperties using ICommand properties // // Arguments: [pIDBProperties] -- IDBProperties interface // [iElement] -- specifies which of the distributed properties to use // // Returns: none - thorws upon failure. // // History: 5-12-97 mohamedn created // //---------------------------------------------------------------------------- void CGetCmdProps::PopulateDbProps(IDBProperties *pIDBProperties, ULONG iElement ) { Win4Assert( !_xICmdProp.IsNull() ); // src Win4Assert( pIDBProperties != 0 ); // destination Win4Assert( _cPropertySets != 0 ); // at least one property set exist. Win4Assert( _xPropSet.GetPointer() != 0 ); DBPROPSET * pPropSet = 0; ULONG cPropSets = 0; XArrayOLEInPlace xPropSet; CreateNewPropSet(&cPropSets, &pPropSet, iElement); Win4Assert( pPropSet != 0 ); Win4Assert( cPropSets != 0 ); xPropSet.Set(cPropSets,(CDbPropSet *)pPropSet); SCODE sc = pIDBProperties->SetProperties( cPropSets, xPropSet.GetPointer()); if ( FAILED(sc) ) THROW( CException(sc) ); } //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::CreateNewPropSet, private // // Synopsis: Creates new property sets on IDBProperties from ICommand properties. // // Arguments: [cPropSets] -- count of property sets // [ppPropSet] -- to return new property sets // [index] -- specifies which of the distributed properties to use // // Returns: none - throws upon failure. // // History: 05-12-97 mohamedn created // //---------------------------------------------------------------------------- void CGetCmdProps::CreateNewPropSet(ULONG *cPropSets, DBPROPSET **ppPropSet, ULONG index) { XArrayOLEInPlace xPropSet(_cPropertySets); ULONG cPropSetsCopied = 0; for ( unsigned i = 0; i < _cPropertySets; i++ ) { if ( _xPropSet[i].guidPropertySet == guidQueryCorePropset ) { CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], index ); cPropSetsCopied++; } else if ( _xPropSet[i].guidPropertySet == guidCiFsExt ) { CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], index ); cPropSetsCopied++; } else { // // Other property sets just get copied verbatim (e.g. index == 0) // CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], 0 ); cPropSetsCopied++; } } *cPropSets = cPropSetsCopied; *ppPropSet = xPropSet.Acquire(); } //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::CopyPropertySet, private // // Synopsis: Copies srcPropSet to destPropSet - using index for distributed props. // // Arguments: [destPropSet] -- destination prop set // [srcPropSet] -- source prop set // [index] -- specifies which of the distributed properties to use // // Returns: none - throws upon failure. // // History: 05-12-97 mohamedn created // //---------------------------------------------------------------------------- void CGetCmdProps::CopyPropertySet( CDbPropSet &destPropSet, CDbPropSet &srcPropSet, ULONG index ) { RtlZeroMemory( &destPropSet, sizeof (CDbPropSet) ); RtlCopyMemory( &destPropSet.guidPropertySet, &srcPropSet.guidPropertySet, sizeof GUID ); XArrayOLEInPlace xDestDbPrp(srcPropSet.cProperties); // // copy all the properties from the src property set // for ( unsigned i = 0; i < srcPropSet.cProperties; i++ ) { CDbProp & destProp = xDestDbPrp[i]; CDbProp & srcProp = (CDbProp &)srcPropSet.rgProperties[i]; RtlZeroMemory(&destProp, sizeof (CDbProp) ); if ( srcProp.dwStatus != DBPROPSTATUS_OK ) { destProp.dwPropertyID = srcPropSet.rgProperties[i].dwPropertyID; destProp.dwStatus = DBPROPSTATUS_NOTSET; destProp.vValue.vt = VT_EMPTY; ciDebugOut(( DEB_TRACE, "PropID: %x, dwStatus: %x\n", srcPropSet.rgProperties[i].dwPropertyID, srcProp.dwStatus )); continue; } if ( destPropSet.guidPropertySet == guidQueryCorePropset ) { switch (srcProp.dwPropertyID) { case DBPROP_MACHINE: CopyDbProp(destProp, srcProp, index); break; default: if ( !destProp.Copy( srcProp ) ) THROW( CException(E_OUTOFMEMORY) ); } } else if ( destPropSet.guidPropertySet == guidCiFsExt ) { switch (srcProp.dwPropertyID) { case DBPROP_CI_INCLUDE_SCOPES: case DBPROP_CI_DEPTHS: // // in none-distributed case, Scope and Depth cardinality can be > 1 // if ( _cCardinality <= 1 ) { if ( !destProp.Copy( srcProp ) ) THROW( CException(E_OUTOFMEMORY) ); } else { // distributed case. CopyDbProp(destProp, srcProp, index); } break; case DBPROP_CI_CATALOG_NAME: CopyDbProp(destProp, srcProp, index); break; default: if ( !destProp.Copy( srcProp ) ) THROW( CException(E_OUTOFMEMORY) ); } } // if-else-if else { if ( !destProp.Copy( srcProp ) ) THROW( CException(E_OUTOFMEMORY) ); } } // for destPropSet.rgProperties = xDestDbPrp.Acquire(); destPropSet.cProperties = srcPropSet.cProperties; } //CopyPropertySet //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::CopyDbProp // // Synopsis: copies source dbprop to the dest dbprop. // // Arguments: [destProp] -- destination dbProp // [srcProp] -- source dbprop // [index] -- specifies which property to copy // // Returns: None - throws upon failure. // // History: 05-12-97 mohamedn created // //---------------------------------------------------------------------------- void CGetCmdProps::CopyDbProp(CDbProp &destProp, CDbProp &srcProp, ULONG index) { RtlCopyMemory(&destProp,&srcProp,sizeof(CDbProp)); VARIANT & srcVar = srcProp.vValue; VARIANT & destVar= destProp.vValue; RtlZeroMemory( &destVar, sizeof (VARIANT) ); // // index must be 0 if variant is not a safearray // if ( !(srcVar.vt & VT_ARRAY) && (0 != index) ) { ciDebugOut(( DEB_ERROR, "index must be zero if not using VT_ARRAY, Index: %x\n", index)); THROW( CException( STATUS_INVALID_PARAMETER ) ); } else if ( (srcVar.vt & VT_ARRAY) && (index >= srcVar.parray->rgsabound[0].cElements) ) { ciDebugOut(( DEB_ERROR, "index value out of range: %x\n", index )); THROW( CException( STATUS_INVALID_PARAMETER ) ); } // // copy dbprop // switch (srcVar.vt) { case VT_ARRAY|VT_BSTR: { SAFEARRAY & sa = *srcVar.parray; BSTR * pBstr = (BSTR *)sa.pvData; if ( sa.cDims != 1 ) THROW( CException( STATUS_INVALID_PARAMETER ) ); destVar.vt = VT_BSTR; destVar.bstrVal = SysAllocString(pBstr[index]); if ( 0 == destVar.bstrVal ) THROW( CException(E_OUTOFMEMORY) ); } break; case VT_BSTR: { destVar.vt = VT_BSTR; destVar.bstrVal = SysAllocString(srcVar.bstrVal); if ( 0 == destVar.bstrVal ) THROW( CException(E_OUTOFMEMORY) ); } break; case VT_ARRAY|VT_I4: case VT_ARRAY|VT_UI4: { SAFEARRAY & sa = *srcVar.parray; DWORD * pdwDepths = (DWORD *)sa.pvData; if ( sa.cDims != 1 ) THROW( CException( STATUS_INVALID_PARAMETER ) ); destVar.vt = VT_I4; destVar.lVal = pdwDepths[index]; } break; case VT_I4: case VT_UI4: { destVar.vt = VT_I4; destVar.lVal = srcVar.lVal; } break; default: ciDebugOut(( DEB_ERROR,"Invalid VARIANT type: %x\n",destVar.vt)); THROW( CException( STATUS_INVALID_PARAMETER ) ); } } //+--------------------------------------------------------------------------- // // Member: CGetDbProps::ProcessDbInitPropSet // // Synopsis: Processes the DBPROPSET_INIT property set. // // Arguments: [propSet] - The property set to process. // // Returns: none - throws upon failure. // // History: 1-13-97 srikants Created // 5-12-97 mohamedn fs/core prop set splits. // //---------------------------------------------------------------------------- void CGetCmdProps::ProcessDbInitPropSet( DBPROPSET & propSet ) { CDbPropSet * pDbPropSet = (CDbPropSet *) &propSet; for ( ULONG i = 0; i < propSet.cProperties; i++ ) { CDbProp * pDbProp = pDbPropSet->GetProperty(i); if ( DBPROPSTATUS_OK != pDbProp->dwStatus ) { ciDebugOut(( DEB_TRACE, "DbProp.dwPropertyID: %x has dwStatus= %x\n", pDbProp->dwPropertyID,pDbProp->dwStatus)); continue; } switch ( pDbProp->dwPropertyID ) { case DBPROP_MACHINE: // machine count can be greater than 1 _aMachines = GetWCharFromVariant(*pDbProp, &_cMachines); Win4Assert( 0 != _aMachines ); break; case DBPROP_CLIENT_CLSID: { WCHAR **apGuids = GetWCharFromVariant(*pDbProp, &_cGuids); if ( _cGuids == 1 ) { CGuidUtil::StringToGuid( apGuids[0], _clientGuid ); _fGuidValid = TRUE; } else { ciDebugOut(( DEB_ERROR, "Invalid value for PropertyID(%x)\n", pDbProp->dwPropertyID )); THROW( CException(STATUS_INVALID_PARAMETER) ); } } break; default: ciDebugOut(( DEB_ERROR, "InvalidPropertyID(%x)\n", pDbProp->dwPropertyID )); THROW( CException(STATUS_INVALID_PARAMETER) ); } } } //ProcessDbInitPropSet //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::ProcessCiFsExtPropSet // // Synopsis: Processes the FSCI extension property set. // // Arguments: [propSet] - The propety set to process. // Returns: none - throws upon failure. // // History: 1-13-97 srikants Created // 5-12-97 mohamedn fs/core prop set splits. // //---------------------------------------------------------------------------- void CGetCmdProps::ProcessCiFsExtPropSet( DBPROPSET & propSet ) { CDbPropSet * pDbPropSet = (CDbPropSet *) &propSet; for ( ULONG i = 0; i < propSet.cProperties; i++ ) { CDbProp * pDbProp = pDbPropSet->GetProperty(i); if ( pDbProp->dwStatus != DBPROPSTATUS_OK ) { ciDebugOut(( DEB_TRACE, "PropStatus (0x%X) for (%d) th property\n", pDbProp->dwStatus, i )); continue; } switch ( pDbProp->dwPropertyID ) { case DBPROP_CI_CATALOG_NAME: _aCatalogs = GetWCharFromVariant(*pDbProp,&_cCatalogs); break; case DBPROP_CI_DEPTHS: _aDepths = GetDepthsFromVariant(*pDbProp, &_cDepths, (ULONG)~( QUERY_SHALLOW | QUERY_DEEP | QUERY_PHYSICAL_PATH | QUERY_VIRTUAL_PATH ) ); break; case DBPROP_CI_INCLUDE_SCOPES: _aPaths = GetWCharFromVariant(*pDbProp, &_cScopes); break; case DBPROP_CI_QUERY_TYPE: switch ( pDbProp->vValue.vt) { case VT_I4: case VT_UI4: _type = (CiMetaData) pDbProp->vValue.ulVal; break; default: ciDebugOut(( DEB_ERROR, "DBPROP_CI_QUERY_TYPE: invalid variant type: %x\n", pDbProp->vValue.vt )); THROW( CException(STATUS_INVALID_PARAMETER) ); } break; default: { // // skip extra properties // ciDebugOut(( DEB_TRACE, "non-Native PropID(%x)\n", pDbProp->dwPropertyID )); } } } } //+--------------------------------------------------------------------------- // // Member: CGetCmdProps::ProcessPropSet // // Synopsis: Processes the given property set. // // Arguments: [propSet] - // // History: 1-13-97 srikants Created // //---------------------------------------------------------------------------- void CGetCmdProps::ProcessPropSet( DBPROPSET & propSet ) { if ( propSet.guidPropertySet == guidCiFsExt ) { ProcessCiFsExtPropSet( propSet ); } else if ( propSet.guidPropertySet == guidQueryCorePropset ) { ProcessDbInitPropSet( propSet ); } else { // // skip other property sets -- not needed for Indexing Service. // } }