1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: Win32-specific part of wxDynamicLibrary and related classes
4
// Author: Vadim Zeitlin
6
// Created: 2005-01-10 (partly extracted from common/dynlib.cpp)
7
// RCS-ID: $Id: dlmsw.cpp,v 1.10 2005/05/22 17:55:30 VZ Exp $
8
// Copyright: (c) 1998-2005 Vadim Zeitlin <vadim@wxwindows.org>
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
12
// ============================================================================
14
// ============================================================================
16
// ----------------------------------------------------------------------------
18
// ----------------------------------------------------------------------------
20
#include "wx/wxprec.h"
26
#if wxUSE_DYNLIB_CLASS
28
#include "wx/msw/private.h"
29
#include "wx/msw/debughlp.h"
31
const wxChar *wxDynamicLibrary::ms_dllext = _T(".dll");
33
// ----------------------------------------------------------------------------
35
// ----------------------------------------------------------------------------
37
// wrap some functions from version.dll: load them dynamically and provide a
42
// load version.dll and bind to its functions
45
// return the file version as string, e.g. "x.y.z.w"
46
wxString GetFileVersion(const wxString& filename) const;
49
typedef DWORD (APIENTRY *GetFileVersionInfoSize_t)(PTSTR, PDWORD);
50
typedef BOOL (APIENTRY *GetFileVersionInfo_t)(PTSTR, DWORD, DWORD, PVOID);
51
typedef BOOL (APIENTRY *VerQueryValue_t)(const PVOID, PTSTR, PVOID *, PUINT);
53
#define DO_FOR_ALL_VER_FUNCS(what) \
54
what(GetFileVersionInfoSize); \
55
what(GetFileVersionInfo); \
58
#define DECLARE_VER_FUNCTION(func) func ## _t m_pfn ## func
60
DO_FOR_ALL_VER_FUNCS(DECLARE_VER_FUNCTION);
62
#undef DECLARE_VER_FUNCTION
65
wxDynamicLibrary m_dll;
68
DECLARE_NO_COPY_CLASS(wxVersionDLL)
71
// class used to create wxDynamicLibraryDetails objects
72
class WXDLLIMPEXP_BASE wxDynamicLibraryDetailsCreator
75
// type of parameters being passed to EnumModulesProc
76
struct EnumModulesProcParams
78
wxDynamicLibraryDetailsArray *dlls;
82
// TODO: fix EnumerateLoadedModules() to use EnumerateLoadedModules64()
84
typedef DWORD64 DWORD_32_64;
86
typedef DWORD DWORD_32_64;
90
EnumModulesProc(PSTR name, DWORD_32_64 base, ULONG size, void *data);
93
// ----------------------------------------------------------------------------
95
// ----------------------------------------------------------------------------
97
// return the module handle for the given base name
99
HMODULE wxGetModuleHandle(const char *name, void *addr)
101
// we want to use GetModuleHandleEx() instead of usual GetModuleHandle()
102
// because the former works correctly for comctl32.dll while the latter
103
// returns NULL when comctl32.dll version 6 is used under XP (note that
104
// GetModuleHandleEx() is only available under XP and later, coincidence?)
106
// check if we can use GetModuleHandleEx
107
typedef BOOL (WINAPI *GetModuleHandleEx_t)(DWORD, LPCSTR, HMODULE *);
109
static const GetModuleHandleEx_t INVALID_FUNC_PTR = (GetModuleHandleEx_t)-1;
111
static GetModuleHandleEx_t s_pfnGetModuleHandleEx = INVALID_FUNC_PTR;
112
if ( s_pfnGetModuleHandleEx == INVALID_FUNC_PTR )
114
wxDynamicLibrary dll(_T("kernel32.dll"), wxDL_VERBATIM);
115
s_pfnGetModuleHandleEx =
116
(GetModuleHandleEx_t)dll.RawGetSymbol(_T("GetModuleHandleExA"));
118
// dll object can be destroyed, kernel32.dll won't be unloaded anyhow
121
// get module handle from its address
122
if ( s_pfnGetModuleHandleEx )
124
// flags are GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
125
// GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
127
if ( s_pfnGetModuleHandleEx(6, (char *)addr, &hmod) && hmod )
131
// Windows CE only has Unicode API, so even we have an ANSI string here, we
132
// still need to use GetModuleHandleW() there and so do it everywhere to
133
// avoid #ifdefs -- this code is not performance-critical anyhow...
134
return ::GetModuleHandle(wxString::FromAscii((char *)name));
137
// ============================================================================
138
// wxVersionDLL implementation
139
// ============================================================================
141
// ----------------------------------------------------------------------------
143
// ----------------------------------------------------------------------------
145
wxVersionDLL::wxVersionDLL()
147
// don't give errors if DLL can't be loaded or used, we're prepared to
151
if ( m_dll.Load(_T("version.dll"), wxDL_VERBATIM) )
153
// the functions we load have either 'A' or 'W' suffix depending on
154
// whether we're in ANSI or Unicode build
159
#endif // UNICODE/ANSI
161
#define LOAD_VER_FUNCTION(name) \
162
m_pfn ## name = (name ## _t)m_dll.GetSymbol(_T(#name SUFFIX)); \
163
if ( !m_pfn ## name ) \
169
DO_FOR_ALL_VER_FUNCS(LOAD_VER_FUNCTION);
171
#undef LOAD_VER_FUNCTION
175
// ----------------------------------------------------------------------------
176
// wxVersionDLL operations
177
// ----------------------------------------------------------------------------
179
wxString wxVersionDLL::GetFileVersion(const wxString& filename) const
182
if ( m_dll.IsLoaded() )
184
wxChar *pc = wx_const_cast(wxChar *, filename.c_str());
187
DWORD sizeVerInfo = m_pfnGetFileVersionInfoSize(pc, &dummy);
190
wxCharBuffer buf(sizeVerInfo);
191
if ( m_pfnGetFileVersionInfo(pc, 0, sizeVerInfo, buf.data()) )
195
if ( m_pfnVerQueryValue(buf.data(), _T("\\"), &pVer, &sizeInfo) )
197
VS_FIXEDFILEINFO *info = (VS_FIXEDFILEINFO *)pVer;
198
ver.Printf(_T("%d.%d.%d.%d"),
199
HIWORD(info->dwFileVersionMS),
200
LOWORD(info->dwFileVersionMS),
201
HIWORD(info->dwFileVersionLS),
202
LOWORD(info->dwFileVersionLS));
207
//else: we failed to load DLL, can't retrieve version info
212
// ============================================================================
213
// wxDynamicLibraryDetailsCreator implementation
214
// ============================================================================
218
wxDynamicLibraryDetailsCreator::EnumModulesProc(PSTR name,
223
EnumModulesProcParams *params = (EnumModulesProcParams *)data;
225
wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails;
227
// fill in simple properties
228
details->m_name = wxString::FromAscii(name);
229
details->m_address = wx_reinterpret_cast(void *, base);
230
details->m_length = size;
232
// to get the version, we first need the full path
233
HMODULE hmod = wxGetModuleHandle(name, (void *)base);
236
wxString fullname = wxGetFullModuleName(hmod);
237
if ( !fullname.empty() )
239
details->m_path = fullname;
240
details->m_version = params->verDLL->GetFileVersion(fullname);
244
params->dlls->Add(details);
246
// continue enumeration (returning FALSE would have stopped it)
250
// ============================================================================
251
// wxDynamicLibrary implementation
252
// ============================================================================
254
// ----------------------------------------------------------------------------
256
// ----------------------------------------------------------------------------
258
wxDllType wxDynamicLibrary::GetProgramHandle()
260
return (wxDllType)::GetModuleHandle(NULL);
263
// ----------------------------------------------------------------------------
264
// loading/unloading DLLs
265
// ----------------------------------------------------------------------------
269
wxDynamicLibrary::RawLoad(const wxString& libname, int WXUNUSED(flags))
271
return ::LoadLibrary(libname);
275
void wxDynamicLibrary::Unload(wxDllType handle)
277
::FreeLibrary(handle);
281
void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
283
return (void *)::GetProcAddress(handle,
288
#endif // __WXWINCE__
292
// ----------------------------------------------------------------------------
293
// enumerating loaded DLLs
294
// ----------------------------------------------------------------------------
297
wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
299
wxDynamicLibraryDetailsArray dlls;
302
if ( wxDbgHelpDLL::Init() )
304
// prepare to use functions for version info extraction
307
wxDynamicLibraryDetailsCreator::EnumModulesProcParams params;
309
params.verDLL = &verDLL;
311
if ( !wxDbgHelpDLL::EnumerateLoadedModules
313
::GetCurrentProcess(),
314
wxDynamicLibraryDetailsCreator::EnumModulesProc,
318
wxLogLastError(_T("EnumerateLoadedModules"));
321
#endif // wxUSE_DBGHELP
326
#endif // wxUSE_DYNLIB_CLASS