From c118a47691b0017042d07601a9d9a1eb6cf5f7f7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 7 Dec 2009 03:04:33 +0000 Subject: [PATCH] Add semi-public wxDynamicLibrary::MSWGetModuleHandle(). Rename old private wxGetModuleHandle() function to wxDynamicLibrary:: MSWGetModuleHandle() to allow its use in the dll sample. This fixes the sample compilation with VC6 which lacks GetModuleHandleEx()- related declarations. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62801 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dynlib.h | 13 ++++++ samples/dll/my_dll.cpp | 20 ++++----- src/msw/dlmsw.cpp | 92 ++++++++++++++++++++---------------------- 3 files changed, 67 insertions(+), 58 deletions(-) diff --git a/include/wx/dynlib.h b/include/wx/dynlib.h index 213df6a8fd..1057f09cae 100644 --- a/include/wx/dynlib.h +++ b/include/wx/dynlib.h @@ -357,6 +357,19 @@ public: static wxString GetPluginsDirectory(); +#ifdef __WXMSW__ + // return the handle (HMODULE/HINSTANCE) of the DLL with the given name + // and/or containing the specified address: for XP and later systems only + // the address is used and the name is ignored but for the previous systems + // only the name (which may be either a full path to the DLL or just its + // base name, possibly even without extension) is used + // + // the returned handle reference count is not incremented so it doesn't + // need to be freed using FreeLibrary() but it also means that it can + // become invalid if the DLL is unloaded + static HINSTANCE MSWGetModuleHandle(const char *name, void *addr); +#endif // __WXMSW__ + protected: // common part of GetSymbol() and HasSymbol() void *DoGetSymbol(const wxString& name, bool *success = 0) const; diff --git a/samples/dll/my_dll.cpp b/samples/dll/my_dll.cpp index 99dbedc002..8097479b7b 100644 --- a/samples/dll/my_dll.cpp +++ b/samples/dll/my_dll.cpp @@ -27,6 +27,7 @@ #endif #include "wx/app.h" +#include "wx/dynlib.h" #include "wx/frame.h" #include "wx/panel.h" #include "wx/sizer.h" @@ -192,16 +193,15 @@ unsigned wxSTDCALL MyAppLauncher(void* event) // at this point and won't release it until we signal it. // We need to pass correct HINSTANCE to wxEntry() and the right value is - // HINSTANCE of this DLL, not of the main .exe. - // - // This method of obtaining DLL's instance handle requires at least - // Windows XP/2003. We could also implement DllMain() and remember it from - // there, that would work on older systems too. - HINSTANCE hInstance; - int ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCTSTR)&MyAppLauncher, - &hInstance); - if ( ret == 0 ) + // HINSTANCE of this DLL, not of the main .exe, use this MSW-specific wx + // function to get it. Notice that under Windows XP and later the name is + // not needed/used as we retrieve the DLL handle from an address inside it + // but you do need to use the correct name for this code to work with older + // systems as well. + const HINSTANCE + hInstance = wxDynamicLibrary::MSWGetModuleHandle("my_dll", + &gs_wxMainThread); + if ( !hInstance ) return 0; // failed to get DLL's handle // IMPLEMENT_WXWIN_MAIN does this as the first thing diff --git a/src/msw/dlmsw.cpp b/src/msw/dlmsw.cpp index 25700c5cdb..ea04a1ae19 100644 --- a/src/msw/dlmsw.cpp +++ b/src/msw/dlmsw.cpp @@ -100,53 +100,6 @@ public: EnumModulesProc(NameStr_t name, DWORD_32_64 base, ULONG size, void *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(wxT("kernel32.dll"), wxDL_VERBATIM); - s_pfnGetModuleHandleEx = - (GetModuleHandleEx_t)dll.RawGetSymbol(wxT("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 // ============================================================================ @@ -246,7 +199,8 @@ wxDynamicLibraryDetailsCreator::EnumModulesProc(NameStr_t name, details->m_length = size; // to get the version, we first need the full path - HMODULE hmod = wxGetModuleHandle(name, details->m_address); + const HMODULE + hmod = wxDynamicLibrary::MSWGetModuleHandle(name, details->m_address); if ( hmod ) { wxString fullname = wxGetFullModuleName(hmod); @@ -341,5 +295,47 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded() return dlls; } +/* static */ +HMODULE wxDynamicLibrary::MSWGetModuleHandle(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(wxT("kernel32.dll"), wxDL_VERBATIM); + s_pfnGetModuleHandleEx = + (GetModuleHandleEx_t)dll.RawGetSymbol(wxT("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 +} + #endif // wxUSE_DYNLIB_CLASS -- 2.47.2