windows-nt/Source/XPSP1/NT/inetsrv/query/restrict/pidremap.cxx
2020-09-26 16:20:57 +08:00

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;
}