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.

754 lines
26 KiB

  1. //-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: caccess.cxx
  7. //
  8. // Contents: Microsoft OleDB/OleDS Data Source Object for ADSI
  9. //
  10. // CImpIAccessor object implementing the IAccessor interface.
  11. //
  12. // History: 10-01-96 shanksh Created.
  13. //-------------------------------------------------------------------------
  14. #include "oleds.hxx"
  15. #pragma hdrstop
  16. //-------------------------------------------------------------------------
  17. // CImpIAccessor::CImpIAccessor
  18. //
  19. // CImpIAccessor constructor.
  20. //
  21. //-------------------------------------------------------------------------
  22. CImpIAccessor::CImpIAccessor (
  23. void *pParentObj, //@parm IN | Parent object pointer
  24. LPUNKNOWN pUnkOuter //@parm IN | Outer Unknown pointer
  25. )
  26. {
  27. // Initialize simple member vars
  28. _pUnkOuter = pUnkOuter;
  29. _pObj = pParentObj;
  30. _pextbuffer = NULL;
  31. _dwStatus = 0;
  32. _pIDC = NULL;
  33. _fCriticalSectionInitialized = FALSE;
  34. _pIMalloc = NULL;
  35. ENLIST_TRACKING(CImpIAccessor);
  36. return;
  37. }
  38. //-------------------------------------------------------------------------
  39. // CImpIAccessor::~CImpIAccessor
  40. //
  41. // @mfunc CImpIAccessor destructor.
  42. //
  43. // @rdesc NONE
  44. //-------------------------------------------------------------------------
  45. CImpIAccessor::~CImpIAccessor (
  46. void
  47. )
  48. {
  49. ULONG_PTR hAccessor, hAccessorLast;
  50. PADSACCESSOR pADsaccessor, pADsaccessorBadHandle;
  51. // Cleanup only if there's anything to clean.
  52. if( _pextbuffer ) {
  53. // Get a pointer to the special "BadHandle" accessor.
  54. _pextbuffer->GetItemOfExtBuffer(hAccessorBadHandle, &pADsaccessorBadHandle);
  55. // Get the number of available accessor handles.
  56. _pextbuffer->GetLastItemHandle(hAccessorLast);
  57. // Loop through the reminding accessor handles deleting those which
  58. // are referenced only by this object and refcount decrementing the
  59. // other ones
  60. for (hAccessor =1; hAccessor <=hAccessorLast; hAccessor++) {
  61. // Get a pointer to the next accessor.
  62. _pextbuffer->GetItemOfExtBuffer(hAccessor, &pADsaccessor);
  63. // For valid accessors just delete them.
  64. if( pADsaccessor != pADsaccessorBadHandle )
  65. DeleteADsAccessor(pADsaccessor);
  66. }
  67. // Now delete the buffer which holds accessor handles.
  68. delete _pextbuffer;
  69. }
  70. if( _pIMalloc )
  71. _pIMalloc->Release();
  72. if( _pIDC )
  73. _pIDC->Release();
  74. // Get rid of the critical section.
  75. if (_fCriticalSectionInitialized)
  76. {
  77. DeleteCriticalSection(&_criticalsectionAccessor);
  78. }
  79. return;
  80. }
  81. //-------------------------------------------------------------------------
  82. // CImpIAccessor::FInit
  83. //
  84. // @mfunc Initialize the Accessor implementation object.
  85. //
  86. // @rdesc Did the Initialization Succeed
  87. // @flag S_OK initialization succeeded,
  88. // @flag E_OUTOFMEMORY initialization failed because of
  89. // memory allocation problem,
  90. //-------------------------------------------------------------------------
  91. STDMETHODIMP
  92. CImpIAccessor::FInit (
  93. void
  94. )
  95. {
  96. HRESULT hr;
  97. PADSACCESSOR pADsaccessorBadHandle;
  98. // Prepare a special, "Bad Handle" accessor.
  99. pADsaccessorBadHandle = (PADSACCESSOR)((BYTE *)&_dwGetDataTypeBadHandle);
  100. _dwGetDataTypeBadHandle = ACCESSORTYPE_INERROR;
  101. // Create the ExtBuffer array to hold pointers to malloc'd accessors.
  102. _pextbuffer = (LPEXTBUFF) new CExtBuff;
  103. if (_pextbuffer == NULL ||
  104. !(_pextbuffer->FInit(
  105. sizeof(PADSACCESSOR),
  106. &pADsaccessorBadHandle
  107. ) ))
  108. RRETURN( E_OUTOFMEMORY );
  109. if( !_pIDC ) {
  110. hr = CoCreateInstance(
  111. CLSID_OLEDB_CONVERSIONLIBRARY,
  112. NULL,
  113. CLSCTX_INPROC_SERVER,
  114. IID_IDataConvert,
  115. (void **)&_pIDC
  116. );
  117. if ( FAILED(hr) ) {
  118. RRETURN (hr);
  119. }
  120. }
  121. hr = CoGetMalloc(MEMCTX_TASK, &_pIMalloc);
  122. if (SUCCEEDED(hr))
  123. {
  124. try
  125. {
  126. // This section is for serializing &CreateAccessor.
  127. InitializeCriticalSection(&_criticalsectionAccessor);
  128. _fCriticalSectionInitialized = TRUE;
  129. }
  130. catch(...)
  131. {
  132. hr = E_FAIL;
  133. }
  134. }
  135. RRETURN (hr);
  136. }
  137. //-------------------------------------------------------------------------
  138. // CImpIAccessor::AddRefAccessor
  139. //
  140. // @mfunc Adds a reference count to an existing accessor.
  141. //
  142. // @rdesc Did release of the accessor Succeed
  143. // @flag S_OK | accessor addrefed successfully,
  144. // @flag DB_E_BADACCESSORHANDLE | accessor could not be addrefed
  145. // because its handle was invalid.
  146. //-------------------------------------------------------------------------
  147. STDMETHODIMP CImpIAccessor::AddRefAccessor(
  148. HACCESSOR hAccessor, //@parm IN | handle of the accessor to release
  149. DBREFCOUNT *pcRefCounts //@parm OUT | count of references
  150. )
  151. {
  152. PADSACCESSOR pADsaccessor, pADsaccessorBadHandle;
  153. HRESULT hr;
  154. // Clear in case of error below.
  155. if( pcRefCounts )
  156. *pcRefCounts = 0;
  157. CAutoBlock cab( &(_criticalsectionAccessor) );
  158. // Get a pointer to the accessor.
  159. _pextbuffer->GetItemOfExtBuffer(hAccessor, &pADsaccessor);
  160. // Get a pointer to the special "BadHandle" accessor.
  161. _pextbuffer->GetItemOfExtBuffer(hAccessorBadHandle, &pADsaccessorBadHandle);
  162. // If the handle is valid
  163. if (pADsaccessor != pADsaccessorBadHandle) {
  164. if (pADsaccessor->cRef <= 0)
  165. BAIL_ON_FAILURE( hr = E_FAIL );
  166. pADsaccessor->cRef++;
  167. if (pcRefCounts)
  168. *pcRefCounts = pADsaccessor->cRef;
  169. RRETURN( S_OK );
  170. }
  171. // otherwise complain about a bad handle.
  172. else
  173. RRETURN( DB_E_BADACCESSORHANDLE );
  174. error:
  175. RRETURN( hr );
  176. }
  177. //-------------------------------------------------------------------------
  178. // CImpIAccessor::CreateAccessor
  179. //
  180. // @mfunc Creates an accessor, which is a set of bindings that can be used to
  181. // send data to or retrieve data from the data cache. The method performs
  182. // extensive validations on the input bindings which include verification of
  183. // the access type requested, column availability, data conversions involved,
  184. // etc.
  185. //
  186. // @rdesc Returns one of the following values:
  187. // S_OK | creation of the accessor succeeded,
  188. // E_INVALIDARG | creation of the accessor failed because
  189. // phAccessor was a NULL pointer,
  190. // E_OUTOFMEMORY | creation of the accessor failed because of
  191. // memory allocation problem,
  192. // DB_E_CANTCREATEACCESSOR | DBROWSETFLAGS_MULTIPLEACCESSOR flag was not
  193. // set and a row-fetching method has already
  194. // been called.
  195. // OTHER | other result codes returned by called functions.
  196. //-------------------------------------------------------------------------
  197. STDMETHODIMP CImpIAccessor::CreateAccessor(
  198. DBACCESSORFLAGS dwAccessorFlags,
  199. DBCOUNTITEM cBindings,
  200. const DBBINDING rgBindings[],
  201. DBLENGTH cbRowSize,
  202. HACCESSOR *phAccessor,
  203. DBBINDSTATUS rgStatus[]
  204. )
  205. {
  206. PADSACCESSOR pADsaccessor;
  207. ULONG_PTR hADsaccessor;
  208. HRESULT hr;
  209. ULONG dwGetDataType, dwSetDataType;
  210. DBCOUNTITEM ibind;
  211. BOOL fProviderOwned;
  212. DBBINDSTATUS bindstatus;
  213. ULONG wMask, wBaseType;
  214. if (phAccessor)
  215. *phAccessor = (HACCESSOR)0;
  216. // At the creation of the CAutoBlock object a critical section
  217. // is entered. Concurrent calls to CreateAccessor are entirely
  218. // legal but their interleaving cannot be allowed. The critical
  219. // section is left when this method terminate and the destructor
  220. // for CAutoBlock is called.
  221. CAutoBlock cab( &(_criticalsectionAccessor) );
  222. // phAccessor must never be NULL, non-zero bindings count implies a
  223. // non-NULL array of bindings.
  224. if( phAccessor == NULL || (cBindings && rgBindings == NULL) )
  225. RRETURN( E_INVALIDARG );
  226. // cBindings is 0 and was called on the Command.
  227. if( cBindings == 0 )
  228. RRETURN( DB_E_NULLACCESSORNOTSUPPORTED );
  229. // dwAccessorFlags cannot take any other values than those legal.
  230. if( dwAccessorFlags & (~DBACCESSOR_VALID_FLAGS) )
  231. RRETURN( DB_E_BADACCESSORFLAGS );
  232. // Compute internal types for use by methods using accessors,
  233. DetermineTypes(
  234. dwAccessorFlags,
  235. &dwGetDataType,
  236. &dwSetDataType
  237. );
  238. // and detect possible inconsistencies in AccessorFlags.
  239. if( dwGetDataType == GD_ACCESSORTYPE_INERROR ||
  240. dwSetDataType == SD_ACCESSORTYPE_INERROR )
  241. RRETURN( DB_E_BADACCESSORFLAGS );
  242. // fix conformance test failure. If BYREF accessors are not supported,
  243. // (indicated by DBPROP_BYREFACCESSORS being FALSE), we should return
  244. // the right error
  245. else if( (DB_E_BYREFACCESSORNOTSUPPORTED == dwGetDataType) ||
  246. (DB_E_BYREFACCESSORNOTSUPPORTED == dwSetDataType) )
  247. RRETURN( DB_E_BYREFACCESSORNOTSUPPORTED );
  248. // Initialize the status array to DBBINDSTATUS_OK.
  249. if( rgStatus )
  250. memset(rgStatus, 0x00, (size_t)(cBindings*sizeof(DBBINDSTATUS)));
  251. hr = S_OK;
  252. fProviderOwned = FALSE;
  253. // Perform validations that apply to all types of accessors.
  254. for (ibind=0; ibind < cBindings; ibind++) {
  255. bindstatus = DBBINDSTATUS_OK;
  256. if( rgBindings[ibind].dwMemOwner != DBMEMOWNER_PROVIDEROWNED &&
  257. rgBindings[ibind].dwMemOwner != DBMEMOWNER_CLIENTOWNED )
  258. bindstatus = DBBINDSTATUS_BADBINDINFO;
  259. // The part to be bound must specify one or more out of three values, and
  260. if( (rgBindings[ibind].dwPart &
  261. (DBPART_VALUE |DBPART_LENGTH |DBPART_STATUS)) == 0 ||
  262. // nothing else.
  263. (rgBindings[ibind].dwPart &
  264. ~(DBPART_VALUE |DBPART_LENGTH |DBPART_STATUS)) ||
  265. // Is it a good type to bind to?
  266. !IsGoodBindingType(rgBindings[ibind].wType) )
  267. bindstatus = DBBINDSTATUS_BADBINDINFO;
  268. // DBTYPE_BYREF, DBTYPE_VECTOR and DBTYPE_ARRAY cannot be combined.
  269. else if( (wMask = (rgBindings[ibind].wType & TYPE_MODIFIERS)) &&
  270. wMask != DBTYPE_BYREF &&
  271. wMask != DBTYPE_VECTOR &&
  272. wMask != DBTYPE_ARRAY )
  273. bindstatus = DBBINDSTATUS_BADBINDINFO;
  274. else if ((wBaseType = (rgBindings[ibind].wType & ~TYPE_MODIFIERS)) ==
  275. DBTYPE_EMPTY ||
  276. wBaseType == DBTYPE_NULL)
  277. bindstatus = DBBINDSTATUS_BADBINDINFO;
  278. // DBTYPE_ARRAY and DBTYPE_VECTOR are not supported types
  279. else if( (rgBindings[ibind].wType & DBTYPE_ARRAY) ||
  280. (rgBindings[ibind].wType & DBTYPE_VECTOR) )
  281. bindstatus = DBBINDSTATUS_UNSUPPORTEDCONVERSION;
  282. // dwFlags was DBBINDFLAG_HTML and the type was not a String
  283. else if ( rgBindings[ibind].dwFlags &&
  284. (rgBindings[ibind].dwFlags != DBBINDFLAG_HTML ||
  285. (wBaseType != DBTYPE_STR &&
  286. wBaseType != DBTYPE_WSTR &&
  287. wBaseType != DBTYPE_BSTR)) )
  288. {
  289. // Set Bind status to DBBINDSTATUS_BADBINDINFO
  290. bindstatus = DBBINDSTATUS_BADBINDINFO;
  291. }
  292. else if( rgBindings[ibind].wType == (DBTYPE_RESERVED | DBTYPE_BYREF) )
  293. bindstatus = DBBINDSTATUS_BADBINDINFO;
  294. else if( rgBindings[ibind].dwMemOwner == DBMEMOWNER_PROVIDEROWNED ) {
  295. if( (rgBindings[ibind].wType & TYPE_MODIFIERS) == 0
  296. && rgBindings[ibind].wType != DBTYPE_BSTR )
  297. bindstatus = DBBINDSTATUS_BADBINDINFO;
  298. else
  299. fProviderOwned = TRUE;
  300. }
  301. if( bindstatus != DBBINDSTATUS_OK )
  302. hr = DB_E_ERRORSOCCURRED;
  303. if( rgStatus )
  304. rgStatus[ibind] = bindstatus;
  305. }
  306. // Check for errors in the bindings
  307. BAIL_ON_FAILURE( hr );
  308. if( fProviderOwned &&
  309. (dwGetDataType == GD_ACCESSORTYPE_READ ||
  310. dwGetDataType == GD_ACCESSORTYPE_READ_OPTIMIZED) )
  311. dwGetDataType = GD_ACCESSORTYPE_READ_COLS_BYREF;
  312. // Allocate space for the accessor structure.
  313. pADsaccessor = (ADSACCESSOR *) new BYTE
  314. [(size_t)(sizeof(ADSACCESSOR) + (cBindings ? (cBindings-1) : 0)*
  315. sizeof(DBBINDING))];
  316. if( pADsaccessor == NULL )
  317. RRETURN( E_OUTOFMEMORY );
  318. if( cBindings )
  319. memcpy(
  320. &(pADsaccessor->rgBindings[0]),
  321. &rgBindings[0],
  322. (size_t)(cBindings*sizeof(DBBINDING))
  323. );
  324. pADsaccessor->cBindings = cBindings;
  325. // For accessors valid for writing fill out a list of columns
  326. // so that notifications about their changes can be properly issued.
  327. if( dwSetDataType == SD_ACCESSORTYPE_READWRITE && cBindings ) {
  328. pADsaccessor->rgcol = new DBORDINAL [ (size_t)cBindings ];
  329. if( pADsaccessor->rgcol == NULL ) {
  330. dwSetDataType = SD_ACCESSORTYPE_INERROR;
  331. }
  332. else
  333. for (ibind =0; ibind <cBindings; ibind++)
  334. (pADsaccessor->rgcol)[ibind] = rgBindings[ibind].iOrdinal;
  335. }
  336. else
  337. pADsaccessor->rgcol = NULL;
  338. // Allocate DBOBJECT structures supporting IUnknown types.
  339. for (ibind =0; ibind <cBindings; ibind++)
  340. pADsaccessor->rgBindings[ibind].pObject = NULL;
  341. // Set accessor flags now, so that possible accessor cleanup routine would
  342. // know about additional structures for IUnknown types support.
  343. pADsaccessor->dwFlags = dwAccessorFlags;
  344. // Insert the new accessor pointer into the extensible buffer in which
  345. // accessors are stored.
  346. if( FAILED(hr = _pextbuffer->InsertIntoExtBuffer(
  347. &pADsaccessor,
  348. hADsaccessor
  349. )) ) {
  350. DeleteADsAccessor(pADsaccessor);
  351. RRETURN (hr);
  352. }
  353. pADsaccessor->cRef = 1;
  354. // Fill out the new accessor structure with the binding info.
  355. //pADsaccessor->obRowData = obRowData;
  356. pADsaccessor->cbRowSize = cbRowSize;
  357. // Return the accessor index in the extensible buffer as the accessor
  358. // handle.
  359. *phAccessor = (HACCESSOR) hADsaccessor;
  360. // Now can safely leave.
  361. RRETURN( NOERROR );
  362. error:
  363. RRETURN( hr );
  364. }
  365. //-------------------------------------------------------------------------
  366. // CImpIAccessor::DetermineTypes
  367. //
  368. // @mfunc Determines internal accessor type classification for use by GetData,
  369. // SetData and parameter handling code. Each of these has a separate type indicator
  370. // variable and a separate set of defined types. This allows a very efficient
  371. // handling of different accessors by methods that utilize them.
  372. // Types are determined on the basis of AccessorFlags. Incorrect combinations of
  373. // flags result in assignment of INERROR types.
  374. //
  375. // @rdesc NONE
  376. //-------------------------------------------------------------------------
  377. STDMETHODIMP_(void)
  378. CImpIAccessor::DetermineTypes(
  379. DBACCESSORFLAGS dwAccessorFlags,
  380. ULONG *pdwGetDataType,
  381. ULONG *pdwSetDataType
  382. )
  383. {
  384. if( dwAccessorFlags & DBACCESSOR_PASSBYREF )
  385. {
  386. *pdwGetDataType = (ULONG) DB_E_BYREFACCESSORNOTSUPPORTED;
  387. *pdwSetDataType = (ULONG) DB_E_BYREFACCESSORNOTSUPPORTED;
  388. return;
  389. }
  390. else if( dwAccessorFlags & DBACCESSOR_PARAMETERDATA )
  391. {
  392. *pdwGetDataType = GD_ACCESSORTYPE_INERROR;
  393. *pdwSetDataType = GD_ACCESSORTYPE_INERROR;
  394. return;
  395. }
  396. // Determine types used in row data manipulations.
  397. if( dwAccessorFlags & DBACCESSOR_ROWDATA ) {
  398. // Determine accessor type from the point of
  399. // view of GetData.
  400. if( dwAccessorFlags & DBACCESSOR_OPTIMIZED )
  401. *pdwGetDataType = GD_ACCESSORTYPE_READ_OPTIMIZED;
  402. else
  403. *pdwGetDataType = GD_ACCESSORTYPE_READ;
  404. // Determine accessor type from the point of
  405. // view of SetData. PASSBYREF is disallowed.
  406. *pdwSetDataType = SD_ACCESSORTYPE_READWRITE;
  407. }
  408. else {
  409. *pdwGetDataType = GD_ACCESSORTYPE_INERROR;
  410. *pdwSetDataType = GD_ACCESSORTYPE_INERROR;
  411. }
  412. return;
  413. }
  414. //-------------------------------------------------------------------------
  415. // CImpIAccessor::GetBindings
  416. //
  417. // @mfunc Returns bindings of an accessor.
  418. //
  419. // @rdesc Returns one of the following values:
  420. // S_OK | getting bindings succeeded,
  421. // E_INVALIDARG | getting bindings failed because
  422. // pdwAccessorFlags or pcBindings or
  423. // prgBindings was a NULL pointer,
  424. // E_OUTOFMEMORY | getting bindings failed because memory
  425. // allocation for the bindings array failed,
  426. // OTHER | other result codes stored on the accessor
  427. // object and singifying invalid accessor handle.
  428. //-------------------------------------------------------------------------
  429. STDMETHODIMP CImpIAccessor::GetBindings
  430. (
  431. HACCESSOR hAccessor, // IN | accessor handle
  432. DBACCESSORFLAGS *pdwAccessorFlags, // OUT | stores accessor flags
  433. DBCOUNTITEM *pcBindings, // OUT | stores # of bindings
  434. DBBINDING **prgBindings // OUT | stores array of bindings
  435. )
  436. {
  437. PADSACCESSOR pADsaccessor;
  438. PADSACCESSOR pADsaccessorBadHandle;
  439. DBCOUNTITEM ibind;
  440. DBOBJECT *pObject;
  441. if( pcBindings )
  442. *pcBindings = 0;
  443. if( prgBindings )
  444. *prgBindings = NULL;
  445. if( pdwAccessorFlags )
  446. *pdwAccessorFlags = DBACCESSOR_INVALID;
  447. // Are arguments valid?
  448. if( pdwAccessorFlags == NULL || pcBindings == NULL || prgBindings == NULL )
  449. RRETURN( E_INVALIDARG );
  450. // Obtain pointer to the accessor to be used.
  451. _pextbuffer->GetItemOfExtBuffer(hAccessor, &pADsaccessor);
  452. // Get a pointer to the special "BadHandle" accessor.
  453. _pextbuffer->GetItemOfExtBuffer(hAccessorBadHandle, &pADsaccessorBadHandle);
  454. // Recognize bad accessor handles and return appropriate HRESULT.
  455. if( pADsaccessor == pADsaccessorBadHandle )
  456. return DB_E_BADACCESSORHANDLE;
  457. // If necessary allocate the array of binding structures.
  458. if( pADsaccessor->cBindings ) {
  459. *prgBindings = (DBBINDING *) _pIMalloc->Alloc((ULONG)(
  460. pADsaccessor->cBindings*sizeof(DBBINDING) ));
  461. if( *prgBindings == NULL )
  462. RRETURN ( E_OUTOFMEMORY );
  463. // Copy bindings.
  464. memcpy(
  465. *prgBindings,
  466. pADsaccessor->rgBindings,
  467. (size_t)(pADsaccessor->cBindings*sizeof(DBBINDING))
  468. );
  469. // Loop through bindings and allocate and copy DBOBJECT structs.
  470. for (ibind=0; ibind <pADsaccessor->cBindings; ibind++) {
  471. // If the accessor had failed bindings for SetData, we have
  472. // overloaded an unused structure member with status info, and
  473. // this needs to be cleaned now.
  474. (*prgBindings)[ibind].pTypeInfo = NULL;
  475. if( (*prgBindings)[ibind].pObject ) {
  476. pObject = (DBOBJECT *) _pIMalloc->Alloc( sizeof(DBOBJECT) );
  477. if( pObject ) {
  478. memcpy(
  479. pObject,
  480. (*prgBindings)[ibind].pObject,
  481. sizeof(DBOBJECT)
  482. );
  483. (*prgBindings)[ibind].pObject = pObject;
  484. }
  485. else {
  486. while (ibind--)
  487. if( (*prgBindings)[ibind].pObject )
  488. _pIMalloc->Free((*prgBindings)[ibind].pObject);
  489. _pIMalloc->Free( *prgBindings );
  490. *prgBindings = NULL;
  491. RRETURN( E_OUTOFMEMORY );
  492. }
  493. }
  494. }
  495. }
  496. // Return the count of bindings,
  497. *pcBindings = pADsaccessor->cBindings;
  498. // and accessor flags.
  499. *pdwAccessorFlags = (pADsaccessor->dwFlags & ~DBACCESSOR_REFERENCES_BLOB);
  500. return S_OK;
  501. }
  502. //-------------------------------------------------------------------------
  503. // CImpIAccessor::ReleaseAccessor
  504. //
  505. // @mfunc Releases accessor. If accessor handle is valid the corresponding accessor
  506. // is either freed (if no one else is using it) or its ref count is decremented.
  507. //
  508. // @rdesc Did release of the accessor Succeed
  509. // @flag S_OK | accessor released successfully,
  510. // @flag DB_E_BADACCESSORHANDLE | accessor could not be released because its
  511. // | handle was invalid.
  512. //-------------------------------------------------------------------------
  513. STDMETHODIMP CImpIAccessor::ReleaseAccessor
  514. (
  515. HACCESSOR hAccessor, //@parm IN | handle of the accessor to release
  516. DBREFCOUNT *pcRefCounts //@parm OUT | ref count of the released accessor
  517. )
  518. {
  519. PADSACCESSOR pADsaccessor, pADsaccessorBadHandle;
  520. if( pcRefCounts )
  521. *pcRefCounts = 0;
  522. CAutoBlock cab( &(_criticalsectionAccessor) );
  523. // Get a pointer to the accessor.
  524. _pextbuffer->GetItemOfExtBuffer(hAccessor, &pADsaccessor);
  525. // Get a pointer to the special "BadHandle" accessor.
  526. _pextbuffer->GetItemOfExtBuffer(hAccessorBadHandle, &pADsaccessorBadHandle);
  527. // If the handle is valid
  528. if( pADsaccessor != pADsaccessorBadHandle ) {
  529. ADsAssert(pADsaccessor->cRef > 0);
  530. // Delete if no one else is using it, otherwise
  531. if( pADsaccessor->cRef == 1 ) {
  532. // Delete the accessor structure itself, as well as allocations
  533. // hanging off this structure.
  534. DeleteADsAccessor(pADsaccessor);
  535. // Make sure this handle is marked as "Bad" for future.
  536. _pextbuffer->DeleteFromExtBuffer(hAccessor);
  537. }
  538. // decrement the refcount.
  539. else {
  540. pADsaccessor->cRef--;
  541. if( pcRefCounts )
  542. *pcRefCounts = pADsaccessor->cRef;
  543. }
  544. return NOERROR;
  545. }
  546. // otherwise complain about a bad handle.
  547. else
  548. RRETURN( DB_E_BADACCESSORHANDLE );
  549. }
  550. //-------------------------------------------------------------------------
  551. // CImpIAccessor::DeleteADsAccessor
  552. //
  553. // @mfunc Deletes structures hanging off the ADSACCESSOR and then deletes the
  554. // accessor structure itself.
  555. //
  556. // @rdesc NONE
  557. //-------------------------------------------------------------------------
  558. STDMETHODIMP_(void) CImpIAccessor::DeleteADsAccessor
  559. (
  560. PADSACCESSOR pADsaccessor //@parm IN | Kagera accessor ptr
  561. )
  562. {
  563. DBCOUNTITEM ibind;
  564. // Delete the list of affected columns.
  565. if( pADsaccessor->rgcol )
  566. delete [] pADsaccessor->rgcol;
  567. // If the accessor references BLOBS then DBOBJECT structures describing
  568. // objects dealing with BLOBS need to be deallocated.
  569. for (ibind =0; ibind <pADsaccessor->cBindings; ibind++)
  570. if( pADsaccessor->rgBindings[ibind].pObject )
  571. delete pADsaccessor->rgBindings[ibind].pObject;
  572. delete [] pADsaccessor;
  573. }
  574. STDMETHODIMP
  575. CImpIAccessor::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  576. {
  577. // Is the pointer bad?
  578. if( ppv == NULL )
  579. RRETURN( E_INVALIDARG );
  580. // Place NULL in *ppv in case of failure
  581. *ppv = NULL;
  582. if( IsEqualIID(iid, IID_IUnknown) ) {
  583. *ppv = (IAccessor FAR *) this;
  584. }
  585. else if( IsEqualIID(iid, IID_IAccessor) ) {
  586. *ppv = (IAccessor FAR *) this;
  587. }
  588. else {
  589. RRETURN( E_NOINTERFACE );
  590. }
  591. AddRef();
  592. return S_OK;
  593. }
  594. //---------------------------------------------------------------------------
  595. // CreateBadAccessor
  596. //
  597. // Inserts a bad accessor into the array of accessors (indexed by accessor
  598. // handles). This is required so that inheritance of accessors from commands
  599. // works correctly. If there are any 'holes' in the command's array of
  600. // accessors, then a rowset created from the command should also inherit these
  601. // 'holes' i,e, the array of accessor handles should not be compacted to
  602. // eliminate these holes. This is done using this function.
  603. //
  604. //---------------------------------------------------------------------------
  605. HRESULT
  606. CImpIAccessor::CreateBadAccessor(void)
  607. {
  608. PADSACCESSOR pADsaccessorBadHandle;
  609. ULONG_PTR hADsaccessor;
  610. HRESULT hr;
  611. // Get a pointer to the special "BadHandle" accessor.
  612. _pextbuffer->GetItemOfExtBuffer(hAccessorBadHandle, &pADsaccessorBadHandle);
  613. // ignore the returned accessor handle
  614. hr = _pextbuffer->InsertIntoExtBuffer(
  615. &pADsaccessorBadHandle, hADsaccessor);
  616. RRETURN( hr );
  617. }
  618. //---------------------------------------------------------------------------