Leaked source code of windows server 2003
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.

1419 lines
49 KiB

  1. //---------------------------------------------------------------------------
  2. // MetadataCursor.cpp : MetadataCursor implementation
  3. //
  4. // Copyright (c) 1996 Microsoft Corporation, All Rights Reserved
  5. // Developed by Sheridan Software Systems, Inc.
  6. //---------------------------------------------------------------------------
  7. #include "stdafx.h"
  8. #include "Notifier.h"
  9. #include "RSColumn.h"
  10. #include "RSSource.h"
  11. #include "CursMain.h"
  12. #include "CursBase.h"
  13. #include "CursMeta.h"
  14. #include "fastguid.h"
  15. #include "resource.h"
  16. SZTHISFILE
  17. //=--------------------------------------------------------------------------=
  18. // CVDMetadataCursor - Constructor
  19. //
  20. CVDMetadataCursor::CVDMetadataCursor()
  21. {
  22. m_dwRefCount = 1;
  23. m_lCurrentRow = -1; // before first
  24. m_ulColumns = 0;
  25. m_pColumns = NULL;
  26. m_ulMetaColumns = 0;
  27. m_pMetaColumns = NULL;
  28. #ifdef _DEBUG
  29. g_cVDMetadataCursorCreated++;
  30. #endif
  31. }
  32. //=--------------------------------------------------------------------------=
  33. // ~CVDMetadataCursor - Destructor
  34. //
  35. CVDMetadataCursor::~CVDMetadataCursor()
  36. {
  37. #ifdef _DEBUG
  38. g_cVDMetadataCursorDestroyed++;
  39. #endif
  40. }
  41. //=--------------------------------------------------------------------------=
  42. // RowToBookmark - Convert row to bookmark
  43. //=--------------------------------------------------------------------------=
  44. //
  45. // Parameters:
  46. // lRow - [in] a row number
  47. // pcbBookmark - [out] a pointer to memory in which to return the length
  48. // in bytes of the corresponding bookmark
  49. // pBookmark - [out] a pointer to memory in which to return the bookmark
  50. //
  51. // Notes:
  52. //
  53. void CVDMetadataCursor::RowToBookmark(LONG lRow, ULONG * pcbBookmark, void * pBookmark) const
  54. {
  55. if (lRow < 0)
  56. {
  57. *pcbBookmark = CURSOR_DB_BMK_SIZE;
  58. memcpy(pBookmark, &CURSOR_DBBMK_BEGINNING, CURSOR_DB_BMK_SIZE);
  59. }
  60. else if (lRow >= (LONG)m_ulColumns)
  61. {
  62. *pcbBookmark = CURSOR_DB_BMK_SIZE;
  63. memcpy(pBookmark, &CURSOR_DBBMK_END, CURSOR_DB_BMK_SIZE);
  64. }
  65. else
  66. {
  67. *pcbBookmark = sizeof(LONG);
  68. memcpy(pBookmark, &lRow, sizeof(LONG));
  69. }
  70. }
  71. //=--------------------------------------------------------------------------=
  72. // BookmarkToRow - Convert bookmark to row
  73. //=--------------------------------------------------------------------------=
  74. //
  75. // Parameters:
  76. // cbBookmark - [in] the length in bytes of the bookmark
  77. // pBookmark - [in] a pointer to the bookmark
  78. // pRow - [out] a pointer to memory in which to return the
  79. // corresponding row
  80. //
  81. // Output:
  82. // BOOL - TRUE if successful
  83. //
  84. // Notes:
  85. //
  86. BOOL CVDMetadataCursor::BookmarkToRow(ULONG cbBookmark, void * pBookmark, LONG * plRow) const
  87. {
  88. BOOL fResult = FALSE;
  89. if (cbBookmark == CURSOR_DB_BMK_SIZE)
  90. {
  91. if (memcmp(pBookmark, &CURSOR_DBBMK_BEGINNING, CURSOR_DB_BMK_SIZE) == 0)
  92. {
  93. *plRow = -1;
  94. fResult = TRUE;
  95. }
  96. else if (memcmp(pBookmark, &CURSOR_DBBMK_END, CURSOR_DB_BMK_SIZE) == 0)
  97. {
  98. *plRow = (LONG)m_ulColumns;
  99. fResult = TRUE;
  100. }
  101. else if (memcmp(pBookmark, &CURSOR_DBBMK_CURRENT, CURSOR_DB_BMK_SIZE) == 0)
  102. {
  103. *plRow = m_lCurrentRow;
  104. fResult = TRUE;
  105. }
  106. }
  107. else
  108. if (cbBookmark == sizeof(LONG))
  109. {
  110. memcpy(plRow, pBookmark, sizeof(LONG));
  111. if (*plRow >= 0 && *plRow < (LONG)m_ulColumns)
  112. fResult = TRUE;
  113. }
  114. return fResult;
  115. }
  116. //=--------------------------------------------------------------------------=
  117. // ReturnData_I4 - Coerce I4 data into buffers
  118. //=--------------------------------------------------------------------------=
  119. // This function coerces the specified data into supplied buffers
  120. //
  121. // Parameters:
  122. // dwData - [in] the 4-byte data
  123. // pCursorBinding - [in] the cursor binding describing the format of the
  124. // returned information
  125. // pData - [in] a pointer to the fixed area buffer
  126. // pVarData - [in] a pointer to the variable length buffer
  127. //
  128. // Output:
  129. // ULONG - the number of bytes used in variable length buffer
  130. //
  131. // Notes:
  132. //
  133. ULONG CVDMetadataCursor::ReturnData_I4(DWORD dwData, CURSOR_DBCOLUMNBINDING * pCursorBinding,
  134. BYTE * pData, BYTE * pVarData)
  135. {
  136. ULONG cbVarData = 0;
  137. if (pCursorBinding->dwBinding == CURSOR_DBBINDING_DEFAULT)
  138. {
  139. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  140. *(DWORD*)(pData + pCursorBinding->obData) = dwData;
  141. }
  142. else if (pCursorBinding->dwBinding == CURSOR_DBBINDING_VARIANT)
  143. {
  144. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  145. {
  146. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  147. VariantInit((VARIANT*)pVariant);
  148. pVariant->vt = CURSOR_DBTYPE_I4;
  149. pVariant->lVal = dwData;
  150. }
  151. }
  152. if (pCursorBinding->obVarDataLen != CURSOR_DB_NOVALUE)
  153. *(ULONG*)(pData + pCursorBinding->obVarDataLen) = 0;
  154. if (pCursorBinding->obInfo != CURSOR_DB_NOVALUE)
  155. *(DWORD*)(pData + pCursorBinding->obInfo) = CURSOR_DB_NOINFO;
  156. return cbVarData;
  157. }
  158. //=--------------------------------------------------------------------------=
  159. // ReturnData_BOOL - Coerce BOOL data into buffers
  160. //=--------------------------------------------------------------------------=
  161. // This function coerces the specified data into supplied buffers
  162. //
  163. // Parameters:
  164. // fData - [in] the boolean data
  165. // pCursorBinding - [in] the cursor binding describing the format of the
  166. // returned information
  167. // pData - [in] a pointer to the fixed area buffer
  168. // pVarData - [in] a pointer to the variable length buffer
  169. //
  170. // Output:
  171. // ULONG - the number of bytes used in variable length buffer
  172. //
  173. // Notes:
  174. //
  175. ULONG CVDMetadataCursor::ReturnData_BOOL(VARIANT_BOOL fData, CURSOR_DBCOLUMNBINDING * pCursorBinding,
  176. BYTE * pData, BYTE * pVarData)
  177. {
  178. ULONG cbVarData = 0;
  179. if (pCursorBinding->dwBinding == CURSOR_DBBINDING_DEFAULT)
  180. {
  181. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  182. *(VARIANT_BOOL*)(pData + pCursorBinding->obData) = fData;
  183. }
  184. else if (pCursorBinding->dwBinding == CURSOR_DBBINDING_VARIANT)
  185. {
  186. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  187. {
  188. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  189. VariantInit((VARIANT*)pVariant);
  190. pVariant->vt = CURSOR_DBTYPE_BOOL;
  191. pVariant->boolVal = fData;
  192. }
  193. }
  194. if (pCursorBinding->obVarDataLen != CURSOR_DB_NOVALUE)
  195. *(ULONG*)(pData + pCursorBinding->obVarDataLen) = 0;
  196. if (pCursorBinding->obInfo != CURSOR_DB_NOVALUE)
  197. *(DWORD*)(pData + pCursorBinding->obInfo) = CURSOR_DB_NOINFO;
  198. return cbVarData;
  199. }
  200. //=--------------------------------------------------------------------------=
  201. // ReturnData_LPWSTR - Coerce LPWSTR data into buffers
  202. //=--------------------------------------------------------------------------=
  203. // This function coerces the specified data into supplied buffers
  204. //
  205. // Parameters:
  206. // pwszData - [in] the string data
  207. // pCursorBinding - [in] the cursor binding describing the format of the
  208. // returned information
  209. // pData - [in] a pointer to the fixed area buffer
  210. // pVarData - [in] a pointer to the variable length buffer
  211. //
  212. // Output:
  213. // ULONG - the number of bytes used in variable length buffer
  214. //
  215. // Notes:
  216. //
  217. ULONG CVDMetadataCursor::ReturnData_LPWSTR(WCHAR * pwszData, CURSOR_DBCOLUMNBINDING * pCursorBinding,
  218. BYTE * pData, BYTE * pVarData)
  219. {
  220. ULONG cbVarData = 0;
  221. ULONG cbLength = 0;
  222. DWORD dwInfo = CURSOR_DB_NOINFO;
  223. if (pCursorBinding->dwBinding == CURSOR_DBBINDING_DEFAULT)
  224. {
  225. if (pCursorBinding->dwDataType == CURSOR_DBTYPE_CHARS)
  226. {
  227. if (pwszData)
  228. cbLength = GET_MBCSLEN_FROMWIDE(pwszData);
  229. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  230. {
  231. if (pwszData)
  232. {
  233. MAKE_MBCSPTR_FROMWIDE(pszData, pwszData);
  234. memcpy(pData + pCursorBinding->obData, pszData, min(pCursorBinding->cbMaxLen, cbLength));
  235. if (pCursorBinding->cbMaxLen < cbLength)
  236. dwInfo = CURSOR_DB_TRUNCATED;
  237. }
  238. else
  239. {
  240. *(CHAR*)(pData + pCursorBinding->obData) = 0;
  241. dwInfo = CURSOR_DB_NULL;
  242. }
  243. }
  244. }
  245. else if (pCursorBinding->dwDataType == CURSOR_DBTYPE_WCHARS)
  246. {
  247. if (pwszData)
  248. cbLength = (lstrlenW(pwszData) + 1) * sizeof(WCHAR);
  249. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  250. {
  251. if (pwszData)
  252. {
  253. memcpy(pData + pCursorBinding->obData, pwszData, min(pCursorBinding->cbMaxLen, cbLength));
  254. if (pCursorBinding->cbMaxLen < cbLength)
  255. dwInfo = CURSOR_DB_TRUNCATED;
  256. }
  257. else
  258. {
  259. *(WCHAR*)(pData + pCursorBinding->obData) = 0;
  260. dwInfo = CURSOR_DB_NULL;
  261. }
  262. }
  263. }
  264. else if (pCursorBinding->dwDataType == CURSOR_DBTYPE_LPSTR)
  265. {
  266. if (pwszData)
  267. cbLength = GET_MBCSLEN_FROMWIDE(pwszData);
  268. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  269. {
  270. if (pwszData)
  271. {
  272. MAKE_MBCSPTR_FROMWIDE(pszData, pwszData);
  273. *(LPSTR*)(pData + pCursorBinding->obData) = (LPSTR)pVarData;
  274. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  275. {
  276. memcpy(pVarData, pszData, cbLength);
  277. cbVarData = cbLength;
  278. }
  279. else
  280. {
  281. memcpy(pVarData, pszData, min(pCursorBinding->cbMaxLen, cbLength));
  282. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  283. if (pCursorBinding->cbMaxLen < cbLength)
  284. dwInfo = CURSOR_DB_TRUNCATED;
  285. }
  286. }
  287. else
  288. {
  289. *(LPSTR*)(pData + pCursorBinding->obData) = NULL;
  290. dwInfo = CURSOR_DB_NULL;
  291. }
  292. }
  293. }
  294. else if (pCursorBinding->dwDataType == CURSOR_DBTYPE_LPWSTR)
  295. {
  296. if (pwszData)
  297. cbLength = (lstrlenW(pwszData) + 1) * sizeof(WCHAR);
  298. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  299. {
  300. if (pwszData)
  301. {
  302. *(LPWSTR*)(pData + pCursorBinding->obData) = (LPWSTR)pVarData;
  303. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  304. {
  305. memcpy(pVarData, pwszData, cbLength);
  306. cbVarData = cbLength;
  307. }
  308. else
  309. {
  310. memcpy(pVarData, pwszData, min(pCursorBinding->cbMaxLen, cbLength));
  311. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  312. if (pCursorBinding->cbMaxLen < cbLength)
  313. dwInfo = CURSOR_DB_TRUNCATED;
  314. }
  315. }
  316. else
  317. {
  318. *(LPWSTR*)(pData + pCursorBinding->obData) = NULL;
  319. dwInfo = CURSOR_DB_NULL;
  320. }
  321. }
  322. }
  323. }
  324. else if (pCursorBinding->dwBinding == CURSOR_DBBINDING_VARIANT)
  325. {
  326. if (pCursorBinding->dwDataType == CURSOR_DBTYPE_LPSTR)
  327. {
  328. if (pwszData)
  329. cbLength = GET_MBCSLEN_FROMWIDE(pwszData);
  330. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  331. {
  332. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  333. VariantInit((VARIANT*)pVariant);
  334. if (pwszData)
  335. {
  336. MAKE_MBCSPTR_FROMWIDE(pszData, pwszData);
  337. pVariant->vt = CURSOR_DBTYPE_LPSTR;
  338. pVariant->pszVal = (LPSTR)pVarData;
  339. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  340. {
  341. memcpy(pVarData, pszData, cbLength);
  342. cbVarData = cbLength;
  343. }
  344. else
  345. {
  346. memcpy(pVarData, pszData, min(pCursorBinding->cbMaxLen, cbLength));
  347. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  348. if (pCursorBinding->cbMaxLen < cbLength)
  349. dwInfo = CURSOR_DB_TRUNCATED;
  350. }
  351. }
  352. else
  353. {
  354. pVariant->vt = VT_NULL;
  355. dwInfo = CURSOR_DB_NULL;
  356. }
  357. }
  358. }
  359. else if (pCursorBinding->dwDataType == CURSOR_DBTYPE_LPWSTR)
  360. {
  361. if (pwszData)
  362. cbLength = (lstrlenW(pwszData) + 1) * sizeof(WCHAR);
  363. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  364. {
  365. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  366. VariantInit((VARIANT*)pVariant);
  367. if (pwszData)
  368. {
  369. pVariant->vt = CURSOR_DBTYPE_LPWSTR;
  370. pVariant->pwszVal = (LPWSTR)pVarData;
  371. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  372. {
  373. memcpy(pVarData, pwszData, cbLength);
  374. cbVarData = cbLength;
  375. }
  376. else
  377. {
  378. memcpy(pVarData, pwszData, min(pCursorBinding->cbMaxLen, cbLength));
  379. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  380. if (pCursorBinding->cbMaxLen < cbLength)
  381. dwInfo = CURSOR_DB_TRUNCATED;
  382. }
  383. }
  384. else
  385. {
  386. pVariant->vt = VT_NULL;
  387. dwInfo = CURSOR_DB_NULL;
  388. }
  389. }
  390. }
  391. else if (pCursorBinding->dwDataType == VT_BSTR)
  392. {
  393. if (pwszData)
  394. cbLength = (lstrlenW(pwszData) + 1) * sizeof(WCHAR);
  395. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  396. {
  397. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  398. VariantInit((VARIANT*)pVariant);
  399. if (pwszData)
  400. {
  401. pVariant->vt = VT_BSTR;
  402. pVariant->pwszVal = SysAllocString(pwszData);
  403. }
  404. else
  405. {
  406. pVariant->vt = VT_NULL;
  407. dwInfo = CURSOR_DB_NULL;
  408. }
  409. }
  410. }
  411. }
  412. if (pCursorBinding->obVarDataLen != CURSOR_DB_NOVALUE)
  413. *(ULONG*)(pData + pCursorBinding->obVarDataLen) = cbLength;
  414. if (pCursorBinding->obInfo != CURSOR_DB_NOVALUE)
  415. *(DWORD*)(pData + pCursorBinding->obInfo) = dwInfo;
  416. return cbVarData;
  417. }
  418. //=--------------------------------------------------------------------------=
  419. // ReturnData_DBCOLUMNID - Coerce DBCOLUMNID data into buffers
  420. //=--------------------------------------------------------------------------=
  421. // This function coerces the specified data into supplied buffers
  422. //
  423. // Parameters:
  424. // cursorColumnID - [in] the cursor column identifier
  425. // pCursorBinding - [in] the cursor binding describing the format of the
  426. // returned information
  427. // pData - [in] a pointer to the fixed area buffer
  428. // pVarData - [in] a pointer to the variable length buffer
  429. //
  430. // Output:
  431. // ULONG - the number of bytes used in variable length buffer
  432. //
  433. // Notes:
  434. //
  435. ULONG CVDMetadataCursor::ReturnData_DBCOLUMNID(CURSOR_DBCOLUMNID cursorColumnID, CURSOR_DBCOLUMNBINDING * pCursorBinding,
  436. BYTE * pData, BYTE * pVarData)
  437. {
  438. ULONG cbVarData = 0;
  439. if (pCursorBinding->dwBinding == CURSOR_DBBINDING_DEFAULT)
  440. {
  441. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  442. *(CURSOR_DBCOLUMNID*)(pData + pCursorBinding->obData) = cursorColumnID;
  443. }
  444. else if (pCursorBinding->dwBinding == CURSOR_DBBINDING_VARIANT)
  445. {
  446. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  447. {
  448. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  449. CURSOR_DBCOLUMNID * pCursorColumnID = (CURSOR_DBCOLUMNID*)pVarData;
  450. VariantInit((VARIANT*)pVariant);
  451. pVariant->vt = CURSOR_DBTYPE_COLUMNID;
  452. pVariant->pColumnid = pCursorColumnID;
  453. *pCursorColumnID = cursorColumnID;
  454. cbVarData = sizeof(CURSOR_DBCOLUMNID);
  455. }
  456. }
  457. if (pCursorBinding->obVarDataLen != CURSOR_DB_NOVALUE)
  458. *(DWORD*)(pData + pCursorBinding->obVarDataLen) = 0;
  459. if (pCursorBinding->obInfo != CURSOR_DB_NOVALUE)
  460. *(DWORD*)(pData + pCursorBinding->obInfo) = CURSOR_DB_NOINFO;
  461. return cbVarData;
  462. }
  463. //=--------------------------------------------------------------------------=
  464. // ReturnData_Bookmark - Coerce bookmark data into buffers
  465. //=--------------------------------------------------------------------------=
  466. // This function coerces the specified data into supplied buffers
  467. //
  468. // Parameters:
  469. // lRow - [in] the current row
  470. // pCursorBinding - [in] the cursor binding describing the format of the
  471. // returned information
  472. // pData - [in] a pointer to the fixed area buffer
  473. // pVarData - [in] a pointer to the variable length buffer
  474. //
  475. // Output:
  476. // ULONG - the number of bytes used in variable length buffer
  477. //
  478. // Notes:
  479. //
  480. ULONG CVDMetadataCursor::ReturnData_Bookmark(LONG lRow, CURSOR_DBCOLUMNBINDING * pCursorBinding,
  481. BYTE * pData, BYTE * pVarData)
  482. {
  483. ULONG cbVarData = 0;
  484. ULONG cbLength = sizeof(LONG);
  485. DWORD dwInfo = CURSOR_DB_NOINFO;
  486. if (pCursorBinding->dwBinding == CURSOR_DBBINDING_DEFAULT)
  487. {
  488. if (pCursorBinding->dwDataType == CURSOR_DBTYPE_BYTES)
  489. {
  490. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  491. {
  492. memcpy(pData + pCursorBinding->obData, &lRow, min(pCursorBinding->cbMaxLen, cbLength));
  493. if (pCursorBinding->cbMaxLen < cbLength)
  494. dwInfo = CURSOR_DB_TRUNCATED;
  495. }
  496. }
  497. else if (pCursorBinding->dwDataType == CURSOR_DBTYPE_BLOB)
  498. {
  499. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  500. {
  501. *(ULONG*)(pData + pCursorBinding->obData) = cbLength;
  502. *(LPBYTE*)(pData + pCursorBinding->obData + sizeof(ULONG)) = (LPBYTE)pVarData;
  503. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  504. {
  505. memcpy((LPBYTE)pVarData, &lRow, cbLength);
  506. cbVarData = cbLength;
  507. }
  508. else
  509. {
  510. memcpy(pVarData, &lRow, min(pCursorBinding->cbMaxLen, cbLength));
  511. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  512. if (pCursorBinding->cbMaxLen < cbLength)
  513. dwInfo = CURSOR_DB_TRUNCATED;
  514. }
  515. }
  516. }
  517. }
  518. else if (pCursorBinding->dwBinding == CURSOR_DBBINDING_VARIANT)
  519. {
  520. if (pCursorBinding->dwDataType == CURSOR_DBTYPE_BLOB)
  521. {
  522. if (pCursorBinding->obData != CURSOR_DB_NOVALUE)
  523. {
  524. CURSOR_DBVARIANT * pVariant = (CURSOR_DBVARIANT*)(pData + pCursorBinding->obData);
  525. VariantInit((VARIANT*)pVariant);
  526. pVariant->vt = CURSOR_DBTYPE_BLOB;
  527. pVariant->blob.cbSize = cbLength;
  528. pVariant->blob.pBlobData = (LPBYTE)pVarData;
  529. if (pCursorBinding->cbMaxLen == CURSOR_DB_NOMAXLENGTH)
  530. {
  531. memcpy((LPBYTE)pVarData, &lRow, cbLength);
  532. cbVarData = cbLength;
  533. }
  534. else
  535. {
  536. memcpy(pVarData, &lRow, min(pCursorBinding->cbMaxLen, cbLength));
  537. cbVarData = min(pCursorBinding->cbMaxLen, cbLength);
  538. if (pCursorBinding->cbMaxLen < cbLength)
  539. dwInfo = CURSOR_DB_TRUNCATED;
  540. }
  541. }
  542. }
  543. }
  544. if (pCursorBinding->obVarDataLen != CURSOR_DB_NOVALUE)
  545. *(ULONG*)(pData + pCursorBinding->obVarDataLen) = cbLength;
  546. if (pCursorBinding->obInfo != CURSOR_DB_NOVALUE)
  547. *(DWORD*)(pData + pCursorBinding->obInfo) = dwInfo;
  548. return cbVarData;
  549. }
  550. //=--------------------------------------------------------------------------=
  551. // Create - Create metadata cursor object
  552. //=--------------------------------------------------------------------------=
  553. // This function creates and initializes a new metadata cursor object
  554. //
  555. // Parameters:
  556. // ulColumns - [in] the number of rowset columns
  557. // pColumns - [in] a pointer to rowset columns where to
  558. // retrieve metadata
  559. // ulMetaColumns - [in] the number of rowset meta-columns (can be 0)
  560. // pMetaColumns - [in] a pointer to rowset meta-columns where to
  561. // retrieve metadata (can be NULL)
  562. // ppMetaDataCursor - [out] a pointer in which to return pointer to
  563. // metadata cursor object
  564. // pResourceDLL - [in] a pointer which keeps track of resource DLL
  565. //
  566. // Output:
  567. // HRESULT - S_OK if successful
  568. // E_INVALIDARG bad parameter
  569. // E_OUTOFMEMORY not enough memory to create object
  570. //
  571. // Notes:
  572. //
  573. HRESULT CVDMetadataCursor::Create(ULONG ulColumns, CVDRowsetColumn * pColumns, ULONG ulMetaColumns,
  574. CVDRowsetColumn * pMetaColumns, CVDMetadataCursor ** ppMetadataCursor, CVDResourceDLL * pResourceDLL)
  575. {
  576. ASSERT_POINTER(pColumns, CVDRowsetColumn)
  577. ASSERT_NULL_OR_POINTER(pMetaColumns, CVDRowsetColumn)
  578. ASSERT_POINTER(ppMetadataCursor, CVDMetadataCursor*)
  579. ASSERT_POINTER(pResourceDLL, CVDResourceDLL)
  580. if (!ppMetadataCursor || !pColumns)
  581. return E_INVALIDARG;
  582. *ppMetadataCursor = NULL;
  583. CVDMetadataCursor * pMetadataCursor = new CVDMetadataCursor();
  584. if (!pMetadataCursor)
  585. return E_OUTOFMEMORY;
  586. pMetadataCursor->m_ulColumns = ulColumns;
  587. pMetadataCursor->m_pColumns = pColumns;
  588. pMetadataCursor->m_ulMetaColumns = ulMetaColumns;
  589. pMetadataCursor->m_pMetaColumns = pMetaColumns;
  590. pMetadataCursor->m_pResourceDLL = pResourceDLL;
  591. *ppMetadataCursor = pMetadataCursor;
  592. return S_OK;
  593. }
  594. //=--------------------------------------------------------------------------=
  595. // IUnknown methods implemented
  596. //=--------------------------------------------------------------------------=
  597. //=--------------------------------------------------------------------------=
  598. // IUnknown QueryInterface
  599. //
  600. HRESULT CVDMetadataCursor::QueryInterface(REFIID riid, void **ppvObjOut)
  601. {
  602. ASSERT_POINTER(ppvObjOut, IUnknown*)
  603. if (!ppvObjOut)
  604. return E_INVALIDARG;
  605. *ppvObjOut = NULL;
  606. switch (riid.Data1)
  607. {
  608. QI_INTERFACE_SUPPORTED((ICursor*)this, IUnknown);
  609. QI_INTERFACE_SUPPORTED(this, ICursor);
  610. QI_INTERFACE_SUPPORTED(this, ICursorMove);
  611. QI_INTERFACE_SUPPORTED(this, ICursorScroll);
  612. QI_INTERFACE_SUPPORTED(this, ISupportErrorInfo);
  613. }
  614. if (NULL == *ppvObjOut)
  615. return E_NOINTERFACE;
  616. AddRef();
  617. return S_OK;
  618. }
  619. //=--------------------------------------------------------------------------=
  620. // IUnknown AddRef
  621. //
  622. ULONG CVDMetadataCursor::AddRef(void)
  623. {
  624. return ++m_dwRefCount;
  625. }
  626. //=--------------------------------------------------------------------------=
  627. // IUnknown Release
  628. //
  629. ULONG CVDMetadataCursor::Release(void)
  630. {
  631. if (1 > --m_dwRefCount)
  632. {
  633. delete this;
  634. return 0;
  635. }
  636. return m_dwRefCount;
  637. }
  638. //=--------------------------------------------------------------------------=
  639. // ICursor methods implemented
  640. //=--------------------------------------------------------------------------=
  641. //=--------------------------------------------------------------------------=
  642. // ICursor GetColumnsCursor
  643. //=--------------------------------------------------------------------------=
  644. // Creates a cursor containing information about the current cursor
  645. //
  646. // Parameters:
  647. // riid - [in] the interface ID to which to return a pointer
  648. // ppvColumnsCursor - [out] a pointer to memory in which to return the
  649. // interface pointer
  650. // pcRows - [out] a pointer to memory in which to return the
  651. // number of rows in the metadata cursor
  652. //
  653. // Output:
  654. // HRESULT - S_OK if successful
  655. // E_FAIL can't create cursor
  656. // E_INVALIDARG bad parameter
  657. // E_OUTOFMEMORY not enough memory
  658. // E_NOINTERFACE interface not available
  659. //
  660. // Notes:
  661. // This function only succeeds when creating a meta-metadata cursor.
  662. //
  663. HRESULT CVDMetadataCursor::GetColumnsCursor(REFIID riid, IUnknown **ppvColumnsCursor, ULONG *pcRows)
  664. {
  665. ASSERT_POINTER(ppvColumnsCursor, IUnknown*)
  666. ASSERT_NULL_OR_POINTER(pcRows, ULONG)
  667. if (!ppvColumnsCursor)
  668. {
  669. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  670. return E_INVALIDARG;
  671. }
  672. // init out parameters
  673. *ppvColumnsCursor = NULL;
  674. if (pcRows)
  675. *pcRows = 0;
  676. if (!m_ulMetaColumns) // can't create meta-meta-metadata cursor
  677. {
  678. VDSetErrorInfo(IDS_ERR_CANTCREATEMETACURSOR, IID_ICursor, m_pResourceDLL);
  679. return E_FAIL;
  680. }
  681. // make sure caller asked for an available interface
  682. if (riid != IID_IUnknown && riid != IID_ICursor && riid != IID_ICursorMove && riid != IID_ICursorScroll)
  683. {
  684. VDSetErrorInfo(IDS_ERR_NOINTERFACE, IID_ICursor, m_pResourceDLL);
  685. return E_NOINTERFACE;
  686. }
  687. // create meta-metadata cursor
  688. CVDMetadataCursor * pMetadataCursor;
  689. HRESULT hr = CVDMetadataCursor::Create(m_ulMetaColumns, m_pMetaColumns, 0, 0, &pMetadataCursor, m_pResourceDLL);
  690. if (FAILED(hr)) // the only reason for failing here is an out of memory condition
  691. {
  692. VDSetErrorInfo(IDS_ERR_OUTOFMEMORY, IID_ICursor, m_pResourceDLL);
  693. return hr;
  694. }
  695. *ppvColumnsCursor = (ICursor*)pMetadataCursor;
  696. if (pcRows)
  697. *pcRows = m_ulMetaColumns;
  698. return S_OK;
  699. }
  700. //=--------------------------------------------------------------------------=
  701. // ICursor SetBindings
  702. //=--------------------------------------------------------------------------=
  703. // Replaces the existing column bindings or adds new column bindings to the
  704. // existing ones
  705. //
  706. // Parameters:
  707. // cCol - [in] the number of columns to bind
  708. // rgBoundColumns - [in] an array of column bindings, one for each
  709. // column for which data is to be returned
  710. // cbRowLength - [in] the number of bytes of inline memory in a
  711. // single row of data
  712. // dwFlags - [in] a flag that specifies whether to replace the
  713. // existing column bindings or add to them
  714. //
  715. // Output:
  716. // HRESULT - S_OK if successful
  717. // E_INVALIDARG bad parameter
  718. // E_OUTOFMEMORY not enough memory
  719. // CURSOR_DB_E_BADBINDINFO bad binding information
  720. // CURSOR_DB_E_COLUMNUNAVAILABLE columnID is not available
  721. // CURSOR_DB_E_ROWTOOSHORT cbRowLength was less than the minumum (and not zero)
  722. //
  723. // Notes:
  724. //
  725. HRESULT CVDMetadataCursor::SetBindings(ULONG cCol, CURSOR_DBCOLUMNBINDING rgBoundColumns[], ULONG cbRowLength, DWORD dwFlags)
  726. {
  727. ASSERT_NULL_OR_POINTER(rgBoundColumns, CURSOR_DBCOLUMNBINDING)
  728. if (!cCol && dwFlags == CURSOR_DBCOLUMNBINDOPTS_ADD)
  729. return S_OK;
  730. if (cCol && !rgBoundColumns)
  731. {
  732. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  733. return E_INVALIDARG;
  734. }
  735. if (dwFlags != CURSOR_DBCOLUMNBINDOPTS_REPLACE && dwFlags != CURSOR_DBCOLUMNBINDOPTS_ADD)
  736. {
  737. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  738. return E_INVALIDARG;
  739. }
  740. // make sure the bindings are okay
  741. ULONG ulColumns = m_ulMetaColumns;
  742. CVDRowsetColumn * pColumns = m_pMetaColumns;
  743. if (!pColumns)
  744. {
  745. ulColumns = m_ulColumns;
  746. pColumns = m_pColumns;
  747. }
  748. ULONG cbNewRowLength;
  749. ULONG cbNewVarRowLength;
  750. HRESULT hr = ValidateCursorBindings(ulColumns, pColumns, cCol, rgBoundColumns, cbRowLength, dwFlags,
  751. &cbNewRowLength, &cbNewVarRowLength);
  752. if (SUCCEEDED(hr)) // if so, then set them in cursor
  753. {
  754. hr = CVDCursorBase::SetBindings(cCol, rgBoundColumns, cbRowLength, dwFlags);
  755. if (SUCCEEDED(hr)) // store new row lengths computed during validation
  756. {
  757. m_cbRowLength = cbNewRowLength;
  758. m_cbVarRowLength = cbNewVarRowLength;
  759. }
  760. }
  761. return hr;
  762. }
  763. //=--------------------------------------------------------------------------=
  764. // ICursor GetNextRows
  765. //=--------------------------------------------------------------------------=
  766. // Fetches the specified number of rows starting with the row after the
  767. // current one
  768. //
  769. // Parameters:
  770. // udlRowsToSkip - [in] the number of rows to skip before fetching
  771. // pFetchParams - [in, out] a pointer to fetch rows structure
  772. //
  773. // Output:
  774. // HRESULT - S_OK if successful
  775. // CURSOR_DB_S_ENDOFCURSOR reached end of the cursor
  776. //
  777. // Notes:
  778. //
  779. HRESULT CVDMetadataCursor::GetNextRows(LARGE_INTEGER udlRowsToSkip, CURSOR_DBFETCHROWS *pFetchParams)
  780. {
  781. ASSERT_NULL_OR_POINTER(pFetchParams, CURSOR_DBFETCHROWS)
  782. // return if caller doesn't supply fetch rows structure
  783. if (!pFetchParams)
  784. return S_OK;
  785. // init out parameter
  786. pFetchParams->cRowsReturned = 0;
  787. // return if caller didn't ask for any rows
  788. if (!pFetchParams->cRowsRequested)
  789. return S_OK;
  790. // make sure fetch flags has only valid values
  791. if (pFetchParams->dwFlags != CURSOR_DBROWFETCH_DEFAULT &&
  792. pFetchParams->dwFlags != CURSOR_DBROWFETCH_CALLEEALLOCATES &&
  793. pFetchParams->dwFlags != CURSOR_DBROWFETCH_FORCEREFRESH &&
  794. pFetchParams->dwFlags != (CURSOR_DBROWFETCH_CALLEEALLOCATES | CURSOR_DBROWFETCH_FORCEREFRESH))
  795. return CURSOR_DB_E_BADFETCHINFO;
  796. // if memory was caller allocated, make sure caller supplied data pointer
  797. if (!(pFetchParams->dwFlags & CURSOR_DBROWFETCH_CALLEEALLOCATES) && !pFetchParams->pData)
  798. return CURSOR_DB_E_BADFETCHINFO;
  799. // if memory was caller allocated, make sure caller supplied var-data pointer and size if needed
  800. if (!(pFetchParams->dwFlags & CURSOR_DBROWFETCH_CALLEEALLOCATES) && m_fNeedVarData &&
  801. (!pFetchParams->pVarData || !pFetchParams->cbVarData))
  802. return CURSOR_DB_E_BADFETCHINFO;
  803. // allocate necessary memory
  804. if (pFetchParams->dwFlags & CURSOR_DBROWFETCH_CALLEEALLOCATES)
  805. {
  806. // inline memory
  807. pFetchParams->pData = g_pMalloc->Alloc(pFetchParams->cRowsRequested * m_cbRowLength);
  808. if (!pFetchParams->pData)
  809. {
  810. VDSetErrorInfo(IDS_ERR_OUTOFMEMORY, IID_ICursor, m_pResourceDLL);
  811. return E_OUTOFMEMORY;
  812. }
  813. if (m_fNeedVarData)
  814. {
  815. // out-of-line memory
  816. pFetchParams->pVarData = g_pMalloc->Alloc(pFetchParams->cRowsRequested * m_cbVarRowLength);
  817. if (!pFetchParams->pData)
  818. {
  819. g_pMalloc->Free(pFetchParams->pData);
  820. pFetchParams->pData = NULL;
  821. VDSetErrorInfo(IDS_ERR_OUTOFMEMORY, IID_ICursor, m_pResourceDLL);
  822. return E_OUTOFMEMORY;
  823. }
  824. }
  825. else
  826. pFetchParams->pVarData = NULL;
  827. }
  828. // fetch data
  829. HRESULT hrFetch = S_OK;
  830. CVDRowsetColumn * pColumn;
  831. CURSOR_DBCOLUMNID cursorColumnID;
  832. CURSOR_DBCOLUMNBINDING * pCursorBinding;
  833. BYTE * pData = (BYTE*)pFetchParams->pData;
  834. BYTE * pVarData = (BYTE*)pFetchParams->pVarData;
  835. // iterate through rows
  836. for (ULONG ulRow = 0; ulRow < pFetchParams->cRowsRequested; ulRow++)
  837. {
  838. // increment row
  839. m_lCurrentRow++;
  840. // make sure we didn't hit end of table
  841. if (m_lCurrentRow >= (LONG)m_ulColumns)
  842. {
  843. m_lCurrentRow = (LONG)m_ulColumns;
  844. hrFetch = CURSOR_DB_S_ENDOFCURSOR;
  845. goto DoneFetchingMetaData;
  846. }
  847. pCursorBinding = m_pCursorBindings;
  848. pColumn = &m_pColumns[m_lCurrentRow];
  849. // iterate through bindings
  850. for (ULONG ulBind = 0; ulBind < m_ulCursorBindings; ulBind++)
  851. {
  852. cursorColumnID = pCursorBinding->columnID;
  853. // return requested data
  854. if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_BINDTYPE))
  855. {
  856. pVarData += ReturnData_I4(pColumn->GetBindType(), pCursorBinding, pData, pVarData);
  857. }
  858. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_COLUMNID))
  859. {
  860. pVarData += ReturnData_DBCOLUMNID(pColumn->GetCursorColumnID(), pCursorBinding, pData, pVarData);
  861. }
  862. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_DATACOLUMN))
  863. {
  864. pVarData += ReturnData_BOOL(pColumn->GetDataColumn(), pCursorBinding, pData, pVarData);
  865. }
  866. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_ENTRYIDMAXLENGTH))
  867. {
  868. pVarData += ReturnData_I4(pColumn->GetEntryIDMaxLength(), pCursorBinding, pData, pVarData);
  869. }
  870. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_FIXED))
  871. {
  872. pVarData += ReturnData_BOOL(pColumn->GetFixed(), pCursorBinding, pData, pVarData);
  873. }
  874. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_MAXLENGTH))
  875. {
  876. pVarData += ReturnData_I4(pColumn->GetMaxLength(), pCursorBinding, pData, pVarData);
  877. }
  878. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_NAME))
  879. {
  880. pVarData += ReturnData_LPWSTR(pColumn->GetName(), pCursorBinding, pData, pVarData);
  881. }
  882. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_NUMBER))
  883. {
  884. pVarData += ReturnData_I4(pColumn->GetNumber(), pCursorBinding, pData, pVarData);
  885. }
  886. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_NULLABLE))
  887. {
  888. pVarData += ReturnData_BOOL(pColumn->GetNullable(), pCursorBinding, pData, pVarData);
  889. }
  890. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_SCALE))
  891. {
  892. pVarData += ReturnData_I4(pColumn->GetScale(), pCursorBinding, pData, pVarData);
  893. }
  894. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_TYPE))
  895. {
  896. pVarData += ReturnData_I4(pColumn->GetCursorType(), pCursorBinding, pData, pVarData);
  897. }
  898. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_UPDATABLE))
  899. {
  900. pVarData += ReturnData_I4(pColumn->GetUpdatable(), pCursorBinding, pData, pVarData);
  901. }
  902. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_UNIQUE))
  903. {
  904. pVarData += ReturnData_BOOL(pColumn->GetUnique(), pCursorBinding, pData, pVarData);
  905. }
  906. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_CASESENSITIVE))
  907. {
  908. pVarData += ReturnData_BOOL(pColumn->GetCaseSensitive(), pCursorBinding, pData, pVarData);
  909. }
  910. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_AUTOINCREMENT))
  911. {
  912. pVarData += ReturnData_BOOL(pColumn->GetAutoIncrement(), pCursorBinding, pData, pVarData);
  913. }
  914. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_HASDEFAULT))
  915. {
  916. pVarData += ReturnData_BOOL(pColumn->GetHasDefault(), pCursorBinding, pData, pVarData);
  917. }
  918. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_COLLATINGORDER))
  919. {
  920. pVarData += ReturnData_I4(pColumn->GetCollatingOrder(), pCursorBinding, pData, pVarData);
  921. }
  922. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_BASENAME))
  923. {
  924. pVarData += ReturnData_LPWSTR(pColumn->GetBaseName(), pCursorBinding, pData, pVarData);
  925. }
  926. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_BASECOLUMNNAME))
  927. {
  928. pVarData += ReturnData_LPWSTR(pColumn->GetBaseColumnName(), pCursorBinding, pData, pVarData);
  929. }
  930. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_DEFAULTVALUE))
  931. {
  932. pVarData += ReturnData_LPWSTR(pColumn->GetDefaultValue(), pCursorBinding, pData, pVarData);
  933. }
  934. else if (IsEqualCursorColumnID(cursorColumnID, CURSOR_COLUMN_BMKTEMPORARY))
  935. {
  936. pVarData += ReturnData_Bookmark(m_lCurrentRow, pCursorBinding, pData, pVarData);
  937. }
  938. pCursorBinding++;
  939. }
  940. // increment returned row count
  941. pFetchParams->cRowsReturned++;
  942. pData += m_cbRowLength;
  943. }
  944. DoneFetchingMetaData:
  945. // cleanup memory allocations if we did not retrieve any rows
  946. if (pFetchParams->dwFlags & CURSOR_DBROWFETCH_CALLEEALLOCATES && !pFetchParams->cRowsReturned)
  947. {
  948. if (pFetchParams->pData)
  949. {
  950. g_pMalloc->Free(pFetchParams->pData);
  951. pFetchParams->pData = NULL;
  952. }
  953. if (pFetchParams->pVarData)
  954. {
  955. g_pMalloc->Free(pFetchParams->pVarData);
  956. pFetchParams->pVarData = NULL;
  957. }
  958. }
  959. return hrFetch;
  960. }
  961. //=--------------------------------------------------------------------------=
  962. // ICursor Requery
  963. //=--------------------------------------------------------------------------=
  964. // Repopulates the cursor based on its original definition
  965. //
  966. // Parameters:
  967. // none
  968. //
  969. // Output:
  970. // HRESULT - S_OK if successful
  971. //
  972. // Notes:
  973. //
  974. HRESULT CVDMetadataCursor::Requery(void)
  975. {
  976. m_lCurrentRow = -1;
  977. return S_OK;
  978. }
  979. //=--------------------------------------------------------------------------=
  980. // ICursorMove methods implemented
  981. //=--------------------------------------------------------------------------=
  982. //=--------------------------------------------------------------------------=
  983. // ICursorMove Move
  984. //=--------------------------------------------------------------------------=
  985. // Moves the current row to a new row within the cursor and optionally fetches
  986. // rows from that new position
  987. //
  988. // Parameters:
  989. // cbBookmark - [in] length in bytes of the bookmark
  990. // pBookmark - [in] a pointer to a bookmark which serves as the
  991. // origin for the calculation that determines the
  992. // target row
  993. // dlOffset - [in] a signed count of the rows from the origin
  994. // bookmark to the target row
  995. // pFetchParams - [in, out] a pointer to fetch rows structure
  996. //
  997. // Output:
  998. // HRESULT - S_OK if successful
  999. // E_INVALIDARG bad parameter
  1000. //
  1001. // Notes:
  1002. //
  1003. HRESULT CVDMetadataCursor::Move(ULONG cbBookmark, void *pBookmark, LARGE_INTEGER dlOffset, CURSOR_DBFETCHROWS *pFetchParams)
  1004. {
  1005. ASSERT_POINTER(pBookmark, BYTE)
  1006. ASSERT_NULL_OR_POINTER(pFetchParams, CURSOR_DBFETCHROWS)
  1007. if (!cbBookmark || !pBookmark)
  1008. {
  1009. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  1010. return E_INVALIDARG;
  1011. }
  1012. if (!BookmarkToRow(cbBookmark, pBookmark, &m_lCurrentRow))
  1013. {
  1014. VDSetErrorInfo(IDS_ERR_BADBOOKMARK, IID_ICursor, m_pResourceDLL);
  1015. return CURSOR_DB_E_BADBOOKMARK;
  1016. }
  1017. m_lCurrentRow += (LONG)dlOffset.LowPart;
  1018. if (m_lCurrentRow < -1)
  1019. {
  1020. m_lCurrentRow = -1;
  1021. return CURSOR_DB_S_ENDOFCURSOR;
  1022. }
  1023. else
  1024. if (m_lCurrentRow >= (LONG)m_ulColumns)
  1025. {
  1026. m_lCurrentRow = (LONG)m_ulColumns;
  1027. return CURSOR_DB_S_ENDOFCURSOR;
  1028. }
  1029. if (!pFetchParams)
  1030. return S_OK;
  1031. // since get next rows starts from the row after the current row we must
  1032. // back up one row
  1033. m_lCurrentRow--;
  1034. if (m_lCurrentRow < -1)
  1035. m_lCurrentRow = -1;
  1036. return CVDMetadataCursor::GetNextRows(g_liZero, pFetchParams);
  1037. }
  1038. //=--------------------------------------------------------------------------=
  1039. // ICursorMove GetBookmark
  1040. //=--------------------------------------------------------------------------=
  1041. // Returns the bookmark of the current row
  1042. //
  1043. // Parameters:
  1044. // pBookmarkType - [in] a pointer to the type of bookmark desired
  1045. // cbMaxSize - [in] length in bytes of the client buffer to put the
  1046. // returned bookmark into
  1047. // pcbBookmark - [out] a pointer to memory in which to return the actual
  1048. // length of the returned bookmark
  1049. // pBookmark - [out] a pointer to client buffer to put the returned
  1050. // bookmark into
  1051. //
  1052. // Output:
  1053. // HRESULT - S_OK if successful
  1054. // E_INVALIDARG bad parameter
  1055. //
  1056. // Notes:
  1057. //
  1058. HRESULT CVDMetadataCursor::GetBookmark(CURSOR_DBCOLUMNID *pBookmarkType,
  1059. ULONG cbMaxSize,
  1060. ULONG *pcbBookmark,
  1061. void *pBookmark)
  1062. {
  1063. ASSERT_POINTER(pBookmarkType, CURSOR_DBCOLUMNID)
  1064. ASSERT_POINTER(pcbBookmark, ULONG)
  1065. ASSERT_POINTER(pBookmark, BYTE)
  1066. if (!pBookmarkType || !pcbBookmark || !pBookmark)
  1067. {
  1068. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  1069. return E_INVALIDARG;
  1070. }
  1071. if (cbMaxSize < sizeof(LONG))
  1072. {
  1073. VDSetErrorInfo(IDS_ERR_BUFFERTOOSMALL, IID_ICursor, m_pResourceDLL);
  1074. return CURSOR_DB_E_BUFFERTOOSMALL;
  1075. }
  1076. RowToBookmark(m_lCurrentRow, pcbBookmark, pBookmark);
  1077. return S_OK;
  1078. }
  1079. //=--------------------------------------------------------------------------=
  1080. // ICursorMove Clone
  1081. //=--------------------------------------------------------------------------=
  1082. // Returns a clone of the cursor
  1083. //
  1084. // Parameters:
  1085. // dwFlags - [in] a flag that specifies the clone options
  1086. // riid - [in] the interface desired for the returned clone
  1087. // ppvClonedCursor - [out] a pointer to memory in which to return newly
  1088. // created clone pointer
  1089. //
  1090. // Output:
  1091. // HRESULT - S_OK if successful
  1092. //
  1093. // Notes:
  1094. //
  1095. HRESULT CVDMetadataCursor::Clone(DWORD dwFlags, REFIID riid, IUnknown **ppvClonedCursor)
  1096. {
  1097. CVDMetadataCursor * pMetaCursor = 0;
  1098. HRESULT hr = CVDMetadataCursor::Create(m_ulColumns,
  1099. m_pColumns,
  1100. m_ulMetaColumns,
  1101. m_pMetaColumns,
  1102. &pMetaCursor,
  1103. m_pResourceDLL);
  1104. *ppvClonedCursor = (ICursor*)pMetaCursor;
  1105. return hr;
  1106. }
  1107. //=--------------------------------------------------------------------------=
  1108. // ICursorScroll methods implemented
  1109. //=--------------------------------------------------------------------------=
  1110. //=--------------------------------------------------------------------------=
  1111. // ICursorScroll Scroll
  1112. //=--------------------------------------------------------------------------=
  1113. // Moves the current row to a new row within the cursor, specified as a
  1114. // fraction, and optionally fetches rows from that new position
  1115. //
  1116. // Parameters:
  1117. // ulNumerator - [in] the numerator of the fraction that states the
  1118. // position to scroll to in the cursor
  1119. // ulDenominator - [in] the denominator of that same fraction
  1120. // pFetchParams - [in, out] a pointer to fetch rows structure
  1121. //
  1122. // Output:
  1123. // HRESULT - S_OK if successful
  1124. // CURSOR_DB_E_BADFRACTION - bad fraction
  1125. //
  1126. // Notes:
  1127. //
  1128. HRESULT CVDMetadataCursor::Scroll(ULONG ulNumerator, ULONG ulDenominator, CURSOR_DBFETCHROWS *pFetchParams)
  1129. {
  1130. ASSERT_NULL_OR_POINTER(pFetchParams, CURSOR_DBFETCHROWS)
  1131. if (!ulDenominator) // division by zero is a bad thing!
  1132. {
  1133. // this is a Viaduct1 error message, which doesn't really apply
  1134. VDSetErrorInfo(IDS_ERR_BADFRACTION, IID_ICursor, m_pResourceDLL);
  1135. return CURSOR_DB_E_BADFRACTION;
  1136. }
  1137. m_lCurrentRow = (LONG)((ulNumerator * m_ulColumns) / ulDenominator);
  1138. if (m_lCurrentRow >= (LONG)m_ulColumns)
  1139. m_lCurrentRow = (LONG)m_ulColumns - 1;
  1140. if (!pFetchParams)
  1141. return S_OK;
  1142. // since get next rows starts from the row after the current row we must
  1143. // back up one row
  1144. m_lCurrentRow--;
  1145. if (m_lCurrentRow < -1)
  1146. m_lCurrentRow = -1;
  1147. return CVDMetadataCursor::GetNextRows(g_liZero, pFetchParams);
  1148. }
  1149. //=--------------------------------------------------------------------------=
  1150. // ICursorScroll GetApproximatePosition
  1151. //=--------------------------------------------------------------------------=
  1152. // Returns the approximate location of a bookmark within the cursor, specified
  1153. // as a fraction
  1154. //
  1155. // Parameters:
  1156. // cbBookmark - [in] length in bytes of the bookmark
  1157. // pBookmark - [in] a pointer to the bookmark
  1158. // pulNumerator - [out] a pointer to memory in which to return the
  1159. // numerator of the faction that defines the
  1160. // approximate position of the bookmark
  1161. // pulDenominator - [out] a pointer to memory in which to return the
  1162. // denominator of that same faction
  1163. //
  1164. // Output:
  1165. // HRESULT - S_OK if successful
  1166. // E_INVALIDARG bad parameter
  1167. //
  1168. // Notes:
  1169. //
  1170. HRESULT CVDMetadataCursor::GetApproximatePosition(ULONG cbBookmark, void *pBookmark, ULONG *pulNumerator, ULONG *pulDenominator)
  1171. {
  1172. ASSERT_POINTER(pBookmark, BYTE)
  1173. ASSERT_POINTER(pulNumerator, ULONG)
  1174. ASSERT_POINTER(pulDenominator, ULONG)
  1175. if (!pBookmark || !pulNumerator || !pulDenominator)
  1176. {
  1177. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  1178. return E_INVALIDARG;
  1179. }
  1180. LONG lRow;
  1181. if (!BookmarkToRow(cbBookmark, pBookmark, &lRow))
  1182. {
  1183. VDSetErrorInfo(IDS_ERR_BADBOOKMARK, IID_ICursor, m_pResourceDLL);
  1184. return CURSOR_DB_E_BADBOOKMARK;
  1185. }
  1186. *pulNumerator = lRow + 1;
  1187. *pulDenominator = m_ulColumns ? m_ulColumns : 1;
  1188. return S_OK;
  1189. }
  1190. //=--------------------------------------------------------------------------=
  1191. // ICursorScroll GetApproximateCount
  1192. //=--------------------------------------------------------------------------=
  1193. // Returns the approximate number of rows in the cursor
  1194. //
  1195. // Parameters:
  1196. // pudlApproxCount - [out] a pointer to a buffer containing the
  1197. // returned approximate count of the rows
  1198. // in the cursor
  1199. // pdwFullyPopuldated - [out] a pointer to a buffer containing returned
  1200. // flags indicating whether the cursor is fully
  1201. // populated
  1202. //
  1203. // Output:
  1204. // HRESULT - S_OK if successful
  1205. // E_INVALIDARG bad parameter
  1206. //
  1207. // Notes:
  1208. //
  1209. HRESULT CVDMetadataCursor::GetApproximateCount(LARGE_INTEGER *pudlApproxCount, DWORD *pdwFullyPopulated)
  1210. {
  1211. ASSERT_POINTER(pudlApproxCount, LARGE_INTEGER)
  1212. ASSERT_NULL_OR_POINTER(pdwFullyPopulated, DWORD)
  1213. if (!pudlApproxCount)
  1214. {
  1215. VDSetErrorInfo(IDS_ERR_INVALIDARG, IID_ICursor, m_pResourceDLL);
  1216. return E_INVALIDARG;
  1217. }
  1218. pudlApproxCount->HighPart = 0;
  1219. pudlApproxCount->LowPart = m_ulColumns;
  1220. if (pdwFullyPopulated)
  1221. *pdwFullyPopulated = CURSOR_DBCURSORPOPULATED_FULLY;
  1222. return S_OK;
  1223. }