1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24
25 #include <osl/module.h>
26 #include <osl/diagnose.h>
27 #include <osl/file.h>
28 #include <osl/thread.h>
29
30 #include <stdlib.h>
31 #include <dlfcn.h>
32
33 #include "system.h"
34
35 /* implemented in file.cxx */
36 int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
37
38 /*****************************************************************************/
39 /* osl_loadModule */
40 /*****************************************************************************/
41
osl_loadModule(rtl_uString * ustrModuleName,sal_Int32 nRtldMode)42 oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
43 {
44 oslModule pModule=0;
45 rtl_uString* ustrTmp = NULL;
46
47 OSL_ENSURE(ustrModuleName,"osl_loadModule : string is not valid");
48
49 /* ensure ustrTmp hold valid string */
50 if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
51 rtl_uString_assign(&ustrTmp, ustrModuleName);
52
53 if (ustrTmp)
54 {
55 char buffer[PATH_MAX];
56
57 if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
58 pModule = osl_loadAsciiModule(buffer, nRtldMode);
59 rtl_uString_release(ustrTmp);
60 }
61
62 return pModule;
63 }
64
65 /*****************************************************************************/
66 /* osl_loadAsciiModule */
67 /*****************************************************************************/
68
osl_loadAsciiModule(const sal_Char * pszModuleName,sal_Int32 nRtldMode)69 oslModule SAL_CALL osl_loadAsciiModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode)
70 {
71 char drive[_MAX_DRIVE], dir[_MAX_DIR];
72 char fname[_MAX_FNAME], ext[_MAX_EXT];
73 char buffer[PATH_MAX];
74 char* dot;
75 void* hModule;
76
77 if (!pszModuleName)
78 return NULL;
79
80 // 21/02/2006 YD dll names must be 8.3: since .uno.dll files
81 // have hardcoded names, I'm truncating names here and also in
82 // the build system
83 _splitpath (pszModuleName, drive, dir, fname, ext);
84 if (strlen(fname)>8)
85 fname[8] = 0; // truncate to 8.3
86 dot = strchr( fname, '.');
87 if (dot)
88 *dot = '\0'; // truncate on dot
89
90 // if drive is not specified, remove starting \ from dir name
91 // so dll is loaded from LIBPATH
92 if (drive[0] == 0 && dir[0] == '\\' && dir[1] == '\\') {
93 while( dir[0] == '\\')
94 strcpy( dir, dir+1);
95 }
96 _makepath( buffer, drive, dir, fname, ext);
97
98 #if OSL_DEBUG_LEVEL>1
99 debug_printf("osl_loadModule module %s", buffer);
100 #endif
101
102 hModule = dlopen( buffer, RTLD_LOCAL);
103 if (hModule != NULL)
104 return (oslModule)hModule;
105
106 // do not show in case rc=2 ENOENT, we must parse dlerror
107 // string to detect it
108 char* err = dlerror();
109 if (!err)
110 return NULL;
111
112 if (strstr( err, "rc=2") != NULL)
113 return NULL;
114
115 sal_Char szError[ PATH_MAX*2 ];
116 sprintf( szError, "Module: %s;\n error: %s;\n\n"
117 "Please contact technical support and report above informations.\n\n",
118 buffer, err);
119 #if OSL_DEBUG_LEVEL>0
120 debug_printf("osl_loadModule error %s", szError);
121 #endif
122
123 #if (OSL_DEBUG_LEVEL==0) || !defined(OSL_DEBUG_LEVEL)
124 WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,
125 szError, "Critical error: DosLoadModule failed",
126 0, MB_ERROR | MB_OK | MB_MOVEABLE);
127 #endif
128
129 return NULL;
130 }
131
132 /*****************************************************************************/
133 /* osl_getModuleHandle */
134 /*****************************************************************************/
135
136 sal_Bool SAL_CALL
osl_getModuleHandle(rtl_uString * pModuleName,oslModule * pResult)137 osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
138 {
139 HMODULE hmod;
140 APIRET rc;
141
142 OSL_ENSURE(pModuleName,"osl_loadModule : string is not valid");
143
144 if (pModuleName)
145 {
146 char buffer[PATH_MAX];
147
148 if (UnicodeToText(buffer, PATH_MAX, pModuleName->buffer,
149 pModuleName->length))
150 {
151 rc = DosQueryModuleHandle(buffer, &hmod);
152 if( rc == NO_ERROR)
153 {
154 *pResult = (oslModule) hmod;
155 return sal_True;
156 }
157 }
158 }
159
160 return sal_False;
161 }
162
163 /*****************************************************************************/
164 /* osl_unloadModule */
165 /*****************************************************************************/
osl_unloadModule(oslModule hModule)166 void SAL_CALL osl_unloadModule(oslModule hModule)
167 {
168 if (hModule)
169 {
170 int nRet = dlclose(hModule);
171 #if OSL_DEBUG_LEVEL > 1
172 if (nRet != 0)
173 {
174 debug_printf( "osl_unloadModule failed with %s\n", dlerror());
175 }
176 #else
177 (void) nRet;
178 #endif /* if OSL_DEBUG_LEVEL */
179 }
180 }
181
182 /*****************************************************************************/
183 /* osl_getSymbol */
184 /*****************************************************************************/
185 void* SAL_CALL
osl_getSymbol(oslModule Module,rtl_uString * pSymbolName)186 osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
187 {
188 return (void *) osl_getFunctionSymbol(Module, pSymbolName);
189 }
190
191 /*****************************************************************************/
192 /* osl_getFunctionSymbol */
193 /*****************************************************************************/
osl_getFunctionSymbol(oslModule Module,rtl_uString * strSymbolName)194 oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
195 {
196 rtl_String *symbolName = NULL;
197 oslGenericFunction address;
198
199 OSL_ASSERT(Module);
200 OSL_ASSERT(strSymbolName);
201
202 rtl_uString2String(
203 &symbolName,
204 strSymbolName->buffer,
205 strSymbolName->length,
206 RTL_TEXTENCODING_UTF8,
207 OUSTRING_TO_OSTRING_CVTFLAGS
208 );
209
210 address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName));
211 rtl_string_release(symbolName);
212
213 return address;
214 }
215
216 /*****************************************************************************/
217 /* osl_getAsciiFunctionSymbol */
218 /*****************************************************************************/
219 oslGenericFunction SAL_CALL
osl_getAsciiFunctionSymbol(oslModule Module,const sal_Char * pSymbol)220 osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
221 {
222 PFN pFunction;
223 APIRET rc;
224 void* pHandle=0;
225
226 OSL_ENSURE(Module,"osl_getSymbol : module handle is not valid");
227 OSL_ENSURE(Module,"osl_getSymbol : ustrSymbolName");
228
229 if ( Module!= 0 && pSymbol != 0 )
230 {
231
232 rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)pSymbol, &pFunction );
233 if( rc == NO_ERROR )
234 {
235 pHandle = (void*)pFunction;
236 }
237 else
238 {
239 // YD try again adding the '_' prefix
240 char _pszSymbolName[255];
241 strcpy( _pszSymbolName, "_");
242 strcat( _pszSymbolName, pSymbol);
243 rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)_pszSymbolName, &pFunction );
244 if( rc == NO_ERROR )
245 pHandle = (void*)pFunction;
246 }
247
248 }
249
250 return pHandle;
251 }
252
253 /*****************************************************************************/
254 /* osl_getModuleURLFromAddress */
255 /*****************************************************************************/
osl_getModuleURLFromAddress(void * addr,rtl_uString ** ppLibraryUrl)256 sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
257 {
258 //APIRET APIENTRY DosQueryModFromEIP (HMODULE *phMod, ULONG *pObjNum,
259 // ULONG BuffLen, PCHAR pBuff, ULONG *pOffset, ULONG Address)
260 HMODULE hMod;
261 ULONG ObjNum;
262 CHAR Buff[2*_MAX_PATH];
263 ULONG Offset;
264 APIRET rc;
265
266 // get module handle (and name)
267 rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, &Offset, (ULONG)addr);
268 if (rc)
269 return sal_False;
270
271 // get module full path
272 rc = DosQueryModuleName( hMod, sizeof( Buff), Buff);
273 if (rc)
274 return sal_False;
275
276 #if OSL_DEBUG_LEVEL > 1
277 OSL_TRACE("module.c::osl_getModuleURLFromAddress - %s\n", Buff);
278 #endif
279
280 // convert to URL
281 rtl_uString *ustrSysPath = NULL;
282 rtl_string2UString( &ustrSysPath, Buff, strlen(Buff), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
283 OSL_ASSERT(ustrSysPath != NULL);
284 osl_getFileURLFromSystemPath( ustrSysPath, ppLibraryUrl );
285 rtl_uString_release( ustrSysPath );
286
287 return sal_True;
288 }
289
290 /*****************************************************************************/
291 /* osl_getModuleURLFromFunctionAddress */
292 /*****************************************************************************/
osl_getModuleURLFromFunctionAddress(oslGenericFunction addr,rtl_uString ** ppLibraryUrl)293 sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl )
294 {
295 return osl_getModuleURLFromAddress( ( void * )addr, ppLibraryUrl );
296 }
297
298 /*****************************************************************************/
299
300