Zweiter CDatabase-Fehler in MFC in Visual Studio 2012

 C Programming >> C-Programmierung >  >> Tags >> MFC
Zweiter CDatabase-Fehler in MFC in Visual Studio 2012

Ich habe kürzlich über einen MFC-Fehler in der CDatabase-Klasse in Visual Studio 2012 geschrieben. In der Zwischenzeit bin ich auf einen noch größeren Fehler gestoßen (siehe diesen Bericht auf Connect für die Details):wenn die OpenEx-Funktion fehlschlägt (falsche Anmeldeinformationen, Dienst nicht erreichbar , Maschine wird abgeschossen usw.) es beschädigt den Speicher. Was dann passiert, ist Zufall. Ich weiß nicht, wann ein Fix verfügbar sein wird, aber bis dahin gibt es eine Problemumgehung dafür. Genau wie beim vorherigen Fehler müssen Sie CDatabase ableiten und die OpenEx-Methode überschreiben, die ursprüngliche Implementierung aus den MFC-Quellen kopieren und eine weitere Zeile hinzufügen, um den Zeiger auf den bereits freigegebenen Speicher auf Null zu setzen. Also erweitere ich meine vorherige CDatabaseEx-Klasse auf die folgende Implementierung:

class CDatabaseEx : public CDatabase  
{  
public:  
   CString GetConnectEx()  
   {  
      CString strConnect = m_strConnect;  
  
      if (strConnect.GetLength() == 0)  
      {  
         DATA_BLOB connectBlob;  
         if (CryptUnprotectData(&m_blobConnect, NULL, NULL, NULL, NULL, 0, &connectBlob))  
         {  
            strConnect = (LPTSTR)connectBlob.pbData;  
            LocalFree(connectBlob.pbData);  
         }  
      }  
  
      return strConnect;  
   }

   virtual BOOL OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions = 0)
   {
     ENSURE_VALID(this);
     ENSURE_ARG(lpszConnectString == NULL || AfxIsValidString(lpszConnectString));
     ENSURE_ARG(!(dwOptions & noOdbcDialog && dwOptions & forceOdbcDialog));

     // Exclusive access not supported.
     ASSERT(!(dwOptions & openExclusive));

     m_bUpdatable = !(dwOptions & openReadOnly);

     TRY
     {
        m_strConnect = lpszConnectString;

        DATA_BLOB connectBlob;
        connectBlob.pbData = (BYTE *)(LPCTSTR)m_strConnect;
        connectBlob.cbData = (DWORD)(AtlStrLen(m_strConnect) + 1) * sizeof(TCHAR);
        if (CryptProtectData(&connectBlob, NULL, NULL, NULL, NULL, 0, &m_blobConnect))
        {
           SecureZeroMemory((BYTE *)(LPCTSTR)m_strConnect, m_strConnect.GetLength() * sizeof(TCHAR));
           m_strConnect.Empty();
        }

        // Allocate the HDBC and make connection
        AllocConnect(dwOptions);
        if(!Connect(dwOptions))
        {
           m_blobConnect.pbData = NULL;
           return FALSE;
        }

        // Verify support for required functionality and cache info
        VerifyConnect();
        GetConnectInfo();
     }
     CATCH_ALL(e)
     {
        // HERE IT IS, the workaround (hopefully temporary) for MFC bug with OpenEx corrupting memory
        // http://connect.microsoft.com/VisualStudio/feedback/details/760371/localfree-called-twice-in-cdatabase-mfc-11
        m_blobConnect.pbData = NULL;
        Free();
        THROW_LAST();
     }
     END_CATCH_ALL

     return TRUE;
   }
};