Leaked source code of windows server 2003
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
41 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: ciprop.cxx
  7. //
  8. // Contents: Content index property retriever
  9. //
  10. // History: 12-Dec-96 SitaramR Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <ciprop.hxx>
  16. #include <catalog.hxx>
  17. #include <smatch.hxx>
  18. #include <prcstob.hxx>
  19. #include <notifmgr.hxx>
  20. #include <scopetbl.hxx>
  21. #define SET_UNICODE_STR( str, buffer, size, maxSize ) \
  22. str.Buffer = buffer; \
  23. str.Length = (USHORT)size; \
  24. str.MaximumLength = (USHORT)maxSize;
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Member: CCiPropRetriever::CCiPropRetriever, public
  28. //
  29. // Synopsis: Constructor
  30. // Adds info for *all* scopes to the hashtable. Hereafter, only
  31. // hashtable is checked to see if a file is in scope.
  32. //
  33. // Requires: All directories in a catalog must have a wid.
  34. // Hashtable must be allowed to grow to hold all specified scopes.
  35. //
  36. // Arguments: [cat] -- Catalog
  37. // [pQueryPropMapper] -- Pid Remapper associated with the query
  38. // [secCache] -- Cache of AccessCheck() results
  39. // [fUsePathAlias] -- TRUE if client is going through rdr/svr
  40. // [scope] -- Root scope.
  41. //
  42. // History: 19-Aug-93 KyleP Created
  43. // 25-Aug-97 EmilyB Add wids for all scopes to the hashtable.
  44. //
  45. //--------------------------------------------------------------------------
  46. CCiPropRetriever::CCiPropRetriever( PCatalog & cat,
  47. ICiQueryPropertyMapper *pQueryPropMapper,
  48. CSecurityCache & secCache,
  49. BOOL fUsePathAlias,
  50. CRestriction * pScope )
  51. : CGenericPropRetriever( cat, pQueryPropMapper, secCache, fUsePathAlias ? pScope : 0 ),
  52. _fFindLoaded( FALSE ),
  53. _fFastFindLoaded( FALSE ),
  54. _fFastStatLoaded( 0 ),
  55. _fFastStatNeverLoad( 0 ),
  56. _pScope( pScope ),
  57. _hTable(MAX_HASHED_DIRECTORIES),
  58. _fAllScopesShallow(TRUE),
  59. _fAllInScope(FALSE),
  60. _fNoneInScope(FALSE)
  61. {
  62. if ( !ValidateScopeRestriction( _pScope ) )
  63. THROW( CException( STATUS_NO_MEMORY ) );
  64. //
  65. // add scopes to hash table
  66. //
  67. if ( RTScope == _pScope->Type() )
  68. {
  69. const CScopeRestriction & scp = * (CScopeRestriction *) _pScope;
  70. Win4Assert( scp.IsValid() );
  71. if (scp.IsVirtual())
  72. AddVirtualScopeRestriction(scp);
  73. else
  74. AddScopeRestriction(scp.GetFunnyPath(), scp.IsDeep() );
  75. }
  76. else if ( RTOr == _pScope->Type() )
  77. {
  78. CNodeRestriction const & node = * _pScope->CastToNode();
  79. for ( ULONG x = 0; x < node.Count() && !_fAllInScope; x++ )
  80. {
  81. Win4Assert( RTScope == node.GetChild( x )->Type() );
  82. const CScopeRestriction & scp = * (CScopeRestriction *)
  83. node.GetChild( x );
  84. Win4Assert( scp.IsValid() );
  85. if (scp.IsVirtual())
  86. AddVirtualScopeRestriction(scp);
  87. else
  88. AddScopeRestriction(scp.GetFunnyPath(), scp.IsDeep() );
  89. }
  90. }
  91. if (!_fAllInScope && 0 == _hTable.Count())
  92. _fNoneInScope = TRUE;
  93. SET_UNICODE_STR( _Path, _xwcPath.Get(), flagNoValueYet, _xwcPath.SizeOf() );
  94. SET_UNICODE_STR( _VPath, _xwcVPath.Get(), flagNoValueYet, _xwcVPath.SizeOf() );
  95. _Name.Length = flagNoValueYet;
  96. } //CCiPropRetriever
  97. //+-------------------------------------------------------------------------
  98. //
  99. // Member: CCiPropRetriever::AddVirtualScopeRestriction, public
  100. //
  101. // Synopsis: Adds info to hashtable for all virtual directories which fall
  102. // within the virtual scope specified. Hashtable entries for
  103. // exclude directories have fInScope = FALSE.
  104. //
  105. // Requires: All directories in a catalog must have a wid.
  106. // Hashtable must be allowed to grow to hold all specified scopes.
  107. //
  108. // Arguments: [scp] - specified scope
  109. //
  110. // History: 25-Aug-97 EmilyB Created
  111. //
  112. //--------------------------------------------------------------------------
  113. void CCiPropRetriever::AddVirtualScopeRestriction(
  114. CScopeRestriction const & scp)
  115. {
  116. unsigned iBmk = 0;
  117. ULONG ulType = 0;
  118. XGrowable<WCHAR> xwcVPath;
  119. CLowerFunnyPath lcaseFunnyPPath;
  120. unsigned ccVPath = 0;
  121. unsigned ccPPath = 0;
  122. //
  123. // enumerate through all virtual roots (both include and exclude) falling
  124. // under specified virtual scope
  125. //
  126. while ( _cat.VirtualToAllPhysicalRoots( scp.GetPath(), // Virtual scope (prefix)
  127. scp.PathLength(), // + length
  128. xwcVPath, // Full virtual root
  129. ccVPath, // + return length
  130. lcaseFunnyPPath, // Full physical root
  131. ccPPath, // + return length
  132. ulType, // root type
  133. iBmk ) ) // Bookmark
  134. {
  135. //
  136. // Special-case shallow queries at '/', so we don't end up with hits
  137. // in the roots of all virtual roots
  138. //
  139. if ( ( 0 != (lcaseFunnyPPath.GetActualPath())[0] ) &&
  140. ( ( scp.IsDeep() ) ||
  141. ( 0 != scp.PathLength() ) ||
  142. ( 1 == ccVPath ) ) )
  143. {
  144. // if virtual scope was invalid, VirtualToPhysicalRoot will return
  145. // path to general root + \invalid scope name, which will not have
  146. // a wid. So this is where we catch invalid virtual scopes.
  147. WORKID wid = _cat.PathToWorkId( lcaseFunnyPPath, FALSE );
  148. if (widInvalid != wid )
  149. {
  150. //
  151. // add info for vroot to hashtable
  152. //
  153. CDirWidHashEntry DirInfo(wid,
  154. scp.IsDeep(),
  155. (ulType & PCatalog::UsedRoot) ? TRUE : FALSE ); // include or exclude scope?
  156. _hTable.AddEntry(DirInfo);
  157. }
  158. else
  159. {
  160. //
  161. // This can happen. We may have hit an exclude scope that
  162. // is not below an include scope.
  163. //
  164. continue;
  165. }
  166. }
  167. ccVPath = ccPPath = 0;
  168. }
  169. if ( scp.IsDeep() )
  170. _fAllScopesShallow = FALSE;
  171. } //AddVirtualScopeRestriction
  172. //+-------------------------------------------------------------------------
  173. //
  174. // Member: CCiPropRetriever::AddScopeRestriction, public
  175. //
  176. // Synopsis: Adds info to hashtable for all physical scope specified.
  177. // Exclude physical scopes are not indexed, so no need to
  178. // check for exclude scopes. If physical scope is
  179. // above all physical roots, then adds those roots which fall
  180. // under scope to the hashtable.
  181. // Sets _fAllInScope to TRUE if physical scope was '\' or
  182. // if it was a directory above all physical roots. There is no
  183. // other way _fAllInScope can be TRUE.
  184. //
  185. // Requires: All directories in a catalog must have a wid.
  186. // Hashtable must be allowed to grow to hold all specified scopes.
  187. //
  188. // Arguments: [lcaseFunnyPhysPath] - specified physical scope
  189. // [fIsDeep] - is scope deep?
  190. //
  191. // History: 25-Aug-97 EmilyB Created
  192. //
  193. //--------------------------------------------------------------------------
  194. void CCiPropRetriever::AddScopeRestriction(
  195. const CLowerFunnyPath & lcaseFunnyPhysPath,
  196. BOOL fIsDeep )
  197. {
  198. WORKID wid;
  199. if (fIsDeep)
  200. _fAllScopesShallow = FALSE;
  201. if ( 0 == lcaseFunnyPhysPath.GetActualLength() )
  202. {
  203. //
  204. // A physical scope of '\' that is shallow makes no sense.
  205. //
  206. if ( fIsDeep )
  207. _fAllInScope = TRUE;
  208. return;
  209. }
  210. CLowerFunnyPath lcaseFunnyFixedPath = lcaseFunnyPhysPath;
  211. BOOL fImpersonated = FALSE;
  212. //
  213. // if scope is unc, use fixed up version
  214. //
  215. if ( lcaseFunnyFixedPath.IsRemote() )
  216. {
  217. // unc -- try to unfixup the scope. if there is no unfixup,
  218. // it'll just use the original path.
  219. _cat.InverseFixupPath( lcaseFunnyFixedPath );
  220. // need to impersonate for remote access here?
  221. if ( lcaseFunnyFixedPath.IsRemote() &&
  222. ! _remoteAccess.IsImpersonated() )
  223. {
  224. // ignore any error return
  225. if ( _remoteAccess.ImpersonateIfNoThrow(
  226. lcaseFunnyFixedPath.GetActualPath(),
  227. 0 ) )
  228. fImpersonated = TRUE;
  229. }
  230. }
  231. //
  232. // Check to see if the input path name contains an 8.3 short name
  233. //
  234. if ( lcaseFunnyFixedPath.IsShortPath() )
  235. {
  236. vqDebugOut(( DEB_WARN,
  237. "CCiPropRetriever::AddScopeRestriction: possible shortname path\n\t%ws ==>\n",
  238. lcaseFunnyFixedPath.GetActualPath() ));
  239. if ( lcaseFunnyFixedPath.ConvertToLongName() )
  240. {
  241. vqDebugOut(( DEB_WARN|DEB_NOCOMPNAME,
  242. "\t%ws\n",
  243. lcaseFunnyFixedPath.GetActualPath() ));
  244. }
  245. else
  246. {
  247. vqDebugOut(( DEB_ERROR, "longname path conversion failed!\n" ));
  248. }
  249. }
  250. if ( fImpersonated )
  251. {
  252. _remoteAccess.Release();
  253. }
  254. wid = _cat.PathToWorkId( lcaseFunnyFixedPath, FALSE );
  255. if (widInvalid != wid )
  256. {
  257. // straightforward case - scope has a wid - which we add to _hTable
  258. CDirWidHashEntry DirInfo(wid, fIsDeep, TRUE);
  259. _hTable.AddEntry(DirInfo);
  260. return;
  261. }
  262. // got here because scope was not global and it didn't have a wid.
  263. // Might be physical directory (not cataloged) above one that is
  264. // in catalog. If scope is shallow, then nothing is in it.
  265. // If scope is deep, enumerate through scopes and see if any
  266. // are subdirectories of scope specified
  267. if (fIsDeep)
  268. {
  269. CScopeMatch Match( lcaseFunnyFixedPath.GetActualPath(),
  270. lcaseFunnyFixedPath.GetActualLength() );
  271. _fAllInScope = TRUE;
  272. CCiScopeTable *pScopes = _cat.GetScopeTable();
  273. if ( 0 != pScopes )
  274. {
  275. unsigned iBmk = 0;
  276. WCHAR awc[MAX_PATH];
  277. while ( pScopes->Enumerate( awc,
  278. (sizeof awc / sizeof WCHAR),
  279. iBmk ) )
  280. {
  281. unsigned ccawc = wcslen(awc);
  282. if ( Match.IsInScope( awc, ccawc ) )
  283. {
  284. CLowerFunnyPath lcaseFunnyAwc( awc, ccawc );
  285. wid = _cat.PathToWorkId( lcaseFunnyAwc, FALSE );
  286. // wid may be widInvalid if it's a scope that hasn't been
  287. // scanned yet.
  288. if (widInvalid != wid )
  289. {
  290. CDirWidHashEntry DirInfo( wid,
  291. fIsDeep,
  292. TRUE );
  293. _hTable.AddEntry(DirInfo);
  294. }
  295. }
  296. else // found a root not included in scope
  297. _fAllInScope = FALSE;
  298. }
  299. }
  300. }
  301. } //AddScopeRestriction
  302. //+---------------------------------------------------------------------------
  303. //
  304. // Member: CCiPropRetriever::GetPath, public
  305. //
  306. // Synopsis: Returns the path for the file
  307. //
  308. // Returns: A path to file
  309. //
  310. // History: 07-Feb-96 KyleP Added header
  311. //
  312. //----------------------------------------------------------------------------
  313. UNICODE_STRING const * CCiPropRetriever::GetPath()
  314. {
  315. if ( _Path.Length == flagNoValueYet )
  316. {
  317. unsigned cwc = _xwcPath.Count();
  318. FetchPath( _Path.Buffer, cwc );
  319. if ( cwc > _xwcPath.Count() )
  320. {
  321. // Need more space
  322. _xwcPath.SetSize( cwc );
  323. SET_UNICODE_STR( _Path, _xwcPath.Get(), _Path.Length, _xwcPath.SizeOf() );
  324. FetchPath( _Path.Buffer, cwc );
  325. // Can't go on asking for more space forever !
  326. Win4Assert( cwc <= _xwcPath.Count() );
  327. }
  328. if ( 0 == cwc )
  329. _Path.Length = 0;
  330. _Name.Length = 0;
  331. if ( _Path.Length == 0 )
  332. return 0;
  333. else
  334. {
  335. _Path.Length = (USHORT)(cwc * sizeof( WCHAR ));
  336. _Name.Buffer = _Path.Buffer + _Path.Length/(sizeof WCHAR) - 1;
  337. // _Path can be path of root (e.g. c:) if indexing directories and
  338. // root is a match. Watch that we don't walk off end.
  339. while ( *_Name.Buffer != L'\\' && _Name.Buffer != _Path.Buffer)
  340. {
  341. Win4Assert( _Name.Length < _Path.Length );
  342. _Name.Length += sizeof(WCHAR);
  343. _Name.Buffer--;
  344. }
  345. if (_Name.Buffer == _Path.Buffer)
  346. {
  347. _Name.Buffer = _Path.Buffer + _Path.Length/(sizeof WCHAR); // point it to /0
  348. _Name.Length=0;
  349. }
  350. else
  351. {
  352. _Name.Buffer++;
  353. _Path.Length -= _Name.Length + sizeof WCHAR;
  354. }
  355. }
  356. }
  357. return &_Path;
  358. } //GetPath
  359. //+---------------------------------------------------------------------------
  360. //
  361. // Member: CCiPropRetriever::FetchVPathInVScope, private
  362. //
  363. // Synopsis: Returns a virtual path for the file that is in the given
  364. // virtual scope
  365. //
  366. // Arguments: [xwcVPath] -- The resulting virtual path
  367. // [pwcVScope] -- The virtual scope
  368. // [cwcVScope] -- # of characters in pwcVScope
  369. // [fVScopeDeep] -- TRUE if the scope is deep
  370. //
  371. // Returns: Length of vpath, if a vpath was found and the vpath is in the vscope
  372. // 0 if no vpath exists in the vscope
  373. //
  374. // History: 02-Feb-98 dlee Created
  375. //
  376. //----------------------------------------------------------------------------
  377. unsigned CCiPropRetriever::FetchVPathInVScope( XGrowable<WCHAR> & xwcVPath,
  378. WCHAR const * pwcVScope,
  379. const unsigned cwcVScope,
  380. const BOOL fVScopeDeep )
  381. {
  382. vqDebugOut(( DEB_ITRACE, "FetchVPathInVScope, vscope '%ws', cwc %d\n",
  383. pwcVScope, cwcVScope ));
  384. CScopeMatch Match( pwcVScope, cwcVScope );
  385. unsigned cSkip = 0;
  386. unsigned cwcVPath = 0;
  387. while ( TRUE )
  388. {
  389. cwcVPath = _cat.WorkIdToVirtualPath( GetPropertyRecord(),
  390. cSkip,
  391. xwcVPath );
  392. if ( 0 == cwcVPath )
  393. return 0;
  394. //
  395. // In scope?
  396. //
  397. vqDebugOut(( DEB_ITRACE, " comparing to cwc %d, '%ws'\n",
  398. cwcVPath, xwcVPath.Get() ));
  399. if ( !Match.IsInScope( xwcVPath.Get(), cwcVPath ) )
  400. {
  401. cSkip++;
  402. continue;
  403. }
  404. Win4Assert( 0 == xwcVPath[cwcVPath] );
  405. //
  406. // If the scope is shallow, check that it's still in scope
  407. //
  408. if ( !fVScopeDeep )
  409. {
  410. unsigned cwcName = 0;
  411. WCHAR * pwcName = xwcVPath.Get() + cwcVPath - 1;
  412. while ( L'\\' != *pwcName )
  413. {
  414. Win4Assert( cwcName < cwcVPath );
  415. cwcName++;
  416. pwcName--;
  417. }
  418. unsigned cwcJustPath = cwcVPath - cwcName;
  419. vqDebugOut(( DEB_ITRACE, "cwcJustPath: %d\n", cwcJustPath ));
  420. BOOL fTooDeep = cwcJustPath > ( cwcVScope + 1 );
  421. if ( fTooDeep )
  422. {
  423. cSkip++;
  424. continue;
  425. }
  426. else
  427. break;
  428. }
  429. else
  430. break;
  431. }
  432. vqDebugOut(( DEB_ITRACE," InVScope: match!\n" ));
  433. return cwcVPath;
  434. } //FetchVPathInVScope
  435. //+---------------------------------------------------------------------------
  436. //
  437. // Member: CCiPropRetriever::FetchVirtualPath, private
  438. //
  439. // Synopsis: Returns the virtual path for the file
  440. //
  441. // Arguments: [xwcVPath] -- The resulting virtual path
  442. //
  443. // Returns: If found, length of vpath ELSE 0
  444. //
  445. // History: 02-Feb-98 dlee Created
  446. //
  447. //----------------------------------------------------------------------------
  448. unsigned CCiPropRetriever::FetchVirtualPath( XGrowable<WCHAR> & xwcVPath )
  449. {
  450. BOOL fUseAnyVPath = FALSE;
  451. unsigned cwc = 0;
  452. if ( RTScope == _pScope->Type() )
  453. {
  454. CScopeRestriction const & scp = * (CScopeRestriction *) _pScope;
  455. if ( scp.IsVirtual() )
  456. {
  457. cwc = FetchVPathInVScope( xwcVPath,
  458. scp.GetPath(),
  459. scp.PathLength(),
  460. scp.IsDeep() );
  461. }
  462. else
  463. fUseAnyVPath = TRUE;
  464. }
  465. else if ( RTOr == _pScope->Type() )
  466. {
  467. CNodeRestriction const & node = * _pScope->CastToNode();
  468. fUseAnyVPath = TRUE;
  469. for ( ULONG x = 0; x < node.Count(); x++ )
  470. {
  471. Win4Assert( RTScope == node.GetChild( x )->Type() );
  472. CScopeRestriction const & scp = * (CScopeRestriction *)
  473. node.GetChild( x );
  474. if ( scp.IsVirtual() )
  475. {
  476. cwc = FetchVPathInVScope( xwcVPath,
  477. scp.GetPath(),
  478. scp.PathLength(),
  479. scp.IsDeep() );
  480. if ( cwc > 0 )
  481. {
  482. fUseAnyVPath = FALSE;
  483. break;
  484. }
  485. }
  486. }
  487. }
  488. //
  489. // If no virtual scope works for the file, grab any virtual path
  490. //
  491. if ( fUseAnyVPath )
  492. cwc = _cat.WorkIdToVirtualPath( GetPropertyRecord(),
  493. 0,
  494. xwcVPath );
  495. return cwc;
  496. } //FetchVirtualPath
  497. //+---------------------------------------------------------------------------
  498. //
  499. // Member: CCiPropRetriever::GetVirtualPath, public
  500. //
  501. // Synopsis: Returns the virtual path for the file
  502. //
  503. // Returns: A virtual path to file, or 0 if none exists.
  504. //
  505. // History: 07-Feb-96 KyleP Added header
  506. //
  507. //----------------------------------------------------------------------------
  508. UNICODE_STRING const * CCiPropRetriever::GetVirtualPath()
  509. {
  510. if ( flagNoValueYet == _VPath.Length )
  511. {
  512. unsigned cwc = FetchVirtualPath( _xwcVPath );
  513. if ( 0 == cwc )
  514. {
  515. SET_UNICODE_STR( _VPath, _xwcVPath.Get(), flagNoValue, _xwcVPath.SizeOf() );
  516. }
  517. else
  518. {
  519. Win4Assert( 0 == _xwcVPath[cwc] );
  520. SET_UNICODE_STR( _VPath, _xwcVPath.Get(), cwc * sizeof WCHAR, _xwcVPath.SizeOf() );
  521. _Name.Length = 0;
  522. _Name.Buffer = _VPath.Buffer + cwc - 1;
  523. while ( L'\\' != *_Name.Buffer )
  524. {
  525. Win4Assert( _Name.Length < _VPath.Length );
  526. _Name.Length += sizeof WCHAR;
  527. _Name.Buffer--;
  528. }
  529. Win4Assert ( L'\\' == *_Name.Buffer );
  530. _Name.Buffer++;
  531. _VPath.Length -= _Name.Length + sizeof WCHAR;
  532. }
  533. }
  534. if ( flagNoValue == _VPath.Length )
  535. return 0;
  536. else
  537. return &_VPath;
  538. } //GetVirtualPath
  539. //+---------------------------------------------------------------------------
  540. //
  541. // Member: CCiPropRetriever::GetShortName, public
  542. //
  543. // Returns: A short name to file
  544. //
  545. // History: 17-Apr-96 KyleP Added header
  546. //
  547. //----------------------------------------------------------------------------
  548. UNICODE_STRING const * CCiPropRetriever::GetShortName()
  549. {
  550. if ( !_fFindLoaded )
  551. Refresh( FALSE );
  552. _ShortName.Length = wcslen( _finddata.cAlternateFileName ) * sizeof(WCHAR);
  553. //
  554. // If we don'th have a short name and it's not just because we were unable
  555. // to load it, return the real file name.
  556. //
  557. if ( ( 0 == _ShortName.Length ) && ( 0xffffffff != _finddata.dwReserved0 ) )
  558. return &_Name;
  559. _ShortName.MaximumLength = _ShortName.Length;
  560. _ShortName.Buffer = &_finddata.cAlternateFileName[0];
  561. return &_ShortName;
  562. } //GetShortName
  563. //+---------------------------------------------------------------------------
  564. //
  565. // Member: CCiPropRetriever::CreateTime, public
  566. //
  567. // Returns: Create time for file, or 0xFFFFFFFFFFFFFFFF if unknown
  568. //
  569. // History: 17-Apr-96 KyleP Added header
  570. //
  571. //----------------------------------------------------------------------------
  572. LONGLONG CCiPropRetriever::CreateTime()
  573. {
  574. //
  575. // First, should we try a fast path?
  576. //
  577. if ( 0 == (_fFastStatLoaded & fsCreate) )
  578. FetchI8StatProp( fsCreate, pidCreateTime, (LONGLONG *)&_finddata.ftCreationTime );
  579. LARGE_INTEGER li;
  580. li.LowPart = _finddata.ftCreationTime.dwLowDateTime;
  581. li.HighPart = _finddata.ftCreationTime.dwHighDateTime;
  582. return li.QuadPart;
  583. } //CreateTime
  584. //+---------------------------------------------------------------------------
  585. //
  586. // Member: CCiPropRetriever::ModifyTime, public
  587. //
  588. // Returns: Last write time for file, or 0xFFFFFFFFFFFFFFFF if unknown
  589. //
  590. // History: 17-Apr-96 KyleP Added header
  591. //
  592. //----------------------------------------------------------------------------
  593. LONGLONG CCiPropRetriever::ModifyTime()
  594. {
  595. //
  596. // First, should we try a fast path?
  597. //
  598. if ( 0 == (_fFastStatLoaded & fsModify) )
  599. FetchI8StatProp( fsModify, pidWriteTime, (LONGLONG *)&_finddata.ftLastWriteTime );
  600. LARGE_INTEGER li;
  601. li.LowPart = _finddata.ftLastWriteTime.dwLowDateTime;
  602. li.HighPart = _finddata.ftLastWriteTime.dwHighDateTime;
  603. return li.QuadPart;
  604. } //ModifyTime
  605. //+---------------------------------------------------------------------------
  606. //
  607. // Member: CCiPropRetriever::AccessTime, public
  608. //
  609. // Returns: Last access time for file, or 0xFFFFFFFFFFFFFFFF if unknown
  610. //
  611. // History: 17-Apr-96 KyleP Added header
  612. //
  613. //----------------------------------------------------------------------------
  614. LONGLONG CCiPropRetriever::AccessTime()
  615. {
  616. //
  617. // First, should we try a fast path?
  618. //
  619. if ( 0 == (_fFastStatLoaded & fsAccess) )
  620. FetchI8StatProp( fsAccess, pidAccessTime, (LONGLONG *)&_finddata.ftLastAccessTime );
  621. LARGE_INTEGER li;
  622. li.LowPart = _finddata.ftLastAccessTime.dwLowDateTime;
  623. li.HighPart = _finddata.ftLastAccessTime.dwHighDateTime;
  624. return li.QuadPart;
  625. } //AccessTime
  626. //+---------------------------------------------------------------------------
  627. //
  628. // Member: CCiPropRetriever::ObjectSize public
  629. //
  630. // Returns: Size of file, or 0xFFFFFFFFFFFFFFFF if unknown
  631. //
  632. // History: 17-Apr-96 KyleP Added header
  633. //
  634. //----------------------------------------------------------------------------
  635. LONGLONG CCiPropRetriever::ObjectSize()
  636. {
  637. //
  638. // First, should we try a fast path?
  639. //
  640. LARGE_INTEGER li;
  641. if ( 0 == (_fFastStatLoaded & fsSize) )
  642. {
  643. //
  644. // If this fails, the FindData will have been initialized.
  645. //
  646. if ( FetchI8StatProp( fsSize, pidSize, (LONGLONG *)&li ) )
  647. {
  648. _finddata.nFileSizeLow = li.LowPart;
  649. _finddata.nFileSizeHigh = li.HighPart;
  650. }
  651. }
  652. li.LowPart = _finddata.nFileSizeLow;
  653. li.HighPart = _finddata.nFileSizeHigh;
  654. return li.QuadPart;
  655. } //ObjectSize
  656. //+---------------------------------------------------------------------------
  657. //
  658. // Member: CCiPropRetriever::Attributes, public
  659. //
  660. // Returns: Attributes for file, or 0xFFFFFFFF if unknown
  661. //
  662. // History: 17-Apr-96 KyleP Added header
  663. //
  664. //----------------------------------------------------------------------------
  665. ULONG CCiPropRetriever::Attributes()
  666. {
  667. //
  668. // First, should we try a fast path?
  669. //
  670. if ( 0 == (_fFastStatLoaded & fsAttrib) )
  671. {
  672. //
  673. // Try property store?
  674. //
  675. if ( 0 == (_fFastStatNeverLoad & fsAttrib) )
  676. {
  677. PROPVARIANT var;
  678. unsigned cb = sizeof(var);
  679. if ( FetchValue( pidAttrib, &var, &cb ) )
  680. {
  681. if ( var.vt == VT_EMPTY )
  682. Refresh( TRUE );
  683. else
  684. {
  685. Win4Assert( var.vt == VT_UI4 );
  686. _finddata.dwFileAttributes = var.ulVal;
  687. _fFastStatLoaded |= fsAttrib;
  688. }
  689. }
  690. else
  691. {
  692. _fFastStatNeverLoad |= fsAttrib;
  693. Refresh( TRUE );
  694. }
  695. }
  696. else
  697. {
  698. Win4Assert( !_fFastFindLoaded );
  699. Refresh( TRUE );
  700. }
  701. }
  702. return _finddata.dwFileAttributes;
  703. } //Attributes
  704. //+-------------------------------------------------------------------------
  705. //
  706. // Member: CCiPropRetriever::IsInScope
  707. //
  708. // Synopsis: Test if workid in scope.
  709. //
  710. // History: 19-Aug-93 KyleP Created
  711. // 30-Oct-96 dlee Added loop, moved guts to isInScope
  712. // 26-Jun-96 emilyb optimized scope checking. No longer
  713. // loads stat properties.
  714. //
  715. //--------------------------------------------------------------------------
  716. SCODE STDMETHODCALLTYPE CCiPropRetriever::IsInScope( BOOL *pfInScope )
  717. {
  718. if ( widInvalid == _widPrimedForPropRetrieval )
  719. return CI_E_WORKID_NOTVALID;
  720. SCODE sc = S_OK;
  721. CTranslateSystemExceptions translate;
  722. TRY
  723. {
  724. *pfInScope = IsInScope( _widPrimedForPropRetrieval );
  725. }
  726. CATCH( CException, e )
  727. {
  728. sc = e.GetErrorCode();
  729. vqDebugOut(( DEB_ERROR,
  730. "CCiPropRetriever::IsInScope - Exception caught 0x%x\n",
  731. sc ));
  732. }
  733. END_CATCH;
  734. return sc;
  735. } //IsInScope
  736. //+-------------------------------------------------------------------------
  737. //
  738. // Member: CCiPropRetriever::IsInScope, private
  739. //
  740. // Synopsis: Test if workid is in scope.
  741. //
  742. // Algorithm: looks for an ancestor of the current file (wid parameter) in
  743. // the hashtable. If it finds one, it uses it to determine if
  744. // current file is in scope. If it doesn't, the current file\
  745. // is not in scope. It also adds an
  746. // entry for the topmost unmatched ancestor to the hashtable.
  747. //
  748. // Requires: All scopes must be in hashtable. For virtual scopes, this
  749. // requirement includes both exclude and include roots
  750. // within the scope.
  751. //
  752. // Returns: TRUE if object is in scope.
  753. //
  754. // History: 27-Jun-97 emilyb created
  755. //
  756. // Notes: The only time widInvalid is valid as a parent is if the
  757. // parent is the root of a drive.
  758. //
  759. //
  760. //--------------------------------------------------------------------------
  761. BOOL CCiPropRetriever::IsInScope( WORKID wid )
  762. {
  763. Win4Assert( wid == _widPrimedForPropRetrieval );
  764. if (_fAllInScope)
  765. {
  766. //
  767. // Still need to check matching attributes.
  768. //
  769. return ( 0 == _ulAttribFilter ) ||
  770. ( (Attributes() & _ulAttribFilter) == 0 );
  771. }
  772. if (_fNoneInScope)
  773. return FALSE;
  774. //
  775. // is wid an inscope directory?
  776. //
  777. //
  778. CDirWidHashEntry DirInfo(wid, 0); // entry to find in hash table
  779. if (_hTable.LookUpWorkId (DirInfo) )
  780. {
  781. if (DirInfo.fInScope())
  782. {
  783. return ( 0 == _ulAttribFilter ) ||
  784. ( (Attributes() & _ulAttribFilter) == 0 );
  785. }
  786. else
  787. return FALSE;
  788. }
  789. //
  790. // find wid of parent
  791. //
  792. WORKID widParent = widInvalid; // parent of wid
  793. WORKID widAncestor = widInvalid; // used to walk up ancestor chain
  794. PROPVARIANT var;
  795. BOOL fFound;
  796. unsigned cb = sizeof(var);
  797. fFound = FetchValue(pidParentWorkId, &var, &cb);
  798. Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
  799. if ( !fFound || VT_EMPTY == var.vt )
  800. {
  801. // file could have been deleted - not in scope
  802. return FALSE;
  803. }
  804. widParent = var.ulVal;
  805. if (widParent == widInvalid)
  806. return FALSE;
  807. //
  808. // look for parent in hash table
  809. //
  810. DirInfo.SetWorkId(widParent); // entry to find in hash table
  811. if (_hTable.LookUpWorkId (DirInfo) )
  812. {
  813. if (DirInfo.fInScope())
  814. {
  815. return ( 0 == _ulAttribFilter ) ||
  816. ( (Attributes() & _ulAttribFilter) == 0 );
  817. }
  818. else
  819. return FALSE;
  820. }
  821. if (_fAllScopesShallow) // should have found it above if it was in scope
  822. {
  823. return FALSE;
  824. }
  825. //
  826. // we've looked for parent without success -- now look for ancestors
  827. //
  828. cb = sizeof(var);
  829. Quiesce(); // Can only read 1 property record at a time.
  830. fFound = _cat.FetchValue(widParent, pidParentWorkId, &var, &cb);
  831. Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
  832. widAncestor = var.ulVal;
  833. DirInfo.SetWorkId(widAncestor);
  834. while ( fFound && VT_UI4 == var.vt &&
  835. widAncestor != widInvalid && // not root
  836. ( !_hTable.LookUpWorkId ( DirInfo) || // not in table already
  837. !DirInfo.fDeep() ) ) // shallow - so it doesn't apply to grandchild
  838. {
  839. // save topmost valid ancestor
  840. widParent = widAncestor;
  841. // get the previous ancestor
  842. Quiesce(); // Can only read 1 property record at a time.
  843. cb = sizeof(var);
  844. fFound = _cat.FetchValue(widAncestor, pidParentWorkId, &var, &cb);
  845. Win4Assert( !fFound || VT_UI4 == var.vt || VT_EMPTY == var.vt );
  846. widAncestor = var.ulVal;
  847. DirInfo.SetWorkId(widAncestor);
  848. }
  849. if ( !fFound || VT_UI4 != var.vt )
  850. {
  851. // file could have been deleted -- not in scope
  852. return FALSE;
  853. }
  854. BOOL fInScope = FALSE; // not in scope unless match found
  855. BOOL fDeep = TRUE; // must be deep, or else wouldn't apply to grandchild
  856. if (widInvalid != widAncestor) // found match
  857. {
  858. Win4Assert( DirInfo.fDeep() );
  859. fInScope = DirInfo.fInScope();
  860. }
  861. Win4Assert( widInvalid != widParent );
  862. // add top ancestor to hashtable
  863. //
  864. // Once hash table reaches max size, stop adding entries to it.
  865. // Because it was seeded with scopes, the data is there to answer
  866. // if something is in scope.
  867. if(_hTable.Count() < MAX_HASHED_DIRECTORIES)
  868. {
  869. CDirWidHashEntry DirAnc( widParent, fDeep, fInScope );
  870. if (!_hTable.LookUpWorkId (DirAnc) ) // be careful not to replace ancestral shallow scopes
  871. {
  872. _hTable.AddEntry(DirAnc);
  873. #if CIDBG == 1
  874. // how often do we max out the hash table
  875. if(_hTable.Count() == MAX_HASHED_DIRECTORIES)
  876. vqDebugOut(( DEB_WARN,
  877. "IsInScope maxed out wid hash table with %d entries\n",
  878. _hTable.Count()) );
  879. #endif
  880. }
  881. }
  882. //
  883. // Still need to check matching attributes.
  884. //
  885. return fInScope && (( 0 == _ulAttribFilter ) ||
  886. ( (Attributes() & _ulAttribFilter) == 0 ));
  887. } //IsInScope
  888. //+-------------------------------------------------------------------------
  889. //
  890. // Member: CCiPropRetriever::Refresh, private
  891. //
  892. // Synopsis: Load stat properties for current object
  893. //
  894. // Arguments: [fFast] -- If TRUE, make fast call and don't load alternate
  895. // file name.
  896. //
  897. // Returns: TRUE if load successful
  898. //
  899. // History: 19-Aug-93 KyleP Created
  900. // 29-Feb-96 KyleP Added GetFileAttributesEx support
  901. //
  902. //--------------------------------------------------------------------------
  903. BOOL CCiPropRetriever::Refresh( BOOL fFast )
  904. {
  905. //
  906. // Physical path may not be loaded.
  907. //
  908. if ( _Path.Length == flagNoValueYet )
  909. {
  910. if ( 0 == GetPath() )
  911. {
  912. RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
  913. _finddata.cAlternateFileName[0] = 0;
  914. return FALSE;
  915. }
  916. }
  917. if ( _Path.Length == 0 )
  918. {
  919. //
  920. // Previously failed to load path, so no way to get attributes
  921. //
  922. RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
  923. _finddata.cAlternateFileName[0] = 0;
  924. return FALSE;
  925. }
  926. if ( CImpersonateRemoteAccess::IsNetPath(_Path.Buffer) )
  927. {
  928. WCHAR const * pwszVPath = (_VPath.Length == flagNoValueYet) ? 0 : _VPath.Buffer;
  929. //
  930. // Just blow off the file if this fails.
  931. //
  932. if ( !_remoteAccess.ImpersonateIfNoThrow( _Path.Buffer,
  933. pwszVPath ) )
  934. {
  935. RtlFillMemory( &_finddata, sizeof WIN32_FILE_ATTRIBUTE_DATA, 0xFF );
  936. _finddata.cAlternateFileName[0] = 0;
  937. _Path.Length = 0;
  938. return FALSE;
  939. }
  940. }
  941. else if ( _remoteAccess.IsImpersonated() )
  942. {
  943. _remoteAccess.Release();
  944. }
  945. if ( fFast )
  946. {
  947. BOOL fResult;
  948. unsigned ccPath = (_Path.Length + _Name.Length) / sizeof(WCHAR);
  949. // handle long paths here
  950. // we do this here instead of keeping a funnypath object all thru,
  951. // because we get the path from the property store(in GetPath), which
  952. // does not recognize funny paths, so we would have to do an extra
  953. // copy operation. This we do here, but only for paths > MAX_PATH
  954. if ( ccPath >= MAX_PATH )
  955. {
  956. CFunnyPath funnyPath( _Path.Buffer, ccPath );
  957. fResult = GetFileAttributesEx( funnyPath.GetPath(), GetFileExInfoStandard, &_finddata );
  958. }
  959. else
  960. {
  961. fResult = GetFileAttributesEx( _Path.Buffer, GetFileExInfoStandard, &_finddata );
  962. }
  963. if ( !fResult )
  964. {
  965. vqDebugOut(( DEB_ERROR, "Can't retrieve fast findfirst data for %ws. Error = %d\n",
  966. _Path.Buffer, GetLastError() ));
  967. RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
  968. _finddata.cAlternateFileName[0] = 0;
  969. return FALSE;
  970. }
  971. _fFastFindLoaded = TRUE;
  972. _fFastStatLoaded = fsCreate | fsModify | fsAccess | fsSize | fsAttrib;
  973. }
  974. else
  975. {
  976. unsigned ccPath = (_Path.Length + _Name.Length) / sizeof(WCHAR);
  977. HANDLE h;
  978. //
  979. // handle long paths here
  980. // we do this here instead of keeping a funnypath object all thru,
  981. // because we get the path from the property store(in GetPath), which
  982. // does not recognize funny paths, so we would have to do an extra
  983. // copy operation. This we do here, but only for paths > MAX_PATH
  984. //
  985. if ( ccPath >= MAX_PATH )
  986. {
  987. CFunnyPath funnyPath( _Path.Buffer, ccPath );
  988. h = FindFirstFile( funnyPath.GetPath(), &_finddata );
  989. }
  990. else
  991. {
  992. h = FindFirstFile( _Path.Buffer, &_finddata );
  993. }
  994. if ( INVALID_HANDLE_VALUE == h )
  995. {
  996. vqDebugOut(( DEB_ERROR, "Can't retrieve findfirst data for %ws\n",
  997. _Path.Buffer ));
  998. RtlFillMemory( &_finddata, sizeof(WIN32_FILE_ATTRIBUTE_DATA), 0xFF );
  999. _finddata.cAlternateFileName[0] = 0;
  1000. return FALSE;
  1001. }
  1002. else
  1003. {
  1004. FindClose( h );
  1005. _fFindLoaded = TRUE;
  1006. _fFastFindLoaded = TRUE;
  1007. _fFastStatLoaded = fsCreate | fsModify | fsAccess | fsSize | fsAttrib;
  1008. }
  1009. }
  1010. return TRUE;
  1011. } //Refresh
  1012. //+-------------------------------------------------------------------------
  1013. //
  1014. // Member: CCiPropRetriever::FetchI8StatProp, private
  1015. //
  1016. // Synopsis: Load stat property. Try property store before hitting file.
  1017. //
  1018. // Arguments: [fsProp] -- Fast stat bit to check.
  1019. // [pid] -- Pid of property
  1020. // [pDestination] -- resulting LONGLONG stored here.
  1021. //
  1022. // Returns: TRUE if property fetch successful *and* value in
  1023. // pDestination is valid.
  1024. //
  1025. // History: 17-Apr-96 KyleP Created
  1026. //
  1027. //--------------------------------------------------------------------------
  1028. BOOL CCiPropRetriever::FetchI8StatProp( CCiPropRetriever::FastStat fsProp,
  1029. PROPID pid,
  1030. LONGLONG * pDestination )
  1031. {
  1032. Win4Assert( 0 == (_fFastStatLoaded & fsProp) );
  1033. //
  1034. // Try property store?
  1035. //
  1036. if ( 0 == (_fFastStatNeverLoad & fsProp) )
  1037. {
  1038. PROPVARIANT var;
  1039. unsigned cb = sizeof(var);
  1040. if ( FetchValue( pid, &var, &cb ) )
  1041. {
  1042. if ( var.vt == VT_EMPTY )
  1043. Refresh( TRUE );
  1044. else
  1045. {
  1046. Win4Assert( var.vt == VT_I8 || var.vt == VT_UI8 || var.vt == VT_FILETIME );
  1047. *(UNALIGNED LONGLONG *)pDestination = var.hVal.QuadPart;
  1048. return TRUE;
  1049. }
  1050. }
  1051. else
  1052. {
  1053. _fFastStatNeverLoad |= fsProp;
  1054. Refresh( TRUE );
  1055. }
  1056. }
  1057. else
  1058. {
  1059. Win4Assert( !_fFastFindLoaded );
  1060. Refresh( TRUE );
  1061. }
  1062. return FALSE;
  1063. } //FetchI8StatProp
  1064. //+-------------------------------------------------------------------------
  1065. //
  1066. // Member: CCiPropRetriever::BeginPropertyRetrieval
  1067. //
  1068. // Synopsis: Prime wid for property retrieval
  1069. //
  1070. // Arguments: [wid] -- Wid to prime
  1071. //
  1072. // History: 12-Dec-96 SitaramR Created
  1073. //
  1074. //--------------------------------------------------------------------------
  1075. SCODE STDMETHODCALLTYPE CCiPropRetriever::BeginPropertyRetrieval( WORKID wid )
  1076. {
  1077. //
  1078. // Check that we are not in the midst of a property retrieval
  1079. //
  1080. Win4Assert( _fFindLoaded == FALSE );
  1081. Win4Assert( _fFastFindLoaded == FALSE );
  1082. Win4Assert( _fFastStatLoaded == 0 );
  1083. Win4Assert( _fFastStatNeverLoad == 0 );
  1084. Win4Assert( _Path.Length == flagNoValueYet );
  1085. Win4Assert( _VPath.Length == flagNoValueYet );
  1086. Win4Assert( _Name.Length == flagNoValueYet );
  1087. Win4Assert( !_remoteAccess.IsImpersonated() );
  1088. Win4Assert( _widPrimedForPropRetrieval == widInvalid );
  1089. //
  1090. // wid should be valid
  1091. //
  1092. Win4Assert( wid != widInvalid );
  1093. _widPrimedForPropRetrieval = wid;
  1094. return S_OK;
  1095. } //BeginPropertyRetrieval
  1096. //+-------------------------------------------------------------------------
  1097. //
  1098. // Member: CCiPropRetriever::EndPropertyRetrieval
  1099. //
  1100. // Synopsis: Reset wid for property retrieval
  1101. //
  1102. // History: 12-Dec-96 SitaramR Created
  1103. //
  1104. //--------------------------------------------------------------------------
  1105. SCODE STDMETHODCALLTYPE CCiPropRetriever::EndPropertyRetrieval( )
  1106. {
  1107. PurgeCachedInfo();
  1108. return CGenericPropRetriever::EndPropertyRetrieval();
  1109. }
  1110. //+-------------------------------------------------------------------------
  1111. //
  1112. // Member: CCiPropRetriever::GetName
  1113. //
  1114. // Synopsis: Return file name
  1115. //
  1116. // History: 12-Dec-96 SitaramR Created
  1117. //
  1118. //--------------------------------------------------------------------------
  1119. UNICODE_STRING const * CCiPropRetriever::GetName()
  1120. {
  1121. //
  1122. // Retrieving Path or VPath will retrieve Name
  1123. //
  1124. if ( _Name.Length == flagNoValueYet )
  1125. GetPath();
  1126. return &_Name;
  1127. } //GetName