Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
wdll_ver.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * return DLL version information.
25  */
26 
27 #include "precompiled.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 
33 #include "lib/sysdep/os/win/win.h"
35 
37 
38 #if MSC_VERSION
39 #pragma comment(lib, "version.lib") // DLL version
40 #endif
41 
42 
43 //-----------------------------------------------------------------------------
44 
45 static Status ReadVersionString(const OsPath& modulePathname, wchar_t* out_ver, size_t out_ver_len)
46 {
47  WinScopedPreserveLastError s; // GetFileVersion*, Ver*
48 
49  // determine size of and allocate memory for version information.
50  DWORD unused;
51  const DWORD ver_size = GetFileVersionInfoSizeW(OsString(modulePathname).c_str(), &unused); // [bytes]
52  if(!ver_size)
53  {
54  // check if the failure is due to not finding modulePathname
55  // (necessary since GetFileVersionInfoSize doesn't SetLastError)
56  HMODULE hModule = LoadLibraryExW(OsString(modulePathname).c_str(), 0, LOAD_LIBRARY_AS_DATAFILE);
57  if(!hModule)
58  return ERR::FAIL; // NOWARN (file not found - due to FS redirection?)
59  FreeLibrary(hModule);
60  return ERR::NOT_SUPPORTED; // NOWARN (module apparently lacks version information)
61  }
62 
63  shared_ptr<u8> mem = Allocate(ver_size);
64  if(!GetFileVersionInfoW(OsString(modulePathname).c_str(), 0, ver_size, mem.get()))
66 
67  u16* lang; // -> 16 bit language ID, 16 bit codepage
68  UINT lang_len;
69  const BOOL ok = VerQueryValueW(mem.get(), L"\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
70  if(!ok || !lang || lang_len != 4)
72 
73  wchar_t subblock[64];
74  swprintf_s(subblock, ARRAY_SIZE(subblock), L"\\StringFileInfo\\%04X%04X\\FileVersion", lang[0], lang[1]);
75  const wchar_t* in_ver;
76  UINT in_ver_len;
77  if(!VerQueryValueW(mem.get(), subblock, (void**)&in_ver, &in_ver_len))
79 
80  wcscpy_s(out_ver, out_ver_len, in_ver);
81  return INFO::OK;
82 }
83 
84 
85 void wdll_ver_Append(const OsPath& pathname, VersionList& list)
86 {
87  if(pathname.empty())
88  return; // avoid error in ReadVersionString
89 
90  // pathname may not have an extension (e.g. driver names from the
91  // registry). note that always appending ".dll" would be incorrect
92  // since some have ".sys" extension.
93  OsPath modulePathname(pathname);
94  if(modulePathname.Extension() == "")
95  modulePathname = modulePathname.ChangeExtension(L".dll");
96  const OsPath moduleName(modulePathname.Filename());
97 
98  // read file version. try this with and without FS redirection since
99  // pathname might assume both.
100  wchar_t versionString[500]; // enclosed in () below
101  if(ReadVersionString(modulePathname, versionString, ARRAY_SIZE(versionString)) != INFO::OK)
102  {
104  // still failed; avoid polluting list with DLLs that don't exist
105  // (requiring callers to check for their existence beforehand would be
106  // onerous and unreliable)
107  if(ReadVersionString(modulePathname, versionString, ARRAY_SIZE(versionString)) != INFO::OK)
108  return;
109  }
110 
111  if(!list.empty())
112  list += L", ";
113 
114  list += moduleName.Filename().string();
115  list += L" (";
116  list += versionString;
117  list += L")";
118 }
shared_ptr< u8 > Allocate(size_t size)
Definition: shared_ptr.cpp:55
const Status _4
Definition: status.h:444
Path Filename() const
Definition: path.h:158
static Status ReadVersionString(const OsPath &modulePathname, wchar_t *out_ver, size_t out_ver_len)
Definition: wdll_ver.cpp:45
const Status OK
Definition: status.h:386
some WinAPI functions SetLastError(0) on success, which is bad because it can hide previous errors...
Definition: wutil.h:119
const Status _3
Definition: status.h:443
int swprintf_s(wchar_t *buf, size_t max_chars, const wchar_t *fmt,...) WPRINTF_ARGS(3)
int BOOL
Definition: wgl.h:51
#define ARRAY_SIZE(name)
int wcscpy_s(wchar_t *dst, size_t max_dst_chars, const wchar_t *src)
const Status NOT_SUPPORTED
Definition: status.h:429
void wdll_ver_Append(const OsPath &pathname, VersionList &list)
Read DLL version information and append it to a string.
Definition: wdll_ver.cpp:85
Definition: path.h:75
const Status _5
Definition: status.h:445
unsigned long DWORD
Definition: wgl.h:56
i64 Status
Error handling system.
Definition: status.h:171
std::wstring VersionList
Definition: wdll_ver.h:32
#define u16
Definition: types.h:40
bool empty() const
Definition: path.h:118
Path ChangeExtension(Path extension) const
Definition: path.h:185
Path Extension() const
Definition: path.h:176
#define WARN_RETURN(status)
Definition: status.h:255
unsigned int UINT
Definition: wgl.h:54
const Status FAIL
Definition: status.h:406
static std::string OsString(const OsPath &path)
Definition: os_path.h:42