// CImpIColumnsInfo::GetColumnInfo ------------------------------------------- // // @mfunc Returns the column metadata needed by most consumers. // // @rdesc HRESULT // @flag S_OK | The method succeeded // @flag E_OUTOFMEMORY | Out of memory // @flag E_INVALIDARG | pcColumns or prginfo or ppStringsbuffer was NULL // STDMETHODIMP CImpIColumnsInfo::GetColumnInfo ( DBORDINAL* pcColumns, //@parm OUT | Number of columns in rowset DBCOLUMNINFO** prgInfo, //@parm OUT | Array of DBCOLUMNINFO Structures WCHAR** ppStringsBuffer //@parm OUT | Storage for all string values ) { HRESULT hr = S_OK; DBORDINAL cCols = 0; DBORDINAL cExtraCols = 0; DBORDINAL cbHeapUsed = 0; DBORDINAL cIter = 0; BYTE * pbHeap = NULL; WCHAR * pwstrBuffer = NULL; DBCOLUMNINFO * rgdbcolinfo = NULL; DBCOLUMNINFO * rgdbInternalcolinfo = NULL; DBCOLUMNINFO * rgdbExtracolinfo = NULL; CRowset * pCRowset = NULL; CFileIO * pFileio = NULL; // // Asserts // assert(m_pObj); // // Check in-params and NULL out-params in case of error // if( pcColumns ) *pcColumns = 0; if( prgInfo ) *prgInfo = NULL; if( ppStringsBuffer ) *ppStringsBuffer = NULL; if( !pcColumns || !prgInfo || !ppStringsBuffer ) return E_INVALIDARG; // // Get the Column Information off of the Command or Rowset // if( m_pObj->GetBaseObjectType() == BOT_COMMAND ) { // // Asserts // assert(((CCommand *) m_pObj)->m_pCSession); assert(((CCommand *) m_pObj)->m_pCSession->m_pCDataSource); // // Check that a command has been set // if( !((CCommand *) m_pObj)->IsCommandSet() ) return DB_E_NOCOMMAND; // // Try to open the file... // hr = ((CCommand *) m_pObj)->m_pCSession->m_pCDataSource->OpenFile( ((CCommand *) m_pObj)->GetCommandText(), &pFileio); if( FAILED(hr) ) return hr; } else { if( m_pObj->GetBaseObjectType() == BOT_ROWSET ) pFileio = ((CRowset *) m_pObj)->GetFileObj(); else { pFileio = ((CRow *) m_pObj)->GetFileObj(); cExtraCols = ((CRow *) m_pObj)->GetExtraColCount(); rgdbExtracolinfo = ((CRow *) m_pObj)->GetExtraColumnInfo(); } } // // Get the column count and delete unneeded info // cCols = pFileio->GetColumnCnt(); pbHeap = pFileio->GetColNameHeap(); cbHeapUsed = pFileio->GetColNameHeapSize(); rgdbInternalcolinfo = pFileio->GetColInfo(); // // Return the column information // SAFE_ALLOC(rgdbcolinfo, DBCOLUMNINFO, (cCols + cExtraCols) * sizeof(DBCOLUMNINFO)); SAFE_ALLOC(pwstrBuffer, WCHAR, cbHeapUsed); memcpy(rgdbcolinfo, &(rgdbInternalcolinfo[1]), cCols*sizeof(DBCOLUMNINFO)); memcpy(rgdbcolinfo+cCols, rgdbExtracolinfo, cExtraCols*sizeof(DBCOLUMNINFO)); // // Need to fix up column ordinals for extra columns // for (cIter=cCols; cIter < cCols+cExtraCols; cIter++) rgdbcolinfo[cIter].iOrdinal = cIter+1; // // Copy the heap for column names. // if( cbHeapUsed ) { ptrdiff_t dp; memcpy(pwstrBuffer, pbHeap, cbHeapUsed); dp = (DBBYTEOFFSET)pwstrBuffer - (DBBYTEOFFSET)(pbHeap); dp >>= 1; // Loop through columns and adjust pointers to column names. for (ULONG icol=0; icol < cCols; icol++) { if( rgdbcolinfo[icol].pwszName ) rgdbcolinfo[icol].pwszName += dp; } } // // Assign in the values // *pcColumns = cCols + cExtraCols; *prgInfo = rgdbcolinfo; *ppStringsBuffer = pwstrBuffer; CLEANUP: // // Cleanup the File Information // if( m_pObj->GetBaseObjectType() == BOT_COMMAND ) SAFE_DELETE(pFileio); if( FAILED(hr) ) { SAFE_DELETE(rgdbcolinfo); SAFE_DELETE(pwstrBuffer); } return hr; }