1
0
forked from 0ad/0ad

# fix DLL version retrieval on Win64

fixes #125

I now have Win64, so this problem can be reproduced :D

windows is 'helpful' and transparently redirects accesses to
$winsysdir/drivers. grr. disable that on win64 to solve this problem.
thanks for the report!

This was SVN commit r4590.
This commit is contained in:
janwas 2006-10-20 20:33:38 +00:00
parent b2b5d4aa57
commit fc026b6f30

View File

@ -33,54 +33,80 @@
#pragma comment(lib, "version.lib") // DLL version
#endif
// helper function that does all the work; caller wraps it and takes care of
// undoing various operations if we fail midway.
static LibError get_ver_impl(const char* module_path, char* out_ver, size_t out_ver_len, void*& mem)
{
// determine size of and allocate memory for version information.
DWORD unused;
const DWORD ver_size = GetFileVersionInfoSize(module_path, &unused);
if(!ver_size)
WARN_RETURN(ERR::FAIL);
mem = malloc(ver_size);
if(!mem)
WARN_RETURN(ERR::NO_MEM);
if(!GetFileVersionInfo(module_path, 0, ver_size, mem))
WARN_RETURN(ERR::FAIL);
u16* lang; // -> 16 bit language ID, 16 bit codepage
uint lang_len;
const BOOL ok = VerQueryValue(mem, "\\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, subblock, (void**)&in_ver, &in_ver_len))
WARN_RETURN(ERR::FAIL);
strcpy_s(out_ver, out_ver_len, in_ver);
return INFO::OK;
}
// get version information for the specified DLL.
static LibError get_ver(const char* module_path, char* out_ver, size_t out_ver_len)
{
WIN_SAVE_LAST_ERROR; // GetFileVersion*, Ver*
// determine size of and allocate memory for version information.
DWORD unused;
const DWORD ver_size = GetFileVersionInfoSize(module_path, &unused);
if(!ver_size)
// WinXP x64 'helpfully' redirects all 32-bit apps' accesses of
// %windir\\system32\\drivers to %windir\\system32\\drivers\\SysWOW64.
// that's bad, because the actual drivers are not in the subdirectory.
// to work around this, we disable the redirection over the duration of
// this call. if not on a 64-bit OS (i.e. these entry points aren't
// found), no action need be taken.
HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID*) = 0;
BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID) = 0;
*(void**)&pWow64DisableWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64DisableWow64FsRedirection");
*(void**)&pWow64RevertWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64RevertWow64FsRedirection");
PVOID old_value = 0;
if(pWow64DisableWow64FsRedirection)
{
wchar_t buf[1000];
swprintf(buf, 1000, L"path: %hs; GLE: %08X", module_path, GetLastError());
DISPLAY_ERROR(buf);
return ERR::FAIL;
// WARN_RETURN(ERR::FAIL);
BOOL ok = pWow64DisableWow64FsRedirection(&old_value);
WARN_IF_FALSE(ok);
}
void* buf = malloc(ver_size);
if(!buf)
WARN_RETURN(ERR::NO_MEM);
LibError ret = ERR::FAIL; // single point of exit (for free())
void* mem;
LibError ret = get_ver_impl(module_path, out_ver, out_ver_len, mem);
free(mem);
if(GetFileVersionInfo(module_path, 0, ver_size, buf))
if(pWow64DisableWow64FsRedirection)
{
u16* lang; // -> 16 bit language ID, 16 bit codepage
uint lang_len;
const BOOL ok = VerQueryValue(buf, "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
if(ok && lang && lang_len == 4)
{
char subblock[64];
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\FileVersion", lang[0], lang[1]);
const char* in_ver;
uint in_ver_len;
if(VerQueryValue(buf, subblock, (void**)&in_ver, &in_ver_len))
{
strcpy_s(out_ver, out_ver_len, in_ver);
ret = INFO::OK;
}
}
BOOL ok = pWow64RevertWow64FsRedirection(old_value);
WARN_IF_FALSE(ok);
}
free(buf);
FreeLibrary(hKernel32Dll);
WIN_RESTORE_LAST_ERROR;
if(ret != INFO::OK)
out_ver[0] = '\0';
return ret;
}
//
// build a string containing DLL filename(s) and their version info.
//