KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q150789: FIX: DFX_Bool Calls Default() with AFX_RFX_LONGBINARY

Article: Q150789
Product(s): Microsoft C Compiler
Version(s): winnt:4.0,4.1; :
Operating System(s): 
Keyword(s): kbDAOsearch kbDatabase kbMFC kbVC
Last Modified: 30-JUL-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Visual C++, versions 4.0, 4.1 
- Microsoft Foundation Classes (MFC) 
-------------------------------------------------------------------------------

SYMPTOMS
========

Memory adjacent to the BOOL variable gets overwritten when working with a BOOL
CDaoRecordset field data member.

CAUSE
=====

The DFX_Bool function delegates the Fixup case to CDaoFieldExchange::Default and
incorrectly passes AFX_RFX_LONGBINARY as the field data type.

RESOLUTION
==========

To resolve this problem, copy the DFX_Bool function to the project and give it a
different name. For example, rename it DFX_Bool2. In the call to
CDaoFieldExchange::Default, change the field data type from AFX_RFX_LONGBINARY
to AFX_RFX_BOOL by using the following code:

Change this code

     case CDaoFieldExchange::Fixup:
        // Convert BOOL value from AFX_DAO_TRUE/FALSE to TRUE/FALSE
        value = (value != AFX_DAO_FALSE);

        pFX->Default(lpszName, (void*)&value,
           AFX_RFX_LONGBINARY, dwBindOptions);
        return;

to this code:

     case CDaoFieldExchange::Fixup:
        // Convert BOOL value from AFX_DAO_TRUE/FALSE to TRUE/FALSE
        value = (value != AFX_DAO_FALSE);

        pFX->Default(lpszName, (void*)&value,
           AFX_RFX_BOOL, dwBindOptions);       // <<-- Change to AFX_RFX_BOOL
        return;

Then, change the class of the CDaoRecordset-derived DoFieldExchange function to
call this new function in place of calling DFX_Bool.

STATUS
======

Microsoft has confirmed this to be a bug in the Microsoft products listed at the
beginning of this article. This bug was corrected in Visual C++ 32-bit Edition
version 4.2.

MORE INFORMATION
================

The code for the Fixup case in CDaoFieldExchange::Default is:

     case Fixup:
        if (m_prs->GetFieldLength(m_nField-1) == DAO_NULL)
        {
           // Set the value to PSEUDO NULL and mark the status NULL
           SetNullValue(pv, dwColumnType);
           m_prs->SetNullFieldStatus(m_nField-1);
        }
        return;

The dwColumn type is the variable that is incorrectly set to AFX_RFX_LONGBINARY
in DFX_Bool. Note that SetNullValue is called with the value passed in the
second parameter. The code for SetNullValue (showing relevant cases) is:

     void CDaoFieldExchange::SetNullValue(void* pv, DWORD dwDataType)
     {
        switch (dwDataType)
        {
           .
           .
           .

        case AFX_RFX_LONGBINARY:
           ((CLongBinary*)pv)->m_dwDataLength = 0;
           break;

        case AFX_RFX_BOOL:
           *(BOOL*)pv = AFX_RFX_BOOL_PSEUDO_NULL;
           break;

          .
          .
          .
      }
  }

Note that the AFX_RFX_BOOL case (the one that should be called) sets the BOOL
variable to the constant AFX_RFX_BOOL_PSEUDO_NULL. The AFX_RFX_LONGBINARY case
(incorrectly called in the MFC source) sets the m_dwDataLength member of a
CLongBinary object (at an offset in the object beyond the size of a BOOL) to
zero. Whatever is adjacent to the BOOL variable has 4 bytes of its memory
overwritten. The symptoms of this memory overwrite depend on what that variable
was used for. There can also be no symptoms.

Additional query words: kbVC400bug 4.00 4.10 4.20 vcfixlist420 MfcDAO

======================================================================
Keywords          : kbDAOsearch kbDatabase kbMFC kbVC 
Technology        : kbVCsearch kbVC400 kbAudDeveloper kbMFC kbVC410
Version           : winnt:4.0,4.1; :
Issue type        : kbbug
Solution Type     : kbfix

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.