#include "stdafx.h" #include "AutoLoadDll.h" #define NOT_WORDY CAutoLoadDll::~CAutoLoadDll() { FreeDll(); } bool CAutoLoadDll::LoadDll() { if (m_hDll) { return IsOk(); } m_bSomeFunctionsFailed = false; m_hDll = ::LoadLibrary(m_strDllName); if (m_hDll <= (HINSTANCE) 32) { LoadLibraryError(); m_hDll = NULL; } else { InitFunctions(); #ifdef _MFC_VER TRACE("Loaded ´%s´\n", m_strDllName); #endif } return IsOk(); } void CAutoLoadDll:

rocFuncError(LPCSTR strFuncName) { #ifdef _MFC_VER TRACE("Unable to load function %s in library %s", strFuncName, m_strDllName); ASSERT(0); #else strFuncName; #ifdef _DEBUG assert(0); #endif #endif } void CAutoLoadDll::LoadLibraryError() { #ifdef _MFC_VER TRACE("LoadLibrary(%s) failed\n", m_strDllName); #else #ifdef _DEBUG assert(0); #endif #endif } void CAutoLoadDll::InitFunctions() { m_bSomeFunctionsFailed = true; typedef void (FAR PASCAL* pFuncType)(); pFuncType* pFuncPtr; // This will be our pointer to the function pointers // TmpPtr now points to the the first function pointer in our DERIVED class! // For this to work m_hDll must be the last variable defined in this class char* pTmpPtr = (char*)&m_hDll + sizeof(m_hDll); pFuncPtr = (pFuncType*)pTmpPtr; pFuncPtr++; // Skip guard long const char** pStr = m_pstrFunNames; while (pStr && *pStr) { // This can corrupt memory if you have too many strings and not enough // function pointers! *pFuncPtr = (pFuncType)::GetProcAddress(m_hDll, *pStr); if (NULL == *pFuncPtr) { // Try a variant TCHAR strNewAttempt[_MAX_PATH]; strncpy(strNewAttempt, *pStr, _MAX_PATH - 2); #ifdef UNICODE strcat(strNewAttempt, "W"); // Add the "W" to the end of the string #else strcat(strNewAttempt, "A"); // Add the "A" to the end of the string #endif *pFuncPtr = (pFuncType)::GetProcAddress(m_hDll, strNewAttempt); // Give up if NULL if (NULL == *pFuncPtr) { m_bSomeFunctionsFailed = true; ProcFuncError(*pStr); } } // Next! ++pFuncPtr; ++pStr; } #ifdef _MFC_VER ASSERT(1234 == *(long*)pTmpPtr); // Check first guard bit ASSERT(4321 == *(long*)pFuncPtr); // Check end guard bit #else #ifdef _DEBUG assert(1234 == *(long*)pTmpPtr); // Check first guard bit assert(4321 == *(long*)pFuncPtr); // Check end guard bit #endif #endif } void CAutoLoadDll::FunctionException(LPCSTR strFuncName) { #ifdef _MFC_VER TRACE("Function %s failed with fatal exception\n", strFuncName); ASSERT(0); #else strFuncName; #ifdef _DEBUG assert(0); #endif #endif } void CAutoLoadDll::FreeDll() { if (m_hDll) { ::FreeLibrary(m_hDll); } m_hDll = NULL; } #ifndef NOT_WORDY //////////////////////////////////////////////////////////////////////////////// void CWordyAutoLoadDll:

rocFuncError(LPCSTR strFuncName) { CString strMess; strMess.FormatMessage(IDS_UNABLE_TO_LOAD_FUNCTION, strFuncName, m_strDllName); AfxMessageBox(strMess); } void CWordyAutoLoadDll::LoadLibraryError() { CString strMess; strMess.FormatMessage(IDS_UNABLE_TO_LOAD_DLL, m_strDllName); AfxMessageBox(strMess); } void CWordyAutoLoadDll::FunctionException(LPCSTR strFuncName) { CString strMess; strMess.FormatMessage(IDS_FATAL_EXCEPTION_IN_FUNC, strFuncName); AfxMessageBox(strMess); } #endif