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.

1141 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: datasrc.cxx
  7. //
  8. // Contents: Class factory description
  9. //
  10. // History: 3-30-97 MohamedN Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <datasrc.hxx>
  16. #include <session.hxx>
  17. #include <cidbprop.hxx> // CDbProperties
  18. #include <dbprpini.hxx> // CGetDbInitProps
  19. // Datasource object interfaces that support ISupportErrorInfo
  20. static const GUID* apDataSrcErrInt[] =
  21. {
  22. &IID_IDBCreateSession,
  23. &IID_IDBInitialize,
  24. &IID_IDBProperties,
  25. &IID_IPersist,
  26. &IID_IDBInfo,
  27. };
  28. static const ULONG cDataSrcErrInt = NUMELEM( apDataSrcErrInt );
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Method: CDataSrc::CDataSrc
  32. //
  33. // Synopsis: ctor
  34. //
  35. // Arguments: pUnkOuter - outer unknown
  36. //
  37. // History: 3-30-97 mohamedn Created
  38. // 10-05-97 danleg _ErrorInfo
  39. // 10-30-97 danleg Prop info for Initialize/Uninitialize
  40. // Notes:
  41. //
  42. //----------------------------------------------------------------------------
  43. CDataSrc::CDataSrc( IUnknown * pUnkOuter,
  44. IUnknown ** ppUnkInner )
  45. : _cSessionCount(0),
  46. _fDSOInitialized(FALSE),
  47. _fGlobalViewsCreated(FALSE),
  48. _xIPVerify(new CImpIParserVerify()),
  49. _UtlProps(_xIPVerify.GetPointer()),
  50. #pragma warning(disable : 4355)
  51. _impIUnknown(this),
  52. _ErrorInfo( * ((IUnknown *) (IDBInitialize *) this), _mtxDSO )
  53. #pragma warning(default : 4355)
  54. {
  55. _pUnkOuter = pUnkOuter ? pUnkOuter : (IUnknown *) &_impIUnknown;
  56. _ErrorInfo.SetInterfaceArray( cDataSrcErrInt, apDataSrcErrInt );
  57. // SQL Text Parser
  58. // @devnote: The following is allocated since its existence is controlled
  59. // by AddRef and Release.
  60. SCODE sc = MakeIParser(((IParser**)_xIParser.GetQIPointer()));
  61. if( FAILED(sc) )
  62. THROW( CException(sc) );
  63. _UtlPropInfo.ExposeMinimalSets();
  64. _UtlProps.ExposeMinimalSets();
  65. *ppUnkInner = (IUnknown *) &_impIUnknown;
  66. (*ppUnkInner)->AddRef();
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Method: CDataSrc::~CDataSrc
  71. //
  72. // Synopsis: d-ctor
  73. //
  74. // Arguments:
  75. //
  76. // History: 3-30-97 mohamedn Created
  77. // 10-30-97 danleg Prop info for Initialize/Uninitialize
  78. //----------------------------------------------------------------------------
  79. CDataSrc::~CDataSrc()
  80. {
  81. _UtlPropInfo.ExposeMaximalSets();
  82. _UtlProps.ExposeMaximalSets();
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Member: CDataSrc::RealQueryInterface
  87. //
  88. // Synopsis: Supports IID_IUnknown,
  89. // IID_IDBInitialize,
  90. // IID_IDBProperties,
  91. // IID_IDBIPersist,
  92. // IID_IDBCreateSession
  93. // IID_IDBInfo
  94. //
  95. // History: 03-30-97 mohamedn created
  96. // 09-05-97 danleg added IDBInfo & ISupportErrorInfo
  97. // 01-29-98 danleg non delegating QI when not aggregated
  98. //
  99. //----------------------------------------------------------------------------
  100. STDMETHODIMP CDataSrc::RealQueryInterface(REFIID riid, void **ppvObj )
  101. {
  102. SCODE sc = S_OK;
  103. if ( !ppvObj )
  104. return E_INVALIDARG;
  105. if ( riid == IID_IUnknown )
  106. {
  107. *ppvObj = (void *) ( (IUnknown *) (IDBInitialize *) this );
  108. }
  109. else if ( riid == IID_IDBInitialize )
  110. {
  111. *ppvObj = (void *) (IDBInitialize *) this;
  112. }
  113. else if ( riid == IID_IDBProperties )
  114. {
  115. *ppvObj = (void *) (IDBProperties *) this;
  116. }
  117. else if ( riid == IID_IPersist )
  118. {
  119. *ppvObj = (void *) (IPersist *) this;
  120. }
  121. else if ( riid == IID_IDBCreateSession )
  122. {
  123. //
  124. // The following interfaces are supported only if DSO is initialized
  125. //
  126. // Make sure we don't get uninitialized
  127. if ( _fDSOInitialized )
  128. {
  129. *ppvObj = (void *) (IDBCreateSession *) this;
  130. }
  131. else
  132. {
  133. *ppvObj = 0;
  134. sc = E_UNEXPECTED; // per OLE DB spec.
  135. }
  136. }
  137. else if ( riid == IID_IDBInfo )
  138. {
  139. *ppvObj = (void *) (IDBInfo *) this;
  140. }
  141. else if ( riid == IID_ISupportErrorInfo )
  142. {
  143. *ppvObj = (void *) ((IUnknown *) (ISupportErrorInfo *) &_ErrorInfo);
  144. }
  145. else
  146. {
  147. *ppvObj = 0;
  148. sc = E_NOINTERFACE;
  149. }
  150. return sc;
  151. } // QueryInterface
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Method: CDataSrc::Initialize
  155. //
  156. // Synopsis: changes the DSO state to Initialized.
  157. //
  158. // Arguments:
  159. //
  160. // History: 3-30-97 mohamedn Created
  161. //
  162. //----------------------------------------------------------------------------
  163. STDMETHODIMP CDataSrc::Initialize()
  164. {
  165. SCODE sc = S_OK;
  166. // Clear previous Error Object for this thread
  167. _ErrorInfo.ClearErrorInfo();
  168. TRANSLATE_EXCEPTIONS;
  169. TRY
  170. {
  171. CLock lck( _mtxDSO );
  172. if ( !_fDSOInitialized )
  173. {
  174. // Expose non-init propsets
  175. sc = _UtlProps.ExposeMaximalSets();
  176. if ( SUCCEEDED(sc) )
  177. {
  178. // Expose propinfo for non-init propsets
  179. _UtlPropInfo.ExposeMaximalSets();
  180. // OK, now we're initialized.
  181. _fDSOInitialized = TRUE;
  182. }
  183. else
  184. {
  185. THROW( CException(sc) );
  186. }
  187. }
  188. else
  189. {
  190. THROW( CException(DB_E_ALREADYINITIALIZED) );
  191. }
  192. }
  193. CATCH( CException, e )
  194. {
  195. sc = _ErrorInfo.PostHResult( e, IID_IDBInitialize );
  196. }
  197. END_CATCH;
  198. UNTRANSLATE_EXCEPTIONS;
  199. return sc;
  200. }
  201. //+---------------------------------------------------------------------------
  202. //
  203. // Method: CDataSrc::Uninitialize
  204. //
  205. // Synopsis: changes the DSO state to Uninitialized.
  206. //
  207. // Arguments:
  208. //
  209. // History: 3-30-97 mohamedn Created
  210. //
  211. //----------------------------------------------------------------------------
  212. STDMETHODIMP CDataSrc::Uninitialize()
  213. {
  214. SCODE sc = S_OK;
  215. // Clear previous Error Object for this thread
  216. _ErrorInfo.ClearErrorInfo();
  217. TRANSLATE_EXCEPTIONS;
  218. TRY
  219. {
  220. CLock lck( _mtxDSO );
  221. if ( 0 == _cSessionCount )
  222. {
  223. // Hide non-init propsets
  224. _UtlProps.ExposeMinimalSets();
  225. _UtlPropInfo.ExposeMinimalSets();
  226. // Mark DSO as uninitialized
  227. _fDSOInitialized = FALSE;
  228. }
  229. else
  230. {
  231. THROW( CException(DB_E_OBJECTOPEN) );
  232. }
  233. }
  234. CATCH( CException, e )
  235. {
  236. sc = _ErrorInfo.PostHResult( e, IID_IDBInitialize );
  237. }
  238. END_CATCH;
  239. UNTRANSLATE_EXCEPTIONS;
  240. return sc;
  241. }
  242. //+-------------------------------------------------------------------------
  243. //
  244. // Function: CDataSrc::GetProperties
  245. //
  246. // Synopsis: gets IDBProperties
  247. //
  248. // Arguments: [cPropertyIDSets] - number of desired property set IDs or 0
  249. // [pPropIDSets] - array of desired property set IDs or NULL
  250. // [pcPropertySets] - number of property sets returned
  251. // [prgPropertySets] - array of returned property sets
  252. //
  253. // Returns: SCODE - result code indicating error return status. One of
  254. // S_OK, DB_S_ERRORSOCCURRED, E_INVALIDARG.
  255. //
  256. // History: 3-30-97 mohamedn Created
  257. // 10-30-97 danleg Chaned to use the Monarch prop code
  258. //
  259. //--------------------------------------------------------------------------
  260. STDMETHODIMP CDataSrc::GetProperties
  261. (
  262. ULONG cPropertySets,
  263. const DBPROPIDSET rgPropertySets[],
  264. ULONG * pcProperties,
  265. DBPROPSET ** prgProperties
  266. )
  267. {
  268. SCODE sc = S_OK;
  269. // Clear previous Error Object for this thread
  270. _ErrorInfo.ClearErrorInfo();
  271. TRANSLATE_EXCEPTIONS;
  272. TRY
  273. {
  274. CLock lck( _mtxDSO );
  275. // Check Arguments
  276. _UtlProps.GetPropertiesArgChk( cPropertySets,
  277. rgPropertySets,
  278. pcProperties,
  279. prgProperties );
  280. // Note that CUtlProps knows about initialization,
  281. // so we don't have to here.
  282. sc = _UtlProps.GetProperties( cPropertySets,
  283. rgPropertySets,
  284. pcProperties,
  285. prgProperties );
  286. if ( FAILED(sc) )
  287. THROW( CException(sc) );
  288. }
  289. CATCH( CException, e )
  290. {
  291. sc = _ErrorInfo.PostHResult( e, IID_IDBProperties );
  292. }
  293. END_CATCH;
  294. UNTRANSLATE_EXCEPTIONS;
  295. return sc;
  296. }
  297. //+---------------------------------------------------------------------------
  298. //
  299. // Function: CDataSrc::SetProperties
  300. //
  301. // Synopsis: sets IDBProperties
  302. //
  303. // Arguments: [cPropertySets] - number of property sets
  304. // [rgPropertySets] - array of property sets
  305. //
  306. // Returns: SCODE - result code indicating error return status. One of
  307. // S_OK, DB_S_ERRORSOCCURRED, E_INVALIDARG.
  308. //
  309. // History: 03-30-97 mohamedn created
  310. // 10-30-97 danleg Changed to use Monarch's prop code
  311. //
  312. //----------------------------------------------------------------------------
  313. STDMETHODIMP CDataSrc::SetProperties
  314. (
  315. ULONG cPropertySets,
  316. DBPROPSET rgPropertySets[]
  317. )
  318. {
  319. // Clear previous Error Object for this thread
  320. _ErrorInfo.ClearErrorInfo();
  321. // Quick return if the Count of Properties is 0
  322. if( cPropertySets == 0 )
  323. return S_OK;
  324. SCODE sc = S_OK;
  325. TRANSLATE_EXCEPTIONS;
  326. TRY
  327. {
  328. XArray<DBPROPSET> xaDbPropSet;
  329. ULONG iNewSet, iSet, iProp;
  330. CLock lck( _mtxDSO );
  331. _UtlProps.SetPropertiesArgChk( cPropertySets, rgPropertySets );
  332. // We need to handle the DBINIT properties specially after being initialized.
  333. // - they should be treated as NOTSETTABLE at this point.
  334. if( _fDSOInitialized )
  335. {
  336. Win4Assert( cPropertySets );
  337. bool fFoundDBINIT = false;
  338. // Allocate a DBPROPSET structure of equal size
  339. xaDbPropSet.Init( cPropertySets );
  340. for( iNewSet=0,iSet=0; iSet<cPropertySets; iSet++ )
  341. {
  342. // Remove any DBPROPSET_DBINIT values and mark them all
  343. // as not settable
  344. if( rgPropertySets[iSet].guidPropertySet == DBPROPSET_DBINIT )
  345. {
  346. fFoundDBINIT = true;
  347. for(iProp=0; iProp<rgPropertySets[iSet].cProperties; iProp++)
  348. {
  349. rgPropertySets[iSet].rgProperties[iProp].dwStatus = DBPROPSTATUS_NOTSETTABLE;
  350. }
  351. }
  352. else
  353. {
  354. // If not DBPROPSET_DBINIT then copy the DBPROPSET values
  355. RtlCopyMemory( &(xaDbPropSet[iNewSet++]), &rgPropertySets[iSet], sizeof(DBPROPSET) );
  356. }
  357. }
  358. // If we have no propertyset to pass on to the property handler,
  359. // we can exit
  360. if( 0 == iNewSet )
  361. {
  362. sc = DB_E_ERRORSOCCURRED;
  363. }
  364. else
  365. {
  366. sc = _UtlProps.SetProperties( iNewSet, xaDbPropSet.GetPointer() );
  367. // If we have determined that one of the property sets was DBINIT, we may
  368. // need to fixup the returned hr value.
  369. if( fFoundDBINIT && (sc == S_OK) )
  370. sc = DB_S_ERRORSOCCURRED;
  371. }
  372. }
  373. else
  374. {
  375. // Note that CUtlProps knows about initialization, so we don't
  376. // have to here. This sets members _bstrCatalog and _bstrMachine
  377. // in CMDSProps
  378. sc = _UtlProps.SetProperties( cPropertySets, rgPropertySets );
  379. }
  380. if ( FAILED(sc) )
  381. THROW( CException(sc) );
  382. }
  383. CATCH( CException, e )
  384. {
  385. sc = _ErrorInfo.PostHResult( e, IID_IDBProperties );
  386. }
  387. END_CATCH;
  388. UNTRANSLATE_EXCEPTIONS;
  389. return sc;
  390. } // CDatasrc::SetProperties
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Function: CDataSrc::GetPropertyInfo
  394. //
  395. // Synopsis: sets IDBProperties
  396. //
  397. // Arguments: [cPropertyIDSets] - number of property sets
  398. // [rgPropertyIDSets] - array of property sets
  399. // [pcPropertyInfoSets] - count of properties returned
  400. // [prgPropertyInfoSets] - property information returned
  401. // [ppDescBuffer] - buffer for returned descriptions
  402. //
  403. // Returns:
  404. //
  405. // History: 10-28-97 danleg created from Monarch
  406. //
  407. //----------------------------------------------------------------------------
  408. STDMETHODIMP CDataSrc::GetPropertyInfo
  409. (
  410. ULONG cPropertyIDSets,
  411. const DBPROPIDSET rgPropertyIDSets[],
  412. ULONG * pcPropertyInfoSets,
  413. DBPROPINFOSET ** prgPropertyInfoSets,
  414. OLECHAR ** ppDescBuffer
  415. )
  416. {
  417. ULONG ul;
  418. ULONG cSpecialPropertySets = 0;
  419. // Clear previous Error Object for this thread
  420. _ErrorInfo.ClearErrorInfo();
  421. // Initialize
  422. if( pcPropertyInfoSets )
  423. *pcPropertyInfoSets = 0;
  424. if( prgPropertyInfoSets )
  425. *prgPropertyInfoSets = 0;
  426. if( ppDescBuffer )
  427. *ppDescBuffer = 0;
  428. // Check Arguments, on failure post HRESULT to error queue
  429. if( ((cPropertyIDSets > 0) && !rgPropertyIDSets ) ||
  430. !pcPropertyInfoSets || !prgPropertyInfoSets )
  431. return _ErrorInfo.PostHResult( E_INVALIDARG, IID_IDBProperties );
  432. // New argument check for > 1 cPropertyIDs and NULL pointer for
  433. // array of property ids.
  434. for(ul=0; ul<cPropertyIDSets; ul++)
  435. {
  436. if( rgPropertyIDSets[ul].cPropertyIDs &&
  437. !(rgPropertyIDSets[ul].rgPropertyIDs) )
  438. return _ErrorInfo.PostHResult( E_INVALIDARG, IID_IDBProperties );
  439. }
  440. //check the count of special propertySets
  441. for(ul=0; ul<cPropertyIDSets; ul++)
  442. {
  443. if( (rgPropertyIDSets[ul].guidPropertySet ==DBPROPSET_DATASOURCEALL) ||
  444. (rgPropertyIDSets[ul].guidPropertySet ==DBPROPSET_DATASOURCEINFOALL) ||
  445. (rgPropertyIDSets[ul].guidPropertySet ==DBPROPSET_DBINITALL) ||
  446. (rgPropertyIDSets[ul].guidPropertySet ==DBPROPSET_ROWSETALL) ||
  447. (rgPropertyIDSets[ul].guidPropertySet ==DBPROPSET_SESSIONALL) )
  448. cSpecialPropertySets++;
  449. }
  450. // if used SpecialPropertySets with non-special Propertysets
  451. if ((cSpecialPropertySets > 0) && (cSpecialPropertySets < cPropertyIDSets))
  452. {
  453. return _ErrorInfo.PostHResult( E_INVALIDARG, IID_IDBProperties );
  454. }
  455. SCODE sc = S_OK;
  456. TRANSLATE_EXCEPTIONS;
  457. TRY
  458. {
  459. CLock lck( _mtxDSO );
  460. sc = _UtlPropInfo.GetPropertyInfo( cPropertyIDSets,
  461. rgPropertyIDSets,
  462. pcPropertyInfoSets,
  463. prgPropertyInfoSets,
  464. ppDescBuffer );
  465. if ( FAILED(sc) )
  466. THROW( CException(sc) );
  467. }
  468. CATCH( CException, e )
  469. {
  470. sc = _ErrorInfo.PostHResult( e, IID_IDBProperties );
  471. }
  472. END_CATCH;
  473. UNTRANSLATE_EXCEPTIONS;
  474. return sc;
  475. }
  476. //+---------------------------------------------------------------------------
  477. //
  478. // Method: CDataSrc::CreateGlobalViews
  479. //
  480. // Synopsis: Creates global views (FILEINFO, WEBINFO etc.). These views
  481. // are removed when the IParser object goes away.
  482. //
  483. // Arguments:
  484. //
  485. // History: 01-09-98 danleg Created
  486. //
  487. //----------------------------------------------------------------------------
  488. void CDataSrc::CreateGlobalViews( IParserSession * pIPSession )
  489. {
  490. SCODE sc = S_OK;
  491. extern const LPWSTR s_pwszPredefinedViews;
  492. DBCOMMANDTREE * pDBCOMMANDTREE = 0;
  493. XInterface<IParserTreeProperties> xIPTProperties;
  494. LCID lcid = GetDSPropsPtr()->GetValLong( CMDSProps::eid_DBPROPSET_DBINIT,
  495. CMDSProps::eid_INIT_LCID );
  496. sc = pIPSession->ToTree( lcid,
  497. s_pwszPredefinedViews,
  498. &pDBCOMMANDTREE,
  499. xIPTProperties.GetPPointer() );
  500. if ( FAILED(sc) )
  501. THROW( CException(sc) );
  502. _fGlobalViewsCreated = TRUE;
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Method: CDataSrc::DupImpersonationToken, public
  507. //
  508. // Synopsis: Clients calling CreateSession can be impersonated. One such
  509. // client, SQL Server's Distributed Query Processor, stays
  510. // impersonated only for the duration of the call to CreateSession.
  511. //
  512. // This routine is called from CreateSession and caches the
  513. // impersonation token. This token is used to get back the security
  514. // context of the client during CreateCommand/OpenRowset.
  515. //
  516. // Arguments:
  517. //
  518. // History: 09-01-98 danleg Created
  519. //
  520. // Notes: Revisit if OLE DB defines "Integrated Security" differently in
  521. // the future, or defines a better security scheme.
  522. //
  523. //----------------------------------------------------------------------------
  524. void CDataSrc::DupImpersonationToken
  525. (
  526. HANDLE & hToken
  527. )
  528. {
  529. DWORD dwLength = 0;
  530. NTSTATUS status = STATUS_SUCCESS;
  531. TOKEN_STATISTICS TokenInformation;
  532. HANDLE hTempToken;
  533. status = NtOpenThreadToken( GetCurrentThread(),
  534. TOKEN_QUERY |
  535. TOKEN_DUPLICATE |
  536. TOKEN_IMPERSONATE,
  537. TRUE,
  538. &hTempToken );
  539. if ( !NT_SUCCESS(status) )
  540. {
  541. if ( STATUS_NO_TOKEN == status )
  542. {
  543. status = NtOpenProcessToken( GetCurrentProcess(),
  544. TOKEN_QUERY |
  545. TOKEN_DUPLICATE |
  546. TOKEN_IMPERSONATE,
  547. &hTempToken );
  548. }
  549. if ( !NT_SUCCESS(status) )
  550. {
  551. vqDebugOut(( DEB_ERROR,
  552. "DupImpersonationToken failed to get token, %x\n",
  553. status ));
  554. THROW( CException(status) );
  555. }
  556. }
  557. SHandle xHandle( hTempToken );
  558. HANDLE hNewToken = INVALID_HANDLE_VALUE;
  559. OBJECT_ATTRIBUTES ObjAttr;
  560. SECURITY_QUALITY_OF_SERVICE qos;
  561. qos.Length = sizeof( SECURITY_QUALITY_OF_SERVICE );
  562. qos.ImpersonationLevel = SecurityImpersonation;
  563. qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  564. qos.EffectiveOnly = FALSE;
  565. InitializeObjectAttributes( &ObjAttr,
  566. NULL,
  567. 0,
  568. NULL,
  569. NULL );
  570. ObjAttr.SecurityQualityOfService = &qos;
  571. status = NtDuplicateToken( hTempToken,
  572. TOKEN_IMPERSONATE |
  573. TOKEN_QUERY |
  574. TOKEN_DUPLICATE,
  575. &ObjAttr,
  576. FALSE,
  577. TokenImpersonation,
  578. &hNewToken );
  579. if ( !NT_SUCCESS(status) )
  580. {
  581. vqDebugOut(( DEB_ERROR,
  582. "DupImpersonationToken failed to duplicate token, %x\n",
  583. status ));
  584. THROW( CException(HRESULT_FROM_WIN32(status)) );
  585. }
  586. hToken = hNewToken;
  587. }
  588. //+---------------------------------------------------------------------------
  589. //
  590. // Method: CDataSrc::CreateSession
  591. //
  592. // Synopsis: Associates a session with the DSO.
  593. //
  594. // Arguments: [pUnkOuter] - controlling unknown
  595. // [riid] - interface requested
  596. // [ppDBSession] - contains returned interface pointer
  597. //
  598. // History: 3-30-97 mohamedn Created
  599. // 1-10-98 danleg Added global views
  600. //
  601. //----------------------------------------------------------------------------
  602. STDMETHODIMP CDataSrc::CreateSession( IUnknown * pUnkOuter,
  603. REFIID riid,
  604. IUnknown ** ppDBSession )
  605. {
  606. _ErrorInfo.ClearErrorInfo();
  607. if ( !ppDBSession )
  608. return _ErrorInfo.PostHResult( E_INVALIDARG, IID_IDBCreateSession );
  609. else
  610. *ppDBSession = 0;
  611. if ( !_fDSOInitialized )
  612. return _ErrorInfo.PostHResult( E_UNEXPECTED, IID_IDBCreateSession );
  613. if (0 != pUnkOuter && riid != IID_IUnknown)
  614. return _ErrorInfo.PostHResult( DB_E_NOAGGREGATION, IID_IDBCreateSession );
  615. SCODE sc = S_OK;
  616. HANDLE hToken = INVALID_HANDLE_VALUE;
  617. TRANSLATE_EXCEPTIONS;
  618. TRY
  619. {
  620. XInterface<IColumnMapperCreator> xColMapCreator;
  621. XInterface<IParserSession> xIPSession;
  622. CLock lck( _mtxDSO );
  623. DupImpersonationToken( hToken );
  624. //
  625. // Service Components set DBPROP_RESETDATASOURCE to indicate that the DSO has been
  626. // pooled. We need to reset the IParser object because it maintains state valid
  627. // across sessions (eg. views)
  628. //
  629. LONG lResetVal = _UtlProps.GetValLong( CMDSProps::eid_DBPROPSET_DATASOURCE,
  630. CMDSProps::eid_DBPROPVAL_RESETDATASOURCE);
  631. if ( DBPROPVAL_RD_RESETALL == lResetVal )
  632. {
  633. // make sure there aren't any outstanding sessions when doing this.
  634. if ( 0 != _cSessionCount )
  635. THROW( CException( E_INVALIDARG ) );
  636. _xIParser.Free();
  637. sc = MakeIParser( _xIParser.GetPPointer() );
  638. if ( FAILED(sc) )
  639. THROW( CException(sc) );
  640. _UtlProps.SetValLong( CMDSProps::eid_DBPROPSET_DATASOURCE,
  641. CMDSProps::eid_DBPROPVAL_RESETDATASOURCE,
  642. 0L );
  643. }
  644. //
  645. // Create an IParserSession object to pass to the session
  646. //
  647. _xIPVerify->GetColMapCreator( xColMapCreator.GetPPointer() );
  648. sc = _xIParser->CreateSession( &DBGUID_MSSQLTEXT,
  649. GetDSPropsPtr()->GetValString(
  650. CMDSProps::eid_DBPROPSET_DBINIT,
  651. CMDSProps::eid_DBPROPVAL_INIT_LOCATION),
  652. _xIPVerify.GetPointer(),
  653. xColMapCreator.GetPointer(),
  654. xIPSession.GetPPointer() );
  655. if ( FAILED(sc) )
  656. THROW( CException(sc) );
  657. LPCWSTR pwszCatalog = 0;
  658. pwszCatalog = GetDSPropsPtr()->GetValString(
  659. CMDSProps::eid_DBPROPSET_DATASOURCE,
  660. CMDSProps::eid_DBPROPVAL_CURRENTCATALOG);
  661. sc = xIPSession->SetCatalog( pwszCatalog );
  662. if( FAILED(sc) )
  663. THROW( CException(sc) );
  664. //
  665. // Predefined views -- only once per DSO
  666. //
  667. if ( !_fGlobalViewsCreated )
  668. CreateGlobalViews( xIPSession.GetPointer() );
  669. //
  670. // Create the session object
  671. //
  672. XInterface<IUnknown> xUnkInner;
  673. CDBSession *pDBSession = new CDBSession( *this,
  674. pUnkOuter,
  675. xUnkInner.GetPPointer(),
  676. xIPSession.GetPointer(),
  677. hToken );
  678. // NOTE: pDBSession is the same object as xUnkInner.
  679. sc = xUnkInner->QueryInterface( riid, (void **) ppDBSession );
  680. if ( FAILED(sc) )
  681. THROW( CException(sc) );
  682. }
  683. CATCH(CException, e)
  684. {
  685. sc = _ErrorInfo.PostHResult( e, IID_IDBCreateSession );
  686. }
  687. END_CATCH;
  688. UNTRANSLATE_EXCEPTIONS;
  689. return sc;
  690. }
  691. //+---------------------------------------------------------------------------
  692. //
  693. // Method: CDataSrc::GetClassID
  694. //
  695. // Synopsis: Return the CLSID for this server object
  696. //
  697. // Arguments: [pClassID]
  698. //
  699. // History: 3-30-97 mohamedn Created
  700. // 10-28-97 danleg added _ErrorInfo
  701. //
  702. //----------------------------------------------------------------------------
  703. STDMETHODIMP CDataSrc::GetClassID ( CLSID *pClassID )
  704. {
  705. _ErrorInfo.ClearErrorInfo();
  706. if (pClassID)
  707. {
  708. RtlCopyMemory( pClassID, &CLSID_CiFwDSO, sizeof(CLSID) );
  709. return S_OK;
  710. }
  711. else
  712. return _ErrorInfo.PostHResult( E_FAIL, IID_IPersist );
  713. }
  714. //============================================================================
  715. // LITERAL INFO Constants
  716. //============================================================================
  717. // The following are constants that define literals that don't change.. When the buffer
  718. // to return literal information is allocated, it is initialized with this string and
  719. // then when a particular literal is asked for; a pointer in these values is used.
  720. static const LPWSTR LIT_BUFFER = L"\"\0.\0%\0_\0[]\0[]\0";
  721. static const ULONG LIT_QUOTE_VALID_OFFSET = 0;
  722. static const ULONG LIT_CATALOG_SEP_VALID_OFFSET = LIT_QUOTE_VALID_OFFSET + NUMELEM(L"\"");
  723. static const ULONG LIT_PERCENT_VALID_OFFSET = LIT_CATALOG_SEP_VALID_OFFSET + NUMELEM(L".");
  724. static const ULONG LIT_UNDERSCORE_VALID_OFFSET = LIT_PERCENT_VALID_OFFSET + NUMELEM(L"%");
  725. static const ULONG LIT_ESCAPE_PERCENT_OFFSET = LIT_UNDERSCORE_VALID_OFFSET + NUMELEM(L"_");
  726. static const ULONG LIT_ESCAPE_UNDERSCORE_OFFSET = LIT_ESCAPE_PERCENT_OFFSET + NUMELEM(L"[]");
  727. static const ULONG LIT_CCH_INITIAL_BUFFER = LIT_ESCAPE_UNDERSCORE_OFFSET + NUMELEM(L"[]");
  728. static const ULONG LIT_CB_INITIAL_BUFFER = LIT_CCH_INITIAL_BUFFER * sizeof(WCHAR);
  729. // List of unique Keywords that OLE DB does not define.
  730. static const WCHAR s_pwszKeyWords[] = {L"ARRAY,COERCE,CONTAINS,DEEP,DERIVATIONAL,"
  731. L"EXCLUDE,FORMSOF,FREETEXT,INFLECTIONAL,"
  732. L"ISABOUT,MATCHES,NEAR,PARAGRAPH,PASSTHROUGH,"
  733. L"PROPERTYNAME,PROPID,RANKMETHOD,SENTENCE,"
  734. L"SCOPE,SEARCH,SHALLOW,SOUNDEX,THESAURUS,"
  735. L"TRAVERSAL,TYPE,WEIGHT,WORD"};
  736. //+---------------------------------------------------------------------------
  737. //
  738. // Function: CDataSrc::GetKeywords
  739. //
  740. // Synopsis: returns a list of provider specific keywords
  741. //
  742. // Arguments: [ppwszKeywords] - string containing returned list of comma
  743. // separated keywords
  744. //
  745. // Returns: HRESULT indicating the status of the method
  746. // S_OK | Keyword list retrieved
  747. // E_FAIL | Provider specific error (ODBC call failed)
  748. // E_OUTOFMEMORY | Buffer could not be allocated for the keywords.
  749. // E_INVALIDARG | Arguments did not match specification
  750. //
  751. // History: 09-05-97 danleg created from Monarch project
  752. //
  753. //----------------------------------------------------------------------------
  754. STDMETHODIMP CDataSrc::GetKeywords(LPOLESTR* ppwszKeywords)
  755. {
  756. SCODE sc = S_OK;
  757. // Clear previous Error Object for this thread
  758. _ErrorInfo.ClearErrorInfo();
  759. TRANSLATE_EXCEPTIONS;
  760. TRY
  761. {
  762. CLock lck( _mtxDSO );
  763. // Check arguments
  764. if( ppwszKeywords )
  765. {
  766. *ppwszKeywords = 0;
  767. // Check that object is initialized
  768. if( _fDSOInitialized )
  769. {
  770. XArrayOLE<WCHAR> xpwszKeyWords( NUMELEM(s_pwszKeyWords) );
  771. RtlCopyMemory( xpwszKeyWords.GetPointer(),
  772. s_pwszKeyWords,
  773. sizeof(s_pwszKeyWords) );
  774. *ppwszKeywords = xpwszKeyWords.Acquire();
  775. }
  776. else
  777. {
  778. vqDebugOut(( DEB_TRACE, "Initialization must occur before IDBInfo can be called\n" ));
  779. sc = E_UNEXPECTED;
  780. }
  781. }
  782. else
  783. {
  784. sc = E_INVALIDARG;
  785. }
  786. if ( FAILED(sc) )
  787. THROW( CException(sc) );
  788. }
  789. CATCH( CException, e )
  790. {
  791. sc = _ErrorInfo.PostHResult( e, IID_IDBInfo );
  792. }
  793. END_CATCH;
  794. UNTRANSLATE_EXCEPTIONS;
  795. return sc;
  796. }
  797. //+---------------------------------------------------------------------------
  798. //
  799. // Function: CDataSrc::GetLiteralInfo
  800. //
  801. // Synopsis: Retreives information about literals. Their length, and special
  802. // characters and whether they are actually supported.
  803. //
  804. // Arguments: [cLiterals] - Number of literals being asked about
  805. // [rgLiterals] - Array of literals being asked about
  806. // [pcLiteralInfo] - Contains returned number of literals
  807. // [prgLiteralInfo] - Contains returned literal information
  808. // [ppCharBuffer] - Buffer for returned string values
  809. //
  810. // Returns: HRESULT indicating the status of the method
  811. // S_OK | Keyword list retrieved
  812. // E_FAIL | Provider specific error (ODBC call failed)
  813. // E_OUTOFMEMORY | Buffer could not be allocated for the keywords.
  814. // E_INVALIDARG | Arguments did not match specification
  815. //
  816. // History: 09-05-97 danleg created from Monarch project
  817. //
  818. //----------------------------------------------------------------------------
  819. STDMETHODIMP CDataSrc::GetLiteralInfo
  820. (
  821. ULONG cLiterals,
  822. const DBLITERAL rgLiterals[],
  823. ULONG* pcLiteralInfo,
  824. DBLITERALINFO** prgLiteralInfo,
  825. OLECHAR** ppCharBuffer
  826. )
  827. {
  828. SCODE sc = S_OK;
  829. const DWORD LITERAL_NORESTRICTIONS = 0x00000001;
  830. const DWORD LITERAL_FAILURE = 0x00000002;
  831. const DWORD LITERAL_SUCCESS = 0x00000004;
  832. const static DBLITERAL s_rgSupportedLiterals[] = {
  833. DBLITERAL_BINARY_LITERAL, DBLITERAL_CATALOG_NAME, DBLITERAL_CATALOG_SEPARATOR,
  834. DBLITERAL_CHAR_LITERAL, DBLITERAL_COLUMN_NAME, DBLITERAL_CORRELATION_NAME,
  835. DBLITERAL_ESCAPE_PERCENT, DBLITERAL_ESCAPE_UNDERSCORE,
  836. DBLITERAL_LIKE_PERCENT, DBLITERAL_LIKE_UNDERSCORE, DBLITERAL_TABLE_NAME,
  837. DBLITERAL_TEXT_COMMAND, DBLITERAL_VIEW_NAME, DBLITERAL_QUOTE_PREFIX,
  838. DBLITERAL_QUOTE_SUFFIX
  839. };
  840. // Clear previous Error Object for this thread
  841. _ErrorInfo.ClearErrorInfo();
  842. // Initialize
  843. if( pcLiteralInfo )
  844. *pcLiteralInfo = 0;
  845. if( prgLiteralInfo )
  846. *prgLiteralInfo = 0;
  847. if( ppCharBuffer )
  848. *ppCharBuffer = 0;
  849. // Check Arguments
  850. if( ((cLiterals > 0) && !rgLiterals) ||
  851. !pcLiteralInfo ||
  852. !ppCharBuffer ||
  853. !prgLiteralInfo )
  854. {
  855. return _ErrorInfo.PostHResult( E_INVALIDARG, IID_IDBInfo );
  856. }
  857. TRANSLATE_EXCEPTIONS;
  858. TRY
  859. {
  860. ULONG ulDex,
  861. ulNew;
  862. DWORD dwStatus = 0;
  863. DBLITERALINFO* pdbLitInfo;
  864. CLock lck( _mtxDSO );
  865. // We must be initialized
  866. if( !_fDSOInitialized )
  867. {
  868. vqDebugOut(( DEB_TRACE, "Initialization must occur before IDBInfo can be called\n" ));
  869. return _ErrorInfo.PostHResult( E_UNEXPECTED, IID_IDBInfo );
  870. }
  871. // Allocate Memory for literal information
  872. if( cLiterals == 0 )
  873. {
  874. dwStatus |= LITERAL_NORESTRICTIONS;
  875. cLiterals = NUMELEM( s_rgSupportedLiterals );
  876. rgLiterals = s_rgSupportedLiterals;
  877. }
  878. XArrayOLE<DBLITERALINFO> xaLiteralInfo( cLiterals );
  879. XArrayOLE<WCHAR> xaCharBuffer( LIT_CCH_INITIAL_BUFFER );
  880. // Initialize the first part of the buffer with our
  881. // static set of literal information
  882. RtlCopyMemory( xaCharBuffer.GetPointer(), LIT_BUFFER, LIT_CB_INITIAL_BUFFER );
  883. // Process each of the DBLITERAL values that are in the
  884. // restriction array or that we potentially could support
  885. for(ulDex=0, ulNew=0; ulDex<cLiterals; ulDex++)
  886. {
  887. pdbLitInfo = &(xaLiteralInfo[ulNew]);
  888. pdbLitInfo->lt = rgLiterals[ulDex];
  889. pdbLitInfo->fSupported = TRUE;
  890. pdbLitInfo->pwszLiteralValue = 0;
  891. pdbLitInfo->pwszInvalidChars = 0;
  892. pdbLitInfo->pwszInvalidStartingChars = 0;
  893. switch( rgLiterals[ulDex] )
  894. {
  895. case DBLITERAL_TEXT_COMMAND:
  896. case DBLITERAL_CHAR_LITERAL:
  897. case DBLITERAL_BINARY_LITERAL:
  898. case DBLITERAL_TABLE_NAME:
  899. pdbLitInfo->cchMaxLen = ~0;
  900. break;
  901. case DBLITERAL_CATALOG_NAME:
  902. case DBLITERAL_COLUMN_NAME:
  903. case DBLITERAL_CORRELATION_NAME:
  904. case DBLITERAL_VIEW_NAME:
  905. pdbLitInfo->cchMaxLen = 128;
  906. break;
  907. case DBLITERAL_CATALOG_SEPARATOR:
  908. pdbLitInfo->cchMaxLen = 1; // L'.';
  909. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_CATALOG_SEP_VALID_OFFSET;
  910. break;
  911. case DBLITERAL_ESCAPE_PERCENT:
  912. pdbLitInfo->cchMaxLen = 2; // L"[]";
  913. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_ESCAPE_PERCENT_OFFSET;
  914. break;
  915. case DBLITERAL_ESCAPE_UNDERSCORE:
  916. pdbLitInfo->cchMaxLen = 2; // L"[]";
  917. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_ESCAPE_UNDERSCORE_OFFSET;
  918. break;
  919. case DBLITERAL_LIKE_PERCENT:
  920. pdbLitInfo->cchMaxLen = 1; // L'%';
  921. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_PERCENT_VALID_OFFSET;
  922. break;
  923. case DBLITERAL_LIKE_UNDERSCORE:
  924. pdbLitInfo->cchMaxLen = 1; // L'_';
  925. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_UNDERSCORE_VALID_OFFSET;
  926. break;
  927. case DBLITERAL_QUOTE_PREFIX:
  928. case DBLITERAL_QUOTE_SUFFIX:
  929. pdbLitInfo->cchMaxLen = 1; // L'"';
  930. pdbLitInfo->pwszLiteralValue = xaCharBuffer.GetPointer() + LIT_QUOTE_VALID_OFFSET;
  931. break;
  932. default:
  933. pdbLitInfo->cchMaxLen = 0;
  934. // If we are given a dbLiteral that we do not
  935. // support, just set the fSupport flag false
  936. // and continue on.
  937. pdbLitInfo->fSupported = FALSE;
  938. break;
  939. }
  940. // If we are returning all the supported literals, then
  941. // we need to drop any that are fSupported = FALSE;
  942. if( dwStatus & LITERAL_NORESTRICTIONS )
  943. {
  944. if( pdbLitInfo->fSupported == FALSE )
  945. continue;
  946. }
  947. else
  948. {
  949. if( pdbLitInfo->fSupported == FALSE )
  950. dwStatus |= LITERAL_FAILURE;
  951. else
  952. dwStatus |= LITERAL_SUCCESS;
  953. }
  954. ulNew++;
  955. }
  956. sc = (dwStatus & LITERAL_FAILURE) ?
  957. ((dwStatus & LITERAL_SUCCESS) ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED) :
  958. S_OK;
  959. *pcLiteralInfo = ulNew;
  960. // We only want to return the string buffer if it
  961. // is a success
  962. if ( SUCCEEDED(sc) )
  963. *ppCharBuffer = xaCharBuffer.Acquire();
  964. // We want to return the LiteralInfo on success and on
  965. // a DB_E_ERRORSOCCURRED failure
  966. if ( SUCCEEDED(sc) || (sc == DB_E_ERRORSOCCURRED) )
  967. *prgLiteralInfo = xaLiteralInfo.Acquire();
  968. if ( FAILED(sc) )
  969. THROW( CException(sc) );
  970. }
  971. CATCH( CException, e )
  972. {
  973. sc = _ErrorInfo.PostHResult( e, IID_IDBInfo );
  974. }
  975. END_CATCH;
  976. UNTRANSLATE_EXCEPTIONS;
  977. return sc;
  978. }