Article ID: 179671
Article Last Modified on 10/2/2003
value.GetBufferSetLength( pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] - 1);Also, at line 1391 in the Daodfx.cpp file within the DAOStringAllocCallback() function [used as a callback function by DFX_Text()], the length of the CString is set to the number of bytes rather than the number of characters returned from the database:
pstr->ReleaseBuffer(dwLen);
pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] - 1);Fixed version:
(pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] / sizeof(TCHAR)) [ASCII 150]
sizeof(TCHAR));
lpsz = pstr->GetBuffer(dwLen);Fixed version:
lpsz = pstr->GetBuffer(dwLen / sizeof(TCHAR));
////////////////////////////////////////////////
STDAPI DaoStringAllocCallback2(DWORD dwLen, DWORD pData, void** ppv);
STDAPI DaoStringAllocCallback2(DWORD dwLen, DWORD pData, void** ppv)
{
LPTSTR lpsz;
CString* pstr = (CString*)pData;
#ifndef _UNICODE
// If using ANSI DAO interfaces, DAO reports field length
// rather than data length. In this case there will not be space
// for NULL terminator if data length equals field length. Make room.
dwLen++;
#endif
TRY
{
// Only re-allocate if necessary
lpsz = pstr->GetBuffer(dwLen / sizeof(TCHAR));
pstr->ReleaseBuffer(dwLen);
*ppv = (void*)(dwLen > 0 ? lpsz : NULL);
}
CATCH_ALL(e)
{
e->Delete();
return E_OUTOFMEMORY;
}
END_CATCH_ALL
return S_OK;
}
void AFXAPI DFX_Text2(CDaoFieldExchange* pFX, LPCTSTR lpszName,
CString& value, int nPreAllocSize = AFX_DAO_TEXT_DEFAULT_SIZE,
DWORD dwBindOptions = AFX_DAO_ENABLE_FIELD_CACHE);
void AFXAPI DFX_Text2(CDaoFieldExchange* pFX, LPCTSTR lpszName,
CString& value, int nPreAllocSize, DWORD dwBindOptions)
{
(pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
++pFX->m_nField: ++pFX->m_nParam;
// Do nothing if op not supported for outputColumn or param type
if (!pFX->IsValidOperation())
return;
DWORD dwDAOType;
#ifdef _UNICODE
dwDAOType = DAO_WCHAR;
#else
dwDAOType = DAO_CHAR;
#endif
switch (pFX->m_nOperation)
{
case CDaoFieldExchange::BindField:
{
// Pre-allocate buffer to prevent needless re-allocations
value.GetBuffer(nPreAllocSize);
value.ReleaseBuffer();
LPDAOCOLUMNBINDING pcb =
&pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
pcb->dwDataType = dwDAOType;
pcb->dwBinding = DAOBINDING_DIRECT | DAOBINDING_CALLBACK;
pcb->dwUser = (DWORD)&value;
pcb->cbDataOffset = (DWORD)DaoStringAllocCallback2;
pcb->cbMaxLen = INT_MAX;
}
// Fall through to finish setting up column binding struct
default:
pFX->Default(lpszName, (void*)&value, AFX_RFX_TEXT,
dwBindOptions);
return;
case CDaoFieldExchange::Fixup:
if (pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] == 0 ||
pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] == DAO_NULL)
{
// If null or empty string set length zero
value.GetBufferSetLength(0);
}
else
{
// Make sure length correct (and doesn't include NULL
//terminator)
value.GetBufferSetLength(
(pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] /
sizeof(TCHAR))- sizeof(TCHAR));
}
pFX->Default(lpszName, (void*)&value,
AFX_RFX_TEXT, dwBindOptions);
return;
#ifdef _DEBUG
case CDaoFieldExchange::DumpField:
*pFX->m_pdcDump << "\n" << lpszName << " = " << value;
return;
#endif //_DEBUG
}
}
//////////////////////////////////////////////
Below is an example of how to use the DFX_Text2 function in your project:
void CDaoSet::DoFieldExchange(CDaoFieldExchange* pFX)
{
#ifdef _UNICODE
//{{AFX_FIELD_MAP(CDaoSet)
pFX->SetFieldType(CDaoFieldExchange::outputColumn);
DFX_Short(pFX, _T("[Hours]"), m_Hours);
//}}AFX_FIELD_MAP
DFX_Text2(pFX, _T("[CourseID]"), m_CourseID);
DFX_Text2(pFX, _T("[CourseTitle]"), m_CourseTitle);
#else
//{{AFX_FIELD_MAP(CDaoSet)
pFX->SetFieldType(CDaoFieldExchange::outputColumn);
DFX_Text(pFX, _T("[CourseID]"), m_CourseID);
DFX_Text(pFX, _T("[CourseTitle]"), m_CourseTitle);
DFX_Short(pFX, _T("[Hours]"), m_Hours);
//}}AFX_FIELD_MAP
#endif
}
Additional query words: MFCDAO MFCDatabase kbDAO kbMFC kbVC600fix kbVC500bug kbdse kbDSupport
Keywords: kbbug kbfix KB179671