📄 sfaccessorimpl.h
字号:
/****************************************************************************** * $Id: SFAccessorImpl.h,v 1.1 2002/08/09 21:36:17 warmerda Exp $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: IAccessor implementation that doesn't suffer IAccessorImpl's * problem with confusion of accessor handle ids. * Author: Frank Warmerdam <warmerdam@pobox.com> * * This code is closely derived from the code in ATLDB.H for IAccessor. * ****************************************************************************** * Copyright (c) 2001, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: SFAccessorImpl.h,v $ * Revision 1.1 2002/08/09 21:36:17 warmerda * New * * Revision 1.2 2001/10/15 15:21:45 warmerda * switch to unix text mode * * Revision 1.1 2001/09/06 03:24:16 warmerda * New * */// It is assumed that ATLDB.H has already been included.// The following is intended to be exactly the same as the ATLDB.H IAccessor// except that IAccessor handles are strictly incrementing 32bit integers// instead of trying to use the pointers as the handle. Using the pointer// causes problems when the accessor is "copied" into other rowsets (ie.// from the ICommand to the IRowset result) causing the handle and pointer// to get out of sync (since the handle has to be preserved but the pointer// changes as a copy of the structure is made). This can be bad if the// old pointer (on the ICommand accessor) is deallocated and then gets reused// as an accessor on the IRowset resulting in two accessors with the same// handle on the Rowset. extern int g_nNextSFAccessorHandle;#ifdef SUPPORT_ATL_NET# define SF_ATL_MAP CAtlMap#else# define SF_ATL_MAP CSimpleMap#endif// SFAccessorImpltemplate <class T, class BindType = ATLBINDINGS, class BindingVector = SF_ATL_MAP < int, BindType* > >class ATL_NO_VTABLE SFAccessorImpl : public IAccessorImplBase<BindType>{ public: typedef BindType _BindType; typedef BindingVector _BindingVector; SFAccessorImpl() { m_bIsCommand = FALSE; m_bHasParamaters = FALSE; m_bIsChangeable = FALSE; } OUT_OF_LINE HRESULT InternalFinalConstruct(IUnknown* pUnkThis) { CComQIPtr<ICommand> spCommand = pUnkThis; if (spCommand != NULL) { m_bIsCommand = TRUE; CComQIPtr<ICommandWithParameters> spCommandParams = pUnkThis; m_bHasParamaters = spCommandParams != NULL; } else // its a Rowset { CComQIPtr<IRowsetChange> spRSChange = pUnkThis; m_bIsChangeable = spRSChange != NULL; } return S_OK; } HRESULT FinalConstruct() { T* pT = (T*)this; return InternalFinalConstruct(pT->GetUnknown()); } void FinalRelease() {#ifdef _DEBUG if (m_rgBindings.GetSize()) ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::~SFAccessorImpl Bindings still in vector, removing\n");#endif //_DEBUG while (m_rgBindings.GetSize()) ReleaseAccessor((HACCESSOR)m_rgBindings.GetKeyAt(0), NULL); } STDMETHOD(AddRefAccessor)(HACCESSOR hAccessor, ULONG *pcRefCount) { ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::AddRefAccessor\n"); if (hAccessor == NULL) { ATLTRACE2(atlTraceDBProvider, 0, _T("AddRefAccessor : Bad hAccessor\n")); return E_INVALIDARG; } if (pcRefCount == NULL) pcRefCount = (ULONG*)_alloca(sizeof(ULONG)); BindType* pBind = m_rgBindings.Lookup((int)hAccessor); *pcRefCount = T::_ThreadModel::Increment((LONG*)&pBind->dwRef); return S_OK; } OUT_OF_LINE ATLCOLUMNINFO* ValidateHelper(ULONG* pcCols, CComPtr<IDataConvert> & rspConvert) { T* pT = (T*)this; rspConvert = pT->m_spConvert; return pT->GetColumnInfo(pT, pcCols); } OUT_OF_LINE HRESULT ValidateBindingsFromMetaData(ULONG cBindings, const DBBINDING rgBindings[], DBBINDSTATUS rgStatus[], bool bHasBookmarks) { HRESULT hr = S_OK; ULONG cCols; CComPtr<IDataConvert> spConvert; ATLCOLUMNINFO* pColInfo = ValidateHelper(&cCols, spConvert); ATLASSERT(pColInfo != NULL); for (ULONG iBinding = 0; iBinding < cBindings; iBinding++) { const DBBINDING& rBindCur = rgBindings[iBinding]; ULONG iOrdAdjusted; if (bHasBookmarks) iOrdAdjusted = rBindCur.iOrdinal; // Bookmarks start with ordinal 0 else iOrdAdjusted = rBindCur.iOrdinal - 1; // Non-bookmarks start w/ ordinal 1 if (rBindCur.iOrdinal > cCols) { hr = DB_E_ERRORSOCCURRED; rgStatus[iBinding] = DBBINDSTATUS_BADORDINAL; continue; } // If a binding specifies provider owned memory, and specifies type // X | BYREF, and the provider's copy is not X or X | BYREF, return // DBBINDSTATUS_BADBINDINFO if (rBindCur.dwMemOwner == DBMEMOWNER_PROVIDEROWNED) { if ((rBindCur.wType & DBTYPE_BYREF) != 0) { DBTYPE dbConsumerType = rBindCur.wType & 0xBFFF; DBTYPE dbProviderType = pColInfo[iOrdAdjusted].wType & 0xBFFF; if (dbConsumerType != dbProviderType) { hr = DB_E_ERRORSOCCURRED; rgStatus[iBinding] = DBBINDSTATUS_BADBINDINFO; continue; } } } ATLASSERT(spConvert != NULL); HRESULT hrConvert = spConvert->CanConvert(pColInfo[iOrdAdjusted].wType, rBindCur.wType); if (FAILED(hrConvert) || hrConvert == S_FALSE) { hr = DB_E_ERRORSOCCURRED; rgStatus[iBinding] = DBBINDSTATUS_UNSUPPORTEDCONVERSION; continue; } } return hr; } STDMETHOD(CreateAccessor)(DBACCESSORFLAGS dwAccessorFlags, ULONG cBindings, const DBBINDING rgBindings[], ULONG cbRowSize, HACCESSOR *phAccessor, DBBINDSTATUS rgStatus[]) { ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::CreateAccessor\n"); T* pT = (T*)this; T::ObjectLock cab(pT); if (!phAccessor) { ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::CreateAccessor : Inavlid NULL Parameter for HACCESSOR*\n"); return E_INVALIDARG; } *phAccessor = NULL; if (cBindings != 0 && rgBindings == NULL) { ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::CreateAccessor : Bad Binding array\n"); return E_INVALIDARG; } if (dwAccessorFlags & DBACCESSOR_PASSBYREF) { CComVariant varByRef; HRESULT hr = pT->GetPropValue(&DBPROPSET_ROWSET, DBPROP_BYREFACCESSORS, &varByRef); if (FAILED(hr) || varByRef.boolVal == VARIANT_FALSE) return DB_E_BYREFACCESSORNOTSUPPORTED; } if (!m_bHasParamaters) { if (dwAccessorFlags & DBACCESSOR_PARAMETERDATA) return DB_E_BADACCESSORFLAGS; } if (m_bIsCommand || !m_bIsChangeable) { if (cBindings == 0) // No NULL Accessors on the command return DB_E_NULLACCESSORNOTSUPPORTED; } if (rgStatus == NULL && cBindings) // Create a fake status array rgStatus = (DBBINDSTATUS*)_alloca(cBindings*sizeof(DBBINDSTATUS)); // Validate the Binding passed HRESULT hr; bool bHasBookmarks = false; CComVariant varBookmarks; HRESULT hrLocal = pT->GetPropValue(&DBPROPSET_ROWSET, DBPROP_BOOKMARKS, &varBookmarks); bHasBookmarks = (hrLocal == S_OK && varBookmarks.boolVal == VARIANT_TRUE); hr = ValidateBindings(cBindings, rgBindings, rgStatus, bHasBookmarks); if (FAILED(hr)) return hr; if (!m_bIsCommand) { hr = ValidateBindingsFromMetaData(cBindings, rgBindings, rgStatus, bHasBookmarks); if (FAILED(hr)) return hr; } hr = IAccessorImplBase<BindType>::CreateAccessor(dwAccessorFlags, cBindings, rgBindings, cbRowSize, phAccessor,rgStatus); if (SUCCEEDED(hr)) { ATLASSERT(*phAccessor != NULL); BindType* pBind = (BindType*)*phAccessor; // NFW: Reset accessor handle! *phAccessor = g_nNextSFAccessorHandle++; hr = m_rgBindings.Add(*phAccessor, pBind) ? S_OK : E_OUTOFMEMORY; } return hr; } STDMETHOD(GetBindings)(HACCESSOR hAccessor, DBACCESSORFLAGS *pdwAccessorFlags, ULONG *pcBindings, DBBINDING **prgBindings) { ATLTRACE2(atlTraceDBProvider, 0, "SFAccessorImpl::GetBindings"); // Zero output parameters in case of failure if (pdwAccessorFlags != NULL) *pdwAccessorFlags = NULL; if (pcBindings != NULL) *pcBindings = NULL; if (prgBindings != NULL) *prgBindings = NULL; // Check if any of the out params are NULL pointers if ((pdwAccessorFlags && pcBindings && prgBindings) == NULL) return E_INVALIDARG; BindType* pBind = m_rgBindings.Lookup((int)hAccessor); HRESULT hr = DB_E_BADACCESSORHANDLE; if (pBind != NULL) { *pdwAccessorFlags = pBind->dwAccessorFlags; *pcBindings = pBind->cBindings; *prgBindings = (DBBINDING*)CoTaskMemAlloc(*pcBindings * sizeof(DBBINDING)); if (*prgBindings == NULL) return E_OUTOFMEMORY; memcpy(*prgBindings, pBind->pBindings, sizeof(DBBINDING) * (*pcBindings)); hr = S_OK; } return hr; } STDMETHOD(ReleaseAccessor)(HACCESSOR hAccessor, ULONG *pcRefCount) { ATLTRACE2(atlTraceDBProvider, 0, _T("SFAccessorImpl::ReleaseAccessor\n")); BindType* pBind = m_rgBindings.Lookup((int)hAccessor); if (pBind == NULL) return DB_E_BADACCESSORHANDLE; if (pcRefCount == NULL) pcRefCount = (ULONG*)_alloca(sizeof(ULONG)); *pcRefCount = T::_ThreadModel::Decrement((LONG*)&pBind->dwRef); if (!(*pcRefCount)) { delete [] pBind->pBindings; delete pBind; return m_rgBindings.Remove((int)hAccessor) ? S_OK : DB_E_BADACCESSORHANDLE; } return S_OK; } BindingVector m_rgBindings;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -