1. extracted MSW-specific part of wxDynamicLibrary in msw/dlmsw.cpp

2. added and documented wxDynamicLibrary::ListLoaded()


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31403 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2005-01-16 20:50:06 +00:00
parent c4526184a7
commit defbed48e7
5 changed files with 487 additions and 23 deletions

View File

@ -33,6 +33,7 @@ All:
- 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):

View File

@ -1,6 +1,6 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: dynlib.tex
%% Purpose: wxDynamicLibrary documentation
%% Purpose: wxDynamicLibrary and wxDynamicLibraryDetails documentation
%% Author: Vadim Zeitlin
%% Modified by:
%% Created: 14.01.02 (extracted from dllload.tex)
@ -22,7 +22,17 @@ done in the objects destructor automatically.
%
%\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}
@ -111,6 +121,19 @@ this function doesn't log an error message if the symbol is not found.
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}}
@ -143,3 +166,70 @@ during a longer period of time than the scope of the wxDynamicLibrary object.
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.

View File

@ -21,6 +21,7 @@
#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__)
@ -32,6 +33,8 @@
#include "wx/msw/private.h"
#endif
class WXDLLIMPEXP_BASE wxDynamicLibraryDetailsCreator;
// ----------------------------------------------------------------------------
// conditional compilation
// ----------------------------------------------------------------------------
@ -106,9 +109,62 @@ enum wxPluginCategory
#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
{
@ -135,8 +191,13 @@ public:
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
@ -172,8 +233,19 @@ public:
//
// 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)
@ -196,7 +268,7 @@ public:
#endif
protected:
// the real implementation of GetSymbol()
// common part of GetSymbol() and HasSymbol()
void *DoGetSymbol(const wxString& name, bool *success = 0) const;

View File

@ -29,10 +29,6 @@
#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"
@ -42,10 +38,13 @@
#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
@ -152,9 +151,9 @@ void *dlsym(void *handle, const char *symbol)
// ---------------------------------------------------------------------------
//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("");
@ -180,11 +179,12 @@ wxDllType wxDynamicLibrary::GetProgramHandle()
#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
@ -279,7 +279,7 @@ bool wxDynamicLibrary::Load(wxString libname, int flags)
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
@ -306,6 +306,8 @@ bool wxDynamicLibrary::Load(wxString libname, int flags)
return IsLoaded();
}
#ifndef __WXMSW__
/* static */
void wxDynamicLibrary::Unload(wxDllType handle)
{
@ -315,8 +317,6 @@ 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
@ -324,6 +324,8 @@ void wxDynamicLibrary::Unload(wxDllType handle)
#endif
}
#endif // !__WXMSW__
void *wxDynamicLibrary::DoGetSymbol(const wxString &name, bool *success) const
{
wxCHECK_MSG( IsLoaded(), NULL,
@ -359,12 +361,7 @@ void *wxDynamicLibrary::DoGetSymbol(const wxString &name, bool *success) const
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
@ -402,6 +399,10 @@ void *wxDynamicLibrary::GetSymbol(const wxString& name, bool *success) const
return symbol;
}
// ----------------------------------------------------------------------------
// informational methods
// ----------------------------------------------------------------------------
/*static*/
wxString
wxDynamicLibrary::CanonicalizeName(const wxString& name,

300
src/msw/dlmsw.cpp Normal file
View File

@ -0,0 +1,300 @@
/////////////////////////////////////////////////////////////////////////////
// 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,
&params
) )
{
wxLogLastError(_T("EnumerateLoadedModules"));
}
}
return dlls;
}
#endif // wxUSE_DYNLIB_CLASS