CDatabase-Fehler in MFC in VS2012

 C Programming >> C-Programmierung >  >> Tags >> MFC
CDatabase-Fehler in MFC in VS2012

Nach der Migration einer MFC-Anwendung von Visual Studio 2008 zu Visual Studio 2012 tritt ein unerwarteter Fehler auf:Die Anwendung hatte Probleme beim Abrufen von Daten aus der SQL Server-Datenbank. Nach dem Debuggen stellte sich heraus, dass die Funktion CDatabase::GetConnect, die ich zum Abrufen der Verbindungszeichenfolge nach dem Öffnen der Datenbank (für verschiedene Zwecke) verwendete, plötzlich eine leere Zeichenfolge zurückgab. Es stellte sich heraus, dass dies ein bekannter MFC-Fehler war, der auf Microsoft Connect gemeldet wurde. Die Ursache des Problems liegt darin, dass CDatabase die Verbindungszeichenfolge verschlüsselt und sie dann leert. Hier ist ein Ausschnitt von OpenEx:

BOOL CDatabase::OpenEx(LPCTSTR lpszConnectString, DWORD dwOptions)
{
	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();
		}

Obwohl Microsoft versprochen hatte, den Fehler in der nächsten Hauptversion zu beheben, brauchte ich jetzt einen Fix. Also hier ist meine Lösung.

CDatabase hat ein geschütztes Mitglied m_strConnect, das die Verbindungszeichenfolge im Klartext halten soll, und eines namens m_blobConnect, das die verschlüsselte Verbindungszeichenfolge darstellt. Es gibt jedoch keine Methode in CDatabase, um dieses Blob zurückzugeben. Wenn Sie den Blob erhalten, können Sie ihn entschlüsseln und die tatsächliche Verbindungszeichenfolge abrufen. Die Lösung besteht also darin, CDatabase abzuleiten, eine Methode bereitzustellen, um die Verbindungszeichenfolge zurückzugeben, und in Ihrem Code CDatabase durch diese abgeleitete Klasse und den Aufruf von GetConnect() für diese neue Methode zu ersetzen.

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;
   }
};