forked from 0ad/0ad
dll_ver: move redirection enable/disable to wutil. add LoadLibraryEx to diagnose cause of GetFileVersionInfoSize failure.
wposix: assert it's initialized wsnd: cleanup This was SVN commit r5089.
This commit is contained in:
parent
1814d9175a
commit
ceee6e00bd
@ -17,66 +17,26 @@
|
||||
#include "lib/path_util.h"
|
||||
#include "win.h"
|
||||
#include "wutil.h"
|
||||
#include "winit.h"
|
||||
|
||||
#if MSC_VERSION
|
||||
#pragma comment(lib, "version.lib") // DLL version
|
||||
#endif
|
||||
|
||||
|
||||
#pragma SECTION_PRE_LIBC(B)
|
||||
WIN_REGISTER_FUNC(dll_ver_PreLibcInit);
|
||||
#pragma FORCE_INCLUDE(dll_ver_PreLibcInit)
|
||||
#pragma SECTION_RESTORE
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// temporarily disable and re-enable Wow64 file redirection.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Wow64 '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 redirection over the duration of get_ver.
|
||||
|
||||
static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID*) = 0;
|
||||
static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID) = 0;
|
||||
|
||||
static void ImportWow64Functions()
|
||||
{
|
||||
HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
|
||||
*(void**)&pWow64DisableWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64DisableWow64FsRedirection");
|
||||
*(void**)&pWow64RevertWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64RevertWow64FsRedirection");
|
||||
FreeLibrary(hKernel32Dll);
|
||||
}
|
||||
|
||||
static void DisableRedirection(PVOID& wasRedirectionEnabled)
|
||||
{
|
||||
// note: don't just check if the function pointers are valid. 32-bit
|
||||
// Vista includes them but isn't running Wow64, so calling the functions
|
||||
// would fail. since we have to check if actually on Wow64, there's no
|
||||
// more need to verify the pointers (their existence is implied).
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64DisableWow64FsRedirection(&wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
static void RevertRedirection(PVOID wasRedirectionEnabled)
|
||||
{
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64RevertWow64FsRedirection(wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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)
|
||||
{
|
||||
#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(module_path, 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(module_path, &unused);
|
||||
@ -114,13 +74,13 @@ static LibError get_ver(const char* module_path, char* out_ver, size_t out_ver_l
|
||||
WIN_SAVE_LAST_ERROR; // GetFileVersion*, Ver*
|
||||
{
|
||||
PVOID wasRedirectionEnabled;
|
||||
DisableRedirection(wasRedirectionEnabled);
|
||||
wutil_DisableWow64Redirection(wasRedirectionEnabled);
|
||||
{
|
||||
void* mem = NULL;
|
||||
ret = get_ver_impl(module_path, out_ver, out_ver_len, mem);
|
||||
free(mem);
|
||||
}
|
||||
RevertRedirection(wasRedirectionEnabled);
|
||||
wutil_RevertWow64Redirection(wasRedirectionEnabled);
|
||||
}
|
||||
WIN_RESTORE_LAST_ERROR;
|
||||
|
||||
@ -170,7 +130,7 @@ LibError dll_list_add(const char* name)
|
||||
}
|
||||
|
||||
// read file version.
|
||||
char dll_ver[128] = "unknown"; // enclosed in () below
|
||||
char dll_ver[500] = "unknown"; // enclosed in () below
|
||||
(void)get_ver(dll_name, dll_ver, sizeof(dll_ver));
|
||||
// if this fails, default is already set and we don't want to abort.
|
||||
|
||||
@ -197,13 +157,3 @@ LibError dll_list_add(const char* name)
|
||||
dll_list_pos = 0; // poison pill, prevent further calls
|
||||
WARN_RETURN(ERR::BUF_SIZE);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static LibError dll_ver_PreLibcInit()
|
||||
{
|
||||
ImportWow64Functions();
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ static void InitSysconf()
|
||||
|
||||
long sysconf(int name)
|
||||
{
|
||||
debug_assert(page_size); // must not be called before InitSysconf
|
||||
|
||||
switch(name)
|
||||
{
|
||||
case _SC_PAGESIZE:
|
||||
|
@ -58,43 +58,29 @@ EXTERN_C __declspec(dllimport) HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALL
|
||||
// note: OpenAL alGetString is worthless: it only returns OpenAL API version
|
||||
// and renderer (e.g. "Software").
|
||||
|
||||
// indicate if this directory entry is an OpenAL DLL.
|
||||
// (matches "*oal.dll" and "*OpenAL*", as with OpenAL router's search)
|
||||
static LibError IsOpenAlDll(const DirEnt* ent)
|
||||
{
|
||||
// not a file
|
||||
if(!DIRENT_IS_DIR(ent))
|
||||
return false;
|
||||
|
||||
// name doesn't match
|
||||
const size_t len = strlen(ent->name);
|
||||
const bool oal = len >= 7 && !strcasecmp(ent->name+len-7, "oal.dll");
|
||||
const bool openal = strstr(ent->name, "OpenAL") != 0;
|
||||
if(!oal && !openal)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ensures each OpenAL DLL is only listed once (even if present in several
|
||||
// directories on our search path).
|
||||
typedef std::set<std::string> StringSet;
|
||||
|
||||
// if this directory entry is an OpenAL DLL, add it to our list.
|
||||
// (matches "*oal.dll" and "*OpenAL*", as with OpenAL router's search)
|
||||
// called by add_oal_dlls_in_dir.
|
||||
//
|
||||
// note: we need the full DLL path for dll_list_add but DirEnt only gives us
|
||||
// the name. for efficiency, we append this in a PathPackage allocated by
|
||||
// add_oal_dlls_in_dir.
|
||||
static LibError add_if_oal_dll(const DirEnt* ent, PathPackage* pp, StringSet* dlls)
|
||||
{
|
||||
const char* fn = ent->name;
|
||||
|
||||
// skip non-files.
|
||||
if(!DIRENT_IS_DIR(ent))
|
||||
return INFO::OK;
|
||||
|
||||
// skip if not an OpenAL DLL.
|
||||
const size_t len = strlen(fn);
|
||||
const bool oal = len >= 7 && !strcasecmp(fn+len-7, "oal.dll");
|
||||
const bool openal = strstr(fn, "OpenAL") != 0;
|
||||
if(!oal && !openal)
|
||||
return INFO::OK;
|
||||
|
||||
// skip if already in StringSet (i.e. has already been dll_list_add-ed)
|
||||
std::pair<StringSet::iterator, bool> ret = dlls->insert(fn);
|
||||
if(!ret.second) // insert failed - element already there
|
||||
return INFO::OK;
|
||||
|
||||
RETURN_ERR(path_package_append_file(pp, fn));
|
||||
return dll_list_add(pp->path);
|
||||
}
|
||||
|
||||
|
||||
// find all OpenAL DLLs in a dir (via file_enum and add_if_oal_dll).
|
||||
// find all OpenAL DLLs in a dir (via file_enum and IsOpenAlDll).
|
||||
// call in library search order (exe dir, then win sys dir); otherwise,
|
||||
// DLLs in the executable's starting directory hide those of the
|
||||
// same name in the system directory.
|
||||
@ -102,19 +88,31 @@ static LibError add_if_oal_dll(const DirEnt* ent, PathPackage* pp, StringSet* dl
|
||||
// <dir>: no trailing.
|
||||
static LibError add_oal_dlls_in_dir(const char* dir, StringSet* dlls)
|
||||
{
|
||||
// note: dll_list_add requires the full DLL path but DirEnt only gives us
|
||||
// the name. for efficiency, we append this via PathPackage.
|
||||
PathPackage pp;
|
||||
RETURN_ERR(path_package_set_dir(&pp, dir));
|
||||
|
||||
DirIterator d;
|
||||
RETURN_ERR(dir_open(dir, &d));
|
||||
|
||||
DirEnt ent;
|
||||
for(;;) // instead of while to avoid warning
|
||||
{
|
||||
DirEnt ent;
|
||||
LibError err = dir_next_ent(&d, &ent);
|
||||
if(err != INFO::OK)
|
||||
break;
|
||||
(void)add_if_oal_dll(&ent, &pp, dlls);
|
||||
|
||||
if(!IsOpenAlDll(&ent))
|
||||
continue;
|
||||
|
||||
// already in StringSet (i.e. has already been dll_list_add-ed)
|
||||
std::pair<StringSet::iterator, bool> ret = dlls->insert(ent.name);
|
||||
if(!ret.second) // insert failed - element already there
|
||||
continue;
|
||||
|
||||
(void)path_package_append_file(&pp, ent.name);
|
||||
(void)dll_list_add(pp.path);
|
||||
}
|
||||
|
||||
(void)dir_close(&d);
|
||||
@ -128,17 +126,18 @@ static char ds_drv_path[MAX_PATH+1];
|
||||
|
||||
// store sound card name and path to DirectSound driver.
|
||||
// called for each DirectSound driver, but aborts after first valid driver.
|
||||
static BOOL CALLBACK ds_enum(void* UNUSED(guid), const char* description,
|
||||
static BOOL CALLBACK ds_enum(void* guid, const char* description,
|
||||
const char* module, void* UNUSED(ctx))
|
||||
{
|
||||
// skip first (dummy) entry, where description == "Primary Sound Driver".
|
||||
if(module[0] == '\0')
|
||||
// skip first dummy entry (description == "Primary Sound Driver")
|
||||
if(guid == NULL)
|
||||
return TRUE; // continue calling
|
||||
|
||||
strcpy_s(snd_card, SND_CARD_LEN, description);
|
||||
snprintf(ds_drv_path, ARRAY_SIZE(ds_drv_path), "%s\\drivers\\%s", win_sys_dir, module);
|
||||
// note: this directory is not in LoadLibrary's search list,
|
||||
|
||||
// note: $system\\drivers is not in LoadLibrary's search list,
|
||||
// so we have to give the full pathname.
|
||||
snprintf(ds_drv_path, ARRAY_SIZE(ds_drv_path), "%s\\drivers\\%s", win_sys_dir, module);
|
||||
|
||||
// we assume the first "driver name" (sound card) is the one we want;
|
||||
// stick with that and stop calling.
|
||||
|
@ -227,18 +227,30 @@ static void EnableLowFragmentationHeap()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wow64 detection
|
||||
// Wow64
|
||||
|
||||
// Wow64 '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, provide for temporarily disabling redirection.
|
||||
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID*) = 0;
|
||||
static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID) = 0;
|
||||
|
||||
static bool isWow64;
|
||||
|
||||
static void ImportWow64Functions()
|
||||
{
|
||||
HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
|
||||
*(void**)&pIsWow64Process = GetProcAddress(hKernel32Dll, "IsWow64Process");
|
||||
*(void**)&pWow64DisableWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64DisableWow64FsRedirection");
|
||||
*(void**)&pWow64RevertWow64FsRedirection = GetProcAddress(hKernel32Dll, "Wow64RevertWow64FsRedirection");
|
||||
FreeLibrary(hKernel32Dll);
|
||||
}
|
||||
|
||||
static void DetectWow64()
|
||||
{
|
||||
// import kernel32!IsWow64Process
|
||||
const HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
|
||||
BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
*(void**)&pIsWow64Process = GetProcAddress(hKernel32Dll, "IsWow64Process");
|
||||
FreeLibrary(hKernel32Dll);
|
||||
|
||||
// function not found => running on 32-bit Windows
|
||||
if(!pIsWow64Process)
|
||||
{
|
||||
@ -257,6 +269,26 @@ bool wutil_IsWow64()
|
||||
return isWow64;
|
||||
}
|
||||
|
||||
void wutil_DisableWow64Redirection(void*& wasRedirectionEnabled)
|
||||
{
|
||||
// note: don't just check if the function pointers are valid. 32-bit
|
||||
// Vista includes them but isn't running Wow64, so calling the functions
|
||||
// would fail. since we have to check if actually on Wow64, there's no
|
||||
// more need to verify the pointers (their existence is implied).
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64DisableWow64FsRedirection(&wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
void wutil_RevertWow64Redirection(void* wasRedirectionEnabled)
|
||||
{
|
||||
if(!wutil_IsWow64())
|
||||
return;
|
||||
BOOL ok = pWow64RevertWow64FsRedirection(wasRedirectionEnabled);
|
||||
WARN_IF_FALSE(ok);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -272,6 +304,7 @@ static LibError wutil_PreLibcInit()
|
||||
|
||||
GetDirectories();
|
||||
|
||||
ImportWow64Functions();
|
||||
DetectWow64();
|
||||
|
||||
return INFO::OK;
|
||||
|
@ -95,9 +95,12 @@ extern char win_exe_dir[MAX_PATH+1];
|
||||
|
||||
|
||||
//
|
||||
// Wow64 detection
|
||||
// Wow64
|
||||
//
|
||||
|
||||
extern bool wutil_IsWow64();
|
||||
extern void wutil_DisableWow64Redirection(void*& wasRedirectionEnabled);
|
||||
extern void wutil_RevertWow64Redirection(void* wasRedirectionEnabled);
|
||||
|
||||
|
||||
#endif // #ifndef INCLUDED_WUTIL
|
||||
|
Loading…
Reference in New Issue
Block a user