613 lines
16 KiB
C++
613 lines
16 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
||
|
//
|
||
|
// File: pidmap.cxx
|
||
|
//
|
||
|
// Contents: Maps pid <--> property name.
|
||
|
//
|
||
|
// History: 31-Jan-93 KyleP Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <pidremap.hxx>
|
||
|
#include <coldesc.hxx>
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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<IPropertyMapper> & 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<CFullPropSpec> 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<IPropertyMapper> & 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<CFullPropSpec> 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<PROPID> & 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|