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

1002 lines
31 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 2000.
//
// File: FDRIVER.CXX
//
// Contents: Filter driver
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <ciole.hxx>
#include <drep.hxx>
#include <tfilt.hxx>
#include <tsource.hxx>
#include <fwevent.hxx>
#include <cievtmsg.h>
#include <propspec.hxx>
#include <imprsnat.hxx>
#include <oleprop.hxx>
#include <fdaemon.hxx>
#include <ntopen.hxx>
#include <ciguid.hxx>
#include "fdriver.hxx"
#include "propfilt.hxx"
#include "docsum.hxx"
static GUID guidNull = { 0x00000000,
0x0000,
0x0000,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
//
// Local procedures
//
BOOL IsNonIndexableProp( CFullPropSpec const & fps, PROPVARIANT const & var );
static CFullPropSpec psRevName( guidQuery, DISPID_QUERY_REVNAME );
static CFullPropSpec psName( guidStorage, PID_STG_NAME );
static CFullPropSpec psPath( guidStorage, PID_STG_PATH);
static CFullPropSpec psDirectory( guidStorage, PID_STG_DIRECTORY );
static CFullPropSpec psCharacterization( guidCharacterization,
propidCharacterization );
static CFullPropSpec psTitle( guidDocSummary, propidTitle );
static GUID guidHtmlInformation = defGuidHtmlInformation;
static CFullPropSpec psAttrib( guidStorage, PID_STG_ATTRIBUTES );
//
// Helper functions
//
inline BOOL IsSpecialPid( FULLPROPSPEC const & fps )
{
return ( fps.psProperty.ulKind == PRSPEC_PROPID &&
fps.psProperty.propid <= PID_CODEPAGE );
}
//+---------------------------------------------------------------------------
//
// Member: CFilterDriver::CFilterDriver, public
//
// Arguments:
// [drep] -- pointer to the data repository for filtered
// information
// [perfobj] -- performance object to update
// [cFilteredBlocks] -- Number of blocks filtered for the current
// document
// [cat] -- reference to a catalog proxy
//
//----------------------------------------------------------------------------
CFilterDriver::CFilterDriver ( CDataRepository * drep,
ICiCAdviseStatus * pAdviseStatus,
ICiCFilterClient * pFilterClient,
CCiFrameworkParams & params,
CI_CLIENT_FILTER_CONFIG_INFO const & configInfo,
ULONG & cFilteredBlocks,
CNonStoredProps & NonStoredProps,
ULONG cbBuf )
: _drep( drep ),
_llFileSize( 0 ),
_cFilteredBlocks( cFilteredBlocks ),
_params( params ),
_pAdviseStatus( pAdviseStatus ),
_pFilterClient( pFilterClient ),
_configInfo( configInfo ),
_NonStoredProps( NonStoredProps ),
_cbBuf( cbBuf ),
_attrib(0),
_lcidSystemDefault( GetSystemDefaultLCID() )
{
}
//+---------------------------------------------------------------------------
//
// Member: CFilterDriver::FillEntryBuffer, public
//
// Synopsis: Filters the document that IFilter loaded.
//
// Arguments: [pbDocName] -- Document in filter
// [cbDocName] -- Size of [pbDocName]
//
// Notes: Calls to SwitchToThread() give up processor.
//
//----------------------------------------------------------------------------
STATUS CFilterDriver::FillEntryBuffer( BYTE const * pbDocName, ULONG cbDocName )
{
_status = CANNOT_OPEN_STREAM;
BOOL fFilterContents = FALSE; // Assume we should NOT filter contents
//
// Get opendoc for access to stored state and safely save it
//
ICiCOpenedDoc *pDocument;
SCODE sc = _pFilterClient->GetOpenedDoc( &pDocument ); SwitchToThread();
if ( !SUCCEEDED( sc ) )
{
ciDebugOut(( DEB_ERROR, "Unable to get OpenedDoc - %x\n", sc ));
return _status;
}
XInterface<ICiCOpenedDoc> Document( pDocument );
//
// Attempt to open the document
//
sc = Document->Open( pbDocName, cbDocName );
SwitchToThread();
if (!SUCCEEDED( sc ))
{
if ( ::IsSharingViolation( sc ) )
{
_status = CI_SHARING_VIOLATION;
}
else
{
ciDebugOut(( DEB_IWARN, "Unable to open docname at 0x%X - 0x%X\n",
pbDocName, sc ));
if ( FILTER_E_UNREACHABLE == sc )
_status = CI_NOT_REACHABLE;
return _status;
}
}
// Initialize LCIDs counter.
_cLCIDs = 0;
//
// Attempt to filter properties
//
CDocCharacterization docChar( _params.GenerateCharacterization() ?
_params.GetMaxCharacterization() : 0 );
//
// Get the stat property enumerator and filter based on it.
//
CDocStatPropertyEnum CPEProp( Document.GetPointer() ); SwitchToThread();
fFilterContents = CPEProp.GetFilterContents( _params.FilterDirectories() );
_llFileSize = CPEProp.GetFileSize( );
FilterObject( CPEProp,
*_drep,
docChar ); SwitchToThread();
//
// filter security on the file.
//
if ( _configInfo.fSupportsSecurity )
{
FilterSecurity( Document.GetPointer( ), *_drep ); SwitchToThread();
}
if ( CI_SHARING_VIOLATION == _status )
return _status;
_status = SUCCESS;
BOOL fFilterOleProperties = fFilterContents;
BOOL fKnownFilter = TRUE;
BOOL fIndexable = TRUE;
if ( fFilterContents && ( 0 == ( FILE_ATTRIBUTE_ENCRYPTED & _attrib )) )
{
//
// Filter time in Mb / hr
//
CFwPerfTime filterCounter( _pAdviseStatus,
CI_PERF_FILTER_TIME,
1024*1024, 1000*60*60 );
filterCounter.TStart();
CFwPerfTime bindCounter( _pAdviseStatus,
CI_PERF_BIND_TIME );
bindCounter.TStart();
IFilter *pTmpIFilter;
sc = Document->GetIFilter( &pTmpIFilter ); SwitchToThread();
if ( !SUCCEEDED( sc ) )
pTmpIFilter = 0;
_pIFilter.Set( pTmpIFilter );
bindCounter.TStop( );
if ( _pIFilter.IsNull( ))
{
//
// We could not obtain an IFilter but we have filtered properties.
// We should just return whatever status we have.
//
ciDebugOut(( DEB_IWARN,
"Did not get a filter for document 0x%X\n",
pbDocName ));
if ( ::IsSharingViolation( sc ))
_status = CI_SHARING_VIOLATION;
else if ( FILTER_E_UNREACHABLE == sc )
_status = CI_NOT_REACHABLE;
if ( fFilterOleProperties )
{
//
// No filter, but it might have properties. Get them.
//
COLEPropertyEnum oleProp( Document.GetPointer( ) ); SwitchToThread();
BOOL fIsStorage = oleProp.IsStorage();
if (fIsStorage)
FilterObject( oleProp,
*_drep,
docChar ); SwitchToThread();
}
return _status;
}
ULONG ulFlags;
STAT_CHUNK statChunk;
sc = _pIFilter->Init( IFILTER_INIT_CANON_PARAGRAPHS |
IFILTER_INIT_CANON_HYPHENS |
IFILTER_INIT_CANON_SPACES |
IFILTER_INIT_APPLY_INDEX_ATTRIBUTES |
IFILTER_INIT_INDEXING_ONLY,
0,
0,
&ulFlags ); SwitchToThread();
if ( FAILED(sc) )
{
ciDebugOut(( DEB_WARN, "IFilter->Init() failed.\n" ));
THROW( CException( sc ) );
}
fFilterOleProperties = (( ulFlags & IFILTER_FLAGS_OLE_PROPERTIES ) != 0);
//
// Determine the maximum number of filtered blocks allowed for this
// file.
//
unsigned __int64 ullMultiplier = _params.GetMaxFilesizeMultiplier();
unsigned __int64 ullcbBuf = _cbBuf;
unsigned __int64 ullcbFile = _llFileSize;
unsigned __int64 ullcBlocks = 1 + ( ullcbFile / ullcbBuf );
unsigned __int64 ullmaxBlocks = ullcBlocks * ullMultiplier;
if ( ullmaxBlocks > ULONG_MAX )
ullmaxBlocks = ULONG_MAX;
ULONG ulMaxFilteredBlocks = (ULONG) ullmaxBlocks;
ciDebugOut(( DEB_ITRACE,
"cbfile %I64d, cBlocks %I64d, maxcBlocks %I64d\n",
ullcbFile, ullcBlocks, ullmaxBlocks ));
//
// Get the first chunk
//
do
{
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
}
while ( SUCCEEDED(sc) && IsSpecialPid( statChunk.attribute ) );
_drep->InitFilteredBlockCount( ulMaxFilteredBlocks );
_cFilteredBlocks = 0;
NTSTATUS Status = STATUS_SUCCESS;
TRY
{
BOOL fBadEmbeddingReport = FALSE;
while ( SUCCEEDED(sc) ||
FILTER_E_LINK_UNAVAILABLE == sc ||
FILTER_E_EMBEDDING_UNAVAILABLE == sc )
{
BOOL fInUse;
Document->IsInUseByAnotherProcess( &fInUse ); SwitchToThread();
if ( fInUse )
{
_status = FILTER_EXCEPTION; // Force retry in driver
break; // Stop filtering this doc
}
_cFilteredBlocks = _drep->GetFilteredBlockCount();
if ( SUCCEEDED(sc) )
{
if ( IsSpecialPid( statChunk.attribute ) )
{
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
continue;
}
//
// Skip over unknown chunks.
//
if ( 0 == (statChunk.flags & (CHUNK_TEXT | CHUNK_VALUE)) )
{
ciDebugOut(( DEB_WARN,
"Filtering of docname at 0x%X produced bogus chunk (not text or value)\n",
pbDocName ));
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
continue;
}
if ( statChunk.flags & CHUNK_VALUE )
{
PROPVARIANT * pvar = 0;
sc = _pIFilter->GetValue( &pvar );
if ( SUCCEEDED(sc) )
{
XPtr<CStorageVariant> xvar( (CStorageVariant *)(ULONG_PTR)pvar );
CFullPropSpec * pps = (CFullPropSpec *)(ULONG_PTR)(&statChunk.attribute);
//
// HACK #275: If we see a ROBOTS=NOINDEX tag, then bail out.
//
if ( IsNonIndexableProp( *pps, *pvar ) )
{
ciDebugOut(( DEB_WARN,
"Document %x is not indexable (robots Meta-tag)\n",
pbDocName ));
sc = S_OK;
fFilterOleProperties = FALSE;
fIndexable = FALSE;
break;
}
// Index this property twice -- once with default locale and with
// the chunk locale.
FilterProperty( *pvar, *pps, *_drep, docChar, statChunk.locale ); SwitchToThread();
if (_lcidSystemDefault != statChunk.locale)
{
FilterProperty( *pvar, *pps, *_drep, docChar, _lcidSystemDefault ); SwitchToThread();
}
//
// Only fetch next if we're done with this chunk.
//
if ( 0 == (statChunk.flags & CHUNK_TEXT) || !SUCCEEDED(sc) )
{
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
continue;
}
}
}
if ( (statChunk.flags & CHUNK_TEXT) && SUCCEEDED(sc) )
{
if ( _drep->PutLanguage( statChunk.locale ) &&
_drep->PutPropName( *((CFullPropSpec *)&statChunk.attribute) ) )
{
CTextSource tsource( _pIFilter.GetPointer( ), statChunk );
docChar.Add( tsource.awcBuffer + tsource.iCur,
tsource.iEnd - tsource.iCur,
statChunk.attribute ); SwitchToThread();
_drep->PutStream( &tsource ); SwitchToThread();
sc = tsource.GetStatus();
}
else
{
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
}
if ( sc == FILTER_E_NO_TEXT && (statChunk.flags & CHUNK_VALUE) )
sc = S_OK;
}
}
if ( FILTER_E_EMBEDDING_UNAVAILABLE == sc )
{
if ( !fBadEmbeddingReport &&
(_params.GetEventLogFlags()&CI_EVTLOG_FLAGS_FAILED_EMBEDDING) )
{
ReportFilterEmbeddingFailure( pbDocName, cbDocName );
fBadEmbeddingReport = TRUE;
}
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
}
else if ( FILTER_E_LINK_UNAVAILABLE == sc )
{
sc = _pIFilter->GetChunk( &statChunk ); SwitchToThread();
if (SUCCEEDED(sc))
RegisterLocale(statChunk.locale);
}
}
}
CATCH ( CException, e )
{
Status = e.GetErrorCode();
ciDebugOut(( DEB_IERROR,
"Exception 0x%x thrown from filter DLL while filtering docName at 0x%X\n",
Status,
pbDocName ));
}
END_CATCH
if ( !NT_SUCCESS(Status) && Status != FDAEMON_E_TOOMANYFILTEREDBLOCKS )
{
THROW( CException(FDAEMON_E_FATALERROR) );
}
if ( Status == FDAEMON_E_TOOMANYFILTEREDBLOCKS )
{
Win4Assert( _drep->GetFilteredBlockCount() > ulMaxFilteredBlocks );
LogOverflow( pbDocName, cbDocName );
//
// Force exit from the loop
//
sc = FILTER_E_END_OF_CHUNKS;
}
_pIFilter.Free( );
filterCounter.TStop( (ULONG)_llFileSize );
}
if ( FILTER_E_END_OF_CHUNKS != sc &&
FILTER_E_PARTIALLY_FILTERED != sc &&
FAILED( sc ) )
{
ciDebugOut(( DEB_IWARN, "Filter document at 0x(%X) returned SCODE 0x%x\n",
pbDocName, sc ));
QUIETTHROW( CException( sc ) );
}
BOOL fIsStorage = FALSE;
if ( fFilterOleProperties )
{
//
// filter ole properties only if it is a docfile
//
COLEPropertyEnum oleProp( Document.GetPointer( ) ); SwitchToThread();
fIsStorage = oleProp.IsStorage();
if (fIsStorage)
FilterObject( oleProp,
*_drep,
docChar ); SwitchToThread();
}
//
// Store the document characterization in the property cache.
// Don't bother if characterization is turned off.
//
if ( _params.GenerateCharacterization() )
{
PROPVARIANT var;
WCHAR awcSummary[ CI_MAX_CHARACTERIZATION_MAX + 1 ];
if ( fIndexable && docChar.HasCharacterization() )
{
unsigned cwcSummary = sizeof awcSummary / sizeof WCHAR;
// Use the raw text in the abstract unless we defaulted
// to the text filter and the file has ole properties.
BOOL fUseRawText = fKnownFilter || !fIsStorage;
docChar.Get( awcSummary, cwcSummary, fUseRawText ); SwitchToThread();
if ( 0 == cwcSummary )
{
var.vt = VT_EMPTY;
}
else
{
var.vt = VT_LPWSTR;
var.pwszVal = awcSummary;
}
}
else
{
var.vt = VT_EMPTY;
}
_drep->StoreValue( psCharacterization, var ); SwitchToThread();
}
return _status;
}
//+---------------------------------------------------------------------------
//
// Member: CFilterDriver::LogOverflow
//
// Synopsis: Notifies the client that there were too many blocks in the
// given document
//
// Arguments: [pbDocName] - Document Name
// [cbDocName] - Number of bytes in the document name.
//
// History: 1-22-97 srikants Created
//
//----------------------------------------------------------------------------
void CFilterDriver::LogOverflow( BYTE const * pbDocName, ULONG cbDocName )
{
PROPVARIANT var[2];
var[0].vt = VT_VECTOR | VT_UI1;
var[0].caub.cElems = cbDocName;
var[0].caub.pElems = (BYTE *) pbDocName;
var[1].vt = VT_UI4;
var[1].ulVal = _params.GetMaxFilesizeMultiplier();
SCODE sc = _pAdviseStatus->NotifyStatus( CI_NOTIFY_FILTER_TOO_MANY_BLOCKS,
2,
var );
if ( !SUCCEEDED(sc) )
{
ciDebugOut(( DEB_WARN,
"Failed to report filter to many blocks event. Error 0x%X\n",
sc ));
}
}
//+---------------------------------------------------------------------------
//
// Member: CFilterDriver::ReportFilterEmbeddingFailure
//
// Synopsis: Notifies the client that there was a failure filtering an
// embedding.
//
// Arguments: [pbDocName] - Document name
// [cbDocName] - Number of bytes in the serialized document name
//
// History: 1-22-97 srikants Created
//
//----------------------------------------------------------------------------
void CFilterDriver::ReportFilterEmbeddingFailure( BYTE const * pbDocName, ULONG cbDocName )
{
PROPVARIANT var;
var.vt = VT_VECTOR | VT_UI1;
var.caub.cElems = cbDocName;
var.caub.pElems = (BYTE *) pbDocName;
SCODE sc = _pAdviseStatus->NotifyStatus( CI_NOTIFY_FILTER_EMBEDDING_FAILURE,
1,
&var );
if ( !SUCCEEDED(sc) )
{
ciDebugOut(( DEB_WARN,
"Failed to report filter embedding failure event. Error 0x%X\n",
sc ));
}
}
//+---------------------------------------------------------------------------
//
// Method: CFilterDriver::FilterProperty
//
// Arguments: [var] -- Property value
// [ps] -- Property ID
// [drep] -- Data repository for filtered information
// [docChar] -- Characterization
//
// Notes: Calls to SwitchToThread() give up processor.
//
//----------------------------------------------------------------------------
inline void CFilterDriver::FilterProperty( CStorageVariant const & var,
CFullPropSpec & ps,
CDataRepository & drep,
CDocCharacterization & docChar,
LCID locale )
{
//
// Filter one very special property: Backwards name
//
if (ps == psName && var.Type( ) == VT_LPWSTR)
{
const WCHAR *pwszPath = var.GetLPWSTR( );
int j = wcslen( pwszPath );
XGrowable<WCHAR> xwcsRevName( j + 1 );
int i;
for ( i = 0; i < j; i++ )
{
xwcsRevName[i] = pwszPath[j - 1 - i];
}
xwcsRevName[i] = L'\0';
PROPVARIANT Variant;
Variant.vt = VT_LPWSTR;
Variant.pwszVal = xwcsRevName.Get();
//
// Cast to avoid turning the PROPVARIANT into a CStorageVariant for no good
// reason. Convert involves alloc/free.
//
CStorageVariant const * pvar = (CStorageVariant const *)(ULONG_PTR)(&Variant);
FilterProperty( *pvar, psRevName, drep, docChar, 0 ); SwitchToThread();
}
//
// Don't filter paths
//
if ( ps != psPath )
{
Win4Assert( psDirectory != ps );
vqDebugOut(( DEB_FILTER, "Filter property 0x%x\n", ps.GetPropertyPropid() ));
//
// Save some property values for use in document characterization
//
docChar.Add( var, ps ); SwitchToThread();
//
// output the property to the data repository
//
drep.PutLanguage( locale );
drep.PutPropName( ps );
drep.PutValue( var ); SwitchToThread();
// Store the value in the property cache if it should be stored there
if ( !_NonStoredProps.IsNonStored( ps ) )
{
BOOL fStoredInCache;
if ( IsNullPointerVariant( (PROPVARIANT *) & var ) )
{
PROPVARIANT propVar;
propVar.vt = VT_EMPTY;
fStoredInCache = drep.StoreValue( ps, propVar ); SwitchToThread();
}
else
{
fStoredInCache = drep.StoreValue( ps, var ); SwitchToThread();
}
// should we ignore this property in the future?
if ( !fStoredInCache )
_NonStoredProps.Add( ps );
}
}
if ( ps == psAttrib )
_attrib = var.GetUI4();
} //FilterProperty
//+---------------------------------------------------------------------------
//
// Method: CFilterDriver::FilterObject
//
// Arguments: [propEnum] -- iterator for properties in a file
// [drep] -- pointer to the data repository for filtered
// information
// [docChar] -- some property values are written here so that
// document characterization can happen
//
// Notes: Calls to SwitchToThread() give up processor.
//
//----------------------------------------------------------------------------
void CFilterDriver::FilterObject(
CPropertyEnum & propEnum,
CDataRepository & drep,
CDocCharacterization & docChar )
{
#if CIDBG == 1
ULONG ulStartTime = GetTickCount();
#endif
CFullPropSpec ps;
// Get the locale for the property set. Use that if available, else use all the
// known locales to maximize the chances of retrieving a property.
LCID locale;
BOOL fUseKnownLocale = SUCCEEDED( propEnum.GetPropertySetLocale(locale));
for ( CStorageVariant const * pvar = propEnum.Next( ps );
pvar != 0;
pvar = propEnum.Next( ps ) )
{
//
// Filter each of the properties and property sets until we run
// out of them. Register each property for each of the registered locales.
//
FilterProperty( *pvar, ps, drep, docChar, _lcidSystemDefault ); SwitchToThread();
if (fUseKnownLocale)
{
ciDebugOut((DEB_FILTER, "Propset locale is 0x%x\n", locale));
if (locale != _lcidSystemDefault)
{
FilterProperty( *pvar, ps, drep, docChar, locale ); SwitchToThread();
}
}
else
{
// We want to index this property with all the known locales only if it
// is a "string" type. For non-string types, locale doesn't matter
VARTYPE vt = pvar->Type() | VT_VECTOR; // enables check with or without vt_vector bit
if (vt == (VT_VECTOR | VT_LPWSTR) ||
vt == (VT_VECTOR | VT_BSTR) ||
vt == (VT_VECTOR | VT_LPSTR)
)
{
int iMin = min(_cLCIDs, cLCIDMax);
for (int i = 0; i < iMin; i++)
{
ciDebugOut(( DEB_ITRACE, "Filtering property 0x%x with locale 0x%x\n",
pvar, _alcidSeen[i] ));
if (_alcidSeen[i] != _lcidSystemDefault)
{
FilterProperty( *pvar, ps, drep, docChar, _alcidSeen[i] ); SwitchToThread();
}
}
}
}
}
#if CIDBG == 1
ULONG ulEndTime = GetTickCount();
ciDebugOut (( DEB_USER1,
"Filtering properties took %d ms\n",
ulEndTime-ulStartTime ));
#endif
}
//+-------------------------------------------------------------------------
//
// Member: CFilterDriver::FilterSecurity, private
//
// Synopsis: Store the security descriptor and map to an SDID
//
// Arguments: [wcsFileName] - file name (used only for error reporting)
// [oplock] - oplock held on the file
// [drep] - data repository
//
// Notes: using ACCESS_SYSTEM_SECURITY AccessMode will cause an
// oplock break, so we should call FilterSecurity before
// taking the oplock.
//
// Notes: Calls to SwitchToThread() give up processor.
//
//--------------------------------------------------------------------------
void CFilterDriver::FilterSecurity(
ICiCOpenedDoc *Document,
CDataRepository & drep )
{
BOOL fCouldStore = FALSE;
SCODE sc;
//
// Initial guess about security descriptor size
//
const cInitSD = 512;
BYTE abBuffer[cInitSD];
ULONG cbSD = cInitSD;
BYTE * pbBuffer = abBuffer;
XPtr<SECURITY_DESCRIPTOR> xSD;
while (TRUE)
{
//
// Attempt to get the security descriptor into the buffer
//
sc = Document->GetSecurity( pbBuffer, &cbSD ); SwitchToThread();
//
// If we don't need to resize, then exit while
//
if (SUCCEEDED( sc ) || CI_E_BUFFERTOOSMALL != sc)
{
break;
}
//
// Allocate a bigger buffer and retrieve the security information into
// it.
//
xSD.Free();
xSD.Set( (SECURITY_DESCRIPTOR *) new BYTE [cbSD] );
pbBuffer = (BYTE *) xSD.GetPointer();
}
if ( !SUCCEEDED( sc ) || 0 == cbSD )
{
//
// Store NULL security descriptor for the file
//
fCouldStore = drep.StoreSecurity( 0, 0 ); SwitchToThread();
}
else
{
// Now store away the security descriptor and map to an SDID
fCouldStore =
drep.StoreSecurity( pbBuffer, cbSD ); SwitchToThread();
}
if (! fCouldStore)
{
ciDebugOut(( DEB_ERROR, "Failed to store security info\n" ));
}
}
//+---------------------------------------------------------------------------
//
// Function: CFilterDriver::RegisterLocale, private
//
// Synopsis: Registers a locale
//
// Arguments: [locale] - the locale
//
// Returns: none
//
// History: 27-Jan-99 KrishnaN Created
//
//----------------------------------------------------------------------------
void CFilterDriver::RegisterLocale(LCID locale)
{
// Ensure that the locale wasn't already registered
int iMin = min(_cLCIDs, cLCIDMax);
for (int i = 0; i < iMin; i++)
{
if (locale == _alcidSeen[i])
return;
}
_alcidSeen[_cLCIDs % cLCIDMax] = locale;
ciDebugOut(( DEB_ITRACE, "Registered %d locale 0x%x\n", _cLCIDs+1, locale));
_cLCIDs++;
}
//+---------------------------------------------------------------------------
//
// Function: IsNonIndexableProp, private
//
// Synopsis: Looks for ROBOTS=NOINDEX tag
//
// Arguments: [fps] -- Property
// [var] -- Value
//
// Returns: TRUE if property [fps] == ROBOTS and value [var] == NOINDEX
//
// History: 7-Oct-97 KyleP Stole from Site Server
//
// Notes: I based my changes to this code in information found at:
// http://info.webcrawler.com/mak/projects/robots/meta-user.html
//
//----------------------------------------------------------------------------
BOOL IsNonIndexableProp( CFullPropSpec const & fps, PROPVARIANT const & var )
{
static GUID guidHTMLMeta = HTMLMetaGuid;
BOOL fIsNonIndexable = FALSE;
if ( fps.IsPropertyName() &&
fps.GetPropSet() == guidHTMLMeta &&
_wcsicmp( fps.GetPropertyName(), L"ROBOTS" ) == 0 &&
(var.vt == VT_LPWSTR || var.vt == VT_BSTR) &&
0 != var.pwszVal )
{
//
// Convert to lowercase to do wcsstr search.
//
unsigned cc = wcslen( var.pwszVal ) + 1;
XGrowable<WCHAR> xwcsTemp( cc );
RtlCopyMemory( xwcsTemp.Get(), var.pwszVal, cc * sizeof(WCHAR) );
_wcslwr( xwcsTemp.Get() );
//
// Check "noindex"
//
fIsNonIndexable = wcsstr( xwcsTemp.Get(), L"noindex") != 0;
//
// Check "all"
//
if ( !fIsNonIndexable )
fIsNonIndexable = wcsstr( xwcsTemp.Get(), L"none") != 0;
}
return fIsNonIndexable;
}