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.

1190 lines
38 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. //
  5. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // IROWSET.CPP IRowsetLocate interface implementation
  8. //
  9. ///////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. /////////////////////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Retrieves data from the rowset's cache
  14. //
  15. // Returns one of the following values:
  16. // S_OK Method Succeeded
  17. // DB_S_ERRORSOCCURED Could not coerce a column value
  18. // DB_E_BADACCESSORHANDLE Invalid Accessor given
  19. // DB_E_BADROWHANDLE Invalid row handle given
  20. // E_INVALIDARG pData was NULL
  21. // OTHER Other HRESULTs returned by called functions
  22. //
  23. /////////////////////////////////////////////////////////////////////////////////////////////////
  24. STDMETHODIMP CImpIRowsetLocate::GetData( HROW hRow, //IN Row Handle
  25. HACCESSOR hAccessor, //IN Accessor to use
  26. void *pData ) //OUT Pointer to buffer where data should go.
  27. {
  28. HRESULT hr = DB_E_BADROWHANDLE;
  29. CSetStructuredExceptionHandler seh;
  30. TRY_BLOCK;
  31. // Seriliaze the object
  32. CAutoBlock cab(ROWSET->GetCriticalSection());
  33. g_pCError->ClearErrorInfo();
  34. if(m_pObj->IsZoombie())
  35. {
  36. hr = E_UNEXPECTED;
  37. }
  38. else
  39. if( hRow > 0)
  40. {
  41. //============================================================
  42. // Call this function of RowFetch Object to fetch data
  43. //============================================================
  44. hr = m_pObj->m_pRowFetchObj->FetchData(m_pObj,hRow,hAccessor,pData);
  45. }
  46. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
  47. CATCH_BLOCK_HRESULT(hr,L"IRowset::GetData");
  48. return hr;
  49. }
  50. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. //
  52. // CImpIRowset::GetNextRows
  53. //
  54. // Fetches rows in a sequential style, remembering the previous position
  55. //
  56. // Returns one of the following values:
  57. // S_OK Method Succeeded
  58. // DB_S_ENDOFROWSET Reached end of rowset
  59. // DB_E_CANTFETCHBACKWARDS cRows was negative and we can't fetch backwards
  60. // DB_E_ROWSNOTRELEASED Must release all HROWs before calling GetNextRows
  61. // E_FAIL Provider-specific error
  62. // E_INVALIDARG pcRowsObtained or prghRows was NULL
  63. // E_OUTOFMEMORY Out of Memory
  64. // OTHER Other HRESULTs returned by called functions
  65. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  66. STDMETHODIMP CImpIRowsetLocate::GetNextRows ( HCHAPTER hChapter, // IN The Chapter handle.
  67. DBROWOFFSET lRowOffset, // IN Rows to skip before reading
  68. DBROWCOUNT cRows, // IN Number of rows to fetch
  69. DBCOUNTITEM *pcRowsObtained, // OUT Number of rows obtained
  70. HROW **prghRows // OUT Array of Hrows obtained
  71. )
  72. {
  73. HRESULT hr;
  74. CSetStructuredExceptionHandler seh;
  75. TRY_BLOCK;
  76. // Seriliaze the object
  77. CAutoBlock cab(ROWSET->GetCriticalSection());
  78. // clear error information
  79. g_pCError->ClearErrorInfo();
  80. //========================================================================
  81. // Check the HChapter is of the current rowset is valid
  82. //========================================================================
  83. if(m_pObj->IsZoombie())
  84. {
  85. hr = E_UNEXPECTED;
  86. }
  87. else
  88. if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
  89. m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
  90. {
  91. hr = DB_E_BADCHAPTER;
  92. }
  93. else
  94. {
  95. //========================================================================
  96. // Check the rowset parameters to see if we support this request
  97. //========================================================================
  98. if(SUCCEEDED(hr = CheckParameters(pcRowsObtained, lRowOffset, cRows, prghRows)))
  99. {
  100. if(hChapter)
  101. {
  102. hr = m_pObj->CheckAndInitializeChapter(hChapter);
  103. }
  104. if(SUCCEEDED(hr))
  105. {
  106. // Create the data members to manage the data only the first time
  107. if(!m_pObj->m_bHelperFunctionCreated)
  108. {
  109. if( SUCCEEDED(hr = m_pObj->CreateHelperFunctions()))
  110. {
  111. m_pObj->m_bHelperFunctionCreated = TRUE;
  112. }
  113. }
  114. if(SUCCEEDED(hr))
  115. {
  116. //========================================================================
  117. // Are there any unreleased rows?
  118. //========================================================================
  119. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
  120. {
  121. hr = DB_E_ROWSNOTRELEASED;
  122. }
  123. else
  124. {
  125. //============================================================
  126. // Call this function of Rowfetch object to fetch rows
  127. //============================================================
  128. hr = m_pObj->m_pRowFetchObj->FetchRows(m_pObj,hChapter,lRowOffset,cRows,pcRowsObtained,prghRows);
  129. } // else
  130. } // if succeeded(hr)
  131. } // if succeeded(hr)
  132. } // if succeeded(hr)
  133. }
  134. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
  135. CATCH_BLOCK_HRESULT(hr,L"IRowset::GetNextRows");
  136. return hr;
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. //
  140. // Releases row handles
  141. //
  142. // Returns one of the following values:
  143. // S_OK | success
  144. // DB_S_ERRORSOCCURRED | some elements of rghRows were invalid
  145. // DB_E_ERRORSOCCURRED | all elements of rghRows were invalid
  146. // E_INVALIDARG | rghRows was a NULL pointer and crow > 0
  147. //
  148. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. STDMETHODIMP CImpIRowsetLocate::ReleaseRows ( DBCOUNTITEM cRows, // IN Number of rows to release
  150. const HROW rghRows[], // IN Array of handles of rows to be released
  151. DBROWOPTIONS rgRowOptions[], // IN Additional Options
  152. DBREFCOUNT rgRefCounts[], // OUT array of ref counts of released rows
  153. DBROWSTATUS rgRowStatus[] // OUT status array of for input rows
  154. )
  155. {
  156. HRESULT hr = S_OK;
  157. ULONG ihRow = 0L;
  158. ULONG cErrors = 0L;
  159. ROWBUFF *pRowBuff = NULL;
  160. BOOL bBuffFlag = FALSE;
  161. LONG lRowRefCount = 0;
  162. CSetStructuredExceptionHandler seh;
  163. TRY_BLOCK;
  164. // Seriliaze the object
  165. CAutoBlock cab(ROWSET->GetCriticalSection());
  166. // clear error information
  167. g_pCError->ClearErrorInfo();
  168. if(cRows == 0)
  169. {
  170. hr = S_OK;
  171. }
  172. else
  173. //============================================================================
  174. // check params
  175. //============================================================================
  176. if ( cRows && !rghRows )
  177. {
  178. hr = E_INVALIDARG;
  179. // return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowset);
  180. }
  181. else
  182. {
  183. ihRow = 0;
  184. // If any rows is fetched data slotlist would have been initialized otherwise
  185. // return invallid rows
  186. if(!m_pObj->m_bHelperFunctionCreated)
  187. {
  188. for (ihRow = 0; ihRow < cRows; ihRow++)
  189. {
  190. if(rgRefCounts)
  191. {
  192. rgRefCounts[ihRow] = 0;
  193. }
  194. if(rgRowStatus)
  195. {
  196. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  197. }
  198. }
  199. hr = DB_E_ERRORSOCCURRED;
  200. // return g_pCError->PostHResult(DB_E_ERRORSOCCURRED,&IID_IRowset);
  201. }
  202. else
  203. {
  204. while ( ihRow < cRows )
  205. {
  206. bBuffFlag = FALSE;
  207. lRowRefCount = 0;
  208. //=============================================================
  209. // if HROW is invalid mark it and continue with the next row
  210. //=============================================================
  211. if(((LONG) rghRows[ihRow]) <= 0)
  212. {
  213. if( rgRowStatus != NULL)
  214. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  215. ihRow++;
  216. cErrors++;
  217. continue;
  218. }
  219. hr = m_pObj->IsSlotSet(rghRows[ihRow]);
  220. if( hr == S_OK)
  221. {
  222. //=============================================================
  223. // Get the buffer address if it is allocated
  224. //=============================================================
  225. pRowBuff=m_pObj->GetRowBuff((ULONG) rghRows[ihRow], TRUE);
  226. if(pRowBuff != NULL)
  227. {
  228. bBuffFlag = TRUE;
  229. }
  230. }
  231. //=========================================================================
  232. // check the row handle
  233. //=========================================================================
  234. if(m_pObj->m_ulRowRefCount && (TRUE == m_pObj->IsRowExists(rghRows[ihRow])))
  235. {
  236. if(bBuffFlag == TRUE)
  237. {
  238. --pRowBuff->ulRefCount;
  239. lRowRefCount = pRowBuff->ulRefCount;
  240. }
  241. //=====================================================================
  242. // Found valid row, so decrement reference counts.
  243. // (Internal error for refcount to be 0 here, since slot set.)
  244. //=====================================================================
  245. --m_pObj->m_ulRowRefCount;
  246. //=====================================================================
  247. // stuff new refcount into caller's array
  248. //=====================================================================
  249. if ( rgRefCounts )
  250. {
  251. rgRefCounts[ihRow] = lRowRefCount;
  252. }
  253. if ( rgRowStatus )
  254. {
  255. rgRowStatus[ihRow] = DBROWSTATUS_S_OK;
  256. }
  257. if ( lRowRefCount == 0 )
  258. {
  259. if(bBuffFlag == TRUE)
  260. {
  261. // Bind the row data to the rowdata mem manager
  262. if (FAILED( m_pObj->Rebind((BYTE *) pRowBuff)))
  263. {
  264. if( rgRowStatus != NULL)
  265. {
  266. rgRowStatus[ihRow] = DBROWSTATUS_E_FAIL;
  267. }
  268. ++cErrors;
  269. //return g_pCError->PostHResult(E_FAIL,&IID_IRowset);
  270. }
  271. else
  272. {
  273. //============================================================
  274. // release the memory allocated for the different columns
  275. //============================================================
  276. m_pObj->m_pRowData->ReleaseRowData();
  277. }
  278. if(m_pObj->m_ulProps & BOOKMARKPROP)
  279. {
  280. m_pObj->m_pHashTblBkmark->DeleteBmk((ULONG)rghRows[ihRow]);
  281. }
  282. if(m_pObj->m_ulLastFetchedRow == rghRows[ihRow])
  283. {
  284. m_pObj->m_ulLastFetchedRow = 0;
  285. }
  286. // release the slots
  287. ReleaseSlots( m_pObj->m_pIBuffer, m_pObj->GetSlotForRow(rghRows[ihRow]), 1 );
  288. }
  289. // release the rows from the instance manager and chapter manager
  290. m_pObj->ReleaseInstancePointer(rghRows[ihRow]);
  291. }
  292. }
  293. else
  294. {
  295. //=====================================================================
  296. // It is an error for client to try to release a row
  297. // for which "IsSetSlot" is false. Client gave us an invalid handle.
  298. // Ignore it (we can't release it...) and report error when done.
  299. //=====================================================================
  300. if ( rgRefCounts )
  301. {
  302. rgRefCounts[ihRow] = 0;
  303. }
  304. if ( rgRowStatus )
  305. {
  306. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  307. }
  308. ++cErrors;
  309. }
  310. ihRow++;
  311. } // while
  312. //=============================================================================
  313. // If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
  314. //=============================================================================
  315. hr = cErrors ? ( cErrors < cRows ) ?
  316. ( DB_S_ERRORSOCCURRED ) :
  317. ( DB_E_ERRORSOCCURRED ) :
  318. ( S_OK );
  319. } // else for if(!m_pObj->m_bHelperFunctionCreated)
  320. } // else for if ( cRows && !rghRows )
  321. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
  322. CATCH_BLOCK_HRESULT(hr,L"IRowset::ReleaseRows");
  323. return hr;
  324. }
  325. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  326. //
  327. // Repositions the next fetch position to the start of the rowset
  328. //
  329. // - all rows must be released before calling this method
  330. // - it is not expensive to Restart us, because we are from a single table
  331. //
  332. //
  333. // Returns one of the following values:
  334. // S_OK | Method Succeeded
  335. // DB_E_ROWSNOTRELEASED | All HROWs must be released before calling
  336. // DB_S_COMMANDREEXECUTED | The command was re-executed. This can happen when a method is
  337. // is executed or RestartPosition is called on Forwardonly rowset
  338. // DB_E_BADCHAPTER | HCHAPTER passed was invalid
  339. //
  340. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  341. STDMETHODIMP CImpIRowsetLocate::RestartPosition( HCHAPTER hChapter ) // IN The Chapter handle.
  342. {
  343. BOOL fCanHoldRows = FALSE;
  344. BOOL fLiteralIdentity = FALSE;
  345. HRESULT hr = S_OK;
  346. CSetStructuredExceptionHandler seh;
  347. TRY_BLOCK;
  348. // Seriliaze the object
  349. CAutoBlock cab(ROWSET->GetCriticalSection());
  350. // clear error information
  351. g_pCError->ClearErrorInfo();
  352. if(m_pObj->IsZoombie())
  353. {
  354. hr = E_UNEXPECTED;
  355. }
  356. else
  357. if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
  358. m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
  359. {
  360. hr = DB_E_BADCHAPTER;
  361. //return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowset);
  362. }
  363. else
  364. {
  365. //=========================================================================
  366. // If no rows are fetched in this rowset after opening don't do anything
  367. // if bitarray is NULL no rows are fetched till now
  368. //=========================================================================
  369. if(!(m_pObj->m_hRow == 0 ||
  370. m_pObj->m_pIAccessor->GetBitArrayPtr() == NULL))
  371. {
  372. /*
  373. //========================================================================
  374. // Get the LiteralIdentity property
  375. //========================================================================
  376. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & LITERALIDENTITY) ){
  377. fLiteralIdentity = TRUE;
  378. }
  379. */
  380. //========================================================================
  381. // Are there any unreleased rows?
  382. //========================================================================
  383. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
  384. {
  385. hr = DB_E_ROWSNOTRELEASED;
  386. //return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED,&IID_IRowset);
  387. }
  388. else
  389. {
  390. /* //============================================================================
  391. // If LiteralIdentity is on reset SlotList
  392. //============================================================================
  393. if ( fLiteralIdentity )
  394. ResetSlotList( m_pObj->m_pIBuffer );
  395. */
  396. //============================================================================
  397. // set "next fetch" position to the start of the rowset
  398. //============================================================================
  399. if( m_pObj->m_uRsType == PROPERTYQUALIFIER ||
  400. m_pObj->m_uRsType == CLASSQUALIFIER )
  401. {
  402. hr = m_pObj->ResetQualifers(hChapter);
  403. }
  404. else
  405. if(m_pObj->m_bIsChildRs == FALSE)
  406. hr = m_pObj->ResetInstances();
  407. if(hr == S_OK)
  408. {
  409. //============================================================================
  410. // clear "end of cursor" flag
  411. //============================================================================
  412. m_pObj->SetStatus(hChapter, ~STAT_ENDOFCURSOR);
  413. // if the rowset is as a result of command then set the return value to signify
  414. // that command has been executed
  415. // Rowset is also reopened if rowset is forward only rowset
  416. // If Command is reexecuted , then release all the rows as the rows will not be
  417. // valid if command is re-executed
  418. if(!((CANSCROLLBACKWARDS & m_pObj->m_ulProps) ||
  419. (CANFETCHBACKWARDS & m_pObj->m_ulProps) ||
  420. (BOOKMARKPROP & m_pObj->m_ulProps)) ||
  421. m_pObj->m_uRsType == METHOD_ROWSET)
  422. {
  423. m_pObj->ReleaseAllRows();
  424. hr = DB_S_COMMANDREEXECUTED;
  425. }
  426. }
  427. } // else for If ( rows are not released when CANHOLDROWS is false)
  428. } // if ( no rows are fetched till now)
  429. } // else if( check for validity of HCHAPTER)
  430. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
  431. CATCH_BLOCK_HRESULT(hr,L"IRowset::RestartPosition");
  432. return hr;
  433. }
  434. ///////////////////////////////////////////////////////////////////////////////////////////////////
  435. //
  436. // Adds a reference count to an existing row handle
  437. //
  438. // Returns one of the following values:
  439. // S_OK | success
  440. // DB_S_ERRORSOCCURRED | some elements of rghRows were invalid
  441. // DB_E_ERRORSOCCURRED | all elements of rghRows were invalid
  442. // E_INVALIDARG | rghRows was a NULL pointer and crow > 0
  443. //
  444. // NTRaid:111815
  445. // 06/06/00
  446. ///////////////////////////////////////////////////////////////////////////////////////////////////
  447. STDMETHODIMP CImpIRowsetLocate::AddRefRows ( DBCOUNTITEM cRows, // IN Number of rows to refcount
  448. const HROW rghRows[], // IN Array of row handles to refcount
  449. DBREFCOUNT rgRefCounts[], // OUT Array of refcounts
  450. DBROWSTATUS rgRowStatus[]) // OUT Array of row status
  451. {
  452. HRESULT hr = S_OK;
  453. ULONG ihRow = 0L;
  454. ULONG cErrors = 0L;
  455. ROWBUFF *pRowBuff = NULL;
  456. CSetStructuredExceptionHandler seh;
  457. TRY_BLOCK;
  458. // Seriliaze the object
  459. CAutoBlock cab(ROWSET->GetCriticalSection());
  460. // clear error information
  461. g_pCError->ClearErrorInfo();
  462. //============================================
  463. // If cRows is 0 do nothing and return S_OK
  464. //============================================
  465. if(cRows == 0)
  466. return S_OK;
  467. //============================================================================
  468. // check params
  469. //============================================================================
  470. if ( cRows && !rghRows )
  471. {
  472. hr = E_INVALIDARG;
  473. //return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowset);
  474. }
  475. else
  476. {
  477. // If any rows is fetched data slotlist would have been initialized otherwise
  478. // return invallid rows
  479. if(!m_pObj->m_bHelperFunctionCreated)
  480. {
  481. for (ihRow = 0; ihRow < cRows; ihRow++)
  482. {
  483. if(rgRefCounts)
  484. {
  485. rgRefCounts[ihRow] = 0;
  486. }
  487. if(rgRowStatus)
  488. {
  489. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  490. }
  491. }
  492. hr = DB_E_ERRORSOCCURRED;
  493. //return g_pCError->PostHResult(DB_E_ERRORSOCCURRED,&IID_IRowset);
  494. }
  495. else
  496. {
  497. //============================================================================
  498. // for each of the HROWs the caller provided...
  499. //============================================================================
  500. for (ihRow = 0; ihRow < cRows; ihRow++){
  501. if( rghRows[ihRow] <= 0)
  502. {
  503. if( rgRowStatus != NULL)
  504. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  505. cErrors++;
  506. continue;
  507. }
  508. //========================================================================
  509. // check the row handle
  510. //========================================================================
  511. if(m_pObj->IsSlotSet((ULONG) rghRows[ihRow]) == S_OK)
  512. {
  513. if(( pRowBuff=m_pObj->GetRowBuff( rghRows[ihRow], TRUE )))
  514. {
  515. //=======================================================
  516. // if row is marked as deleted then set the status
  517. //=======================================================
  518. if(DBROWSTATUS_E_DELETED == m_pObj->GetRowStatus(rghRows[ihRow]))
  519. {
  520. if ( rgRowStatus )
  521. {
  522. rgRowStatus[ihRow] = DBROWSTATUS_E_DELETED;
  523. }
  524. ++cErrors;
  525. }
  526. else
  527. {
  528. //====================================================================
  529. // bump refcount
  530. //====================================================================
  531. assert( pRowBuff->ulRefCount != 0 );
  532. assert( m_pObj->m_ulRowRefCount != 0 );
  533. ++pRowBuff->ulRefCount;
  534. ++m_pObj->m_ulRowRefCount;
  535. //====================================================================
  536. // stuff new refcount into caller's array
  537. //====================================================================
  538. if ( rgRefCounts )
  539. {
  540. rgRefCounts[ihRow] = pRowBuff->ulRefCount;
  541. }
  542. if ( rgRowStatus )
  543. {
  544. rgRowStatus[ihRow] = DBROWSTATUS_S_OK;
  545. }
  546. }
  547. }
  548. else
  549. {
  550. if( rgRowStatus != NULL)
  551. {
  552. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  553. }
  554. cErrors++;
  555. continue;
  556. }
  557. }
  558. else
  559. {
  560. if ( rgRefCounts )
  561. {
  562. rgRefCounts[ihRow] = 0;
  563. }
  564. if ( rgRowStatus )
  565. {
  566. rgRowStatus[ihRow] = DBROWSTATUS_E_INVALID;
  567. }
  568. ++cErrors;
  569. }
  570. }
  571. // If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
  572. hr = cErrors ? ( cErrors < cRows ) ?
  573. ( DB_S_ERRORSOCCURRED ) :
  574. ( DB_E_ERRORSOCCURRED ) :
  575. ( S_OK );
  576. } // Else for If( any rows are fetched till now)
  577. } // Else for If( Validate input arguments )
  578. CATCH_BLOCK_HRESULT(hr,L"IRowset::AddRefRows");
  579. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowset);
  580. return hr;
  581. }
  582. //////////////////////////////////////////////////////////////////////////////////////
  583. //// IRowsetLocate Methods /////////////////////
  584. //////////////////////////////////////////////////////////////////////////////////////
  585. //////////////////////////////////////////////////////////////////////////////////////
  586. // CImpIRowsetScroll::Compare
  587. //
  588. // Compares two bookmarks.
  589. //
  590. // Returns one of the following values:
  591. // S_OK compare bookmarks succeeded,
  592. // E_INVALIDARG one of the bookmark had 0 length or
  593. // one of the bookmark pointer was null
  594. // or pdwComparison was NULL,
  595. // DB_E_BADBOOKMARK one or both of the bookmarks was a standard
  596. // bookmark,
  597. // DBCOMPARE_NOTCOMPARABLE The bookmarks passed are not comparable
  598. // E_FAIL Compare failed for some other reason,
  599. //
  600. //////////////////////////////////////////////////////////////////////////////////////
  601. STDMETHODIMP CImpIRowsetLocate::Compare (HCHAPTER hChapter,
  602. DBBKMARK cbBookmark1,
  603. const BYTE * pBookmark1,
  604. DBBKMARK cbBookmark2,
  605. const BYTE * pBookmark2,
  606. DBCOMPARE * pComparison)
  607. {
  608. HRESULT hr = S_OK;
  609. CSetStructuredExceptionHandler seh;
  610. TRY_BLOCK;
  611. // Serialize the object
  612. CAutoBlock cab(ROWSET->GetCriticalSection() );
  613. // clear error information
  614. g_pCError->ClearErrorInfo();
  615. if(m_pObj->IsZoombie())
  616. {
  617. hr = E_UNEXPECTED;
  618. }
  619. else
  620. // Are arguments valid?
  621. if (cbBookmark1 == 0 || cbBookmark2 == 0 || pBookmark1 == NULL
  622. || pBookmark2 == NULL || pComparison == NULL)
  623. {
  624. hr = E_INVALIDARG;
  625. // return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowsetLocate);
  626. }
  627. else
  628. {
  629. *pComparison = DBCOMPARE_NE;
  630. if ((cbBookmark1 != STD_BOOKMARKLENGTH
  631. && cbBookmark1 != BOOKMARKSIZE)
  632. || (cbBookmark2 != STD_BOOKMARKLENGTH
  633. && cbBookmark2 != BOOKMARKSIZE)
  634. || (cbBookmark1 == STD_BOOKMARKLENGTH
  635. && *pBookmark1 == DBBMK_INVALID)
  636. || (cbBookmark2 == STD_BOOKMARKLENGTH
  637. && *pBookmark2 == DBBMK_INVALID) )
  638. {
  639. hr = DB_E_BADBOOKMARK;
  640. }
  641. else
  642. if (cbBookmark1 == STD_BOOKMARKLENGTH)
  643. {
  644. *pComparison = (cbBookmark2 == STD_BOOKMARKLENGTH && *(BYTE*)pBookmark1 == *(BYTE*)pBookmark2)
  645. ? DBCOMPARE_EQ : DBCOMPARE_NE;
  646. }
  647. else
  648. if (cbBookmark1 == BOOKMARKSIZE)
  649. {
  650. *pComparison = (cbBookmark2 == BOOKMARKSIZE
  651. && *(ULONG *)pBookmark1 == *(ULONG *)pBookmark2)
  652. ? DBCOMPARE_EQ : DBCOMPARE_NE;
  653. }
  654. else
  655. {
  656. hr = DBCOMPARE_NOTCOMPARABLE;
  657. }
  658. } // Else for validating arguments
  659. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
  660. CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::Compare");
  661. return hr;
  662. }
  663. /////////////////////////////////////////////////////////////////////////////////////////////////
  664. // CImpIRowsetScroll::GetRowsAt
  665. //
  666. // Fetches rows starting with the row specified by an offset from a bookmark.
  667. //
  668. // Returns one of the following values:
  669. // S_OK Row fetching suceeded
  670. // DB_S_ENDOFROWSET Start or End of rowset was reached during fetching
  671. // E_INVALIDARG Arguments pcRowsObtained or prghRows was a NULL pointer,
  672. // E_OUTOFMEMORY Fetching rows failed because of memory alloccation problem,
  673. // E_FAIL fetching rows failed for some other reason,
  674. // DB_E_ROWSNOTRELEASED Previous rowhandles were not release as
  675. // required by the rowset type,
  676. // DB_E_CANTFETCHBACKWARD cRows was negative and the rowset cannot fetch backward,
  677. // DB_E_CANTSCROLLBACKWARD cRowsToSkip was negative and the rowset
  678. // cannot scroll backward,
  679. // OTHER | other result codes returned by called functions.
  680. /////////////////////////////////////////////////////////////////////////////////////////////////
  681. STDMETHODIMP CImpIRowsetLocate::GetRowsAt (HWATCHREGION hReserved1,
  682. HCHAPTER hChapter,
  683. DBBKMARK cbBookmark,
  684. const BYTE * pBookmark,
  685. DBROWOFFSET lRowsOffset,
  686. DBROWCOUNT cRows,
  687. DBCOUNTITEM * pcRowsObtained,
  688. HROW ** prghRows)
  689. {
  690. HRESULT hr = S_OK;
  691. CSetStructuredExceptionHandler seh;
  692. TRY_BLOCK;
  693. // Serialize the object
  694. CAutoBlock cab(ROWSET->GetCriticalSection() );
  695. // Clear previous Error Object for this thread
  696. g_pCError->ClearErrorInfo();
  697. if(m_pObj->IsZoombie())
  698. {
  699. hr = E_UNEXPECTED;
  700. }
  701. else
  702. // Initialize pointer argument.
  703. if (pcRowsObtained)
  704. {
  705. *pcRowsObtained = 0;
  706. }
  707. //========================================================================
  708. // Check the HChapter is of the current rowset is valid
  709. //========================================================================
  710. if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
  711. m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
  712. {
  713. hr = DB_E_BADCHAPTER;
  714. //return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
  715. }
  716. else
  717. if ( (pcRowsObtained == NULL || prghRows == NULL) || // Check validity of pointer arguments.
  718. (cbBookmark == 0 || pBookmark == NULL)) // Is bookmark valid?
  719. {
  720. hr = E_INVALIDARG;
  721. //return g_pCError->PostHResult(E_INVALIDARG, &IID_IRowsetLocate);
  722. }
  723. else
  724. {
  725. //========================================================================
  726. // Check the rowset parameters to see if we support this request
  727. //========================================================================
  728. if( S_OK == (hr = CheckParameters(pcRowsObtained, lRowsOffset, cRows, prghRows)))
  729. {
  730. if(hChapter)
  731. {
  732. hr = m_pObj->CheckAndInitializeChapter(hChapter);
  733. /* if(FAILED(hr))
  734. return g_pCError->PostHResult(hr, &IID_IRowsetLocate);
  735. */ }
  736. if(SUCCEEDED(hr))
  737. {
  738. // Create the data members to manage the data only the first time
  739. if(!m_pObj->m_bHelperFunctionCreated)
  740. {
  741. if( SUCCEEDED(hr = m_pObj->CreateHelperFunctions()))
  742. m_pObj->m_bHelperFunctionCreated = TRUE;
  743. }
  744. if(SUCCEEDED(hr))
  745. {
  746. //========================================================================
  747. // Are there any unreleased rows?
  748. //========================================================================
  749. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
  750. {
  751. hr = DB_E_ROWSNOTRELEASED;
  752. //return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
  753. }
  754. else
  755. {
  756. // call the function to fetch rows by bookmark
  757. hr = m_pObj->m_pRowFetchObj->FetchNextRowsByBookMark( m_pObj,
  758. hChapter,
  759. cbBookmark,
  760. pBookmark,
  761. lRowsOffset,
  762. cRows,
  763. pcRowsObtained,
  764. prghRows);
  765. } // Rows not released with CANHOLDROWS set to false
  766. } // If succeded(hr) if CreateHelperFunction called
  767. } // if Succeeded(hr) after initializing the chapter if any
  768. } // If(CheckParameters())
  769. } // Else for if validating some arguments
  770. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
  771. CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::GetRowsAt");
  772. return hr;
  773. }
  774. /////////////////////////////////////////////////////////////////////////////////////////////////
  775. // CImpIRowsetScroll::GetRowsByBookmark
  776. //
  777. // Fetches rows with specified bookmarks.
  778. //
  779. // Returns one of the following values:
  780. // S_OK Getting rows succeeded,
  781. // DB_S_ERRORSOCCURRED Getting rows succeeded but there were errors
  782. // associated with some returned rows,
  783. // E_INVALIDARG Getting rows failed because pcRowsObtained
  784. // or prghRows was a NULL pointer, or
  785. // cRows was not zero and either rgcbBookmarks
  786. // or rgpBookmarks was a NULL pointer, or
  787. // fReturnErrors was TRUE and either pcErrors or
  788. // prgErrors was a NULL pointer,
  789. // E_OUTOFMEMORY Getting rows failed because memory for
  790. // holding row handles could not be allocated,
  791. // or memory for error structures could not
  792. // be allocated,
  793. // DB_E_ROWSNOTRELEASED Getting rows failed because previous rowhandles
  794. // were not released as required by the rowset type,
  795. // OTHER Other result codes returned by called functions.
  796. /////////////////////////////////////////////////////////////////////////////////////////////////
  797. STDMETHODIMP CImpIRowsetLocate::GetRowsByBookmark (HCHAPTER hChapter,
  798. DBCOUNTITEM cRows,
  799. const DBBKMARK rgcbBookmarks[],
  800. const BYTE * rgpBookmarks[],
  801. HROW rghRows[],
  802. DBROWSTATUS rgRowStatus[])
  803. {
  804. HRESULT hr = S_OK;
  805. CSetStructuredExceptionHandler seh;
  806. TRY_BLOCK;
  807. // Serialize the object
  808. CAutoBlock cab(ROWSET->GetCriticalSection() );
  809. // Clear previous Error Object for this thread
  810. g_pCError->ClearErrorInfo();
  811. if(m_pObj->IsZoombie())
  812. {
  813. hr = E_UNEXPECTED;
  814. }
  815. else
  816. //===========================================================================
  817. // No-op case always succeeds.
  818. //===========================================================================
  819. if ( cRows == 0 ){
  820. hr = S_OK ;
  821. }
  822. else
  823. //========================================================================
  824. // Check the HChapter is of the current rowset is valid
  825. //========================================================================
  826. if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
  827. m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
  828. {
  829. hr = DB_E_BADCHAPTER;
  830. //return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
  831. }
  832. else
  833. //===========================================================================
  834. // This implementation doesn't support scrolling backward. if the CANFETCHBACKWARDS is false
  835. //===========================================================================
  836. if((LONG_PTR)cRows < 0 && !(m_pObj->m_ulProps & CANFETCHBACKWARDS) )
  837. {
  838. hr = DB_E_CANTFETCHBACKWARDS;
  839. //return g_pCError->PostHResult(DB_E_CANTFETCHBACKWARDS,&IID_IRowsetLocate);
  840. }
  841. else
  842. if( (rghRows == NULL) || // Check validity of pointer arguments.
  843. (rgcbBookmarks == NULL || rgpBookmarks == NULL)) // If more than zero rows required pointers to bookmarks must be real.
  844. {
  845. hr = E_INVALIDARG;
  846. //return g_pCError->PostHResult(E_INVALIDARG,&IID_IRowsetLocate);
  847. }
  848. else
  849. // Must detect unreleased rows in cases when holding them over is illegal.
  850. if (!(m_pObj->m_ulProps & CANHOLDROWS))
  851. {
  852. hr = DB_E_ROWSNOTRELEASED;
  853. //return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
  854. }
  855. else
  856. {
  857. // Initialize the Chapters if the rowset is chaptered rowset
  858. if(hChapter)
  859. {
  860. hr = m_pObj->CheckAndInitializeChapter(hChapter);
  861. }
  862. if(SUCCEEDED(hr))
  863. {
  864. // Create the data members to manage the data only the first time
  865. if(!m_pObj->m_bHelperFunctionCreated)
  866. {
  867. if(SUCCEEDED(hr = m_pObj->CreateHelperFunctions()))
  868. m_pObj->m_bHelperFunctionCreated = TRUE;
  869. }
  870. if(SUCCEEDED(hr))
  871. {
  872. //========================================================================
  873. // Are there any unreleased rows?
  874. //========================================================================
  875. if( ((m_pObj->m_pIAccessor->GetBitArrayPtr())->ArrayEmpty() != S_OK) && !(m_pObj->m_ulProps & CANHOLDROWS) )
  876. {
  877. hr = DB_E_ROWSNOTRELEASED;
  878. // return g_pCError->PostHResult(DB_E_ROWSNOTRELEASED, &IID_IRowsetLocate);
  879. }
  880. else
  881. {
  882. hr = m_pObj->m_pRowFetchObj->FetchRowsByBookMark(m_pObj,hChapter,cRows,rgcbBookmarks,rgpBookmarks,rghRows,rgRowStatus);
  883. }
  884. } // if(SUCCEEDED(hr)) after calling CreateHelperFunction()
  885. } // if(Succeeded(hr)) after initializing chapters if any
  886. } // Else for check of parameters
  887. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
  888. CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::GetRowsByBookMark");
  889. return hr;
  890. }
  891. /////////////////////////////////////////////////////////////////////////////////////////////////
  892. //
  893. // Returns hash values for the specified bookmarks.
  894. //
  895. // Returns one of the following values:
  896. // S_OK Getting hash succeeded,
  897. // DB_S_ERRORSOCCURED At least one bookmark was successfully hashed
  898. // but an element of rgcbBookmarks was 0, or
  899. // an element of rgpBookmarks was null pointer, or
  900. // an element of rgpBookmarks pointed to a
  901. // standard bookmark,
  902. // E_INVALIDARG cBookmarks was not 0 and rgcbBookmarks or
  903. // rgpBookmarks was a null pointer, or
  904. // prgHashedValues was a null pointer,
  905. // DB_E_ERRORSOCCURED No bookmarks were successfully hashed,
  906. // OTHER other result codes returned by called functions.
  907. /////////////////////////////////////////////////////////////////////////////////////////////////
  908. STDMETHODIMP CImpIRowsetLocate::Hash (HCHAPTER hChapter,
  909. DBBKMARK cBookmarks,
  910. const DBBKMARK rgcbBookmarks[],
  911. const BYTE * rgpBookmarks[],
  912. DBHASHVALUE rgHashedValues[],
  913. DBROWSTATUS rgBookmarkStatus[])
  914. {
  915. ULONG iBmk, cErrors;
  916. HRESULT hr;
  917. CSetStructuredExceptionHandler seh;
  918. TRY_BLOCK;
  919. // Serialize the object
  920. CAutoBlock cab(ROWSET->GetCriticalSection() );
  921. // Clear previous Error Object for this thread
  922. g_pCError->ClearErrorInfo();
  923. if(m_pObj->IsZoombie())
  924. {
  925. hr = E_UNEXPECTED;
  926. }
  927. else
  928. //========================================================================
  929. // Check the HChapter is of the current rowset is valid
  930. //========================================================================
  931. if((m_pObj->m_bIsChildRs == TRUE && hChapter == DB_NULL_HCHAPTER) || (LONG_PTR)hChapter < 0 ||
  932. m_pObj->m_bIsChildRs == FALSE && hChapter != 0)
  933. {
  934. hr = DB_E_BADCHAPTER;
  935. //return g_pCError->PostHResult(DB_E_BADCHAPTER,&IID_IRowsetLocate);
  936. }
  937. else
  938. // Check arguments
  939. if ( (cBookmarks && (rgcbBookmarks == NULL || rgpBookmarks == NULL))
  940. || (rgHashedValues == NULL))
  941. {
  942. hr = E_INVALIDARG;
  943. //return g_pCError->PostHResult(E_INVALIDARG, &IID_IRowsetLocate);
  944. }
  945. else
  946. {
  947. cErrors = 0;
  948. //=================================================================
  949. // Initialize the BookMarkStatus if valid pointer is passed
  950. //=================================================================
  951. if (rgBookmarkStatus)
  952. {
  953. for (iBmk =0; iBmk <cBookmarks; iBmk++)
  954. rgBookmarkStatus[iBmk] = DBROWSTATUS_S_OK;
  955. }
  956. // Loop through the array of bookmarks hashing 'em and recording
  957. // their status.
  958. for (iBmk =0; iBmk <cBookmarks; iBmk++)
  959. {
  960. hr = m_pObj->m_pHashTblBkmark->HashBmk(rgcbBookmarks[iBmk],
  961. rgpBookmarks[iBmk],
  962. &(rgHashedValues[iBmk]));
  963. if (FAILED(hr))
  964. {
  965. cErrors++;
  966. if (rgBookmarkStatus)
  967. {
  968. rgBookmarkStatus[iBmk] = DBROWSTATUS_E_INVALID;
  969. }
  970. }
  971. }
  972. hr = cErrors
  973. ? (cErrors <cBookmarks)
  974. ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED
  975. : S_OK;
  976. } // Else for Validating arguments
  977. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IRowsetLocate);
  978. CATCH_BLOCK_HRESULT(hr,L"IRowsetLocate::Hash");
  979. return hr;
  980. }
  981. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  982. // Check the input parameters
  983. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  984. HRESULT CImpIRowsetLocate::CheckParameters(DBCOUNTITEM * pcRowsObtained, DBROWOFFSET lRowOffset, DBROWCOUNT cRows,HROW **prghRows )
  985. {
  986. HRESULT hr = S_OK;
  987. //===========================================================================
  988. // init out-params
  989. //===========================================================================
  990. if ( pcRowsObtained ){
  991. *pcRowsObtained = 0;
  992. }
  993. //===========================================================================
  994. // Check validity of arguments.
  995. //===========================================================================
  996. if ( pcRowsObtained == NULL || prghRows == NULL )
  997. {
  998. hr = E_INVALIDARG;
  999. //return E_INVALIDARG ;
  1000. }
  1001. else
  1002. //===========================================================================
  1003. // No-op case always succeeds.
  1004. //===========================================================================
  1005. if ( cRows == 0 )
  1006. {
  1007. hr = S_OK;
  1008. //return S_OK ;
  1009. }
  1010. else
  1011. //===========================================================================
  1012. // This implementation doesn't support scrolling backward. if the CANFETCHBACKWARDS is false
  1013. //===========================================================================
  1014. if((LONG_PTR)cRows < 0 && !(m_pObj->m_ulProps & CANFETCHBACKWARDS) )
  1015. {
  1016. hr = DB_E_CANTFETCHBACKWARDS;
  1017. //return DB_E_CANTFETCHBACKWARDS ;
  1018. }
  1019. else
  1020. //===========================================================================
  1021. // This implementation doesn't support scrolling backward.if the CANTSCROLLBACKWARDS is false
  1022. //===========================================================================
  1023. if ( lRowOffset < 0 && !(m_pObj->m_ulProps & CANSCROLLBACKWARDS) )
  1024. {
  1025. hr = DB_E_CANTSCROLLBACKWARDS;
  1026. //return DB_E_CANTSCROLLBACKWARDS ;
  1027. }
  1028. //===========================================================================
  1029. // return success
  1030. //===========================================================================
  1031. return hr;
  1032. }