1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: module.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
35 #include <osl/module.h>
36 #include <osl/diagnose.h>
37 #include <osl/thread.h>
39 #include <rtl/logfile.h>
41 under WIN32, we use the void* oslModule
42 as a WIN32 HANDLE (which is also a 32-bit value)
45 /*****************************************************************************/
47 /*****************************************************************************/
48 oslModule SAL_CALL
osl_loadModule(rtl_uString
*strModuleName
, sal_Int32 nRtldMode
)
51 UINT errorMode
= SetErrorMode(SEM_NOOPENFILEERRORBOX
| SEM_FAILCRITICALERRORS
);
52 rtl_uString
* Module
= NULL
;
56 RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %S", (LPTSTR
)&strModuleName
->buffer
);
58 OSL_ASSERT(strModuleName
);
60 nRtldMode
= nRtldMode
; /* avoid warnings */
62 nError
= osl_getSystemPathFromFileURL(strModuleName
, &Module
);
64 if ( osl_File_E_None
!= nError
)
65 rtl_uString_assign(&Module
, strModuleName
);
67 hInstance
= LoadLibraryW(Module
->buffer
);
68 if (hInstance
== NULL
)
69 hInstance
= LoadLibraryExW(Module
->buffer
, NULL
,
70 LOAD_WITH_ALTERED_SEARCH_PATH
);
72 if (hInstance
<= (HINSTANCE
)HINSTANCE_ERROR
)
75 ret
= (oslModule
) hInstance
;
76 rtl_uString_release(Module
);
77 SetErrorMode(errorMode
);
79 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR
)&strModuleName
->buffer
);
84 /*****************************************************************************/
85 /* osl_loadModuleAscii */
86 /*****************************************************************************/
87 oslModule SAL_CALL
osl_loadModuleAscii(const sal_Char
*pModuleName
, sal_Int32 nRtldMode
)
89 (void) nRtldMode
; /* avoid warnings */
92 UINT errorMode
= SetErrorMode(SEM_NOOPENFILEERRORBOX
| SEM_FAILCRITICALERRORS
);
96 RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %s", pModuleName
);
98 OSL_ASSERT(pModuleName
);
100 hInstance
= LoadLibrary(pModuleName
);
101 if (hInstance
== NULL
)
102 hInstance
= LoadLibraryEx(pModuleName
, NULL
,
103 LOAD_WITH_ALTERED_SEARCH_PATH
);
105 if (hInstance
<= (HINSTANCE
)HINSTANCE_ERROR
)
108 ret
= (oslModule
) hInstance
;
109 SetErrorMode(errorMode
);
111 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %s", pModuleName
);
116 /*****************************************************************************/
117 /* osl_getModuleHandle */
118 /*****************************************************************************/
121 osl_getModuleHandle(rtl_uString
*pModuleName
, oslModule
*pResult
)
123 HINSTANCE hInstance
= GetModuleHandleW(pModuleName
->buffer
);
126 *pResult
= (oslModule
) hInstance
;
133 /*****************************************************************************/
134 /* osl_unloadModule */
135 /*****************************************************************************/
136 void SAL_CALL
osl_unloadModule(oslModule Module
)
138 FreeLibrary((HINSTANCE
)Module
);
141 /*****************************************************************************/
143 /*****************************************************************************/
144 void* SAL_CALL
osl_getSymbol(oslModule Module
, rtl_uString
*strSymbolName
)
146 /* casting from a function pointer to a data pointer is invalid
147 be in this case unavoidable because the API has to stay
148 compitable we need to keep this function which returns a
149 void* by definition */
151 #pragma warning(push)
152 #pragma warning(disable:4054)
154 return (void*)(osl_getFunctionSymbol(Module
, strSymbolName
));
160 /*****************************************************************************/
161 /* osl_getFunctionSymbol */
162 /*****************************************************************************/
163 oslGenericFunction SAL_CALL
osl_getFunctionSymbol( oslModule Module
, rtl_uString
*strSymbolName
)
165 rtl_String
*symbolName
= NULL
;
166 oslGenericFunction address
;
169 OSL_ASSERT(strSymbolName
);
173 strSymbolName
->buffer
,
174 strSymbolName
->length
,
175 RTL_TEXTENCODING_UTF8
,
176 OUSTRING_TO_OSTRING_CVTFLAGS
179 address
=osl_getAsciiFunctionSymbol(Module
, rtl_string_getStr(symbolName
));
180 rtl_string_release(symbolName
);
185 /*****************************************************************************/
186 /* osl_getAsciiFunctionSymbol */
187 /*****************************************************************************/
188 oslGenericFunction SAL_CALL
189 osl_getAsciiFunctionSymbol( oslModule Module
, const sal_Char
*pSymbol
)
191 oslGenericFunction fncAddr
= NULL
;
194 fncAddr
=(oslGenericFunction
)GetProcAddress((HINSTANCE
) Module
, pSymbol
);
201 /*****************************************************************************/
202 /* osl_addressGetModuleURL */
203 /*****************************************************************************/
205 /*****************************************************************************/
206 /* Implementation for Windows 95, 98 and Me */
207 /*****************************************************************************/
209 /* Undefine because there is no explicit "A" definition */
215 #ifdef LPMODULEENTRY32
216 #undef LPMODULEENTRY32
219 typedef HANDLE (WINAPI
*CreateToolhelp32Snapshot_PROC
)( DWORD dwFlags
, DWORD th32ProcessID
);
220 typedef BOOL (WINAPI
*Module32First_PROC
)( HANDLE hSnapshot
, LPMODULEENTRY32 lpme32
);
221 typedef BOOL (WINAPI
*Module32Next_PROC
)( HANDLE hSnapshot
, LPMODULEENTRY32 lpme32
);
223 static sal_Bool SAL_CALL
_osl_addressGetModuleURL_Windows( void *pv
, rtl_uString
**pustrURL
)
225 sal_Bool bSuccess
= sal_False
; /* Assume failure */
226 HMODULE hModKernel32
= GetModuleHandleA( "KERNEL32.DLL" );
230 CreateToolhelp32Snapshot_PROC lpfnCreateToolhelp32Snapshot
= (CreateToolhelp32Snapshot_PROC
)GetProcAddress( hModKernel32
, "CreateToolhelp32Snapshot" );
231 Module32First_PROC lpfnModule32First
= (Module32First_PROC
)GetProcAddress( hModKernel32
, "Module32First" );
232 Module32Next_PROC lpfnModule32Next
= (Module32Next_PROC
)GetProcAddress( hModKernel32
, "Module32Next" );
234 if ( lpfnCreateToolhelp32Snapshot
&& lpfnModule32First
&& lpfnModule32Next
)
236 HANDLE hModuleSnap
= NULL
;
237 DWORD dwProcessId
= GetCurrentProcessId();
239 // Take a snapshot of all modules in the specified process.
241 hModuleSnap
= lpfnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE
, dwProcessId
);
243 if ( INVALID_HANDLE_VALUE
!= hModuleSnap
)
245 MODULEENTRY32 me32
= {0};
247 // Fill the size of the structure before using it.
249 me32
.dwSize
= sizeof(MODULEENTRY32
);
251 // Walk the module list of the process, and find the module of
252 // interest. Then copy the information to the buffer pointed
253 // to by lpMe32 so that it can be returned to the caller.
255 if ( lpfnModule32First(hModuleSnap
, &me32
) )
259 if ( (BYTE
*)pv
>= (BYTE
*)me32
.hModule
&& (BYTE
*)pv
< (BYTE
*)me32
.hModule
+ me32
.modBaseSize
)
261 rtl_uString
*ustrSysPath
= NULL
;
263 rtl_string2UString( &ustrSysPath
, me32
.szExePath
, strlen(me32
.szExePath
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
264 OSL_ASSERT(ustrSysPath
!= NULL
);
265 osl_getFileURLFromSystemPath( ustrSysPath
, pustrURL
);
266 rtl_uString_release( ustrSysPath
);
271 } while ( !bSuccess
&& lpfnModule32Next( hModuleSnap
, &me32
) );
275 // Do not forget to clean up the snapshot object.
277 CloseHandle (hModuleSnap
);
286 /***************************************************************************************/
287 /* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
288 /***************************************************************************************/
291 #pragma warning(push,1) /* disable warnings within system headers */
293 #include <imagehlp.h>
298 typedef BOOL (WINAPI
*SymInitialize_PROC
)(
300 LPSTR UserSearchPath
,
304 typedef BOOL (WINAPI
*SymCleanup_PROC
)(
308 typedef BOOL (WINAPI
*SymGetModuleInfo_PROC
)(
311 PIMAGEHLP_MODULE ModuleInfo
314 /* Seems that IMAGEHLP.DLL is always availiable on NT 4. But MSDN from Platform SDK says Win 2K is required. MSDN from VS 6.0a says
315 it's O.K on NT 4 ???!!!
316 BTW: We are using ANSI function because not all version of IMAGEHLP.DLL contain Unicode support
319 static sal_Bool SAL_CALL
_osl_addressGetModuleURL_NT4( void *pv
, rtl_uString
**pustrURL
)
321 sal_Bool bSuccess
= sal_False
; /* Assume failure */
323 /* IMAGEHELP.DLL has a bug that it recursivly scans subdirectories of
324 the root when calling SymInitialize(), so we preferr DBGHELP.DLL
325 which exports the same symbols and is shipped with OOo */
327 HMODULE hModImageHelp
= LoadLibrary( "DBGHELP.DLL" );
329 if ( !hModImageHelp
)
330 hModImageHelp
= LoadLibrary( "IMAGEHLP.DLL" );
334 SymGetModuleInfo_PROC lpfnSymGetModuleInfo
;
335 SymInitialize_PROC lpfnSymInitialize
;
336 SymCleanup_PROC lpfnSymCleanup
;
339 lpfnSymInitialize
= (SymInitialize_PROC
)GetProcAddress( hModImageHelp
, "SymInitialize" );
340 lpfnSymCleanup
= (SymCleanup_PROC
)GetProcAddress( hModImageHelp
, "SymCleanup" );
341 lpfnSymGetModuleInfo
= (SymGetModuleInfo_PROC
)GetProcAddress( hModImageHelp
, "SymGetModuleInfo" );
344 if ( lpfnSymInitialize
&& lpfnSymCleanup
&& lpfnSymGetModuleInfo
)
346 IMAGEHLP_MODULE ModuleInfo
;
347 CHAR szModuleFileName
[MAX_PATH
];
348 LPSTR lpSearchPath
= NULL
;
350 if ( GetModuleFileNameA( NULL
, szModuleFileName
, sizeof(szModuleFileName
) ) )
352 char *pLastBkSlash
= strrchr( szModuleFileName
, '\\' );
356 pLastBkSlash
> szModuleFileName
357 && *(pLastBkSlash
- 1) != ':'
358 && *(pLastBkSlash
- 1) != '\\'
362 lpSearchPath
= szModuleFileName
;
366 lpfnSymInitialize( GetCurrentProcess(), lpSearchPath
, TRUE
);
368 ZeroMemory( &ModuleInfo
, sizeof(ModuleInfo
) );
369 ModuleInfo
.SizeOfStruct
= sizeof(ModuleInfo
);
371 bSuccess
= (sal_Bool
)(!!lpfnSymGetModuleInfo( GetCurrentProcess(), (DWORD
)pv
, &ModuleInfo
));
375 /* #99182 On localized (non-english) NT4 and XP (!!!) for some libraries the LoadedImageName member of ModuleInfo isn't filled. Because
376 other members ModuleName and ImageName do not contain the full path we can cast the Member
377 BaseOfImage to a HMODULE (on NT it's the same) and use GetModuleFileName to retrieve the full
378 path of the loaded image */
380 if ( ModuleInfo
.LoadedImageName
[0] || GetModuleFileNameA( (HMODULE
)ModuleInfo
.BaseOfImage
, ModuleInfo
.LoadedImageName
, sizeof(ModuleInfo
.LoadedImageName
) ) )
382 rtl_uString
*ustrSysPath
= NULL
;
384 rtl_string2UString( &ustrSysPath
, ModuleInfo
.LoadedImageName
, strlen(ModuleInfo
.LoadedImageName
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
385 OSL_ASSERT(ustrSysPath
!= NULL
);
386 osl_getFileURLFromSystemPath( ustrSysPath
, pustrURL
);
387 rtl_uString_release( ustrSysPath
);
390 bSuccess
= sal_False
;
393 lpfnSymCleanup( GetCurrentProcess() );
396 FreeLibrary( hModImageHelp
);
403 typedef struct _MODULEINFO
{
407 } MODULEINFO
, *LPMODULEINFO
;
409 typedef BOOL (WINAPI
*EnumProcessModules_PROC
)(
410 HANDLE hProcess
, // handle to the process
411 HMODULE
* lphModule
, // array to receive the module handles
412 DWORD cb
, // size of the array
413 LPDWORD lpcbNeeded
// receives the number of bytes returned
416 typedef BOOL (WINAPI
*GetModuleInformation_PROC
)(
417 HANDLE hProcess
, // handle to the process
418 HMODULE hModule
, // handle to the module
419 LPMODULEINFO lpmodinfo
, // structure that receives information
420 DWORD cb
// size of the structure
423 #define bufsizeof(buffer) (sizeof(buffer) / sizeof((buffer)[0]))
425 /* This version can fail because PSAPI.DLL is not always part of NT 4 despite MSDN Libary 6.0a say so */
427 static sal_Bool SAL_CALL
_osl_addressGetModuleURL_NT( void *pv
, rtl_uString
**pustrURL
)
429 sal_Bool bSuccess
= sal_False
; /* Assume failure */
430 static HMODULE hModPsapi
= NULL
;
433 hModPsapi
= LoadLibrary( "PSAPI.DLL" );
437 EnumProcessModules_PROC lpfnEnumProcessModules
= (EnumProcessModules_PROC
)GetProcAddress( hModPsapi
, "EnumProcessModules" );
438 GetModuleInformation_PROC lpfnGetModuleInformation
= (GetModuleInformation_PROC
)GetProcAddress( hModPsapi
, "GetModuleInformation" );
440 if ( lpfnEnumProcessModules
&& lpfnGetModuleInformation
)
443 HMODULE
*lpModules
= NULL
;
448 lpfnEnumProcessModules( GetCurrentProcess(), NULL
, 0, &cbNeeded
);
450 lpModules
= (HMODULE
*)_alloca( cbNeeded
);
451 lpfnEnumProcessModules( GetCurrentProcess(), lpModules
, cbNeeded
, &cbNeeded
);
453 nModules
= cbNeeded
/ sizeof(HMODULE
);
455 for ( iModule
= 0; !bSuccess
&& iModule
< nModules
; iModule
++ )
457 lpfnGetModuleInformation( GetCurrentProcess(), lpModules
[iModule
], &modinfo
, sizeof(modinfo
) );
459 if ( (BYTE
*)pv
>= (BYTE
*)modinfo
.lpBaseOfDll
&& (BYTE
*)pv
< (BYTE
*)modinfo
.lpBaseOfDll
+ modinfo
.SizeOfImage
)
461 WCHAR szBuffer
[MAX_PATH
];
462 rtl_uString
*ustrSysPath
= NULL
;
464 GetModuleFileNameW( lpModules
[iModule
], szBuffer
, bufsizeof(szBuffer
) );
466 rtl_uString_newFromStr( &ustrSysPath
, szBuffer
);
467 osl_getFileURLFromSystemPath( ustrSysPath
, pustrURL
);
468 rtl_uString_release( ustrSysPath
);
480 /*****************************************************************************/
481 /* Dispatcher for osl_osl_addressGetModuleURL */
482 /*****************************************************************************/
484 sal_Bool SAL_CALL
osl_getModuleURLFromAddress( void *pv
, rtl_uString
**pustrURL
)
486 /* Use ..._NT first because ..._NT4 is much slower */
488 return _osl_addressGetModuleURL_NT( pv
, pustrURL
) || _osl_addressGetModuleURL_NT4( pv
, pustrURL
);
490 return _osl_addressGetModuleURL_Windows( pv
, pustrURL
);
493 /*****************************************************************************/
494 /* osl_getModuleURLFromFunctionAddress */
495 /*****************************************************************************/
496 sal_Bool SAL_CALL
osl_getModuleURLFromFunctionAddress( oslGenericFunction addr
, rtl_uString
** ppLibraryUrl
)
498 /* casting a function pointer to a data pointer (void*) is
499 not allowed according to the C/C++ standards. In this case
500 it is unavoidable because we have to stay compatible we
501 cannot remove any function. */
503 #pragma warning(push)
504 #pragma warning(disable:4054)
506 return osl_getModuleURLFromAddress((void*)addr
, ppLibraryUrl
);