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.

743 lines
22 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998.
  5. //
  6. // File: qsession.cxx
  7. //
  8. // Contents: Query Session. Implements ICiCQuerySession interface.
  9. //
  10. // Classes: CQuerySession
  11. //
  12. // History: 12-Dec-96 SitaramR Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <qsession.hxx>
  18. #include <catalog.hxx>
  19. #include <ciprop.hxx>
  20. #include <vrtenum.hxx>
  21. #include <metapenm.hxx>
  22. #include <scopeenm.hxx>
  23. #include <defprop.hxx>
  24. #include <dbprputl.hxx>
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Member: CQuerySession::CQuerySession
  28. //
  29. // Synopsis: Constructor
  30. //
  31. // Arguments: [cat] -- Catalog
  32. // [xSecCache] -- Cache of access check results
  33. //
  34. // History: 12-Dec-96 SitaramR Created
  35. //
  36. //--------------------------------------------------------------------------
  37. CQuerySession::CQuerySession( PCatalog & cat )
  38. : _cat(cat),
  39. _secCache( cat ),
  40. _fUsePathAlias( FALSE ),
  41. _cRefs(1)
  42. {
  43. }
  44. //+-------------------------------------------------------------------------
  45. //
  46. // Member: CQuerySession::~CQuerySession
  47. //
  48. // Synopsis: Destructor
  49. //
  50. // History: 12-Dec-96 SitaramR Created
  51. //
  52. //--------------------------------------------------------------------------
  53. CQuerySession::~CQuerySession()
  54. {
  55. }
  56. //+-------------------------------------------------------------------------
  57. //
  58. // Method: CQuerySession::AddRef
  59. //
  60. // Synopsis: Increments refcount
  61. //
  62. // History: 12-Dec-1996 SitaramR Created
  63. //
  64. //--------------------------------------------------------------------------
  65. ULONG STDMETHODCALLTYPE CQuerySession::AddRef()
  66. {
  67. return InterlockedIncrement( (long *)&_cRefs );
  68. }
  69. //+-------------------------------------------------------------------------
  70. //
  71. // Method: CQuerySession::Release
  72. //
  73. // Synopsis: Decrement refcount. Delete if necessary.
  74. //
  75. // History: 12-Dec-1996 SitaramR Created
  76. //
  77. //--------------------------------------------------------------------------
  78. ULONG STDMETHODCALLTYPE CQuerySession::Release()
  79. {
  80. Win4Assert( _cRefs > 0 );
  81. ULONG uTmp = InterlockedDecrement( (long *)&_cRefs );
  82. if ( 0 == uTmp )
  83. delete this;
  84. return uTmp;
  85. }
  86. //+-------------------------------------------------------------------------
  87. //
  88. // Method: CQuerySession::QueryInterface
  89. //
  90. // Synopsis: Rebind to other interface
  91. //
  92. // Arguments: [riid] -- IID of new interface
  93. // [ppvObject] -- New interface * returned here
  94. //
  95. // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
  96. //
  97. // History: 12-Dec-1996 SitaramR Created
  98. //
  99. //--------------------------------------------------------------------------
  100. SCODE STDMETHODCALLTYPE CQuerySession::QueryInterface(
  101. REFIID riid,
  102. void ** ppvObject)
  103. {
  104. *ppvObject = 0;
  105. if ( IID_ICiCQuerySession == riid )
  106. *ppvObject = (IUnknown *)(ICiCQuerySession *)this;
  107. else if ( IID_IUnknown == riid )
  108. *ppvObject = (IUnknown *)this;
  109. else
  110. return E_NOINTERFACE;
  111. AddRef();
  112. return S_OK;
  113. }
  114. //+-------------------------------------------------------------------------
  115. //
  116. // Member: CQuerySession::Init
  117. //
  118. // Synopsis: Initializes a query session
  119. //
  120. // Arguments: [nProps] -- # of props in apPropSpec
  121. // [apPropSpec] -- Properties that may be retrieved by the query
  122. // [pDBProperties] -- Properties such as scope
  123. // [pQueryPropMapper] -- Propspec <-> pid mapper
  124. //
  125. // History: 12-Dec-96 SitaramR Created
  126. //
  127. //--------------------------------------------------------------------------
  128. SCODE STDMETHODCALLTYPE CQuerySession::Init( ULONG nProps,
  129. const FULLPROPSPEC *const *apPropSpec,
  130. IDBProperties *pDBProperties,
  131. ICiQueryPropertyMapper *pQueryPropertyMapper)
  132. {
  133. SCODE sc = S_OK;
  134. pQueryPropertyMapper->AddRef();
  135. _xQueryPropMapper.Set( pQueryPropertyMapper );
  136. TRY
  137. {
  138. //
  139. // Form the scope, _eType and _fUsePathAlias
  140. //
  141. CGetDbProps dbProps;
  142. dbProps.GetProperties( pDBProperties,
  143. CGetDbProps::eMachine |
  144. CGetDbProps::eScopesAndDepths |
  145. CGetDbProps::eCatalog |
  146. CGetDbProps::eQueryType );
  147. WCHAR const * pwszMachine = dbProps.GetMachine();
  148. if ( 0 == pwszMachine )
  149. THROW( CException( E_INVALIDARG ) );
  150. _fUsePathAlias = (L'.' != pwszMachine[0]);
  151. //
  152. // The registry can override a local client so paths are returned
  153. // with the alias taken into account.
  154. //
  155. CCiRegParams * pRegParams = _cat.GetRegParams();
  156. if ( 0 != pRegParams && pRegParams->GetForcePathAlias() )
  157. _fUsePathAlias = TRUE;
  158. _eType = dbProps.GetQueryType();
  159. if ( CiNormal == _eType )
  160. {
  161. const ULONG allScp = ( QUERY_SHALLOW | QUERY_DEEP |
  162. QUERY_PHYSICAL_PATH | QUERY_VIRTUAL_PATH );
  163. WCHAR const * const * aScopes = dbProps.GetScopes();
  164. DWORD const * aDepths = dbProps.GetDepths();
  165. if ( 0 == aScopes || 0 == aDepths )
  166. THROW( CException( E_INVALIDARG ) );
  167. ULONG cScopes = dbProps.GetScopeCount();
  168. ULONG cCatalogs = dbProps.GetCatalogCount();
  169. Win4Assert( cCatalogs == 1 );
  170. Win4Assert( cScopes > 0 );
  171. //
  172. // Get clean array of scopes.
  173. //
  174. CDynArray<WCHAR> aNormalizedScopes( cScopes );
  175. GetNormalizedScopes(aScopes, aDepths, cScopes, cCatalogs, aNormalizedScopes);
  176. if ( cScopes == 1 )
  177. {
  178. _xScope.Set( new CScopeRestriction( aNormalizedScopes.Get(0),
  179. 0 != ( aDepths[0] & QUERY_DEEP ),
  180. 0 != ( aDepths[0] & QUERY_VIRTUAL_PATH ) ) );
  181. }
  182. else
  183. {
  184. CNodeRestriction * pNodeRst = new CNodeRestriction( RTOr, cScopes );
  185. _xScope.Set( pNodeRst );
  186. for ( ULONG i = 0; i < cScopes; i++ )
  187. {
  188. if ( ( 0 != ( aDepths[i] & (~allScp) ) ) ||
  189. ( 0 == aNormalizedScopes.Get(i) ) )
  190. THROW( CException( E_INVALIDARG ) );
  191. XPtr<CScopeRestriction> xScope( new CScopeRestriction(
  192. aNormalizedScopes.Get(i),
  193. 0 != ( aDepths[i] & QUERY_DEEP ),
  194. 0 != ( aDepths[i] & QUERY_VIRTUAL_PATH ) ) );
  195. pNodeRst->AddChild( xScope.GetPointer() );
  196. xScope.Acquire();
  197. }
  198. }
  199. if ( !ValidateScopeRestriction( _xScope.GetPointer() ) )
  200. THROW( CException( STATUS_NO_MEMORY ) );
  201. }
  202. }
  203. CATCH( CException, e )
  204. {
  205. sc = e.GetErrorCode();
  206. vqDebugOut(( DEB_ERROR,
  207. "CQuerySession::Init - Exception caught 0x%x\n",
  208. sc ));
  209. }
  210. END_CATCH;
  211. return sc;
  212. } //Init
  213. //+-------------------------------------------------------------------------
  214. //
  215. // Member: CQuerySession::GetNormalizedScopes
  216. //
  217. // Synopsis: Validates/Normalizes scopes format
  218. //
  219. // Arguments: [aScopes] - pointer to array of scopes
  220. // [aDepths] - pointer to array of depths
  221. // [cScopes] - count of scopes
  222. // [cCatalogs] - count of catalogs
  223. // [aNormalizedScopes] - array of clean scopes to be returned.
  224. //
  225. // History: 14-May-97 mohamedn moved/merged from CQuerySpec
  226. //
  227. //--------------------------------------------------------------------------
  228. void CQuerySession::GetNormalizedScopes(WCHAR const * const *aScopes,
  229. ULONG const * aDepths,
  230. ULONG cScopes,
  231. ULONG cCatalogs,
  232. CDynArray<WCHAR> & aNormalizedScopes)
  233. {
  234. //
  235. // Don't allow 'current directory' opens like 'd:'. Must be 'd:\'
  236. //
  237. BOOL fAnyVirtual = FALSE;
  238. for ( ULONG iScope = 0; iScope < cScopes; iScope++ )
  239. {
  240. unsigned len = wcslen( aScopes[ iScope ] );
  241. // empty scopes mean "\", and they come from v5 clients
  242. if ( 0 != len )
  243. {
  244. if ( ( len < 3 ) &&
  245. ( !IsVScope( aDepths[ iScope ] ) ) &&
  246. ( wcscmp( aScopes[ iScope ], L"\\" ) ) )
  247. THROW ( CException(E_INVALIDARG) );
  248. if ( IsVScope( aDepths[ iScope ] ) )
  249. fAnyVirtual = TRUE;
  250. }
  251. }
  252. // A catalog must be specified with virtual paths (since a virtual path
  253. // tells you nothing about catalog location.
  254. if ( 0 == cCatalogs && fAnyVirtual )
  255. THROW ( CException(E_INVALIDARG) );
  256. //
  257. // Generate clean scopes
  258. //
  259. for ( ULONG i = 0; i < cScopes; i++ )
  260. {
  261. XArray<WCHAR> xScope;
  262. CleanupScope( xScope,
  263. aDepths[i],
  264. aScopes[i] );
  265. aNormalizedScopes.Add( xScope.Get(), i );
  266. xScope.Acquire();
  267. }
  268. } //GetNormalizedScopes
  269. //+-------------------------------------------------------------------------
  270. //
  271. // Function: CQuerySession::CleanupScope, public
  272. //
  273. // Synopsis: Makes sure a scope is well-formed
  274. //
  275. // Arguments: [xScope] -- Returns a cleaned-up scope
  276. // [dwDepth] -- Scope flags: deep/virtual
  277. // [pwcScope] -- Scope as specified by the user
  278. //
  279. // History: 1-Nov-96 dlee Moved Kyle's code from EvalQuery
  280. //
  281. //--------------------------------------------------------------------------
  282. void CQuerySession::CleanupScope( XArray<WCHAR> & xScope,
  283. DWORD dwDepth,
  284. WCHAR const * pwcScope )
  285. {
  286. // A non-slash terminated path to root is illegal. A slash
  287. // terminated path to a directory other than the root is
  288. // illegal. Sigh.
  289. Win4Assert( 0 != pwcScope );
  290. XGrowable<WCHAR> xTempScope;
  291. WCHAR const * pwcFinalScope = 0;
  292. if ( ( 0 == *pwcScope ) ||
  293. ( !_wcsicmp( L"catalog", pwcScope ) ) ||
  294. ( !wcscmp( L"\\", pwcScope ) ) )
  295. {
  296. pwcFinalScope = L"";
  297. }
  298. else if ( IsVScope( dwDepth ) )
  299. {
  300. pwcFinalScope = pwcScope;
  301. }
  302. else
  303. {
  304. int len = wcslen( pwcScope );
  305. BOOL fEndsInSlash = (pwcScope[len-1] == L'\\');
  306. BOOL fIsRoot;
  307. if ( len == 3 )
  308. fIsRoot = TRUE;
  309. else if ( pwcScope[0] == L'\\' && pwcScope[1] == L'\\' )
  310. {
  311. unsigned cSlash = 2;
  312. for ( unsigned i = 2; pwcScope[i] != 0; i++ )
  313. {
  314. if ( pwcScope[i] == L'\\' )
  315. {
  316. cSlash++;
  317. if ( cSlash > 4 )
  318. break;
  319. }
  320. }
  321. if ( cSlash > 4 )
  322. fIsRoot = FALSE;
  323. else if ( cSlash == 4 && !fEndsInSlash )
  324. fIsRoot = FALSE;
  325. else
  326. fIsRoot = TRUE;
  327. }
  328. else
  329. fIsRoot = FALSE;
  330. if ( fIsRoot )
  331. {
  332. if ( !fEndsInSlash )
  333. {
  334. xTempScope.SetSize( len + 1 + 1 );
  335. memcpy( xTempScope.Get(), pwcScope, len * sizeof WCHAR );
  336. xTempScope[len] = L'\\';
  337. len++;
  338. xTempScope[len] = 0;
  339. pwcFinalScope = xTempScope.Get();
  340. }
  341. else
  342. pwcFinalScope = pwcScope;
  343. }
  344. else
  345. {
  346. if ( fEndsInSlash )
  347. {
  348. xTempScope.SetSize( len );
  349. memcpy( xTempScope.Get(), pwcScope, (len-1)*sizeof(WCHAR) );
  350. xTempScope[len - 1] = 0;
  351. pwcFinalScope = xTempScope.Get();
  352. }
  353. else
  354. pwcFinalScope = pwcScope;
  355. }
  356. }
  357. Win4Assert( 0 != pwcFinalScope );
  358. int len = wcslen( pwcFinalScope );
  359. xScope.Init( 1 + len );
  360. RtlCopyMemory( xScope.GetPointer(), pwcFinalScope, xScope.SizeOf() );
  361. } //CleanupScope
  362. //+-------------------------------------------------------------------------
  363. //
  364. // Member: CQuerySession::GetEnumOption
  365. //
  366. // Synopsis: Specify the enumeration type
  367. //
  368. // Arguments: [pEnumOption] -- Enumeration option returned here
  369. //
  370. // History: 12-Dec-96 SitaramR Created
  371. //
  372. //--------------------------------------------------------------------------
  373. SCODE STDMETHODCALLTYPE CQuerySession::GetEnumOption( CI_ENUM_OPTIONS *pEnumOption)
  374. {
  375. SCODE sc = S_OK;
  376. TRY
  377. {
  378. Win4Assert( pEnumOption != 0 );
  379. switch ( _eType )
  380. {
  381. case CiProperties: // Fall thru
  382. case CiVirtualRoots:
  383. *pEnumOption = CI_ENUM_MUST_NEVER_DEFER;
  384. break;
  385. case CiPhysicalRoots:
  386. Win4Assert( !"Not implemented");
  387. vqDebugOut(( DEB_ERROR,
  388. "CQuerySession::GetEnumOption - CiPhysicalRoots not implemented\n" ));
  389. sc = E_NOTIMPL;
  390. break;
  391. case CiNormal:
  392. if ( IsAnyScopeDeep() )
  393. *pEnumOption = CI_ENUM_BIG;
  394. else
  395. *pEnumOption = CI_ENUM_SMALL;
  396. break;
  397. default:
  398. Win4Assert( !"Unknown value of case selector");
  399. vqDebugOut(( DEB_ERROR,
  400. "CQuerySession::GetEnumOption - Unknown case selector: %d\n",
  401. _eType ));
  402. sc = E_FAIL;
  403. break;
  404. }
  405. }
  406. CATCH( CException, e )
  407. {
  408. sc = e.GetErrorCode();
  409. vqDebugOut(( DEB_ERROR,
  410. "CQuerySession::GetEnumOption - Exception caught 0x%x\n",
  411. sc ));
  412. }
  413. END_CATCH;
  414. return sc;
  415. } //GetEnumOption
  416. //+-------------------------------------------------------------------------
  417. //
  418. // Member: CQuerySession::CreatePropRetriever
  419. //
  420. // Synopsis: Creates property retriever object for the given scope
  421. //
  422. // Arguments: [ppICiCPropRetreiver] -- Property retriever returned here
  423. //
  424. // History: 12-Dec-96 SitaramR Created
  425. //
  426. //--------------------------------------------------------------------------
  427. SCODE STDMETHODCALLTYPE CQuerySession::CreatePropRetriever( ICiCPropRetriever **ppICiCPropRetriever)
  428. {
  429. SCODE sc = S_OK;
  430. TRY
  431. {
  432. CCiPropRetriever *pPropRetriever = new CCiPropRetriever( _cat,
  433. _xQueryPropMapper.GetPointer(),
  434. _secCache,
  435. _fUsePathAlias,
  436. _xScope.GetPointer() );
  437. SCODE sc = pPropRetriever->QueryInterface( IID_ICiCPropRetriever,
  438. (void **) ppICiCPropRetriever );
  439. //
  440. // Either QI does an AddRef, or if failed free pPropRetriever
  441. //
  442. pPropRetriever->Release();
  443. #if CIDBG == 1
  444. if ( FAILED(sc) )
  445. vqDebugOut(( DEB_ERROR,
  446. "CQuerySession::CreatePropRetriever : QI failed 0x%x\n",
  447. sc ));
  448. #endif
  449. }
  450. CATCH( CException, e )
  451. {
  452. sc = e.GetErrorCode();
  453. vqDebugOut(( DEB_ERROR,
  454. "CQuerySession::CreatePropRetriever - Exception caught 0x%x\n",
  455. sc ));
  456. }
  457. END_CATCH;
  458. return sc;
  459. }
  460. //+-------------------------------------------------------------------------
  461. //
  462. // Member: CQuerySession::CreateDeferredPropRetriever
  463. //
  464. // Synopsis: Creates a deferred property retriever object for the given scope
  465. //
  466. // Arguments: [ppICiCDefPropRetreiver] -- Deferred property retriever returned here
  467. //
  468. // History: 12-Jan-97 SitaramR Created
  469. //
  470. //--------------------------------------------------------------------------
  471. SCODE STDMETHODCALLTYPE CQuerySession::CreateDeferredPropRetriever(
  472. ICiCDeferredPropRetriever **ppICiCDefPropRetriever)
  473. {
  474. SCODE sc = S_OK;
  475. TRY
  476. {
  477. CCiCDeferredPropRetriever *pDefPropRetriever = new CCiCDeferredPropRetriever(
  478. _cat,
  479. _secCache,
  480. _fUsePathAlias );
  481. SCODE sc = pDefPropRetriever->QueryInterface( IID_ICiCDeferredPropRetriever,
  482. (void **) ppICiCDefPropRetriever );
  483. //
  484. // Either QI does an AddRef, or if failed free pDefPropRetriever
  485. //
  486. pDefPropRetriever->Release();
  487. #if CIDBG == 1
  488. if ( FAILED(sc) )
  489. vqDebugOut(( DEB_ERROR,
  490. "CQuerySession::CreateDeferredPropRetriever : QI failed 0x%x\n",
  491. sc ));
  492. #endif
  493. }
  494. CATCH( CException, e )
  495. {
  496. sc = e.GetErrorCode();
  497. vqDebugOut(( DEB_ERROR,
  498. "CQuerySession::CreateDeferredPropRetriever - Exception caught 0x%x\n",
  499. sc ));
  500. }
  501. END_CATCH;
  502. return sc;
  503. }
  504. //+-------------------------------------------------------------------------
  505. //
  506. // Member: CQuerySession::CreateEnumerator
  507. //
  508. // Synopsis: Creates scope retriever object for the given scope
  509. //
  510. // Arguments: [ppICiCScopeEnumerator] -- Enumerator object returned here
  511. //
  512. // History: 12-Dec-96 SitaramR Created
  513. //
  514. //--------------------------------------------------------------------------
  515. SCODE STDMETHODCALLTYPE CQuerySession::CreateEnumerator( ICiCScopeEnumerator **ppICiCScopeEnumerator)
  516. {
  517. SCODE sc = S_OK;
  518. TRY
  519. {
  520. switch ( _eType )
  521. {
  522. case CiNormal:
  523. {
  524. CScopeEnum *pScopeEnum = new CScopeEnum( _cat,
  525. _xQueryPropMapper.GetPointer(),
  526. _secCache,
  527. _fUsePathAlias,
  528. _xScope.GetReference() );
  529. SCODE sc = pScopeEnum->QueryInterface( IID_ICiCScopeEnumerator,
  530. (void **) ppICiCScopeEnumerator );
  531. //
  532. // Either QI does an AddRef, or if failed free pScopeEnum
  533. //
  534. pScopeEnum->Release();
  535. break;
  536. }
  537. case CiVirtualRoots:
  538. {
  539. CVRootEnum *pVRootEnum = new CVRootEnum( _cat,
  540. _xQueryPropMapper.GetPointer(),
  541. _secCache,
  542. _fUsePathAlias );
  543. SCODE sc = pVRootEnum->QueryInterface( IID_ICiCScopeEnumerator,
  544. (void **) ppICiCScopeEnumerator );
  545. //
  546. // Either QI does an AddRef, or if failed free pVRootEnum
  547. //
  548. pVRootEnum->Release();
  549. break;
  550. }
  551. case CiProperties:
  552. {
  553. CMetaPropEnum *pMetaPropEnum = new CMetaPropEnum( _cat,
  554. _xQueryPropMapper.GetPointer(),
  555. _secCache,
  556. _fUsePathAlias );
  557. SCODE sc = pMetaPropEnum->QueryInterface( IID_ICiCScopeEnumerator,
  558. (void **) ppICiCScopeEnumerator );
  559. //
  560. // Either QI does an AddRef, or if failed free pMetaPropEnum
  561. //
  562. pMetaPropEnum->Release();
  563. break;
  564. }
  565. default:
  566. *ppICiCScopeEnumerator = 0;
  567. Win4Assert( !"Unknown value of case selector");
  568. vqDebugOut(( DEB_ERROR,
  569. "CQuerySession::CreateEnumerator - Unknown case selector: %d\n",
  570. _eType ));
  571. sc = E_FAIL;
  572. break;
  573. }
  574. }
  575. CATCH( CException, e )
  576. {
  577. sc = e.GetErrorCode();
  578. vqDebugOut(( DEB_ERROR, "CQuerySession::CreateEnumerator - Exception caught 0x%x\n", sc ));
  579. }
  580. END_CATCH;
  581. #if CIDBG == 1
  582. if ( FAILED(sc) )
  583. vqDebugOut(( DEB_ERROR, "CQuerySession::CreateEnumerator : QI failed 0x%x\n", sc ));
  584. #endif
  585. return sc;
  586. }
  587. //+-------------------------------------------------------------------------
  588. //
  589. // Member: CQuerySession::IsAnyScopeDeep
  590. //
  591. // Synopsis: Returns is any of the scopes is deep
  592. //
  593. // History: 12-Dec-96 DLee Created
  594. //
  595. //--------------------------------------------------------------------------
  596. BOOL CQuerySession::IsAnyScopeDeep() const
  597. {
  598. if ( 0 == &(_xScope.GetReference()) )
  599. return FALSE;
  600. if ( RTScope == _xScope->Type() )
  601. {
  602. CScopeRestriction const & scp = (CScopeRestriction const &) _xScope.GetReference();
  603. return scp.IsDeep();
  604. }
  605. else if ( RTOr == _xScope->Type() )
  606. {
  607. CNodeRestriction const & node = * _xScope->CastToNode();
  608. for ( ULONG x = 0; x < node.Count(); x++ )
  609. {
  610. Win4Assert( RTScope == node.GetChild( x )->Type() );
  611. CScopeRestriction & scp = * (CScopeRestriction *) node.GetChild( x );
  612. if ( scp.IsDeep() )
  613. return TRUE;
  614. }
  615. }
  616. return FALSE;
  617. }