⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verinfo.cpp

📁 查看exe/dll文件版本的类
💻 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 + -