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.

1181 lines
35 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-2000.
  5. //
  6. // File: propret.cxx
  7. //
  8. // Contents: Generic property retriever filesystems
  9. //
  10. // Classes: CGenericPropRetriever
  11. //
  12. // History: 12-Dec-96 SitaramR Created
  13. //
  14. //-------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <propret.hxx>
  18. #include <seccache.hxx>
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CGenericPropRetriever::CGenericPropRetriever
  22. //
  23. // Synopsis: Extracts property and object tables from the catalog.
  24. //
  25. // Arguments: [cat] -- Catalog
  26. // [pQueryPropMapper] -- Pid Remapper associated with the query
  27. // [secCache] -- Cache of AccessCheck() results
  28. // [pScope] -- Scope (for fixup match) if client is going
  29. // through rdr/svr, else 0.
  30. // [amAlreadyAccessChecked] -- Don't need to re-check for this
  31. // access mask.
  32. //
  33. // History: 21-Aug-91 KyleP Created
  34. //
  35. //----------------------------------------------------------------------------
  36. CGenericPropRetriever::CGenericPropRetriever( PCatalog & cat,
  37. ICiQueryPropertyMapper *pQueryPropMapper,
  38. CSecurityCache & secCache,
  39. CRestriction const * pScope,
  40. ACCESS_MASK amAlreadyAccessChecked )
  41. : _cat( cat ),
  42. _pQueryPropMapper( pQueryPropMapper ),
  43. _secCache( secCache ),
  44. _widPrimedForPropRetrieval( widInvalid ),
  45. _remoteAccess( cat.GetImpersonationTokenCache() ),
  46. _pScope( pScope ),
  47. _ulAttribFilter( cat.GetRegParams()->FilterDirectories() ?
  48. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :
  49. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_DIRECTORY ),
  50. _pPropRec( 0 ),
  51. _cRefs( 1 ),
  52. _amAlreadyAccessChecked( amAlreadyAccessChecked )
  53. {
  54. }
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Member: CGenericPropRetriever::~CGenericPropRetriever, public
  58. //
  59. // Synopsis: Closes catalog tables associated with this instance.
  60. //
  61. // History: 21-Aug-91 KyleP Created.
  62. //
  63. //----------------------------------------------------------------------------
  64. CGenericPropRetriever::~CGenericPropRetriever()
  65. {
  66. Quiesce();
  67. }
  68. //+-------------------------------------------------------------------------
  69. //
  70. // Method: CGenericPropRetriever::Quiesce, public
  71. //
  72. // Synopsis: Close any open resources.
  73. //
  74. // History: 3-May-1994 KyleP Created
  75. //
  76. //--------------------------------------------------------------------------
  77. void CGenericPropRetriever::Quiesce()
  78. {
  79. _propMgr.Close();
  80. _cat.CloseValueRecord( _pPropRec );
  81. _pPropRec = 0;
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Member: CGenericPropRetriever::RetrieveValueByPid
  86. //
  87. // Effects: Fetch value from the property cache.
  88. //
  89. // Arguments: [pid] -- Property to fetch
  90. // [pbData] -- Place to return the value
  91. // [pcb] -- On input, the maximum number of bytes to
  92. // write at pbData. On output, the number of
  93. // bytes written if the call was successful,
  94. // else the number of bytes required.
  95. //
  96. // History: 12-Dec-96 SitaramR Created
  97. //
  98. //----------------------------------------------------------------------------
  99. inline BYTE * PastHeader( PROPVARIANT * ppv )
  100. {
  101. return( (BYTE *)ppv + sizeof( PROPVARIANT ) );
  102. }
  103. SCODE STDMETHODCALLTYPE CGenericPropRetriever::RetrieveValueByPid( PROPID pid,
  104. PROPVARIANT *pbData,
  105. ULONG *pcb )
  106. {
  107. static const UNICODE_STRING EmptyUnicodeString = { 0, 0, 0 };
  108. if ( widInvalid == _widPrimedForPropRetrieval )
  109. return CI_E_WORKID_NOTVALID;
  110. SCODE sc = S_OK;
  111. TRY
  112. {
  113. unsigned cb = sizeof( PROPVARIANT );
  114. //
  115. // System properties are retrieved directly from FindFirst buffer.
  116. // User properties must be retrieved through the standard retrieval
  117. // mechanism.
  118. //
  119. switch ( pid )
  120. {
  121. case pidDirectory:
  122. {
  123. pbData->vt = VT_LPWSTR;
  124. pbData->pwszVal = (WCHAR *)PastHeader(pbData);
  125. unsigned cbExtra = 0;
  126. // If the client is remote, apply the fixup to the path
  127. if ( IsClientRemote() )
  128. {
  129. XGrowable<WCHAR> xwcBuf;
  130. cbExtra = BuildPath( GetPath(),
  131. & EmptyUnicodeString,
  132. xwcBuf );
  133. if ( 0 != cbExtra )
  134. {
  135. unsigned cwcBuf = ( *pcb - sizeof PROPVARIANT ) / sizeof WCHAR;
  136. unsigned cwc = FixupPath( xwcBuf.Get(),
  137. pbData->pwszVal,
  138. cwcBuf );
  139. cbExtra = (1 + cwc) * sizeof WCHAR;
  140. }
  141. }
  142. else
  143. {
  144. cbExtra = BuildPath( GetPath(),
  145. & EmptyUnicodeString,
  146. pbData->pwszVal,
  147. *pcb - sizeof PROPVARIANT );
  148. }
  149. if ( 0 == cbExtra )
  150. pbData->vt = VT_EMPTY;
  151. else
  152. cb += cbExtra;
  153. break;
  154. }
  155. case pidClassId:
  156. {
  157. //
  158. // If it's a Docfile, retrieve the class ID from the Docfile,
  159. // otherwise, just return a default file or directory class id.
  160. //
  161. pbData->vt = VT_CLSID;
  162. cb += sizeof( GUID );
  163. if ( cb <= *pcb )
  164. {
  165. pbData->puuid = (GUID *)PastHeader(pbData);
  166. SCODE sc = E_FAIL;
  167. CFunnyPath funnyBuf;
  168. if ( 0 == BuildPath( GetPath(), GetName(), funnyBuf ) )
  169. {
  170. pbData->vt = VT_EMPTY;
  171. cb -= sizeof(GUID);
  172. }
  173. else
  174. {
  175. //
  176. // Try to retrieve the class id
  177. //
  178. sc = GetClassFile ( funnyBuf.GetPath(), pbData->puuid );
  179. if ( FAILED(sc) )
  180. {
  181. // OLE was unable to obtain or infer the class id
  182. cb -= sizeof( GUID );
  183. pbData->vt = VT_EMPTY;
  184. }
  185. }
  186. }
  187. break;
  188. }
  189. case pidPath:
  190. {
  191. pbData->vt = VT_LPWSTR;
  192. pbData->pwszVal = (WCHAR *)PastHeader(pbData);
  193. unsigned cbExtra = 0;
  194. // If the client is remote, apply the fixup to the path
  195. if ( IsClientRemote() )
  196. {
  197. XGrowable<WCHAR> xwcBuf;
  198. cbExtra = BuildPath( GetPath(),
  199. GetName(),
  200. xwcBuf );
  201. if ( 0 != cbExtra )
  202. {
  203. unsigned cwcBuf = ( *pcb - sizeof PROPVARIANT ) / sizeof WCHAR;
  204. unsigned cwc = FixupPath( xwcBuf.Get(),
  205. pbData->pwszVal,
  206. cwcBuf );
  207. cbExtra = (1 + cwc) * sizeof WCHAR;
  208. }
  209. }
  210. else
  211. {
  212. cbExtra = BuildPath( GetPath(),
  213. GetName(),
  214. pbData->pwszVal,
  215. *pcb - sizeof PROPVARIANT );
  216. }
  217. if ( 0 == cbExtra )
  218. pbData->vt = VT_EMPTY;
  219. else
  220. cb += cbExtra;
  221. break;
  222. }
  223. case pidVirtualPath:
  224. {
  225. UNICODE_STRING const * pPath = GetVirtualPath();
  226. if ( 0 == pPath )
  227. pbData->vt = VT_EMPTY;
  228. else
  229. {
  230. pbData->vt = VT_LPWSTR;
  231. pbData->pwszVal = (WCHAR *)PastHeader(pbData);
  232. cb += BuildPath( pPath, GetName(), pbData->pwszVal, *pcb - sizeof(PROPVARIANT) );
  233. }
  234. break;
  235. }
  236. case pidName:
  237. cb = *pcb;
  238. StringToVariant( GetName(), pbData, &cb );
  239. break;
  240. case pidShortName:
  241. cb = *pcb;
  242. StringToVariant( GetShortName(), pbData, &cb );
  243. break;
  244. case pidLastChangeUsn:
  245. pbData->vt = VT_I8;
  246. pbData->hVal.QuadPart = 1; // First legal USN
  247. break;
  248. case pidSize:
  249. pbData->vt = VT_I8;
  250. pbData->hVal.QuadPart = ObjectSize();
  251. if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
  252. pbData->vt = VT_EMPTY;
  253. #if CIDBG == 1
  254. if ( VT_I8 == pbData->vt )
  255. Win4Assert( 0xdddddddddddddddd != pbData->hVal.QuadPart );
  256. #endif // CIDBG == 1
  257. break;
  258. case pidAttrib:
  259. pbData->vt = VT_UI4;
  260. pbData->ulVal = Attributes();
  261. if ( pbData->ulVal == 0xFFFFFFFF )
  262. pbData->vt = VT_EMPTY;
  263. #if CIDBG == 1
  264. if ( VT_UI4 == pbData->vt )
  265. Win4Assert( 0xdddddddd != pbData->ulVal );
  266. #endif // CIDBG == 1
  267. break;
  268. case pidWriteTime:
  269. pbData->vt = VT_FILETIME;
  270. pbData->hVal.QuadPart = ModifyTime();
  271. if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
  272. pbData->vt = VT_EMPTY;
  273. break;
  274. case pidCreateTime:
  275. pbData->vt = VT_FILETIME;
  276. pbData->hVal.QuadPart = CreateTime();
  277. if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
  278. pbData->vt = VT_EMPTY;
  279. break;
  280. case pidAccessTime:
  281. pbData->vt = VT_FILETIME;
  282. pbData->hVal.QuadPart = AccessTime();
  283. if ( pbData->hVal.QuadPart == 0xFFFFFFFFFFFFFFFF )
  284. pbData->vt = VT_EMPTY;
  285. break;
  286. case pidStorageType:
  287. pbData->vt = VT_UI4;
  288. pbData->ulVal = StorageType();
  289. if ( 0xFFFFFFFF == pbData->ulVal )
  290. {
  291. //
  292. // Try VRootType
  293. //
  294. if ( GetVRootType( pbData->ulVal ) )
  295. {
  296. if ( pbData->ulVal & PCatalog::NNTPRoot )
  297. pbData->ulVal = 1;
  298. else
  299. pbData->ulVal = 0;
  300. }
  301. else
  302. pbData->vt = VT_EMPTY;
  303. }
  304. break;
  305. case pidPropertyStoreLevel:
  306. pbData->vt = VT_UI4;
  307. pbData->ulVal = StorageLevel();
  308. break;
  309. case pidPropDataModifiable:
  310. pbData->vt = VT_BOOL;
  311. pbData->boolVal = IsModifiable() ? VARIANT_TRUE : VARIANT_FALSE;
  312. break;
  313. case pidVRootUsed:
  314. {
  315. if ( GetVRootType( pbData->ulVal ) )
  316. {
  317. pbData->vt = VT_BOOL;
  318. if ( pbData->ulVal & PCatalog::UsedRoot )
  319. pbData->boolVal = VARIANT_TRUE;
  320. else
  321. pbData->boolVal = VARIANT_FALSE;
  322. }
  323. else
  324. pbData->vt = VT_EMPTY;
  325. break;
  326. }
  327. case pidVRootAutomatic:
  328. {
  329. if ( GetVRootType( pbData->ulVal ) )
  330. {
  331. pbData->vt = VT_BOOL;
  332. if ( pbData->ulVal & PCatalog::AutomaticRoot )
  333. pbData->boolVal = VARIANT_TRUE;
  334. else
  335. pbData->boolVal = VARIANT_FALSE;
  336. }
  337. else
  338. pbData->vt = VT_EMPTY;
  339. break;
  340. }
  341. case pidVRootManual:
  342. {
  343. if ( GetVRootType( pbData->ulVal ) )
  344. {
  345. pbData->vt = VT_BOOL;
  346. if ( pbData->ulVal & PCatalog::ManualRoot )
  347. pbData->boolVal = VARIANT_TRUE;
  348. else
  349. pbData->boolVal = VARIANT_FALSE;
  350. }
  351. else
  352. pbData->vt = VT_EMPTY;
  353. break;
  354. }
  355. case pidPropertyGuid:
  356. cb += sizeof( GUID );
  357. if ( cb <= *pcb )
  358. {
  359. pbData->puuid = (GUID *)PastHeader(pbData);
  360. if ( GetPropGuid( *pbData->puuid ) )
  361. pbData->vt = VT_CLSID;
  362. else
  363. {
  364. cb -= sizeof(GUID);
  365. pbData->vt = VT_EMPTY;
  366. }
  367. }
  368. break;
  369. case pidPropertyDispId:
  370. pbData->ulVal = GetPropPropid();
  371. if ( pbData->ulVal == pidInvalid )
  372. pbData->vt = VT_EMPTY;
  373. else
  374. pbData->vt = VT_UI4;
  375. break;
  376. case pidPropertyName:
  377. cb = *pcb;
  378. StringToVariant( GetPropName(), pbData, &cb );
  379. break;
  380. default:
  381. {
  382. //
  383. // First, try the property cache.
  384. //
  385. cb = *pcb;
  386. BOOL fTryOLE = TRUE;
  387. if ( FetchValue( pid, pbData, &cb ) )
  388. {
  389. fTryOLE = FALSE;
  390. if ( ( cb <= *pcb ) &&
  391. ( IsNullPointerVariant( pbData ) ) )
  392. {
  393. pbData->vt = VT_EMPTY;
  394. cb = sizeof( PROPVARIANT );
  395. }
  396. // If we got back VT_EMPTY, it may be because the file has
  397. // been scanned and not filtered. If there is no write time,
  398. // the file hasn't been filtered yet, so trying OLE to load
  399. // the value is worth it.
  400. if ( VT_EMPTY == pbData->vt )
  401. {
  402. PROPVARIANT vWrite;
  403. vWrite.vt = VT_EMPTY;
  404. unsigned cbWrite = sizeof vWrite;
  405. FetchValue( pidWriteTime, &vWrite, &cbWrite );
  406. if ( VT_EMPTY == vWrite.vt )
  407. fTryOLE = TRUE;
  408. }
  409. }
  410. if ( fTryOLE )
  411. {
  412. CImpersonateClient impClient( GetClientToken() );
  413. if ( !_propMgr.isOpen() )
  414. {
  415. //
  416. // Get a full, null-terminated, path.
  417. //
  418. CFunnyPath funnyBuf;
  419. if ( 0 != BuildPath( GetPath(),
  420. GetName(),
  421. funnyBuf ) )
  422. {
  423. // Open property manager.
  424. if ( CImpersonateRemoteAccess::IsNetPath( funnyBuf.GetActualPath() ) )
  425. {
  426. UNICODE_STRING const * pVPath = GetVirtualPath();
  427. WCHAR const * pwszVPath = 0 != pVPath ? pVPath->Buffer : 0;
  428. if ( !_remoteAccess.ImpersonateIfNoThrow( funnyBuf.GetActualPath(),
  429. pwszVPath ) )
  430. {
  431. return CI_E_LOGON_FAILURE;
  432. }
  433. }
  434. else if ( _remoteAccess.IsImpersonated() )
  435. {
  436. _remoteAccess.Release();
  437. }
  438. BOOL fSharingViolation = _propMgr.Open( funnyBuf );
  439. if ( fSharingViolation )
  440. return CI_E_SHARING_VIOLATION;
  441. }
  442. }
  443. FULLPROPSPEC const *pPropSpec;
  444. SCODE sc = _pQueryPropMapper->PropidToProperty( pid, &pPropSpec );
  445. if ( FAILED( sc ) )
  446. {
  447. Win4Assert( !"PropidToProperty failed" );
  448. THROW ( CException( sc ) );
  449. }
  450. CFullPropSpec const * ps = (CFullPropSpec const *) pPropSpec;
  451. cb = *pcb;
  452. _propMgr.FetchProperty( ps->GetPropSet(),
  453. ps->GetPropSpec(),
  454. pbData,
  455. &cb );
  456. }
  457. break;
  458. }
  459. } // case
  460. if ( cb <= *pcb )
  461. {
  462. *pcb = cb;
  463. #if CIDBG == 1
  464. CStorageVariant var( *pbData );
  465. vqDebugOut(( DEB_PROPTIME, "Fetched value (pid = 0x%x): ", pid ));
  466. var.DisplayVariant( DEB_PROPTIME | DEB_NOCOMPNAME, 0 );
  467. vqDebugOut(( DEB_PROPTIME | DEB_NOCOMPNAME, "\n" ));
  468. #endif
  469. }
  470. else
  471. {
  472. *pcb = cb;
  473. vqDebugOut(( DEB_PROPTIME, "Failed to fetch value (pid = 0x%x)\n", pid ));
  474. sc = CI_E_BUFFERTOOSMALL ;
  475. }
  476. }
  477. CATCH( CException, e )
  478. {
  479. sc = e.GetErrorCode();
  480. vqDebugOut(( DEB_ERROR,
  481. "CGenericPropRetriever::RetrieveValueByPid - Exception caught 0x%x\n",
  482. sc ));
  483. }
  484. END_CATCH;
  485. return sc;
  486. }
  487. //+---------------------------------------------------------------------------
  488. //
  489. // Member: CGenericPropRetriever::StringToVariant, private
  490. //
  491. // Arguments: [pString] -- String to copy.
  492. // [pbData] -- String stored here.
  493. // [pcb] -- On input: max length in bytes of [pbData].
  494. // On output: size required by [pString]. If
  495. // less-than-or-equal-to input size, then string
  496. // was copied.
  497. //
  498. // History: 17-Jul-95 KyleP Created header.
  499. //
  500. //----------------------------------------------------------------------------
  501. void CGenericPropRetriever::StringToVariant( UNICODE_STRING const * pString,
  502. PROPVARIANT * pbData,
  503. unsigned * pcb )
  504. {
  505. unsigned cb = sizeof(PROPVARIANT);
  506. if ( 0 == pString || 0 == pString->Length )
  507. {
  508. pbData->vt = VT_EMPTY;
  509. }
  510. else
  511. {
  512. pbData->vt = VT_LPWSTR;
  513. cb += pString->Length + sizeof( WCHAR ); // For L'\0' at end.
  514. if ( cb <= *pcb )
  515. {
  516. WCHAR * pwcName = (WCHAR *)PastHeader(pbData);
  517. pbData->pwszVal = pwcName;
  518. RtlCopyMemory( pwcName,
  519. pString->Buffer,
  520. pString->Length );
  521. pwcName[pString->Length/sizeof(WCHAR)] = L'\0';
  522. }
  523. }
  524. *pcb = cb;
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: CGenericPropRetriever::BuildPath, private
  529. //
  530. // Synopsis: Gloms path + filename together
  531. //
  532. // Arguments: [pPath] -- Path, sans filename
  533. // [pFilename] -- Filename
  534. // [funnyBuf] -- Full path copied here.
  535. //
  536. // Returns: Size in **bytes** of full path. 0 --> No path
  537. //
  538. // History: 04-Jun-98 VikasMan Created
  539. //
  540. //----------------------------------------------------------------------------
  541. unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
  542. UNICODE_STRING const * pFilename,
  543. CFunnyPath & funnyBuf)
  544. {
  545. if ( 0 == pPath || 0 == pPath->Length || 0 == pFilename )
  546. return 0;
  547. funnyBuf.SetPath( pPath->Buffer, pPath->Length/sizeof(WCHAR) );
  548. if ( pFilename->Length > 0 )
  549. {
  550. funnyBuf.AppendBackSlash();
  551. funnyBuf.AppendPath( pFilename->Buffer, pFilename->Length/sizeof(WCHAR) );
  552. }
  553. return funnyBuf.GetLength() * sizeof(WCHAR);
  554. }
  555. //+---------------------------------------------------------------------------
  556. //
  557. // Member: CGenericPropRetriever::BuildPath, private
  558. //
  559. // Synopsis: Gloms path + filename together
  560. //
  561. // Arguments: [pPath] -- Path, sans filename
  562. // [pFilename] -- Filename
  563. // [xwcBuf] -- Full path copied here.
  564. //
  565. // Returns: Size in **bytes** of full path. 0 --> No path
  566. //
  567. // History: 04-Jun-98 VikasMan Created
  568. //
  569. //----------------------------------------------------------------------------
  570. unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
  571. UNICODE_STRING const * pFilename,
  572. XGrowable<WCHAR> & xwcBuf)
  573. {
  574. if ( 0 == pPath || 0 == pFilename )
  575. return 0;
  576. unsigned cb = pPath->Length +
  577. pFilename->Length +
  578. sizeof WCHAR; // L'\0' at end
  579. if ( pFilename->Length > 0 )
  580. cb += sizeof WCHAR; // L'\\' between path and filename
  581. xwcBuf.SetSizeInBytes( cb );
  582. return BuildPath( pPath, pFilename, xwcBuf.Get(), cb );
  583. }
  584. //+---------------------------------------------------------------------------
  585. //
  586. // Member: CGenericPropRetriever::BuildPath, private
  587. //
  588. // Synopsis: Gloms path + filename together
  589. //
  590. // Arguments: [pPath] -- Path, sans filename
  591. // [pFilename] -- Filename
  592. // [pwcBuf] -- Full path copied here.
  593. // [cbBuf] -- Size in **bytes** of pwcBuf.
  594. //
  595. // Returns: Size in **bytes** of full path. Path only built if return
  596. // value is <= [cbBuf]. 0 --> No path
  597. //
  598. // History: 07-Feb-96 KyleP Created header.
  599. //
  600. //----------------------------------------------------------------------------
  601. unsigned CGenericPropRetriever::BuildPath( UNICODE_STRING const * pPath,
  602. UNICODE_STRING const * pFilename,
  603. WCHAR * pwcBuf,
  604. unsigned cbBuf )
  605. {
  606. if ( 0 == pPath || 0 == pFilename )
  607. return 0;
  608. unsigned cb = pPath->Length +
  609. pFilename->Length +
  610. sizeof WCHAR; // L'\0' at end
  611. if ( pFilename->Length > 0 )
  612. cb += sizeof WCHAR; // L'\\' between path and filename
  613. if ( cb <= cbBuf )
  614. {
  615. RtlCopyMemory( pwcBuf, pPath->Buffer, pPath->Length );
  616. pwcBuf += pPath->Length/sizeof(WCHAR);
  617. if ( pFilename->Length > 0 )
  618. {
  619. *pwcBuf++ = L'\\';
  620. RtlCopyMemory( pwcBuf,
  621. pFilename->Buffer,
  622. pFilename->Length );
  623. pwcBuf += pFilename->Length / sizeof WCHAR;
  624. }
  625. *pwcBuf = 0;
  626. }
  627. return cb;
  628. }
  629. //+---------------------------------------------------------------------------
  630. //
  631. // Member: CGenericPropRetriever::FetchValue, protected
  632. //
  633. // Effects: Fetch value from the property cache.
  634. //
  635. // Arguments: [pid] -- Property to fetch
  636. // [pbData] -- Place to return the value
  637. // [pcb] -- On input, the maximum number of bytes to
  638. // write at pbData. On output, the number of
  639. // bytes written if the call was successful,
  640. // else the number of bytes required.
  641. //
  642. // Returns: TRUE if property was fetched
  643. //
  644. // History: 03-Apr-96 KyleP Created.
  645. //
  646. //----------------------------------------------------------------------------
  647. BOOL CGenericPropRetriever::FetchValue( PROPID pid, PROPVARIANT * pbData, unsigned * pcb )
  648. {
  649. OpenPropertyRecord();
  650. return _cat.FetchValue( _pPropRec, pid, pbData, pcb );
  651. }
  652. //+-------------------------------------------------------------------------
  653. //
  654. // Member: CGenericPropRetriever::CheckSecurity
  655. //
  656. // Synopsis: Test wid for security access
  657. //
  658. // Arguments: [am] -- Access Mask
  659. // [pfGranted] -- Result of security check returned here
  660. //
  661. // History: 19-Aug-93 KyleP Created
  662. //
  663. //--------------------------------------------------------------------------
  664. SCODE STDMETHODCALLTYPE CGenericPropRetriever::CheckSecurity( ACCESS_MASK am,
  665. BOOL *pfGranted)
  666. {
  667. //
  668. // No need to impersonate the client because the Win32 AccessCheck API
  669. // takes a client token as a parameter
  670. //
  671. SCODE sc = S_OK;
  672. TRY
  673. {
  674. if ( _widPrimedForPropRetrieval == widInvalid )
  675. sc = CI_E_WORKID_NOTVALID;
  676. else
  677. {
  678. OpenPropertyRecord();
  679. if ( am != _amAlreadyAccessChecked )
  680. {
  681. SDID sdid = _cat.FetchSDID( _pPropRec,
  682. _widPrimedForPropRetrieval );
  683. *pfGranted = _secCache.IsGranted( sdid, am );
  684. }
  685. else
  686. *pfGranted = TRUE;
  687. }
  688. }
  689. CATCH( CException, e )
  690. {
  691. sc = e.GetErrorCode();
  692. vqDebugOut(( DEB_ERROR,
  693. "CGenericPropRetriever::CheckSecurity - Exception caught 0x%x\n",
  694. sc ));
  695. }
  696. END_CATCH;
  697. return sc;
  698. }
  699. //+-------------------------------------------------------------------------
  700. //
  701. // Member: CGenericPropRetriever::EndPropertyRetrieval
  702. //
  703. // Synopsis: Reset wid for property retrieval
  704. //
  705. // History: 12-Dec-96 SitaramR Created
  706. //
  707. //--------------------------------------------------------------------------
  708. SCODE STDMETHODCALLTYPE CGenericPropRetriever::EndPropertyRetrieval()
  709. {
  710. Win4Assert( _widPrimedForPropRetrieval != widInvalid );
  711. SCODE sc = S_OK;
  712. TRY
  713. {
  714. Quiesce();
  715. if ( _remoteAccess.IsImpersonated() )
  716. _remoteAccess.Release();
  717. _widPrimedForPropRetrieval = widInvalid;
  718. }
  719. CATCH( CException, e )
  720. {
  721. sc = e.GetErrorCode();
  722. vqDebugOut(( DEB_ERROR,
  723. "CGenericPropRetriever::EndPropertyRetrieval - Exception caught 0x%x\n",
  724. sc ));
  725. }
  726. END_CATCH;
  727. return sc;
  728. }
  729. //+-------------------------------------------------------------------------
  730. //
  731. // Method: CGenericPropRetriever::AddRef
  732. //
  733. // Synopsis: Increments refcount
  734. //
  735. // History: 12-Dec-1996 SitaramR Created
  736. //
  737. //--------------------------------------------------------------------------
  738. ULONG STDMETHODCALLTYPE CGenericPropRetriever::AddRef()
  739. {
  740. return InterlockedIncrement( (long *) &_cRefs );
  741. }
  742. //+-------------------------------------------------------------------------
  743. //
  744. // Method: CGenericPropRetriever::Release
  745. //
  746. // Synopsis: Decrement refcount. Delete if necessary.
  747. //
  748. // History: 12-Dec-1996 SitaramR Created
  749. //
  750. //--------------------------------------------------------------------------
  751. ULONG STDMETHODCALLTYPE CGenericPropRetriever::Release()
  752. {
  753. Win4Assert( _cRefs > 0 );
  754. ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
  755. if ( 0 == uTmp )
  756. delete this;
  757. return uTmp;
  758. }
  759. //+-------------------------------------------------------------------------
  760. //
  761. // Method: CGenericPropRetriever::QueryInterface
  762. //
  763. // Synopsis: Rebind to other interface
  764. //
  765. // Arguments: [riid] -- IID of new interface
  766. // [ppvObject] -- New interface * returned here
  767. //
  768. // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
  769. //
  770. // History: 12-Dec-1996 SitaramR Created
  771. //
  772. //--------------------------------------------------------------------------
  773. SCODE STDMETHODCALLTYPE CGenericPropRetriever::QueryInterface(
  774. REFIID riid,
  775. void ** ppvObject)
  776. {
  777. *ppvObject = 0;
  778. if ( IID_ICiCPropRetriever == riid )
  779. *ppvObject = (IUnknown *)(ICiCPropRetriever *)this;
  780. else if ( IID_IUnknown == riid )
  781. *ppvObject = (IUnknown *)this;
  782. else
  783. return E_NOINTERFACE;
  784. AddRef();
  785. return S_OK;
  786. }
  787. //+-------------------------------------------------------------------------
  788. //
  789. // Method: CGenericPropRetriever::FetchPath, protected
  790. //
  791. // Synopsis: Reads the path from the open property record
  792. //
  793. // Arguments: [pwcPath] -- where to put the path
  794. // [cwc] -- size of the buffer in/out in characters
  795. //
  796. // History: 15-Jan-1998 dlee Created
  797. //
  798. //--------------------------------------------------------------------------
  799. void CGenericPropRetriever::FetchPath(
  800. WCHAR * pwcPath,
  801. unsigned & cwc )
  802. {
  803. PROPVARIANT var;
  804. unsigned cb = cwc * sizeof WCHAR;
  805. if ( _cat.FetchValue( GetPropertyRecord(),
  806. pidPath,
  807. &var,
  808. (BYTE *) pwcPath,
  809. &cb ) )
  810. cwc = cb / sizeof WCHAR;
  811. else
  812. cwc = 0;
  813. } //FetchPath
  814. //+-------------------------------------------------------------------------
  815. //
  816. // Method: CGenericPropRetriever::FixupPath, private
  817. //
  818. // Synopsis: Fixes up path (e.g. converts E:\Foo --> \\KyleP-1\RootE\Foo)
  819. //
  820. // Arguments: [pwcsPath] -- Source (local) path
  821. // [pwcsFixup] -- Aliased result
  822. // [cwcFixup] -- Count of characters in [pwcsFixup].
  823. //
  824. // Returns: Count of characters that are in [pwcsFixup]. If return
  825. // value is larger than [cwcFixup] then nothing was copied.
  826. //
  827. // History: 01-Oct-1998 KyleP Created (from ciprop.cxx vroot equivalent)
  828. //
  829. //--------------------------------------------------------------------------
  830. unsigned CGenericPropRetriever::FixupPath( WCHAR const * pwcsPath,
  831. WCHAR * pwcsFixup,
  832. unsigned cwcFixup )
  833. {
  834. BOOL fUseAnyPath = FALSE;
  835. unsigned cwc = 0;
  836. if ( RTScope == _pScope->Type() )
  837. {
  838. CScopeRestriction const & scp = * (CScopeRestriction *) _pScope;
  839. if ( scp.IsPhysical() )
  840. {
  841. BOOL fUnchanged;
  842. cwc = FetchFixupInScope( pwcsPath,
  843. pwcsFixup,
  844. cwcFixup,
  845. scp.GetPath(),
  846. scp.PathLength(),
  847. scp.IsDeep(),
  848. fUnchanged );
  849. Win4Assert( cwc > 0 );
  850. }
  851. else
  852. fUseAnyPath = TRUE;
  853. }
  854. else if ( RTOr == _pScope->Type() )
  855. {
  856. CNodeRestriction const & node = * _pScope->CastToNode();
  857. fUseAnyPath = TRUE;
  858. for ( ULONG x = 0; x < node.Count(); x++ )
  859. {
  860. Win4Assert( RTScope == node.GetChild( x )->Type() );
  861. CScopeRestriction const & scp = * (CScopeRestriction *)
  862. node.GetChild( x );
  863. if ( scp.IsPhysical() )
  864. {
  865. BOOL fUnchanged;
  866. cwc = FetchFixupInScope( pwcsPath,
  867. pwcsFixup,
  868. cwcFixup,
  869. scp.GetPath(),
  870. scp.PathLength(),
  871. scp.IsDeep(),
  872. fUnchanged );
  873. if ( cwc > 0 && !fUnchanged )
  874. {
  875. fUseAnyPath = FALSE;
  876. break;
  877. }
  878. }
  879. }
  880. }
  881. //
  882. // If no fixup works for the file, use the first match to physical scope.
  883. //
  884. if ( fUseAnyPath )
  885. cwc = _cat.FixupPath( pwcsPath,
  886. pwcsFixup,
  887. cwcFixup,
  888. 0 );
  889. return cwc;
  890. } //FixupPath
  891. //+-------------------------------------------------------------------------
  892. //
  893. // Method: CGenericPropRetriever::FetchFixupInScope, private
  894. //
  895. // Synopsis: Worker subroutine for FixupPath
  896. //
  897. // Arguments: [pwcsPath] -- Source (local) path
  898. // [pwcsFixup] -- Aliased result
  899. // [cwcFixup] -- Count of characters in [pwcsFixup].
  900. // [pwcRoot] -- Root scope (must match alias)
  901. // [cwcRoot] -- Size (in chars) of [pwcRoot]
  902. // [fDeep] -- True if [pwcRoot] is a deep scope.
  903. //
  904. // Returns: Count of characters that are in [pwcsFixup]. If return
  905. // value is larger than [cwcFixup] then nothing was copied.
  906. //
  907. // History: 01-Oct-1998 KyleP Created (from ciprop.cxx vroot equivalent)
  908. //
  909. //--------------------------------------------------------------------------
  910. unsigned CGenericPropRetriever::FetchFixupInScope( WCHAR const * pwcsPath,
  911. WCHAR * pwcsFixup,
  912. unsigned cwcFixup,
  913. WCHAR const * pwcRoot,
  914. unsigned cwcRoot,
  915. BOOL fDeep,
  916. BOOL & fUnchanged )
  917. {
  918. fUnchanged = FALSE;
  919. CScopeMatch Match( pwcRoot, cwcRoot );
  920. unsigned cSkip = 0;
  921. unsigned cwcPath = 0;
  922. unsigned cwcMaxPath = 0; // Used to hold longest path (when cwcFixup == 0)
  923. unsigned cwcOriginalPath = wcslen( pwcsPath );
  924. while ( TRUE )
  925. {
  926. cwcPath = _cat.FixupPath( pwcsPath,
  927. pwcsFixup,
  928. cwcFixup,
  929. cSkip );
  930. if ( 0 == cwcPath )
  931. return cwcMaxPath;
  932. //
  933. // If no fixups matched, return the original path
  934. //
  935. if ( cwcPath == cwcOriginalPath &&
  936. RtlEqualMemory( pwcsPath, pwcsFixup, cwcPath * sizeof WCHAR ) )
  937. {
  938. fUnchanged = TRUE;
  939. return cwcPath;
  940. }
  941. //
  942. // In scope?
  943. //
  944. if ( cwcPath > cwcFixup || !Match.IsInScope( pwcsFixup, cwcFixup ) )
  945. {
  946. cSkip++;
  947. //
  948. // Update max fixup size if we're polling for space requirements.
  949. //
  950. if ( cwcPath > cwcFixup && cwcPath > cwcMaxPath )
  951. cwcMaxPath = cwcPath;
  952. continue;
  953. }
  954. Win4Assert( 0 == pwcsFixup[cwcPath] );
  955. //
  956. // If the scope is shallow, check that it's still in scope
  957. //
  958. if ( !fDeep )
  959. {
  960. unsigned cwcName = 0;
  961. WCHAR * pwcName = pwcsFixup + cwcPath - 1;
  962. while ( L'\\' != *pwcName )
  963. {
  964. Win4Assert( cwcName < cwcPath );
  965. cwcName++;
  966. pwcName--;
  967. }
  968. unsigned cwcJustPath = cwcPath - cwcName - 1;
  969. BOOL fTooDeep = cwcJustPath > cwcRoot;
  970. if ( fTooDeep )
  971. {
  972. cSkip++;
  973. continue;
  974. }
  975. else
  976. break;
  977. }
  978. else
  979. break;
  980. }
  981. if (0 == cwcMaxPath)
  982. return cwcPath;
  983. else
  984. return cwcMaxPath;
  985. } //FetchFixupInScope