//////////////////////////////////////////////////////////////// // 1998 Microsoft Systems Journal // If this code works, it was written by Paul DiLascia. // If not, I don't know who wrote it. // // CModuleVersion provides an easy way to get version info // for a module.(DLL or EXE). // // This code appeard in April 1998 edition of Microsoft Systems // Journal. // // 27-July-1998 -- Adapted by James A. McLaughiln (Schlumberger // Technology Corp.) for Smart Cards. Merged with the concepts from // CFileVersion class contributed by Manuel Laflamme on a posting to // www.codeguru.com. If these mods don't work, then you can blame me. #include "StdAfx.h" #include "slbModVer.h" CModuleVersion::CModuleVersion() : m_pVersionInfo(NULL) { } ////////////////// // Destroy: delete version info // CModuleVersion::~CModuleVersion() { delete [] m_pVersionInfo; } BOOL CModuleVersion::GetFileVersionInfo(LPCTSTR modulename) { // get module handle HMODULE hModule = ::GetModuleHandle(modulename); if (hModule==NULL && modulename!=NULL) return FALSE; return GetFileVersionInfo(hModule); } ////////////////// // Get file version info for a given module // Allocates storage for all info, fills "this" with // VS_FIXEDFILEINFO, and sets codepage. // BOOL CModuleVersion::GetFileVersionInfo(HMODULE hModule) { m_translation.charset = 1252; // default = ANSI code page memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO)); // get module file name TCHAR filename[_MAX_PATH]; DWORD len = GetModuleFileName(hModule, filename, sizeof(filename)/sizeof(filename[0])); if (len <= 0) return FALSE; // read file version info DWORD dwDummyHandle; // will always be set to zero len = GetFileVersionInfoSize(filename, &dwDummyHandle); if (len <= 0) return FALSE; m_pVersionInfo = new BYTE[len]; // allocate version info if (!::GetFileVersionInfo(filename, 0, len, m_pVersionInfo)) return FALSE; // copy fixed info to myself, which am derived from VS_FIXEDFILEINFO if (!GetFixedInfo(*(VS_FIXEDFILEINFO*)this)) return FALSE; // Get translation info LPVOID lpvi; UINT iLen; if (VerQueryValue(m_pVersionInfo, TEXT("\\VarFileInfo\\Translation"), &lpvi, &iLen) && iLen >= 4) { m_translation = *(TRANSLATION*)lpvi; TRACE(TEXT("code page = %d\n"), m_translation.charset); } return dwSignature == VS_FFI_SIGNATURE; } ////////////////// // Get string file info. // Key name is something like "CompanyName". // returns the value as a CString. // CString CModuleVersion::GetValue(LPCTSTR lpKeyName) { CString sVal; if (m_pVersionInfo) { // To get a string value must pass query in the form // // "\StringFileInfo\\keyname" // // where is the languageID concatenated with the // code page, in hex. Wow. // CString query; query.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), m_translation.langID, m_translation.charset, lpKeyName); LPCTSTR pVal; UINT iLenVal; if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)query, (LPVOID*)&pVal, &iLenVal)) { sVal = pVal; } } return sVal; } // typedef for DllGetVersion proc typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); ///////////////// // Get DLL Version by calling DLL's DllGetVersion proc // BOOL CModuleVersion::DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi) { HINSTANCE hinst = LoadLibrary(modulename); if (!hinst) return FALSE; // Must use GetProcAddress because the DLL might not implement // DllGetVersion. Depending upon the DLL, the lack of implementation of the // function may be a version marker in itself. // DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinst, reinterpret_cast(_T("DllGetVersion"))); if (!pDllGetVersion) return FALSE; memset(&dvi, 0, sizeof(dvi)); // clear dvi.cbSize = sizeof(dvi); // set size for Windows return SUCCEEDED((*pDllGetVersion)(&dvi)); } BOOL CModuleVersion::GetFixedInfo(VS_FIXEDFILEINFO& vsffi) { // Must furst call GetFileVersionInfo or constructor with arg ASSERT(m_pVersionInfo != NULL); if ( m_pVersionInfo == NULL ) return FALSE; UINT nQuerySize; VS_FIXEDFILEINFO* pVsffi; if ( ::VerQueryValue((void **)m_pVersionInfo, _T("\\"), (void**)&pVsffi, &nQuerySize) ) { vsffi = *pVsffi; return TRUE; } return FALSE; } CString CModuleVersion::GetFixedFileVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if (GetFixedInfo(vsffi)) { strVersion.Format (_T("%u,%u,%u,%u"),HIWORD(dwFileVersionMS), LOWORD(dwFileVersionMS), HIWORD(dwFileVersionLS), LOWORD(dwFileVersionLS)); } return strVersion; } CString CModuleVersion::GetFixedProductVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if (GetFixedInfo(vsffi)) { strVersion.Format (_T("%u,%u,%u,%u"), HIWORD(dwProductVersionMS), LOWORD(dwProductVersionMS), HIWORD(dwProductVersionLS), LOWORD(dwProductVersionLS)); } return strVersion; }