]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dlmsw.cpp
Fix harmless g++ warning about operator precedence.
[wxWidgets.git] / src / msw / dlmsw.cpp
index f0f1076135f4d200c0038ac9cc9198bb69130c86..0bb76d72db470bdca66717ab349bf1c7ec9e09bc 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        msw/dlmsw.cpp
+// Name:        src/msw/dlmsw.cpp
 // Purpose:     Win32-specific part of wxDynamicLibrary and related classes
 // Author:      Vadim Zeitlin
 // Modified by:
@@ -27,8 +27,9 @@
 
 #include "wx/msw/private.h"
 #include "wx/msw/debughlp.h"
+#include "wx/filename.h"
 
-const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
+const wxString wxDynamicLibrary::ms_dllext(wxT(".dll"));
 
 // ----------------------------------------------------------------------------
 // private classes
@@ -65,7 +66,7 @@ private:
     wxDynamicLibrary m_dll;
 
 
-    DECLARE_NO_COPY_CLASS(wxVersionDLL)
+    wxDECLARE_NO_COPY_CLASS(wxVersionDLL);
 };
 
 // class used to create wxDynamicLibraryDetails objects
@@ -79,52 +80,17 @@ public:
         wxVersionDLL *verDLL;
     };
 
+    // TODO: fix EnumerateLoadedModules() to use EnumerateLoadedModules64()
+    #ifdef __WIN64__
+        typedef DWORD64 DWORD_32_64;
+    #else
+        typedef DWORD DWORD_32_64;
+    #endif
+
     static BOOL CALLBACK
-        EnumModulesProc(PSTR name, DWORD base, ULONG size, void *data);
+    EnumModulesProc(PCSTR 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, 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(_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;
-    }
-
-    // if failed, try by name
-    return ::GetModuleHandleA(name);
-}
-
 // ============================================================================
 // wxVersionDLL implementation
 // ============================================================================
@@ -139,7 +105,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
@@ -150,7 +116,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();                                                   \
@@ -172,7 +138,7 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const
     wxString ver;
     if ( m_dll.IsLoaded() )
     {
-        wxChar *pc = wx_const_cast(wxChar *, filename.c_str());
+        wxChar *pc = const_cast<wxChar *>((const wxChar*) filename.t_str());
 
         DWORD dummy;
         DWORD sizeVerInfo = m_pfnGetFileVersionInfoSize(pc, &dummy);
@@ -183,10 +149,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<wxChar *>(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),
@@ -206,8 +175,8 @@ wxString wxVersionDLL::GetFileVersion(const wxString& filename) const
 
 /* static */
 BOOL CALLBACK
-wxDynamicLibraryDetailsCreator::EnumModulesProc(PSTR name,
-                                                DWORD base,
+wxDynamicLibraryDetailsCreator::EnumModulesProc(PCSTR name,
+                                                DWORD_32_64 base,
                                                 ULONG size,
                                                 void *data)
 {
@@ -217,11 +186,12 @@ wxDynamicLibraryDetailsCreator::EnumModulesProc(PSTR name,
 
     // fill in simple properties
     details->m_name = wxString::FromAscii(name);
-    details->m_address = wx_reinterpret_cast(void *, base);
+    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(name, details->m_address);
     if ( hmod )
     {
         wxString fullname = wxGetFullModuleName(hmod);
@@ -242,14 +212,75 @@ wxDynamicLibraryDetailsCreator::EnumModulesProc(PSTR name,
 // wxDynamicLibrary implementation
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// misc functions
+// ----------------------------------------------------------------------------
+
+wxDllType wxDynamicLibrary::GetProgramHandle()
+{
+    return (wxDllType)::GetModuleHandle(NULL);
+}
+
 // ----------------------------------------------------------------------------
 // loading/unloading DLLs
 // ----------------------------------------------------------------------------
 
+#ifndef MAX_PATH
+    #define MAX_PATH 260        // from VC++ headers
+#endif
+
 /* static */
-wxDllType wxDynamicLibrary::RawLoad(const wxString& libname)
+wxDllType
+wxDynamicLibrary::RawLoad(const wxString& libname, int flags)
 {
-    return ::LoadLibrary(libname);
+    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 */
@@ -261,7 +292,13 @@ void wxDynamicLibrary::Unload(wxDllType handle)
 /* static */
 void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
 {
-    return ::GetProcAddress(handle, name);
+    return (void *)::GetProcAddress(handle,
+#ifdef __WXWINCE__
+                                            name.c_str()
+#else
+                                            name.ToAscii()
+#endif // __WXWINCE__
+                                   );
 }
 
 // ----------------------------------------------------------------------------
@@ -273,6 +310,7 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
 {
     wxDynamicLibraryDetailsArray dlls;
 
+#if wxUSE_DBGHELP
     if ( wxDbgHelpDLL::Init() )
     {
         // prepare to use functions for version info extraction
@@ -282,19 +320,68 @@ wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
         params.dlls = &dlls;
         params.verDLL = &verDLL;
 
+        // Note that the cast of EnumModulesProc is needed because the type of
+        // PENUMLOADED_MODULES_CALLBACK changed: in old SDK versions its first
+        // argument was non-const PSTR while now it's PCSTR. By explicitly
+        // casting to whatever the currently used headers require we ensure
+        // that the code compilers in any case.
         if ( !wxDbgHelpDLL::EnumerateLoadedModules
                             (
                                 ::GetCurrentProcess(),
+                                (PENUMLOADED_MODULES_CALLBACK)
                                 wxDynamicLibraryDetailsCreator::EnumModulesProc,
                                 &params
                             ) )
         {
-            wxLogLastError(_T("EnumerateLoadedModules"));
+            wxLogLastError(wxT("EnumerateLoadedModules"));
         }
     }
+#endif // wxUSE_DBGHELP
 
     return dlls;
 }
 
+/* static */
+WXHMODULE 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