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.

644 lines
21 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // CRowFetchObj class implementation
  7. //
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. #include "WmiOleDBMap.h"
  12. /////////////////////////////////////////////////////////////////////////////////////
  13. ////CRowFetchObj class Implementation
  14. /////////////////////////////////////////////////////////////////////////////////////
  15. ///////////////////////////////////////////////////////////////////////////////////////////
  16. // Function which fetches data and puts it into the given buffer
  17. // NTRaid:111834
  18. // 06/07/00
  19. ///////////////////////////////////////////////////////////////////////////////////////////
  20. HRESULT CRowFetchObj::FetchData(CRowset * pRowset,
  21. HROW hRow, //IN Row Handle
  22. HACCESSOR hAccessor, //IN Accessor to use
  23. void *pData )
  24. {
  25. // NTRaid:111834
  26. // 06/13/00
  27. PACCESSOR pAccessor = NULL;
  28. DBORDINAL icol = 0;
  29. DBORDINAL ibind = 0;
  30. ROWBUFF *pRowBuff = NULL;
  31. COLUMNDATA *pColumnData = NULL;
  32. DBBINDING *pBinding = NULL;
  33. DBROWCOUNT cBindings = NULL;
  34. ULONG ulErrorCount = 0;
  35. DBTYPE dwSrcType = 0;
  36. DBTYPE dwDstType = 0;
  37. void *pSrc = NULL;
  38. void *pDst = NULL;
  39. DBLENGTH ulSrcLength = 0;
  40. DBLENGTH *pulDstLength = NULL;
  41. DBLENGTH ulDstMaxLength = 0;
  42. DBSTATUS dwSrcStatus = 0;
  43. DBSTATUS *pdwDstStatus = NULL;
  44. DWORD dwPart = 0;
  45. HRESULT hr = S_OK;
  46. HSLOT hSlot = 0;
  47. BOOL bUseDataConvert = TRUE;
  48. CWbemClassWrapper * pInst = NULL;
  49. CDataMap dataMap;
  50. //========================================================================================
  51. // Coerce data for row 'hRow', according to hAccessor. Put in location 'pData'.
  52. // Offsets and types are in hAccessor's bindings.
  53. //
  54. // Return S_OK if all lossless conversions,
  55. // return DB_S_ERRORSOCCURED if lossy conversion (truncation, rounding, etc.)
  56. // Return E_FAIL, etc., if horrible errors.
  57. // GetItemOfExtBuffer is basically operator[].
  58. // It takes an index (or handle) (referenced from 1...n),
  59. // and a ptr for where to write the data.
  60. //
  61. // It holds ptrs to a variable-length ACCESSOR struct.
  62. // So we get the ACCESSOR ptr for the client's accessor handle.
  63. //========================================================================================
  64. assert( pRowset->m_pIAccessor->GetAccessorPtr());
  65. hr = pRowset->m_pIAccessor->GetAccessorPtr()->GetItemOfExtBuffer( hAccessor, &pAccessor );
  66. if (FAILED( hr ) || pAccessor == NULL)
  67. {
  68. hr = DB_E_BADACCESSORHANDLE;
  69. }
  70. else
  71. {
  72. assert( pAccessor );
  73. cBindings = pAccessor->cBindings;
  74. pBinding = pAccessor->rgBindings;
  75. //========================================================================================
  76. // Ensure a place to put data, unless the accessor is the null accessor then
  77. // a NULL pData is okay.
  78. //========================================================================================
  79. if ( pData == NULL && cBindings != 0 )
  80. {
  81. hr = E_INVALIDARG ;
  82. }
  83. else
  84. //========================================================================================
  85. // IsSlotSet returns S_OK if row is marked.
  86. // S_FALSE if row is not marked.
  87. // The "mark" means that there is data present in the row.
  88. // Rows are [1...n], slot marks are [0...n-1].
  89. //========================================================================================
  90. if (pRowset->IsSlotSet(hRow ) != S_OK)
  91. {
  92. hr = DB_E_BADROWHANDLE;
  93. }
  94. else
  95. //===================================================================
  96. // if data is not already fetched to the memory ( which is done
  97. // if other updatedelete is false)
  98. //===================================================================
  99. if( (pRowset->m_ulProps & OTHERUPDATEDELETE) && (pRowset->m_ulLastFetchedRow != hRow))
  100. {
  101. if(SUCCEEDED (hr = pRowset->GetDataToLocalBuffer(hRow)))
  102. {
  103. pRowset->m_ulLastFetchedRow = hRow;
  104. }
  105. }
  106. if(SUCCEEDED(hr))
  107. {
  108. //========================================================================================
  109. // Internal error for a 0 reference count on this row,
  110. // since we depend on the slot-set stuff.
  111. //========================================================================================
  112. pRowBuff = pRowset->GetRowBuff( (ULONG) hRow, TRUE );
  113. assert( pRowBuff->ulRefCount );
  114. //========================================================================================
  115. // Check for the Deleted Row
  116. //========================================================================================
  117. ulErrorCount = 0;
  118. for (ibind = 0; ibind < (DBORDINAL)cBindings; ibind++) {
  119. bUseDataConvert = TRUE;
  120. icol = pBinding[ibind].iOrdinal;
  121. // pColumnData = pRowBuff->GetColumnData(icol);
  122. //========================================================================================
  123. // If bookmark is not requested by setting the DBPROP_BOOKMARK property
  124. // then skip getting the bookmark
  125. //========================================================================================
  126. if(!(pRowset->m_ulProps & BOOKMARKPROP) && icol == 0)
  127. {
  128. continue;
  129. }
  130. else
  131. //========================================================================================
  132. // if it is a bookmark column get the bookmark column from the ROWBUFF Structure
  133. //========================================================================================
  134. if(icol == 0)
  135. {
  136. dwSrcType = DBTYPE_I4;
  137. pSrc = &pRowBuff->dwBmk;
  138. ulSrcLength = pRowBuff->cbBmk;
  139. dwSrcStatus = DBSTATUS_S_OK;
  140. }
  141. else
  142. {
  143. pColumnData = (COLUMNDATA *) ((BYTE *) pRowBuff + pRowset->m_Columns.GetDataOffset(icol));
  144. dwSrcType = (DBTYPE)pColumnData->dwType ; //pRowset->m_Columns.ColumnType(icol);
  145. //===================================================================
  146. // FIXXX More work is to be done on this
  147. //===================================================================
  148. if( dwSrcType == DBTYPE_BSTR )
  149. {
  150. pSrc = &(pColumnData->pbData);
  151. }
  152. else
  153. {
  154. pSrc = (pColumnData->pbData);
  155. }
  156. ulSrcLength = pColumnData->dwLength;
  157. dwSrcStatus = pColumnData->dwStatus;
  158. if(dwSrcType == DBTYPE_HCHAPTER)
  159. {
  160. dwSrcType = DBTYPE_UI4;
  161. }
  162. }
  163. ulDstMaxLength = pBinding[ibind].cbMaxLen;
  164. dwDstType = pBinding[ibind].wType;
  165. dwPart = pBinding[ibind].dwPart;
  166. pDst = dwPart & DBPART_VALUE ? ((BYTE*) pData + pBinding[ibind].obValue) : NULL;
  167. pulDstLength = dwPart & DBPART_LENGTH ? (DBLENGTH *) ((BYTE*) pData + pBinding[ibind].obLength) : NULL;
  168. pdwDstStatus = dwPart & DBPART_STATUS ? (DBSTATUS *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
  169. //==========================================================
  170. // if the column is of type chapter then consider that
  171. // as a of type long as HCHAPTER is a ULONG value
  172. //==========================================================
  173. if(dwDstType == DBTYPE_HCHAPTER)
  174. {
  175. dwDstType = DBTYPE_UI4;
  176. }
  177. if((dwSrcType & DBTYPE_ARRAY) && (dwDstType & DBTYPE_ARRAY))
  178. {
  179. bUseDataConvert = FALSE;
  180. }
  181. if( dwSrcType != VT_NULL && dwSrcType != VT_EMPTY && bUseDataConvert == TRUE && pSrc != NULL)
  182. {
  183. BSTR strData;
  184. if( dwDstType == DBTYPE_BSTR && pDst == NULL)
  185. {
  186. void **pTemp = &pDst;
  187. *pTemp = (void *)&strData;
  188. }
  189. hr = g_pIDataConvert->DataConvert(
  190. dwSrcType,
  191. dwDstType,
  192. ulSrcLength,
  193. pulDstLength,
  194. pSrc,
  195. pDst,
  196. ulDstMaxLength,
  197. dwSrcStatus,
  198. pdwDstStatus,
  199. pBinding[ibind].bPrecision, // bPrecision for conversion to DBNUMERIC
  200. pBinding[ibind].bScale, // bScale for conversion to DBNUMERIC
  201. DBDATACONVERT_DEFAULT);
  202. if(!(dwPart & DBPART_VALUE) && pulDstLength != NULL)
  203. {
  204. hr =g_pIDataConvert->GetConversionSize(dwSrcType,dwDstType,&ulSrcLength,pulDstLength,pSrc);
  205. }
  206. if(!(dwPart & DBPART_VALUE) && dwDstType == DBTYPE_BSTR )
  207. {
  208. if(pulDstLength != NULL)
  209. {
  210. *pulDstLength = SysStringLen(strData);
  211. }
  212. SysFreeString(strData);
  213. }
  214. if(hr == DB_E_UNSUPPORTEDCONVERSION && pdwDstStatus != NULL)
  215. {
  216. *pdwDstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  217. }
  218. }
  219. else
  220. if(bUseDataConvert == FALSE && pSrc != NULL )
  221. {
  222. if(pDst != NULL)
  223. {
  224. //========================================================================================
  225. // Call this function to get the array in the destination address
  226. //========================================================================================
  227. hr = dataMap.ConvertAndCopyArray((SAFEARRAY *)pSrc,(SAFEARRAY **)pDst, dwSrcType,dwDstType,pdwDstStatus);
  228. }
  229. if(pulDstLength != NULL)
  230. {
  231. *pulDstLength = sizeof(SAFEARRAY);
  232. }
  233. if( pdwDstStatus != NULL && *pdwDstStatus == DBSTATUS_E_CANTCONVERTVALUE && pulDstLength != NULL)
  234. {
  235. *pulDstLength = 0;
  236. }
  237. }
  238. else
  239. {
  240. if(pulDstLength)
  241. {
  242. *pulDstLength = 0;
  243. }
  244. if(pdwDstStatus)
  245. {
  246. *pdwDstStatus = DBSTATUS_S_ISNULL;
  247. }
  248. }
  249. if (hr != S_OK )
  250. {
  251. ulErrorCount++; // can't coerce
  252. }
  253. } // for loop
  254. } // if succeeded(hr)
  255. } // else for check for bad accessor
  256. //===================================================================
  257. // We report any lossy conversions with a special status.
  258. // Note that DB_S_ERRORSOCCURED is a success, rather than failure.
  259. //===================================================================
  260. if ( SUCCEEDED(hr) )
  261. {
  262. hr = ( ulErrorCount ? DB_S_ERRORSOCCURRED : S_OK );
  263. }
  264. return hr;
  265. }
  266. ///////////////////////////////////////////////////////////////////////////////////////////
  267. // Function to clear all the allocated buffer if any error occurs while getting data
  268. ///////////////////////////////////////////////////////////////////////////////////////////
  269. void CRowFetchObj::ClearRowBuffer(void *pData,
  270. DBBINDING *pBinding,
  271. int nCurCol)
  272. {
  273. ULONG *pulDstLength;
  274. DWORD *pdwDstStatus;
  275. CDataMap map;
  276. void *pDst;
  277. DWORD dwPart;
  278. //========================================================================================
  279. // Check for the Deleted Row
  280. //========================================================================================
  281. for (int ibind = 0; ibind < nCurCol; ibind++)
  282. {
  283. dwPart = pBinding[ibind].dwPart;
  284. pDst = dwPart & DBPART_VALUE ? ((BYTE*) pData + pBinding[ibind].obValue) : NULL;
  285. pulDstLength = dwPart & DBPART_LENGTH ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obLength) : NULL;
  286. pdwDstStatus = dwPart & DBPART_STATUS ? (ULONG *) ((BYTE*) pData + pBinding[ibind].obStatus) : NULL;
  287. if(pDst)
  288. {
  289. map.ClearData(pBinding[ibind].wType,(BYTE *)pDst);
  290. }
  291. if(pulDstLength)
  292. {
  293. *pulDstLength = 0;
  294. }
  295. if(pdwDstStatus)
  296. {
  297. *pdwDstStatus = 0;
  298. }
  299. }
  300. }
  301. ///////////////////////////////////////////////////////////////////////////////////////////
  302. // Function which get the position of the first row to be fetched
  303. ///////////////////////////////////////////////////////////////////////////////////////////
  304. LONG_PTR CRowFetchObj::GetFirstFetchPos(CRowset *pRowset,DBCOUNTITEM cRows,DBROWOFFSET lOffset)
  305. {
  306. FETCHDIRECTION lFetchDir;
  307. LONG_PTR lFirstPos = -1;
  308. lFetchDir = (LONG_PTR)cRows < 0 ? FETCHDIRBACKWARD : FETCHDIRFORWARD;
  309. if( cRows != 0)
  310. {
  311. lFirstPos = pRowset->m_lLastFetchPos + lOffset;
  312. if((pRowset->m_FetchDir != FETCHDIRNONE) && pRowset->m_FetchDir != lFetchDir)
  313. {
  314. }
  315. else
  316. {
  317. lFirstPos = (LONG_PTR)cRows < 0 ? lFirstPos - 1 : lFirstPos + 1;
  318. }
  319. }
  320. if(lFirstPos <= 0)
  321. {
  322. lFirstPos = -1;
  323. }
  324. return lFirstPos;
  325. }
  326. ///////////////////////////////////////////////////////////////////////////////////////////
  327. // Function which get the position of the first row to be fetched
  328. // NTRaid:111770
  329. // 06/07/00
  330. ///////////////////////////////////////////////////////////////////////////////////////////
  331. HRESULT CRowFetchObj::FetchRowsByBookMark(CRowset * pRowset,
  332. HCHAPTER hChapter, // IN The Chapter handle.
  333. DBROWCOUNT cRows, // IN Number of rows to fetch
  334. const DBBKMARK rgcbBookmarks[], //@parm IN | an array of bookmark sizes
  335. const BYTE* rgpBookmarks[], //@parm IN | an array of pointers to bookmarks
  336. HROW rghRows[], // OUT Array of Hrows obtained
  337. DBROWSTATUS rgRowStatus[]) // OUT status of rows
  338. {
  339. DBCOUNTITEM ibmk, cErrors, cRowsObtained;
  340. PROWBUFF prowbuff;
  341. HROW hrow, hrowFound;
  342. HRESULT hr;
  343. BYTE* pbBmk;
  344. DBBKMARK cbBmk;
  345. DBROWSTATUS dbrowstatus;
  346. ULONG_PTR ulLastFetchPos;
  347. FETCHDIRECTION lFetchDir;
  348. DBROWOFFSET lOffset = 0;
  349. HROW * phRow;
  350. ulLastFetchPos = pRowset->m_lLastFetchPos;
  351. lFetchDir = pRowset->m_FetchDir;
  352. if(pRowset->m_FetchDir == FETCHDIRNONE)
  353. {
  354. pRowset->m_FetchDir = FETCHDIRFORWARD;
  355. }
  356. //========================================================================================
  357. // Now, loop thru all supplied bookmarks.
  358. //========================================================================================
  359. for (ibmk =0, cErrors =0; ibmk < (DBCOUNTITEM)cRows; ibmk++)
  360. {
  361. pbBmk = (BYTE*)&rgpBookmarks[ibmk];
  362. cbBmk = pbBmk? rgcbBookmarks[ibmk] : 0;
  363. //========================================================================================
  364. // Must be a valid bookmark
  365. //========================================================================================
  366. if (cbBmk != BOOKMARKSIZE)
  367. {
  368. dbrowstatus = DBROWSTATUS_E_INVALID;
  369. hrow = DB_NULL_HROW;
  370. }
  371. //========================================================================================
  372. // We might already have this bookmark in our hashtable.
  373. //========================================================================================
  374. else if (pRowset->m_pHashTblBkmark->InsertFindBmk(TRUE, 0,
  375. cbBmk, pbBmk, &hrow) == S_OK)
  376. {
  377. //========================================================================================
  378. // Row handle for this Bookmark was already in memory,
  379. // so return the row handle that was found.
  380. //========================================================================================
  381. prowbuff = pRowset->GetRowBuffFromSlot(hrow);
  382. if (pRowset->GetRowStatus(hrow) & DBROWSTATUS_E_DELETED)
  383. {
  384. dbrowstatus = DBROWSTATUS_E_INVALID;
  385. hrow = DB_NULL_HROW;
  386. }
  387. else
  388. {
  389. dbrowstatus = DBROWSTATUS_S_OK;
  390. prowbuff->ulRefCount++;
  391. }
  392. }
  393. else
  394. //==========================================================================================
  395. // if bookmark not alread present then fetch the row and put the bookmark in hash table
  396. //==========================================================================================
  397. {
  398. lOffset = *((ULONG *)pbBmk) - pRowset->m_lLastFetchPos;
  399. lOffset = (pRowset->m_FetchDir == FETCHDIRFORWARD) ? --lOffset : ++lOffset;
  400. cRowsObtained = 0;
  401. phRow = &hrow;
  402. //====================================================================================
  403. // Use a utility object method to fetch the row with the bookmark.
  404. //====================================================================================
  405. hr = FetchRows(pRowset,hChapter ,lOffset,ONE_ROW, &cRowsObtained, &phRow);
  406. //==========================================================================================
  407. // In case of any problem with fetching the row make an entry
  408. // in the error array.
  409. //==========================================================================================
  410. if (FAILED(hr) || cRowsObtained < ONE_ROW)
  411. {
  412. dbrowstatus = (hr == E_OUTOFMEMORY)
  413. ? DBROWSTATUS_E_OUTOFMEMORY
  414. : DBROWSTATUS_E_INVALID;
  415. hrow = DB_NULL_HROW;
  416. }
  417. else
  418. {
  419. prowbuff = pRowset->GetRowBuffFromSlot(hrow);
  420. //==========================================================================
  421. // Now, enter this bookmark in our hashtable.
  422. //==========================================================================
  423. if (SUCCEEDED(hr))
  424. {
  425. prowbuff->cbBmk = BOOKMARKSIZE;
  426. prowbuff->dwBmk = rgcbBookmarks[ibmk];
  427. hr = (pRowset->m_pHashTblBkmark)->InsertFindBmk(FALSE,
  428. hrow, prowbuff->cbBmk, pbBmk, &hrowFound);
  429. if (FAILED(hr))
  430. {
  431. ReleaseSlots(pRowset->m_pIBuffer,hrow, ONE_ROW);
  432. dbrowstatus = DBROWSTATUS_E_OUTOFMEMORY;
  433. hrow = DB_NULL_HROW;
  434. }
  435. else
  436. {
  437. assert(hr == S_FALSE);
  438. dbrowstatus = DBROWSTATUS_S_OK;
  439. }
  440. }
  441. }
  442. }
  443. // mark status.
  444. if (rgRowStatus)
  445. rgRowStatus[ibmk] = dbrowstatus;
  446. if (dbrowstatus != DBROWSTATUS_S_OK)
  447. cErrors++;
  448. // Put the rowhandle in the output array, and
  449. rghRows[ibmk] = (HROW)hrow;
  450. }
  451. // Reverting back the state of the rowset
  452. pRowset->m_lLastFetchPos = ulLastFetchPos;
  453. pRowset->m_FetchDir = lFetchDir;
  454. return
  455. cErrors
  456. ? (cErrors < (ULONG)cRows)
  457. ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED
  458. : S_OK;
  459. }
  460. ///////////////////////////////////////////////////////////////////////////////////////////
  461. // Function to fetch the next few rows as requested from the bookmark specified
  462. ///////////////////////////////////////////////////////////////////////////////////////////
  463. HRESULT CRowFetchObj::FetchNextRowsByBookMark(CRowset * pRowset,
  464. HCHAPTER hChapter, // IN The Chapter handle.
  465. DBBKMARK cbBookmark, // size of BOOKMARK
  466. const BYTE * pBookmark, // The bookmark from which fetch should start
  467. DBROWOFFSET lRowsOffset,
  468. DBROWCOUNT cRows,
  469. DBCOUNTITEM * pcRowsObtained,
  470. HROW ** prghRows) // array containing the row handles
  471. {
  472. HRESULT hr = S_OK;
  473. //=====================================================================
  474. // Must be a valid bookmark
  475. //=====================================================================
  476. if (cbBookmark != BOOKMARKSIZE && cbBookmark != STD_BOOKMARKLENGTH)
  477. {
  478. hr = DB_E_BADBOOKMARK;
  479. }
  480. else
  481. //=============================================================================
  482. // If the bookmark is a standard bookmark
  483. //=============================================================================
  484. if( cbBookmark == STD_BOOKMARKLENGTH)
  485. {
  486. switch(*pBookmark)
  487. {
  488. case DBBMK_INVALID:
  489. return DB_E_BADBOOKMARK;
  490. case DBBMK_FIRST:
  491. lRowsOffset = lRowsOffset - pRowset->m_lLastFetchPos ;
  492. if(cRows < 0)
  493. {
  494. hr = DB_S_ENDOFROWSET;
  495. }
  496. break;
  497. case DBBMK_LAST:
  498. lRowsOffset = lRowsOffset + pRowset->m_lRowCount - pRowset->m_lLastFetchPos;
  499. if(cRows > 0)
  500. {
  501. hr = DB_S_ENDOFROWSET;
  502. }
  503. break;
  504. }
  505. }
  506. //=============================================================================
  507. // If not a standard bookmark
  508. //=============================================================================
  509. else
  510. {
  511. lRowsOffset = lRowsOffset + (*(ULONG_PTR *)pBookmark - pRowset->m_lLastFetchPos);
  512. // Adjust the offset , so that the first received row is correct
  513. lRowsOffset = cRows > 0 ? lRowsOffset -1 : lRowsOffset + 1;
  514. }
  515. if(hr == S_OK)
  516. {
  517. if( 0 > (LONG)(lRowsOffset + pRowset->m_lLastFetchPos) &&
  518. (lRowsOffset + pRowset->m_lLastFetchPos) > pRowset->m_lRowCount)
  519. {
  520. hr = DB_E_BADSTARTPOSITION;
  521. }
  522. else
  523. {
  524. // NTRaid : 134987
  525. // 07/12/00
  526. ULONG_PTR lPrevPos = pRowset->m_lLastFetchPos;
  527. FETCHDIRECTION lFetchDir = pRowset->GetCurFetchDirection();
  528. // set the direction flag on the enumerator so that the
  529. // enumerator returns instance starting from the last instance
  530. if(cbBookmark == STD_BOOKMARKLENGTH && *pBookmark == DBBMK_LAST)
  531. {
  532. pRowset->SetCurFetchDirection(FETCHDIRFORWARD);
  533. }
  534. //=============================================================================
  535. // call this function to fetch rows
  536. //=============================================================================
  537. if(SUCCEEDED(hr = FetchRows(pRowset,hChapter ,lRowsOffset,cRows, pcRowsObtained, prghRows)))
  538. {
  539. HRESULT hrLocal = S_OK;
  540. // Adjust the position of the enumerator after fetching
  541. ULONG_PTR lOffSetAdjust = lPrevPos -pRowset->m_lLastFetchPos;
  542. if(SUCCEEDED(hrLocal = pRowset->ResetRowsetToNewPosition(lOffSetAdjust,pRowset->m_pInstance)))
  543. {
  544. pRowset->m_lLastFetchPos = lPrevPos;
  545. pRowset->SetCurFetchDirection(lFetchDir);
  546. }
  547. if(FAILED(hrLocal))
  548. {
  549. hr = hrLocal;
  550. }
  551. }
  552. }
  553. }
  554. return hr;
  555. }