BUG: DAO 3.6 Causes Debug Errors in MFC DAO Non-Unicode Builds

ID: Q235507


The information in this article applies to:


SYMPTOMS

When converting an MFC DAO application to use DAO 3.6 as described in the Knowledge Base article Q216152 PRB: Unrecognized Database Format Error with Access 2000 Database, the application can produce a debug error. This is the exact error message:

DAMAGE: after Normal block (#204) at <hex address>


CAUSE

DAO 3.6 incorrectly overwrites the character buffer supplied to it by MFC when it fetches text data. It first copies the Unicode string into the buffer that is twice as long as the length of the buffer and then converts the string to an Ansi string.


RESOLUTION

MFC defines a function called DaoStringAllocCallback in Daodfx.cpp. This function reallocates the internal CString buffer to the size necessary to hold the data and passes the buffer back to DAO. DAO then fills the buffer with the data. It is possible to define a different callback function that allocates twice the necessary bytes and changes the cbDataOffset member of the DAO binding structure to point to this function. See the More Information section below for details.


STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.


MORE INFORMATION

Steps to Reproduce Behavior

  1. Create a new MFC application with database support using DAO and pointing to the Northwind.mdb sample database. Use the Employees table to base your recordset class.

    1. Select Multiple Documents if necessary on step one.


    2. Select Database View without file support on step two.


    3. Click Data Source.


    4. In the Database Options dialog box select DAO and specify the Northwind.mdb file in the corresponding edit box. Click OK on the Database Options dialog.


    5. Select the Employees table from the list and click OK in the Select Database Tables dialog box.


    6. Click Finish on step two of the wizard to accept default options and finish creating your project.




  2. Insert the following line as the first line in your application's InitInstance() method. This will load DAO 3.6 instead of DAO 3.5 as described in Knowledge Base article Q216152.
    
    AfxGetModuleState()->m_dwVersion = 0x0601; 


  3. Build your application in the Win32 Debug configuration.


  4. Run your application.


  5. Click Move Next a few times. You will get a debug error similar to the one described above.


Workaround

  1. Declare your own callback function in your application header file. It should be in the same file where your application class is declared.
    
    STDAPI MyDaoStringAllocCallback(DWORD dwLen, DWORD pData, void** ppv); 


  2. Define the function in the implementation file where your application class is defined. This function is very similar to the function that MFC defines except it reallocates the CString internal buffer to twice the size that is needed.
    
    STDAPI MyDaoStringAllocCallback(DWORD dwLen, DWORD pData, void** ppv)
    {
    	LPTSTR lpsz;
    	CString* pstr = (CString*)pData;
    
    	dwLen++;
    
    	TRY
    	{
    		//Allocate twice the space needed so that DAO does not overwrite the buffer
    		lpsz = pstr->GetBufferSetLength(2*dwLen/sizeof(TCHAR));
    		*ppv = (void*)(dwLen > 0 ? lpsz : NULL);
    	}
    	CATCH_ALL(e)
    	{
    		e->Delete();
    		return E_OUTOFMEMORY;
    	}
    	END_CATCH_ALL
    
    	return S_OK;
    } 
     


  3. In your DoFieldExchange function for your recordset class, add the code below. This modifies the DAO binding structure for each field that is a text field so that the callback function is called instead of the MFC function. Insert the code after the calls to the RFX functions.
    
    if (pFX->m_nOperation == CDaoFieldExchange::BindField)
    {
    	for (int i=0;i<this->m_nFields;i++)
    	{
    		LPDAOCOLUMNBINDING pcb = &m_prgDaoColBindInfo[i];
    		if (pcb->dwDataType == DAO_CHAR)
    		{
    			pcb->cbDataOffset = (DWORD)MyDaoStringAllocCallback;
    		}			
    	}
    }
     


  4. Compile your application.


  5. Run the application.


  6. Moving through the recordset does not produce errors.



REFERENCES

Q216152 PRB: Unrecognized Database Format Error with Access 2000
Q236056 PRB: DAO 3.6 Overruns buffers in GetRowsEx method

Additional query words: DAO AppWizard MFC MoveNext


Keywords          : kbDatabase kbMFC kbVC600 kbGrpVCDB kbDAO360 kbDAO360bug 
Version           : winnt:6.0
Platform          : winnt 
Issue type        : kbbug 

Last Reviewed: July 13, 1999