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.

515 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1998.
  5. //
  6. // File: DisAcc.cxx
  7. //
  8. // Contents: Distributed accessor class
  9. //
  10. // Classes: CDistributedAccessor
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
  14. //
  15. // Notes: See DisBmk.hxx for a description of distriubted bookmark
  16. // format.
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <pch.cxx>
  20. #pragma hdrstop
  21. #include "disacc.hxx"
  22. #include "bmkacc.hxx"
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Member: CDistributedAccessor::CDistributedAccessor, public
  26. //
  27. // Synopsis: Builds bindings to fetch bookmark.
  28. //
  29. // Arguments: [aCursor] -- Child rowsets.
  30. // [cCursor] -- Count of [aCursor].
  31. // [dwAccessorFlags] -- Binding type.
  32. // [cBindings] -- Count of bindings in [rgBindings].
  33. // [rgBindings] -- Bindings. One per bound column.
  34. // [rgStatus] -- Status reported here. May be null.
  35. // [iBookmark] -- Ordinal of bookmark column.
  36. // [cbBookmark] -- Size of bookmark.
  37. // [pCreator] -- IRowset pointer of creator
  38. // [rgAllBindings] -- rgBindings does not contain the bookmark bindings.
  39. // This param contains all the bindings.
  40. // [cAllBindings] -- Count of all bindings
  41. //
  42. // History: 05-Jun-95 KyleP Created.
  43. //
  44. //----------------------------------------------------------------------------
  45. CDistributedAccessor::CDistributedAccessor( IRowset ** const aCursor,
  46. unsigned cCursor,
  47. DBACCESSORFLAGS dwAccessorFlags,
  48. DBCOUNTITEM cBindings,
  49. DBBINDING const * rgBindings,
  50. DBLENGTH cbRowWidth,
  51. DBBINDSTATUS rgStatus[],
  52. void * pCreator,
  53. DBBINDING const * rgAllBindings,
  54. DBCOUNTITEM cAllBindings )
  55. :
  56. CAccessorBase(pCreator, CAccessorBase::eRowDataAccessor),
  57. _aCursor( aCursor ),
  58. _cCursor( cCursor ),
  59. _aIacc( 0 ),
  60. _ahaccBase( 0 ),
  61. _pDistBmkAcc( 0 ),
  62. _cBookmark( 0 ),
  63. _cBookmarkOffsets( 0 ),
  64. _cAllBindings( 0 ),
  65. _dwAccessorFlags( dwAccessorFlags )
  66. {
  67. SCODE sc = S_OK;
  68. SCODE scLast = S_OK;
  69. unsigned cChildIacc = 0;
  70. unsigned iChildBase = 0;
  71. unsigned iChildBookmark = 0;
  72. // make a copy of all the bindings
  73. Win4Assert( rgAllBindings && cAllBindings > 0 );
  74. _cAllBindings = cAllBindings;
  75. _xAllBindings.Init( (ULONG) _cAllBindings );
  76. RtlCopyMemory( _xAllBindings.GetPointer(),
  77. rgAllBindings,
  78. sizeof( DBBINDING ) * _cAllBindings );
  79. // Copy DBOBJECTs
  80. for ( unsigned iBinding = 0; iBinding < _cAllBindings; iBinding++ )
  81. {
  82. if ( 0 != rgAllBindings[iBinding].pTypeInfo ||
  83. 0 != rgAllBindings[iBinding].pBindExt )
  84. {
  85. // These should be NULL as per OLE DB 2.0
  86. if ( rgStatus )
  87. {
  88. rgStatus[iBinding] = DBBINDSTATUS_BADBINDINFO;
  89. }
  90. scLast = DB_E_ERRORSOCCURRED;
  91. }
  92. if ( rgAllBindings[iBinding].pObject )
  93. {
  94. _xAllBindings[iBinding].pObject = new DBOBJECT;
  95. RtlCopyMemory( _xAllBindings[iBinding].pObject,
  96. rgAllBindings[iBinding].pObject,
  97. sizeof( DBOBJECT ) );
  98. }
  99. }
  100. if ( 0 == cBindings )
  101. {
  102. if (FAILED(scLast))
  103. THROW( CException(scLast) );
  104. // 0 bindings - can occur if the bindings only had a bookmark column
  105. return;
  106. }
  107. XArray<DBBINDSTATUS> rgStatTmp( (unsigned) cBindings );
  108. TRY
  109. {
  110. //
  111. // Get accessors from child cursors. All column requests except bookmark
  112. // can be satisfied by a single child cursor. Note that we actually fetch
  113. // the child bookmark here, since it may be a binding(s). We just throw
  114. // that bookmark away. It would be too much trouble to find it later.
  115. //
  116. _ahaccBase = new HACCESSOR [ _cCursor ];
  117. _aIacc = new IAccessor* [ _cCursor ];
  118. RtlZeroMemory(_aIacc, sizeof (IAccessor*) * _cCursor);
  119. for ( ; iChildBase < _cCursor; iChildBase++ )
  120. {
  121. sc = _aCursor[iChildBase]->QueryInterface( IID_IAccessor,
  122. (void **)&_aIacc[iChildBase] );
  123. if (SUCCEEDED( sc ))
  124. {
  125. cChildIacc++;
  126. sc = _aIacc[iChildBase]->CreateAccessor( dwAccessorFlags,
  127. cBindings,
  128. rgBindings,
  129. cbRowWidth,
  130. &_ahaccBase[iChildBase],
  131. rgStatTmp.GetPointer());
  132. if (sc == DB_S_ERRORSOCCURRED && rgStatus)
  133. for (ULONG i = 0; i < cBindings; i++)
  134. if (rgStatTmp[i] != DBBINDSTATUS_OK)
  135. rgStatus[i] = rgStatTmp[i];
  136. }
  137. if ( FAILED(sc) )
  138. {
  139. scLast = sc;
  140. vqDebugOut(( DEB_ERROR,
  141. "CDistributedAccessor: CreateAccessor(child %d) returned 0x%x\n",
  142. iChildBase, sc ));
  143. // Don't throw here. We want to continue on and catch all possible errors
  144. continue;
  145. }
  146. }
  147. if (FAILED(scLast))
  148. THROW( CException(scLast) );
  149. }
  150. CATCH( CException, e )
  151. {
  152. //
  153. // Cleanup as best we can on failure.
  154. //
  155. for ( ; iChildBase > 0; iChildBase-- )
  156. {
  157. _aIacc[iChildBase-1]->ReleaseAccessor( _ahaccBase[iChildBase-1], 0 );
  158. }
  159. for ( ; cChildIacc > 0; cChildIacc-- )
  160. {
  161. _aIacc[cChildIacc-1]->Release();
  162. }
  163. delete [] _aIacc;
  164. _aIacc = 0;
  165. delete [] _ahaccBase;
  166. _ahaccBase = 0;
  167. RETHROW();
  168. }
  169. END_CATCH
  170. Win4Assert( SUCCEEDED(sc) );
  171. }
  172. void CDistributedAccessor::SetupBookmarkAccessor(
  173. CDistributedBookmarkAccessor * pDistBmkAcc,
  174. DBBINDSTATUS rgStatus[],
  175. DBORDINAL iBookmark,
  176. DBBKMARK cBookmark )
  177. {
  178. _cBookmark = cBookmark;
  179. //
  180. // Look for bookmark binding(s)
  181. //
  182. for ( unsigned i = 0; i < _cAllBindings; i++ )
  183. {
  184. if ( _xAllBindings[i].iOrdinal == iBookmark )
  185. {
  186. if ( ( _xAllBindings[i].wType & ~DBTYPE_BYREF) != DBTYPE_BYTES )
  187. {
  188. if ( rgStatus )
  189. rgStatus[i] = DBBINDSTATUS_UNSUPPORTEDCONVERSION;
  190. continue;
  191. }
  192. _xBookmarkOffsets.ReSize( _cBookmarkOffsets + 1 );
  193. _xBookmarkOffsets[_cBookmarkOffsets] = &_xAllBindings[i];
  194. _cBookmarkOffsets++;
  195. }
  196. }
  197. if ( _cBookmarkOffsets )
  198. {
  199. _pDistBmkAcc = pDistBmkAcc;
  200. }
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Member: CDistributedAccessor::~CDistributedAccessor, public
  205. //
  206. // Synopsis: Destructor.
  207. //
  208. // History: 05-Jun-95 KyleP Created.
  209. //
  210. //----------------------------------------------------------------------------
  211. CDistributedAccessor::~CDistributedAccessor()
  212. {
  213. // We should have no references left to it
  214. Win4Assert(GetRefcount() == 0);
  215. // Delete DBOBJECTs
  216. for ( unsigned iBinding = 0; iBinding < _cAllBindings; iBinding++ )
  217. {
  218. if ( _xAllBindings[iBinding].pObject )
  219. {
  220. delete _xAllBindings[iBinding].pObject;
  221. }
  222. // These are for future use according to OLE-DB 2.0 and should be NULL
  223. Win4Assert( 0 == _xAllBindings[iBinding].pTypeInfo &&
  224. 0 == _xAllBindings[iBinding].pBindExt );
  225. }
  226. delete [] _ahaccBase;
  227. delete [] _aIacc;
  228. CAccessorBase * pParent = GetParent();
  229. if (pParent)
  230. {
  231. if (0 == pParent->DecInheritors() && 0 == pParent->GetRefcount())
  232. {
  233. delete pParent;
  234. }
  235. }
  236. }
  237. //+---------------------------------------------------------------------------
  238. //
  239. // Member: CDistributedAccessor::Release, public
  240. //
  241. // Synopsis: Release all resources (accessors)
  242. //
  243. // Returns: SCODE
  244. //
  245. // History: 05-Jun-95 KyleP Created.
  246. //
  247. // Notes: Even on error, we still try to release as much as possible.
  248. //
  249. //----------------------------------------------------------------------------
  250. ULONG CDistributedAccessor::Release()
  251. {
  252. SCODE sc = S_OK;
  253. if ( 0 == CAccessorBase::Release())
  254. {
  255. if ( 0 != _aIacc )
  256. {
  257. for ( unsigned iChild = 0; iChild < _cCursor; iChild++ )
  258. {
  259. Win4Assert (0 != _aIacc[iChild]);
  260. //
  261. // If this call throws (which it shouldn't accoring to spec)
  262. // we could miss release of some child accessors.
  263. //
  264. SCODE scTemp = _aIacc[iChild]->ReleaseAccessor( _ahaccBase[iChild], 0 );
  265. if ( sc == S_OK )
  266. sc = scTemp;
  267. /*
  268. if ( 0 != _ahaccBookmark )
  269. {
  270. //
  271. // If this call throws (which it shouldn't accoring to spec)
  272. // we could miss release of some child accessors.
  273. //
  274. SCODE scTemp = _aIacc[iChild]->ReleaseAccessor( _ahaccBookmark[iChild], 0 );
  275. if ( sc == S_OK )
  276. sc = scTemp;
  277. }
  278. */
  279. _aIacc[iChild]->Release();
  280. _aIacc[iChild] = 0;
  281. }
  282. }
  283. }
  284. if (FAILED(sc))
  285. {
  286. THROW( CException(sc) );
  287. }
  288. return( _cRef );
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Member: CDistributedAccessor::GetBindings, public
  293. //
  294. // Synopsis: Retrieve a copy of client bindings.
  295. //
  296. // Arguments: [pdwAccessorFlags] -- Bind type returned here.
  297. // [pcBindings] -- Count of bindings in [prgBindings] returned
  298. // here.
  299. // [prgBindings] -- Bindings.
  300. //
  301. // Returns: SCODE
  302. //
  303. // History: 05-Jun-95 KyleP Created.
  304. //
  305. //----------------------------------------------------------------------------
  306. SCODE CDistributedAccessor::GetBindings( DBACCESSORFLAGS * pdwAccessorFlags,
  307. DBCOUNTITEM * pcBindings,
  308. DBBINDING * * prgBindings )
  309. {
  310. Win4Assert( pdwAccessorFlags && pcBindings && prgBindings );
  311. *pcBindings = 0;
  312. *prgBindings = 0;
  313. *pdwAccessorFlags = DBACCESSOR_INVALID;
  314. Win4Assert( _cAllBindings && _xAllBindings.GetPointer() );
  315. *prgBindings = (DBBINDING *) newOLE( sizeof( DBBINDING ) * (ULONG) _cAllBindings );
  316. RtlCopyMemory( *prgBindings,
  317. _xAllBindings.GetPointer(),
  318. sizeof( DBBINDING ) * _cAllBindings );
  319. // Copy DBOBJECTs
  320. for ( unsigned iBinding = 0; iBinding < _cAllBindings; iBinding++ )
  321. {
  322. if ( _xAllBindings[iBinding].pObject )
  323. {
  324. (*prgBindings)[iBinding].pObject = (DBOBJECT*) newOLE( sizeof( DBOBJECT ) );
  325. RtlCopyMemory( (*prgBindings)[iBinding].pObject,
  326. _xAllBindings[iBinding].pObject,
  327. sizeof( DBOBJECT ) );
  328. }
  329. // These are for future use according to OLE-DB 2.0 and should be NULL
  330. Win4Assert( 0 == _xAllBindings[iBinding].pTypeInfo &&
  331. 0 == _xAllBindings[iBinding].pBindExt );
  332. }
  333. *pcBindings = _cAllBindings;
  334. *pdwAccessorFlags =_dwAccessorFlags;
  335. return S_OK;
  336. }
  337. //+---------------------------------------------------------------------------
  338. //
  339. // Member: CDistributedAccessor::GetData, public
  340. //
  341. // Synopsis: Fetches data.
  342. //
  343. // Arguments: [iChild] -- Index of child cursor from which base data is
  344. // to be fetched. Indicates 'current' row in [ahrow].
  345. // [hrow] -- HROW for iChild cursor.
  346. // [pData] -- Base for client's data.
  347. //
  348. // Returns: SCODE
  349. //
  350. // History: 05-Jun-95 KyleP Created.
  351. //
  352. // Notes: This optimized version doesn't fetch bookmark(s).
  353. //
  354. //----------------------------------------------------------------------------
  355. SCODE CDistributedAccessor::GetData( unsigned iChild, HROW hrow, void * pData )
  356. {
  357. //
  358. // Fetch base columns
  359. //
  360. return ( _ahaccBase ?
  361. _aCursor[iChild]->GetData( hrow, _ahaccBase[iChild], pData ) :
  362. S_OK );
  363. }
  364. //+---------------------------------------------------------------------------
  365. //
  366. // Member: CDistributedAccessor::GetData, public
  367. //
  368. // Synopsis: Fetches data, including bookmark column.
  369. //
  370. // Arguments: [iChild] -- Index of child cursor from which base data is
  371. // to be fetched. Indicates 'current' row in [ahrow].
  372. // [ahrow] -- 'Top' HROW for all cursors. Used for bookmark
  373. // hints.
  374. // [pData] -- Base for client's data.
  375. //
  376. // Returns: SCODE
  377. //
  378. // History: 05-Jun-95 KyleP Created.
  379. //
  380. //----------------------------------------------------------------------------
  381. SCODE CDistributedAccessor::GetData( unsigned iChild, HROW * ahrow, void * pData )
  382. {
  383. //
  384. // Fetch base columns
  385. //
  386. SCODE sc = GetData( iChild, ahrow[iChild], pData );
  387. //
  388. // If we have bookmark columns, fetch those too.
  389. //
  390. SCODE Status;
  391. XGrowable<BYTE> xBookmarkData;
  392. if ( SUCCEEDED( sc ) && 0 != _pDistBmkAcc )
  393. {
  394. xBookmarkData.SetSize( (unsigned) _cBookmark );
  395. // Fetch bookmark data and value
  396. sc = _pDistBmkAcc->GetData( iChild,
  397. ahrow,
  398. xBookmarkData.Get(),
  399. _cBookmark,
  400. _aCursor,
  401. _cCursor,
  402. &Status );
  403. if ( SUCCEEDED(sc) )
  404. {
  405. // Copy the bookmark data across various bindings
  406. for ( unsigned i = 0; i < _cBookmarkOffsets; i++ )
  407. {
  408. if ( _xBookmarkOffsets[i]->dwPart & DBPART_VALUE )
  409. {
  410. BYTE * pDest;
  411. // is the dest byref
  412. if ( (_xBookmarkOffsets[i]->wType & DBTYPE_BYREF) == DBTYPE_BYREF )
  413. {
  414. pDest = (BYTE*) newOLE( (unsigned) _cBookmark );
  415. *((ULONG_PTR*)((BYTE*)pData + _xBookmarkOffsets[i]->obValue)) =
  416. (ULONG_PTR)pDest;
  417. }
  418. else
  419. {
  420. pDest = (BYTE *)pData + _xBookmarkOffsets[i]->obValue;
  421. }
  422. RtlCopyMemory( pDest, xBookmarkData.Get(), _cBookmark );
  423. }
  424. if ( _xBookmarkOffsets[i]->dwPart & DBPART_LENGTH )
  425. *(DBBKMARK UNALIGNED *)((BYTE *)pData + _xBookmarkOffsets[i]->obLength) = _cBookmark;
  426. if ( _xBookmarkOffsets[i]->dwPart & DBPART_STATUS )
  427. *(DBBKMARK UNALIGNED *)((BYTE *)pData + _xBookmarkOffsets[i]->obStatus) = Status;
  428. }
  429. }
  430. }
  431. return( sc );
  432. }