- Added support to the wxODBC classes for Firebird 1.5 database
- The samples\db sample program now includes an optional example of using a BLOB
datatype (if BLOB support is enabled and supported by the database)
+- added wxDynamicLibrary::ListLoaded()
All (GUI):
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: dynlib.tex
-%% Purpose: wxDynamicLibrary documentation
+%% Purpose: wxDynamicLibrary and wxDynamicLibraryDetails documentation
%% Author: Vadim Zeitlin
%% Modified by:
%% Created: 14.01.02 (extracted from dllload.tex)
%
%\helpref{wxDllLoader}{wxdllloader}
+\wxheading{Derived from}
+No base class.
+
+\wxheading{Include files}
+
+<wx/dynlib.h>
+
+(only available if \texttt{wxUSE\_DYNLIB\_CLASS} is set to $1$)
+
+\latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxDynamicLibrary::wxDynamicLibrary}\label{wxdynamiclibrarywxdynamiclibrary}
Returns \true if the library was successfully loaded, \false otherwise.
+\membersection{wxDynamicLibrary::ListLoaded}\label{wxdynamiclibrarylistloaded}
+
+\func{static wxDynamicLibraryDetailsArray}{ListLoaded}{\void}
+
+This static method returns an \helpref{array}{wxarray} containing the details
+of all modules loaded into the address space of the current project, the array
+elements are object of \texttt{wxDynamicLibraryDetails} class. The array will
+be empty if an error occured.
+
+This method is currently only implemented under Win32 and is useful mostly for
+diagnostics purposes.
+
+
\membersection{wxDynamicLibrary::Load}\label{wxdynamiclibraryload}
\func{bool}{Load}{\param{const wxString\& }{name}, \param{int }{flags = wxDL\_DEFAULT}}
In this case you may call \helpref{Detach}{wxdynamiclibrarydetach} and store
the handle somewhere and call this static method later to unload it.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{\class{wxDynamicLibraryDetails}}\label{wxdynamiclibrarydetails}
+
+This class is used for the objects returned by
+\helpref{wxDynamicLibrary::ListLoaded}{wxdynamiclibrarylistloaded} method and
+contains the information about a single module loaded into the address space of
+the current process. A module in this context may be either a dynamic library
+or the main program itself.
+
+\wxheading{Derived from}
+
+No base class.
+
+\wxheading{Include files}
+
+<wx/dynlib.h>
+
+(only available if \texttt{wxUSE\_DYNLIB\_CLASS} is set to $1$)
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxDynamicLibraryDetails::GetName}\label{wxdynamiclibrarygetname}
+
+\constfunc{wxString}{GetName}{\void}
+
+Returns the base name of this module, e.g. \texttt{kernel32.dll} or
+\texttt{libc-2.3.2.so}.
+
+
+\membersection{wxDynamicLibraryDetails::GetPath}\label{wxdynamiclibrarygetpath}
+
+\constfunc{wxString}{GetPath}{\void}
+
+Returns the full path of this module if available, e.g.
+\texttt{c:$\backslash$windows$\backslash$system32$\backslash$kernel32.dll} or
+\texttt{/lib/libc-2.3.2.so}.
+
+
+\membersection{wxDynamicLibraryDetails::GetAddress}\label{wxdynamiclibrarygetaddress}
+
+\constfunc{bool}{GetAddress}{\param{void **}{addr}, \param{size\_t }{*len}}
+
+Retrieves the load address and the size of this module.
+
+\wxheading{Parameters}
+
+\docparam{addr}{the pointer to the location to return load address in, may be
+\texttt{NULL}}
+
+\docparam{len}{pointer to the location to return the size of this module in
+memory in, may be \texttt{NULL}}
+
+\wxheading{Return value}
+
+\true if the load address and module size were retrieved, \false if this
+information is not available.
+
+
+\membersection{wxDynamicLibraryDetails::GetVersion}\label{wxdynamiclibrarygetversion}
+
+\constfunc{wxString}{GetVersion}{\void}
+
+Returns the version of this module, e.g. \texttt{5.2.3790.0} or
+\texttt{2.3.2}. The returned string is empty if the version information is not
+available.
+
#if wxUSE_DYNLIB_CLASS
#include "wx/string.h"
+#include "wx/dynarray.h"
// FIXME: can this go in private.h or something too??
#if defined(__WXPM__) || defined(__EMX__)
#include "wx/msw/private.h"
#endif
+class WXDLLIMPEXP_BASE wxDynamicLibraryDetailsCreator;
+
// ----------------------------------------------------------------------------
// conditional compilation
// ----------------------------------------------------------------------------
#define wxDYNLIB_FUNCTION(type, name, dynlib) \
type pfn ## name = (type)(dynlib).GetSymbol(_T(#name))
-// ---------------------------------------------------------------------------
-// wxDynamicLibrary
-// ---------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// wxDynamicLibraryDetails: contains details about a loaded wxDynamicLibrary
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxDynamicLibraryDetails
+{
+public:
+ // ctor, normally never used as these objects are only created by
+ // wxDynamicLibrary::ListLoaded()
+ wxDynamicLibraryDetails() { m_address = NULL; m_length = 0; }
+
+ // get the (base) name
+ wxString GetName() const { return m_name; }
+
+ // get the full path of this object
+ wxString GetPath() const { return m_path; }
+
+ // get the load address and the extent, return true if this information is
+ // available
+ bool GetAddress(void **addr, size_t *len) const
+ {
+ if ( !m_address )
+ return false;
+
+ if ( addr )
+ *addr = m_address;
+ if ( len )
+ *len = m_length;
+
+ return true;
+ }
+
+ // return the version of the DLL (may be empty if no version info)
+ wxString GetVersion() const
+ {
+ return m_version;
+ }
+
+private:
+ wxString m_name,
+ m_path,
+ m_version;
+
+ void *m_address;
+ size_t m_length;
+
+ friend class wxDynamicLibraryDetailsCreator;
+};
+
+WX_DECLARE_USER_EXPORTED_OBJARRAY(wxDynamicLibraryDetails,
+ wxDynamicLibraryDetailsArray,
+ WXDLLIMPEXP_BASE);
+
+// ----------------------------------------------------------------------------
+// wxDynamicLibrary: represents a handle to a DLL/shared object
+// ----------------------------------------------------------------------------
class WXDLLIMPEXP_BASE wxDynamicLibrary
{
bool IsLoaded() const { return m_handle != 0; }
// load the library with the given name (full or not), return true if ok
- bool Load(wxString libname, int flags = wxDL_DEFAULT);
+ bool Load(const wxString& libname, int flags = wxDL_DEFAULT);
+ // raw function for loading dynamic libs: always behaves as if
+ // wxDL_VERBATIM were specified and doesn't log error message if the
+ // library couldn't be loaded but simply returns NULL
+ static wxDllType RawLoad(const wxString& libname);
+
// detach the library object from its handle, i.e. prevent the object from
// unloading the library in its dtor -- the caller is now responsible for
// doing this
//
// Returns a pointer to the symbol on success, or NULL if an error occurred
// or the symbol wasn't found.
- void *GetSymbol(const wxString& name, bool *success = 0) const;
+ void *GetSymbol(const wxString& name, bool *success = NULL) const;
+ // low-level version of GetSymbol()
+ static void *RawGetSymbol(wxDllType handle, const wxString& name);
+ void *RawGetSymbol(const wxString& name) const
+ {
+ return RawGetSymbol(m_handle, name);
+ }
+
+ // return all modules/shared libraries in the address space of this process
+ //
+ // returns an empty array if not implemented or an error occured
+ static wxDynamicLibraryDetailsArray ListLoaded();
// return platform-specific name of dynamic library with proper extension
// and prefix (e.g. "foo.dll" on Windows or "libfoo.so" on Linux)
#endif
protected:
- // the real implementation of GetSymbol()
+ // common part of GetSymbol() and HasSymbol()
void *DoGetSymbol(const wxString& name, bool *success = 0) const;
#if wxUSE_DYNLIB_CLASS
-#if defined(__WINDOWS__)
- #include "wx/msw/wrapwin.h"
-#endif
-
#include "wx/dynlib.h"
#include "wx/filefn.h"
#include "wx/intl.h"
#include "wx/app.h"
#include "wx/apptrait.h"
+#include "wx/arrimpl.cpp"
+
#if defined(__WXMAC__)
#include "wx/mac/private.h"
#endif
+WX_DEFINE_USER_EXPORTED_OBJARRAY(wxDynamicLibraryDetailsArray);
// ============================================================================
// implementation
// ---------------------------------------------------------------------------
//FIXME: This class isn't really common at all, it should be moved into
-// platform dependent files.
+// platform dependent files (already done for Windows)
-#if defined(__WINDOWS__) || defined(__WXPM__) || defined(__EMX__)
+#if defined(__WXPM__) || defined(__EMX__)
const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
#elif defined(__WXMAC__) && !defined(__DARWIN__)
const wxChar *wxDynamicLibrary::ms_dllext = _T("");
#endif
}
-bool wxDynamicLibrary::Load(wxString libname, int flags)
+bool wxDynamicLibrary::Load(const wxString& libnameOrig, int flags)
{
wxASSERT_MSG(m_handle == 0, _T("Library already loaded."));
// add the proper extension for the DLL ourselves unless told not to
+ wxString libname = libnameOrig;
if ( !(flags & wxDL_VERBATIM) )
{
// and also check that the libname doesn't already have it
m_handle = shl_load(libname.fn_str(), BIND_DEFERRED, 0);
#elif defined(__WINDOWS__)
- m_handle = ::LoadLibrary(libname.c_str());
+ m_handle = RawLoad(libname);
#else
#error "runtime shared lib support not implemented on this platform"
#endif
return IsLoaded();
}
+#ifndef __WXMSW__
+
/* static */
void wxDynamicLibrary::Unload(wxDllType handle)
{
dlclose( handle );
#elif defined(HAVE_SHL_LOAD)
shl_unload( handle );
-#elif defined(__WINDOWS__)
- ::FreeLibrary( handle );
#elif defined(__WXMAC__) && !defined(__DARWIN__)
CloseConnection( (CFragConnectionID*) &handle );
#else
#endif
}
+#endif // !__WXMSW__
+
void *wxDynamicLibrary::DoGetSymbol(const wxString &name, bool *success) const
{
wxCHECK_MSG( IsLoaded(), NULL,
symbol = 0;
#elif defined(__WINDOWS__)
-#ifdef __WXWINCE__
- symbol = (void*) ::GetProcAddress( m_handle, name );
-#else
- symbol = (void*) ::GetProcAddress( m_handle, name.mb_str() );
-#endif
-
+ symbol = RawGetSymbol(m_handle, name);
#else
#error "runtime shared lib support not implemented"
#endif
return symbol;
}
+// ----------------------------------------------------------------------------
+// informational methods
+// ----------------------------------------------------------------------------
+
/*static*/
wxString
wxDynamicLibrary::CanonicalizeName(const wxString& name,
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: msw/dlmsw.cpp
+// Purpose: Win32-specific part of wxDynamicLibrary and related classes
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 2005-01-10 (partly extracted from common/dynlib.cpp)
+// RCS-ID: $Id$
+// Copyright: (c) 1998-2005 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_DYNLIB_CLASS
+
+#include "wx/msw/private.h"
+#include "wx/msw/debughlp.h"
+
+const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+// wrap some functions from version.dll: load them dynamically and provide a
+// clean interface
+class wxVersionDLL
+{
+public:
+ // load version.dll and bind to its functions
+ wxVersionDLL();
+
+ // return the file version as string, e.g. "x.y.z.w"
+ wxString GetFileVersion(const wxString& filename) const;
+
+private:
+ typedef DWORD (APIENTRY *GetFileVersionInfoSize_t)(PTSTR, PDWORD);
+ typedef BOOL (APIENTRY *GetFileVersionInfo_t)(PTSTR, DWORD, DWORD, PVOID);
+ typedef BOOL (APIENTRY *VerQueryValue_t)(const PVOID, PTSTR, PVOID *, PUINT);
+
+ #define DO_FOR_ALL_VER_FUNCS(what) \
+ what(GetFileVersionInfoSize); \
+ what(GetFileVersionInfo); \
+ what(VerQueryValue)
+
+ #define DECLARE_VER_FUNCTION(func) func ## _t m_pfn ## func
+
+ DO_FOR_ALL_VER_FUNCS(DECLARE_VER_FUNCTION);
+
+ #undef DECLARE_VER_FUNCTION
+
+
+ wxDynamicLibrary m_dll;
+
+
+ DECLARE_NO_COPY_CLASS(wxVersionDLL)
+};
+
+// class used to create wxDynamicLibraryDetails objects
+class WXDLLIMPEXP_BASE wxDynamicLibraryDetailsCreator
+{
+public:
+ // type of parameters being passed to EnumModulesProc
+ struct EnumModulesProcParams
+ {
+ wxDynamicLibraryDetailsArray *dlls;
+ wxVersionDLL *verDLL;
+ };
+
+ static BOOL CALLBACK
+ EnumModulesProc(PSTR name, DWORD 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
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// loading
+// ----------------------------------------------------------------------------
+
+wxVersionDLL::wxVersionDLL()
+{
+ // don't give errors if DLL can't be loaded or used, we're prepared to
+ // handle it
+ wxLogNull noLog;
+
+ if ( m_dll.Load(_T("version.dll"), wxDL_VERBATIM) )
+ {
+ // the functions we load have either 'A' or 'W' suffix depending on
+ // whether we're in ANSI or Unicode build
+ #ifdef UNICODE
+ #define SUFFIX L"W"
+ #else // ANSI
+ #define SUFFIX "A"
+ #endif // UNICODE/ANSI
+
+ #define LOAD_VER_FUNCTION(name) \
+ m_pfn ## name = (name ## _t)m_dll.GetSymbol(_T(#name SUFFIX)); \
+ if ( !m_pfn ## name ) \
+ { \
+ m_dll.Unload(); \
+ return; \
+ }
+
+ DO_FOR_ALL_VER_FUNCS(LOAD_VER_FUNCTION);
+
+ #undef LOAD_VER_FUNCTION
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxVersionDLL operations
+// ----------------------------------------------------------------------------
+
+wxString wxVersionDLL::GetFileVersion(const wxString& filename) const
+{
+ wxString ver;
+ if ( m_dll.IsLoaded() )
+ {
+ wxChar *pc = wx_const_cast(wxChar *, filename.c_str());
+
+ DWORD dummy;
+ DWORD sizeVerInfo = m_pfnGetFileVersionInfoSize(pc, &dummy);
+ if ( sizeVerInfo )
+ {
+ wxCharBuffer buf(sizeVerInfo);
+ if ( m_pfnGetFileVersionInfo(pc, 0, sizeVerInfo, buf.data()) )
+ {
+ void *pVer;
+ UINT sizeInfo;
+ if ( m_pfnVerQueryValue(buf.data(), _T("\\"), &pVer, &sizeInfo) )
+ {
+ VS_FIXEDFILEINFO *info = (VS_FIXEDFILEINFO *)pVer;
+ ver.Printf(_T("%d.%d.%d.%d"),
+ HIWORD(info->dwFileVersionMS),
+ LOWORD(info->dwFileVersionMS),
+ HIWORD(info->dwFileVersionLS),
+ LOWORD(info->dwFileVersionLS));
+ }
+ }
+ }
+ }
+ //else: we failed to load DLL, can't retrieve version info
+
+ return ver;
+}
+
+// ============================================================================
+// wxDynamicLibraryDetailsCreator implementation
+// ============================================================================
+
+/* static */
+BOOL CALLBACK
+wxDynamicLibraryDetailsCreator::EnumModulesProc(PSTR name,
+ DWORD base,
+ ULONG size,
+ void *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);
+ details->m_length = size;
+
+ // to get the version, we first need the full path
+ HMODULE hmod = wxGetModuleHandle(name, (void *)base);
+ if ( hmod )
+ {
+ wxString fullname = wxGetFullModuleName(hmod);
+ if ( !fullname.empty() )
+ {
+ details->m_path = fullname;
+ details->m_version = params->verDLL->GetFileVersion(fullname);
+ }
+ }
+
+ params->dlls->Add(details);
+
+ // continue enumeration (returning FALSE would have stopped it)
+ return TRUE;
+}
+
+// ============================================================================
+// wxDynamicLibrary implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// loading/unloading DLLs
+// ----------------------------------------------------------------------------
+
+/* static */
+wxDllType wxDynamicLibrary::RawLoad(const wxString& libname)
+{
+ return ::LoadLibrary(libname);
+}
+
+/* static */
+void wxDynamicLibrary::Unload(wxDllType handle)
+{
+ ::FreeLibrary(handle);
+}
+
+/* static */
+void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
+{
+ return ::GetProcAddress(handle, name);
+}
+
+// ----------------------------------------------------------------------------
+// enumerating loaded DLLs
+// ----------------------------------------------------------------------------
+
+/* static */
+wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
+{
+ wxDynamicLibraryDetailsArray dlls;
+
+ if ( wxDbgHelpDLL::Init() )
+ {
+ // prepare to use functions for version info extraction
+ wxVersionDLL verDLL;
+
+ wxDynamicLibraryDetailsCreator::EnumModulesProcParams params;
+ params.dlls = &dlls;
+ params.verDLL = &verDLL;
+
+ if ( !wxDbgHelpDLL::EnumerateLoadedModules
+ (
+ ::GetCurrentProcess(),
+ wxDynamicLibraryDetailsCreator::EnumModulesProc,
+ ¶ms
+ ) )
+ {
+ wxLogLastError(_T("EnumerateLoadedModules"));
+ }
+ }
+
+ return dlls;
+}
+
+#endif // wxUSE_DYNLIB_CLASS
+