FIX: You receive a "DAMAGE: after Normal block (#204)" debug error message when you convert a MFC DAO application to use DAO 3.6 in Visual C++ (235507)



The information in this article applies to:

  • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • Microsoft Visual C++, 32-bit Learning Edition 6.0

This article was previously published under Q235507

SYMPTOMS

When you convert a Microsoft Foundation Classes (MFC) Data Access Objects (DAO) application to use DAO 3.6, the application can produce a debug error. The exact error message is as follows:
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

With the exception of one case where the error still occurs, this problem has been fixed in DAO 3.60 version 3.60.3714.5. To obtain the updated DAO 3.60 dll, install the latest Microsoft Jet 4.0 service pack 4. For more information, click the following article number to view the article in the Microsoft Knowledge Base:

239114 How to obtain the latest service pack for the Microsoft Jet 4.0 Database Engine

Even after you apply this fix, the problem may still occur when the table you are accessing through DAO contains a text field that is defined to be only one character in length. If the field definition allows more than one character in the field, the problem should be resolved by applying the fix described above.

If your table must contain a single-character text field, you need to use the code workaround in the More Information section.

STATUS

Microsoft has confirmed that this is a problem in the Microsoft products that are listed in the "Applies to" section.

This problem was corrected in Microsoft Jet 4.0 Service Pack 4, with the one exception noted in the Resolution section of this article.

MORE INFORMATION

Steps to reproduce the 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.
    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

239114 How to obtain the latest service pack for the Microsoft Jet 4.0 Database Engine

236991 Unrecognized database format error with Access 2000 database

236056 FIX: DAO 3.6 overruns buffers in GetRowsEx method


Modification Type:MinorLast Reviewed:9/23/2005
Keywords:kbHotfixServer kbQFE kberrmsg kbQFE kbBug kbDatabase kbfix KB235507 kbAudDeveloper