From ceee6e00bdde9686abb2e61af565e28e7c95918a Mon Sep 17 00:00:00 2001 From: janwas Date: Thu, 24 May 2007 12:31:16 +0000 Subject: [PATCH] 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. --- source/lib/sysdep/win/dll_ver.cpp | 72 ++++------------------ source/lib/sysdep/win/wposix/wposix.cpp | 2 + source/lib/sysdep/win/wsnd.cpp | 79 ++++++++++++------------- source/lib/sysdep/win/wutil.cpp | 47 ++++++++++++--- source/lib/sysdep/win/wutil.h | 5 +- 5 files changed, 96 insertions(+), 109 deletions(-) diff --git a/source/lib/sysdep/win/dll_ver.cpp b/source/lib/sysdep/win/dll_ver.cpp index 4f50dba1cb..0a7c94b301 100644 --- a/source/lib/sysdep/win/dll_ver.cpp +++ b/source/lib/sysdep/win/dll_ver.cpp @@ -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; -} diff --git a/source/lib/sysdep/win/wposix/wposix.cpp b/source/lib/sysdep/win/wposix/wposix.cpp index fff59e3900..1fc5dc0530 100644 --- a/source/lib/sysdep/win/wposix/wposix.cpp +++ b/source/lib/sysdep/win/wposix/wposix.cpp @@ -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: diff --git a/source/lib/sysdep/win/wsnd.cpp b/source/lib/sysdep/win/wsnd.cpp index 35418f0971..c5e3e0eaa8 100644 --- a/source/lib/sysdep/win/wsnd.cpp +++ b/source/lib/sysdep/win/wsnd.cpp @@ -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 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 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 // : 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 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. diff --git a/source/lib/sysdep/win/wutil.cpp b/source/lib/sysdep/win/wutil.cpp index 44141db3e1..232c47dd08 100644 --- a/source/lib/sysdep/win/wutil.cpp +++ b/source/lib/sysdep/win/wutil.cpp @@ -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; diff --git a/source/lib/sysdep/win/wutil.h b/source/lib/sysdep/win/wutil.h index ca3583768d..cba3d7a2db 100644 --- a/source/lib/sysdep/win/wutil.h +++ b/source/lib/sysdep/win/wutil.h @@ -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