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.

526 lines
15 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // CQualifierRowFetchObj 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 CQualifierRowFetchObj::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, ih;
  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;
  34. BSTR strQualifier;
  35. CBSTR strKey;
  36. LONG_PTR lFetchPos = 0;
  37. BOOL bHRowsAllocated = FALSE;
  38. DBROWCOUNT ulMax = 0;
  39. BOOL bMaxRowsExceed = 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. if(pRowset->m_bIsChildRs == FALSE)
  60. {
  61. assert(pRowset->m_pInstance != NULL);
  62. }
  63. //========================
  64. // Fetch Data
  65. //========================
  66. if (lRowOffset)
  67. {
  68. if(hChapter > 0)
  69. {
  70. pInst = pRowset->m_pChapterMgr->GetInstance(hChapter);
  71. }
  72. else
  73. if(pRowset->m_bIsChildRs == FALSE)
  74. {
  75. pInst = pRowset->m_pInstance;
  76. }
  77. //===================================
  78. // Calculate the new position
  79. //===================================
  80. hr = pRowset->ResetRowsetToNewPosition(lRowOffset,pInst);
  81. if( hr != S_OK )
  82. {
  83. pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
  84. hr = DB_S_ENDOFROWSET ;
  85. }
  86. }
  87. if(hr == S_OK)
  88. {
  89. if(0 >( lFetchPos = GetFirstFetchPos(pRowset,cRows,lRowOffset)))
  90. {
  91. hr = DB_E_BADSTARTPOSITION;
  92. }
  93. else
  94. {
  95. cRowsTmp = cRows >= 0 ? cRows : cRows * (-1);
  96. ulMax = ulMax - pRowset->m_ulRowRefCount;
  97. if(ulMax < (DBROWCOUNT)cRowsTmp)
  98. {
  99. bMaxRowsExceed = TRUE;
  100. }
  101. else
  102. {
  103. ulMax = cRowsTmp;
  104. }
  105. cRowsTmp = 0;
  106. pRowset->m_FetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD;
  107. bFetchBack = (LONG_PTR)cRows < 0 ? TRUE : FALSE;
  108. // cRows = cRows >=0 ? cRows : cRows * (-1);
  109. //=======================================================================
  110. // If any rows is to be retrieved then allocate memory for the HROWS
  111. //=======================================================================
  112. if (ulMax )
  113. {
  114. try
  115. {
  116. prghRowsTemp = (HROW *) g_pIMalloc->Alloc( ulMax * sizeof( HROW ));
  117. }
  118. catch(...)
  119. {
  120. if(prghRowsTemp != NULL)
  121. {
  122. g_pIMalloc->Free(prghRowsTemp);
  123. }
  124. throw;
  125. }
  126. }
  127. if(prghRowsTemp == NULL)
  128. {
  129. hr = E_OUTOFMEMORY;
  130. }
  131. }
  132. if(SUCCEEDED(hr))
  133. {
  134. memset(prghRowsTemp,0,ulMax * sizeof( HROW ));
  135. hRowTemp = pRowset->m_hRowLastFetched;
  136. for (irow =1; irow <= (DBCOUNTITEM)ulMax; irow++)
  137. {
  138. bAlreadyFetched = FALSE;
  139. bAlreadyDataRetrieved = FALSE;
  140. if(pRowset->m_bIsChildRs == TRUE)
  141. {
  142. //==============================================================================
  143. // Find out whether qualifier is already obtained
  144. //==============================================================================
  145. pInst = pRowset->m_pChapterMgr->GetInstance(hChapter);
  146. pRowset->m_pChapterMgr->GetInstanceKey(hChapter,(BSTR *)&strKey);
  147. }
  148. else
  149. if( pRowset->m_pInstance != NULL)
  150. {
  151. pInst = pRowset->m_pInstance;
  152. }
  153. switch(pRowset->m_uRsType)
  154. {
  155. case CLASSQUALIFIER:
  156. hr = pRowset->GetNextClassQualifier(pInst,strQualifier,bFetchBack);
  157. break;
  158. case PROPERTYQUALIFIER:
  159. hr = pRowset->GetNextPropertyQualifier(pInst,pRowset->m_strPropertyName,strQualifier,bFetchBack);
  160. break;
  161. }
  162. if(S_OK != hr)
  163. {
  164. pRowset->SetStatus(hChapter , STAT_ENDOFCURSOR);
  165. hr = DB_S_ENDOFROWSET;
  166. break;
  167. }
  168. if( hr == S_OK)
  169. {
  170. strKey.Clear();
  171. strKey.Unbind();
  172. strKey.SetStr(strQualifier);
  173. if(pRowset->m_bIsChildRs == TRUE)
  174. {
  175. hRowTemp = pRowset->m_pChapterMgr->GetHRow(hChapter,strQualifier);
  176. }
  177. else
  178. {
  179. hRowTemp = pRowset->m_InstMgr->GetHRow(strQualifier);
  180. }
  181. if( (LONG)hRowTemp > 0)
  182. {
  183. bAlreadyFetched = TRUE;
  184. }
  185. }
  186. if( bAlreadyFetched == TRUE)
  187. {
  188. hRowCurrent = hRowTemp;
  189. if(pRowset->m_bIsChildRs == TRUE)
  190. {
  191. hSlot = pRowset->m_pChapterMgr->GetSlot(hRowCurrent);
  192. }
  193. else
  194. {
  195. hSlot = pRowset->m_InstMgr->GetSlot(hRowCurrent);
  196. }
  197. if( hSlot != -1)
  198. {
  199. bAlreadyDataRetrieved = TRUE;
  200. }
  201. }
  202. //====================================================
  203. // Get the HROW if row is not already fetched
  204. //====================================================
  205. if( bAlreadyFetched == FALSE)
  206. hRowCurrent = pRowset->GetNextHRow();
  207. //=====================================================
  208. // Get the data if data is already not fetched
  209. //=====================================================
  210. if(bAlreadyDataRetrieved == FALSE)
  211. {
  212. hSlot = -1;
  213. if (SUCCEEDED( hr = GetNextSlots( pRowset->m_pIBuffer, 1, &hSlot )))
  214. {
  215. if (FAILED( pRowset->Rebind((BYTE *) pRowset->GetRowBuffFromSlot( hSlot, TRUE ))))
  216. {
  217. hr = E_FAIL;
  218. break;
  219. }
  220. }
  221. else
  222. {
  223. break;
  224. }
  225. hRowCurrent = hSlot;
  226. //=================================================================================================
  227. // if the other updates visible property is set to false ,then get the data to the local buffer
  228. //=================================================================================================
  229. if(!( pRowset->m_ulProps & OTHERUPDATEDELETE))
  230. {
  231. if(FAILED(hr = pRowset->GetInstanceDataToLocalBuffer(pInst,hSlot,strQualifier)))
  232. {
  233. break;
  234. }
  235. //===========================================================================
  236. // if there is atleast one row retrieved and there are neseted columns
  237. // then allocate rows for the child recordsets
  238. //===========================================================================
  239. if(pRowset->m_cNestedCols > 0 )
  240. {
  241. if(pRowset->m_ppChildRowsets == NULL)
  242. {
  243. pRowset->AllocateAndInitializeChildRowsets();
  244. }
  245. //=====================================================================
  246. // Fill the HCHAPTERS for the column
  247. //=====================================================================
  248. if(S_OK != (hr = pRowset->FillHChaptersForRow(pInst,strKey)))
  249. {
  250. break;
  251. }
  252. }
  253. }
  254. if(SUCCEEDED(hr))
  255. {
  256. //===================================================
  257. // if the rowset is not a child rowset
  258. //===================================================
  259. if(pRowset->m_bIsChildRs == FALSE)
  260. {
  261. //=================================================
  262. // add instance pointer to instance manager
  263. //=================================================
  264. if(FAILED(hr = pRowset->m_InstMgr->AddInstanceToList(hRowCurrent,pInst,strQualifier,hSlot)))
  265. {
  266. break;
  267. }
  268. }
  269. //=================================================================================
  270. // if rowset is refering to qualifiers then add the row to the particular chapter
  271. //=================================================================================
  272. else
  273. {
  274. // add instance pointer to instance manager
  275. if(FAILED(hr = pRowset->m_pChapterMgr->AddHRowForChapter(hChapter,hRowCurrent, NULL ,hSlot)))
  276. {
  277. break;
  278. }
  279. pRowset->m_pChapterMgr->SetInstance(hChapter,pInst, strQualifier ,hRowCurrent);
  280. }
  281. }
  282. } //if(bAlreadyDataRetrieved == FALSE)
  283. // prghRowsTemp[irow-1] = hRowCurrent;
  284. prghRowsTemp[irow-1] = hSlot;
  285. SysFreeString(strQualifier);
  286. strKey.Clear();
  287. strKey.Unbind();
  288. strQualifier = Wmioledb_SysAllocString(NULL);
  289. }
  290. if(SUCCEEDED(hr))
  291. {
  292. cRowsTmp = irow - 1; //Irow will be +1 because of For Loop
  293. //=====================================================================
  294. // Through fetching many rows of data
  295. //
  296. // Allocate row handles for client. Note that we need to use IMalloc
  297. // for this. Should only malloc cRowsTmp, instead of ulMax.
  298. // Should malloc ulMax, since client will assume it's that big.
  299. //=====================================================================
  300. if ( *prghRows == NULL && cRowsTmp )
  301. {
  302. try
  303. {
  304. *prghRows = (HROW *) g_pIMalloc->Alloc( cRowsTmp * sizeof( HROW ));
  305. }
  306. catch(...)
  307. {
  308. if(*prghRows)
  309. {
  310. g_pIMalloc->Free(prghRows);
  311. }
  312. throw;
  313. }
  314. bHRowsAllocated = TRUE;
  315. memset(*prghRows,0,cRowsTmp * sizeof( HROW ));
  316. }
  317. if ( *prghRows == NULL && cRowsTmp )
  318. {
  319. hr = E_OUTOFMEMORY ;
  320. }
  321. else
  322. {
  323. //=====================================================================
  324. // Fill in the status information: Length, IsNull. May be able to wait
  325. // until first call to GetData, but have to do it sometime.
  326. //
  327. // Suggest keeping an array of structs of accessor info. One element is
  328. // whether accessor requires any status info or length info.
  329. //
  330. // Then we could skip this whole section.
  331. //
  332. // Added check for cRowsTmp to MarkRows call. Don't want to call if
  333. // cRowsTmp==0.
  334. // (Range passed to MarkRows is inclusive, so can't specify marking 0 rows.)
  335. //
  336. // Note that SetSlots is a CBitArray member function -- not an IBuffer function.
  337. //
  338. // Added row-wise reference counts and cursor-wise reference counts.
  339. //
  340. // Set row handles, fix data length field and compute data status field.
  341. //=======================================================================
  342. pRowset->m_cRows = cRowsTmp;
  343. // set the first position if it is zero
  344. if(lFetchPos == 0)
  345. {
  346. lFetchPos = 1;
  347. }
  348. for (ih =0; ih < (ULONG) pRowset->m_cRows; ih++)
  349. {
  350. //=============================================================================
  351. // Increment the rows-read count,
  352. // then store it as the bookmark in the very first DWORD of the row.
  353. //=============================================================================
  354. prowbuff = pRowset->GetRowBuff( prghRowsTemp[ih], TRUE );
  355. //=======================================================================================
  356. // Insert the bookmark and its row number (from 1...n) into a hash table.
  357. // This allows us to quickly determine the presence of a row in mem, given the bookmark.
  358. // The bookmark is contained in the row buffer, at the very beginning.
  359. // Bookmark is the row number within the entire result set [1...num_rows_read].
  360. // This was a new Bookmark, not in memory,
  361. // so return to user (in *prghRows) the hRow we stored.
  362. //=======================================================================================
  363. prowbuff->ulRefCount++;
  364. pRowset->m_ulRowRefCount++;
  365. (*prghRows)[ih] = prghRowsTemp[ih]; // (HROW) ( irow );
  366. pRowset->m_hRowLastFetched = prghRowsTemp[ih];
  367. // if bookmark property is true then initialize the bookmark
  368. if(pRowset->m_ulProps & BOOKMARKPROP)
  369. {
  370. if(ih != 0)
  371. {
  372. lFetchPos = (pRowset->m_FetchDir == FETCHDIRFORWARD ) ? lFetchPos + 1 : lFetchPos -1;
  373. }
  374. prowbuff->dwBmk = lFetchPos;
  375. prowbuff->cbBmk = BOOKMARKSIZE;
  376. pRowset->m_lLastFetchPos = lFetchPos;
  377. // Add bookmark to the hashtable
  378. pRowset->m_pHashTblBkmark->InsertFindBmk(FALSE,prghRowsTemp[ih],prowbuff->cbBmk,(BYTE *)&(prowbuff->dwBmk),(HROW *)&hSlot);
  379. }
  380. } // for loop
  381. } // else for memory allocation for HROWS
  382. } // if(succeeded(hr))
  383. if(SUCCEEDED(hr))
  384. {
  385. *pcRowsObtained = cRowsTmp;
  386. }
  387. //===================================================
  388. // set return value if MAX_ROWS is exceeded
  389. //===================================================
  390. if( hr == S_OK && bMaxRowsExceed == TRUE)
  391. {
  392. hr = DB_S_ROWLIMITEXCEEDED;
  393. }
  394. } // else for some basic parameter checking
  395. } // if(Succeeded(hr)) after setting the resetting offset
  396. } // else after checking for MAX rows limit
  397. } // if(cRows != 0)
  398. //==============================================
  399. // free the temporary memory allocated
  400. //==============================================
  401. if(FAILED(hr))
  402. {
  403. // for(irow = irowFirst ; irow <= hRowTemp ; irow++)
  404. for (ih =0; ih < (ULONG) cRowsTmp; ih++)
  405. {
  406. if(prghRowsTemp[ih] != 0)
  407. {
  408. if(pRowset->m_bIsChildRs == FALSE)
  409. {
  410. pRowset->m_InstMgr->DeleteInstanceFromList(prghRowsTemp[ih]);
  411. }
  412. else
  413. {
  414. pRowset->m_pChapterMgr->DeleteHRow(prghRowsTemp[ih]);
  415. }
  416. }
  417. }
  418. if(pcRowsObtained)
  419. {
  420. *pcRowsObtained = 0;
  421. }
  422. // if HROWS for output parameter is allcated by this method
  423. // then release them
  424. if(prghRows && bHRowsAllocated == TRUE)
  425. {
  426. g_pIMalloc->Free(prghRows);
  427. prghRows = NULL;
  428. }
  429. else
  430. if(prghRows)
  431. {
  432. *prghRows = NULL;
  433. }
  434. if(pcRowsObtained)
  435. {
  436. *pcRowsObtained = 0;
  437. }
  438. if(strQualifier != NULL)
  439. {
  440. SysFreeString(strQualifier);
  441. }
  442. }
  443. //==============================================
  444. // free the temporary memory allocated
  445. //==============================================
  446. if(prghRowsTemp)
  447. {
  448. g_pIMalloc->Free(prghRowsTemp);
  449. prghRowsTemp = NULL;
  450. }
  451. // reset the starting position to the original position
  452. if(lRowOffset && (FAILED(hr) || (hr != S_OK && cRowsTmp == 0)))
  453. {
  454. pRowset->ResetRowsetToNewPosition(lRowOffset * (-1),pInst);
  455. }
  456. return hr;
  457. }