2025-11-28 00:35:46 +09:00

877 lines
22 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Sample Provider
// (C) Copyright 1991 - 1999 Microsoft Corporation. All Rights Reserved.
//
// @doc
//
// @module ROW.CPP | CRow object implementation
//
//
// Includes ------------------------------------------------------------------
#include "headers.h"
// Code ----------------------------------------------------------------------
// CRow::CRow ----------------------------------------------------------------
//
// @mfunc Constructor for this class
//
// @rdesc NONE
//
CRow::CRow
(
LPUNKNOWN pUnkOuter //@parm IN | Outer Unkown Pointer
) // invoke ctor for base class
: CBaseObj( BOT_ROW )
{
// Initialize simple member vars
m_cRef = 0L;
m_pUnkOuter = pUnkOuter ? pUnkOuter : this;
m_pFileio = NULL;
m_cbRowSize = 0;
m_pRowBuff = NULL;
m_pParentObj = NULL;
m_pIRow = NULL;
m_pIColumnsInfo = NULL;
m_pIConvertType = NULL;
m_pIGetSession = NULL;
m_pIRowChange = NULL;
// Fill in information about the ROW object's default stream
// This is the only extra column that Sample Provider support
m_rgExtracolinfo[DEFAULT_STREAM].wType = DBTYPE_IUNKNOWN;
m_rgExtracolinfo[DEFAULT_STREAM].ulColumnSize = sizeof(IUnknown *);
m_rgExtracolinfo[DEFAULT_STREAM].pwszName = NULL;
m_rgExtracolinfo[DEFAULT_STREAM].pTypeInfo = NULL;
m_rgExtracolinfo[DEFAULT_STREAM].iOrdinal = 0;
m_rgExtracolinfo[DEFAULT_STREAM].dwFlags = DBCOLUMNFLAGS_ISDEFAULTSTREAM;
m_rgExtracolinfo[DEFAULT_STREAM].bPrecision = ~0;
m_rgExtracolinfo[DEFAULT_STREAM].bScale = ~0;
memcpy(&m_rgExtracolinfo[DEFAULT_STREAM].columnid, &DBROWCOL_DEFAULTSTREAM,
sizeof(DBID));
m_cExtraCols = EXTRA_COLUMNS;
//Associated Row Handle
m_hRow = DB_NULL_HROW;
// Increment global object count.
OBJECT_CONSTRUCTED();
}
// CRow::~CRow ---------------------------------------------------------------
//
// @mfunc Destructor for this class
//
// @rdesc NONE
//
CRow:: ~CRow
(
void
)
{
delete [] m_pRowBuff;
SAFE_DELETE(m_pFileio);
SAFE_DELETE(m_pIRow);
SAFE_DELETE(m_pIColumnsInfo);
SAFE_DELETE(m_pIConvertType);
SAFE_DELETE(m_pIGetSession);
SAFE_DELETE(m_pIRowChange);
//Release outstanding row handle...
IRowset * pIRowset = NULL;
if( m_pParentObj &&
m_pParentObj->GetBaseObjectType() == BOT_ROWSET &&
SUCCEEDED(m_pParentObj->QueryInterface(IID_IRowset, (void**)&pIRowset)) )
{
if( pIRowset )
{
pIRowset->ReleaseRows(1, &m_hRow, NULL, NULL, NULL);
pIRowset->Release();
}
}
if( m_pParentObj )
m_pParentObj->GetOuterUnknown()->Release();
}
// CRow::FInit ---------------------------------------------------------------
//
// @mfunc Initialize the row Object when it is a part of a rowset
//
// @rdesc Did the Initialization Succeed
// @flag TRUE | Initialization succeeded
// @flag FALSE | Initialization failed
//
BOOL CRow::FInit
(
CRowset * pParentObj //@parm IN | pointer to parent rowset object
)
{
assert(pParentObj);
assert(pParentObj->m_pFileio);
assert(m_pUnkOuter);
m_pParentObj = pParentObj;
m_pParentObj->GetOuterUnknown()->AddRef();
// Allocate contained interface objects
m_pIRow = new CImpIRow( this, m_pUnkOuter );
m_pIColumnsInfo = new CImpIColumnsInfo( this, m_pUnkOuter );
m_pIConvertType = new CImpIConvertType( this, m_pUnkOuter );
m_pIGetSession = new CImpIGetSession( this, m_pUnkOuter );
m_pIRowChange = new CImpIRowChange( this, m_pUnkOuter );
m_cbRowSize = pParentObj->m_cbRowSize;
// if all interfaces were created, return success
return (BOOL) (m_pIRow && m_pIColumnsInfo && m_pIConvertType &&
m_pIGetSession && m_pIRowChange);
}
// CRow::FInit ---------------------------------------------------------------
//
// @mfunc Initialize the row Object on a direct bind
//
// @rdesc Did the Initialization Succeed
// @flag TRUE | Initialization succeeded
// @flag FALSE | Initialization failed
//
BOOL CRow::FInit
(
CDBSession * pParentObj, //@parm IN | pointer to parent session object
CFileIO * pFileIO, //@parm IN | pointer to FileIO object
DBCOUNTITEM ulRowNum //@parm IN | Row number to fetch
)
{
DBORDINAL cCols;
COLUMNDATA * pColumn = NULL;
assert(pFileIO);
assert(m_pUnkOuter);
m_pParentObj = pParentObj;
m_pParentObj->GetOuterUnknown()->AddRef();
m_pFileio = pFileIO;
// Allocate contained interface objects
m_pIRow = new CImpIRow( this, m_pUnkOuter );
m_pIColumnsInfo = new CImpIColumnsInfo( this, m_pUnkOuter );
m_pIConvertType = new CImpIConvertType( this, m_pUnkOuter );
m_pIGetSession = new CImpIGetSession( this, m_pUnkOuter );
m_pIRowChange = new CImpIRowChange( this, m_pUnkOuter );
m_cbRowSize = m_pFileio->GetRowSize();
m_pRowBuff = new BYTE [ ROUND_UP( m_pFileio->GetRowSize() + sizeof(ROWBUFF), COLUMN_ALIGNVAL ) ];
memset(m_pRowBuff, 0, ROUND_UP( m_pFileio->GetRowSize() + sizeof(ROWBUFF), COLUMN_ALIGNVAL ) );
// Set up the row buff bindings
for (cCols=1; cCols <= m_pFileio->GetColumnCnt(); cCols++)
{
pColumn = m_pFileio->GetColumnData(cCols, (ROWBUFF *)m_pRowBuff);
if (FAILED(m_pFileio->SetColumnBind(cCols, pColumn)))
return FALSE;
}
// Actually fetch the data
if( S_OK != m_pFileio->Fetch( ulRowNum ) )
return FALSE;
((ROWBUFF *)m_pRowBuff)->ulRefCount = 1;
((ROWBUFF *)m_pRowBuff)->pbBmk = /*(void *)*/ulRowNum;
// if all interfaces were created, return success
return (BOOL) (m_pIRow && m_pIColumnsInfo && m_pIConvertType &&
m_pIGetSession && m_pIRowChange && m_pFileio &&
m_pRowBuff);
}
// CRow::QueryInterface ------------------------------------------------------
//
// @mfunc Returns a pointer to a specified interface. Callers use
// QueryInterface to determine which interfaces the called object
// supports.
//
// @rdesc HRESULT indicating the status of the method
// @flag S_OK | Interface is supported and ppvObject is set.
// @flag E_NOINTERFACE | Interface is not supported by the object
// @flag E_INVALIDARG | One or more arguments are invalid.
//
STDMETHODIMP CRow::QueryInterface
(
REFIID riid,
LPVOID * ppv
)
{
if( NULL == ppv )
return E_INVALIDARG;
// Place NULL in *ppv in case of failure
*ppv = NULL;
// This is the non-delegating IUnknown implementation
if( riid == IID_IUnknown )
*ppv = (LPVOID) this;
else if( riid == IID_IRow )
*ppv = (LPVOID) m_pIRow;
else if( riid == IID_IColumnsInfo )
*ppv = (LPVOID) m_pIColumnsInfo;
else if( riid == IID_IConvertType )
*ppv = (LPVOID) m_pIConvertType;
else if( riid == IID_IGetSession )
*ppv = m_pIGetSession;
else if( riid == IID_IRowChange )
*ppv = m_pIRowChange;
// If we're going to return an interface, AddRef it first
if( *ppv )
{
((LPUNKNOWN) *ppv)->AddRef();
return ResultFromScode( S_OK );
}
else
return ResultFromScode( E_NOINTERFACE );
}
// CRow::AddRef --------------------------------------------------------------
//
// @mfunc Increments a persistence count for the object
//
// @rdesc Current reference count
//
STDMETHODIMP_( DBREFCOUNT ) CRow::AddRef
(
void
)
{
return ++m_cRef;
}
// CRow::Release -------------------------------------------------------------
//
// @mfunc Decrements a persistence count for the object and if
// persistence count is 0, the object destroys itself.
//
// @rdesc Current reference count
//
STDMETHODIMP_( DBREFCOUNT ) CRow::Release
(
void
)
{
if (!--m_cRef)
{
delete this;
return 0;
}
return m_cRef;
}
// CRow::SetRowHandle --------------------------------------------------------
//
// @mfunc Internal member function which sets the HROW which this row object
// represents
//
// @rdesc HRESULT indicating the status of the method
// @flag S_OK | method succeeded
// @flag DB_E_DELETEDROW | hrow referred to a deleted row
// @flag DB_E_BADROWHANDLE | hrow did not belong to the parent rowset
//
STDMETHODIMP CRow::SetRowHandle(HROW hRow)
{
IRowset * pIRowset = NULL;
HRESULT hr = DB_E_NOSOURCEOBJECT;
DBROWSTATUS dwRowStatus = DBROWSTATUS_S_OK;
//Obtain the parent rowset...
if( m_pParentObj )
{
hr = m_pParentObj->QueryInterface(IID_IRowset, (void**)&pIRowset);
if( pIRowset )
{
//AddRef the row,
//To be able to hang onto the row, and determine if its invalid or not...
if(FAILED(hr = pIRowset->AddRefRows(1, &hRow, NULL, &dwRowStatus)))
{
switch(dwRowStatus)
{
case DBROWSTATUS_E_DELETED:
hr = DB_E_DELETEDROW;
break;
default:
hr = DB_E_BADROWHANDLE;
break;
};
}
//We made it this far, store the row...
if( SUCCEEDED(hr) )
m_hRow = hRow;
pIRowset->Release();
}
}
return hr;
}
// CRow::GetRowBuff ----------------------------------------------------------
//
// @mfunc Returns the underlying ROWBUFF
//
ROWBUFF * CRow::GetRowBuff()
{
if( BOT_ROWSET == m_pParentObj->GetBaseObjectType() )
return ((CRowset *)m_pParentObj)->GetRowBuff( m_hRow, TRUE );
else
{
assert( BOT_SESSION == m_pParentObj->GetBaseObjectType() );
return (ROWBUFF *)m_pRowBuff;
}
}
// CRow::GetFileObj ----------------------------------------------------------
//
// @mfunc Returns the underlying Fileio object
//
CFileIO * CRow::GetFileObj()
{
if( BOT_ROWSET == m_pParentObj->GetBaseObjectType() )
return ((CRowset *)m_pParentObj)->m_pFileio;
else
{
assert( BOT_SESSION == m_pParentObj->GetBaseObjectType() );
return m_pFileio;
}
}
// CRow::GetColumnData -------------------------------------------------------
//
// @mfunc Returns TRUE if pColumnID is valid
//
BOOL CRow::GetColumnOrdinal
(
CFileIO * pFileio,
DBID * pColumnID,
DBORDINAL * pcCol
)
{
if( (pColumnID->eKind == DBKIND_GUID_PROPID) &&
(pColumnID->uGuid.guid == GUID_NULL) &&
(pColumnID->uName.ulPropid >= 1) &&
(pColumnID->uName.ulPropid <= pFileio->GetColumnCnt()) )
{
if( pcCol )
*pcCol = pColumnID->uName.ulPropid;
return TRUE;
}
else
return FALSE;
}
// CImpIRow::GetColumns ------------------------------------------------------
//
// @mfunc Gets multiple columns from the row
//
// @rdesc HRESULT
// @flag S_OK | Method Succeeded
// @flag E_INVALIDARG | rgColumns was null and cColumns != 0
// @flag DB_E_DELETEDROW | The row has been deleted
// @flag DB_S_ERRORSOCCURRED | Failure to retrieve one or more values
//
STDMETHODIMP CImpIRow::GetColumns
(
DBORDINAL cColumns,
DBCOLUMNACCESS rgColumns[]
)
{
HRESULT hr;
DBORDINAL cCols;
DBORDINAL cIter;
DBORDINAL cErrorCount;
ROWBUFF * pRowBuff = NULL;
COLUMNDATA * pColumnData = NULL;
CFileIO * pFileio = NULL;
DBCOLUMNINFO * rgdbcolumninfo = NULL;
CStream * pCStream = NULL;
//
// Asserts
//
assert( m_pObj );
// cColumns == 0 is a no-op
if( cColumns == 0 )
return S_OK;
if( !rgColumns )
return E_INVALIDARG;
// Check to see if we have a DC
if( !g_pIDataConvert )
return E_FAIL;
pFileio = m_pObj->GetFileObj();
assert( pFileio );
// Internal error for a 0 reference count on this row,
// since we depend on the slot-set stuff.
pRowBuff = m_pObj->GetRowBuff();
assert( pRowBuff->ulRefCount );
// Check for the Deleted Row
if ( pFileio->IsDeleted( (DBBKMARK) pRowBuff->pbBmk ) == S_OK )
return DB_E_DELETEDROW;
cErrorCount = 0;
rgdbcolumninfo = pFileio->GetColInfo();
for (cIter = 0; cIter < cColumns; cIter++)
{
if( IsEqualDBID(&rgColumns[cIter].columnid, &DBROWCOL_DEFAULTSTREAM) )
{
if( rgColumns[cIter].wType == DBTYPE_IUNKNOWN )
{
pCStream = new CStream(NULL);
if( pCStream && pCStream->FInit(m_pObj, pRowBuff) )
{
//Obtain the requested interface
pCStream->AddRef();
if( rgColumns[cIter].pData )
*((IUnknown **)rgColumns[cIter].pData) = (IUnknown *)pCStream;
else
pCStream->Release();
rgColumns[cIter].dwStatus = DBSTATUS_S_OK;
rgColumns[cIter].cbDataLen = sizeof(IUnknown *);
}
else
{
rgColumns[cIter].dwStatus = DBSTATUS_E_CANTCREATE;
cErrorCount++;
}
}
else
{
rgColumns[cIter].dwStatus = DBSTATUS_E_BADACCESSOR;
cErrorCount++;
}
continue;
}
if( !m_pObj->GetColumnOrdinal(pFileio, &rgColumns[cIter].columnid, &cCols) )
{
rgColumns[cIter].dwStatus = DBSTATUS_E_DOESNOTEXIST;
cErrorCount++;
continue;
}
pColumnData = pFileio->GetColumnData(cCols, pRowBuff);
hr = g_pIDataConvert->DataConvert(
rgdbcolumninfo[cCols].wType, // src Type
rgColumns[cIter].wType, // dst Type
pColumnData->uLength, // src Length
&rgColumns[cIter].cbDataLen, // dst Length
&(pColumnData->bData), // pSrc
rgColumns[cIter].pData, // pDst
rgColumns[cIter].cbMaxLen, // cbMaxLen
pColumnData->dwStatus, // src Status
&rgColumns[cIter].dwStatus, // dst Status
rgColumns[cIter].bPrecision, // bPrecision for conversion to DBNUMERIC
rgColumns[cIter].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_DEFAULT);
if (hr != S_OK)
cErrorCount++;
}
// Return S_OK if all columns retrieved with successful status
// Return DB_S_ERRORSOCCURED on failure to retrieve one or more column values
// Return DB_E_ERRORSOCCURED on failure to retrieve all column values
return cErrorCount ? ( cErrorCount < cColumns ) ?
ResultFromScode( DB_S_ERRORSOCCURRED ) :
ResultFromScode( DB_E_ERRORSOCCURRED ) :
ResultFromScode( S_OK );
}
// CImpIRow::GetSourceRowset -------------------------------------------------
//
// @mfunc Returns the rowset interface of which this row is a part
//
// @rdesc HRESULT
// @flag S_OK | Method Succeeded
// @flag E_INVALIDARG | Invalid parameters were specified
//
STDMETHODIMP CImpIRow::GetSourceRowset
(
REFIID riid,
IUnknown ** ppRowset,
HROW * phRow
)
{
HRESULT hr;
CRowset * pCRowset = NULL;
IUnknown * pSourceRowset = NULL;
ROWBUFF * pRowBuff = NULL;
//
// Asserts
//
assert(m_pObj);
assert(m_pObj->m_pParentObj);
if( !ppRowset && !phRow )
return E_INVALIDARG;
if( ppRowset )
*ppRowset = NULL;
if( phRow )
*phRow = DB_NULL_HROW;
if( BOT_SESSION == m_pObj->m_pParentObj->GetBaseObjectType() )
return DB_E_NOSOURCEOBJECT;
pCRowset = (CRowset *)m_pObj->m_pParentObj;
if( !pCRowset )
return E_FAIL;
hr = pCRowset->m_pUnkOuter->QueryInterface(riid, (LPVOID *)&pSourceRowset);
if( FAILED(hr) )
return hr;
// Check for the Deleted Row
pRowBuff = pCRowset->GetRowBuff( (DBCOUNTITEM)m_pObj->m_hRow, TRUE );
assert( pRowBuff && pRowBuff->ulRefCount );
if ( pCRowset->m_pFileio &&
pCRowset->m_pFileio->IsDeleted( (DBBKMARK) pRowBuff->pbBmk ) == S_OK )
{
pSourceRowset->Release();
return DB_E_DELETEDROW;
}
if( ppRowset )
*ppRowset = pSourceRowset;
else
pSourceRowset->Release();
if( phRow )
{
// return the HROW and add a refcout
*phRow = m_pObj->m_hRow;
pRowBuff->ulRefCount++;
pCRowset->m_ulRowRefCount++;
}
return S_OK;
}
// CImpIRow::Open ------------------------------------------------------------
//
// @mfunc Retrieves interface from an object valued column
//
// @rdesc HRESULT
// @flag S_OK | method succeeded
// @flag DB_E_OBJECTMISMATCH | Requested an object that does not match
// the object type of the column
//
STDMETHODIMP CImpIRow::Open
(
IUnknown * pUnkOuter,
DBID * pColumnID,
REFGUID rguidColumnType,
DWORD dwBindFlags,
REFIID riid,
IUnknown ** ppUnk
)
{
HRESULT hr = S_OK;
CStream * pCStream = NULL;
CFileIO * pFileio = NULL;
ROWBUFF * pRowBuff = NULL;
//
// Asserts
//
assert(m_pObj);
if( ppUnk )
*ppUnk = NULL;
if(!pColumnID )
return E_INVALIDARG;
if( pUnkOuter && riid != IID_IUnknown )
return DB_E_NOAGGREGATION;
pFileio = m_pObj->GetFileObj();
pRowBuff = m_pObj->GetRowBuff();
if( pFileio->IsDeleted( (DBBKMARK) pRowBuff->pbBmk ) == S_OK )
return DB_E_DELETEDROW;
// The only supported object valued column is the default stream object
if( rguidColumnType != DBGUID_STREAM &&
rguidColumnType != GUID_NULL )
return DB_E_OBJECTMISMATCH;
if( IsEqualDBID(pColumnID, &DBROWCOL_DEFAULTSTREAM) )
{
pCStream = new CStream(pUnkOuter);
if( pCStream && pCStream->FInit(m_pObj, pRowBuff) )
{
//Obtain the requested interface
hr = pCStream->QueryInterface(riid, (void**)ppUnk);
}
else
hr = E_OUTOFMEMORY;
}
else
{
//Either this columnid does not exist or
//this columnid is not an object valued column
if( !m_pObj->GetColumnOrdinal(pFileio, pColumnID, NULL) )
{
hr = DB_E_BADCOLUMNID;
}
else
hr = DB_E_OBJECTMISMATCH;
}
if( FAILED(hr) )
SAFE_DELETE( pCStream );
return hr;
}
// CImpIGetSession::GetSession -----------------------------------------------
//
// @mfunc Returns the session interface on which the row has been created
//
// @rdesc HRESULT
// @flag S_OK | Method Succeeded
// @flag DB_E_NOSOURCEOBJECT | There is no session object for the row
// @flag E_INVALIDARG | Invalid parameters were specified
//
STDMETHODIMP CImpIGetSession::GetSession
(
REFIID riid,
IUnknown ** ppunkSession
)
{
CRowset * pCRowset = NULL;
CBaseObj * pCRowsetParent = NULL;
CDBSession * pCSession = NULL;
//
// Asserts
//
assert(m_pObj);
assert(m_pObj->m_pParentObj);
if( NULL == ppunkSession )
return (E_INVALIDARG);
*ppunkSession = NULL;
if( BOT_SESSION == m_pObj->m_pParentObj->GetBaseObjectType() )
{
pCSession = (CDBSession *)m_pObj->m_pParentObj;
}
else
{
assert( BOT_ROWSET == m_pObj->m_pParentObj->GetBaseObjectType() );
pCRowset = (CRowset *)m_pObj->m_pParentObj;
if( !pCRowset )
return E_FAIL;
pCRowsetParent = pCRowset->m_pParentObj;
if( !pCRowsetParent )
return E_FAIL;
if( BOT_SESSION == pCRowsetParent->GetBaseObjectType() )
pCSession = (CDBSession *)pCRowsetParent;
else if( BOT_COMMAND == pCRowsetParent->GetBaseObjectType() )
pCSession = ((CCommand *)pCRowsetParent)->m_pCSession;
else
return E_FAIL;
}
if( pCSession )
return pCSession->GetOuterUnknown()->QueryInterface(riid, (LPVOID*)ppunkSession);
else
return DB_E_NOSOURCEOBJECT;
}
// CImpIRowChange::SetColumns ------------------------------------------------
//
// @mfunc Sets multiple column values on a row
//
// @rdesc HRESULT
// @flag S_OK | Method Succeeded
// @flag E_INVALIDARG | rgColumns was null and cColumns != 0
// @flag DB_E_DELETEDROW | The row has been deleted or moved
// @flag DB_E_ERRORSOCCURRED | No columns set
// @flag DB_E_DELETEDROW | The row has been deleted
//
STDMETHODIMP CImpIRowChange::SetColumns
(
DBORDINAL cColumns,
DBCOLUMNACCESS rgColumns[]
)
{
HRESULT hr;
DBORDINAL cIter = 0;
DBORDINAL cErrorCount = 0;
DBORDINAL cCols = 0;
DWORD dwSrcStatus;
ROWBUFF * pRowBuff = NULL;
COLUMNDATA * pColumnData = NULL;
BYTE * rgbRowDataSave = NULL;
DBCOLUMNINFO * rgdbcolumninfo = NULL;
CFileIO * pFileio = NULL;
//
// Asserts
//
assert( m_pObj );
assert( m_pObj->m_pParentObj );
// cColumns == 0 is a no-op
if( cColumns == 0 )
return S_OK;
if( !rgColumns )
return E_INVALIDARG;
// Check to see if we have a DC
if( !g_pIDataConvert )
return E_FAIL;
pFileio = m_pObj->GetFileObj();
pRowBuff = m_pObj->GetRowBuff();
// Is row handle deleted?
if ( pFileio->IsDeleted((DBBKMARK) ((PROWBUFF) pRowBuff)->pbBmk ) == S_OK )
return DB_E_DELETEDROW;
rgbRowDataSave = new BYTE[m_pObj->m_cbRowSize];
if ( rgbRowDataSave == NULL )
return E_OUTOFMEMORY;
// Save the row.
memcpy( rgbRowDataSave, pRowBuff, m_pObj->m_cbRowSize );
rgdbcolumninfo = pFileio->GetColInfo();
for (cIter = 0; cIter < cColumns; cIter++)
{
// Check the Status for DBSTATUS_S_IGNORE
dwSrcStatus = rgColumns[cIter].dwStatus;
if( dwSrcStatus == DBSTATUS_S_IGNORE )
continue;
if( IsEqualDBID(&rgColumns[cIter].columnid, &DBROWCOL_DEFAULTSTREAM) )
{
// Default stream column is read only
rgColumns[cIter].dwStatus = DBSTATUS_E_PERMISSIONDENIED;
cErrorCount++;
continue;
}
else
{
if( !m_pObj->GetColumnOrdinal(pFileio, &rgColumns[cIter].columnid, &cCols) )
{
rgColumns[cIter].dwStatus = DBSTATUS_E_DOESNOTEXIST;
cErrorCount++;
continue;
}
}
pColumnData = pFileio->GetColumnData(cCols, pRowBuff);
// Check the Status for DBSTATUS_S_DEFAULT
if( dwSrcStatus == DBSTATUS_S_DEFAULT )
dwSrcStatus = DBSTATUS_S_ISNULL;
// Check the Status of the value being sent in
if( (dwSrcStatus != DBSTATUS_S_OK && dwSrcStatus != DBSTATUS_S_ISNULL &&
dwSrcStatus != DBSTATUS_S_IGNORE && dwSrcStatus != DBSTATUS_S_DEFAULT) )
{
rgColumns[cIter].dwStatus = DBSTATUS_E_BADSTATUS;
cErrorCount++;
continue;
}
hr = g_pIDataConvert->DataConvert(
rgColumns[cIter].wType, // src Type
rgdbcolumninfo[cCols].wType, // dst Type
rgColumns[cIter].cbDataLen, // src Length
&(pColumnData->uLength), // dst Length
rgColumns[cIter].pData, // pSrc
&(pColumnData->bData), // pDst
rgColumns[cIter].cbMaxLen, // cbMaxLen
dwSrcStatus, // src Status
&(pColumnData->dwStatus), // dst Status
rgColumns[cIter].bPrecision, // bPrecision for conversion to DBNUMERIC
rgColumns[cIter].bScale, // bScale for conversion to DBNUMERIC
DBDATACONVERT_SETDATABEHAVIOR);
// fatal error
if( FAILED(hr) )
{
cErrorCount++;
rgColumns[cIter].dwStatus = pColumnData->dwStatus;
continue;
}
}
// Carry out the update.
if( FAILED( pFileio->UpdateRow((DBBKMARK) ((PROWBUFF) pRowBuff)->pbBmk, (BYTE *)pRowBuff, UPDATE )) )
{
// Restore the row to its previous state
memcpy( pRowBuff, rgbRowDataSave, m_pObj->m_cbRowSize );
return ResultFromScode( E_FAIL );
}
delete [] rgbRowDataSave;
// Return S_OK if all columns were updated
// Return DB_S_ERRORSOCCURED one or more columns failed to be updated
// Return DB_E_ERRORSOCCURED on failure to set all columns
return cErrorCount ? ( cErrorCount < cColumns ) ?
ResultFromScode( DB_S_ERRORSOCCURRED ) :
ResultFromScode( DB_E_ERRORSOCCURRED ) :
ResultFromScode( S_OK );
}