X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d6f2a8911e509fd9e61f881cc881a97f5aa05ae8..e8481866872d3eec6e0ce1fa7eab856abff26c34:/src/msw/dlmsw.cpp diff --git a/src/msw/dlmsw.cpp b/src/msw/dlmsw.cpp index 39830797dc..00cd88b5cd 100644 --- a/src/msw/dlmsw.cpp +++ b/src/msw/dlmsw.cpp @@ -1,10 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/dlmsw.cpp +// Name: src/msw/dlmsw.cpp // Purpose: Win32-specific part of wxDynamicLibrary and related classes // Author: Vadim Zeitlin -// Modified by: +// Modified by: Suzumizaki-kimitaka 2013-04-09 // Created: 2005-01-10 (partly extracted from common/dynlib.cpp) -// RCS-ID: $Id$ // Copyright: (c) 1998-2005 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -27,8 +26,12 @@ #include "wx/msw/private.h" #include "wx/msw/debughlp.h" +#include "wx/filename.h" -const wxString wxDynamicLibrary::ms_dllext(_T(".dll")); +// defined for TDM's GCC/mingw32 +#ifndef PCTSTR +#define PCTSTR LPCTSTR +#endif // ---------------------------------------------------------------------------- // private classes @@ -65,7 +68,7 @@ private: wxDynamicLibrary m_dll; - DECLARE_NO_COPY_CLASS(wxVersionDLL) + wxDECLARE_NO_COPY_CLASS(wxVersionDLL); }; // class used to create wxDynamicLibraryDetails objects @@ -79,74 +82,10 @@ public: wxVersionDLL *verDLL; }; - // the declared type of the first EnumModulesProc() parameter changed in - // recent SDK versions and is no PCSTR instead of old PSTR, we know that - // it's const in version 11 and non-const in version 8 included with VC8 - // (and earlier), suppose that it's only changed in version 11 - #if defined(API_VERSION_NUMBER) && API_VERSION_NUMBER >= 11 - typedef PCSTR NameStr_t; - #else - typedef PSTR NameStr_t; - #endif - - // TODO: fix EnumerateLoadedModules() to use EnumerateLoadedModules64() - #ifdef __WIN64__ - typedef DWORD64 DWORD_32_64; - #else - typedef DWORD DWORD_32_64; - #endif - static BOOL CALLBACK - EnumModulesProc(NameStr_t name, DWORD_32_64 base, ULONG size, void *data); + EnumModulesProc(PCTSTR name, DWORD64 base, ULONG size, PVOID data); }; -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- - -// return the module handle for the given base name -static -HMODULE wxGetModuleHandle(const char *name, void *addr) -{ - // we want to use GetModuleHandleEx() instead of usual GetModuleHandle() - // because the former works correctly for comctl32.dll while the latter - // returns NULL when comctl32.dll version 6 is used under XP (note that - // GetModuleHandleEx() is only available under XP and later, coincidence?) - - // check if we can use GetModuleHandleEx - typedef BOOL (WINAPI *GetModuleHandleEx_t)(DWORD, LPCSTR, HMODULE *); - - static const GetModuleHandleEx_t INVALID_FUNC_PTR = (GetModuleHandleEx_t)-1; - - static GetModuleHandleEx_t s_pfnGetModuleHandleEx = INVALID_FUNC_PTR; - if ( s_pfnGetModuleHandleEx == INVALID_FUNC_PTR ) - { - wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM); - s_pfnGetModuleHandleEx = - (GetModuleHandleEx_t)dll.RawGetSymbol(_T("GetModuleHandleExA")); - - // dll object can be destroyed, kernel32.dll won't be unloaded anyhow - } - - // get module handle from its address - if ( s_pfnGetModuleHandleEx ) - { - // flags are GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | - // GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS - HMODULE hmod; - if ( s_pfnGetModuleHandleEx(6, (char *)addr, &hmod) && hmod ) - return hmod; - } - - // Windows CE only has Unicode API, so even we have an ANSI string here, we - // still need to use GetModuleHandleW() there -#ifdef __WXWINCE__ - return ::GetModuleHandleW(wxConvLibc.cMB2WC(name).data()); -#else - return ::GetModuleHandleA((char *)name); -#endif -} - // ============================================================================ // wxVersionDLL implementation // ============================================================================ @@ -161,7 +100,7 @@ wxVersionDLL::wxVersionDLL() // handle it wxLogNull noLog; - if ( m_dll.Load(_T("version.dll"), wxDL_VERBATIM) ) + if ( m_dll.Load(wxT("version.dll"), wxDL_VERBATIM) ) { // the functions we load have either 'A' or 'W' suffix depending on // whether we're in ANSI or Unicode build @@ -172,7 +111,7 @@ wxVersionDLL::wxVersionDLL() #endif // UNICODE/ANSI #define LOAD_VER_FUNCTION(name) \ - m_pfn ## name = (name ## _t)m_dll.GetSymbol(_T(#name SUFFIX)); \ + m_pfn ## name = (name ## _t)m_dll.GetSymbol(wxT(#name SUFFIX)); \ if ( !m_pfn ## name ) \ { \ m_dll.Unload(); \ @@ -194,7 +133,7 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const wxString ver; if ( m_dll.IsLoaded() ) { - wxChar *pc = wx_const_cast(wxChar *, filename.wx_str()); + wxChar *pc = const_cast((const wxChar*) filename.t_str()); DWORD dummy; DWORD sizeVerInfo = m_pfnGetFileVersionInfoSize(pc, &dummy); @@ -205,10 +144,13 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const { void *pVer; UINT sizeInfo; - if ( m_pfnVerQueryValue(buf.data(), _T("\\"), &pVer, &sizeInfo) ) + if ( m_pfnVerQueryValue(buf.data(), + const_cast(wxT("\\")), + &pVer, + &sizeInfo) ) { VS_FIXEDFILEINFO *info = (VS_FIXEDFILEINFO *)pVer; - ver.Printf(_T("%d.%d.%d.%d"), + ver.Printf(wxT("%d.%d.%d.%d"), HIWORD(info->dwFileVersionMS), LOWORD(info->dwFileVersionMS), HIWORD(info->dwFileVersionLS), @@ -228,22 +170,30 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const /* static */ BOOL CALLBACK -wxDynamicLibraryDetailsCreator::EnumModulesProc(NameStr_t name, - DWORD_32_64 base, +wxDynamicLibraryDetailsCreator::EnumModulesProc(PCTSTR name, + DWORD64 base, ULONG size, - void *data) + PVOID data) { EnumModulesProcParams *params = (EnumModulesProcParams *)data; wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails; // fill in simple properties - details->m_name = wxString::FromAscii(name); - details->m_address = wx_reinterpret_cast(void *, base); +#ifdef UNICODE + details->m_name = name; +#else + details->m_name = wxString(name, wxConvLocal); +#endif + details->m_address = wxUIntToPtr(base); details->m_length = size; // to get the version, we first need the full path - HMODULE hmod = wxGetModuleHandle(name, (void *)base); + const HMODULE hmod = wxDynamicLibrary::MSWGetModuleHandle + ( + details->m_name, + details->m_address + ); if ( hmod ) { wxString fullname = wxGetFullModuleName(hmod); @@ -277,11 +227,62 @@ wxDllType wxDynamicLibrary::GetProgramHandle() // loading/unloading DLLs // ---------------------------------------------------------------------------- +#ifndef MAX_PATH + #define MAX_PATH 260 // from VC++ headers +#endif + /* static */ wxDllType -wxDynamicLibrary::RawLoad(const wxString& libname, int WXUNUSED(flags)) +wxDynamicLibrary::RawLoad(const wxString& libname, int flags) { - return ::LoadLibrary(libname.wx_str()); + if (flags & wxDL_GET_LOADED) + return ::GetModuleHandle(libname.t_str()); + + // Explicitly look in the same path as where the main wx HINSTANCE module + // is located (usually the executable or the DLL that uses wx). Normally + // this is automatically part of the default search path but in some cases + // it may not be, such as when the wxPython extension modules need to load + // a DLL, but the intperpreter executable is located elsewhere. Doing + // this allows us to always be able to dynamically load a DLL that is + // located at the same place as the wx modules. + wxString modpath, path; + ::GetModuleFileName(wxGetInstance(), + wxStringBuffer(modpath, MAX_PATH+1), + MAX_PATH); + + wxFileName::SplitPath(modpath, &path, NULL, NULL); + + typedef BOOL (WINAPI *SetDllDirectory_t)(LPCTSTR lpPathName); + + static SetDllDirectory_t s_pfnSetDllDirectory = (SetDllDirectory_t) -1; + + if ( s_pfnSetDllDirectory == (SetDllDirectory_t) -1 ) + { + /* + Should wxLoadedDLL ever not be used here (or rather, the + wxDL_GET_LOADED flag isn't used), infinite recursion will take + place (unless s_pfnSetDllDirectory is set to NULL here right + before loading the DLL). + */ + wxLoadedDLL dllKernel("kernel32.dll"); + + wxDL_INIT_FUNC_AW(s_pfn, SetDllDirectory, dllKernel); + } + + if (s_pfnSetDllDirectory) + { + s_pfnSetDllDirectory(path.t_str()); + } + + wxDllType handle = ::LoadLibrary(libname.t_str()); + + // reset the search path + if (s_pfnSetDllDirectory) + { + s_pfnSetDllDirectory(NULL); + } + + return handle; } /* static */ @@ -321,14 +322,14 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded() params.dlls = &dlls; params.verDLL = &verDLL; - if ( !wxDbgHelpDLL::EnumerateLoadedModules + if ( !wxDbgHelpDLL::EnumerateLoadedModulesT ( ::GetCurrentProcess(), wxDynamicLibraryDetailsCreator::EnumModulesProc, ¶ms ) ) { - wxLogLastError(_T("EnumerateLoadedModules")); + wxLogLastError(wxT("EnumerateLoadedModulesT")); } } #endif // wxUSE_DBGHELP @@ -336,5 +337,41 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded() return dlls; } +/* static */ +WXHMODULE wxDynamicLibrary::MSWGetModuleHandle(const wxString& name, void *addr) +{ + // we want to use GetModuleHandleEx() instead of usual GetModuleHandle() + // because the former works correctly for comctl32.dll while the latter + // returns NULL when comctl32.dll version 6 is used under XP (note that + // GetModuleHandleEx() is only available under XP and later, coincidence?) + + // check if we can use GetModuleHandleEx + typedef BOOL (WINAPI *GetModuleHandleEx_t)(DWORD, LPCTSTR, HMODULE *); + + static const GetModuleHandleEx_t INVALID_FUNC_PTR = (GetModuleHandleEx_t)-1; + + static GetModuleHandleEx_t s_pfnGetModuleHandleEx = INVALID_FUNC_PTR; + if ( s_pfnGetModuleHandleEx == INVALID_FUNC_PTR ) + { + wxDynamicLibrary dll(wxT("kernel32.dll"), wxDL_VERBATIM); + s_pfnGetModuleHandleEx = + (GetModuleHandleEx_t)dll.GetSymbolAorW(wxT("GetModuleHandleEx")); + + // dll object can be destroyed, kernel32.dll won't be unloaded anyhow + } + + // get module handle from its address + if ( s_pfnGetModuleHandleEx ) + { + // flags are GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | + // GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + HMODULE hmod; + if ( s_pfnGetModuleHandleEx(6, (LPCTSTR)addr, &hmod) && hmod ) + return hmod; + } + + return ::GetModuleHandle(name.t_str()); +} + #endif // wxUSE_DYNLIB_CLASS