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.

491 lines
16 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // CInstanceRowFetchObj object implementation
  7. //
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "WmiOleDBMap.h"
  12. ///////////////////////////////////////////////////////////////////////////////////////
  13. // Function which fetches required number of rows
  14. ///////////////////////////////////////////////////////////////////////////////////////
  15. HRESULT CInstanceRowFetchObj::FetchRows(CRowset * pRowset,
  16. HCHAPTER hChapter, // IN The Chapter handle.
  17. DBROWOFFSET lRowOffset, // IN Rows to skip before reading
  18. DBROWCOUNT cRows, // IN Number of rows to fetch
  19. DBCOUNTITEM* pcRowsObtained, // OUT Number of rows obtained
  20. HROW ** prghRows) // OUT Array of Hrows obtained)
  21. {
  22. DBCOUNTITEM cRowsTmp = 0;
  23. HROW irow(0), ih(0);
  24. PROWBUFF prowbuff = NULL;
  25. HRESULT hr = S_OK;
  26. HROW *prghRowsTemp = NULL;
  27. HROW hRowCurrent = 0;
  28. HSLOT hSlot = -1;
  29. BOOL bAlreadyDataRetrieved = FALSE;
  30. BOOL bAlreadyFetched = FALSE;
  31. CVARIANT varKey;
  32. BOOL bFetchBack = FALSE;
  33. HROW hRowTemp = 0;
  34. CBSTR strKey;
  35. LONG_PTR lFetchPos = 0;
  36. DBROWCOUNT ulMax = 0;
  37. BOOL bMaxRowsExceed = FALSE;
  38. DBSTATUS dwStat = DBSTATUS_S_OK;
  39. BOOL bHRowsAllocated = FALSE;
  40. CWbemClassWrapper *pInst = NULL;
  41. if(cRows != 0)
  42. {
  43. {
  44. VARIANT varTemp;
  45. VariantInit(&varTemp);
  46. pRowset->GetRowsetProperty(DBPROP_MAXOPENROWS,varTemp);
  47. ulMax = varTemp.lVal;
  48. VariantClear(&varTemp);
  49. }
  50. //=======================================================
  51. // If already maximum rows are opened then return
  52. //=======================================================
  53. if( pRowset->m_ulRowRefCount >= (DBROWCOUNT)ulMax)
  54. {
  55. hr = DB_S_ROWLIMITEXCEEDED;
  56. }
  57. else
  58. {
  59. //========================
  60. // Fetch Data
  61. //========================
  62. if (lRowOffset)
  63. {
  64. //===================================
  65. // Calculate the new position
  66. //===================================
  67. hr = pRowset->ResetRowsetToNewPosition(lRowOffset,pInst);
  68. if( FAILED(hr))
  69. {
  70. pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
  71. hr = DB_S_ENDOFROWSET ;
  72. }
  73. }
  74. // 07/11/00
  75. //141938
  76. if(hr == S_OK)
  77. {
  78. if(0 >( lFetchPos = GetFirstFetchPos(pRowset,cRows,lRowOffset)))
  79. {
  80. hr = DB_E_BADSTARTPOSITION;
  81. }
  82. else
  83. {
  84. cRowsTmp = cRows >= 0 ? cRows : cRows * (-1);
  85. ulMax = ulMax - pRowset->m_ulRowRefCount;
  86. if(ulMax < (DBROWCOUNT)cRowsTmp)
  87. {
  88. bMaxRowsExceed = TRUE;
  89. }
  90. else
  91. {
  92. ulMax = cRowsTmp;
  93. }
  94. cRowsTmp = 0;
  95. //=======================================================================
  96. // If any rows is to be retrieved then allocate memory for the HROWS
  97. //=======================================================================
  98. if (ulMax )
  99. {
  100. try
  101. {
  102. prghRowsTemp = (HROW *) g_pIMalloc->Alloc( ulMax * sizeof( HROW ));
  103. }
  104. catch(...)
  105. {
  106. if(prghRowsTemp != NULL)
  107. {
  108. g_pIMalloc->Free(prghRowsTemp);
  109. }
  110. throw;
  111. }
  112. }
  113. if(prghRowsTemp == NULL)
  114. {
  115. hr = E_OUTOFMEMORY;
  116. }
  117. else
  118. {
  119. memset(prghRowsTemp,0,ulMax * sizeof(HROW));
  120. pRowset->m_FetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD;
  121. bFetchBack = (LONG_PTR)cRows < 0 ? TRUE : FALSE;
  122. hRowTemp = pRowset->m_hRowLastFetched;
  123. for (irow =1; irow <= (ULONG)ulMax; irow++)
  124. {
  125. bAlreadyFetched = FALSE;
  126. bAlreadyDataRetrieved = FALSE;
  127. dwStat = DBSTATUS_S_OK;
  128. //============================================================
  129. // Get the pointer to the next instance
  130. //============================================================
  131. if (S_OK != ( hr = pRowset->GetNextInstance(pInst,strKey,bFetchBack)))
  132. {
  133. pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
  134. hr = DB_S_ENDOFROWSET;
  135. break;
  136. }
  137. //==========================================================================
  138. // If the instance is a deleted instance and deleted instance is to be
  139. // removed then continue to the next instance
  140. // If the rowset is opened in dyanamic cursor mode then skipping of
  141. // deleted row doesn't depend on REMOVEDELETED
  142. //==========================================================================
  143. if(pRowset->IsInstanceDeleted(pInst) &&
  144. (pRowset->m_ulProps & OTHERINSERT) ||
  145. ( pRowset->m_ulProps & REMOVEDELETED) )
  146. {
  147. irow--;
  148. continue;
  149. }
  150. //=================================================================
  151. // Check if instance already exist
  152. //=================================================================
  153. bAlreadyFetched = pRowset->m_InstMgr->IsInstanceExist(strKey);
  154. //==========================================================================
  155. // If not able to find the instance by key ( key might change sometime
  156. // in some cases if all the properties are keys) So check if the instance
  157. // is already fetched by the instance pointers
  158. //==========================================================================
  159. if(bAlreadyFetched == FALSE)
  160. {
  161. bAlreadyFetched = pRowset->m_InstMgr->IsInstanceExist(pInst );
  162. //==========================================================================
  163. // if found the instance has to be refreshed
  164. //==========================================================================
  165. if(bAlreadyFetched == TRUE)
  166. {
  167. pRowset->RefreshInstance(pInst);
  168. }
  169. }
  170. //==================================================================
  171. // if already exists get the HROW and slot number for the instance
  172. //==================================================================
  173. if(bAlreadyFetched == TRUE)
  174. {
  175. hRowCurrent = pRowset->m_InstMgr->GetHRow(strKey);
  176. if((pRowset->GetRowStatus(hRowCurrent) & DBROWSTATUS_E_DELETED) && ( pRowset->m_ulProps & REMOVEDELETED))
  177. {
  178. continue;
  179. }
  180. //=================================================================
  181. // if the slot number for the instance exist this means thet
  182. // data is already retrieved for the row
  183. //=================================================================
  184. if((hSlot = pRowset->m_InstMgr->GetSlot(hRowCurrent)) != -1)
  185. {
  186. bAlreadyDataRetrieved = TRUE;
  187. }
  188. }
  189. else
  190. {
  191. hRowCurrent = pRowset->GetNextHRow();
  192. }
  193. //=====================================================
  194. // Get the data if data is already not fetched
  195. //=====================================================
  196. if(bAlreadyDataRetrieved == FALSE)
  197. {
  198. hSlot = -1;
  199. //============================================
  200. // Get the next slot for retrieving data and
  201. // bind it to the column mem manager
  202. //============================================
  203. if (FAILED( hr = GetNextSlots( pRowset->m_pIBuffer, 1, &hSlot )))
  204. {
  205. break;
  206. }
  207. if (FAILED( pRowset->Rebind((BYTE *) pRowset->GetRowBuffFromSlot( hSlot, TRUE ))))
  208. {
  209. hr = E_FAIL;
  210. break;
  211. }
  212. hRowCurrent = hSlot;
  213. //=========================================================
  214. // fill the bookmark with keyvalue of the instance
  215. //=========================================================
  216. varKey.SetStr(strKey);
  217. //=================================================================================================
  218. // if the other updates visible property is set to false ,then get the data to the local buffer
  219. //=================================================================================================
  220. if(!( pRowset->m_ulProps & OTHERUPDATEDELETE))
  221. {
  222. if(FAILED(hr = pRowset->GetInstanceDataToLocalBuffer(pInst,hSlot)))
  223. {
  224. break;
  225. }
  226. //===========================================================================
  227. // if there is atleast one row retrieved and there are neseted columns
  228. // then allocate rows for the child recordsets
  229. //===========================================================================
  230. if(pRowset->m_cNestedCols > 0 )
  231. {
  232. if(pRowset->m_ppChildRowsets == NULL)
  233. {
  234. pRowset->AllocateAndInitializeChildRowsets();
  235. }
  236. //=====================================================================
  237. // Fill the HCHAPTERS for the column
  238. //=====================================================================
  239. if(FAILED(hr = pRowset->FillHChaptersForRow(pInst,strKey)))
  240. {
  241. break;
  242. }
  243. }
  244. }
  245. //=================================================
  246. // add instance pointer to instance manager
  247. //=================================================
  248. if(FAILED(hr = pRowset->m_InstMgr->AddInstanceToList(hRowCurrent,pInst,strKey,hSlot)))
  249. {
  250. break;
  251. }
  252. //=====================================================
  253. // if the row is deleted then set the row status
  254. //=====================================================
  255. if(pRowset->IsInstanceDeleted(pInst) && SUCCEEDED(hr))
  256. {
  257. pRowset->SetRowStatus(hRowCurrent,DBROWSTATUS_E_DELETED);
  258. }
  259. varKey.Clear();
  260. }
  261. prghRowsTemp[irow-1] = hSlot;
  262. strKey.Clear();
  263. strKey.Unbind();
  264. }
  265. if(SUCCEEDED(hr))
  266. {
  267. cRowsTmp = irow - 1; //Irow will be +1 because of For Loop
  268. //=====================================================================
  269. // Through fetching many rows of data
  270. //
  271. // Allocate row handles for client. Note that we need to use IMalloc
  272. // for this. Should only malloc cRowsTmp, instead of cRows.
  273. // Should malloc cRows, since client will assume it's that big.
  274. //=====================================================================
  275. if ( *prghRows == NULL && cRowsTmp )
  276. {
  277. try
  278. {
  279. *prghRows = (HROW *) g_pIMalloc->Alloc( cRowsTmp * sizeof( HROW ));
  280. }
  281. catch(...)
  282. {
  283. if(*prghRows)
  284. {
  285. g_pIMalloc->Free(*prghRows);
  286. }
  287. throw;
  288. }
  289. bHRowsAllocated = TRUE;
  290. }
  291. if ( *prghRows == NULL && cRowsTmp )
  292. {
  293. hr = E_OUTOFMEMORY ;
  294. }
  295. else
  296. {
  297. memset(*prghRows,0,cRowsTmp * sizeof( HROW ));
  298. //=====================================================================
  299. // Fill in the status information: Length, IsNull. May be able to wait
  300. // until first call to GetData, but have to do it sometime.
  301. //
  302. // Suggest keeping an array of structs of accessor info. One element is
  303. // whether accessor requires any status info or length info.
  304. //
  305. // Then we could skip this whole section.
  306. //
  307. // Added check for cRowsTmp to MarkRows call. Don't want to call if
  308. // cRowsTmp==0.
  309. // (Range passed to MarkRows is inclusive, so can't specify marking 0 rows.)
  310. //
  311. // Note that SetSlots is a CBitArray member function -- not an IBuffer function.
  312. //
  313. // Bits are [0...n-1], row handles are [1...n].
  314. //
  315. // Cleanup. Row handles, bits, indices are the same [m....(m+n)], where
  316. // m is some # >0,
  317. //
  318. // Added row-wise reference counts and cursor-wise reference counts.
  319. //
  320. // Set row handles, fix data length field and compute data status field.
  321. //=======================================================================
  322. pRowset->m_cRows = cRowsTmp;
  323. for (ih =0; ih < (ULONG) pRowset->m_cRows; ih++)
  324. {
  325. //=============================================================================
  326. // Increment the rows-read count,
  327. // then store it as the bookmark in the very first DWORD of the row.
  328. //=============================================================================
  329. prowbuff = pRowset->GetRowBuff( prghRowsTemp[ih], TRUE );
  330. //=======================================================================================
  331. // Insert the bookmark and its row number (from 1...n) into a hash table.
  332. // This allows us to quickly determine the presence of a row in mem, given the bookmark.
  333. // The bookmark is contained in the row buffer, at the very beginning.
  334. // Bookmark is the row number within the entire result set [1...num_rows_read].
  335. // This was a new Bookmark, not in memory,
  336. // so return to user (in *prghRows) the hRow we stored.
  337. //=======================================================================================
  338. prowbuff->ulRefCount++;
  339. pRowset->m_ulRowRefCount++;
  340. (*prghRows)[ih] = prghRowsTemp[ih]; // (HROW) ( irow );
  341. pRowset->m_hRowLastFetched = prghRowsTemp[ih];
  342. if(pRowset->m_ulProps & BOOKMARKPROP)
  343. {
  344. if(ih != 0)
  345. {
  346. lFetchPos = (pRowset->m_FetchDir == FETCHDIRFORWARD ) ? lFetchPos + 1 : lFetchPos -1;
  347. }
  348. prowbuff->dwBmk = lFetchPos;
  349. prowbuff->cbBmk = BOOKMARKSIZE;
  350. pRowset->m_lLastFetchPos = lFetchPos;
  351. // Add bookmark to the hashtable
  352. pRowset->m_pHashTblBkmark->InsertFindBmk(FALSE,prghRowsTemp[ih],prowbuff->cbBmk,(BYTE *)&(prowbuff->dwBmk),(ULONG_PTR*)&hSlot);
  353. }
  354. }
  355. } // If proper allocation of *prghRows if required
  356. } // If succeeded(hr) after the loop
  357. if(SUCCEEDED(hr))
  358. {
  359. *pcRowsObtained = cRowsTmp;
  360. }
  361. //=====================================================
  362. // if the number of rows asked is more than
  363. // the max number of open rows and if there
  364. // is no error then set the error number
  365. //=====================================================
  366. if( hr == S_OK && bMaxRowsExceed == TRUE)
  367. {
  368. hr = DB_S_ROWLIMITEXCEEDED;
  369. }
  370. } // Else for check for proper allocation prghRowsTemp
  371. } // Else for check for DB_E_BADSTARTPOSITION
  372. }
  373. }
  374. } // if cRow > 0
  375. // IF failed clean up
  376. if( FAILED(hr))
  377. {
  378. for (ih =0; ih < (ULONG) cRowsTmp; ih++)
  379. {
  380. if(prghRowsTemp[ih] != 0)
  381. {
  382. pRowset->m_InstMgr->DeleteInstanceFromList(prghRowsTemp[ih]);
  383. }
  384. }
  385. if(pcRowsObtained)
  386. {
  387. *pcRowsObtained = 0;
  388. }
  389. if(prghRows && bHRowsAllocated == TRUE)
  390. {
  391. g_pIMalloc->Free(prghRows);
  392. prghRows = NULL;
  393. }
  394. else
  395. if(prghRows)
  396. {
  397. *prghRows = NULL;
  398. }
  399. if(pcRowsObtained)
  400. {
  401. *pcRowsObtained = 0;
  402. }
  403. }
  404. //==============================================
  405. // free the temporary memory allocated
  406. //==============================================
  407. if(prghRowsTemp)
  408. {
  409. g_pIMalloc->Free(prghRowsTemp);
  410. prghRowsTemp = NULL;
  411. }
  412. // reset the starting position to the original position
  413. if(lRowOffset && (FAILED(hr) || (hr != S_OK && cRowsTmp == 0)))
  414. {
  415. pRowset->ResetRowsetToNewPosition(lRowOffset * (-1),pInst);
  416. }
  417. return hr;
  418. }