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