Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

LintProject - Improving the Usability of PC-Lint with Visual C++ Solutions and Projects

, , 29 Jan 2009
Utility to run PC-Lint on Visual C++ solutions and projects, generating XML and HTML reports of the results.
////////////////////////////////////////////////////////////////
// 1998 Microsoft Systems Journal
//
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//

/// \file	
/// \brief CModuleVersion definition/implementation.

#ifndef __ModuleVersion_H__
#define __ModuleVersion_H__

#pragma once


// tell linker to link with version.lib for VerQueryValue, etc.
#pragma comment(linker, "/defaultlib:version.lib")

#ifndef _INC_SHLWAPI
	#pragma message(__FILE__" : For faster compilation, #include <shlwapi.h> in stdafx.h")
	#include <shlwapi.h>
#endif

/*
#ifndef DLLVERSIONINFO
// following is from shlwapi.h, in November 1997 release of the Windows SDK

typedef struct _DllVersionInfo
{
        DWORD cbSize;
        DWORD dwMajorVersion;                   // Major version
        DWORD dwMinorVersion;                   // Minor version
        DWORD dwBuildNumber;                    // Build number
        DWORD dwPlatformID;                     // DLLVER_PLATFORM_*
} DLLVERSIONINFO;

// Platform IDs for DLLVERSIONINFO
#define DLLVER_PLATFORM_WINDOWS         0x00000001      // Windows 95
#define DLLVER_PLATFORM_NT              0x00000002      // Windows NT

#endif // DLLVERSIONINFO
*/



namespace Riverblade
{
	namespace Libraries
	{
		namespace Utils
		{
			/// \brief Returns version information about a module (DLL or EXE).
			///
			/// Usage:
			///
			/// \code
			///
			/// CModuleVersion ver;
			/// if (ver.GetFileVersionInfo(_T("mymodule") ) )
			/// {
			///		// info is in ver, you can call GetValue to get variable info like
			///		CString s = ver.GetValue(_T("CompanyName") );
			/// }
			///
			/// \endcode
			///
			/// You can also call the static function DllGetVersion() to retrieve DLLVERSIONINFO directly.
			///
			class CModuleVersion : public VS_FIXEDFILEINFO
			{
				protected:
					BYTE* m_pVersionInfo;				///< Raw version information data 

					struct TRANSLATION
					{
						WORD langID;					///< Language ID
						WORD charset;					///< Character set (code page)
					} m_translation;					///< Translation info (language/character set)

				public:
					/// \brief Main constructor.
					///
					CModuleVersion(void)
						:	m_pVersionInfo(NULL)
					{
						// Clear VS_FIXEDFILEINFO
						::ZeroMemory(this, sizeof(VS_FIXEDFILEINFO) );	//lint !e1415 (Warning -- Pointer to non-POD class 'CModuleVersion' passed to function 'memset(void *, int, unsigned int)' (arg. no. 1))
					}


					/// \brief Class destructor.
					///
					virtual ~CModuleVersion(void)
					{
						delete [] m_pVersionInfo;
					}


					/// \brief Read the file version info for a given module.
					///
					/// Allocates storage for all info, fills "this" with VS_FIXEDFILEINFO, and the sets codepage.
					///
					/// Modified to give application version info by default if hModule is NULL (AJM 21/4/99).
					///
					/// \param	hModule			The instance handle of the module whose version should be read.
					///							May be NULL.
					/// \return	BOOL			\em true if the file version information was read correctly;
					///							\em false otherwise.
					///
					bool GetFileVersionInfo(HMODULE hModule = NULL)
					{
						TCHAR szFileName[_MAX_PATH];

						szFileName[0] = '\0';

						if (NULL != hModule)
						{
							// Get module file name
							const DWORD dwLen = GetModuleFileName(hModule, szFileName, sizeof(szFileName) / sizeof(szFileName[0]) );
							if (dwLen == 0)
							{
								return false;
							}
						}
						return GetFileVersionInfo(szFileName);
					}


					/// \brief Read the file version info for the module with the given name.
					///
					/// \param	pszModuleName	The name of the module.
					/// \return	BOOL			\em true if the file version information was read correctly;
					///							\em false otherwise.
					///
					bool GetFileVersionInfo(LPCTSTR const pszModuleName)
					{
						const CString sModule(pszModuleName);

						m_translation.charset = 1252;		// default = ANSI code page

						//memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO));

						// get module handle
						TCHAR filename[_MAX_PATH];
						const HMODULE hModule = ::GetModuleHandle(sModule);

						if ( (NULL == hModule) && !sModule.IsEmpty() )
						{
							return false;
						}

						// get module file name
						const DWORD dwLen = ::GetModuleFileName(hModule, filename, sizeof(filename)/sizeof(filename[0]));
						if (dwLen > 0)
						{
							return GetFileVersionInfoFromPathName(filename);
						}
						return false;
					}


					/// \brief Read the file version info for the module with the given pathname.
					///
					/// \param	pszPathName		The pathname of the module.
					/// \return	BOOL			\em true if the file version information was read correctly;
					///							\em false otherwise.
					///
					bool GetFileVersionInfoFromPathName(LPCTSTR const pszPathName)
					{
						m_translation.charset = 1252;		// default = ANSI code page

						//memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO));

						// read file version info
						DWORD dwDummyHandle = 0; // will always be set to zero
						const DWORD dwLen = GetFileVersionInfoSize(pszPathName, &dwDummyHandle);
						if (0 == dwLen)
						{
							return false;
						}
						m_pVersionInfo = new BYTE[dwLen]; // allocate version info
						if (!::GetFileVersionInfo(pszPathName, 0, dwLen, m_pVersionInfo) )
						{
							return false;
						}

						LPVOID lpvi = NULL;
						UINT uLen = 0;
						if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &uLen) )		 //lint !e1776 (Info -- Converting a string literal to char * is not const safe (arg. no. 2))
						{
							return false;
						}

