Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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