//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: pidmap.cxx // // Contents: Maps pid <--> property name. // // History: 31-Jan-93 KyleP Created // //-------------------------------------------------------------------------- #include #pragma hdrstop #include #include //+------------------------------------------------------------------------- // // Member: CPidRemapper::CPidRemapper, public // // Synopsis: Creates a prop id remapper. Translates input arguments // 'fake' propids to real propids. // // Arguments: [pidmap] - input prop ID mapping array // [xPropMapper] - property mapper for real pid lookup // [prst] - optional restriction, pids will be mapped // [pcol] - optional output columns, pids will be mapped // [pso] - optional sort specification, pids will be mapped // // History: 31-Jan-93 KyleP Created // //-------------------------------------------------------------------------- CPidRemapper::CPidRemapper( const CPidMapper & pidmap, XInterface & xPropMapper, CRestriction * prst, CColumnSet * pcol, CSortSet * pso ) : _xPropMapper( xPropMapper.Acquire() ), _fAnyStatProps( FALSE ), _fContentProp ( FALSE ), _fRankVectorProp( FALSE ), _cRefs( 1 ) { _cpidReal = pidmap.Count(); _xaPidReal.Set( _cpidReal, new PROPID[ _cpidReal ] ); // // Iterate through the list // for ( unsigned i = 0; i < _cpidReal; i++ ) { PROPID pid; FULLPROPSPEC const * pFullPropSpec = pidmap.Get(i)->CastToStruct(); SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &pid ); if ( FAILED( sc ) ) THROW( CException( sc ) ); _xaPidReal[i] = pid; if ( IsUserDefinedPid( _xaPidReal[i] ) ) { // // Any user-defined property is a content property. // Note that the document characterization is a user-defined prop. // _fContentProp = TRUE; } else { if ( _xaPidReal[i] == pidContents ) _fContentProp = TRUE; else _fAnyStatProps = TRUE; if ( _xaPidReal[i] == pidRankVector ) _fRankVectorProp = TRUE; } #if CIDBG == 1 if ( vqInfoLevel & DEB_ITRACE ) { CFullPropSpec const & ps = *pidmap.Get(i); GUID const & guid = ps.GetPropSet(); char szGuid[50]; sprintf( szGuid, "%08lX-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X\\", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] ); vqDebugOut(( DEB_ITRACE, szGuid )); if ( ps.IsPropertyName() ) vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, "%ws ", ps.GetPropertyName() )); else vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, "0x%x ", ps.GetPropertyPropid() )); vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, " --> pid 0x%x\n", _xaPidReal[i] )); } #endif // CIDBG == 1 CFullPropSpec * ppsFull = new CFullPropSpec( *pidmap.Get(i) ); XPtr xpps(ppsFull); if ( xpps.IsNull() || !xpps->IsValid() ) { THROW( CException( STATUS_NO_MEMORY ) ); } _propNames.Add( ppsFull, i ); xpps.Acquire(); Win4Assert( _xaPidReal[i] != pidInvalid ); } if ( prst ) RemapPropid( prst ); if ( pcol ) RemapPropid( pcol ); if ( pso ) RemapPropid( pso ); } //+------------------------------------------------------------------------- // // Member: CPidRemapper::CPidRemapper, public // // Synopsis: Creates a prop id remapper. // // Arguments: [xPropMapper] - Property mapper for real pid lookup // // History: 12-Mar-95 DwightKr Created // //-------------------------------------------------------------------------- CPidRemapper::CPidRemapper( XInterface & xPropMapper ) : _xPropMapper( xPropMapper.Acquire() ), _cpidReal( 0 ), _cRefs( 1 ) { } //+------------------------------------------------------------------------- // // Member: CPidRemapper::~CPidRemapper, public // // History: 15-Feb-93 KyleP Created // //-------------------------------------------------------------------------- CPidRemapper::~CPidRemapper() { } //+------------------------------------------------------------------------- // // Member: CPidRemapper::RealToName, public // // Effects: Convert a PROPID to a propspec // // Arguments: [pid] - Given pid // // History: 22-Jan-97 SitaramR Added header // //-------------------------------------------------------------------------- CFullPropSpec const * CPidRemapper::RealToName( PROPID pid ) const { Win4Assert( ! _xaPidReal.IsNull() ); // // Just linear search // for ( unsigned i = 0; i < _cpidReal && _xaPidReal[i] != pid; i++ ) { continue; } Win4Assert( i < _cpidReal ); // // This can happen if a hacker tries to munge query requests // if ( i == _cpidReal ) THROW( CException( E_ABORT ) ); return( _propNames.Get( i ) ); } //+------------------------------------------------------------------------- // // Member: CPidRemapper::NameToReal, public // // Effects: Convert a property which is not necessarily in the pid map // to a PROPID. // // Arguments: [pProperty] - pointer to the propspec. // // Returns: PROPID - the mapped property ID or pidInvalid. // // History: 28 Jun 94 AlanW Created // //-------------------------------------------------------------------------- PROPID CPidRemapper::NameToReal( CFullPropSpec const * pProperty ) { for (unsigned i = 0; i < _cpidReal; i++) { if (*pProperty == *_propNames.Get(i)) { return _xaPidReal[ i ]; } } // // Property is not in the mapping array. Add it. // PROPID Prop; FULLPROPSPEC const * pFullPropSpec = pProperty->CastToStruct(); SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &Prop ); if ( FAILED( sc ) ) THROW( CException( sc ) ); if (Prop != pidInvalid) { PROPID *ppidReal = new PROPID[ _cpidReal+1 ]; memcpy(ppidReal, _xaPidReal.GetPointer(), _cpidReal * sizeof (PROPID)); // // No lock is needed here to prevent races with RealToName since in current // usage everything is added in the query path by a single thread before // reads happen from multiple threads. // PROPID *ppidTemp = _xaPidReal.Acquire(); _xaPidReal.Set( _cpidReal+1, ppidReal ); delete [] ppidTemp; CFullPropSpec * ppsFull = new CFullPropSpec( *pProperty ); XPtr xpps(ppsFull); if ( xpps.IsNull() || !xpps->IsValid() ) { THROW( CException( STATUS_NO_MEMORY ) ); } _propNames.Add( ppsFull, _cpidReal ); xpps.Acquire(); Win4Assert(*_propNames.Get(_cpidReal) == *pProperty); _xaPidReal[_cpidReal] = Prop; _cpidReal++; } return Prop; } //+------------------------------------------------------------------------- // // Member: CPidRemapper::RemapPropid, public // // Effects: Traverses [pRst], converting 'fake' propid to 'real' // // Arguments: [pRst] -- Restriction // // History: 15-Feb-93 KyleP Created // //-------------------------------------------------------------------------- void CPidRemapper::RemapPropid( CRestriction * pRst ) { Win4Assert ( pRst != 0 ); switch( pRst->Type() ) { case RTInternalProp: { CInternalPropertyRestriction * pPropRst = (CInternalPropertyRestriction *)pRst; pPropRst->SetPid( FakeToReal( pPropRst->Pid() ) ); if ( 0 != pPropRst->GetContentHelper() ) RemapPropid( pPropRst->GetContentHelper() ); break; } case RTWord: { CWordRestriction * pWordRst = (CWordRestriction *)pRst; pWordRst->SetPid( FakeToReal( pWordRst->Pid() ) ); break; } case RTSynonym: { CSynRestriction * pSynRst = (CSynRestriction *)pRst; CKeyArray & keys = pSynRst->GetKeys(); for ( int i = keys.Count() - 1; i >= 0; i-- ) { CKey & key = keys.Get(i); key.SetPid( FakeToReal( key.Pid() ) ); } break; } case RTNot: { CNotRestriction * pnrst = (CNotRestriction *)pRst; RemapPropid( pnrst->GetChild() ); break; } case RTAnd: case RTOr: case RTVector: case RTProximity: case RTPhrase: { CNodeRestriction * pNodeRst = pRst->CastToNode(); for ( int i = pNodeRst->Count() - 1; i >= 0; i-- ) { RemapPropid( pNodeRst->GetChild( i ) ); } break; } case RTRange: case RTNone: // probably a noise word in a vector query break; default: Win4Assert( !"RemapPropid: Unknown type." ); break; } } //+------------------------------------------------------------------------- // // Member: CPidRemapper::RemapPropid, public // // Effects: Traverses [pColumns], converting 'fake' propid to 'real' // // Arguments: [pColumns] -- Output columns // // History: 22-Jun-93 KyleP Created // //-------------------------------------------------------------------------- void CPidRemapper::RemapPropid( CColumnSet * pColumns ) { for ( unsigned i = 0; i < pColumns->Count(); i++ ) { pColumns->Get(i) = FakeToReal( pColumns->Get(i) ); } } //+------------------------------------------------------------------------- // // Member: CPidRemapper::RemapPropid, public // // Effects: Traverses [pSort], converting 'fake' propid to 'real' // // Arguments: [pSort] -- Restriction // // History: 15-Feb-93 KyleP Created // //-------------------------------------------------------------------------- void CPidRemapper::RemapPropid( CSortSet * pSort ) { for ( unsigned i = 0; i < pSort->Count(); i++ ) { pSort->Get(i).pidColumn = FakeToReal( pSort->Get(i).pidColumn ); } } //+------------------------------------------------------------------------- //-------------------------------------------------------------------------- void CPidRemapper::ReBuild( const CPidMapper & pidmap ) { if ( _cpidReal < pidmap.Count() ) { delete [] _xaPidReal.Acquire(); _cpidReal = 0; _xaPidReal.Set( pidmap.Count(), new PROPID[ pidmap.Count() ] ); } _cpidReal = pidmap.Count(); // // Iterate through the list // for ( unsigned i = 0; i < _cpidReal; i++ ) { PROPID pid; FULLPROPSPEC const * pFullPropSpec = pidmap.Get(i)->CastToStruct(); SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &pid ); if ( FAILED( sc ) ) THROW( CException( sc ) ); _xaPidReal[i] = pid; Win4Assert( _xaPidReal[i] != pidInvalid ); } } //+------------------------------------------------------------------------- //-------------------------------------------------------------------------- void CPidRemapper::Set( XArray & aPids ) { delete [] _xaPidReal.Acquire(); _cpidReal = aPids.Count(); _xaPidReal.Set( _cpidReal, aPids.Acquire() ); } // // This has to go somewhere... // UNICODECALLOUTS UnicodeCallouts = { WIN32_UNICODECALLOUTS }; //+------------------------------------------------------------------------- // // Method: CPidRemapper::AddRef // // Synopsis: Increments refcount // // History: 22-Jan-1997 SitaramR Created // //-------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CPidRemapper::AddRef() { return InterlockedIncrement( (long *) &_cRefs ); } //+------------------------------------------------------------------------- // // Method: CPidRemapper::Release // // Synopsis: Decrement refcount. Delete if necessary. // // History: 22-Jan-1997 SitaramR Created // //-------------------------------------------------------------------------- ULONG STDMETHODCALLTYPE CPidRemapper::Release() { Win4Assert( _cRefs > 0 ); ULONG uTmp = InterlockedDecrement( (long *) &_cRefs ); if ( 0 == uTmp ) delete this; return(uTmp); } //+------------------------------------------------------------------------- // // Method: CPidRemapper::QueryInterface // // Synopsis: Rebind to other interface // // Arguments: [riid] -- IID of new interface // [ppvObject] -- New interface * returned here // // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed // // History: 22-Jan-1997 SitaramR Created // //-------------------------------------------------------------------------- SCODE STDMETHODCALLTYPE CPidRemapper::QueryInterface( REFIID riid, void ** ppvObject) { if ( IID_ICiQueryPropertyMapper == riid ) *ppvObject = (ICiQueryPropertyMapper *)this; else if ( IID_IUnknown == riid ) *ppvObject = (IUnknown *)this; else { *ppvObject = 0; return E_NOINTERFACE; } AddRef(); return S_OK; } //+------------------------------------------------------------------------- // // Method: CPidRemapper::PropertyToPropid // // Synopsis: Convert propspec to pid // // Arguments: [pFullPropSpec] -- propspec to convert // [pPropId] -- pid returned here // // History: 22-Jan-1997 SitaramR Created // //-------------------------------------------------------------------------- SCODE STDMETHODCALLTYPE CPidRemapper::PropertyToPropid( const FULLPROPSPEC *pFullPropSpec, PROPID *pPropId) { SCODE sc = S_OK; TRY { CFullPropSpec const * pProperty = (CFullPropSpec const *) pFullPropSpec; *pPropId = NameToReal( pProperty ); } CATCH( CException, e ) { sc = e.GetErrorCode(); vqDebugOut(( DEB_ERROR, "CPidRemapper:PropertyToPropid - Exception caught 0x%x\n", sc )); } END_CATCH; return sc; } //+------------------------------------------------------------------------- // // Method: CPidRemapper::PropidToProperty // // Synopsis: Convert pid to propspec // // Arguments: [pPropId] -- pid to convert // [pFullPropSpec] -- propspec returned here // // Notes: *ppFullPropSpec is owned by CPidRemapper // // History: 22-Jan-1997 SitaramR Created // //-------------------------------------------------------------------------- SCODE STDMETHODCALLTYPE CPidRemapper::PropidToProperty( PROPID propId, FULLPROPSPEC const **ppFullPropSpec ) { SCODE sc = S_OK; TRY { *ppFullPropSpec = RealToName( propId )->CastToStruct(); } CATCH( CException, e ) { sc = e.GetErrorCode(); vqDebugOut(( DEB_ERROR, "CPidRemapper:PropidToProperty - Exception caught 0x%x\n", sc )); } END_CATCH; return sc; }