						// copy fixed info to myself, which am derived from VS_FIXEDFILEINFO
						//
						//lint -save -e929 (Note -- cast from pointer to pointer)
						*static_cast<VS_FIXEDFILEINFO*>(this) = *static_cast<VS_FIXEDFILEINFO*>(lpvi);
						//lint -restore

						// Get translation info
						if (VerQueryValue(m_pVersionInfo, _T("\\VarFileInfo\\Translation"), &lpvi, &uLen) && uLen >= 4)	//lint !e1776 (Info -- Converting a string literal to char * is not const safe (arg. no. 2))
						{
							m_translation = *static_cast<TRANSLATION*>(lpvi);

							ATLTRACE("CModuleVersion::GetFileVersionInfoFromPathName(): code page = %d\n", m_translation.charset);
						}
						return dwSignature == VS_FFI_SIGNATURE;
					}


					/// \brief Read the specified field from the currently loaded version information.
					///
					/// \param	pszValueName		The name of the value to read (e.g. "FileVersion", "CompanyName" etc.)
					/// \return	CString				The value of the property, or an empty string if it does not exist.
					///
					CString	GetValue(LPCTSTR const pszValueName)
					{
						CString sVal;

						if (NULL != m_pVersionInfo)
						{
							// To get a string value must pass q query in the form:
							//
							//    "\StringFileInfo\<langID><codepage>\keyname"
							//
							// where <lang-codepage> is the languageID concatenated with the
							// code page, in hex. Wow.
							//
							CString sQuery;
							sQuery.Format(	_T("\\StringFileInfo\\%04x%04x\\%s"),
											m_translation.langID,
											m_translation.charset,
											pszValueName);

							LPTSTR pVal = NULL;
							UINT uLenVal = 0;

							//lint -save -e929 -e1773	(Note -- cast from pointer to pointer)
							//							(Info -- Attempt to cast away const (or volatile) )
							if (::VerQueryValue(m_pVersionInfo,
												const_cast<LPTSTR>(sQuery.GetString() ),
												reinterpret_cast<LPVOID*>(&pVal),
												&uLenVal))
							{
								sVal = pVal;
							}
							//lint -restore
						}
						return sVal;
					}


					/// \brief Get DLL Version by calling a DLL's DllGetVersion proc
					///
					static BOOL DllGetVersion(LPCTSTR const modulename, DLLVERSIONINFO& dvi)
					{
						const HINSTANCE hinst = LoadLibrary(modulename);
						if (NULL == 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.
						//
						//lint -save -e929 (Note -- cast from pointer to pointer)
						const DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hinst, "DllGetVersion");	//lint !e1924
						//lint -restore

						if (!pDllGetVersion)
							return FALSE;

						memset(&dvi, 0, sizeof(dvi));			 // clear
						dvi.cbSize = sizeof(dvi);				 // set size for Windows

						return SUCCEEDED((*pDllGetVersion)(&dvi));
					}
			};


			////lint -save -e955 -e761	(Note -- Parameter name missing from prototype for function 'DLLGETVERSIONPROC')
			////							(Info -- Redundant typedef 'DLLGETVERSIONPROC' previously declared at line 1323, file C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\include\shlwapi.h)
			///// \brief typedef for DllGetVersion proc
			/////
			//typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
			////lint -restore
		}
	}
}
#endif	//!__ModuleVersion_H__

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Authors

Anna-Jayne Metcalfe
Founder Riverblade Limited
United Kingdom United Kingdom
I haven't always written software for a living. When I graduated from Surrey University in 1989, it was with an Electronic Engineering degree, but unfortunately that never really gave me the opportunity to do anything particularly interesting (with the possible exception of designing Darth Vader's Codpiece * for the UK Army in 1990).
    * Also known as the Standard Army Bootswitch. But that's another story...
Since the opportunity arose to lead a software team developing C++ software for Avionic Test Systems in 1996, I've not looked back. More recently I've been involved in the development of subsea acoustic navigation systems, digital TV broadcast systems, port security/tracking systems, and most recently software development tools with my own company, Riverblade Ltd.
 
One of my personal specialities is IDE plug-in development. ResOrg was my first attempt at a plug-in, but my day to day work is with Visual Lint, an interactive code analysis tool environment with works within the Visual Studio and Eclipse IDEs or on build servers.
 
I love lots of things, but particularly music, photography and anything connected with history or engineering. I despise ignorant, intolerant and obstructive people - and it shows...I can be a bolshy cow if you wind me up the wrong way...Laugh | :laugh:
 
I'm currently based 15 minutes walk from the beach in Bournemouth on the south coast of England. Since I moved here I've grown to love the place - even if it is full of grockles in Summer!
Follow on   Twitter

-+- Beth Mackenzie -+-
Software Developer Riverblade Ltd
United Kingdom United Kingdom
I'm a software developer and/or tester with Riverblade Ltd (www.riverblade.co.uk) developing our core product range including our Visual Lint integration product and Lint Project Professional.
 
I incorporate a number of technologies into a daily basis including Windows API, C++ (VS2008), Managed C++, CLI, Databases, Java, JNI, Eclipse Framework, CDT and of course Visual Studio Extensibility (VSIP VSX).
 
In my spare time I enjoy cooking (prepping ingredients from scratch!), running, cycling, swimming, reading, interested in experimental electronic music (such as ClockDVA), movies, volunteering my IT skills where I can.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 29 Jan 2009
Article Copyright 2004 by Anna-Jayne Metcalfe, -+- Beth Mackenzie -+-
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid