1 ////////////////////////////////////////////////////////////////
2 // 1998 Microsoft Systems Journal
3 // If this code works, it was written by Paul DiLascia.
4 // If not, I don't know who wrote it.
6 // CModuleVersion provides an easy way to get version info
7 // for a module.(DLL or EXE).
10 #include "UIModulVer.h"
12 CModuleVersion::CModuleVersion()
14 m_pVersionInfo = NULL; // raw version info data
18 // Destroy: delete version info
20 CModuleVersion::~CModuleVersion()
22 delete [] m_pVersionInfo;
26 // Get file version info for a given module
27 // Allocates storage for all info, fills "this" with
28 // VS_FIXEDFILEINFO, and sets codepage.
30 BOOL CModuleVersion::GetFileVersionInfo(LPCTSTR modulename)
32 m_translation.charset = 1252; // default = ANSI code page
33 memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO));
35 CLoadLibrary lib(modulename);
38 TCHAR filename[_MAX_PATH];
39 HMODULE hModule = ::GetModuleHandle(modulename);
40 if (hModule==NULL && modulename!=NULL)
43 // get module file name
44 DWORD len = GetModuleFileName(hModule, filename,
45 sizeof(filename)/sizeof(filename[0]));
49 // read file version info
50 DWORD dwDummyHandle; // will always be set to zero
51 len = GetFileVersionInfoSize(filename, &dwDummyHandle);
56 delete m_pVersionInfo;
57 m_pVersionInfo = new BYTE[len]; // allocate version info
58 if (!::GetFileVersionInfo(filename, 0, len, m_pVersionInfo))
63 if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &iLen))
66 // copy fixed info to myself, which am derived from VS_FIXEDFILEINFO
67 *(VS_FIXEDFILEINFO*)this = *(VS_FIXEDFILEINFO*)lpvi;
69 // Get translation info
70 // Note: VerQueryValue could return a value > 4, in which case
71 // mulitple languages are supported and VerQueryValue returns an
72 // array of langID/codepage pairs and you have to decide which to use.
73 if (VerQueryValue(m_pVersionInfo,
74 _T("\\VarFileInfo\\Translation"), &lpvi, &iLen) && iLen >= 4) {
75 m_translation = *(TRANSLATION*)lpvi;
76 TRACE1("code page = %d\n", m_translation.charset);
79 return dwSignature == VS_FFI_SIGNATURE;
83 // Get string file info.
84 // Key name is something like "CompanyName".
85 // returns the value as a CString.
87 CString CModuleVersion::GetValue(LPCTSTR lpKeyName)
92 // To get a string value must pass query in the form
94 // "\StringFileInfo\<langID><codepage>\keyname"
96 // where <lang-codepage> is the languageID concatenated with the
97 // code page, in hex. Wow.
100 query.Format(_T("\\StringFileInfo\\%04x%04x\\%s"),
101 m_translation.langID,
102 m_translation.charset,
107 if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)query,
108 (LPVOID*)&pVal, &iLenVal)) {
116 // typedef for DllGetVersion proc
117 typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
120 // Get DLL Version by calling DLL's DllGetVersion proc
122 BOOL CModuleVersion::DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi)
124 CLoadLibrary lib(modulename);
128 // Must use GetProcAddress because the DLL might not implement
129 // DllGetVersion. Depending upon the DLL, the lack of implementation of the
130 // function may be a version marker in itself.
132 DLLGETVERSIONPROC pDllGetVersion =
133 (DLLGETVERSIONPROC)GetProcAddress(lib, "DllGetVersion");
137 memset(&dvi, 0, sizeof(dvi)); // clear
138 dvi.cbSize = sizeof(dvi); // set size for Windows
140 return SUCCEEDED((*pDllGetVersion)(&dvi));