Bump for 3.6-28
[LibreOffice.git] / sal / osl / w32 / module.cxx
blob026cf514b50f37fbe78ad0cf14dbe319a6c2795e
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 ************************************************************************/
29 #include "system.h"
30 #include <tlhelp32.h>
32 #include "file_url.h"
33 #include "path_helper.hxx"
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>
40 #include <vector>
43 under WIN32, we use the void* oslModule
44 as a WIN32 HANDLE (which is also a 32-bit value)
47 /*****************************************************************************/
48 /* osl_loadModule */
49 /*****************************************************************************/
50 oslModule SAL_CALL osl_loadModule(rtl_uString *strModuleName, sal_Int32 /*nRtldMode*/ )
52 HINSTANCE hInstance;
53 #if OSL_DEBUG_LEVEL < 2
54 UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
55 #endif
56 rtl_uString* Module = NULL;
57 oslModule ret = 0;
58 oslFileError nError;
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);
85 if (len )
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)
97 hInstance = 0;
99 ret = (oslModule) hInstance;
100 rtl_uString_release(Module);
101 #if OSL_DEBUG_LEVEL < 2
102 SetErrorMode(errorMode);
103 #endif
105 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR)&strModuleName->buffer );
107 return ret;
110 /*****************************************************************************/
111 /* osl_loadModuleAscii */
112 /*****************************************************************************/
113 oslModule SAL_CALL osl_loadModuleAscii(const sal_Char *pModuleName, sal_Int32 nRtldMode )
115 (void) nRtldMode; /* avoid warnings */
117 HINSTANCE hInstance;
118 UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
119 oslModule ret = 0;
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)
131 hInstance = 0;
133 ret = (oslModule) hInstance;
134 SetErrorMode(errorMode);
136 RTL_LOGFILE_TRACE1( "} osl_loadModule end: %s", pModuleName );
138 return ret;
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 /*****************************************************************************/
151 sal_Bool SAL_CALL
152 osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
154 HINSTANCE hInstance = GetModuleHandleW(reinterpret_cast<LPCWSTR>(pModuleName->buffer));
155 if( hInstance )
157 *pResult = (oslModule) hInstance;
158 return sal_True;
161 return sal_False;
164 /*****************************************************************************/
165 /* osl_unloadModule */
166 /*****************************************************************************/
167 void SAL_CALL osl_unloadModule(oslModule Module)
169 FreeLibrary((HINSTANCE)Module);
172 /*****************************************************************************/
173 /* osl_getSymbol */
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 */
181 #ifdef _MSC_VER
182 #pragma warning(push)
183 #pragma warning(disable:4054)
184 #endif
185 return (void*)(osl_getFunctionSymbol(Module, strSymbolName));
186 #ifdef _MSC_VER
187 #pragma warning(pop)
188 #endif
191 /*****************************************************************************/
192 /* osl_getFunctionSymbol */
193 /*****************************************************************************/
194 oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
196 rtl_String *symbolName = NULL;
197 oslGenericFunction address;
199 OSL_ASSERT(Module);
200 OSL_ASSERT(strSymbolName);
202 rtl_uString2String(
203 &symbolName,
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);
213 return address;
216 /*****************************************************************************/
217 /* osl_getAsciiFunctionSymbol */
218 /*****************************************************************************/
219 oslGenericFunction SAL_CALL
220 osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
222 oslGenericFunction fncAddr = NULL;
224 if( pSymbol )
225 fncAddr=(oslGenericFunction)GetProcAddress((HINSTANCE) Module, pSymbol);
227 return fncAddr;
232 /*****************************************************************************/
233 /* osl_addressGetModuleURL */
234 /*****************************************************************************/
236 /*****************************************************************************/
237 /* Implementation for Windows 95, 98 and Me */
238 /*****************************************************************************/
240 /* Undefine because there is no explicit "A" definition */
242 #ifdef MODULEENTRY32
243 #undef MODULEENTRY32
244 #endif
246 #ifdef LPMODULEENTRY32
247 #undef LPMODULEENTRY32
248 #endif
250 /***************************************************************************************/
251 /* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
252 /***************************************************************************************/
254 #ifdef _MSC_VER
255 #pragma warning(push,1) /* disable warnings within system headers */
256 #endif
257 #include <imagehlp.h>
258 #ifdef _MSC_VER
259 #pragma warning(pop)
260 #endif
262 typedef BOOL (WINAPI *SymInitialize_PROC)(
263 HANDLE hProcess,
264 LPSTR UserSearchPath,
265 BOOL fInvadeProcess
268 typedef BOOL (WINAPI *SymCleanup_PROC)(
269 HANDLE hProcess
272 typedef BOOL (WINAPI *SymGetModuleInfo_PROC)(
273 HANDLE hProcess,
274 DWORD dwAddr,
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" );
296 if ( hModImageHelp )
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, '\\' );
318 if (
319 pLastBkSlash &&
320 pLastBkSlash > (sal_Char*)aModuleFileName
321 && *(pLastBkSlash - 1) != ':'
322 && *(pLastBkSlash - 1) != '\\'
325 *pLastBkSlash = 0;
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 ));
337 if ( bSuccess )
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 );
353 else
354 bSuccess = sal_False;
357 lpfnSymCleanup( GetCurrentProcess() );
360 FreeLibrary( hModImageHelp );
363 return bSuccess;
367 typedef struct _MODULEINFO {
368 LPVOID lpBaseOfDll;
369 DWORD SizeOfImage;
370 LPVOID EntryPoint;
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;
394 if ( !hModPsapi )
395 hModPsapi = LoadLibrary( "PSAPI.DLL" );
397 if ( hModPsapi )
399 EnumProcessModules_PROC lpfnEnumProcessModules = (EnumProcessModules_PROC)GetProcAddress( hModPsapi, "EnumProcessModules" );
400 GetModuleInformation_PROC lpfnGetModuleInformation = (GetModuleInformation_PROC)GetProcAddress( hModPsapi, "GetModuleInformation" );
402 if ( lpfnEnumProcessModules && lpfnGetModuleInformation )
404 DWORD cbNeeded = 0;
405 HMODULE *lpModules = NULL;
406 DWORD nModules = 0;
407 UINT iModule = 0;
408 MODULEINFO modinfo;
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 );
432 bSuccess = sal_True;
439 return bSuccess;
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. */
461 #ifdef _MSC_VER
462 #pragma warning(push)
463 #pragma warning(disable:4054)
464 #endif
465 return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
466 #ifdef _MSC_VER
467 #pragma warning(pop)
468 #endif
472 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */