///////////////////////////////////////////////////////////////// // HRESULT CRow::SetupColAccess // ///////////////////////////////////////////////////////////////// HRESULT CRow::SetupColAccess(BINDCOLS eBindCols) { HRESULT hr = S_OK; DBLENGTH dwOffset = 0; ULONG i; //Only capable of the Following Converions (for Display) DWORD dwMaxLength = GetOptions()->m_dwMaxLength; DWORD dwAccessorOpts = GetOptions()->m_dwAccessorOpts; if(m_pIColumnsInfo == NULL) return E_FAIL; //GetColumnInfo GetColInfo(); //Alloc the space to hold the ColumnAccess structs ULONG cBindings = 0; DBBINDING* rgBindings = NULL; SAFE_ALLOC(m_rgColAccess, DBCOLUMNACCESS, m_ColumnInfo.GetCount()); SAFE_ALLOC(rgBindings, DBBINDING, m_ColumnInfo.GetCount()); //Figure out how big to make the buffer... for(i=0; i<m_ColumnInfo.GetCount(); i++) { //Offset m_rgColAccess[i].cbMaxLen = GetMaxDisplaySize(GetOptions()->GetBindingType(m_ColumnInfo[i].wType), m_ColumnInfo[i].wType, m_ColumnInfo[i].ulColumnSize, dwMaxLength); dwOffset = ROUNDUP( dwOffset + m_rgColAccess[i].cbMaxLen ); } //Size for pData SAFE_REALLOC(m_pData, BYTE, dwOffset); dwOffset = 0; m_cColAccess = 0; cBindings = 0; for(i=0; i<m_ColumnInfo.GetCount(); i++) { DBCOLUMNINFO* pColInfo = &m_ColumnInfo[i]; DBCOLUMNACCESS* pColAccess = &m_rgColAccess[m_cColAccess]; DBBINDING* pBinding = &rgBindings[cBindings]; //Setup the Bindings pColAccess->columnid = pColInfo->columnid; pColAccess->bPrecision = pColInfo->bPrecision; pColAccess->bScale = pColInfo->bScale; pColAccess->wType = GetOptions()->GetBindingType(pColInfo->wType); pColAccess->cbDataLen = 0; //NOTE: This is setup above in the Previous for loop... pColAccess->cbMaxLen = m_rgColAccess[i].cbMaxLen; //BLOB or IUnknown Bindings if(pColAccess->wType == DBTYPE_IUNKNOWN || pColInfo->wType == DBTYPE_IUNKNOWN || (pColInfo->dwFlags & DBCOLUMNFLAGS_ISLONG && (dwAccessorOpts & (ACCESSOR_BLOB_ISEQSTREAM|ACCESSOR_BLOB_ILOCKBYTES|ACCESSOR_BLOB_ISTORAGE|ACCESSOR_BLOB_ISTREAM)))) { pColAccess->wType = DBTYPE_IUNKNOWN; pColAccess->cbMaxLen = sizeof(IUnknown*); } //If the consumer requested not to bind the Value in Options, then set pData = NULL //This is how the 2.5 spec says to indicate VALUE is not bound (since their is no dwPart). pColAccess->pData = NULL; if(dwAccessorOpts & ACCESSOR_BIND_VALUE) pColAccess->pData = (BYTE*)m_pData + dwOffset; //Initialize the Status to an error, so we don't end up freeing outofline //data we haven't retreived yet... pColAccess->dwStatus = DBSTATUS_E_UNAVAILABLE; //Special Handling for other non-OLE DB defined convertable types to WSTR //NOTE: The spec requires all supported types to be converted to //WSTR, but this only applies where the OLE DB conversion is defined. //Some are not defined so we need to bind nativly. switch(pColInfo->wType) { case DBTYPE_IUNKNOWN: case DBTYPE_IDISPATCH: pColAccess->wType = pColInfo->wType; pColAccess->cbMaxLen = sizeof(IUnknown*); break; case DBTYPE_HCHAPTER: pColAccess->wType = pColInfo->wType; pColAccess->cbMaxLen = sizeof(HCHAPTER); break; default: //DBTYPE_VECTOR if(pColInfo->wType & DBTYPE_VECTOR) { pColAccess->wType = pColInfo->wType; pColAccess->cbMaxLen= sizeof(DBVECTOR); } //DBTYPE_ARRAY if(pColInfo->wType & DBTYPE_ARRAY) { pColAccess->wType = pColInfo->wType; pColAccess->cbMaxLen= sizeof(SAFEARRAY*); } break; }; //Offset dwOffset += pColAccess->cbMaxLen; dwOffset = ROUNDUP( dwOffset ); //Build a real simple binding on top of this ColumnAccess struct. //The reason is all of our data manipulations routines deal with binding structs, so instead //have having numerous code lines, we will just map this to a binding struct... pBinding->iOrdinal = pColInfo->iOrdinal; pBinding->obStatus = (DBBYTEOFFSET)((BYTE*)&pColAccess->dwStatus - (BYTE*)m_pData); pBinding->obLength = (DBBYTEOFFSET)((BYTE*)&pColAccess->cbDataLen - (BYTE*)m_pData); pBinding->obValue = (DBBYTEOFFSET)((BYTE*)pColAccess->pData - (BYTE*)m_pData); pBinding->pTypeInfo = NULL; pBinding->pObject = NULL; pBinding->pBindExt = NULL; pBinding->dwPart = DBPART_LENGTH|DBPART_STATUS; if(pColAccess->pData) pBinding->dwPart |= DBPART_VALUE; pBinding->dwMemOwner = (dwAccessorOpts & ACCESSOR_OWNED_PROVIDER) ? DBMEMOWNER_PROVIDEROWNED : DBMEMOWNER_CLIENTOWNED; pBinding->eParamIO = DBPARAMIO_NOTPARAM; pBinding->cbMaxLen = pColAccess->cbMaxLen; pBinding->dwFlags = 0; pBinding->wType = pColAccess->wType; pBinding->bPrecision = pColAccess->bPrecision; pBinding->bScale = pColAccess->bScale; //Do we real want this column? switch(eBindCols) { case BIND_ALLCOLS: m_cColAccess++; cBindings++; break; case BIND_ALLCOLSEXPECTBOOKMARK: if(pColInfo->iOrdinal != 0) { m_cColAccess++; cBindings++; } break; case BIND_UPDATEABLECOLS: if(pColInfo->dwFlags & DBCOLUMNFLAGS_WRITE || pColInfo->dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN) { m_cColAccess++; cBindings++; } break; default: ASSERT(!"Unhandled Type!"); break; } } CLEANUP: m_Bindings.Attach(cBindings, rgBindings); return hr; }
/** Get maximum display size. @return Display size. */ virtual std::size_t GetMaxDisplaySize() { return GetMaxDisplaySize(GetServerType()); }