1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
33 #include "path_helper.hxx"
35 #include <osl/module.h>
36 #include <osl/diagnose.h>
37 #include <osl/thread.h>
39 #include <rtl/logfile.h>
43 under WIN32, we use the void* oslModule
44 as a WIN32 HANDLE (which is also a 32-bit value)
47 /*****************************************************************************/
49 /*****************************************************************************/
50 oslModule SAL_CALL
osl_loadModule(rtl_uString
*strModuleName
, sal_Int32
/*nRtldMode*/ )
53 #if OSL_DEBUG_LEVEL < 2
54 UINT errorMode
= SetErrorMode(SEM_NOOPENFILEERRORBOX
| SEM_FAILCRITICALERRORS
);
56 rtl_uString
* Module
= NULL
;
60 RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %S", (LPTSTR
)&strModuleName
->buffer
);
62 OSL_ASSERT(strModuleName
);
64 nError
= osl_getSystemPathFromFileURL(strModuleName
, &Module
);
66 if ( osl_File_E_None
!= nError
)
67 rtl_uString_assign(&Module
, strModuleName
);
69 hInstance
= LoadLibraryW(reinterpret_cast<LPCWSTR
>(Module
->buffer
));
71 if (hInstance
== NULL
)
72 hInstance
= LoadLibraryExW(reinterpret_cast<LPCWSTR
>(Module
->buffer
), NULL
,
73 LOAD_WITH_ALTERED_SEARCH_PATH
);
75 //In case of long path names (\\?\c:\...) try to shorten the filename.
76 //LoadLibrary cannot handle file names which exceed 260 letters.
77 //In case the path is to long, the function will fail. However, the error
78 //code can be different. For example, it returned ERROR_FILENAME_EXCED_RANGE
79 //on Windows XP and ERROR_INSUFFICIENT_BUFFER on Windows 7 (64bit)
80 if (hInstance
== NULL
&& Module
->length
> 260)
82 std::vector
<sal_Unicode
> vec(Module
->length
+ 1);
83 DWORD len
= GetShortPathNameW(reinterpret_cast<LPCWSTR
>(Module
->buffer
),
84 reinterpret_cast<LPWSTR
>(&vec
[0]), Module
->length
+ 1);
87 hInstance
= LoadLibraryW(reinterpret_cast<LPWSTR
>(&vec
[0]));
89 if (hInstance
== NULL
)
90 hInstance
= LoadLibraryExW(reinterpret_cast<LPWSTR
>(&vec
[0]), NULL
,
91 LOAD_WITH_ALTERED_SEARCH_PATH
);
96 if (hInstance
<= (HINSTANCE
)HINSTANCE_ERROR
)
99 ret
= (oslModule
) hInstance
;
100 rtl_uString_release(Module
);
101 #if OSL_DEBUG_LEVEL < 2
102 SetErrorMode(errorMode
);
105 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR
)&strModuleName
->buffer
);
110 /*****************************************************************************/
111 /* osl_loadModuleAscii */
112 /*****************************************************************************/
113 oslModule SAL_CALL
osl_loadModuleAscii(const sal_Char
*pModuleName
, sal_Int32 nRtldMode
)
115 (void) nRtldMode
; /* avoid warnings */
118 UINT errorMode
= SetErrorMode(SEM_NOOPENFILEERRORBOX
| SEM_FAILCRITICALERRORS
);
121 RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %s", pModuleName
);
123 OSL_ASSERT(pModuleName
);
125 hInstance
= LoadLibrary(pModuleName
);
126 if (hInstance
== NULL
)
127 hInstance
= LoadLibraryEx(pModuleName
, NULL
,
128 LOAD_WITH_ALTERED_SEARCH_PATH
);
130 if (hInstance
<= (HINSTANCE
)HINSTANCE_ERROR
)
133 ret
= (oslModule
) hInstance
;
134 SetErrorMode(errorMode
);
136 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %s", pModuleName
);
141 oslModule
osl_loadModuleRelativeAscii(
142 oslGenericFunction
, char const * relativePath
, sal_Int32 mode
)
144 return osl_loadModuleAscii(relativePath
, mode
); //TODO: FIXME
147 /*****************************************************************************/
148 /* osl_getModuleHandle */
149 /*****************************************************************************/
152 osl_getModuleHandle(rtl_uString
*pModuleName
, oslModule
*pResult
)
154 HINSTANCE hInstance
= GetModuleHandleW(reinterpret_cast<LPCWSTR
>(pModuleName
->buffer
));
157 *pResult
= (oslModule
) hInstance
;
164 /*****************************************************************************/
165 /* osl_unloadModule */
166 /*****************************************************************************/
167 void SAL_CALL
osl_unloadModule(oslModule Module
)
169 FreeLibrary((HINSTANCE
)Module
);
172 /*****************************************************************************/
174 /*****************************************************************************/
175 void* SAL_CALL
osl_getSymbol(oslModule Module
, rtl_uString
*strSymbolName
)
177 /* casting from a function pointer to a data pointer is invalid
178 be in this case unavoidable because the API has to stay
179 compitable we need to keep this function which returns a
180 void* by definition */
182 #pragma warning(push)
183 #pragma warning(disable:4054)
185 return (void*)(osl_getFunctionSymbol(Module
, strSymbolName
));
191 /*****************************************************************************/
192 /* osl_getFunctionSymbol */
193 /*****************************************************************************/
194 oslGenericFunction SAL_CALL
osl_getFunctionSymbol( oslModule Module
, rtl_uString
*strSymbolName
)
196 rtl_String
*symbolName
= NULL
;
197 oslGenericFunction address
;
200 OSL_ASSERT(strSymbolName
);
204 strSymbolName
->buffer
,
205 strSymbolName
->length
,
206 RTL_TEXTENCODING_UTF8
,
207 OUSTRING_TO_OSTRING_CVTFLAGS
210 address
=osl_getAsciiFunctionSymbol(Module
, rtl_string_getStr(symbolName
));
211 rtl_string_release(symbolName
);
216 /*****************************************************************************/
217 /* osl_getAsciiFunctionSymbol */
218 /*****************************************************************************/
219 oslGenericFunction SAL_CALL
220 osl_getAsciiFunctionSymbol( oslModule Module
, const sal_Char
*pSymbol
)
222 oslGenericFunction fncAddr
= NULL
;
225 fncAddr
=(oslGenericFunction
)GetProcAddress((HINSTANCE
) Module
, pSymbol
);
232 /*****************************************************************************/
233 /* osl_addressGetModuleURL */
234 /*****************************************************************************/
236 /*****************************************************************************/
237 /* Implementation for Windows 95, 98 and Me */
238 /*****************************************************************************/
240 /* Undefine because there is no explicit "A" definition */
246 #ifdef LPMODULEENTRY32
247 #undef LPMODULEENTRY32
250 /***************************************************************************************/
251 /* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
252 /***************************************************************************************/
255 #pragma warning(push,1) /* disable warnings within system headers */
257 #include <imagehlp.h>
262 typedef BOOL (WINAPI
*SymInitialize_PROC
)(
264 LPSTR UserSearchPath
,
268 typedef BOOL (WINAPI
*SymCleanup_PROC
)(
272 typedef BOOL (WINAPI
*SymGetModuleInfo_PROC
)(
275 PIMAGEHLP_MODULE ModuleInfo
278 /* 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
279 it's O.K on NT 4 ???!!!
280 BTW: We are using ANSI function because not all version of IMAGEHLP.DLL contain Unicode support
283 static sal_Bool SAL_CALL
_osl_addressGetModuleURL_NT4( void *pv
, rtl_uString
**pustrURL
)
285 sal_Bool bSuccess
= sal_False
; /* Assume failure */
287 /* IMAGEHELP.DLL has a bug that it recursivly scans subdirectories of
288 the root when calling SymInitialize(), so we preferr DBGHELP.DLL
289 which exports the same symbols and is shipped with OOo */
291 HMODULE hModImageHelp
= LoadLibrary( "DBGHELP.DLL" );
293 if ( !hModImageHelp
)
294 hModImageHelp
= LoadLibrary( "IMAGEHLP.DLL" );
298 SymGetModuleInfo_PROC lpfnSymGetModuleInfo
;
299 SymInitialize_PROC lpfnSymInitialize
;
300 SymCleanup_PROC lpfnSymCleanup
;
303 lpfnSymInitialize
= (SymInitialize_PROC
)GetProcAddress( hModImageHelp
, "SymInitialize" );
304 lpfnSymCleanup
= (SymCleanup_PROC
)GetProcAddress( hModImageHelp
, "SymCleanup" );
305 lpfnSymGetModuleInfo
= (SymGetModuleInfo_PROC
)GetProcAddress( hModImageHelp
, "SymGetModuleInfo" );
308 if ( lpfnSymInitialize
&& lpfnSymCleanup
&& lpfnSymGetModuleInfo
)
310 IMAGEHLP_MODULE ModuleInfo
;
311 ::osl::LongPathBuffer
< sal_Char
> aModuleFileName( MAX_LONG_PATH
);
312 LPSTR lpSearchPath
= NULL
;
314 if ( GetModuleFileNameA( NULL
, aModuleFileName
, aModuleFileName
.getBufSizeInSymbols() ) )
316 char *pLastBkSlash
= strrchr( aModuleFileName
, '\\' );
320 pLastBkSlash
> (sal_Char
*)aModuleFileName
321 && *(pLastBkSlash
- 1) != ':'
322 && *(pLastBkSlash
- 1) != '\\'
326 lpSearchPath
= aModuleFileName
;
330 lpfnSymInitialize( GetCurrentProcess(), lpSearchPath
, TRUE
);
332 ZeroMemory( &ModuleInfo
, sizeof(ModuleInfo
) );
333 ModuleInfo
.SizeOfStruct
= sizeof(ModuleInfo
);
335 bSuccess
= (sal_Bool
)(!!lpfnSymGetModuleInfo( GetCurrentProcess(), (DWORD
)pv
, &ModuleInfo
));
339 /* #99182 On localized (non-english) NT4 and XP (!!!) for some libraries the LoadedImageName member of ModuleInfo isn't filled. Because
340 other members ModuleName and ImageName do not contain the full path we can cast the Member
341 BaseOfImage to a HMODULE (on NT it's the same) and use GetModuleFileName to retrieve the full
342 path of the loaded image */
344 if ( ModuleInfo
.LoadedImageName
[0] || GetModuleFileNameA( (HMODULE
)ModuleInfo
.BaseOfImage
, ModuleInfo
.LoadedImageName
, sizeof(ModuleInfo
.LoadedImageName
) ) )
346 rtl_uString
*ustrSysPath
= NULL
;
348 rtl_string2UString( &ustrSysPath
, ModuleInfo
.LoadedImageName
, strlen(ModuleInfo
.LoadedImageName
), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS
);
349 OSL_ASSERT(ustrSysPath
!= NULL
);
350 osl_getFileURLFromSystemPath( ustrSysPath
, pustrURL
);
351 rtl_uString_release( ustrSysPath
);
354 bSuccess
= sal_False
;
357 lpfnSymCleanup( GetCurrentProcess() );
360 FreeLibrary( hModImageHelp
);
367 typedef struct _MODULEINFO
{
371 } MODULEINFO
, *LPMODULEINFO
;
373 typedef BOOL (WINAPI
*EnumProcessModules_PROC
)(
374 HANDLE hProcess
, // handle to the process
375 HMODULE
* lphModule
, // array to receive the module handles
376 DWORD cb
, // size of the array
377 LPDWORD lpcbNeeded
// receives the number of bytes returned
380 typedef BOOL (WINAPI
*GetModuleInformation_PROC
)(
381 HANDLE hProcess
, // handle to the process
382 HMODULE hModule
, // handle to the module
383 LPMODULEINFO lpmodinfo
, // structure that receives information
384 DWORD cb
// size of the structure
387 /* This version can fail because PSAPI.DLL is not always part of NT 4 despite MSDN Libary 6.0a say so */
389 static sal_Bool SAL_CALL
_osl_addressGetModuleURL_NT( void *pv
, rtl_uString
**pustrURL
)
391 sal_Bool bSuccess
= sal_False
; /* Assume failure */
392 static HMODULE hModPsapi
= NULL
;
395 hModPsapi
= LoadLibrary( "PSAPI.DLL" );
399 EnumProcessModules_PROC lpfnEnumProcessModules
= (EnumProcessModules_PROC
)GetProcAddress( hModPsapi
, "EnumProcessModules" );
400 GetModuleInformation_PROC lpfnGetModuleInformation
= (GetModuleInformation_PROC
)GetProcAddress( hModPsapi
, "GetModuleInformation" );
402 if ( lpfnEnumProcessModules
&& lpfnGetModuleInformation
)
405 HMODULE
*lpModules
= NULL
;
410 lpfnEnumProcessModules( GetCurrentProcess(), NULL
, 0, &cbNeeded
);
412 lpModules
= (HMODULE
*)_alloca( cbNeeded
);
413 lpfnEnumProcessModules( GetCurrentProcess(), lpModules
, cbNeeded
, &cbNeeded
);
415 nModules
= cbNeeded
/ sizeof(HMODULE
);
417 for ( iModule
= 0; !bSuccess
&& iModule
< nModules
; iModule
++ )
419 lpfnGetModuleInformation( GetCurrentProcess(), lpModules
[iModule
], &modinfo
, sizeof(modinfo
) );
421 if ( (BYTE
*)pv
>= (BYTE
*)modinfo
.lpBaseOfDll
&& (BYTE
*)pv
< (BYTE
*)modinfo
.lpBaseOfDll
+ modinfo
.SizeOfImage
)
423 ::osl::LongPathBuffer
< sal_Unicode
> aBuffer( MAX_LONG_PATH
);
424 rtl_uString
*ustrSysPath
= NULL
;
426 GetModuleFileNameW( lpModules
[iModule
], ::osl::mingw_reinterpret_cast
<LPWSTR
>(aBuffer
), aBuffer
.getBufSizeInSymbols() );
428 rtl_uString_newFromStr( &ustrSysPath
, aBuffer
);
429 osl_getFileURLFromSystemPath( ustrSysPath
, pustrURL
);
430 rtl_uString_release( ustrSysPath
);
442 /*****************************************************************************/
443 /* Dispatcher for osl_osl_addressGetModuleURL */
444 /*****************************************************************************/
446 sal_Bool SAL_CALL
osl_getModuleURLFromAddress( void *pv
, rtl_uString
**pustrURL
)
448 /* Use ..._NT first because ..._NT4 is much slower */
449 return _osl_addressGetModuleURL_NT( pv
, pustrURL
) || _osl_addressGetModuleURL_NT4( pv
, pustrURL
);
452 /*****************************************************************************/
453 /* osl_getModuleURLFromFunctionAddress */
454 /*****************************************************************************/
455 sal_Bool SAL_CALL
osl_getModuleURLFromFunctionAddress( oslGenericFunction addr
, rtl_uString
** ppLibraryUrl
)
457 /* casting a function pointer to a data pointer (void*) is
458 not allowed according to the C/C++ standards. In this case
459 it is unavoidable because we have to stay compatible we
460 cannot remove any function. */
462 #pragma warning(push)
463 #pragma warning(disable:4054)
465 return osl_getModuleURLFromAddress((void*)addr
, ppLibraryUrl
);
472 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */