update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / Seashell / SeaShellExt / UIModulVer.cpp
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.
5 //
6 // CModuleVersion provides an easy way to get version info
7 // for a module.(DLL or EXE).
8 //
9 #include "StdAfx.h"
10 #include "UIModulVer.h"
11
12 CModuleVersion::CModuleVersion()
13 {
14         m_pVersionInfo = NULL;                          // raw version info data 
15 }
16
17 //////////////////
18 // Destroy: delete version info
19 //
20 CModuleVersion::~CModuleVersion()
21 {
22         delete [] m_pVersionInfo;
23 }
24
25 //////////////////
26 // Get file version info for a given module
27 // Allocates storage for all info, fills "this" with
28 // VS_FIXEDFILEINFO, and sets codepage.
29 //
30 BOOL CModuleVersion::GetFileVersionInfo(LPCTSTR modulename)
31 {
32         m_translation.charset = 1252;           // default = ANSI code page
33         memset((VS_FIXEDFILEINFO*)this, 0, sizeof(VS_FIXEDFILEINFO));
34
35         CLoadLibrary lib(modulename);
36
37         // get module handle
38         TCHAR filename[_MAX_PATH];
39         HMODULE hModule = ::GetModuleHandle(modulename);
40         if (hModule==NULL && modulename!=NULL) 
41                 return FALSE;
42
43         // get module file name
44         DWORD len = GetModuleFileName(hModule, filename,
45                 sizeof(filename)/sizeof(filename[0]));
46         if (len <= 0)
47                 return FALSE;
48
49         // read file version info
50         DWORD dwDummyHandle; // will always be set to zero
51         len = GetFileVersionInfoSize(filename, &dwDummyHandle);
52         if (len <= 0)
53                 return FALSE;
54
55         if (m_pVersionInfo)
56                 delete m_pVersionInfo;
57         m_pVersionInfo = new BYTE[len]; // allocate version info
58         if (!::GetFileVersionInfo(filename, 0, len, m_pVersionInfo))
59                 return FALSE;
60
61         LPVOID lpvi;
62         UINT iLen;
63         if (!VerQueryValue(m_pVersionInfo, _T("\\"), &lpvi, &iLen))
64                 return FALSE;
65
66         // copy fixed info to myself, which am derived from VS_FIXEDFILEINFO
67         *(VS_FIXEDFILEINFO*)this = *(VS_FIXEDFILEINFO*)lpvi;
68
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);
77         }
78
79         return dwSignature == VS_FFI_SIGNATURE;
80 }
81
82 //////////////////
83 // Get string file info.
84 // Key name is something like "CompanyName".
85 // returns the value as a CString.
86 //
87 CString CModuleVersion::GetValue(LPCTSTR lpKeyName)
88 {
89         CString sVal;
90         if (m_pVersionInfo) {
91
92                 // To get a string value must pass query in the form
93                 //
94                 //    "\StringFileInfo\<langID><codepage>\keyname"
95                 //
96                 // where <lang-codepage> is the languageID concatenated with the
97                 // code page, in hex. Wow.
98                 //
99                 CString query;
100                 query.Format(_T("\\StringFileInfo\\%04x%04x\\%s"),
101                         m_translation.langID,
102                         m_translation.charset,
103                         lpKeyName);
104
105                 LPCTSTR pVal;
106                 UINT iLenVal;
107                 if (VerQueryValue(m_pVersionInfo, (LPTSTR)(LPCTSTR)query,
108                                 (LPVOID*)&pVal, &iLenVal)) {
109
110                         sVal = pVal;
111                 }
112         }
113         return sVal;
114 }
115
116 // typedef for DllGetVersion proc
117 typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
118
119 /////////////////
120 // Get DLL Version by calling DLL's DllGetVersion proc
121 //
122 BOOL CModuleVersion::DllGetVersion(LPCTSTR modulename, DLLVERSIONINFO& dvi)
123 {
124         CLoadLibrary lib(modulename);
125         if (!lib)
126                 return FALSE;
127
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.
131         //
132         DLLGETVERSIONPROC pDllGetVersion =
133                 (DLLGETVERSIONPROC)GetProcAddress(lib, "DllGetVersion");
134         if (!pDllGetVersion)
135                 return FALSE;
136
137         memset(&dvi, 0, sizeof(dvi));                    // clear
138         dvi.cbSize = sizeof(dvi);                                // set size for Windows
139
140         return SUCCEEDED((*pDllGetVersion)(&dvi));
141 }