// Created by Larry Leonard, Definitive Solutions, Inc. #include "stdafx.h" #include "MyAtlFileVersion.h" ////////////////////////////////////////////////////////////////////// // MyAtlFileVersion // Constructor. MyAtlFileVersion::MyAtlFileVersion() : m_lpVersionData(NULL) , m_dwLangCharset(0) { } // Destructor. /* virtual */ MyAtlFileVersion::~MyAtlFileVersion() { Close(); } // Close the object. void MyAtlFileVersion::Close() { VALIDATE; delete [] m_lpVersionData; m_lpVersionData = NULL; m_dwLangCharset = 0; } // Open the object. bool MyAtlFileVersion::Open(const string& sModuleName) { VALIDATE; ATLASSERT(! sModuleName.empty() && "Must provide executable file name: 'AprCalc.exe'"); ATLASSERT(! m_lpVersionData && "Must NOT have already called Open()"); bool bReturn(false); // Get the version information size for allocate the buffer. DWORD dwHandle(0); DWORD dwDataSize(::GetFileVersionInfoSize( const_cast (sModuleName.data()), &dwHandle)); if (dwDataSize) { // Allocate buffer and retrieve version information. m_lpVersionData = new BYTE[dwDataSize]; if (m_lpVersionData) { if (::GetFileVersionInfo((char*) sModuleName.data(), dwHandle, dwDataSize, (PVOID*) m_lpVersionData)) { // Retrieve the first language and character-set identifier. UINT nQuerySize(0U); DWORD* pTransTable = NULL; if (::VerQueryValue(m_lpVersionData, _T("\\VarFileInfo\\Translation"), (PVOID*) &pTransTable, &nQuerySize)) { // Swap the words to have lang-charset in the correct format. m_dwLangCharset = MAKELONG(HIWORD(pTransTable[0]), LOWORD(pTransTable[0])); bReturn = true; } else { Close(); ATLASSERT(! "::VerQueryValue"); } } else { Close(); ATLASSERT(! "::GetFileVersionInfo"); } } } else { ATLASSERT(! "::GetFileVersionInfoSize"); } return bReturn; } // Ask for a specific value. string MyAtlFileVersion::QueryValue(const string& sValueName, DWORD dwLangCharset /* = 0 */ ) const { VALIDATE; ATLASSERT(m_lpVersionData && "Must call Open() first"); string sReturn; if (m_lpVersionData) { // If no lang-charset specified use default. if (0 == dwLangCharset) { dwLangCharset = m_dwLangCharset; } // Convert the lang-charset to an 8-char string. strstream tmp8; tmp8 << hex << m_dwLangCharset << ends; string sLangCharset(tmp8.str()); while (8 > sLangCharset.length()) { sLangCharset = _T("0") + sLangCharset; } // Query version information value. UINT nQuerySize(0U); LPVOID lpData = NULL; string sBlockName; strstream tmp; tmp << _T("\\StringFileInfo\\"); tmp << sLangCharset; tmp << _T("\\") << sValueName << ends; sBlockName = tmp.str(); if (::VerQueryValue((PVOID*) m_lpVersionData, (char*) sBlockName.data(), &lpData, &nQuerySize)) { sReturn = (LPCTSTR) lpData; } else { DOMYLOG (SEV_AUDIT, "::VerQueryValue() found no value for blockname <%t>.", sValueName); } } else { ATLASSERT(! "m_lpVersionData"); } return sReturn; } // Get the VS_FIXEDFILEINFO structure. bool MyAtlFileVersion::GetFixedInfo(VS_FIXEDFILEINFO& vsffi) const { VALIDATE; ATLASSERT(m_lpVersionData && "Must call Open() first"); bool bReturn(false); if (m_lpVersionData) { UINT nQuerySize(0U); VS_FIXEDFILEINFO* pVsffi = NULL; if (::VerQueryValue((PVOID*) m_lpVersionData, _T("\\"), (PVOID*) &pVsffi, &nQuerySize)) { vsffi = *pVsffi; bReturn = true; } } else { ATLASSERT(! "m_lpVersionData"); } return bReturn; } // string MyAtlFileVersion::GetFixedFileVersion() const { VALIDATE; string sVersion; VS_FIXEDFILEINFO vsffi; ::ZeroMemory(&vsffi, sizeof vsffi); if (GetFixedInfo(vsffi)) { strstream tmp; tmp << HIWORD(vsffi.dwFileVersionMS); tmp << _T("."); tmp << LOWORD(vsffi.dwFileVersionMS); tmp << _T("."); tmp << HIWORD(vsffi.dwFileVersionLS); tmp << _T("."); tmp << LOWORD(vsffi.dwFileVersionLS); tmp << ends; sVersion = tmp.str(); } return sVersion; } // string MyAtlFileVersion::GetFixedProductVersion() const { VALIDATE; string sVersion; VS_FIXEDFILEINFO vsffi; ::ZeroMemory(&vsffi, sizeof vsffi); if (GetFixedInfo(vsffi)) { strstream tmp; tmp << HIWORD(vsffi.dwProductVersionMS); tmp << _T("."); tmp << LOWORD(vsffi.dwProductVersionMS); tmp << _T("."); tmp << HIWORD(vsffi.dwProductVersionLS); tmp << _T("."); tmp << LOWORD(vsffi.dwProductVersionLS); tmp << ends; sVersion = tmp.str(); } return sVersion; }