// FileVersion.cpp: implementation of the CFileVersion class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FileVersion.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CFileVersion::CFileVersion() { m_lpVersionData = NULL; m_dwLangCharset = 0; } CFileVersion::~CFileVersion() { Close(); } void CFileVersion::Close() { delete[] m_lpVersionData; m_lpVersionData = NULL; m_dwLangCharset = 0; } BOOL CFileVersion::Open(LPCTSTR lpszModuleName) { ASSERT(_tcslen(lpszModuleName) > 0); ASSERT(m_lpVersionData == NULL); // Get the version information size for allocate the buffer DWORD dwHandle; DWORD dwDataSize = ::GetFileVersionInfoSize((LPTSTR)lpszModuleName, &dwHandle); if ( dwDataSize == 0 ) return FALSE; // Allocate buffer and retrieve version information m_lpVersionData = new BYTE[dwDataSize]; if (!::GetFileVersionInfo((LPTSTR)lpszModuleName, dwHandle, dwDataSize, (void**)m_lpVersionData) ) { Close(); return FALSE; } // Retrieve the first language and character-set identifier UINT nQuerySize; DWORD* pTransTable; if (!::VerQueryValue(m_lpVersionData, _T("\\VarFileInfo\\Translation"), (void **)&pTransTable, &nQuerySize) ) { Close(); return FALSE; } // Swap the words to have lang-charset in the correct format m_dwLangCharset = MAKELONG(HIWORD(pTransTable[0]), LOWORD(pTransTable[0])); return TRUE; } CString CFileVersion::QueryValue(LPCTSTR lpszValueName, DWORD dwLangCharset /* = 0*/) { // Must call Open() first // ASSERT(m_lpVersionData != NULL); if ( m_lpVersionData == NULL ) return (CString)_T(""); // If no lang-charset specified use default if ( dwLangCharset == 0 ) dwLangCharset = m_dwLangCharset; // Query version information value UINT nQuerySize; LPVOID lpData; CString strValue, strBlockName; strBlockName.Format(_T("\\StringFileInfo\\%08lx\\%s"), dwLangCharset, lpszValueName); if ( ::VerQueryValue((void **)m_lpVersionData, strBlockName.GetBuffer(0), &lpData, &nQuerySize) ) strValue = (LPCTSTR)lpData; strBlockName.ReleaseBuffer(); return strValue; } BOOL CFileVersion::GetFixedInfo(VS_FIXEDFILEINFO& vsffi) { // Must call Open() first ASSERT(m_lpVersionData != NULL); if ( m_lpVersionData == NULL ) return FALSE; UINT nQuerySize; VS_FIXEDFILEINFO* pVsffi; if ( ::VerQueryValue((void **)m_lpVersionData, _T("\\"), (void**)&pVsffi, &nQuerySize) ) { vsffi = *pVsffi; return TRUE; } return FALSE; } CString CFileVersion::GetFixedFileVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if ( GetFixedInfo(vsffi) ) { strVersion.Format(_T("%u,%u,%u,%u"),HIWORD(vsffi.dwFileVersionMS), LOWORD(vsffi.dwFileVersionMS), HIWORD(vsffi.dwFileVersionLS), LOWORD(vsffi.dwFileVersionLS)); } return strVersion; } CString CFileVersion::GetFixedProductVersion() { CString strVersion; VS_FIXEDFILEINFO vsffi; if ( GetFixedInfo(vsffi) ) { strVersion.Format(_T("%u,%u,%u,%u"), HIWORD(vsffi.dwProductVersionMS), LOWORD(vsffi.dwProductVersionMS), HIWORD(vsffi.dwProductVersionLS), LOWORD(vsffi.dwProductVersionLS)); } return strVersion; }