📄 verinfo.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
/*
DESCRIPTION:
CFileVersionInfo - Class for getting file version information
http://www.codeproject.com/file/VersionInfo.asp
NOTES:
Copyright(C) Armen Hakobyan, 2003
mailto:armen.h@web.am
VERSION HISTORY:
25 Jul 2003 - Posted the article
27 Jul 2003 - Added DLLVERSIONINFO2 support to DllGetVersion
21 Jan 2004 - Added GetFileVersionMajor, GetFileVersionMinor,
GetFileVersionBuild, GetFileVersionQFE functions
29 Jan 2004 - Added GetProductVersionMajor, GetProductVersionMinor,
GetProductVersionBuild, GetProductVersionQFE functions
*/
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "verinfo.h"
/////////////////////////////////////////////////////////////////////////////
//#define _wslPackVersion( major, minor ) MAKELONG( minor, major )
#ifndef _free
#define _free(p) { if( p != NULL ){ free(p); p = NULL; } }
#endif
#ifndef ASSERT_RETURN
#define ASSERT_RETURN(x) { ASSERT(0); return x; }
#endif
/////////////////////////////////////////////////////////////////////////////
#ifndef DLLVER_MAJOR_MASK
typedef struct _DLLVERSIONINFO2
{
DLLVERSIONINFO info1;
DWORD dwFlags; // No flags currently defined
ULONGLONG ullVersion;
}
DLLVERSIONINFO2;
#endif // DLLVER_MAJOR_MASK
#ifndef MAKEDLLVERULL
#define MAKEDLLVERULL( major, minor, build, qfe )\
( ( (ULONGLONG)(major) << 48 ) | \
( (ULONGLONG)(minor) << 32 ) | \
( (ULONGLONG)(build) << 16 ) | \
( (ULONGLONG)( qfe) << 0 ) )
#endif // MAKEDLLVERULL
/////////////////////////////////////////////////////////////////////////////
#ifndef lstrcpyn
inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength)
{
if ( lpstrDest == NULL || lpstrSrc == NULL || nLength <= 0 )
{
return NULL;
}
int nStrLen = (int)(lstrlen(lpstrSrc));
int nTempLen = nLength - 1;
int nLen = min(nStrLen, nTempLen);
size_t szCpy = (size_t)nLen * sizeof(TCHAR);
LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, szCpy);
lpstrDest[nLen] = 0;
return lpstrRet;
}
#endif // !lstrcpyn
HRESULT STDAPICALLTYPE DllGetVersion(IN HMODULE hModule,
OUT DLLVERSIONINFO* lpDVI)
{
if ( hModule == NULL ||
::IsBadReadPtr( lpDVI, sizeof( DLLVERSIONINFO* ) ) )
{
ASSERT_RETURN(S_FALSE);
}
CONST DWORD cbSize = lpDVI->cbSize;
if (
#ifdef DLLVERSIONINFO2
(
#endif
cbSize != sizeof(DLLVERSIONINFO)
#ifdef DLLVERSIONINFO2
&& cbSize != sizeof(DLLVERSIONINFO2) )
#endif
|| ::IsBadWritePtr(lpDVI, cbSize) )
{
ASSERT_RETURN( S_FALSE );
}
::ZeroMemory(lpDVI, cbSize);
lpDVI->cbSize = cbSize;
CFileVersionInfo fvi;
if ( fvi.Open(hModule) )
{
VS_FIXEDFILEINFO vsffi = fvi.GetVSFFI();
if ( vsffi.dwFileType == VFT_DLL ||
vsffi.dwFileType == VFT_STATIC_LIB )
{
switch ( vsffi.dwFileOS )
{
case VOS__WINDOWS32:
case VOS_NT_WINDOWS32:
lpDVI->dwPlatformID = DLLVER_PLATFORM_WINDOWS;
break;
case VOS_NT:
lpDVI->dwPlatformID = DLLVER_PLATFORM_NT;
break;
default:
return (S_FALSE);
}
lpDVI->dwMajorVersion = HIWORD(vsffi.dwFileVersionMS);
lpDVI->dwMinorVersion = LOWORD(vsffi.dwFileVersionMS);
lpDVI->dwBuildNumber = HIWORD(vsffi.dwFileVersionLS);
#ifdef DLLVERSIONINFO2
if ( cbSize == sizeof(DLLVERSIONINFO2) )
{
DLLVERSIONINFO2* lpDVI2 = (DLLVERSIONINFO2*)lpDVI;
lpDVI2->ullVersion = MAKEDLLVERULL(
lpDVI->dwMajorVersion,
lpDVI->dwMinorVersion,
lpDVI->dwBuildNumber,
LOWORD( vsffi.dwFileVersionLS )
);
}
#endif
return (S_OK);
}
#ifdef _DEBUG
else
ASSERT(0);
#endif
fvi.Close();
}
return ( S_FALSE );
}
/////////////////////////////////////////////////////////////////////////////
// HIWORD( ffi.dwFileVersionMS ) - major
// LOWORD( ffi.dwFileVersionMS ) - minor
// HIWORD( ffi.dwFileVersionLS ) - build
// LOWORD( ffi.dwFileVersionLS ) - QFE
/////////////////////////////////////////////////////////////////////////////
CFileVersionInfo::CFileVersionInfo(void)
: m_lpbyVIB( NULL )
{
Close();
}
CFileVersionInfo::~CFileVersionInfo( void )
{
try
{
Close();
}
catch (...)
{}
}
LPCTSTR CFileVersionInfo::s_ppszStr[] = {
_T( "Comments" ), _T( "CompanyName" ),
_T( "FileDescription" ), _T( "FileVersion" ),
_T( "InternalName" ), _T( "LegalCopyright" ),
_T( "LegalTrademarks" ), _T( "OriginalFilename" ),
_T( "PrivateBuild" ), _T( "ProductName" ),
_T( "ProductVersion" ), _T( "SpecialBuild" ),
_T( "OLESelfRegister" )
};
////////////////////////////////////////////////////////////////////////////////
// Implementation
BOOL CFileVersionInfo::Open(IN HINSTANCE hInstance)
{
if ( hInstance == NULL )
{
ASSERT_RETURN( FALSE );
}
TCHAR szFileName[ MAX_PATH ] = { 0 };
if ( ::GetModuleFileName(hInstance, szFileName, MAX_PATH) )
{
return Open( szFileName );
}
return FALSE;
};
BOOL CFileVersionInfo::Open(IN LPCTSTR lpszFileName)
{
if ( lpszFileName == NULL )
{
ASSERT_RETURN( FALSE );
}
Close();
if ( !GetVersionInfo( lpszFileName ) || !QueryVersionTrans() )
{
Close();
}
return m_bValid;
};
BOOL CFileVersionInfo::GetVersionInfo(IN LPCTSTR lpszFileName)
{
DWORD dwDummy = 0;
DWORD dwSize = ::GetFileVersionInfoSize(
const_cast< LPTSTR >(lpszFileName), &dwDummy // Set to 0
);
if ( dwSize > 0 )
{
m_lpbyVIB = (LPBYTE)malloc(dwSize);
if ( m_lpbyVIB != NULL &&
::GetFileVersionInfo( const_cast< LPTSTR >(lpszFileName),
0, dwSize, m_lpbyVIB ) )
{
UINT uLen = 0;
LPVOID lpVSFFI = NULL;
if ( ::VerQueryValue(m_lpbyVIB, _T( "\\" ), (LPVOID*)&lpVSFFI, &uLen) )
{
::CopyMemory( &m_vsffi, lpVSFFI, sizeof(VS_FIXEDFILEINFO) );
m_bValid = (m_vsffi.dwSignature == VS_FFI_SIGNATURE);
}
}
}
return m_bValid;
}
BOOL CFileVersionInfo::QueryVersionTrans(void)
{
if ( m_bValid == FALSE )
{
ASSERT_RETURN( FALSE );
}
UINT uLen = 0;
LPVOID lpBuf = NULL;
if ( ::VerQueryValue(m_lpbyVIB, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lpBuf, &uLen) )
{
m_lpdwTrans = (LPDWORD)lpBuf;
m_nTransCnt = ( uLen / sizeof(DWORD) );
}
return (BOOL)( m_lpdwTrans != NULL );
}
void CFileVersionInfo::Close(void)
{
m_nTransCnt = 0;
m_nTransCur = 0;
m_bValid = FALSE;
m_lpdwTrans = NULL;
::ZeroMemory( &m_vsffi, sizeof(VS_FIXEDFILEINFO) );
_free( m_lpbyVIB );
}
#pragma warning (disable : 4996)
BOOL CFileVersionInfo::QueryStringValue(IN LPCTSTR lpszItem,
OUT LPTSTR lpszValue,
IN INT nBuf) const
{
if ( m_bValid == FALSE || lpszItem == NULL )
{
ASSERT_RETURN(FALSE);
}
if ( lpszValue != NULL && nBuf <= 0 )
{
ASSERT_RETURN(FALSE);
}
::ZeroMemory(lpszValue, nBuf * sizeof(TCHAR));
TCHAR szSFI[ MAX_PATH ] = { 0 };
::wsprintf( szSFI, _T( "\\StringFileInfo\\%04X%04X\\%s" ),
GetCurLID(), GetCurCP(), lpszItem );
BOOL bRes = FALSE;
UINT uLen = 0;
LPTSTR lpszBuf = NULL;
if ( ::VerQueryValue(m_lpbyVIB, (LPTSTR)szSFI, (LPVOID*)&lpszBuf, &uLen) )
{
if ( lpszValue != NULL && nBuf > 0 )
{
bRes = (BOOL)(::lstrcpyn( lpszValue, lpszBuf, nBuf ) != NULL);
}
else
{
bRes = TRUE;
}
}
return (bRes);
}
#pragma warning (default : 4996)
BOOL CFileVersionInfo::QueryStringValue(IN INT nIndex,
OUT LPTSTR lpszValue,
IN INT nBuf) const
{
if ( nIndex < (int)VI_STR_COMMENTS ||
nIndex > (int)VI_STR_OLESELFREGISTER )
{
ASSERT_RETURN(FALSE);
}
return QueryStringValue(s_ppszStr[ nIndex ], lpszValue, nBuf);
}
LPCTSTR CFileVersionInfo::GetVerStringName(IN INT nIndex) const
{
if ( nIndex < (int)VI_STR_COMMENTS ||
nIndex > (int)VI_STR_OLESELFREGISTER )
{
ASSERT_RETURN(FALSE);
}
return (LPCTSTR)s_ppszStr[nIndex];
}
INT CFileVersionInfo::FindTrans(IN LANGID wLID,
IN WORD wCP) const
{
if ( m_bValid == FALSE )
{
ASSERT_RETURN(-1);
}
for ( UINT n = 0; n < m_nTransCnt; n++ )
{
if ( NULL != m_lpdwTrans )
{
if ( LOWORD(m_lpdwTrans[n]) == wLID &&
HIWORD(m_lpdwTrans[n]) == wCP )
{
return (int)n;
}
}
}
return -1;
}
BOOL CFileVersionInfo::SetTrans(IN LANGID wLID /*LANG_NEUTRAL*/,
IN WORD wCP /*WSLVI_CP_UNICODE*/)
{
if ( !m_bValid )
{
ASSERT_RETURN(FALSE);
}
if ( GetCurLID() == wLID && GetCurCP() == wCP )
{
return TRUE;
}
INT nPos = FindTrans(wLID, wCP);
if ( nPos != -1 )
{
m_nTransCur = (UINT)nPos;
}
return (m_nTransCur == (UINT)nPos);
}
DWORD CFileVersionInfo::GetTransByIndex(IN UINT nIndex) const
{
if ( !m_bValid || nIndex > m_nTransCnt )
{
ASSERT_RETURN(0);
}
return m_lpdwTrans[nIndex];
}
BOOL CFileVersionInfo::SetTransIndex(IN UINT nIndex /*0*/)
{
if ( !m_bValid )
{
ASSERT_RETURN(FALSE);
}
if ( m_nTransCur == nIndex )
{
return TRUE;
}
if ( nIndex <= m_nTransCnt )
{
m_nTransCur = nIndex;
}
return (m_nTransCur == nIndex);
}
/////////////////////////////////////////////////////////////////////////////
// Static members
// If the CP identifier is unknown, it returns a
// default string ("Unknown"):
BOOL CFileVersionInfo::GetCPName(IN WORD wCP,
OUT LPCTSTR* ppszName)
{
if ( ppszName == NULL )
{
ASSERT_RETURN(FALSE);
}
BOOL bRes = TRUE;
*ppszName = NULL;
switch ( wCP )
{
case VI_CP_ASCII:
*ppszName = _T("7-bit ASCII");
break;
case VI_CP_JAPAN:
*ppszName = _T("Japan (Shift ?JIS X-0208)");
break;
case VI_CP_KOREA:
*ppszName = _T("Korea (Shift ?KSC 5601)");
break;
case VI_CP_TAIWAN:
*ppszName = _T("Taiwan (Big5)");
break;
case VI_CP_UNICODE:
*ppszName = _T("Unicode");
break;
case VI_CP_LATIN2:
*ppszName = _T("Latin-2 (Eastern European)");
break;
case VI_CP_CYRILLIC:
*ppszName = _T("Cyrillic");
break;
case VI_CP_MULTILNG:
*ppszName = _T("Multilingual");
break;
case VI_CP_GREEK:
*ppszName = _T("Greek");
break;
case VI_CP_TURKISH:
*ppszName = _T("Turkish");
break;
case VI_CP_HEBREW:
*ppszName = _T("Hebrew");
break;
case VI_CP_ARABIC:
*ppszName = _T("Arabic");
break;
default:
*ppszName = _T("Unknown");
bRes = FALSE;
break;
}
return bRes;
}
//////////////////////////////////////////////////////////////////////////
BOOL CFileVersionInfo::IsValid(void) const
{
return m_bValid;
}
const VS_FIXEDFILEINFO& CFileVersionInfo::GetVSFFI(void) const
{
return m_vsffi;
}
////////////////////////////////////////////////////////////////////////////////
WORD CFileVersionInfo::GetFileVersionMajor( void ) const
{
ASSERT(m_bValid);
return HIWORD(m_vsffi.dwFileVersionMS);
}
WORD CFileVersionInfo::GetFileVersionMinor(void) const
{
ASSERT(m_bValid);
return LOWORD(m_vsffi.dwFileVersionMS);
}
WORD CFileVersionInfo::GetFileVersionBuild(void) const
{
ASSERT(m_bValid);
return HIWORD(m_vsffi.dwFileVersionLS);
}
WORD CFileVersionInfo::GetFileVersionQFE(void) const
{
ASSERT(m_bValid);
return LOWORD(m_vsffi.dwFileVersionLS);
}
WORD CFileVersionInfo::GetProductVersionMajor(void) const
{
ASSERT(m_bValid);
return HIWORD(m_vsffi.dwProductVersionMS);
}
WORD CFileVersionInfo::GetProductVersionMinor(void) const
{
ASSERT(m_bValid);
return LOWORD(m_vsffi.dwProductVersionMS);
}
WORD CFileVersionInfo::GetProductVersionBuild(void) const
{
ASSERT(m_bValid);
return HIWORD(m_vsffi.dwProductVersionLS);
}
WORD CFileVersionInfo::GetProductVersionQFE(void) const
{
ASSERT(m_bValid);
return LOWORD(m_vsffi.dwProductVersionLS);
}
////////////////////////////////////////////////////////////////////////////////
// Translation functions
UINT CFileVersionInfo::GetTransCount(void) const
{
ASSERT(m_bValid);
return m_nTransCnt;
}
UINT CFileVersionInfo::GetCurTransIndex(void) const
{
ASSERT(m_bValid);
return m_nTransCur;
}
LANGID CFileVersionInfo::GetLIDByIndex(IN UINT nIndex) const
{
return LOWORD( GetTransByIndex(nIndex) );
}
WORD CFileVersionInfo::GetCPByIndex(IN UINT nIndex) const
{
return HIWORD( GetTransByIndex(nIndex) );
}
DWORD CFileVersionInfo::GetCurTrans(void) const
{
return GetTransByIndex( GetCurTransIndex() );
}
LANGID CFileVersionInfo::GetCurLID(void) const
{
return GetLIDByIndex( GetCurTransIndex() );
}
WORD CFileVersionInfo::GetCurCP(void) const
{
return GetCPByIndex( GetCurTransIndex() );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -