xref: /trunk/main/sal/osl/w32/module.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir *
3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir *
5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir *
7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir *
9*cdf0e10cSrcweir * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir *
11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir *
15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir *
21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir *
26*cdf0e10cSrcweir ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "system.h"
29*cdf0e10cSrcweir #include <tlhelp32.h>
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "file_url.h"
32*cdf0e10cSrcweir #include "path_helper.hxx"
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir #include <osl/module.h>
35*cdf0e10cSrcweir #include <osl/diagnose.h>
36*cdf0e10cSrcweir #include <osl/thread.h>
37*cdf0e10cSrcweir #include <osl/file.h>
38*cdf0e10cSrcweir #include <rtl/logfile.h>
39*cdf0e10cSrcweir #include <vector>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir /*
42*cdf0e10cSrcweir 	under WIN32, we use the void* oslModule
43*cdf0e10cSrcweir 	as a WIN32 HANDLE (which is also a 32-bit value)
44*cdf0e10cSrcweir */
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir /*****************************************************************************/
47*cdf0e10cSrcweir /* osl_loadModule */
48*cdf0e10cSrcweir /*****************************************************************************/
49*cdf0e10cSrcweir oslModule SAL_CALL osl_loadModule(rtl_uString *strModuleName, sal_Int32 nRtldMode )
50*cdf0e10cSrcweir {
51*cdf0e10cSrcweir     HINSTANCE hInstance;
52*cdf0e10cSrcweir 	UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
53*cdf0e10cSrcweir 	rtl_uString* Module = NULL;
54*cdf0e10cSrcweir 	oslModule ret = 0;
55*cdf0e10cSrcweir 	oslFileError	nError;
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir     RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %S", (LPTSTR)&strModuleName->buffer );
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir 	OSL_ASSERT(strModuleName);
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir     nRtldMode = nRtldMode; /* avoid warnings */
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir 	nError = osl_getSystemPathFromFileURL(strModuleName, &Module);
64*cdf0e10cSrcweir 
65*cdf0e10cSrcweir 	if ( osl_File_E_None != nError )
66*cdf0e10cSrcweir 		rtl_uString_assign(&Module, strModuleName);
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir 	hInstance = LoadLibraryW(reinterpret_cast<LPCWSTR>(Module->buffer));
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir     if (hInstance == NULL)
71*cdf0e10cSrcweir         hInstance = LoadLibraryExW(reinterpret_cast<LPCWSTR>(Module->buffer), NULL,
72*cdf0e10cSrcweir                                   LOAD_WITH_ALTERED_SEARCH_PATH);
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir 	//In case of long path names (\\?\c:\...) try to shorten the filename.
75*cdf0e10cSrcweir 	//LoadLibrary cannot handle file names which exceed 260 letters.
76*cdf0e10cSrcweir     //In case the path is to long, the function will fail. However, the error
77*cdf0e10cSrcweir     //code can be different. For example, it returned  ERROR_FILENAME_EXCED_RANGE
78*cdf0e10cSrcweir     //on Windows XP and ERROR_INSUFFICIENT_BUFFER on Windows 7 (64bit)
79*cdf0e10cSrcweir 	if (hInstance == NULL && Module->length > 260)
80*cdf0e10cSrcweir 	{
81*cdf0e10cSrcweir         std::vector<WCHAR, rtl::Allocator<WCHAR> > vec(Module->length + 1);
82*cdf0e10cSrcweir 		DWORD len = GetShortPathNameW(reinterpret_cast<LPCWSTR>(Module->buffer),
83*cdf0e10cSrcweir                                       &vec[0], Module->length + 1);
84*cdf0e10cSrcweir 		if (len )
85*cdf0e10cSrcweir 		{
86*cdf0e10cSrcweir 			hInstance = LoadLibraryW(&vec[0]);
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir 			if (hInstance == NULL)
89*cdf0e10cSrcweir 				hInstance = LoadLibraryExW(&vec[0], NULL,
90*cdf0e10cSrcweir                                   LOAD_WITH_ALTERED_SEARCH_PATH);
91*cdf0e10cSrcweir 		}
92*cdf0e10cSrcweir 	}
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir 	if (hInstance <= (HINSTANCE)HINSTANCE_ERROR)
96*cdf0e10cSrcweir 		hInstance = 0;
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir 	ret = (oslModule) hInstance;
99*cdf0e10cSrcweir 	rtl_uString_release(Module);
100*cdf0e10cSrcweir 	SetErrorMode(errorMode);
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir     RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR)&strModuleName->buffer );
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir 	return ret;
105*cdf0e10cSrcweir }
106*cdf0e10cSrcweir 
107*cdf0e10cSrcweir /*****************************************************************************/
108*cdf0e10cSrcweir /* osl_getModuleHandle */
109*cdf0e10cSrcweir /*****************************************************************************/
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir sal_Bool SAL_CALL
112*cdf0e10cSrcweir osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
113*cdf0e10cSrcweir {
114*cdf0e10cSrcweir     HINSTANCE hInstance = GetModuleHandleW(reinterpret_cast<LPCWSTR>(pModuleName->buffer));
115*cdf0e10cSrcweir     if( hInstance )
116*cdf0e10cSrcweir     {
117*cdf0e10cSrcweir         *pResult = (oslModule) hInstance;
118*cdf0e10cSrcweir         return sal_True;
119*cdf0e10cSrcweir     }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir     return sal_False;
122*cdf0e10cSrcweir }
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir /*****************************************************************************/
125*cdf0e10cSrcweir /* osl_unloadModule */
126*cdf0e10cSrcweir /*****************************************************************************/
127*cdf0e10cSrcweir void SAL_CALL osl_unloadModule(oslModule Module)
128*cdf0e10cSrcweir {
129*cdf0e10cSrcweir 	FreeLibrary((HINSTANCE)Module);
130*cdf0e10cSrcweir }
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir /*****************************************************************************/
133*cdf0e10cSrcweir /* osl_getSymbol */
134*cdf0e10cSrcweir /*****************************************************************************/
135*cdf0e10cSrcweir void* SAL_CALL osl_getSymbol(oslModule Module, rtl_uString *strSymbolName)
136*cdf0e10cSrcweir {
137*cdf0e10cSrcweir     /* casting from a function pointer to a data pointer is invalid
138*cdf0e10cSrcweir        be in this case unavoidable because the API has to stay
139*cdf0e10cSrcweir        compitable we need to keep this function which returns a
140*cdf0e10cSrcweir        void* by definition */
141*cdf0e10cSrcweir #ifdef _MSC_VER
142*cdf0e10cSrcweir #pragma warning(push)
143*cdf0e10cSrcweir #pragma warning(disable:4054)
144*cdf0e10cSrcweir #endif
145*cdf0e10cSrcweir     return (void*)(osl_getFunctionSymbol(Module, strSymbolName));
146*cdf0e10cSrcweir #ifdef _MSC_VER
147*cdf0e10cSrcweir #pragma warning(pop)
148*cdf0e10cSrcweir #endif
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir /*****************************************************************************/
152*cdf0e10cSrcweir /* osl_getFunctionSymbol */
153*cdf0e10cSrcweir /*****************************************************************************/
154*cdf0e10cSrcweir oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
155*cdf0e10cSrcweir {
156*cdf0e10cSrcweir     rtl_String *symbolName = NULL;
157*cdf0e10cSrcweir 	oslGenericFunction address;
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir 	OSL_ASSERT(Module);
160*cdf0e10cSrcweir 	OSL_ASSERT(strSymbolName);
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir 	rtl_uString2String(
163*cdf0e10cSrcweir 		&symbolName,
164*cdf0e10cSrcweir 		strSymbolName->buffer,
165*cdf0e10cSrcweir 		strSymbolName->length,
166*cdf0e10cSrcweir 		RTL_TEXTENCODING_UTF8,
167*cdf0e10cSrcweir 		OUSTRING_TO_OSTRING_CVTFLAGS
168*cdf0e10cSrcweir 	);
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir 	address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName));
171*cdf0e10cSrcweir 	rtl_string_release(symbolName);
172*cdf0e10cSrcweir 
173*cdf0e10cSrcweir     return address;
174*cdf0e10cSrcweir }
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir /*****************************************************************************/
177*cdf0e10cSrcweir /* osl_getAsciiFunctionSymbol */
178*cdf0e10cSrcweir /*****************************************************************************/
179*cdf0e10cSrcweir oslGenericFunction SAL_CALL
180*cdf0e10cSrcweir osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
181*cdf0e10cSrcweir {
182*cdf0e10cSrcweir 	oslGenericFunction fncAddr = NULL;
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir     if( pSymbol )
185*cdf0e10cSrcweir         fncAddr=(oslGenericFunction)GetProcAddress((HINSTANCE) Module, pSymbol);
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir     return fncAddr;
188*cdf0e10cSrcweir }
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir /*****************************************************************************/
193*cdf0e10cSrcweir /* osl_addressGetModuleURL */
194*cdf0e10cSrcweir /*****************************************************************************/
195*cdf0e10cSrcweir 
196*cdf0e10cSrcweir /*****************************************************************************/
197*cdf0e10cSrcweir /* Implementation for Windows 95, 98 and Me */
198*cdf0e10cSrcweir /*****************************************************************************/
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir /* Undefine because there is no explicit "A" definition */
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir #ifdef MODULEENTRY32
203*cdf0e10cSrcweir #undef MODULEENTRY32
204*cdf0e10cSrcweir #endif
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir #ifdef LPMODULEENTRY32
207*cdf0e10cSrcweir #undef LPMODULEENTRY32
208*cdf0e10cSrcweir #endif
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_PROC)( DWORD dwFlags, DWORD th32ProcessID );
211*cdf0e10cSrcweir typedef BOOL (WINAPI *Module32First_PROC)( HANDLE	hSnapshot, LPMODULEENTRY32 lpme32 );
212*cdf0e10cSrcweir typedef BOOL (WINAPI *Module32Next_PROC)( HANDLE	hSnapshot, LPMODULEENTRY32 lpme32 );
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir static sal_Bool SAL_CALL _osl_addressGetModuleURL_Windows( void *pv, rtl_uString **pustrURL )
215*cdf0e10cSrcweir {
216*cdf0e10cSrcweir 	sal_Bool	bSuccess		= sal_False;	/* Assume failure */
217*cdf0e10cSrcweir 	HMODULE		hModKernel32	= GetModuleHandleA( "KERNEL32.DLL" );
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir 	if ( hModKernel32 )
220*cdf0e10cSrcweir 	{
221*cdf0e10cSrcweir 		CreateToolhelp32Snapshot_PROC	lpfnCreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_PROC)GetProcAddress( hModKernel32, "CreateToolhelp32Snapshot" );
222*cdf0e10cSrcweir 		Module32First_PROC				lpfnModule32First = (Module32First_PROC)GetProcAddress( hModKernel32, "Module32First" );
223*cdf0e10cSrcweir 		Module32Next_PROC				lpfnModule32Next = (Module32Next_PROC)GetProcAddress( hModKernel32, "Module32Next" );
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir 		if ( lpfnCreateToolhelp32Snapshot && lpfnModule32First && lpfnModule32Next )
226*cdf0e10cSrcweir 		{
227*cdf0e10cSrcweir 			HANDLE	hModuleSnap	= NULL;
228*cdf0e10cSrcweir 			DWORD	dwProcessId = GetCurrentProcessId();
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir 			// Take a snapshot of all modules in the specified process.
231*cdf0e10cSrcweir 
232*cdf0e10cSrcweir 			hModuleSnap = lpfnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId );
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir 			if ( INVALID_HANDLE_VALUE != hModuleSnap )
235*cdf0e10cSrcweir 			{
236*cdf0e10cSrcweir 				MODULEENTRY32	me32	= {0};
237*cdf0e10cSrcweir 
238*cdf0e10cSrcweir 				// Fill the size of the structure before using it.
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir 				me32.dwSize = sizeof(MODULEENTRY32);
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir 				// Walk the module list of the process, and find the module of
243*cdf0e10cSrcweir 				// interest. Then copy the information to the buffer pointed
244*cdf0e10cSrcweir 				// to by lpMe32 so that it can be returned to the caller.
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir 				if ( lpfnModule32First(hModuleSnap, &me32) )
247*cdf0e10cSrcweir 				{
248*cdf0e10cSrcweir 					do
249*cdf0e10cSrcweir 					{
250*cdf0e10cSrcweir 						if ( (BYTE *)pv >= (BYTE *)me32.hModule && (BYTE *)pv < (BYTE *)me32.hModule + me32.modBaseSize )
251*cdf0e10cSrcweir 						{
252*cdf0e10cSrcweir 							rtl_uString	*ustrSysPath = NULL;
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir 							rtl_string2UString( &ustrSysPath, me32.szExePath, strlen(me32.szExePath), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
255*cdf0e10cSrcweir                             OSL_ASSERT(ustrSysPath != NULL);
256*cdf0e10cSrcweir 							osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
257*cdf0e10cSrcweir 							rtl_uString_release( ustrSysPath );
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir 							bSuccess = sal_True;
260*cdf0e10cSrcweir 						}
261*cdf0e10cSrcweir 
262*cdf0e10cSrcweir 					} while ( !bSuccess && lpfnModule32Next( hModuleSnap, &me32 ) );
263*cdf0e10cSrcweir 				}
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir 				// Do not forget to clean up the snapshot object.
267*cdf0e10cSrcweir 
268*cdf0e10cSrcweir 				CloseHandle (hModuleSnap);
269*cdf0e10cSrcweir 			}
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir 		}
272*cdf0e10cSrcweir 	}
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir 	return	bSuccess;
275*cdf0e10cSrcweir }
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir /***************************************************************************************/
278*cdf0e10cSrcweir /* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
279*cdf0e10cSrcweir /***************************************************************************************/
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir #ifdef _MSC_VER
282*cdf0e10cSrcweir #pragma warning(push,1) /* disable warnings within system headers */
283*cdf0e10cSrcweir #endif
284*cdf0e10cSrcweir #include <imagehlp.h>
285*cdf0e10cSrcweir #ifdef _MSC_VER
286*cdf0e10cSrcweir #pragma warning(pop)
287*cdf0e10cSrcweir #endif
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir typedef BOOL (WINAPI *SymInitialize_PROC)(
290*cdf0e10cSrcweir     HANDLE   hProcess,
291*cdf0e10cSrcweir     LPSTR    UserSearchPath,
292*cdf0e10cSrcweir     BOOL     fInvadeProcess
293*cdf0e10cSrcweir     );
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir typedef BOOL (WINAPI *SymCleanup_PROC)(
296*cdf0e10cSrcweir     HANDLE hProcess
297*cdf0e10cSrcweir 	);
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir typedef BOOL (WINAPI *SymGetModuleInfo_PROC)(
300*cdf0e10cSrcweir     HANDLE              hProcess,
301*cdf0e10cSrcweir     DWORD               dwAddr,
302*cdf0e10cSrcweir     PIMAGEHLP_MODULE  ModuleInfo
303*cdf0e10cSrcweir     );
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir /* 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
306*cdf0e10cSrcweir 	it's O.K on NT 4 ???!!!
307*cdf0e10cSrcweir 	BTW: We are using ANSI function because not all version of IMAGEHLP.DLL contain Unicode support
308*cdf0e10cSrcweir */
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT4( void *pv, rtl_uString **pustrURL )
311*cdf0e10cSrcweir {
312*cdf0e10cSrcweir 	sal_Bool	bSuccess	= sal_False;	/* Assume failure */
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir 	/*	IMAGEHELP.DLL has a bug that it recursivly scans subdirectories of
315*cdf0e10cSrcweir 		the root when calling SymInitialize(), so we preferr DBGHELP.DLL
316*cdf0e10cSrcweir 		which exports the same symbols and is shipped with OOo */
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 	HMODULE		hModImageHelp = LoadLibrary( "DBGHELP.DLL" );
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir 	if ( !hModImageHelp )
321*cdf0e10cSrcweir 		hModImageHelp = LoadLibrary( "IMAGEHLP.DLL" );
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir 	if ( hModImageHelp )
324*cdf0e10cSrcweir 	{
325*cdf0e10cSrcweir 		SymGetModuleInfo_PROC	lpfnSymGetModuleInfo;
326*cdf0e10cSrcweir 		SymInitialize_PROC		lpfnSymInitialize;
327*cdf0e10cSrcweir 		SymCleanup_PROC			lpfnSymCleanup;
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir 
330*cdf0e10cSrcweir 		lpfnSymInitialize = (SymInitialize_PROC)GetProcAddress( hModImageHelp, "SymInitialize" );
331*cdf0e10cSrcweir 		lpfnSymCleanup = (SymCleanup_PROC)GetProcAddress( hModImageHelp, "SymCleanup" );
332*cdf0e10cSrcweir 		lpfnSymGetModuleInfo = (SymGetModuleInfo_PROC)GetProcAddress( hModImageHelp, "SymGetModuleInfo" );
333*cdf0e10cSrcweir 
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir 		if ( lpfnSymInitialize && lpfnSymCleanup && lpfnSymGetModuleInfo )
336*cdf0e10cSrcweir 		{
337*cdf0e10cSrcweir 			IMAGEHLP_MODULE	ModuleInfo;
338*cdf0e10cSrcweir 			::osl::LongPathBuffer< sal_Char > aModuleFileName( MAX_LONG_PATH );
339*cdf0e10cSrcweir 			LPSTR	lpSearchPath = NULL;
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir 			if ( GetModuleFileNameA( NULL, aModuleFileName, aModuleFileName.getBufSizeInSymbols() ) )
342*cdf0e10cSrcweir 			{
343*cdf0e10cSrcweir 				char *pLastBkSlash = strrchr( aModuleFileName, '\\' );
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 				if (
346*cdf0e10cSrcweir 					pLastBkSlash &&
347*cdf0e10cSrcweir 					pLastBkSlash > (sal_Char*)aModuleFileName
348*cdf0e10cSrcweir 					&& *(pLastBkSlash - 1) != ':'
349*cdf0e10cSrcweir 					&& *(pLastBkSlash - 1) != '\\'
350*cdf0e10cSrcweir 					)
351*cdf0e10cSrcweir 				{
352*cdf0e10cSrcweir 					*pLastBkSlash = 0;
353*cdf0e10cSrcweir 					lpSearchPath = aModuleFileName;
354*cdf0e10cSrcweir 				}
355*cdf0e10cSrcweir 			}
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir 			lpfnSymInitialize( GetCurrentProcess(), lpSearchPath, TRUE );
358*cdf0e10cSrcweir 
359*cdf0e10cSrcweir 			ZeroMemory( &ModuleInfo, sizeof(ModuleInfo) );
360*cdf0e10cSrcweir 			ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir 			bSuccess = (sal_Bool)(!!lpfnSymGetModuleInfo( GetCurrentProcess(), (DWORD)pv, &ModuleInfo ));
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir 			if ( bSuccess )
365*cdf0e10cSrcweir 			{
366*cdf0e10cSrcweir 				/*	#99182 On localized (non-english) NT4 and XP (!!!) for some libraries the LoadedImageName member of ModuleInfo isn't filled. Because
367*cdf0e10cSrcweir 					other members ModuleName and ImageName do not contain the full path we can cast the Member
368*cdf0e10cSrcweir 					BaseOfImage to a HMODULE (on NT it's the same) and use GetModuleFileName to retrieve the full
369*cdf0e10cSrcweir 					path of the loaded image */
370*cdf0e10cSrcweir 
371*cdf0e10cSrcweir 				if ( ModuleInfo.LoadedImageName[0] || GetModuleFileNameA( (HMODULE)ModuleInfo.BaseOfImage, ModuleInfo.LoadedImageName, sizeof(ModuleInfo.LoadedImageName) ) )
372*cdf0e10cSrcweir 				{
373*cdf0e10cSrcweir 					rtl_uString	*ustrSysPath = NULL;
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir 					rtl_string2UString( &ustrSysPath, ModuleInfo.LoadedImageName, strlen(ModuleInfo.LoadedImageName), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
376*cdf0e10cSrcweir                     OSL_ASSERT(ustrSysPath != NULL);
377*cdf0e10cSrcweir 					osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
378*cdf0e10cSrcweir 					rtl_uString_release( ustrSysPath );
379*cdf0e10cSrcweir 				}
380*cdf0e10cSrcweir 				else
381*cdf0e10cSrcweir 					bSuccess = sal_False;
382*cdf0e10cSrcweir 			}
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir 			lpfnSymCleanup( GetCurrentProcess() );
385*cdf0e10cSrcweir 		}
386*cdf0e10cSrcweir 
387*cdf0e10cSrcweir 		FreeLibrary( hModImageHelp );
388*cdf0e10cSrcweir 	}
389*cdf0e10cSrcweir 
390*cdf0e10cSrcweir 	return bSuccess;
391*cdf0e10cSrcweir }
392*cdf0e10cSrcweir 
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir typedef struct _MODULEINFO {
395*cdf0e10cSrcweir     LPVOID lpBaseOfDll;
396*cdf0e10cSrcweir     DWORD SizeOfImage;
397*cdf0e10cSrcweir     LPVOID EntryPoint;
398*cdf0e10cSrcweir } MODULEINFO, *LPMODULEINFO;
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir typedef BOOL (WINAPI *EnumProcessModules_PROC)(
401*cdf0e10cSrcweir   HANDLE hProcess,      // handle to the process
402*cdf0e10cSrcweir   HMODULE * lphModule,  // array to receive the module handles
403*cdf0e10cSrcweir   DWORD cb,             // size of the array
404*cdf0e10cSrcweir   LPDWORD lpcbNeeded    // receives the number of bytes returned
405*cdf0e10cSrcweir );
406*cdf0e10cSrcweir 
407*cdf0e10cSrcweir typedef BOOL (WINAPI *GetModuleInformation_PROC)(
408*cdf0e10cSrcweir   HANDLE hProcess,         // handle to the process
409*cdf0e10cSrcweir   HMODULE hModule,         // handle to the module
410*cdf0e10cSrcweir   LPMODULEINFO lpmodinfo,  // structure that receives information
411*cdf0e10cSrcweir   DWORD cb                 // size of the structure
412*cdf0e10cSrcweir );
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir #define bufsizeof(buffer) (sizeof(buffer) / sizeof((buffer)[0]))
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir /* This version can fail because PSAPI.DLL is not always part of NT 4 despite MSDN Libary 6.0a say so */
417*cdf0e10cSrcweir 
418*cdf0e10cSrcweir static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT( void *pv, rtl_uString **pustrURL )
419*cdf0e10cSrcweir {
420*cdf0e10cSrcweir 	sal_Bool	bSuccess	= sal_False;	/* Assume failure */
421*cdf0e10cSrcweir 	static HMODULE		hModPsapi = NULL;
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir 	if ( !hModPsapi )
424*cdf0e10cSrcweir 		hModPsapi = LoadLibrary( "PSAPI.DLL" );
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir 	if ( hModPsapi )
427*cdf0e10cSrcweir 	{
428*cdf0e10cSrcweir 		EnumProcessModules_PROC		lpfnEnumProcessModules		= (EnumProcessModules_PROC)GetProcAddress( hModPsapi, "EnumProcessModules" );
429*cdf0e10cSrcweir 		GetModuleInformation_PROC	lpfnGetModuleInformation	= (GetModuleInformation_PROC)GetProcAddress( hModPsapi, "GetModuleInformation" );
430*cdf0e10cSrcweir 
431*cdf0e10cSrcweir 		if ( lpfnEnumProcessModules && lpfnGetModuleInformation )
432*cdf0e10cSrcweir 		{
433*cdf0e10cSrcweir 			DWORD		cbNeeded = 0;
434*cdf0e10cSrcweir 			HMODULE		*lpModules = NULL;
435*cdf0e10cSrcweir 			DWORD		nModules = 0;
436*cdf0e10cSrcweir 			UINT		iModule = 0;
437*cdf0e10cSrcweir 			MODULEINFO	modinfo;
438*cdf0e10cSrcweir 
439*cdf0e10cSrcweir 			lpfnEnumProcessModules( GetCurrentProcess(), NULL, 0, &cbNeeded );
440*cdf0e10cSrcweir 
441*cdf0e10cSrcweir 			lpModules = (HMODULE *)_alloca( cbNeeded );
442*cdf0e10cSrcweir 			lpfnEnumProcessModules( GetCurrentProcess(), lpModules, cbNeeded, &cbNeeded );
443*cdf0e10cSrcweir 
444*cdf0e10cSrcweir 			nModules = cbNeeded / sizeof(HMODULE);
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir 			for ( iModule = 0; !bSuccess && iModule < nModules; iModule++ )
447*cdf0e10cSrcweir 			{
448*cdf0e10cSrcweir 				lpfnGetModuleInformation( GetCurrentProcess(), lpModules[iModule], &modinfo, sizeof(modinfo) );
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir 				if ( (BYTE *)pv >= (BYTE *)modinfo.lpBaseOfDll && (BYTE *)pv < (BYTE *)modinfo.lpBaseOfDll + modinfo.SizeOfImage )
451*cdf0e10cSrcweir 				{
452*cdf0e10cSrcweir                     ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
453*cdf0e10cSrcweir 					rtl_uString	*ustrSysPath = NULL;
454*cdf0e10cSrcweir 
455*cdf0e10cSrcweir 					GetModuleFileNameW( lpModules[iModule], ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols() );
456*cdf0e10cSrcweir 
457*cdf0e10cSrcweir 					rtl_uString_newFromStr( &ustrSysPath, aBuffer );
458*cdf0e10cSrcweir 					osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
459*cdf0e10cSrcweir 					rtl_uString_release( ustrSysPath );
460*cdf0e10cSrcweir 
461*cdf0e10cSrcweir 					bSuccess = sal_True;
462*cdf0e10cSrcweir 				}
463*cdf0e10cSrcweir 			}
464*cdf0e10cSrcweir 		}
465*cdf0e10cSrcweir 
466*cdf0e10cSrcweir 	}
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir 	return bSuccess;
469*cdf0e10cSrcweir }
470*cdf0e10cSrcweir 
471*cdf0e10cSrcweir /*****************************************************************************/
472*cdf0e10cSrcweir /* Dispatcher for osl_osl_addressGetModuleURL */
473*cdf0e10cSrcweir /*****************************************************************************/
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir sal_Bool SAL_CALL osl_getModuleURLFromAddress( void *pv, rtl_uString **pustrURL )
476*cdf0e10cSrcweir {
477*cdf0e10cSrcweir 	/* Use ..._NT first because ..._NT4 is much slower */
478*cdf0e10cSrcweir 	if ( IS_NT )
479*cdf0e10cSrcweir 		return _osl_addressGetModuleURL_NT( pv, pustrURL ) || _osl_addressGetModuleURL_NT4( pv, pustrURL );
480*cdf0e10cSrcweir 	else
481*cdf0e10cSrcweir 		return _osl_addressGetModuleURL_Windows( pv, pustrURL );
482*cdf0e10cSrcweir }
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir /*****************************************************************************/
485*cdf0e10cSrcweir /* osl_getModuleURLFromFunctionAddress */
486*cdf0e10cSrcweir /*****************************************************************************/
487*cdf0e10cSrcweir sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl )
488*cdf0e10cSrcweir {
489*cdf0e10cSrcweir     /* casting a function pointer to a data pointer (void*) is
490*cdf0e10cSrcweir        not allowed according to the C/C++ standards. In this case
491*cdf0e10cSrcweir        it is unavoidable because we have to stay compatible we
492*cdf0e10cSrcweir        cannot remove any function. */
493*cdf0e10cSrcweir #ifdef _MSC_VER
494*cdf0e10cSrcweir #pragma warning(push)
495*cdf0e10cSrcweir #pragma warning(disable:4054)
496*cdf0e10cSrcweir #endif
497*cdf0e10cSrcweir     return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
498*cdf0e10cSrcweir #ifdef _MSC_VER
499*cdf0e10cSrcweir #pragma warning(pop)
500*cdf0e10cSrcweir #endif
501*cdf0e10cSrcweir }
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 
504