mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-07 07:25:47 -07:00
- directoryPosix: replace most methods with boost filesystem (but not all: the latter cannot efficiently enumerate files AND query their size/mtime) - AllocatorChecker: better name for member functions - file: move the File class here - trace: bugfix - io: move UnalignedWriter to write_buffer.cpp (basically the same thing) - vfs: remove unnecessary "vfs" warts from variable names - vfs_tree: VfsFile now stores single Name/Size/MTime fields instead of the FileInfo record (less clunky) - vfs_path: use boost filesystem's version of the basename/extension functions - lf_alloc: remove (no longer necessary, won't be finished - not worth the trouble) - path_util: remove path_foreach_component (replaced by better path traversal logic) and PathPackage (obsoleted by fs::path) ! resource loading code now receives VfsPath as its filename. there is also OsPath (native absolute path) and Path (relative to binaries/data) - tex is now independent of file loading code; it just en/decodes in-memory buffers - wdll_ver: clean up, use smart pointer to simplify bailout code - wsdl: remove nonexistent failure path from calc_gamma (cruised by here because SDL_SetGamme is failing once after a cold boot at work) - wsnd: simplify OpenAL DLL search, use boost::filesystem - wutil: Wow64 redirection is now packaged in a (RAII) class This was SVN commit r5525.
134 lines
4.1 KiB
C++
134 lines
4.1 KiB
C++
/**
|
|
* =========================================================================
|
|
* File : wdll_ver.cpp
|
|
* Project : 0 A.D.
|
|
* Description : return DLL version information.
|
|
* =========================================================================
|
|
*/
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
#include "precompiled.h"
|
|
#include "wdll_ver.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "win.h"
|
|
#include "wutil.h"
|
|
|
|
#include "lib/file/io/io.h" // io_Allocate
|
|
|
|
#if MSC_VERSION
|
|
#pragma comment(lib, "version.lib") // DLL version
|
|
#endif
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static LibError ReadVersionString(const OsPath& modulePathname_, char* out_ver, size_t out_ver_len)
|
|
{
|
|
WIN_SAVE_LAST_ERROR; // GetFileVersion*, Ver*
|
|
WinScopedDisableWow64Redirection noRedirect;
|
|
|
|
const std::string modulePathname = modulePathname_.external_file_string();
|
|
|
|
#ifndef NDEBUG
|
|
// make sure the file exists (rules out that problem as a cause of
|
|
// GetFileVersionInfoSize failing, since it doesn't SetLastError)
|
|
HMODULE hModule = LoadLibraryEx(modulePathname.c_str(), 0, LOAD_LIBRARY_AS_DATAFILE);
|
|
debug_assert(hModule != 0);
|
|
FreeLibrary(hModule);
|
|
#endif
|
|
|
|
// determine size of and allocate memory for version information.
|
|
DWORD unused;
|
|
const DWORD ver_size = GetFileVersionInfoSize(modulePathname.c_str(), &unused);
|
|
if(!ver_size)
|
|
WARN_RETURN(ERR::FAIL);
|
|
|
|
shared_ptr<u8> mem = io_Allocate(ver_size);
|
|
if(!GetFileVersionInfo(modulePathname.c_str(), 0, ver_size, mem.get()))
|
|
WARN_RETURN(ERR::FAIL);
|
|
|
|
u16* lang; // -> 16 bit language ID, 16 bit codepage
|
|
uint lang_len;
|
|
const BOOL ok = VerQueryValue(mem.get(), "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
|
|
if(!ok || !lang || lang_len != 4)
|
|
WARN_RETURN(ERR::FAIL);
|
|
|
|
char subblock[64];
|
|
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\FileVersion", lang[0], lang[1]);
|
|
const char* in_ver;
|
|
uint in_ver_len;
|
|
if(!VerQueryValue(mem.get(), subblock, (void**)&in_ver, &in_ver_len))
|
|
WARN_RETURN(ERR::FAIL);
|
|
|
|
strcpy_s(out_ver, out_ver_len, in_ver);
|
|
|
|
WIN_RESTORE_LAST_ERROR;
|
|
return INFO::OK;
|
|
}
|
|
|
|
//
|
|
// build a string containing DLL filename(s) and their version info.
|
|
//
|
|
|
|
static char* ver_list_buf;
|
|
static size_t ver_list_chars;
|
|
static char* ver_list_pos;
|
|
|
|
// set output buffer into which DLL names and their versions will be written.
|
|
void wdll_ver_list_init(char* buf, size_t chars)
|
|
{
|
|
ver_list_pos = ver_list_buf = buf;
|
|
ver_list_chars = chars;
|
|
}
|
|
|
|
|
|
// read DLL file version and append that and its name to the list.
|
|
//
|
|
// name should preferably be the complete path to DLL, to make sure
|
|
// we don't inadvertently load another one on the library search path.
|
|
// we add the .dll extension if necessary.
|
|
LibError wdll_ver_list_add(const OsPath& pathname)
|
|
{
|
|
// not be called before wdll_ver_list_init or after failure
|
|
if(!ver_list_pos)
|
|
WARN_RETURN(ERR::LOGIC);
|
|
|
|
// pathname may not have an extension (e.g. driver names from the
|
|
// registry). note that always appending ".dll" would be incorrect
|
|
// since some have ".sys" extension.
|
|
OsPath modulePathname(pathname);
|
|
if(fs::extension(modulePathname).empty())
|
|
modulePathname = fs::change_extension(modulePathname, ".dll");
|
|
|
|
// read file version.
|
|
// (note: we can ignore the return value since the default
|
|
// text has already been set)
|
|
char versionString[500] = "unknown"; // enclosed in () below
|
|
(void)ReadVersionString(modulePathname, versionString, ARRAY_SIZE(versionString));
|
|
|
|
// reserve enough room for subsequent comma and "..." strings.
|
|
const ssize_t max_chars_to_write = (ssize_t)ver_list_chars - (ver_list_pos-ver_list_buf) - 10;
|
|
|
|
// not first time: prepend comma to string (room was reserved above).
|
|
if(ver_list_pos != ver_list_buf)
|
|
ver_list_pos += sprintf(ver_list_pos, ", ");
|
|
|
|
// extract filename.
|
|
const std::string moduleName(modulePathname.leaf());
|
|
int len = snprintf(ver_list_pos, max_chars_to_write, "%s (%s)", moduleName.c_str(), versionString);
|
|
// success
|
|
if(len > 0)
|
|
{
|
|
ver_list_pos += len;
|
|
return INFO::OK;
|
|
}
|
|
|
|
// didn't fit; complain
|
|
sprintf(ver_list_pos, "..."); // (room was reserved above)
|
|
ver_list_pos = 0; // poison pill, prevent further calls
|
|
WARN_RETURN(ERR::BUF_SIZE);
|
|
}
|