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.

637 lines
17 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: CRSInfo.cxx
  7. //
  8. // Contents: IRowsetInfo and IGetRow methods
  9. //
  10. // Functions:
  11. //
  12. // Notes:
  13. //
  14. //
  15. // History: 08/30/96 | RenatoB | Created
  16. //----------------------------------------------------------------------------
  17. //-----------------------------------------------------------------------------
  18. // @class CRowsetInfo | embedding of Rowset,
  19. // to give our IrowsetInfo interface
  20. //
  21. //
  22. //-----------------------------------------------------------------------------
  23. // Includes
  24. #include "oleds.hxx"
  25. #include "atl.h"
  26. #include "row.hxx"
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: CRowsetInfo::QueryInterface
  30. //
  31. // Synopsis: @mfunc QueryInterface.
  32. //
  33. // Update: This function should never be called as RowsetInfo is now contained
  34. // in CRowset.
  35. //
  36. //-----------------------------------------------------------------------.
  37. HRESULT
  38. CRowsetInfo::QueryInterface(
  39. REFIID riid,
  40. LPVOID * ppv
  41. )
  42. {
  43. ADsAssert(FALSE);
  44. RRETURN( E_INVALIDARG );
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Function: CRowsetInfo::CRowsetInfo
  49. //
  50. // Synopsis: @mfunc Ctor
  51. //
  52. // Arguments:
  53. //
  54. //
  55. // Returns: @rdesc NONE
  56. //
  57. // Modifies:
  58. //
  59. // History: 08/30/96 RenatoB Created
  60. //
  61. //----------------------------------------------------------------------------
  62. CRowsetInfo::CRowsetInfo(
  63. IUnknown * pUnkOuter, // controlling unknown)
  64. IUnknown * pParentObject, // RowProvider
  65. CSessionObject * pCSession, // Session that created rowset
  66. CCommandObject * pCCommand, // Command object that created rowset
  67. CRowProvider * pRowProvider // Row provider pointer
  68. )
  69. {
  70. //
  71. // Asserts
  72. //
  73. ADsAssert(pRowProvider);
  74. _pUnkOuter = (pUnkOuter == NULL) ? (IRowsetInfo FAR *)this : pUnkOuter;
  75. _pRowset = NULL;
  76. _pParentObject = pParentObject;
  77. _pCSession = pCSession;
  78. _pCCommand = pCCommand;
  79. // AddRef twice - once for command/session object, once for parent object
  80. if( NULL == _pCCommand )
  81. {
  82. _pCSession->AddRef();
  83. _pCSession->AddRef();
  84. }
  85. else if( NULL == _pCSession )
  86. {
  87. _pCCommand->AddRef();
  88. _pCCommand->AddRef();
  89. }
  90. else // shouldn't get here
  91. ADsAssert(FALSE);
  92. _pRowProvider = pRowProvider;
  93. _pRowProvider->AddRef();
  94. _pMalloc = NULL;
  95. if( _pCCommand != NULL )
  96. _pCCommand->IncrementOpenRowsets();
  97. //this section is for IRowsetInfo and IUnknown methods.
  98. InitializeCriticalSection(&_csRowsetInfo);
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Function: CRowsetInfo::~CRowsetInfo
  103. //
  104. // Synopsis: @mfunc Dtor
  105. //
  106. // Arguments:
  107. //
  108. //
  109. // Returns: @rdesc NONE
  110. //
  111. // Modifies:
  112. //
  113. // History: 08/30/96 RenatoB Created
  114. //
  115. //----------------------------------------------------------------------------
  116. CRowsetInfo::~CRowsetInfo()
  117. {
  118. if( _pMalloc != NULL )
  119. _pMalloc->Release();
  120. if( _pCCommand != NULL ) {
  121. _pCCommand->DecrementOpenRowsets();
  122. _pCCommand->Release();
  123. }
  124. if( _pCSession != NULL ) {
  125. _pCSession->Release();
  126. }
  127. if( _pParentObject != NULL ) {
  128. _pParentObject->Release();
  129. }
  130. if( _pRowProvider != NULL ) {
  131. _pRowProvider->Release();
  132. }
  133. DeleteCriticalSection(&_csRowsetInfo);
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // Function: CRowsetInfo::FInit
  138. //
  139. // Synopsis: @mfunc Initializer
  140. //
  141. // Synopsis: @mfunc Initializer
  142. //
  143. // Arguments:
  144. //
  145. //
  146. // Returns: @rdesc NONE
  147. // @flag S_OK | Interface is supported
  148. // @flag E_OUTOFMEMORY | Not enough memory
  149. // @flag E_INVALIDARG | One or more arguments are invalid.
  150. //
  151. // Modifies:
  152. //
  153. // History: 08/30/96 RenatoB Created
  154. //
  155. //----------------------------------------------------------------------------
  156. HRESULT
  157. CRowsetInfo::FInit(
  158. IUnknown * pRowset) // rowset interface
  159. {
  160. HRESULT hr;
  161. hr = S_OK;
  162. if( FAILED(CoGetMalloc(MEMCTX_TASK, &_pMalloc)) )
  163. RRETURN( E_OUTOFMEMORY );
  164. // Should not AddRef here because RowsetInfo is contained in CRowset
  165. _pRowset = pRowset;
  166. RRETURN( hr );
  167. }
  168. //+---------------------------------------------------------------------------
  169. //
  170. // Function: CRowsetInfo::GetReferencedRowset
  171. //
  172. // Synopsis: @mfunc Returns an interface pointer to the rowset to which a bookmark applies
  173. //
  174. // Called by: Client
  175. // Called when: Any time
  176. //
  177. // Arguments:
  178. // iOrdinal [in] Bookmark column for which to get related rowset. Must be 0 in this impl.
  179. // riid [in] IID of the interface pointer to return in *ppReferencedRowset.
  180. // ppReferencedRowset[out] pointer to Rowset object referenced by Bookmark
  181. //
  182. //
  183. // Returns: @rdesc NONE
  184. // S_OK | Interface is supported
  185. // E_INVALIDARG | ppReferencedRowset was a NULL pointer
  186. // E_FAIL | provider specific error
  187. // E_NOINTERFACE | Rowset does not support interface
  188. // DB_E_NOTAREFENCEDCOLUMN | iOrdinal was not 0
  189. //
  190. //----------------------------------------------------------------------------
  191. HRESULT
  192. CRowsetInfo::GetReferencedRowset(
  193. DBORDINAL iOrdinal,
  194. REFIID riid,
  195. IUnknown ** ppReferencedRowset
  196. )
  197. {
  198. CAutoBlock cab (&_csRowsetInfo);
  199. //
  200. // Asserts
  201. //
  202. ADsAssert(_pRowProvider);
  203. ADsAssert(_pRowset);
  204. if( ppReferencedRowset == NULL )
  205. RRETURN( E_INVALIDARG );
  206. *ppReferencedRowset = NULL;
  207. if( iOrdinal >= _pRowProvider->GetColumnCount() )
  208. RRETURN( DB_E_BADORDINAL );
  209. if( iOrdinal != 0 )
  210. RRETURN( DB_E_NOTAREFERENCECOLUMN );
  211. RRETURN(_pRowset->QueryInterface(
  212. riid,
  213. (void**)ppReferencedRowset)
  214. );
  215. };
  216. //+---------------------------------------------------------------------------
  217. //
  218. // Function: CRowsetInfo::GetSpecificaton
  219. //
  220. // Synopsis: @mfunc Returns an interface pointer to the command that created the rowset
  221. //
  222. // Called by: Client
  223. // Called when: Any time
  224. //
  225. // Arguments:
  226. // riid [in] IID of the interface pointer to return in *ppSpecification.
  227. // ppSpecification [out] pointer to command
  228. //
  229. //
  230. // Returns: @rdesc NONE
  231. // S_OK | Interface is supported
  232. // E_INVALIDARG | ppSpecification was a NULL pointer
  233. // E_FAIL | provider specific error
  234. // E_NOINTERFACE | Command does not support interface
  235. // S_FALSE | Rowset does not have command that created it
  236. //----------------------------------------------------------------------------
  237. HRESULT
  238. CRowsetInfo::GetSpecification(
  239. REFIID riid,
  240. IUnknown ** ppSpecification
  241. )
  242. {
  243. CAutoBlock cab(&_csRowsetInfo);
  244. if( ppSpecification == NULL )
  245. RRETURN( E_INVALIDARG );
  246. *ppSpecification = NULL;
  247. if( _pParentObject == NULL )
  248. RRETURN( S_FALSE );
  249. RRETURN( _pParentObject->QueryInterface(riid, (void**)ppSpecification) );
  250. };
  251. //+---------------------------------------------------------------------------
  252. //
  253. // Function: CRowsetInfo::GetProperties
  254. //
  255. // Synopsis: @mfunc GetProperties
  256. // Called by: Client.
  257. // Called when: Any time.
  258. //
  259. // Arguments:
  260. // cPropertyIDSets[in] The number of DBPROPIDSET structures in rgProperttySets
  261. // rgPropertyIDSets[in] Array of cPropertyIDSets of DBPROIDSET structs.
  262. // pcPropertySets[out] number of DBPROPSET returned in *prgPropertySets
  263. // prgPropertySets[out] pointer to array of DBPROPSET structures, having the
  264. // value and status of requested properties
  265. //
  266. // Returns: @rdesc HRESULT
  267. // S_OK Success
  268. // DB_S_ERRORSOCCURRED Values were not supported for some properties
  269. // E_FAIL A provider-specific error occurred
  270. // E_INVALIDARG cPropertyIDSets > 0 and rgPropertyIdSEts = NULL
  271. // pcPropertySets or prgPropertySets was NULL pointer
  272. // In al element of rgPropertyIDSets, cPropertyIDs was not zero
  273. // and rgPropertyIDs was a Null pointer
  274. // E_OUTOFMEMORY Provider could not allocate memory
  275. // DB_E_ERRORSOCCURRED Values were not returned for any properties
  276. //-----------------------------------------------------------------------.
  277. HRESULT
  278. CRowsetInfo::GetProperties(
  279. const ULONG cPropertyIDSets,
  280. const DBPROPIDSET rgPropertyIDSets[],
  281. ULONG * pcPropertySets,
  282. DBPROPSET ** prgPropertySets
  283. )
  284. {
  285. // should never get here because this call is handled by CRowset
  286. ADsAssert(FALSE);
  287. RRETURN( E_FAIL );
  288. };
  289. //+---------------------------------------------------------------------------
  290. //
  291. // Function: CRowsetInfo::GetRowFromHROW
  292. //
  293. // Synopsis: @mfunc Returns an interface pointer to a row in the rowset.
  294. //
  295. // Called by: Client
  296. // Called when: Any time
  297. //
  298. // Arguments:
  299. // IUnknown *pUnkOuter Outer unknown.
  300. // HROW hRow Handle to row.
  301. // REFIID riid, Interface requested.
  302. // [out]IUnknown **ppUnk returned interface
  303. //
  304. //
  305. // Returns: HRESULT
  306. //----------------------------------------------------------------------------
  307. HRESULT
  308. CRowsetInfo::GetRowFromHROW(
  309. IUnknown *pUnkOuter,
  310. HROW hRow,
  311. REFIID riid,
  312. IUnknown * *ppUnk,
  313. BOOL fIsTearOff,
  314. BOOL fAllAttrs
  315. )
  316. {
  317. #if (!defined(BUILD_FOR_NT40))
  318. HRESULT hr = S_OK;
  319. CAutoBlock cab(&_csRowsetInfo);
  320. auto_tm<WCHAR> lpwszURL;
  321. auto_rel<IGetDataSource> pGetDataSource;
  322. auto_rel<ICommand> pCommand;
  323. auto_rel<IRowset> pRowset;
  324. auto_rel<IRowset> pRealRowset;
  325. CComObject<CRow> *pRow = NULL;
  326. auto_rel<IRow> pRowDelete;
  327. CCredentials creds;
  328. CCredentials *pCreds;
  329. PWSTR pwszUserID = NULL, pwszPassword = NULL;
  330. //Initialize return arguments
  331. if (ppUnk)
  332. *ppUnk = NULL;
  333. //We currently don't support aggregation.
  334. if (pUnkOuter != NULL)
  335. RRETURN(DB_E_NOAGGREGATION);
  336. if (ppUnk == NULL)
  337. RRETURN(E_INVALIDARG);
  338. if ( _pParentObject == NULL)
  339. RRETURN(S_FALSE);
  340. TRYBLOCK
  341. PWSTR pURL;
  342. ADsAssert(_pRowset != NULL);
  343. hr = _pRowset->QueryInterface(__uuidof(IRowset), (void **)&pRealRowset);
  344. BAIL_ON_FAILURE(hr);
  345. hr = _pRowProvider->GetURLFromHROW( hRow,&pURL, pRealRowset);
  346. BAIL_ON_FAILURE(hr);
  347. //assign returned ptr to auto_tm class for auto deletion.
  348. lpwszURL = pURL;
  349. *ppUnk = NULL;
  350. //
  351. // Get the session and QI for any mandatory interface -
  352. // we query for IGetDataSource.
  353. //
  354. hr = _pParentObject->QueryInterface(
  355. IID_IGetDataSource,
  356. (void**)&pGetDataSource);
  357. if (FAILED(hr))
  358. {
  359. hr = _pParentObject->QueryInterface(
  360. IID_ICommand,
  361. (void**)&pCommand);
  362. BAIL_ON_FAILURE(hr);
  363. hr = pCommand->GetDBSession (
  364. IID_IGetDataSource,
  365. (LPUNKNOWN *)&pGetDataSource);
  366. BAIL_ON_FAILURE(hr);
  367. }
  368. //Get user id and password properties for authentication
  369. //If the RowProvider has cached special credentials, we use them,
  370. //Otherwise we use the DBPROP_AUTH_USERID and DBPROP_AUTH_PASSWORD
  371. //properties in the originating DataSource object.
  372. if ((pCreds = _pRowProvider->GetCredentials()) == NULL)
  373. {
  374. hr = GetCredentials(pGetDataSource, creds);
  375. BAIL_ON_FAILURE(hr);
  376. pCreds = &creds;
  377. }
  378. hr = pCreds->GetUserName(&pwszUserID);
  379. BAIL_ON_FAILURE(hr);
  380. hr = pCreds->GetPassword(&pwszPassword);
  381. BAIL_ON_FAILURE(hr);
  382. //Instantiate a row object.
  383. hr = CComObject<CRow>::CreateInstance(&pRow);
  384. if (FAILED(hr))
  385. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  386. //To make sure we delete the row object in case
  387. //we encounter errors after this point.
  388. pRow->AddRef();
  389. pRowDelete = pRow;
  390. //Initialize the row object.
  391. hr = pRow->Initialize( lpwszURL,
  392. (IUnknown *)pGetDataSource,
  393. (IUnknown *)_pRowset,
  394. hRow,
  395. pwszUserID,
  396. pwszPassword,
  397. DBBINDURLFLAG_READ, //we are currently a read-only provider.
  398. fIsTearOff, // see comment at beginning of row.cxx
  399. !fAllAttrs, // see comment at beginning of row.cxx
  400. _pRowProvider
  401. );
  402. if (FAILED(hr))
  403. {
  404. if (INVALID_CREDENTIALS_ERROR(hr))
  405. {
  406. BAIL_ON_FAILURE(hr = DB_SEC_E_PERMISSIONDENIED);
  407. }
  408. else if (hr == E_NOINTERFACE)
  409. {
  410. BAIL_ON_FAILURE(hr);
  411. }
  412. else
  413. {
  414. BAIL_ON_FAILURE(hr = DB_E_NOTFOUND);
  415. }
  416. }
  417. //Get the requested interface on the Row.
  418. hr = pRow->QueryInterface(riid, (void**)ppUnk);
  419. if (FAILED(hr))
  420. BAIL_ON_FAILURE(hr = E_NOINTERFACE);
  421. CATCHBLOCKBAIL(hr)
  422. if (pwszUserID)
  423. FreeADsStr(pwszUserID);
  424. if (pwszPassword)
  425. FreeADsStr(pwszPassword);
  426. RRETURN(S_OK);
  427. error:
  428. if (pwszUserID)
  429. FreeADsStr(pwszUserID);
  430. if (pwszPassword)
  431. FreeADsStr(pwszPassword);
  432. RRETURN(hr);
  433. #else
  434. RRETURN(E_FAIL);
  435. #endif
  436. }
  437. //+---------------------------------------------------------------------------
  438. //
  439. // Function: CRowsetInfo::GetURLFromHROW
  440. //
  441. // Synopsis: @mfunc Returns an interface pointer to a row in the rowset.
  442. //
  443. // Called by: Client
  444. // Called when: Any time
  445. //
  446. // Arguments:
  447. // HROW hRow Handle to row.
  448. // LPOLESTR ppwszURL, URL name for the row.
  449. //
  450. //
  451. // Returns: HRESULT
  452. //----------------------------------------------------------------------------
  453. HRESULT
  454. CRowsetInfo::GetURLFromHROW(
  455. HROW hRow,
  456. LPOLESTR *ppwszURL
  457. )
  458. {
  459. #if (!defined(BUILD_FOR_NT40))
  460. CAutoBlock cab(&_csRowsetInfo);
  461. LPWSTR lpwszURL = NULL;
  462. auto_rel<IRowset> pRealRowset;
  463. HRESULT hr = S_OK;
  464. if (ppwszURL == NULL)
  465. RRETURN(E_INVALIDARG);
  466. ADsAssert(_pRowset != NULL);
  467. hr = _pRowset->QueryInterface(__uuidof(IRowset), (void **)&pRealRowset);
  468. BAIL_ON_FAILURE(hr);
  469. // Call row provider to get the URL.
  470. hr = _pRowProvider->GetURLFromHROW( hRow,ppwszURL, pRealRowset);
  471. BAIL_ON_FAILURE(hr);
  472. error:
  473. RRETURN(hr);
  474. #else
  475. RRETURN(E_FAIL);
  476. #endif
  477. };
  478. //+---------------------------------------------------------------------------
  479. //
  480. // Function: CRowsetInfo::GetCredentials
  481. //
  482. // Synopsis: @mfunc Gets credentials stored in INIT properties.
  483. //
  484. // Arguments:
  485. // pSession [in] IGetDataSource interface ptr on Session.
  486. // refCredentials [in] CCredentials containing user id and password.
  487. //
  488. // Returns: HRESULT
  489. //
  490. //----------------------------------------------------------------------------
  491. HRESULT CRowsetInfo::GetCredentials(
  492. IGetDataSource *pSession,
  493. CCredentials &refCredentials
  494. )
  495. {
  496. #if (!defined(BUILD_FOR_NT40))
  497. HRESULT hr = S_OK;
  498. auto_rel<IDBProperties> pDBProp;
  499. ULONG i, j, cPropertySets = 0;
  500. Assert(pSession);
  501. hr = pSession->GetDataSource(
  502. __uuidof(IDBProperties),
  503. (IUnknown **)&pDBProp);
  504. BAIL_ON_FAILURE(hr);
  505. DBPROPID propids[2];
  506. propids[0] = DBPROP_AUTH_USERID;
  507. propids[1] = DBPROP_AUTH_PASSWORD;
  508. DBPROPIDSET rgPropertyIDSets[1];
  509. rgPropertyIDSets[0].rgPropertyIDs = propids;
  510. rgPropertyIDSets[0].cPropertyIDs = 2;
  511. rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DBINIT;
  512. DBPROPSET *prgPropertySets;
  513. hr = pDBProp->GetProperties(
  514. 1,
  515. rgPropertyIDSets,
  516. &cPropertySets,
  517. &prgPropertySets);
  518. if (hr == DB_E_ERRORSOCCURRED)
  519. BAIL_ON_FAILURE(hr);
  520. for (i = 0; i < cPropertySets; i++)
  521. {
  522. for (j = 0; j < prgPropertySets[i].cProperties; j++)
  523. {
  524. DBPROP *pProp = &prgPropertySets[i].rgProperties[j];
  525. Assert(pProp);
  526. if (pProp->dwStatus == S_OK &&
  527. pProp->dwPropertyID == DBPROP_AUTH_USERID)
  528. refCredentials.SetUserName(V_BSTR(&pProp->vValue));
  529. else if (pProp->dwStatus == S_OK &&
  530. pProp->dwPropertyID == DBPROP_AUTH_PASSWORD)
  531. refCredentials.SetPassword(V_BSTR(&pProp->vValue));
  532. else
  533. continue;
  534. }
  535. }
  536. error:
  537. for (i = 0; i < cPropertySets; i++)
  538. {
  539. for (j = 0; j < prgPropertySets[i].cProperties; j++)
  540. {
  541. DBPROP *pProp = &(prgPropertySets[i].rgProperties[j]);
  542. Assert(pProp);
  543. FreeDBID(&pProp->colid);
  544. VariantClear(&pProp->vValue);
  545. }
  546. CoTaskMemFree(prgPropertySets[i].rgProperties);
  547. }
  548. CoTaskMemFree(prgPropertySets);
  549. RRETURN ( hr );
  550. #else
  551. RRETURN(E_FAIL);
  552. #endif
  553. }