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.

664 lines
19 KiB

  1. //---------------------------------------------------------------------------
  2. // RowsetColumn.cpp : RowsetColumn 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 "RSColumn.h"
  9. SZTHISFILE
  10. //=--------------------------------------------------------------------------=
  11. // CVDRowsetColumn - Constructor
  12. //
  13. CVDRowsetColumn::CVDRowsetColumn()
  14. {
  15. m_ulOrdinal = 0;
  16. m_wType = 0;
  17. m_pwszBaseColumnName = NULL;
  18. m_pwszBaseName = NULL;
  19. m_dwBindType = 0;
  20. m_lcidCollatingOrder = 0;
  21. m_pwszDefaultValue = NULL;
  22. m_cbEntryIDMaxLength = 0;
  23. m_cbMaxLength = 0;
  24. m_pwszName = NULL;
  25. m_dwNumber = 0;
  26. m_dwScale = 0;
  27. m_dwCursorType = 0;
  28. m_dwUpdatable = 0;
  29. m_dwVersion = 0;
  30. m_dwStatus = 0;
  31. m_bool.fInitialized = FALSE;
  32. m_bool.fAutoIncrement = FALSE;
  33. m_bool.fCaseSensitive = TRUE;
  34. m_bool.fDataColumn = FALSE;
  35. m_bool.fFixed = FALSE;
  36. m_bool.fHasDefault = FALSE;
  37. m_bool.fMultiValued = FALSE;
  38. m_bool.fNullable = FALSE;
  39. m_bool.fSearchable = FALSE;
  40. m_bool.fUnique = FALSE;
  41. m_ulMaxStrLen = 0;
  42. memset(&m_columnID, 0, sizeof(DBID));
  43. memset(&m_cursorColumnID, 0, sizeof(CURSOR_DBCOLUMNID));
  44. #ifdef _DEBUG
  45. g_cVDRowsetColumnCreated++;
  46. #endif
  47. }
  48. //=--------------------------------------------------------------------------=
  49. // ~CVDRowsetColumn - Destructor
  50. //
  51. CVDRowsetColumn::~CVDRowsetColumn()
  52. {
  53. delete [] m_pwszBaseColumnName;
  54. delete [] m_pwszBaseName;
  55. delete [] m_pwszDefaultValue;
  56. delete [] m_pwszName;
  57. if (m_columnID.eKind == DBKIND_PGUID_NAME || m_columnID.eKind == DBKIND_PGUID_PROPID)
  58. delete m_columnID.uGuid.pguid;
  59. if (m_columnID.eKind == DBKIND_GUID_NAME || m_columnID.eKind == DBKIND_NAME || m_columnID.eKind == DBKIND_PGUID_NAME)
  60. delete [] m_columnID.uName.pwszName;
  61. if (m_cursorColumnID.dwKind == CURSOR_DBCOLKIND_GUID_NAME || m_cursorColumnID.dwKind == CURSOR_DBCOLKIND_NAME)
  62. delete [] m_cursorColumnID.lpdbsz;
  63. #ifdef _DEBUG
  64. g_cVDRowsetColumnDestroyed++;
  65. #endif
  66. }
  67. //=--------------------------------------------------------------------------=
  68. // Initialize - Initialize rowset column object from IRowset metadata (#1)
  69. //=--------------------------------------------------------------------------=
  70. // This function converts and stores IRowset metadata in ICursor format
  71. //
  72. // Parameters:
  73. // ulOrdinal - [in] original IRowset ordinal of column
  74. // ulCursorOrdinal - [in] newly assigned ICursor ordinal of column
  75. // pColumnInfo - [in] a pointer to an IRowset DBCOLUMNINFO structure
  76. // where to retrieve metadata
  77. // cbMaxBookmark - [in] maximum size of an IRowset bookmark
  78. // pBookmarkColumnID - [in] a pointer to bookmark column identifier if this
  79. // is a bookmark column, otherwise NULL
  80. //
  81. // Output:
  82. // BOOL - TRUE if successful
  83. //
  84. // Notes:
  85. // This function should only be called once
  86. //
  87. BOOL CVDRowsetColumn::Initialize(ULONG ulOrdinal,
  88. ULONG ulCursorOrdinal,
  89. DBCOLUMNINFO * pColumnInfo,
  90. ULONG cbMaxBookmark,
  91. CURSOR_DBCOLUMNID * pBookmarkColumnID)
  92. {
  93. if (m_bool.fInitialized)
  94. {
  95. ASSERT(FALSE, VD_ASSERTMSG_COLALREADYINITIALIZED)
  96. return FALSE;
  97. }
  98. m_ulOrdinal = ulOrdinal;
  99. // Store IRowset metadata
  100. m_wType = pColumnInfo->wType;
  101. m_columnID = pColumnInfo->columnid;
  102. // make copy of guid if necessary
  103. if (m_columnID.eKind == DBKIND_PGUID_NAME || m_columnID.eKind == DBKIND_PGUID_PROPID)
  104. {
  105. m_columnID.uGuid.pguid = new GUID;
  106. if (!m_columnID.uGuid.pguid)
  107. return E_OUTOFMEMORY;
  108. memcpy(m_columnID.uGuid.pguid, pColumnInfo->columnid.uGuid.pguid, sizeof(GUID));
  109. }
  110. // make copy of name if necessary
  111. if (m_columnID.eKind == DBKIND_GUID_NAME || m_columnID.eKind == DBKIND_NAME || m_columnID.eKind == DBKIND_PGUID_NAME)
  112. {
  113. const int nLength = lstrlenW(pColumnInfo->columnid.uName.pwszName);
  114. m_columnID.uName.pwszName = new WCHAR[nLength + 1];
  115. if (!m_columnID.uName.pwszName)
  116. return E_OUTOFMEMORY;
  117. memcpy(m_columnID.uName.pwszName, pColumnInfo->columnid.uName.pwszName, (nLength + 1) * sizeof(WCHAR));
  118. }
  119. // Store ICursor metadata
  120. if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_MAYDEFER)
  121. m_dwBindType = CURSOR_DBBINDTYPE_BOTH;
  122. else
  123. m_dwBindType = CURSOR_DBBINDTYPE_DATA;
  124. if (!pBookmarkColumnID)
  125. m_cursorColumnID = ColumnIDToCursorColumnID(pColumnInfo->columnid, ulCursorOrdinal);
  126. else
  127. m_cursorColumnID = *pBookmarkColumnID; // use supplied bookmark column identifier
  128. if (m_dwBindType == CURSOR_DBBINDTYPE_BOTH)
  129. m_cbEntryIDMaxLength = sizeof(ULONG) + sizeof(ULONG) + cbMaxBookmark;
  130. else
  131. m_cbEntryIDMaxLength = 0;
  132. // rowset types DBTYPE_GUID and DBTYPE_DBTIMESTAMP are returned as CURSOR_DBTYPE_LPWSTRs
  133. if (pColumnInfo->wType == DBTYPE_GUID || pColumnInfo->wType == DBTYPE_DBTIMESTAMP)
  134. m_cbMaxLength = 64;
  135. else
  136. m_cbMaxLength = pColumnInfo->ulColumnSize;
  137. if (pColumnInfo->pwszName)
  138. {
  139. const int nLength = lstrlenW(pColumnInfo->pwszName);
  140. m_pwszName = new WCHAR[nLength + 1];
  141. if (!m_pwszName)
  142. return E_OUTOFMEMORY;
  143. memcpy(m_pwszName, pColumnInfo->pwszName, (nLength + 1) * sizeof(WCHAR));
  144. }
  145. m_dwNumber = ulCursorOrdinal;
  146. m_dwScale = pColumnInfo->bScale;
  147. m_dwCursorType = TypeToCursorType(pColumnInfo->wType);
  148. if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_WRITE)
  149. m_dwUpdatable = CURSOR_DBUPDATEABLE_UPDATEABLE;
  150. if (!(pColumnInfo->dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
  151. m_bool.fDataColumn = TRUE;
  152. if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_ISFIXEDLENGTH)
  153. {
  154. m_bool.fFixed = TRUE;
  155. m_ulMaxStrLen = GetCursorTypeMaxStrLen(m_dwCursorType, m_cbMaxLength);
  156. }
  157. if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_MAYBENULL)
  158. m_bool.fNullable = TRUE;
  159. m_bool.fInitialized = TRUE;
  160. return TRUE;
  161. }
  162. //=--------------------------------------------------------------------------=
  163. // Initialize - Initialize rowset column object from meta-metadata (#2)
  164. //=--------------------------------------------------------------------------=
  165. // The function stores ICursor meta-metadata
  166. //
  167. // Parameters:
  168. // cursorColumnID - [in] ICursor column identifier
  169. // fDataColumn - [in] is data column?
  170. // cbMaxLength - [in] maximum length of this datatype
  171. // pszName - [in] column name
  172. // dwCursorType - [in] datatype
  173. // dwNumber - [in] ordinal position
  174. //
  175. // Output:
  176. // BOOL - TRUE if successful
  177. //
  178. // Notes:
  179. // This function should only be called once
  180. //
  181. BOOL CVDRowsetColumn::Initialize(const CURSOR_DBCOLUMNID * pCursorColumnID,
  182. BOOL fDataColumn,
  183. ULONG cbMaxLength,
  184. CHAR * pszName,
  185. DWORD dwCursorType,
  186. DWORD dwNumber)
  187. {
  188. if (m_bool.fInitialized)
  189. {
  190. ASSERT(FALSE, VD_ASSERTMSG_COLALREADYINITIALIZED)
  191. return FALSE;
  192. }
  193. // Store ICursor meta-metadata
  194. m_dwBindType = CURSOR_DBBINDTYPE_DATA;
  195. m_cursorColumnID = *pCursorColumnID;
  196. m_cbEntryIDMaxLength = 0;
  197. m_cbMaxLength = cbMaxLength;
  198. if (pszName)
  199. {
  200. MAKE_WIDEPTR_FROMANSI(pwszName, pszName);
  201. const int nLength = lstrlenW(pwszName);
  202. m_pwszName = new WCHAR[nLength + 1];
  203. if (!m_pwszName)
  204. return E_OUTOFMEMORY;
  205. memcpy(m_pwszName, pwszName, (nLength + 1) * sizeof(WCHAR));
  206. }
  207. m_dwNumber = dwNumber;
  208. m_dwScale = 0;
  209. m_dwCursorType = dwCursorType;
  210. m_dwUpdatable = CURSOR_DBUPDATEABLE_NOTUPDATEABLE;
  211. m_bool.fDataColumn = fDataColumn;
  212. m_bool.fFixed = TRUE;
  213. m_bool.fNullable = FALSE;
  214. m_bool.fInitialized = TRUE;
  215. return TRUE;
  216. }
  217. //=--------------------------------------------------------------------------=
  218. // SetStringProperty
  219. //=--------------------------------------------------------------------------=
  220. // The function is called from SetBaseColumnName, SetBaseName and SetDefaultValue
  221. //
  222. // Parameters:
  223. // ppStringProp - [in] A ptr to the ptr that holds the string value
  224. // pNewString - [in] A pointer to the new string value
  225. // ulLength - [in] the length of the string in bytes
  226. //
  227. // Notes:
  228. //
  229. void CVDRowsetColumn::SetStringProperty(WCHAR ** ppStringProp,
  230. WCHAR * pNewString,
  231. ULONG ulLength)
  232. {
  233. // free old string prop if any
  234. delete [] *ppStringProp;
  235. // if ulLength = zero then just return
  236. if (!ulLength)
  237. {
  238. *ppStringProp = NULL;
  239. return;
  240. }
  241. ASSERT_POINTER_LEN(pNewString, ulLength);
  242. *ppStringProp = new WCHAR[ulLength + sizeof(WCHAR)];
  243. if (*ppStringProp)
  244. {
  245. // init null terminator
  246. (*ppStringProp)[ulLength] = 0;
  247. // copy string over
  248. memcpy(*ppStringProp, pNewString, ulLength);
  249. }
  250. }
  251. //=--------------------------------------------------------------------------=
  252. // ColumnIDToCursorColumnID - Convert rowset column ID to cursor column ID
  253. //=--------------------------------------------------------------------------=
  254. // Converts an IRowset DBID structure into its ICursor DBCOLUMNID equivalent
  255. //
  256. // Parameters:
  257. // columnID - [in] the IRowset column identifier
  258. // ulCursorOrdinal - [in] the column's ordinal position in ICursor
  259. //
  260. // Output:
  261. // CURSOR_DBCOLUMNID - The ICursor CURSOR_DBCOLUMNID equivalent of columnID
  262. //
  263. // Notes:
  264. //
  265. CURSOR_DBCOLUMNID CVDRowsetColumn::ColumnIDToCursorColumnID(const DBID& columnID, ULONG ulCursorOrdinal)
  266. {
  267. CURSOR_DBCOLUMNID cursorColumnID;
  268. GUID guidNumberOnly = CURSOR_GUID_NUMBERONLY;
  269. cursorColumnID.guid = guidNumberOnly;
  270. cursorColumnID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
  271. cursorColumnID.lNumber = ulCursorOrdinal;
  272. return cursorColumnID;
  273. // The following code is the old implementation of this function. It caused problems with some
  274. // cursor consumers because it tried to create a cursor column identifier as close as possible
  275. // to the rowset column identifier, thus utilized the problematic lpdbsz member.
  276. /*
  277. CURSOR_DBCOLUMNID ID;
  278. switch (columnID.eKind)
  279. {
  280. case DBKIND_GUID_NAME:
  281. ID.guid = columnID.uGuid.guid;
  282. ID.dwKind = CURSOR_DBCOLKIND_GUID_NAME;
  283. ID.lpdbsz = columnID.uName.pwszName;
  284. break;
  285. case DBKIND_GUID_PROPID:
  286. ID.guid = columnID.uGuid.guid;
  287. ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
  288. ID.lNumber = ulCursorOrdinal;
  289. break;
  290. case DBKIND_NAME:
  291. ID.dwKind = CURSOR_DBCOLKIND_NAME;
  292. ID.lpdbsz = columnID.uName.pwszName;
  293. break;
  294. case DBKIND_PGUID_NAME:
  295. ID.guid = *columnID.uGuid.pguid;
  296. ID.dwKind = CURSOR_DBCOLKIND_GUID_NAME;
  297. ID.lpdbsz = columnID.uName.pwszName;
  298. break;
  299. case DBKIND_PGUID_PROPID:
  300. ID.guid = *columnID.uGuid.pguid;
  301. ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
  302. ID.lNumber = ulCursorOrdinal;
  303. break;
  304. case DBKIND_GUID:
  305. ID.guid = columnID.uGuid.guid;
  306. ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
  307. ID.lNumber = ulCursorOrdinal;
  308. break;
  309. case DBKIND_PROPID:
  310. memset(&ID.guid, 0, sizeof(GUID)); // encode ordinal in guid
  311. ID.guid.Data1 = ulCursorOrdinal;
  312. ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
  313. ID.lNumber = ulCursorOrdinal;
  314. break;
  315. }
  316. // make copy of name if necessary
  317. if (ID.dwKind == CURSOR_DBCOLKIND_GUID_NAME || ID.dwKind == CURSOR_DBCOLKIND_NAME)
  318. {
  319. const int nLength = lstrlenW(columnID.uName.pwszName);
  320. ID.lpdbsz = new WCHAR[nLength + 1];
  321. if (ID.lpdbsz)
  322. memcpy(ID.lpdbsz, columnID.uName.pwszName, (nLength + 1) * sizeof(WCHAR));
  323. }
  324. return ID;
  325. */
  326. }
  327. //=--------------------------------------------------------------------------=
  328. // TypeToCursorType - Convert rowset datatype to cursor datatype
  329. //=--------------------------------------------------------------------------=
  330. // Converts a IRowset DBTYPE value into its ICursor DBVARENUM equivalent
  331. //
  332. // Parameters:
  333. // wType - [in] the IRowset datatype
  334. //
  335. // Output:
  336. // CURSOR_DBVARENUM - The ICursor DBVARENUM equivalent of DBTYPE
  337. //
  338. // Notes:
  339. //
  340. CURSOR_DBVARENUM CVDRowsetColumn::TypeToCursorType(DBTYPE wType)
  341. {
  342. DWORD dwType = 0;
  343. switch (wType)
  344. {
  345. case DBTYPE_ERROR:
  346. dwType = CURSOR_DBTYPE_HRESULT;
  347. break;
  348. case DBTYPE_VARIANT:
  349. dwType = CURSOR_DBTYPE_ANYVARIANT;
  350. break;
  351. case DBTYPE_UI2:
  352. dwType = CURSOR_DBTYPE_UI2;
  353. break;
  354. case DBTYPE_UI4:
  355. dwType = CURSOR_DBTYPE_UI4;
  356. break;
  357. case DBTYPE_UI8:
  358. dwType = CURSOR_DBTYPE_UI8;
  359. break;
  360. case DBTYPE_BYTES:
  361. dwType = CURSOR_DBTYPE_BLOB;
  362. break;
  363. case DBTYPE_STR:
  364. dwType = VT_BSTR;
  365. break;
  366. case DBTYPE_WSTR:
  367. dwType = CURSOR_DBTYPE_LPWSTR;
  368. break;
  369. case DBTYPE_NUMERIC:
  370. dwType = CURSOR_DBTYPE_R8;
  371. break;
  372. //case DBTYPE_HCHAPTER: <- doesn't exist in new spec
  373. // break; // no equivalent
  374. case DBTYPE_UDT:
  375. break; // no equivalent
  376. case DBTYPE_DBDATE:
  377. dwType = CURSOR_DBTYPE_DATE;
  378. break;
  379. case DBTYPE_DBTIME:
  380. dwType = CURSOR_DBTYPE_DATE;
  381. break;
  382. // rowset types DBTYPE_GUID and DBTYPE_DBTIMESTAMP are returned as CURSOR_DBTYPE_LPWSTRs
  383. case DBTYPE_GUID:
  384. case DBTYPE_DBTIMESTAMP:
  385. dwType = CURSOR_DBTYPE_LPWSTR;
  386. break;
  387. default:
  388. dwType = wType;
  389. }
  390. return (CURSOR_DBVARENUM)dwType;
  391. }
  392. //=--------------------------------------------------------------------------=
  393. // CursorTypeToType - Convert cursor datatype to rowset datatype
  394. //=--------------------------------------------------------------------------=
  395. // Converts a ICursor DBVARENUM value into its IRowset DBTYPE equivalent
  396. //
  397. // Parameters:
  398. // CURSOR_DBVARENUM - [in] the ICursor value
  399. //
  400. // Output:
  401. // DBTYPE - The IRowset DBTYPE equivalent of DBVARENUM
  402. //
  403. // Notes:
  404. //
  405. DBTYPE CVDRowsetColumn::CursorTypeToType(CURSOR_DBVARENUM dwCursorType)
  406. {
  407. DBTYPE wType = 0;
  408. switch (dwCursorType)
  409. {
  410. case CURSOR_DBTYPE_HRESULT:
  411. wType = DBTYPE_ERROR;
  412. break;
  413. case CURSOR_DBTYPE_LPSTR:
  414. wType = DBTYPE_STR;
  415. break;
  416. case CURSOR_DBTYPE_LPWSTR:
  417. wType = DBTYPE_WSTR;
  418. break;
  419. case CURSOR_DBTYPE_FILETIME:
  420. wType = DBTYPE_DBTIMESTAMP;
  421. break;
  422. case CURSOR_DBTYPE_BLOB:
  423. wType = DBTYPE_BYTES;
  424. break;
  425. case CURSOR_DBTYPE_DBEXPR:
  426. break; // no equivalent
  427. case CURSOR_DBTYPE_UI2:
  428. wType = DBTYPE_UI2;
  429. break;
  430. case CURSOR_DBTYPE_UI4:
  431. wType = DBTYPE_UI4;
  432. break;
  433. case CURSOR_DBTYPE_UI8:
  434. wType = DBTYPE_UI8;
  435. break;
  436. case CURSOR_DBTYPE_COLUMNID:
  437. wType = DBTYPE_GUID;
  438. break;
  439. case CURSOR_DBTYPE_BYTES:
  440. wType = DBTYPE_BYTES;
  441. break;
  442. case CURSOR_DBTYPE_CHARS:
  443. wType = DBTYPE_STR;
  444. break;
  445. case CURSOR_DBTYPE_WCHARS:
  446. wType = DBTYPE_WSTR;
  447. break;
  448. case CURSOR_DBTYPE_ANYVARIANT:
  449. wType = DBTYPE_VARIANT;
  450. break;
  451. default:
  452. wType = (WORD)dwCursorType;
  453. }
  454. return wType;
  455. }
  456. //=--------------------------------------------------------------------------=
  457. // GetCursorTypeMaxStrLen - Get the buffer size in characters required by
  458. // cursor data type when represented as a string
  459. // (doesn't include NULL terminator)
  460. //
  461. // Notes:
  462. //
  463. // The way these values where computed is as follows:
  464. //
  465. // (1) the maximum precision for each datatype was taken from "Precision of Numeric Data Types" in
  466. // appendix A of the "OLE DB Programmer's Reference, Volume 2".
  467. // (2) the precision was then divided by two and added to the original precision to allow space for
  468. // numberic symbols, like negative signs, dollar signs, commas, etc., that might be present.
  469. // (3) the sum was then doubled to allow for multibyte character sets.
  470. //
  471. // Since this table is not appropriate for floating point datatypes, their values where computed based
  472. // on the string length of the minimum/maximum possible values for these datatypes, then doubled.
  473. //
  474. // datatype minimum value maximum value length
  475. // -------- ------------- ------------- ------
  476. // float 1.175494351e-38 3.402823466e+38 15
  477. // double 2.2250738585072014e-308 1.7976931348623158e+308 23
  478. //
  479. ULONG CVDRowsetColumn::GetCursorTypeMaxStrLen(DWORD dwCursorType, ULONG cbMaxLength)
  480. {
  481. ULONG ulMaxStrLen = cbMaxLength; // default for fixed length strings
  482. switch (dwCursorType)
  483. {
  484. case VT_I1:
  485. ulMaxStrLen = (3 + 1) * 2;
  486. break;
  487. case CURSOR_DBTYPE_I2:
  488. ulMaxStrLen = (5 + 2) * 2;
  489. break;
  490. case CURSOR_DBTYPE_I4:
  491. ulMaxStrLen = (10 + 5) * 2;
  492. break;
  493. case CURSOR_DBTYPE_I8:
  494. ulMaxStrLen = (19 + 9) * 2;
  495. break;
  496. case CURSOR_DBTYPE_R4:
  497. ulMaxStrLen = (15) * 2;
  498. break;
  499. case CURSOR_DBTYPE_R8:
  500. ulMaxStrLen = (23) * 2;
  501. break;
  502. case CURSOR_DBTYPE_CY:
  503. ulMaxStrLen = (19 + 9) * 2;
  504. break;
  505. case CURSOR_DBTYPE_DATE:
  506. ulMaxStrLen = (32 + 16) * 2;
  507. break;
  508. case CURSOR_DBTYPE_FILETIME:
  509. ulMaxStrLen = (32 + 16) * 2;
  510. break;
  511. case CURSOR_DBTYPE_BOOL:
  512. ulMaxStrLen = (5 + 2) * 2;
  513. break;
  514. case VT_UI1:
  515. ulMaxStrLen = (3 + 1) * 2;
  516. break;
  517. case CURSOR_DBTYPE_UI2:
  518. ulMaxStrLen = (5 + 2) * 2;
  519. break;
  520. case CURSOR_DBTYPE_UI4:
  521. ulMaxStrLen = (10 + 5) * 2;
  522. break;
  523. case CURSOR_DBTYPE_UI8:
  524. ulMaxStrLen = (20 + 10) * 2;
  525. break;
  526. }
  527. return ulMaxStrLen;
  528. }