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.

419 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1999.
  5. //
  6. // File: hraccess.hxx
  7. //
  8. // Contents: HRow accessor classes
  9. //
  10. // Classes: CAccessor
  11. // CAccessorAllocator
  12. // CRowDataAccessor
  13. //
  14. // History: 25 Nov 94 dlee Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #pragma once
  18. #include <query.hxx>
  19. #include <accbase.hxx>
  20. #include <tblalloc.hxx>
  21. #include <odbvarnt.hxx>
  22. #include <rowbuf.hxx>
  23. #include <colinfo.hxx>
  24. #include <tbag.hxx>
  25. #include <msdadc.h> // oledb data conversion (IDataConvert) interface
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Class: CAccessorAllocator
  29. //
  30. // Purpose: Handles accessor allocations for BYREF data. Needs to
  31. // inherit from PVarAllocator so COLEDBVariant/CTableVariant methods
  32. // can be called from CAccessor.
  33. //
  34. //--------------------------------------------------------------------------
  35. class CAccessorAllocator : public PVarAllocator
  36. {
  37. public:
  38. void * Allocate(ULONG cbNeeded)
  39. { return newOLE( cbNeeded ); }
  40. void Free(void * pMem)
  41. { deleteOLE( pMem); }
  42. PVOID CopyBSTR(size_t cbNeeded, WCHAR* pwszBuf)
  43. { return SysAllocStringByteLen((CHAR*)pwszBuf, cbNeeded ); }
  44. PVOID AllocBSTR(size_t cbNeeded)
  45. {
  46. return SysAllocStringByteLen( NULL, cbNeeded );
  47. }
  48. void FreeBSTR(PVOID pMem) { SysFreeString((BSTR)pMem); }
  49. BOOL IsBasedMemory(void)
  50. { return FALSE; }
  51. void SetBase(BYTE * pbBaseAddr)
  52. { }
  53. void * OffsetToPointer(ULONG_PTR oBuf)
  54. { return (void *) oBuf; }
  55. ULONG_PTR PointerToOffset(void * pBuf)
  56. { return (ULONG_PTR) pBuf; }
  57. };
  58. //+-------------------------------------------------------------------------
  59. //
  60. // Class: COffsetLengthPair
  61. //
  62. // Purpose: Helper class for making sure accessor output fields don't
  63. // overlap each other.
  64. //
  65. // History: 23 May 1995 dlee Created
  66. //
  67. //--------------------------------------------------------------------------
  68. class COffsetLengthPair
  69. {
  70. public:
  71. void Set( DBBYTEOFFSET ob, DBLENGTH cb)
  72. { _obOffset = ob; _cbLength = cb; }
  73. BOOL isInConflict( COffsetLengthPair &other ) const
  74. {
  75. DBBYTEOFFSET end = _obOffset + _cbLength - 1;
  76. DBBYTEOFFSET otherEnd = other._obOffset + other._cbLength - 1;
  77. if ( _obOffset >= other._obOffset &&
  78. _obOffset <= otherEnd )
  79. return TRUE;
  80. else if ( end >= other._obOffset &&
  81. end <= otherEnd )
  82. return TRUE;
  83. else if ( otherEnd >= _obOffset &&
  84. otherEnd <= end )
  85. return TRUE;
  86. else
  87. return FALSE;
  88. }
  89. private:
  90. DBBYTEOFFSET _obOffset;
  91. DBLENGTH _cbLength;
  92. };
  93. //+-------------------------------------------------------------------------
  94. //
  95. // Class: CDataBinding
  96. //
  97. // Purpose: Wraps DBBINDING structure
  98. //
  99. // Notes: This class is used to add a mapped column ID to the user's
  100. // column binding for bookmark support. This is necessary
  101. // because GetBindings must return the same bindings as the
  102. // user set.
  103. //
  104. // History: 25 Mar 1995 Alanw Created
  105. // 04 Jan 2000 KLam CollectOuputPairs using wrong sizes
  106. //
  107. //--------------------------------------------------------------------------
  108. class CDataBinding
  109. {
  110. public:
  111. CDataBinding( ) :
  112. _iRealColumn( 0 ),
  113. _cbRealMaxLen( 0 ),
  114. _fChapter( FALSE )
  115. {
  116. }
  117. CDataBinding( const DBBINDING & Binding ) :
  118. _iRealColumn( Binding.iOrdinal ),
  119. _cbRealMaxLen( Binding.cbMaxLen ),
  120. _fChapter( FALSE )
  121. {
  122. _Binding = Binding;
  123. }
  124. void SetDataColumn( DBORDINAL iColumn ) { _iRealColumn = iColumn; }
  125. DBORDINAL GetDataColumn( void ) const { return _iRealColumn; }
  126. void SetMaxLen( DBLENGTH cbMaxLen ) { _cbRealMaxLen = cbMaxLen; }
  127. DBLENGTH GetMaxLen( void ) const { return _cbRealMaxLen; }
  128. void SetChapter( BOOL fChapt ) { _fChapter = fChapt; }
  129. BOOL IsChapter( void ) const { return _fChapter; }
  130. DBBINDING & Binding() { return _Binding; }
  131. void CollectOutputPairs( COffsetLengthPair * pPairs,
  132. ULONG & cPairs )
  133. {
  134. DBPART part = Binding().dwPart;
  135. if (DBPART_VALUE & part)
  136. pPairs[cPairs++].Set(Binding().obValue, _cbRealMaxLen);
  137. if (DBPART_STATUS & part)
  138. pPairs[cPairs++].Set(Binding().obStatus, sizeof DBROWSTATUS );
  139. if (DBPART_LENGTH & part)
  140. pPairs[cPairs++].Set(Binding().obLength, sizeof DBLENGTH );
  141. }
  142. private:
  143. DBBINDING _Binding; // user's binding structure
  144. DBORDINAL _iRealColumn; // mapped column ID
  145. DBLENGTH _cbRealMaxLen; // our copy of the maxlen - which is
  146. // different from DBBINDINGs if
  147. // passed by ref
  148. BOOL _fChapter; // TRUE if value binding to chapter
  149. };
  150. //+-------------------------------------------------------------------------
  151. //
  152. // Class: CAccessor
  153. //
  154. // Purpose: Gives oledb accessor functionality
  155. //
  156. // Notes: Should there also be an additional class for optimized
  157. // transfer of a field from row buffers to user data when
  158. // no conversion is necessary?
  159. //
  160. // History: 17 Nov 1994 dlee Created
  161. //
  162. //--------------------------------------------------------------------------
  163. class CAccessor : public CAccessorBase
  164. {
  165. public:
  166. CAccessor(DBACCESSORFLAGS dwAccessorFlags,
  167. DBCOUNTITEM cBindings,
  168. const DBBINDING * rgBindings,
  169. DBBINDSTATUS * rgBindStatus,
  170. BOOL fExtendedTypes,
  171. CColumnsInfo * pColumns,
  172. EAccessorType eType,
  173. void * pCreator
  174. );
  175. ~CAccessor();
  176. SCODE GetBindings( DBACCESSORFLAGS * pBindIo,
  177. DBCOUNTITEM * pcBindings,
  178. DBBINDING ** ppBindings);
  179. virtual void GetData(HROW hRow,
  180. void * pData,
  181. CRowBufferSet & rBufferSet,
  182. PQuery & rQuery,
  183. CColumnsInfo & colInfo,
  184. XInterface<IDataConvert>& xDataConvert)
  185. {
  186. Win4Assert( !"CAccessor::GetData must be overridden" );
  187. }
  188. static BOOL CanConvertType(DBTYPE wFromType,
  189. DBTYPE wToType,
  190. BOOL fExtypes,
  191. XInterface<IDataConvert>& xDataConvert);
  192. HACCESSOR Cast() { if (! IsValidType())
  193. THROW( CException( DB_E_BADACCESSORHANDLE) );
  194. return (HACCESSOR) this; }
  195. void Validate( CColumnsInfo & rColumnsInfo, DBBINDSTATUS * pBindStatus );
  196. protected:
  197. void _ConstructorFailed(SCODE scFailure
  198. #if DBG == 1
  199. ,char* pszExplanation = 0
  200. #endif // DBG == 1
  201. );
  202. void _BindingFailed(DBBINDSTATUS BindStat,
  203. DBORDINAL iBinding,
  204. DBBINDSTATUS * pBindStatus
  205. #if DBG == 1
  206. ,char* pszExplanation = 0
  207. #endif // DBG == 1
  208. );
  209. void _Initialize(DBACCESSORFLAGS dwAccessorFlags,
  210. DBCOUNTITEM cBindings,
  211. const DBBINDING * rgBindings,
  212. DBBINDSTATUS * rgBindStatus);
  213. void _ValidateOffsets(DBBINDSTATUS * rgBindStatus);
  214. DBACCESSORFLAGS _dwAccessorFlags;
  215. BOOL _fExtendedTypes;
  216. SCODE _scStatus;
  217. DBCOUNTITEM _cBindings;
  218. XArray<CDataBinding> _aBindings;
  219. // Column # of path for deferred/self loads, or 0xffffffff if none
  220. DBORDINAL _iPathColumn;
  221. // Column # of vpath for special translation of \ to /
  222. DBORDINAL _iVpathBinding;
  223. // Column info needed to go from a column id to a propspec for deferred
  224. // values.
  225. ULONG _idColInfo; // Id of the columns info
  226. CColumnsInfo * _pColumnsInfo;
  227. // All ByRef data is allocated from this pool and freed by the client
  228. // (except dbbindio byref data which is allocated by this pool but NOT
  229. // freed by the client). This is static since it doesn't have any
  230. // state data.
  231. static CAccessorAllocator _Pool;
  232. }; //CAccessor
  233. class CRowDataAccessor : public CAccessor
  234. {
  235. public:
  236. CRowDataAccessor(DBACCESSORFLAGS dwAccessorFlags,
  237. DBCOUNTITEM cBindings,
  238. const DBBINDING * rgBindings,
  239. DBBINDSTATUS * rgBindStatus,
  240. BOOL fExtTypes,
  241. void * pCreator,
  242. CColumnsInfo * pColumns = 0 )
  243. : CAccessor( dwAccessorFlags, cBindings, rgBindings,
  244. rgBindStatus, fExtTypes, pColumns,
  245. CAccessorBase::eRowDataAccessor, pCreator ),
  246. _pQuery(0)
  247. {
  248. }
  249. virtual void GetData(HROW hRow,
  250. void * pData,
  251. CRowBufferSet & rBufferSet,
  252. PQuery & rQuery,
  253. CColumnsInfo & colInfo,
  254. XInterface<IDataConvert>& xDataConvert);
  255. protected:
  256. DBSTATUS _BindToObject(BYTE * pbDst,
  257. CDataBinding & rDstBinding,
  258. BYTE * pbSrc,
  259. CTableColumn & rSrcColumn,
  260. CTableColumnSet & rSrcSet);
  261. DBSTATUS _LoadDeferred(CTableVariant & rSrvVar,
  262. BYTE * pbSrc,
  263. DBORDINAL iColumn,
  264. CTableColumnSet & rSrcSet);
  265. DBSTATUS _ComplexCopy(CDataBinding & rDstBinding,
  266. BYTE * pbSrc,
  267. CTableColumn & rSrcColumn,
  268. DBORDINAL iColumn,
  269. VARTYPE vtSrc,
  270. DBLENGTH & rcbDstLengh,
  271. BYTE * pbSrcData,
  272. VARTYPE vtDst,
  273. BYTE * pbDstData,
  274. CTableColumnSet & rSrcSet,
  275. CRowBuffer & rRowBuffer,
  276. HROW hrow,
  277. XInterface<IDataConvert>& xDataConvert);
  278. DBSTATUS _ByRefCopy(CDataBinding & rDstBinding,
  279. BYTE * pbSrc,
  280. CTableColumn & rSrcColumn,
  281. VARTYPE vtSrc,
  282. CTableVariant & SrcVar,
  283. BYTE * pbSrcData,
  284. VARTYPE vtDst,
  285. BYTE * pbDstData);
  286. DBSTATUS _CopyColumn(BYTE * pbDst,
  287. CDataBinding & rDstBinding,
  288. BYTE * pbSrc,
  289. CTableColumn & rSrcColumn,
  290. CTableColumnSet & rSrcSet,
  291. DBORDINAL iColumn,
  292. CRowBuffer & rRowBuffer,
  293. HROW hrow,
  294. XInterface<IDataConvert>& xDataConvert);
  295. void _LoadPath(CTableColumnSet & rSrcSet,
  296. BYTE * pbSrc,
  297. CFunnyPath & funnyPath );
  298. WORKID _RowWid( CTableColumnSet &rSet, BYTE * pbRow )
  299. {
  300. CTableColumn *pCol = rSet.Find( _pColumnsInfo->GetRowIdColumn() );
  301. if ( VT_VARIANT == pCol->GetStoredType() )
  302. return ((PROPVARIANT *) ( pbRow + pCol->GetValueOffset() ))->lVal;
  303. else
  304. return * (WORKID *) ( pbRow + pCol->GetValueOffset() );
  305. }
  306. // Query object needed for wid to path conversions for deferred values
  307. PQuery * _pQuery;
  308. };
  309. class CRowDataAccessorByRef : public CRowDataAccessor
  310. {
  311. public:
  312. CRowDataAccessorByRef(DBACCESSORFLAGS dwAccessorFlags,
  313. DBCOUNTITEM cBindings,
  314. const DBBINDING * rgBindings,
  315. DBBINDSTATUS * rgBindStatus,
  316. BOOL fExtTypes,
  317. void * pCreator,
  318. CColumnsInfo * pColumns = 0 )
  319. : CRowDataAccessor( dwAccessorFlags,
  320. cBindings,
  321. rgBindings,
  322. rgBindStatus,
  323. fExtTypes,
  324. pCreator,
  325. pColumns )
  326. {
  327. }
  328. virtual void GetData(HROW hRow,
  329. void * pData,
  330. CRowBufferSet & rBufferSet,
  331. PQuery & rQuery,
  332. CColumnsInfo & colInfo,
  333. XInterface<IDataConvert>& xDataConvert);
  334. };
  335. // This function creates an accessor of the appropriate class
  336. CAccessor * CreateAnAccessor( DBACCESSORFLAGS dwAccessorFlags,
  337. DBCOUNTITEM cBindings,
  338. const DBBINDING * rgBindings,
  339. DBBINDSTATUS * rgBindStatus,
  340. BOOL fExtendedTypes,
  341. void * pCreator,
  342. CColumnsInfo * pColumns = 0 );