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.

540 lines
11 KiB

  1. //------------------------------------------------------------------------------
  2. //
  3. // Microsoft Sidewalk
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: oledbhelp.h
  7. //
  8. // Contents: OLE DB helper methods
  9. //
  10. // Owner: BassamT
  11. //
  12. // History: 11/30/97 BassamT Created.
  13. //
  14. //------------------------------------------------------------------------------
  15. #if (!defined(BUILD_FOR_NT40))
  16. #pragma once
  17. //
  18. // typedefs
  19. //
  20. // Column Number (cn). This number starts at 1.
  21. typedef ULONG CNUM;
  22. // Row number (rn). These numbers start at 0.
  23. typedef ULONG RNUM;
  24. // Offset (in bytes) into a structure or buffer (ob)
  25. typedef DWORD OFFSET;
  26. // Bookmark data type (bmk)
  27. typedef ULONG BOOKMARK;
  28. //
  29. // constants that can be tuned for performance
  30. //
  31. // The maximum number of bytes to store inline for variable size data types.
  32. const UINT k_cbInlineMax = 100;
  33. // the number of rows to fetch at once.
  34. const ULONG k_RowFetchCount = 20;
  35. // Column alignment within a row.
  36. // TODO : Should this be sizeof(DWORD) instead ?
  37. const DWORD k_ColumnAlign = 8;
  38. //
  39. // constants
  40. //
  41. // invalid row number
  42. const CNUM CNUM_INVALID = 0xFFFFFFFF;
  43. // invalid row number
  44. const RNUM RNUM_INVALID = 0xFFFFFFFF;
  45. //
  46. // conversion helpers
  47. //
  48. const UINT k_cchUCHARAsDecimalString = sizeof("255") - 1;
  49. const UINT k_cchUSHORTAsDecimalString = sizeof("32767") - 1;
  50. const UINT k_cchUINTAsDecimalString = sizeof("4294967294") - 1;
  51. const UINT k_cchUINTAsHexString = sizeof("FFFFFFFF") - 1;
  52. const UINT k_cchINTAsDecimalString = sizeof("-2147483648") - 1;
  53. const UINT k_cchBOOLAsDecimalString = sizeof("1") - 1;
  54. const UINT k_cchDOUBLEAsDecimalString = sizeof("2.2250738585072014 E + 308") - 1;
  55. //
  56. // macros
  57. //
  58. #define static_wcslen(pwsz) ((sizeof(pwsz) / sizeof(WCHAR)) - 1)
  59. #define inrange(z,zmin,zmax) ( (zmin) <= (z) && (z) <= (zmax) )
  60. #define DBID_USE_GUID_OR_PGUID(e) \
  61. ((1<<(e)) & \
  62. ( 1<<DBKIND_GUID \
  63. | 1<<DBKIND_GUID_NAME \
  64. | 1<<DBKIND_GUID_PROPID \
  65. | 1<<DBKIND_PGUID_NAME \
  66. | 1<<DBKIND_PGUID_PROPID ))
  67. #define DBID_USE_GUID(e) \
  68. ((1<<(e)) & \
  69. ( 1<<DBKIND_GUID \
  70. | 1<<DBKIND_GUID_NAME \
  71. | 1<<DBKIND_GUID_PROPID ))
  72. #define DBID_USE_PGUID(e) \
  73. ((1<<(e)) & \
  74. ( 1<<DBKIND_PGUID_NAME \
  75. | 1<<DBKIND_PGUID_PROPID ))
  76. #define DBID_USE_NAME(e) \
  77. ((1<<(e)) & \
  78. ( 1<<DBKIND_NAME \
  79. | 1<<DBKIND_GUID_NAME \
  80. | 1<<DBKIND_PGUID_NAME ))
  81. #define DBID_USE_PROPID(e) \
  82. ((1<<(e)) & \
  83. ( 1<<DBKIND_PROPID \
  84. | 1<<DBKIND_GUID_PROPID \
  85. | 1<<DBKIND_PGUID_PROPID ))
  86. #define DBID_IS_BOOKMARK(dbid) \
  87. ( DBID_USE_GUID(dbid.eKind) && dbid.uGuid.guid == DBCOL_SPECIALCOL \
  88. || DBID_USE_PGUID(dbid.eKind) && *dbid.uGuid.pguid == DBCOL_SPECIALCOL )
  89. #define SET_DBID_FROM_NAME(dbid, pwsz) \
  90. dbid.eKind = DBKIND_NAME;\
  91. dbid.uName.pwszName = pwsz;
  92. #define IsBadPointer(v) (IsBadReadPtr((void*)hAccessor, sizeof(void*)))
  93. //
  94. // functions
  95. //
  96. inline DWORD RoundDown(DWORD dwSize, DWORD dwAmount)
  97. {
  98. return dwSize & ~(dwAmount - 1);
  99. }
  100. inline DWORD RoundUp(DWORD dwSize, DWORD dwAmount)
  101. {
  102. return (dwSize + (dwAmount - 1)) & ~(dwAmount - 1);
  103. }
  104. #define CLIENT_MALLOC(cb) (CoTaskMemAlloc(cb))
  105. #define CLIENT_FREE(x) (CoTaskMemFree(x), x = NULL)
  106. HRESULT CopyDBIDs(DBID * pdbidDest, const DBID *pdbidSrc);
  107. BOOL CompareDBIDs(const DBID *pdbid1, const DBID *pdbid2);
  108. HRESULT IsValidDBID(const DBID *pdbid);
  109. void FreeDBID(DBID *pdbid);
  110. INT CompareOLEDBTypes(DBTYPE wType, void * pvValue1, void * pvValue2);
  111. inline BOOL IsColumnVarLength
  112. //------------------------------------------------------------------------------
  113. // return TRUE if the column is of a variable length type
  114. (
  115. DBTYPE wType
  116. )
  117. {
  118. if (wType == DBTYPE_BSTR ||
  119. wType == DBTYPE_STR ||
  120. wType == DBTYPE_WSTR ||
  121. wType == DBTYPE_BYTES)
  122. {
  123. return TRUE;
  124. }
  125. return FALSE;
  126. }
  127. inline DWORD AdjustVariableTypesLength
  128. //------------------------------------------------------------------------------
  129. // adjusts the length of variable length data types
  130. (
  131. DBTYPE wType,
  132. DWORD cb
  133. )
  134. {
  135. if (wType == DBTYPE_STR)
  136. {
  137. return cb + 1;
  138. }
  139. if (wType == DBTYPE_WSTR)
  140. {
  141. return cb + sizeof(WCHAR);
  142. }
  143. return cb;
  144. }
  145. inline USHORT GetColumnMaxPrecision
  146. //------------------------------------------------------------------------------
  147. // returns the maximium possible precision of a column, given its type.
  148. // Do not pass a byref, array, or vector column type.
  149. (
  150. DBTYPE wType
  151. // [in] the OLE DB data type
  152. )
  153. {
  154. if ((wType & DBTYPE_BYREF) ||
  155. (wType & DBTYPE_ARRAY) ||
  156. (wType & DBTYPE_VECTOR))
  157. {
  158. Assert (FALSE);
  159. return 0;
  160. }
  161. switch( wType )
  162. {
  163. case DBTYPE_I1:
  164. case DBTYPE_UI1:
  165. return 3;
  166. case DBTYPE_I2:
  167. case DBTYPE_UI2:
  168. return 5;
  169. case DBTYPE_I4:
  170. case DBTYPE_UI4:
  171. return 10;
  172. case DBTYPE_R4:
  173. return 7;
  174. case DBTYPE_I8:
  175. return 19;
  176. case DBTYPE_UI8:
  177. return 20;
  178. case DBTYPE_R8:
  179. return 16;
  180. case DBTYPE_DATE:
  181. return 8;
  182. case DBTYPE_CY:
  183. return 19;
  184. case DBTYPE_DECIMAL:
  185. return 28;
  186. case DBTYPE_NUMERIC:
  187. return 38;
  188. case DBTYPE_EMPTY:
  189. case DBTYPE_NULL:
  190. case DBTYPE_ERROR:
  191. case DBTYPE_BOOL:
  192. case DBTYPE_BSTR:
  193. case DBTYPE_IDISPATCH:
  194. case DBTYPE_IUNKNOWN:
  195. case DBTYPE_VARIANT:
  196. case DBTYPE_GUID:
  197. case DBTYPE_BYTES:
  198. case DBTYPE_STR:
  199. case DBTYPE_WSTR:
  200. case DBTYPE_DBDATE:
  201. case DBTYPE_DBTIME:
  202. case DBTYPE_DBTIMESTAMP:
  203. case DBTYPE_HCHAPTER:
  204. return 0;
  205. default:
  206. Assert (FALSE && "Unsupported data type");
  207. return 0;
  208. }
  209. }
  210. inline ULONG GetColumnSize
  211. //------------------------------------------------------------------------------
  212. // returns the size of the column in bytes
  213. (
  214. DBTYPE wType,
  215. // [in] the OLE DB data type
  216. DWORD cchMaxLength
  217. // [in] if this is a variable size field then this is the max length
  218. // if there is one defined. Otherwise this is 0xFFFFFFFF
  219. )
  220. {
  221. // Handle BYREF destination separately
  222. if ((wType & DBTYPE_BYREF) ||
  223. (wType & DBTYPE_ARRAY) ||
  224. (wType & DBTYPE_VECTOR))
  225. {
  226. return sizeof(void*);
  227. }
  228. switch( wType )
  229. {
  230. case DBTYPE_EMPTY:
  231. case DBTYPE_NULL:
  232. return 0;
  233. case DBTYPE_I2:
  234. case DBTYPE_UI2:
  235. return 2;
  236. case DBTYPE_I4:
  237. case DBTYPE_R4:
  238. case DBTYPE_UI4:
  239. return 4;
  240. case DBTYPE_I8:
  241. case DBTYPE_R8:
  242. case DBTYPE_DATE:
  243. case DBTYPE_UI8:
  244. return 8;
  245. case DBTYPE_ERROR:
  246. return sizeof(SCODE);
  247. case DBTYPE_BOOL:
  248. return sizeof(VARIANT_BOOL);
  249. case DBTYPE_CY:
  250. return sizeof(CY);
  251. case DBTYPE_BSTR:
  252. return sizeof(BSTR);
  253. case DBTYPE_IDISPATCH:
  254. return sizeof(IDispatch*);
  255. case DBTYPE_IUNKNOWN:
  256. return sizeof(IUnknown*);
  257. case DBTYPE_VARIANT:
  258. return sizeof(VARIANT);
  259. case DBTYPE_DECIMAL:
  260. return sizeof(DECIMAL);
  261. case DBTYPE_I1:
  262. case DBTYPE_UI1:
  263. return 1;
  264. case DBTYPE_GUID:
  265. return sizeof(GUID);
  266. case DBTYPE_BYTES:
  267. return cchMaxLength;
  268. case DBTYPE_STR:
  269. return cchMaxLength * sizeof(char);
  270. case DBTYPE_WSTR:
  271. return cchMaxLength * sizeof(WCHAR);
  272. case DBTYPE_NUMERIC:
  273. return sizeof(DB_NUMERIC);
  274. case DBTYPE_DBDATE:
  275. return sizeof(DBDATE);
  276. case DBTYPE_DBTIME:
  277. return sizeof(DBTIME);
  278. case DBTYPE_DBTIMESTAMP:
  279. return sizeof(DBTIMESTAMP);
  280. case DBTYPE_HCHAPTER:
  281. return sizeof(HCHAPTER);
  282. default:
  283. Assert (FALSE && "Unsupported data type");
  284. return 0;
  285. }
  286. }
  287. //
  288. // IUnknown Macros
  289. //
  290. // put this macros in your class definition. Make sure that
  291. // you inherit from IUnknown and that you use the
  292. // INIT_IUNKNOWN macro in your class constructor
  293. #define DEFINE_IUNKNOWN \
  294. private:\
  295. LONG _cRefs;\
  296. public:\
  297. STDMETHOD(InternalQueryInterface)(REFIID riid, void ** ppv);\
  298. STDMETHOD(QueryInterface)(REFIID riid, void ** ppv)\
  299. {\
  300. return InternalQueryInterface(riid, ppv);\
  301. }\
  302. STDMETHOD_(ULONG,AddRef)() \
  303. {\
  304. return InterlockedIncrement(&_cRefs);\
  305. }\
  306. STDMETHOD_(ULONG,Release)()\
  307. {\
  308. if (InterlockedDecrement(&_cRefs) == 0)\
  309. {\
  310. delete this;\
  311. return 0;\
  312. }\
  313. return _cRefs;\
  314. }
  315. #define INIT_IUNKNOWN _cRefs = 1;
  316. #define DEFINE_IUNKNOWN_WITH_CALLBACK(x) \
  317. private:\
  318. LONG _cRefs;\
  319. public:\
  320. STDMETHOD(InternalQueryInterface)(REFIID riid, void ** ppv);\
  321. STDMETHOD(QueryInterface)(REFIID riid, void ** ppv)\
  322. {\
  323. return InternalQueryInterface(riid, ppv);\
  324. }\
  325. STDMETHOD_(ULONG,AddRef)() \
  326. {\
  327. return InterlockedIncrement(&_cRefs);\
  328. }\
  329. STDMETHOD_(ULONG,Release)()\
  330. {\
  331. if (InterlockedDecrement(&_cRefs) == 0)\
  332. {\
  333. x();\
  334. return 0;\
  335. }\
  336. return _cRefs;\
  337. }
  338. // put this macros in your class definition. Make sure that
  339. // you inherit from IUnknown and that you use the
  340. // INIT_AGGREGATE_IUNKNOWN macro in your class constructor.
  341. // Also make sure that you use SET_OUTER_IUNKNOWN in wherever
  342. // you get a pointer to the Outer IUnknown
  343. interface INonDelegatingUnknown
  344. {
  345. virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface
  346. (
  347. REFIID riid,
  348. void __RPC_FAR *__RPC_FAR *ppvObject
  349. ) = 0;
  350. virtual ULONG STDMETHODCALLTYPE NonDelegatingAddRef(void) = 0;
  351. virtual ULONG STDMETHODCALLTYPE NonDelegatingRelease(void) = 0;
  352. };
  353. #define DEFINE_AGGREGATE_IUNKNOWN \
  354. private:\
  355. IUnknown * _punkOuter;\
  356. LONG _cRefs;\
  357. public:\
  358. STDMETHOD(InternalQueryInterface)(REFIID riid, void ** ppv);\
  359. STDMETHOD(NonDelegatingQueryInterface)(REFIID riid, void ** ppv)\
  360. {\
  361. if (ppv == NULL) return E_INVALIDARG;\
  362. if (riid != IID_IUnknown)\
  363. {\
  364. return InternalQueryInterface(riid, ppv);\
  365. }\
  366. else\
  367. {\
  368. *ppv = static_cast<INonDelegatingUnknown*>(this);\
  369. NonDelegatingAddRef();\
  370. return NOERROR;\
  371. }\
  372. }\
  373. STDMETHOD_(ULONG,NonDelegatingAddRef)() \
  374. {\
  375. return InterlockedIncrement(&_cRefs);\
  376. }\
  377. STDMETHOD_(ULONG,NonDelegatingRelease)()\
  378. {\
  379. if (InterlockedDecrement(&_cRefs) == 0)\
  380. {\
  381. delete this;\
  382. return 0;\
  383. }\
  384. return _cRefs;\
  385. }\
  386. STDMETHOD(QueryInterface)(REFIID riid, void ** ppv)\
  387. {\
  388. return _punkOuter->QueryInterface(riid, ppv);\
  389. }\
  390. STDMETHOD_(ULONG,AddRef)() \
  391. {\
  392. return _punkOuter->AddRef();\
  393. }\
  394. STDMETHOD_(ULONG,Release)()\
  395. {\
  396. return _punkOuter->Release();\
  397. }
  398. #define INIT_AGGREGATE_IUNKNOWN \
  399. _punkOuter = reinterpret_cast<IUnknown*>(static_cast<INonDelegatingUnknown*>(this)); \
  400. _cRefs = 1;
  401. #define SET_OUTER_IUNKNOWN(punk) if (punk != NULL) _punkOuter = punk;
  402. #define DEFINE_AGGREGATE_IUNKNOWN_WITH_CALLBACKS(_AddRef, _Release) \
  403. private:\
  404. IUnknown * _punkOuter;\
  405. LONG _cRefs;\
  406. public:\
  407. STDMETHOD(InternalQueryInterface)(REFIID riid, void ** ppv);\
  408. STDMETHOD(NonDelegatingQueryInterface)(REFIID riid, void ** ppv)\
  409. {\
  410. if (ppv == NULL) return E_INVALIDARG;\
  411. if (riid != IID_IUnknown)\
  412. {\
  413. return InternalQueryInterface(riid, ppv);\
  414. }\
  415. else\
  416. {\
  417. *ppv = static_cast<INonDelegatingUnknown*>(this);\
  418. NonDelegatingAddRef();\
  419. return NOERROR;\
  420. }\
  421. }\
  422. STDMETHOD_(ULONG,NonDelegatingAddRef)() \
  423. {\
  424. _AddRef();\
  425. return InterlockedIncrement(&_cRefs);\
  426. }\
  427. STDMETHOD_(ULONG,NonDelegatingRelease)()\
  428. {\
  429. _Release();\
  430. if (InterlockedDecrement(&_cRefs) == 0)\
  431. {\
  432. delete this;\
  433. return 0;\
  434. }\
  435. return _cRefs;\
  436. }\
  437. STDMETHOD(QueryInterface)(REFIID riid, void ** ppv)\
  438. {\
  439. return _punkOuter->QueryInterface(riid, ppv);\
  440. }\
  441. STDMETHOD_(ULONG,AddRef)() \
  442. {\
  443. return _punkOuter->AddRef();\
  444. }\
  445. STDMETHOD_(ULONG,Release)()\
  446. {\
  447. return _punkOuter->Release();\
  448. }
  449. #endif