Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1331 lines
39 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: ciprop.cxx
//
// Contents: Content index property retriever
//
// History: 12-Dec-96 SitaramR Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <ciprop.hxx>
#include <catalog.hxx>
#include <smatch.hxx>
#include <prcstob.hxx>
#include <notifmgr.hxx>
#include <scopetbl.hxx>
#define SET_UNICODE_STR( str, buffer, size, maxSize ) \
str.Buffer = buffer; \
str.Length = (USHORT)size; \
str.MaximumLength = (USHORT)maxSize;
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::CCiPropRetriever, public
//
// Synopsis: Constructor
// Adds info for *all* scopes to the hashtable. Hereafter, only
// hashtable is checked to see if a file is in scope.
//
// Requires: All directories in a catalog must have a wid.
// Hashtable must be allowed to grow to hold all specified scopes.
//
// Arguments: [cat] -- Catalog
// [pQueryPropMapper] -- Pid Remapper associated with the query
// [secCache] -- Cache of AccessCheck() results
// [fUsePathAlias] -- TRUE if client is going through rdr/svr
// [scope] -- Root scope.
//
// History: 19-Aug-93 KyleP Created
// 25-Aug-97 EmilyB Add wids for all scopes to the hashtable.
//
//--------------------------------------------------------------------------
CCiPropRetriever::CCiPropRetriever( PCatalog & cat,
ICiQueryPropertyMapper *pQueryPropMapper,
CSecurityCache & secCache,
BOOL fUsePathAlias,
CRestriction * pScope )
: CGenericPropRetriever( cat, pQueryPropMapper, secCache, fUsePathAlias ? pScope : 0 ),
_fFindLoaded( FALSE ),
_fFastFindLoaded( FALSE ),
_fFastStatLoaded( 0 ),
_fFastStatNeverLoad( 0 ),
_pScope( pScope ),
_hTable(MAX_HASHED_DIRECTORIES),
_fAllScopesShallow(TRUE),
_fAllInScope(FALSE),
_fNoneInScope(FALSE)
{
if ( !ValidateScopeRestriction( _pScope ) )
THROW( CException( STATUS_NO_MEMORY ) );
//
// add scopes to hash table
//
if ( RTScope == _pScope->Type() )
{
const CScopeRestriction & scp = * (CScopeRestriction *) _pScope;
Win4Assert( scp.IsValid() );
if (scp.IsVirtual())
AddVirtualScopeRestriction(scp);
else
AddScopeRestriction(scp.GetFunnyPath(), scp.IsDeep() );
}
else if ( RTOr == _pScope->Type() )
{
CNodeRestriction const & node = * _pScope->CastToNode();
for ( ULONG x = 0; x < node.Count() && !_fAllInScope; x++ )
{
Win4Assert( RTScope == node.GetChild( x )->Type() );
const CScopeRestriction & scp = * (CScopeRestriction *)
node.GetChild( x );
Win4Assert( scp.IsValid() );
if (scp.IsVirtual())
AddVirtualScopeRestriction(scp);
else
AddScopeRestriction(scp.GetFunnyPath(), scp.IsDeep() );
}
}
if (!_fAllInScope && 0 == _hTable.Count())
_fNoneInScope = TRUE;
SET_UNICODE_STR( _Path, _xwcPath.Get(), flagNoValueYet, _xwcPath.SizeOf() );
SET_UNICODE_STR( _VPath, _xwcVPath.Get(), flagNoValueYet, _xwcVPath.SizeOf() );
_Name.Length = flagNoValueYet;
} //CCiPropRetriever
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::AddVirtualScopeRestriction, public
//
// Synopsis: Adds info to hashtable for all virtual directories which fall
// within the virtual scope specified. Hashtable entries for
// exclude directories have fInScope = FALSE.
//
// Requires: All directories in a catalog must have a wid.
// Hashtable must be allowed to grow to hold all specified scopes.
//
// Arguments: [scp] - specified scope
//
// History: 25-Aug-97 EmilyB Created
//
//--------------------------------------------------------------------------
void CCiPropRetriever::AddVirtualScopeRestriction(
CScopeRestriction const & scp)
{
unsigned iBmk = 0;
ULONG ulType = 0;
XGrowable<WCHAR> xwcVPath;
CLowerFunnyPath lcaseFunnyPPath;
unsigned ccVPath = 0;
unsigned ccPPath = 0;
//
// enumerate through all virtual roots (both include and exclude) falling
// under specified virtual scope
//
while ( _cat.VirtualToAllPhysicalRoots( scp.GetPath(), // Virtual scope (prefix)
scp.PathLength(), // + length
xwcVPath, // Full virtual root
ccVPath, // + return length
lcaseFunnyPPath, // Full physical root
ccPPath, // + return length
ulType, // root type
iBmk ) ) // Bookmark
{
//
// Special-case shallow queries at '/', so we don't end up with hits
// in the roots of all virtual roots
//
if ( ( 0 != (lcaseFunnyPPath.GetActualPath())[0] ) &&
( ( scp.IsDeep() ) ||
( 0 != scp.PathLength() ) ||
( 1 == ccVPath ) ) )
{
// if virtual scope was invalid, VirtualToPhysicalRoot will return
// path to general root + \invalid scope name, which will not have
// a wid. So this is where we catch invalid virtual scopes.
WORKID wid = _cat.PathToWorkId( lcaseFunnyPPath, FALSE );
if (widInvalid != wid )
{
//
// add info for vroot to hashtable
//
CDirWidHashEntry DirInfo(wid,
scp.IsDeep(),
(ulType & PCatalog::UsedRoot) ? TRUE : FALSE ); // include or exclude scope?
_hTable.AddEntry(DirInfo);
}
else
{
//
// This can happen. We may have hit an exclude scope that
// is not below an include scope.
//
continue;
}
}
ccVPath = ccPPath = 0;
}
if ( scp.IsDeep() )
_fAllScopesShallow = FALSE;
} //AddVirtualScopeRestriction
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::AddScopeRestriction, public
//
// Synopsis: Adds info to hashtable for all physical scope specified.
// Exclude physical scopes are not indexed, so no need to
// check for exclude scopes. If physical scope is
// above all physical roots, then adds those roots which fall
// under scope to the hashtable.
// Sets _fAllInScope to TRUE if physical scope was '\' or
// if it was a directory above all physical roots. There is no
// other way _fAllInScope can be TRUE.
//
// Requires: All directories in a catalog must have a wid.
// Hashtable must be allowed to grow to hold all specified scopes.
//
// Arguments: [lcaseFunnyPhysPath] - specified physical scope
// [fIsDeep] - is scope deep?
//
// History: 25-Aug-97 EmilyB Created
//
//--------------------------------------------------------------------------
void CCiPropRetriever::AddScopeRestriction(
const CLowerFunnyPath & lcaseFunnyPhysPath,
BOOL fIsDeep )
{
WORKID wid;
if (fIsDeep)
_fAllScopesShallow = FALSE;
if ( 0 == lcaseFunnyPhysPath.GetActualLength() )
{
//
// A physical scope of '\' that is shallow makes no sense.
//
if ( fIsDeep )
_fAllInScope = TRUE;
return;
}
CLowerFunnyPath lcaseFunnyFixedPath = lcaseFunnyPhysPath;
BOOL fImpersonated = FALSE;
//
// if scope is unc, use fixed up version
//
if ( lcaseFunnyFixedPath.IsRemote() )
{
// unc -- try to unfixup the scope. if there is no unfixup,
// it'll just use the original path.
_cat.InverseFixupPath( lcaseFunnyFixedPath );
// need to impersonate for remote access here?
if ( lcaseFunnyFixedPath.IsRemote() &&
! _remoteAccess.IsImpersonated() )
{
// ignore any error return
if ( _remoteAccess.ImpersonateIfNoThrow(
lcaseFunnyFixedPath.GetActualPath(),
0 ) )
fImpersonated = TRUE;
}
}
//
// Check to see if the input path name contains an 8.3 short name
//
if ( lcaseFunnyFixedPath.IsShortPath() )
{
vqDebugOut(( DEB_WARN,
"CCiPropRetriever::AddScopeRestriction: possible shortname path\n\t%ws ==>\n",
lcaseFunnyFixedPath.GetActualPath() ));
if ( lcaseFunnyFixedPath.ConvertToLongName() )
{
vqDebugOut(( DEB_WARN|DEB_NOCOMPNAME,
"\t%ws\n",
lcaseFunnyFixedPath.GetActualPath() ));
}
else
{
vqDebugOut(( DEB_ERROR, "longname path conversion failed!\n" ));
}
}
if ( fImpersonated )
{
_remoteAccess.Release();
}
wid = _cat.PathToWorkId( lcaseFunnyFixedPath, FALSE );
if (widInvalid != wid )
{
// straightforward case - scope has a wid - which we add to _hTable
CDirWidHashEntry DirInfo(wid, fIsDeep, TRUE);
_hTable.AddEntry(DirInfo);
return;
}
// got here because scope was not global and it didn't have a wid.
// Might be physical directory (not cataloged) above one that is
// in catalog. If scope is shallow, then nothing is in it.
// If scope is deep, enumerate through scopes and see if any
// are subdirectories of scope specified
if (fIsDeep)
{
CScopeMatch Match( lcaseFunnyFixedPath.GetActualPath(),
lcaseFunnyFixedPath.GetActualLength() );
_fAllInScope = TRUE;
CCiScopeTable *pScopes = _cat.GetScopeTable();
if ( 0 != pScopes )
{
unsigned iBmk = 0;
WCHAR awc[MAX_PATH];
while ( pScopes->Enumerate( awc,
(sizeof awc / sizeof WCHAR),
iBmk ) )
{
unsigned ccawc = wcslen(awc);
if ( Match.IsInScope( awc, ccawc ) )
{
CLowerFunnyPath lcaseFunnyAwc( awc, ccawc );
wid = _cat.PathToWorkId( lcaseFunnyAwc, FALSE );
// wid may be widInvalid if it's a scope that hasn't been
// scanned yet.
if (widInvalid != wid )
{
CDirWidHashEntry DirInfo( wid,
fIsDeep,
TRUE );
_hTable.AddEntry(DirInfo);
}
}
else // found a root not included in scope
_fAllInScope = FALSE;
}
}
}
} //AddScopeRestriction
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::GetPath, public
//
// Synopsis: Returns the path for the file
//
// Returns: A path to file
//
// History: 07-Feb-96 KyleP Added header
//
//----------------------------------------------------------------------------
UNICODE_STRING const * CCiPropRetriever::GetPath()
{
if ( _Path.Length == flagNoValueYet )
{
unsigned cwc = _xwcPath.Count();
FetchPath( _Path.Buffer, cwc );
if ( cwc > _xwcPath.Count() )
{
// Need more space
_xwcPath.SetSize( cwc );
SET_UNICODE_STR( _Path, _xwcPath.Get(), _Path.Length, _xwcPath.SizeOf() );
FetchPath( _Path.Buffer, cwc );
// Can't go on asking for more space forever !
Win4Assert( cwc <= _xwcPath.Count() );
}
if ( 0 == cwc )
_Path.Length = 0;
_Name.Length = 0;
if ( _Path.Length == 0 )
return 0;
else
{
_Path.Length = (USHORT)(cwc * sizeof( WCHAR ));
_Name.Buffer = _Path.Buffer + _Path.Length/(sizeof WCHAR) - 1;
// _Path can be path of root (e.g. c:) if indexing directories and
// root is a match. Watch that we don't walk off end.
while ( *_Name.Buffer != L'\\' && _Name.Buffer != _Path.Buffer)
{
Win4Assert( _Name.Length < _Path.Length );
_Name.Length += sizeof(WCHAR);
_Name.Buffer--;
}
if (_Name.Buffer == _Path.Buffer)
{
_Name.Buffer = _Path.Buffer + _Path.Length/(sizeof WCHAR); // point it to /0
_Name.Length=0;
}
else
{
_Name.Buffer++;
_Path.Length -= _Name.Length + sizeof WCHAR;
}
}
}
return &_Path;
} //GetPath
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::FetchVPathInVScope, private
//
// Synopsis: Returns a virtual path for the file that is in the given
// virtual scope
//
// Arguments: [xwcVPath] -- The resulting virtual path
// [pwcVScope] -- The virtual scope
// [cwcVScope] -- # of characters in pwcVScope
// [fVScopeDeep] -- TRUE if the scope is deep
//
// Returns: Length of vpath, if a vpath was found and the vpath is in the vscope
// 0 if no vpath exists in the vscope
//
// History: 02-Feb-98 dlee Created
//
//----------------------------------------------------------------------------
unsigned CCiPropRetriever::FetchVPathInVScope( XGrowable<WCHAR> & xwcVPath,
WCHAR const * pwcVScope,
const unsigned cwcVScope,
const BOOL fVScopeDeep )
{
vqDebugOut(( DEB_ITRACE, "FetchVPathInVScope, vscope '%ws', cwc %d\n",
pwcVScope, cwcVScope ));
CScopeMatch Match( pwcVScope, cwcVScope );
unsigned cSkip = 0;
unsigned cwcVPath = 0;
while ( TRUE )
{
cwcVPath = _cat.WorkIdToVirtualPath( GetPropertyRecord(),
cSkip,
xwcVPath );
if ( 0 == cwcVPath )
return 0;
//
// In scope?
//
vqDebugOut(( DEB_ITRACE, " comparing to cwc %d, '%ws'\n",
cwcVPath, xwcVPath.Get() ));
if ( !Match.IsInScope( xwcVPath.Get(), cwcVPath ) )
{
cSkip++;
continue;
}
Win4Assert( 0 == xwcVPath[cwcVPath] );
//
// If the scope is shallow, check that it's still in scope
//
if ( !fVScopeDeep )
{
unsigned cwcName = 0;
WCHAR * pwcName = xwcVPath.Get() + cwcVPath - 1;
while ( L'\\' != *pwcName )
{
Win4Assert( cwcName < cwcVPath );
cwcName++;
pwcName--;
}
unsigned cwcJustPath = cwcVPath - cwcVPath;
vqDebugOut(( DEB_ITRACE, "cwcJustPath: %d\n", cwcJustPath ));
BOOL fTooDeep = cwcJustPath > cwcVScope;
if ( fTooDeep )
{
cSkip++;
continue;
}
else
break;
}
else
break;
}
vqDebugOut(( DEB_ITRACE," InVScope: match!\n" ));
return cwcVPath;
} //FetchVPathInVScope
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::FetchVirtualPath, private
//
// Synopsis: Returns the virtual path for the file
//
// Arguments: [xwcVPath] -- The resulting virtual path
//
// Returns: If found, length of vpath ELSE 0
//
// History: 02-Feb-98 dlee Created
//
//----------------------------------------------------------------------------
unsigned CCiPropRetriever::FetchVirtualPath( XGrowable<WCHAR> & xwcVPath )
{
BOOL fUseAnyVPath = FALSE;
unsigned cwc = 0;
if ( RTScope == _pScope->Type() )
{
CScopeRestriction const & scp = * (CScopeRestriction *) _pScope;
if ( scp.IsVirtual() )
{
cwc = FetchVPathInVScope( xwcVPath,
scp.GetPath(),
scp.PathLength(),
scp.IsDeep() );
}
else
fUseAnyVPath = TRUE;
}
else if ( RTOr == _pScope->Type() )
{
CNodeRestriction const & node = * _pScope->CastToNode();
fUseAnyVPath = TRUE;
for ( ULONG x = 0; x < node.Count(); x++ )
{
Win4Assert( RTScope == node.GetChild( x )->Type() );
CScopeRestriction const & scp = * (CScopeRestriction *)
node.GetChild( x );
if ( scp.IsVirtual() )
{
cwc = FetchVPathInVScope( xwcVPath,
scp.GetPath(),
scp.PathLength(),
scp.IsDeep() );
if ( cwc > 0 )
{
fUseAnyVPath = FALSE;
break;
}
}
}
}
//
// If no virtual scope works for the file, grab any virtual path
//
if ( fUseAnyVPath )
cwc = _cat.WorkIdToVirtualPath( GetPropertyRecord(),
0,
xwcVPath );
return cwc;
} //FetchVirtualPath
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::GetVirtualPath, public
//
// Synopsis: Returns the virtual path for the file
//
// Returns: A virtual path to file, or 0 if none exists.
//
// History: 07-Feb-96 KyleP Added header
//
//----------------------------------------------------------------------------
UNICODE_STRING const * CCiPropRetriever::GetVirtualPath()
{
if ( flagNoValueYet == _VPath.Length )
{
unsigned cwc = FetchVirtualPath( _xwcVPath );
if ( 0 == cwc )
{
SET_UNICODE_STR( _VPath, _xwcVPath.Get(), flagNoValue, _xwcVPath.SizeOf() );
}
else
{
Win4Assert( 0 == _xwcVPath[cwc] );
SET_UNICODE_STR( _VPath, _xwcVPath.Get(), cwc * sizeof WCHAR, _xwcVPath.SizeOf() );
_Name.Length = 0;
_Name.Buffer = _VPath.Buffer + cwc - 1;
while ( L'\\' != *_Name.Buffer )
{
Win4Assert( _Name.Length < _VPath.Length );
_Name.Length += sizeof WCHAR;
_Name.Buffer--;
}
Win4Assert ( L'\\' == *_Name.Buffer );
_Name.Buffer++;
_VPath.Length -= _Name.Length + sizeof WCHAR;
}
}
if ( flagNoValue == _VPath.Length )
return 0;
else
return &_VPath;
} //GetVirtualPath
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::GetShortName, public
//
// Returns: A short name to file
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
UNICODE_STRING const * CCiPropRetriever::GetShortName()
{
if ( !_fFindLoaded )
Refresh( FALSE );
_ShortName.Length = wcslen( _finddata.cAlternateFileName ) * sizeof(WCHAR);
//
// If we don'th have a short name and it's not just because we were unable
// to load it, return the real file name.
//
if ( ( 0 == _ShortName.Length ) && ( 0xffffffff != _finddata.dwReserved0 ) )
return &_Name;
_ShortName.MaximumLength = _ShortName.Length;
_ShortName.Buffer = &_finddata.cAlternateFileName[0];
return &_ShortName;
} //GetShortName
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::CreateTime, public
//
// Returns: Create time for file, or 0xFFFFFFFFFFFFFFFF if unknown
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
LONGLONG CCiPropRetriever::CreateTime()
{
//
// First, should we try a fast path?
//
if ( 0 == (_fFastStatLoaded & fsCreate) )
FetchI8StatProp( fsCreate, pidCreateTime, (LONGLONG *)&_finddata.ftCreationTime );
LARGE_INTEGER li;
li.LowPart = _finddata.ftCreationTime.dwLowDateTime;
li.HighPart = _finddata.ftCreationTime.dwHighDateTime;
return li.QuadPart;
} //CreateTime
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::ModifyTime, public
//
// Returns: Last write time for file, or 0xFFFFFFFFFFFFFFFF if unknown
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
LONGLONG CCiPropRetriever::ModifyTime()
{
//
// First, should we try a fast path?
//
if ( 0 == (_fFastStatLoaded & fsModify) )
FetchI8StatProp( fsModify, pidWriteTime, (LONGLONG *)&_finddata.ftLastWriteTime );
LARGE_INTEGER li;
li.LowPart = _finddata.ftLastWriteTime.dwLowDateTime;
li.HighPart = _finddata.ftLastWriteTime.dwHighDateTime;
return li.QuadPart;
} //ModifyTime
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::AccessTime, public
//
// Returns: Last access time for file, or 0xFFFFFFFFFFFFFFFF if unknown
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
LONGLONG CCiPropRetriever::AccessTime()
{
//
// First, should we try a fast path?
//
if ( 0 == (_fFastStatLoaded & fsAccess) )
FetchI8StatProp( fsAccess, pidAccessTime, (LONGLONG *)&_finddata.ftLastAccessTime );
LARGE_INTEGER li;
li.LowPart = _finddata.ftLastAccessTime.dwLowDateTime;
li.HighPart = _finddata.ftLastAccessTime.dwHighDateTime;
return li.QuadPart;
} //AccessTime
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::ObjectSize public
//
// Returns: Size of file, or 0xFFFFFFFFFFFFFFFF if unknown
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
LONGLONG CCiPropRetriever::ObjectSize()
{
//
// First, should we try a fast path?
//
LARGE_INTEGER li;
if ( 0 == (_fFastStatLoaded & fsSize) )
{
//
// If this fails, the FindData will have been initialized.
//
if ( FetchI8StatProp( fsSize, pidSize, (LONGLONG *)&li ) )
{
_finddata.nFileSizeLow = li.LowPart;
_finddata.nFileSizeHigh = li.HighPart;
}
}
li.LowPart = _finddata.nFileSizeLow;
li.HighPart = _finddata.nFileSizeHigh;
return li.QuadPart;
} //ObjectSize
//+---------------------------------------------------------------------------
//
// Member: CCiPropRetriever::Attributes, public
//
// Returns: Attributes for file, or 0xFFFFFFFF if unknown
//
// History: 17-Apr-96 KyleP Added header
//
//----------------------------------------------------------------------------
ULONG CCiPropRetriever::Attributes()
{
//
// First, should we try a fast path?
//
if ( 0 == (_fFastStatLoaded & fsAttrib) )
{
//
// Try property store?
//
if ( 0 == (_fFastStatNeverLoad & fsAttrib) )
{
PROPVARIANT var;
unsigned cb = sizeof(var);
if ( FetchValue( pidAttrib, &var, &cb ) )
{
if ( var.vt == VT_EMPTY )
Refresh( TRUE );
else
{
Win4Assert( var.vt == VT_UI4 );
_finddata.dwFileAttributes = var.ulVal;
_fFastStatLoaded |= fsAttrib;
}
}
else
{
_fFastStatNeverLoad |= fsAttrib;
Refresh( TRUE );
}
}
else
{
Win4Assert( !_fFastFindLoaded );
Refresh( TRUE );
}
}
return _finddata.dwFileAttributes;
} //Attributes
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::IsInScope
//
// Synopsis: Test if workid in scope.
//
// History: 19-Aug-93 KyleP Created
// 30-Oct-96 dlee Added loop, moved guts to isInScope
// 26-Jun-96 emilyb optimized scope checking. No longer
// loads stat properties.
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CCiPropRetriever::IsInScope( BOOL *pfInScope )
{
if ( widInvalid == _widPrimedForPropRetrieval )
return CI_E_WORKID_NOTVALID;
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
*pfInScope = IsInScope( _widPrimedForPropRetrieval );
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
vqDebugOut(( DEB_ERROR,
"CCiPropRetriever::IsInScope - Exception caught 0x%x\n",
sc ));
}
END_CATCH;
return sc;
} //IsInScope
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::IsInScope, private
//
// Synopsis: Test if workid is in scope.
//
// Algorithm: looks for an ancestor of the current file (wid parameter) in
// the hashtable. If it finds one, it uses it to determine if
// current file is in scope. If it doesn't, the current file\
// is not in scope. It also adds an
// entry for the topmost unmatched ancestor to the hashtable.
//
// Requires: All scopes must be in hashtable. For virtual scopes, this
// requirement includes both exclude and include roots
// within the scope.
//
// Returns: TRUE if object is in scope.
//
// History: 27-Jun-97 emilyb created
//
// Notes: The only time widInvalid is valid as a parent is if the
// parent is the root of a drive.
//
//
//--------------------------------------------------------------------------
BOOL CCiPropRetriever::IsInScope( WORKID wid )
{
Win4Assert( wid == _widPrimedForPropRetrieval );
if (_fAllInScope)
{
//
// Still need to check matching attributes.
//
return ( 0 == _ulAttribFilter ) ||
( (Attributes() & _ulAttribFilter) == 0 );
}
if (_fNoneInScope)
return FALSE;
//
// is wid an inscope directory?
//
//
CDirWidHashEntry DirInfo(wid, 0); // entry to find in hash table
if (_hTable.LookUpWorkId (DirInfo) )
{
if (DirInfo.fInScope())
{
return ( 0 == _ulAttribFilter ) ||
( (Attributes() & _ulAttribFilter) == 0 );
}
else
return FALSE;
}
//
// find wid of parent
//
WORKID widParent = widInvalid; // parent of wid
WORKID widAncestor = widInvalid; // used to walk up ancestor chain
PROPVARIANT var;
BOOL fFound;
unsigned cb = sizeof(var);
fFound = FetchValue(pidParentWorkId, &var, &cb);
Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
if ( !fFound || VT_EMPTY == var.vt )
{
// file could have been deleted - not in scope
return FALSE;
}
widParent = var.ulVal;
if (widParent == widInvalid)
return FALSE;
//
// look for parent in hash table
//
DirInfo.SetWorkId(widParent); // entry to find in hash table
if (_hTable.LookUpWorkId (DirInfo) )
{
if (DirInfo.fInScope())
{
return ( 0 == _ulAttribFilter ) ||
( (Attributes() & _ulAttribFilter) == 0 );
}
else
return FALSE;
}
if (_fAllScopesShallow) // should have found it above if it was in scope
{
return FALSE;
}
//
// we've looked for parent without success -- now look for ancestors
//
cb = sizeof(var);
Quiesce(); // Can only read 1 property record at a time.
fFound = _cat.FetchValue(widParent, pidParentWorkId, &var, &cb);
Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
widAncestor = var.ulVal;
DirInfo.SetWorkId(widAncestor);
while ( fFound && VT_UI4 == var.vt &&
widAncestor != widInvalid && // not root
( !_hTable.LookUpWorkId ( DirInfo) || // not in table already
!DirInfo.fDeep() ) ) // shallow - so it doesn't apply to grandchild
{
// save topmost valid ancestor
widParent = widAncestor;
// get the previous ancestor
Quiesce(); // Can only read 1 property record at a time.
cb = sizeof(var);
fFound = _cat.FetchValue(widAncestor, pidParentWorkId, &var, &cb);
Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
widAncestor = var.ulVal;
DirInfo.SetWorkId(widAncestor);
}
if ( !fFound || VT_UI4 != var.vt )
{
// file could have been deleted -- not in scope
return FALSE;
}
BOOL fInScope = FALSE; // not in scope unless match found
BOOL fDeep = TRUE; // must be deep, or else wouldn't apply to grandchild
if (widInvalid != widAncestor) // found match
{
Win4Assert( DirInfo.fDeep() );
fInScope = DirInfo.fInScope();
}
Win4Assert( widInvalid != widParent );
// add top ancestor to hashtable
//
// Once hash table reaches max size, stop adding entries to it.
// Because it was seeded with scopes, the data is there to answer
// if something is in scope.
if(_hTable.Count() < MAX_HASHED_DIRECTORIES)
{
CDirWidHashEntry DirAnc( widParent, fDeep, fInScope );
if (!_hTable.LookUpWorkId (DirAnc) ) // be careful not to replace ancestral shallow scopes
{
_hTable.AddEntry(DirAnc);
#if CIDBG == 1
// how often do we max out the hash table
if(_hTable.Count() == MAX_HASHED_DIRECTORIES)
vqDebugOut(( DEB_WARN,
"IsInScope maxed out wid hash table with %d entries\n",
_hTable.Count()) );
#endif
}
}
//
// Still need to check matching attributes.
//
return fInScope && (( 0 == _ulAttribFilter ) ||
( (Attributes() & _ulAttribFilter) == 0 ));
} //IsInScope
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::Refresh, private
//
// Synopsis: Load stat properties for current object
//
// Arguments: [fFast] -- If TRUE, make fast call and don't load alternate
// file name.
//
// Returns: TRUE if load successful
//
// History: 19-Aug-93 KyleP Created
// 29-Feb-96 KyleP Added GetFileAttributesEx support
//
//--------------------------------------------------------------------------
BOOL CCiPropRetriever::Refresh( BOOL fFast )
{
//
// Physical path may not be loaded.
//
if ( _Path.Length == flagNoValueYet )
{
if ( 0 == GetPath() )
{
RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
_finddata.cAlternateFileName[0] = 0;
return FALSE;
}
}
if ( _Path.Length == 0 )
{
//
// Previously failed to load path, so no way to get attributes
//
RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
_finddata.cAlternateFileName[0] = 0;
return FALSE;
}
if ( CImpersonateRemoteAccess::IsNetPath(_Path.Buffer) )
{
WCHAR const * pwszVPath = (_VPath.Length == flagNoValueYet) ? 0 : _VPath.Buffer;
//
// Just blow off the file if this fails.
//
if ( !_remoteAccess.ImpersonateIfNoThrow( _Path.Buffer,
pwszVPath ) )
{
RtlFillMemory( &_finddata, sizeof WIN32_FILE_ATTRIBUTE_DATA, 0xFF );
_finddata.cAlternateFileName[0] = 0;
_Path.Length = 0;
return FALSE;
}
}
else if ( _remoteAccess.IsImpersonated() )
{
_remoteAccess.Release();
}
if ( fFast )
{
BOOL fResult;
unsigned ccPath = (_Path.Length + _Name.Length) / sizeof(WCHAR);
// handle long paths here
// we do this here instead of keeping a funnypath object all thru,
// because we get the path from the property store(in GetPath), which
// does not recognize funny paths, so we would have to do an extra
// copy operation. This we do here, but only for paths > MAX_PATH
if ( ccPath >= MAX_PATH )
{
CFunnyPath funnyPath( _Path.Buffer, ccPath );
fResult = GetFileAttributesEx( funnyPath.GetPath(), GetFileExInfoStandard, &_finddata );
}
else
{
fResult = GetFileAttributesEx( _Path.Buffer, GetFileExInfoStandard, &_finddata );
}
if ( !fResult )
{
vqDebugOut(( DEB_ERROR, "Can't retrieve fast findfirst data for %ws. Error = %d\n",
_Path.Buffer, GetLastError() ));
RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
_finddata.cAlternateFileName[0] = 0;
return FALSE;
}
_fFastFindLoaded = TRUE;
_fFastStatLoaded = fsCreate | fsModify | fsAccess | fsSize | fsAttrib;
}
else
{
unsigned ccPath = (_Path.Length + _Name.Length) / sizeof(WCHAR);
HANDLE h;
//
// handle long paths here
// we do this here instead of keeping a funnypath object all thru,
// because we get the path from the property store(in GetPath), which
// does not recognize funny paths, so we would have to do an extra
// copy operation. This we do here, but only for paths > MAX_PATH
//
if ( ccPath >= MAX_PATH )
{
CFunnyPath funnyPath( _Path.Buffer, ccPath );
h = FindFirstFile( funnyPath.GetPath(), &_finddata );
}
else
{
h = FindFirstFile( _Path.Buffer, &_finddata );
}
if ( INVALID_HANDLE_VALUE == h )
{
vqDebugOut(( DEB_ERROR, "Can't retrieve findfirst data for %ws\n",
_Path.Buffer ));
RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
_finddata.cAlternateFileName[0] = 0;
return FALSE;
}
else
{
FindClose( h );
_fFindLoaded = TRUE;
_fFastFindLoaded = TRUE;
_fFastStatLoaded = fsCreate | fsModify | fsAccess | fsSize | fsAttrib;
}
}
return TRUE;
} //Refresh
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::FetchI8StatProp, private
//
// Synopsis: Load stat property. Try property store before hitting file.
//
// Arguments: [fsProp] -- Fast stat bit to check.
// [pid] -- Pid of property
// [pDestination] -- resulting LONGLONG stored here.
//
// Returns: TRUE if property fetch successful *and* value in
// pDestination is valid.
//
// History: 17-Apr-96 KyleP Created
//
//--------------------------------------------------------------------------
BOOL CCiPropRetriever::FetchI8StatProp( CCiPropRetriever::FastStat fsProp,
PROPID pid,
LONGLONG * pDestination )
{
Win4Assert( 0 == (_fFastStatLoaded & fsProp) );
//
// Try property store?
//
if ( 0 == (_fFastStatNeverLoad & fsProp) )
{
PROPVARIANT var;
unsigned cb = sizeof(var);
if ( FetchValue( pid, &var, &cb ) )
{
if ( var.vt == VT_EMPTY )
Refresh( TRUE );
else
{
Win4Assert( var.vt == VT_I8 || var.vt == VT_UI8 || var.vt == VT_FILETIME );
*(UNALIGNED LONGLONG *)pDestination = var.hVal.QuadPart;
return TRUE;
}
}
else
{
_fFastStatNeverLoad |= fsProp;
Refresh( TRUE );
}
}
else
{
Win4Assert( !_fFastFindLoaded );
Refresh( TRUE );
}
return FALSE;
} //FetchI8StatProp
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::BeginPropertyRetrieval
//
// Synopsis: Prime wid for property retrieval
//
// Arguments: [wid] -- Wid to prime
//
// History: 12-Dec-96 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CCiPropRetriever::BeginPropertyRetrieval( WORKID wid )
{
//
// Check that we are not in the midst of a property retrieval
//
Win4Assert( _fFindLoaded == FALSE );
Win4Assert( _fFastFindLoaded == FALSE );
Win4Assert( _fFastStatLoaded == 0 );
Win4Assert( _fFastStatNeverLoad == 0 );
Win4Assert( _Path.Length == flagNoValueYet );
Win4Assert( _VPath.Length == flagNoValueYet );
Win4Assert( _Name.Length == flagNoValueYet );
Win4Assert( !_remoteAccess.IsImpersonated() );
Win4Assert( _widPrimedForPropRetrieval == widInvalid );
//
// wid should be valid
//
Win4Assert( wid != widInvalid );
_widPrimedForPropRetrieval = wid;
return S_OK;
} //BeginPropertyRetrieval
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::EndPropertyRetrieval
//
// Synopsis: Reset wid for property retrieval
//
// History: 12-Dec-96 SitaramR Created
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CCiPropRetriever::EndPropertyRetrieval( )
{
PurgeCachedInfo();
return CGenericPropRetriever::EndPropertyRetrieval();
}
//+-------------------------------------------------------------------------
//
// Member: CCiPropRetriever::GetName
//
// Synopsis: Return file name
//
// History: 12-Dec-96 SitaramR Created
//
//--------------------------------------------------------------------------
UNICODE_STRING const * CCiPropRetriever::GetName()
{
//
// Retrieving Path or VPath will retrieve Name
//
if ( _Name.Length == flagNoValueYet )
GetPath();
return &_Name;
} //GetName