///////////////////////////////////////////////////////////////////////////// // VersionInfo.cpp : Implementation of the ZVersionInfo class. // #include "pch.h" #include "VersionInfo.h" ///////////////////////////////////////////////////////////////////////////// // ZVersionInfo ///////////////////////////////////////////////////////////////////////////// // Construction / Destruction ZVersionInfo::ZVersionInfo(bool) : m_pVerInfo(NULL), m_cbVerInfo(0), m_pFixed(NULL), m_wLangID(-1), m_wCodePage(-1) { } ZVersionInfo::ZVersionInfo(LPCTSTR szModule) : m_pVerInfo(NULL), m_cbVerInfo(0), m_pFixed(NULL), m_wLangID(-1), m_wCodePage(-1) { HRESULT hr = Load(szModule); assert(SUCCEEDED(hr)); } ZVersionInfo::ZVersionInfo(HINSTANCE hinstance) : m_pVerInfo(NULL), m_cbVerInfo(0), m_pFixed(NULL), m_wLangID(-1), m_wCodePage(-1) { HRESULT hr = Load(hinstance); assert(SUCCEEDED(hr)); } ZVersionInfo::~ZVersionInfo() { // Ensure that there is no previous version information block allocated Unload(); } bool ZVersionInfo::Load(LPCTSTR szModule) { // Check for a NULL or empty string if (!szModule || TEXT('\0') == *szModule) return Load(HINSTANCE(NULL)); // Ensure that there is no previous version information block allocated Unload(); assert(!m_cbVerInfo); assert(!m_pVerInfo); assert(!m_pFixed); // Get the size of the version information of the specified module BYTE* pVerInfo = NULL; DWORD cbVerInfo, dummy; cbVerInfo = GetFileVersionInfoSize(const_cast(szModule), &dummy); if (cbVerInfo) { // Allocate space to hold the version information pVerInfo = new BYTE[cbVerInfo]; if (!pVerInfo) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return false; } } else cbVerInfo = sizeof(*m_pFixed); // Attempt to load the version information block if (!GetFileVersionInfo(const_cast(szModule), 0, cbVerInfo, pVerInfo)) { DWORD dwLastError = GetLastError(); delete [] pVerInfo; SetLastError(dwLastError ? dwLastError : ERROR_NO_MORE_ITEMS); return false; } // Attempt to get a pointer to the fixed version information VS_FIXEDFILEINFO* pFixed = NULL; UINT cbFixed = 0; if (!VerQueryValue(pVerInfo, TEXT("\\"), (void**)&pFixed, &cbFixed) || cbFixed != sizeof(*pFixed)) { DWORD dwLastError = GetLastError(); delete [] pVerInfo; SetLastError(dwLastError); return false; } // Save the size of the version info and the allocated pointers m_cbVerInfo = cbVerInfo; m_pVerInfo = pVerInfo; m_pFixed = pFixed; // Indicate success SetLastError(0); return true; } bool ZVersionInfo::Load(HINSTANCE hinstance) { // Get the module name of the specified instance TCHAR szModule[_MAX_PATH]; if (!GetModuleFileName(hinstance, szModule, sizeofArray(szModule))) return false; // Pass on to the string overload of this function return Load(szModule); } bool ZVersionInfo::Load(const void* pvVerInfo, UINT cbVerInfo) { // Ensure that a NULL was not passed if (!pvVerInfo) { SetLastError(ERROR_INVALID_PARAMETER); return false; } // Ensure that there is no previous version information block allocated Unload(); // Allocate space to hold the version information BYTE* pVerInfo = new BYTE[cbVerInfo]; if (!pVerInfo) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return false; } // Copy the specified block CopyMemory(pVerInfo, pvVerInfo, cbVerInfo); // Attempt to get a pointer to the fixed version information VS_FIXEDFILEINFO* pFixed = NULL; UINT cbFixed = 0; if (!VerQueryValue(pVerInfo, TEXT("\\"), (void**)&pFixed, &cbFixed) || cbFixed != sizeof(*pFixed)) { DWORD dwLastError = GetLastError(); delete [] pVerInfo; SetLastError(dwLastError ? dwLastError : ERROR_NO_MORE_ITEMS); return false; } // Save the size of the version info and the allocated and fixed pointers m_cbVerInfo = cbVerInfo; m_pVerInfo = pVerInfo; m_pFixed = pFixed; // Indicate success SetLastError(0); return true; } void ZVersionInfo::Unload() { // Deallocate the version information block if (m_pVerInfo) delete m_pVerInfo; m_pVerInfo = NULL; m_cbVerInfo = 0; m_pFixed = NULL; } ///////////////////////////////////////////////////////////////////////////// // Attributes ///////////////////////////////////////////////////////////////////////////// // String Values ZString ZVersionInfo::GetStringValue(LPCTSTR pszKey, bool* pbExists) const { // Initialize the [out] parameter if (pbExists) *pbExists = false; // Ensure that we have a non-NULL key if (!pszKey) { SetLastError(ERROR_INVALID_PARAMETER); return ZString(); } // Determine if a LANGID was specified LANGID wLangID = LANGID((LANGID(-1) == GetLanguageID()) ? MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) : GetLanguageID()); // Determine if a code page was specified WORD rgwCodePages[] = { 1200, // Unicode 1252, // Windows Multilingual 0000, // Neutral }; int cCodePages = sizeofArray(rgwCodePages); if (WORD(-1) != m_wCodePage) { rgwCodePages[0] = m_wCodePage; cCodePages = 1; } // Format the base sub-block string TCHAR szBase[32]; _stprintf(szBase, TEXT("\\StringFileInfo\\%04X"), wLangID); // Loop thru each code page for (int iCP = 0; iCP < cCodePages; ++iCP) { // Format a sub-block string TCHAR szSubBlock[_MAX_PATH * 2]; _stprintf(szSubBlock, TEXT("%s%04X\\%s"), szBase, rgwCodePages[iCP], pszKey); // Query the value UINT cbValue = 0; LPCTSTR pszValue = NULL; if (VerQueryValue(m_pVerInfo, szSubBlock, (void**)&pszValue, &cbValue)) { // Indicate that the key exists if (pbExists) *pbExists = true; // Indicate success SetLastError(0); return ZString(pszValue); } } // Indicate success SetLastError(0); return ZString(); }