www.pudn.com > gui_Outlook.rar > modulver.cpp


//////////////////////////////////////////////////////////////// 
// 1998 Microsoft Systems Journal 
// If this code works, it was written by Paul DiLascia. 
// If not, I don't know who wrote it. 
// 
// CModuleVersion provides an easy way to get version info 
// for a module.(DLL or EXE). 
// 
#include "StdAfx.h" 
#include "ModulVer.h" 
 
CModuleVersion::CModuleVersion() 
{ 
	m_pVersionInfo = NULL;				// raw version info data  
} 
 
////////////////// 
// *** Kirk Stowell - Return the module version. 
// 
int CModuleVersion::GetModuleVer(CString cs) 
{ 
	DLLVERSIONINFO dvi; 
	return DllGetVersion(cs, dvi) ? 
		(dvi.dwMajorVersion*100 + dvi.dwMinorVersion) : 0; 
} 
 
////////////////// 
// Destroy: delete version info 
// 
CModuleVersion::~CModuleVersion() 
{ 
	delete [] m_pVersionInfo; 
} 
 
////////////////// 
// Get file version info for a given module 
// Allocates storage for all info, fills "this" with 
// VS_FIXEDFILEINFO, and sets codepage. 
// 
BOOL CModuleVersion::GetFileVersionInfo(LPCTSTR modulename) 
{ 
	m_translation.charset = 1252;		// default = ANSI code page 
	memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO)); 
 
	// get module handle 
	TCHAR filename[_MAX_PATH]; 
	HMODULE hModule = ::GetModuleHandle(modulename); 
	if (hModule==NULL && modulename!=NULL) 
		return FALSE; 
 
	// get module file name 
	DWORD len = GetModuleFileName(hModule, filename, 
		sizeof(filename)/sizeof(filename[0])); 
	if (len <= 0) 
		return FALSE; 
 
	// read file version info 
	DWORD dwDummyHandle; // will always be set to zero 
	len = GetFileVersionInfoSize(filename, &dwDummyHandle); 
	if (len <= 0) 
		return FALSE; 
 
	// delete old, if any 
	if (m_pVersionInfo) 
		delete m_pVersionInfo; 
 
	m_pVersionInfo = new BYTE[len]; // allocate version info 
	if (!::GetFileVersionInfo(filename, 0, len, m_pVersionInfo)) 
		return FALSE; 
 
	LPVOID lpvi; 
	UINT iLen; 
	if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &iLen)) 
		return FALSE; 
 
	// copy fixed info to myself, which am derived from VS_FIXEDFILEINFO 
	*(VS_FIXEDFILEINFO*)this = *(VS_FIXEDFILEINFO*)lpvi; 
 
	// Get translation info 
	if (VerQueryValue(m_pVersionInfo, 
		"\\VarFileInfo\\Translation", &lpvi, &iLen) && iLen >= 4) { 
		m_translation = *(TRANSLATION*)lpvi; 
		TRACE("code page = %d\n", m_translation.charset); 
	} 
 
	return dwSignature == VS_FFI_SIGNATURE; 
} 
 
////////////////// 
// Get string file info. 
// Key name is something like "CompanyName". 
// returns the value as a CString. 
// 
CString CModuleVersion::GetValue(LPCTSTR lpKeyName) 
{ 
	CString sVal; 
	if (m_pVersionInfo) { 
 
		// To get a string value must pass query in the form 
		// 
		//    "\StringFileInfo\\keyname" 
		// 
		// where  is the languageID concatenated with the 
		// code page, in hex. Wow. 
		// 
		CString query; 
		query.Format(_T("\\StringFileInfo\\%04x%04x\\%s"), 
			m_translation.langID, 
			m_translation.charset, 
			lpKeyName); 
 
		LPCTSTR pVal; 
		UINT iLenVal; 
		if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)query, 
				(LPVOID*)&pVal, &iLenVal)) { 
 
			sVal = pVal; 
		} 
	} 
	return sVal; 
} 
 
// typedef for DllGetVersion proc 
typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); 
 
///////////////// 
// Get DLL Version by calling DLL's DllGetVersion proc 
// 
BOOL CModuleVersion::DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi) 
{ 
	HINSTANCE hinst = LoadLibrary(modulename); 
	if (!hinst) 
		return FALSE; 
 
	// Must use GetProcAddress because the DLL might not implement  
	// DllGetVersion. Depending upon the DLL, the lack of implementation of the  
	// function may be a version marker in itself. 
	// 
	DLLGETVERSIONPROC pDllGetVersion = 
		(DLLGETVERSIONPROC)GetProcAddress(hinst, _T("DllGetVersion")); 
 
	if (!pDllGetVersion) 
		return FALSE; 
 
	memset(&dvi, 0, sizeof(dvi));			 // clear 
	dvi.cbSize = sizeof(dvi);				 // set size for Windows 
 
	return SUCCEEDED((*pDllGetVersion)(&dvi)); 
}