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:
janwas 2007-05-24 12:31:16 +00:00
parent 1814d9175a
commit ceee6e00bd
5 changed files with 96 additions and 109 deletions

View File

@ -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;
}

View File

@ -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:

View File

@ -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.

View File

@ -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;

View File

@ -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