update dev300-m58
[ooovba.git] / sal / osl / w32 / module.c
blobafef00989cfc5c41a4d366160d38b71ca648f0c6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: module.c,v $
10 * $Revision: 1.25 $
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 ************************************************************************/
32 #include "system.h"
33 #include <tlhelp32.h>
35 #include <osl/module.h>
36 #include <osl/diagnose.h>
37 #include <osl/thread.h>
38 #include <osl/file.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 /*****************************************************************************/
46 /* osl_loadModule */
47 /*****************************************************************************/
48 oslModule SAL_CALL osl_loadModule(rtl_uString *strModuleName, sal_Int32 nRtldMode )
50 HINSTANCE hInstance;
51 UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
52 rtl_uString* Module = NULL;
53 oslModule ret = 0;
54 oslFileError nError;
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)
73 hInstance = 0;
75 ret = (oslModule) hInstance;
76 rtl_uString_release(Module);
77 SetErrorMode(errorMode);
79 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR)&strModuleName->buffer );
81 return ret;
84 /*****************************************************************************/
85 /* osl_loadModuleAscii */
86 /*****************************************************************************/
87 oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode )
89 (void) nRtldMode; /* avoid warnings */
91 HINSTANCE hInstance;
92 UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
93 oslModule ret = 0;
94 oslFileError nError;
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)
106 hInstance = 0;
108 ret = (oslModule) hInstance;
109 SetErrorMode(errorMode);
111 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %s", pModuleName );
113 return ret;
116 /*****************************************************************************/
117 /* osl_getModuleHandle */
118 /*****************************************************************************/
120 sal_Bool SAL_CALL
121 osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
123 HINSTANCE hInstance = GetModuleHandleW(pModuleName->buffer);
124 if( hInstance )
126 *pResult = (oslModule) hInstance;
127 return sal_True;
130 return sal_False;
133 /*****************************************************************************/
134 /* osl_unloadModule */
135 /*****************************************************************************/
136 void SAL_CALL osl_unloadModule(oslModule Module)
138 FreeLibrary((HINSTANCE)Module);
141 /*****************************************************************************/
142 /* osl_getSymbol */
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 */
150 #ifdef _MSC_VER
151 #pragma warning(push)
152 #pragma warning(disable:4054)
153 #endif
154 return (void*)(osl_getFunctionSymbol(Module, strSymbolName));
155 #ifdef _MSC_VER
156 #pragma warning(pop)
157 #endif
160 /*****************************************************************************/
161 /* osl_getFunctionSymbol */
162 /*****************************************************************************/
163 oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
165 rtl_String *symbolName = NULL;
166 oslGenericFunction address;
168 OSL_ASSERT(Module);
169 OSL_ASSERT(strSymbolName);
171 rtl_uString2String(
172 &symbolName,
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);
182 return address;
185 /*****************************************************************************/
186 /* osl_getAsciiFunctionSymbol */
187 /*****************************************************************************/
188 oslGenericFunction SAL_CALL
189 osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
191 oslGenericFunction fncAddr = NULL;
193 if( pSymbol )
194 fncAddr=(oslGenericFunction)GetProcAddress((HINSTANCE) Module, pSymbol);
196 return fncAddr;
201 /*****************************************************************************/
202 /* osl_addressGetModuleURL */
203 /*****************************************************************************/
205 /*****************************************************************************/
206 /* Implementation for Windows 95, 98 and Me */
207 /*****************************************************************************/
209 /* Undefine because there is no explicit "A" definition */
211 #ifdef MODULEENTRY32
212 #undef MODULEENTRY32
213 #endif
215 #ifdef LPMODULEENTRY32
216 #undef LPMODULEENTRY32
217 #endif
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" );
228 if ( hModKernel32 )
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 );
268 bSuccess = sal_True;
271 } while ( !bSuccess && lpfnModule32Next( hModuleSnap, &me32 ) );
275 // Do not forget to clean up the snapshot object.
277 CloseHandle (hModuleSnap);
283 return bSuccess;
286 /***************************************************************************************/
287 /* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
288 /***************************************************************************************/
290 #ifdef _MSC_VER
291 #pragma warning(push,1) /* disable warnings within system headers */
292 #endif
293 #include <imagehlp.h>
294 #ifdef _MSC_VER
295 #pragma warning(pop)
296 #endif
298 typedef BOOL (WINAPI *SymInitialize_PROC)(
299 HANDLE hProcess,
300 LPSTR UserSearchPath,
301 BOOL fInvadeProcess
304 typedef BOOL (WINAPI *SymCleanup_PROC)(
305 HANDLE hProcess
308 typedef BOOL (WINAPI *SymGetModuleInfo_PROC)(
309 HANDLE hProcess,
310 DWORD dwAddr,
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" );
332 if ( hModImageHelp )
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, '\\' );
354 if (
355 pLastBkSlash &&
356 pLastBkSlash > szModuleFileName
357 && *(pLastBkSlash - 1) != ':'
358 && *(pLastBkSlash - 1) != '\\'
361 *pLastBkSlash = 0;
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 ));
373 if ( bSuccess )
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 );
389 else
390 bSuccess = sal_False;
393 lpfnSymCleanup( GetCurrentProcess() );
396 FreeLibrary( hModImageHelp );
399 return bSuccess;
403 typedef struct _MODULEINFO {
404 LPVOID lpBaseOfDll;
405 DWORD SizeOfImage;
406 LPVOID EntryPoint;
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;
432 if ( !hModPsapi )
433 hModPsapi = LoadLibrary( "PSAPI.DLL" );
435 if ( hModPsapi )
437 EnumProcessModules_PROC lpfnEnumProcessModules = (EnumProcessModules_PROC)GetProcAddress( hModPsapi, "EnumProcessModules" );
438 GetModuleInformation_PROC lpfnGetModuleInformation = (GetModuleInformation_PROC)GetProcAddress( hModPsapi, "GetModuleInformation" );
440 if ( lpfnEnumProcessModules && lpfnGetModuleInformation )
442 DWORD cbNeeded = 0;
443 HMODULE *lpModules = NULL;
444 DWORD nModules = 0;
445 UINT iModule = 0;
446 MODULEINFO modinfo;
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 );
470 bSuccess = sal_True;
477 return bSuccess;
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 */
487 if ( IS_NT )
488 return _osl_addressGetModuleURL_NT( pv, pustrURL ) || _osl_addressGetModuleURL_NT4( pv, pustrURL );
489 else
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. */
502 #ifdef _MSC_VER
503 #pragma warning(push)
504 #pragma warning(disable:4054)
505 #endif
506 return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
507 #ifdef _MSC_VER
508 #pragma warning(pop)
509 #endif