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.

664 lines
20 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: CRSEmbed.cxx
  7. //
  8. // Contents: IUnknown embedder for temptable.
  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. //+---------------------------------------------------------------------------
  26. //
  27. // Function: CRowsetInfo::QueryInterface
  28. //
  29. // Synopsis: @mfunc QueryInterface.
  30. // IUknown implementation.
  31. // IID_IUnknown and IID_IRowsetInfo are not delegated
  32. // All other IID's are delegated to _pRowset
  33. //
  34. //-----------------------------------------------------------------------.
  35. HRESULT
  36. CRowsetInfo::QueryInterface(
  37. REFIID riid,
  38. LPVOID *ppv
  39. )
  40. {
  41. HRESULT hr;
  42. if (ppv == NULL)
  43. RRETURN(E_INVALIDARG);
  44. *ppv = NULL;
  45. if (riid == IID_IUnknown) {
  46. *ppv = (IRowsetInfo FAR *) this;
  47. AddRef();
  48. }
  49. if (riid == IID_IRowsetInfo) {
  50. *ppv = (IRowsetInfo FAR *) this;
  51. AddRef();
  52. }
  53. //delegate all the rest to the TempTable Rowset
  54. if (_pRowset == NULL)
  55. RRETURN(E_UNEXPECTED);
  56. hr=((LPUNKNOWN)_pRowset)->QueryInterface(riid, ppv);
  57. RRETURN(hr);
  58. }
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Function: CRowsetInfo::CRowsetInfo
  62. //
  63. // Synopsis: @mfunc Ctor
  64. //
  65. // Arguments:
  66. //
  67. //
  68. // Returns: @rdesc NONE
  69. //
  70. // Modifies:
  71. //
  72. // History: 08/30/96 RenatoB Created
  73. //
  74. //----------------------------------------------------------------------------
  75. CRowsetInfo::CRowsetInfo(
  76. IUnknown *pUnkOuter, // controlling unknown)
  77. IUnknown *pParentObject, // RowProvider
  78. CSessionObject *pCSession, // Session that created rowset
  79. CCommandObject *pCCommand // Command object that created rowset
  80. )
  81. {
  82. _pUnkOuter= (pUnkOuter == NULL) ? this : pUnkOuter;
  83. _pRowset = NULL;
  84. _pParentObject = pParentObject;
  85. _pCSession= pCSession;
  86. _pCCommand = pCCommand;
  87. _pMalloc = NULL;
  88. _dwStatus = 0;
  89. _cPropertySets = 0;
  90. _pPropertySets = NULL;
  91. if (_pCCommand !=NULL)
  92. _pCCommand->IncrementOpenRowsets();
  93. //this section is for IRowsetInfo and IUnknown methods.
  94. InitializeCriticalSection(&_csRowsetInfo);
  95. }
  96. //+---------------------------------------------------------------------------
  97. //
  98. // Function: CRowsetInfo::~CRowsetInfo
  99. //
  100. // Synopsis: @mfunc Dtor
  101. //
  102. // Arguments:
  103. //
  104. //
  105. // Returns: @rdesc NONE
  106. //
  107. // Modifies:
  108. //
  109. // History: 08/30/96 RenatoB Created
  110. //
  111. //----------------------------------------------------------------------------
  112. CRowsetInfo::~CRowsetInfo()
  113. {
  114. // release _pPropertySets
  115. FreePropertySets(_cPropertySets, _pPropertySets);
  116. if (_pMalloc!= NULL) _pMalloc->Release();
  117. if (_pCCommand !=NULL) {
  118. _pCCommand->DecrementOpenRowsets();
  119. _pCCommand->Release();
  120. _pCCommand = NULL;
  121. }
  122. if (_pCSession != NULL) {
  123. _pCSession->Release();
  124. _pCSession = NULL;
  125. }
  126. if (_pParentObject != NULL){
  127. _pParentObject->Release();
  128. _pParentObject=NULL;
  129. }
  130. if (_pRowset != NULL){
  131. ((LPUNKNOWN)_pRowset)->Release();
  132. _pRowset=NULL;
  133. }
  134. if ( _pCRowsetInfo!= NULL) {
  135. delete _pCRowsetInfo;
  136. _pCRowsetInfo = NULL;
  137. }
  138. DeleteCriticalSection(&_csRowsetInfo);
  139. }
  140. //+---------------------------------------------------------------------------
  141. //
  142. // Function: CRowsetInfo::FInit
  143. //
  144. // Synopsis: @mfunc Initializer
  145. //
  146. // Called by: CreateTempTable
  147. // Called when: After calling pIServiceProvider->ProvideService
  148. // Synopsis: @mfunc Initializer
  149. //
  150. // Arguments:
  151. //
  152. //
  153. // Returns: @rdesc NONE
  154. // @flag S_OK | Interface is supported
  155. // @flag E_OUTOFMEMORY | Interface is not supported by the TempTable
  156. // @flag E_INVALIDARG | One or more arguments are invalid.
  157. //
  158. // Modifies:
  159. //
  160. // History: 08/30/96 RenatoB Created
  161. //
  162. //----------------------------------------------------------------------------
  163. HRESULT
  164. CRowsetInfo::FInit(
  165. IUnknown *pRowset) // TmpTable interface
  166. {
  167. HRESULT hr;
  168. hr = S_OK;
  169. _pRowset = pRowset;
  170. RRETURN(hr);
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Function: CRowsetInfo::GetReferencedRowset
  175. //
  176. // Synopsis: @mfunc Returns an interface pointer to the rowset to which a bookmark applies
  177. //
  178. // Called by: Client
  179. // Called when: Any time
  180. //
  181. // Arguments:
  182. // iOrdinal [in] Bookmark column for which to get related rowset. Must be 0 in this impl.
  183. // riid [in] IID of the interface pointer to return in *ppReferencedRowset.
  184. // ppReferencedRowset[out] pointer to Rowset object referenced by Bookmark
  185. //
  186. //
  187. // Returns: @rdesc NONE
  188. // S_OK | Interface is supported
  189. // E_INVALIDARG | ppReferencedRowset was a NULL pointer
  190. // E_FAIL | provider specific error
  191. // E_NOINTERFACE | Rowset does not support interface
  192. // DB_E_NOTAREFENCEDCOLUMN | iOrdinal was not 0
  193. //
  194. //----------------------------------------------------------------------------
  195. HRESULT
  196. CRowsetInfo::GetReferencedRowset(
  197. DBORDINAL iOrdinal,
  198. REFIID riid,
  199. IUnknown** ppReferencedRowset
  200. )
  201. {
  202. CAutoBlock(&(_csRowsetInfo));
  203. if (ppReferencedRowset == NULL)
  204. RRETURN(E_INVALIDARG);
  205. if (iOrdinal != 0)
  206. RRETURN(DB_E_BADORDINAL);
  207. RRETURN(QueryInterface(
  208. riid,
  209. (void**)ppReferencedRowset)
  210. );
  211. };
  212. //+---------------------------------------------------------------------------
  213. //
  214. // Function: CRowsetInfo::GetSpecificaton
  215. //
  216. // Synopsis: @mfunc Returns an interface pointer to the command that created the rowset
  217. //
  218. // Called by: Client
  219. // Called when: Any time
  220. //
  221. // Arguments:
  222. // riid [in] IID of the interface pointer to return in *ppSpecification.
  223. // ppSpecification [out] pointer to command
  224. //
  225. //
  226. // Returns: @rdesc NONE
  227. // S_OK | Interface is supported
  228. // E_INVALIDARG | ppSpecification was a NULL pointer
  229. // E_FAIL | provider specific error
  230. // E_NOINTERFACE | Command does not support interface
  231. // S_FALSE | Rowset does not have command that created it
  232. //----------------------------------------------------------------------------
  233. HRESULT
  234. CRowsetInfo::GetSpecification(
  235. REFIID riid,
  236. IUnknown** ppSpecification
  237. )
  238. {
  239. CAutoBlock(&(_csRowsetInfo));
  240. if (ppSpecification == NULL)
  241. RRETURN(E_INVALIDARG);
  242. if ( _pParentObject == NULL)
  243. RRETURN(S_FALSE);
  244. RRETURN(_pParentObject->QueryInterface(riid, (void**)ppSpecification));
  245. };
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Function: CRowsetInfo::GetProperties
  249. //
  250. // Synopsis: @mfunc GetProperties
  251. // Overloads the TempTable's IRowsetInfo::GetProperties.
  252. // The first time this function is called, it calls the
  253. // TmpTable IRowsetInfo::GetProperties with cPropertyIdSets == 0
  254. //
  255. // Called by: Client.
  256. // Called when: Any time.
  257. //
  258. // Arguments:
  259. // cPropertyIDSets[in] The number of DBPROPIDSET structures in rgProperttySets
  260. // rgPropertyIDSets[in] Array of cPropertyIDSets of DBPROIDSET structs.
  261. // pcPropertySets[out] number of DBPROPSET returned in *prgPropertySets
  262. // prgPropertySets[out] pointer to array of DBPROPSET structures, having the
  263. // value and status of requested properties
  264. //
  265. // Returns: @rdesc HRESULT
  266. // S_OK Success
  267. // DB_S_ERRORSOCCURRED Values were not supported for some properties
  268. // E_FAIL A provider-specific error occurred
  269. // E_INVALIDARG cPropertyIDSets > 0 and rgPropertyIdSEts = NULL
  270. // pcPropertySets or prgPropertySets was NULL pointer
  271. // In al element of rgPropertyIDSets, cPropertyIDs was not zero
  272. // and rgPropertyIDs was a Null pointer
  273. // E_OUTOFMEMORY Provider could not allocate memory
  274. // DB_E_ERRORSOCCURRED Values were not returned for any properties
  275. //-----------------------------------------------------------------------.
  276. HRESULT
  277. CRowsetInfo::GetProperties(
  278. const ULONG cPropertyIDSets,
  279. const DBPROPIDSET rgPropertyIDSets[],
  280. ULONG* pcPropertySets,
  281. DBPROPSET** prgPropertySets
  282. )
  283. {
  284. CAutoBlock(&(_csRowsetInfo));
  285. // mplPropertyIDsets maps the position of a property set in rgPropertyIDSets[]
  286. // within _pPropertySets. It has (-1) if not mappable
  287. LONG mplPropertyIDSets[50];
  288. // mplPropertySets maps the position of a property within its corresponding
  289. // rgProperties in _pPropertySets. It has (-1) if not mappable.
  290. LONG position;
  291. HRESULT hr = S_OK;
  292. ULONG i;
  293. ULONG j;
  294. ULONG ibPropertyIDsets;
  295. ULONG ibPropertySets;
  296. BOOL bPartialSuccess = FALSE;
  297. BOOL bErrorsOccurred = FALSE;
  298. //validate arguments
  299. if ( ((cPropertyIDSets > 0) && ( rgPropertyIDSets == NULL)) ||
  300. (pcPropertySets == NULL) ||
  301. (prgPropertySets == NULL) )
  302. RRETURN(E_INVALIDARG);
  303. for (i = 0; i< cPropertyIDSets; i++) {
  304. if ((rgPropertyIDSets[i].cPropertyIDs > 0) &&
  305. (rgPropertyIDSets[i].rgPropertyIDs ==NULL))
  306. RRETURN(E_INVALIDARG);
  307. }
  308. //Initializate, if needed
  309. if (_dwStatus == 0) InitProperties();
  310. if (_dwStatus & STAT_INITERROR) //initialization was unsuccessful
  311. RRETURN(E_FAIL);
  312. // If CPropertyIDSets == 0, just copy
  313. *pcPropertySets = 0;
  314. *prgPropertySets = NULL;
  315. //case when cPropertyIDSets == 0
  316. if (cPropertyIDSets == 0) {
  317. //allocate memory for the property sets
  318. *prgPropertySets = (DBPROPSET*) _pMalloc->Alloc(
  319. _cPropertySets*sizeof(DBPROPSET)
  320. );
  321. if (*prgPropertySets == NULL) {
  322. hr = E_OUTOFMEMORY;
  323. goto error;
  324. };
  325. *pcPropertySets = _cPropertySets;
  326. // copy the array of property sets and make rgProperties equal to NULL
  327. memcpy(
  328. (void*) *prgPropertySets,
  329. (void*) _pPropertySets,
  330. _cPropertySets*sizeof(DBPROPSET)
  331. );
  332. for (i = 0; i< _cPropertySets; i++)
  333. (*prgPropertySets)[i].rgProperties = NULL;
  334. // make copies of each of the rgProperties contained in _pPropertySets
  335. for (i = 0; i< _cPropertySets ; i++) {
  336. (*prgPropertySets)[i].rgProperties=
  337. (DBPROP*)_pMalloc->Alloc(
  338. _pPropertySets[i].cProperties*sizeof(DBPROP)
  339. );
  340. if ((*prgPropertySets)[i].rgProperties == NULL) {
  341. hr = E_OUTOFMEMORY;
  342. goto error;
  343. };
  344. memcpy(
  345. (void*)((*prgPropertySets)[i].rgProperties),
  346. (void*) (_pPropertySets[i].rgProperties),
  347. _pPropertySets[i].cProperties*sizeof(DBPROP)
  348. );
  349. };
  350. RRETURN(S_OK);
  351. };
  352. // This is the case when cPropertyIDSets != 0
  353. // First, allocate memory
  354. *prgPropertySets = (DBPROPSET*) _pMalloc->Alloc(
  355. cPropertyIDSets*sizeof(DBPROPSET)
  356. );
  357. if (*prgPropertySets == NULL) {
  358. hr = E_OUTOFMEMORY;
  359. goto error;
  360. };
  361. memset((void*)*prgPropertySets, 0, sizeof(DBPROPSET)*cPropertyIDSets );
  362. *pcPropertySets= cPropertyIDSets;
  363. memset(mplPropertyIDSets, 0, sizeof(LONG)*cPropertyIDSets );
  364. for (i=0; i<cPropertyIDSets; i++) {
  365. (*prgPropertySets)[i].guidPropertySet =
  366. rgPropertyIDSets[i].guidPropertySet;
  367. mplPropertyIDSets[i] = SearchGuid(
  368. rgPropertyIDSets[i].guidPropertySet
  369. );
  370. if (mplPropertyIDSets[i] < 0) {
  371. bErrorsOccurred = TRUE;
  372. (*prgPropertySets)[i].cProperties = 0;
  373. (*prgPropertySets)[i].rgProperties = NULL;
  374. (*prgPropertySets)[i].guidPropertySet =
  375. rgPropertyIDSets[i].guidPropertySet;
  376. }
  377. else {
  378. //The PropertySet is supported. Remember its position in ibPropertyIDsets
  379. ibPropertyIDsets = mplPropertyIDSets[i];
  380. //We write the property-set's GUID
  381. (*prgPropertySets)[i].guidPropertySet =
  382. rgPropertyIDSets[i].guidPropertySet;
  383. if (rgPropertyIDSets[i].cPropertyIDs == 0) {
  384. //the client is asking for all properties
  385. bPartialSuccess = TRUE;
  386. (*prgPropertySets)[i].rgProperties=
  387. (DBPROP*)_pMalloc->Alloc(
  388. _pPropertySets[ibPropertyIDsets].cProperties*sizeof(DBPROP)
  389. );
  390. if ((*prgPropertySets)[i].rgProperties == NULL) {
  391. hr = E_OUTOFMEMORY;
  392. goto error;
  393. };
  394. (*prgPropertySets)[i].cProperties=
  395. _pPropertySets[ibPropertyIDsets].cProperties;
  396. memcpy(
  397. (void*) ((*prgPropertySets)[i].rgProperties),
  398. (void*) _pPropertySets[ibPropertyIDsets].rgProperties,
  399. _pPropertySets[ibPropertyIDsets].cProperties*sizeof(DBPROP)
  400. );
  401. }
  402. else {
  403. //the client asks for some properties only. Alloc and clear memory
  404. (*prgPropertySets)[i].rgProperties=
  405. (DBPROP*)_pMalloc->Alloc(rgPropertyIDSets[i].cPropertyIDs
  406. *sizeof(DBPROP));
  407. if ((*prgPropertySets)[i].rgProperties == NULL) {
  408. hr = E_OUTOFMEMORY;
  409. goto error;
  410. };
  411. (*prgPropertySets)[i].cProperties =
  412. rgPropertyIDSets[i].cPropertyIDs;
  413. memset(
  414. ((*prgPropertySets)[i].rgProperties),
  415. 0,
  416. rgPropertyIDSets[i].cPropertyIDs*sizeof(DBPROP)
  417. );
  418. //iterate and set values
  419. for (j=0; j <rgPropertyIDSets[i].cPropertyIDs; j++) {
  420. position =
  421. SearchPropid(
  422. ibPropertyIDsets,
  423. rgPropertyIDSets[i].rgPropertyIDs[j]
  424. );
  425. if (position < 0) {
  426. //could not find a property
  427. bErrorsOccurred = TRUE;
  428. (*prgPropertySets)[i].rgProperties[j].dwPropertyID =
  429. rgPropertyIDSets[i].rgPropertyIDs[j];
  430. (*prgPropertySets)[i].rgProperties[j].dwStatus =
  431. DBPROPSTATUS_NOTSUPPORTED;
  432. }
  433. else {
  434. bPartialSuccess= TRUE;
  435. ibPropertySets = position;
  436. memcpy(
  437. (void*)&((*prgPropertySets)[i].rgProperties[j] ),
  438. (void*)&(_pPropertySets[ibPropertyIDsets].
  439. rgProperties[ibPropertySets]),
  440. sizeof(DBPROP));
  441. }
  442. }
  443. }
  444. }
  445. }
  446. if ((bPartialSuccess == TRUE) && (bErrorsOccurred == FALSE))
  447. RRETURN(S_OK);
  448. if (bPartialSuccess == TRUE)
  449. RRETURN(DB_S_ERRORSOCCURRED);
  450. hr = DB_E_ERRORSOCCURRED;
  451. goto error;
  452. error:
  453. FreePropertySets( *pcPropertySets, *prgPropertySets);
  454. *pcPropertySets = NULL;
  455. *prgPropertySets = NULL;
  456. RRETURN(hr);
  457. };
  458. //+---------------------------------------------------------------------------
  459. //
  460. // Function: CRowsetInfo::FreePropertySets
  461. //
  462. // Synopsis: @mfunc releases the memory of property sets
  463. //
  464. // Arguments:
  465. // cPropertySets [in] number of property sets to be freed
  466. // rgPropertySets [in/out] array with the property sets to be released
  467. // Called by: Provider
  468. // Called when: By the destructor, or for method that needs cleanup
  469. // of property sets
  470. //----------------------------------------------------------------------------
  471. void
  472. CRowsetInfo::FreePropertySets(
  473. ULONG cPropertySets,
  474. DBPROPSET *rgPropertySets
  475. )
  476. {
  477. ULONG i;
  478. if ((cPropertySets > 0) && (rgPropertySets == NULL)) {
  479. return;
  480. }
  481. if (cPropertySets == 0) return;
  482. if (_pMalloc == NULL) {
  483. return;
  484. }
  485. //Free the individual arrays of properties
  486. for (i=0; i< cPropertySets; i++) {
  487. if ((rgPropertySets[i].cProperties > 0) &&
  488. (rgPropertySets[i].rgProperties != NULL))
  489. _pMalloc->Free(rgPropertySets[i].rgProperties);
  490. };
  491. //Free the array of propertysets
  492. _pMalloc->Free(rgPropertySets);
  493. }
  494. //+---------------------------------------------------------------------------
  495. //
  496. // Function: CRowsetInfo::InitProperties
  497. //
  498. // Synopsis: @mfunc initilizes _cPropertySets and _pPropertySets from
  499. // _pRowset
  500. //
  501. //----------------------------------------------------------------------------
  502. HRESULT CRowsetInfo::InitProperties(void)
  503. {
  504. HRESULT hr;
  505. IRowsetInfo* pRowsetInfo = NULL;
  506. hr = CoGetMalloc(MEMCTX_TASK, &_pMalloc);
  507. if (FAILED(hr)) {
  508. goto error;
  509. }
  510. if (_pRowset == NULL) {
  511. hr = E_FAIL;
  512. goto error;
  513. };
  514. hr = _pRowset->QueryInterface(IID_IRowsetInfo, (void**) &pRowsetInfo);
  515. if (FAILED (hr)) {
  516. goto error;
  517. };
  518. hr= pRowsetInfo->GetProperties(0, NULL, &_cPropertySets, &_pPropertySets);
  519. if (FAILED(hr)) {
  520. goto error;
  521. }
  522. _dwStatus =STAT_DIDINIT;
  523. pRowsetInfo->Release();
  524. RRETURN(S_OK);
  525. error:
  526. _dwStatus = STAT_INITERROR;
  527. if (_pMalloc != NULL) {
  528. _pMalloc->Release();
  529. _pMalloc = NULL;
  530. }
  531. if (pRowsetInfo != NULL)
  532. pRowsetInfo->Release();
  533. ;
  534. RRETURN(hr);
  535. };
  536. //+---------------------------------------------------------------------------
  537. //
  538. // Function: CRowsetInfo::SearchGuid
  539. //
  540. // Synopsis: @mfunc
  541. //
  542. // Arguments: riid [in] GUID to be searched for
  543. //
  544. // Returns:
  545. // The position of the GUID withing _pPropertySets. Returns -1
  546. // if not found
  547. //
  548. //----------------------------------------------------------------------------
  549. LONG CRowsetInfo::SearchGuid(GUID riid)
  550. {
  551. ULONG i;
  552. for (i = 0; i < _cPropertySets; i++) {
  553. if (_pPropertySets[i].guidPropertySet == riid) return (i);
  554. };
  555. return -1;
  556. };
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Function: CRowsetInfo::SearchPropid
  560. //
  561. // Synopsis: @mfunc Searchs for a Propid within _PropertySets
  562. //
  563. // Arguments:
  564. // ibPropertySet [in] The index, within _pPropertySets,
  565. // of the DBPROPSET to be searched
  566. // dwPropertyID [in] The propid to be searched
  567. // Returns:
  568. // The position of the DBPROP with propid=dwPropertyID
  569. // within _pPropertySets[ibPropertySet]. Returns -1
  570. // if not found
  571. //
  572. //----------------------------------------------------------------------------
  573. LONG CRowsetInfo::SearchPropid(
  574. ULONG ibPropertySet,
  575. DWORD dwPropertyID)
  576. {
  577. ULONG i;
  578. for (i = 0; i < _pPropertySets[ibPropertySet].cProperties; i++) {
  579. if (_pPropertySets[ibPropertySet].rgProperties[i].dwPropertyID ==dwPropertyID )
  580. return (i);
  581. };
  582. return -1;
  583. };