#include "pch.h"
#include "VersionInfo.h"
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()
{
Unload();
}
bool ZVersionInfo::Load(LPCTSTR szModule)
{
if (!szModule || TEXT('\0') == *szModule)
return Load(HINSTANCE(NULL));
Unload();
assert(!m_cbVerInfo);
assert(!m_pVerInfo);
assert(!m_pFixed);
BYTE* pVerInfo = NULL;
DWORD cbVerInfo, dummy;
cbVerInfo = GetFileVersionInfoSize(const_cast<LPTSTR>(szModule), &dummy);
if (cbVerInfo)
{
pVerInfo = new BYTE[cbVerInfo];
if (!pVerInfo)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return false;
}
}
else
cbVerInfo = sizeof(*m_pFixed);
if (!GetFileVersionInfo(const_cast<LPTSTR>(szModule), 0, cbVerInfo, pVerInfo))
{
DWORD dwLastError = GetLastError();
delete [] pVerInfo;
SetLastError(dwLastError ? dwLastError : ERROR_NO_MORE_ITEMS);
return false;
}
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;
}
m_cbVerInfo = cbVerInfo;
m_pVerInfo = pVerInfo;
m_pFixed = pFixed;
SetLastError(0);
return true;
}
bool ZVersionInfo::Load(HINSTANCE hinstance)
{
TCHAR szModule[_MAX_PATH];
if (!GetModuleFileName(hinstance, szModule, sizeofArray(szModule)))
return false;
return Load(szModule);
}
bool ZVersionInfo::Load(const void* pvVerInfo, UINT cbVerInfo)
{
if (!pvVerInfo)
{
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
Unload();
BYTE* pVerInfo = new BYTE[cbVerInfo];
if (!pVerInfo)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return false;
}
CopyMemory(pVerInfo, pvVerInfo, cbVerInfo);
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;
}
m_cbVerInfo = cbVerInfo;
m_pVerInfo = pVerInfo;
m_pFixed = pFixed;
SetLastError(0);
return true;
}
void ZVersionInfo::Unload()
{
if (m_pVerInfo)
delete m_pVerInfo;
m_pVerInfo = NULL;
m_cbVerInfo = 0;
m_pFixed = NULL;
}
ZString ZVersionInfo::GetStringValue(LPCTSTR pszKey, bool* pbExists) const
{
if (pbExists)
*pbExists = false;
if (!pszKey)
{
SetLastError(ERROR_INVALID_PARAMETER);
return ZString();
}
LANGID wLangID = LANGID((LANGID(-1) == GetLanguageID()) ?
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) : GetLanguageID());
WORD rgwCodePages[] =
{
1200, 1252, 0000, };
int cCodePages = sizeofArray(rgwCodePages);
if (WORD(-1) != m_wCodePage)
{
rgwCodePages[0] = m_wCodePage;
cCodePages = 1;
}
TCHAR szBase[32];
_stprintf_s(szBase, 32, TEXT("\\StringFileInfo\\%04X"), wLangID);
for (int iCP = 0; iCP < cCodePages; ++iCP)
{
TCHAR szSubBlock[_MAX_PATH * 2];
_stprintf_s(szSubBlock, _MAX_PATH * 2, TEXT("%s%04X\\%s"), szBase, rgwCodePages[iCP], pszKey);
UINT cbValue = 0;
LPCTSTR pszValue = NULL;
if (VerQueryValue(m_pVerInfo, szSubBlock, (void**)&pszValue, &cbValue))
{
if (pbExists)
*pbExists = true;
SetLastError(0);
return ZString(pszValue);
}
}
SetLastError(0);
return ZString();
}