//================================================================= // // DllWrapperBase.cpp // // Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved // //================================================================= #include "precomp.h" #include #include "DllWrapperBase.h" #include <..\..\framework\provexpt\include\provexpt.h> /****************************************************************************** * Constructor ******************************************************************************/ CDllWrapperBase::CDllWrapperBase(LPCTSTR a_tstrWrappedDllName) : m_tstrWrappedDllName(a_tstrWrappedDllName), m_hDll(NULL) { } /****************************************************************************** * Destructor ******************************************************************************/ CDllWrapperBase::~CDllWrapperBase() { if(m_hDll != NULL) { FreeLibrary(m_hDll); } } /****************************************************************************** * Initialization function to load the dll, obtain function addresses, and * check that we obtained function addresses. * Init should fail only if the minimum set of functions was not available; * functions added in later versions may or may not be present - it is the * client's responsibility in such cases to check, in their code, for the * version of the dll before trying to call such functions. Not doing so * when the function is not present will result in an AV. ******************************************************************************/ // bool CDllWrapperBase::Init() // << PURE VIRTUAL FUNCTION -> DERIVED CLASSES MUST OVERLOAD. /****************************************************************************** * Helper for loading the dll that hides the implementation. Returns true * if we succeeded in obtaining a handle to the dll. ******************************************************************************/ bool CDllWrapperBase::LoadLibrary() { bool t_fRet = false; if(m_hDll != NULL) { FreeLibrary(m_hDll); } if((m_hDll = ::LoadLibrary(m_tstrWrappedDllName)) != NULL) { t_fRet = true; } else { // this is possible to be neccessary in the future !!! // resource manager may start to care about error from load library // // let resource manager know load failed // m_bValid = FALSE; m_dwCreationError = ::GetLastError (); LogErrorMessage2(L"Failed to load library: %s", m_tstrWrappedDllName); } return t_fRet; } /****************************************************************************** * Helper for getting proc addresses that hides the implementation. ******************************************************************************/ FARPROC CDllWrapperBase::GetProcAddress(LPCSTR a_strProcName) { FARPROC t_fpProc = NULL; if(m_hDll != NULL) { t_fpProc = ::GetProcAddress(m_hDll, a_strProcName); } return t_fpProc; } /****************************************************************************** * Helper for retrieving the version of the dll wrapped by this class. ******************************************************************************/ BOOL CDllWrapperBase::GetDllVersion(CHString& a_chstrVersion) { return (GetVarFromVersionInfo( m_tstrWrappedDllName, // Name of file to get ver info about _T("ProductVersion"), // String identifying resource of interest a_chstrVersion)); // Buffer to hold version string } /****************************************************************************** * Member functions wrapping Kernel32 api functions. Add new functions here * as required. ******************************************************************************/ // << Section empty in base class only. >> /****************************************************************************** * Private parts. ******************************************************************************/ BOOL CDllWrapperBase::GetVarFromVersionInfo ( LPCTSTR a_szFile, LPCTSTR a_szVar, CHString &a_strValue ) { BOOL t_fRc = FALSE; DWORD t_dwTemp; DWORD t_dwBlockSize = 0L; LPVOID t_pInfo = NULL; // Use of delay loaded function requires exception handler. SetStructuredExceptionHandler seh; try { t_dwBlockSize = ::GetFileVersionInfoSize((LPTSTR) a_szFile, &t_dwTemp); if (t_dwBlockSize) { t_pInfo = (LPVOID) new BYTE[t_dwBlockSize + 4]; if ( !t_pInfo ) { throw CHeap_Exception( CHeap_Exception::E_ALLOCATION_ERROR ) ; } UINT t_len; memset( t_pInfo, NULL, t_dwBlockSize + 4); if (::GetFileVersionInfo((LPTSTR) a_szFile, 0, t_dwBlockSize, t_pInfo)) { WORD wLang = 0; WORD wCodePage = 0; if(!GetVersionLanguage(t_pInfo, &wLang, &wCodePage) ) { // on failure: default to English // this returns a pointer to an array of WORDs WORD *pArray; bool fGotTranslation = false; fGotTranslation = ::VerQueryValue( t_pInfo, _T("\\VarFileInfo\\Translation"), (void **)(&pArray), &t_len); if(fGotTranslation) { t_len = t_len / sizeof(WORD); // find the english one... for (int i = 0; i < t_len; i += 2) { if( pArray[i] == 0x0409 ) { wLang = pArray[i]; wCodePage = pArray[i + 1]; break; } } } } TCHAR *pMfg, szTemp[256]; StringCchPrintf(szTemp,LENGTH_OF(szTemp), _T("\\StringFileInfo\\%04X%04X\\%s"), wLang, wCodePage, a_szVar); bool fGotCodePageInfo = false; fGotCodePageInfo = ::VerQueryValue( t_pInfo, szTemp, (void **) (&pMfg), &t_len); if(fGotCodePageInfo) { a_strValue = pMfg; t_fRc = TRUE; } } delete t_pInfo; t_pInfo = NULL ; } } catch(Structured_Exception se) { DelayLoadDllExceptionFilter(se.GetExtendedInfo()); if (t_pInfo) { delete t_pInfo ; } t_fRc = FALSE; } catch(...) { if (t_pInfo) { delete t_pInfo ; } throw ; } return t_fRc; } BOOL CDllWrapperBase::GetVersionLanguage ( void *a_vpInfo, WORD *a_wpLang, WORD *a_wpCodePage ) { WORD *t_wpTemp; WORD t_wLength; WCHAR *t_wcpTemp; char *t_cpTemp; BOOL t_bRet = FALSE; t_wpTemp = (WORD *) a_vpInfo; t_cpTemp = (char *) a_vpInfo; t_wpTemp++; // jump past buffer length. t_wLength = *t_wpTemp; // capture value length. t_wpTemp++; // skip past value length to what should be type code in new format if (*t_wpTemp == 0 || *t_wpTemp == 1) // new format expect unicode strings. { t_cpTemp = t_cpTemp + 38 + t_wLength + 8; t_wcpTemp = (WCHAR *) t_cpTemp; if (wcscmp(L"StringFileInfo", t_wcpTemp) == 0) // OK! were aligned properly. { t_bRet = TRUE; t_cpTemp += 30; // skip over "StringFileInfo" while ((DWORD_PTR) t_cpTemp % 4 > 0) // 32 bit align t_cpTemp++; t_cpTemp += 6; // skip over length and type fields. t_wcpTemp = (WCHAR *) t_cpTemp; swscanf(t_wcpTemp, L"%4x%4x", a_wpLang, a_wpCodePage); } } else // old format, expect single byte character strings. { t_cpTemp += 20 + t_wLength + 4; if (strcmp("StringFileInfo", t_cpTemp) == 0) // OK! were aligned properly. { t_bRet = TRUE; t_cpTemp += 20; // skip over length fields. sscanf(t_cpTemp, "%4x%4x", a_wpLang, a_wpCodePage); } } return (t_bRet); }