/////////////////////////////////////////////////////////////////////////////
-// Name: msw/dlmsw.cpp
+// Name: src/msw/dlmsw.cpp
// Purpose: Win32-specific part of wxDynamicLibrary and related classes
// Author: Vadim Zeitlin
// Modified by:
#include "wx/msw/private.h"
#include "wx/msw/debughlp.h"
+#include "wx/filename.h"
const wxString wxDynamicLibrary::ms_dllext(wxT(".dll"));
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;
#endif
static BOOL CALLBACK
- EnumModulesProc(NameStr_t name, DWORD_32_64 base, ULONG size, void *data);
+ EnumModulesProc(PCSTR name, DWORD_32_64 base, ULONG size, void *data);
};
// ============================================================================
/* static */
BOOL CALLBACK
-wxDynamicLibraryDetailsCreator::EnumModulesProc(NameStr_t name,
+wxDynamicLibraryDetailsCreator::EnumModulesProc(PCSTR name,
DWORD_32_64 base,
ULONG size,
void *data)
// loading/unloading DLLs
// ----------------------------------------------------------------------------
+#ifndef MAX_PATH
+ #define MAX_PATH 260 // from VC++ headers
+#endif
+
/* static */
wxDllType
wxDynamicLibrary::RawLoad(const wxString& libname, int flags)
{
- return flags & wxDL_GET_LOADED
- ? ::GetModuleHandle(libname.t_str())
- : ::LoadLibrary(libname.t_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 */
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,
¶ms
) )
}
/* static */
-WXHINSTANCE wxDynamicLibrary::MSWGetModuleHandle(const char *name, void *addr)
+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