//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 2000. // // File: ciprop.cxx // // Contents: Content index property retriever // // History: 12-Dec-96 SitaramR Created // //-------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include #include #include #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 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 & 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 - cwcName; vqDebugOut(( DEB_ITRACE, "cwcJustPath: %d\n", cwcJustPath )); BOOL fTooDeep = cwcJustPath > ( cwcVScope + 1 ); 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 & 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