Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #ifdef WNT
22 : : # include <stdio.h>
23 : : # include <sys/stat.h>
24 : : # include <windows.h>
25 : : #endif
26 : :
27 : : #ifdef ANDROID
28 : : # include <dlfcn.h>
29 : : #endif
30 : :
31 : : #if OSL_DEBUG_LEVEL > 0
32 : : #include <stdio.h>
33 : : #endif
34 : : #include <string.h>
35 : :
36 : : #include "boost/scoped_array.hpp"
37 : : #include "osl/diagnose.h"
38 : : #include "rtl/ustring.hxx"
39 : : #include "rtl/ustrbuf.hxx"
40 : : #include "osl/module.hxx"
41 : : #include "osl/mutex.hxx"
42 : : #include "osl/thread.hxx"
43 : : #include "osl/file.hxx"
44 : : #include "rtl/instance.hxx"
45 : : #include "osl/getglobalmutex.hxx"
46 : : #include <setjmp.h>
47 : : #include <signal.h>
48 : : #include <stack>
49 : :
50 : : #include "jni.h"
51 : : #include "rtl/byteseq.hxx"
52 : : #include "jvmfwk/vendorplugin.h"
53 : : #include "util.hxx"
54 : : #include "sunversion.hxx"
55 : : #include "vendorlist.hxx"
56 : : #include "diagnostics.h"
57 : :
58 : : #ifdef ANDROID
59 : : #include <osl/detail/android-bootstrap.h>
60 : : #endif
61 : :
62 : : #if defined HAVE_VALGRIND_H
63 : : #include <valgrind.h>
64 : : #else
65 : : #define RUNNING_ON_VALGRIND 0
66 : : #endif
67 : :
68 : : #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
69 : : #define SUN_MICRO "Sun Microsystems Inc."
70 : :
71 : : using namespace osl;
72 : : using namespace std;
73 : : using namespace jfw_plugin;
74 : :
75 : : using ::rtl::OUString;
76 : : using ::rtl::OUStringBuffer;
77 : : using ::rtl::OString;
78 : :
79 : : namespace {
80 : :
81 : : struct PluginMutex: public ::rtl::Static<osl::Mutex, PluginMutex> {};
82 : :
83 : : #if defined UNX
84 : 4 : OString getPluginJarPath(
85 : : const OUString & sVendor,
86 : : const OUString& sLocation,
87 : : const OUString& sVersion)
88 : : {
89 : 4 : OString ret;
90 [ + - ]: 4 : OUString sName1(RTL_CONSTASCII_USTRINGPARAM("javaplugin.jar"));
91 [ + - ]: 4 : OUString sName2(RTL_CONSTASCII_USTRINGPARAM("plugin.jar"));
92 : 4 : OUString sPath;
93 [ - + ]: 4 : if ( sVendor == SUN_MICRO )
94 : : {
95 [ # # ]: 0 : SunVersion ver142("1.4.2-ea");
96 [ # # ]: 0 : SunVersion ver150("1.5.0-ea");
97 [ # # ]: 0 : SunVersion ver(sVersion);
98 : : OSL_ASSERT(ver142 && ver150 && ver);
99 : :
100 : 0 : OUString sName;
101 [ # # ][ # # ]: 0 : if (ver < ver142)
102 : : {
103 : 0 : sName = sName1;
104 : : }
105 [ # # ][ # # ]: 0 : else if (ver < ver150)
106 : : {//this will cause ea, beta etc. to have plugin.jar in path.
107 : : //but this does not harm. 1.5.0-beta < 1.5.0
108 : 0 : sName = sName2;
109 : : }
110 [ # # ]: 0 : if (!sName.isEmpty())
111 : : {
112 [ # # ]: 0 : sName = sLocation + OUSTR("/lib/") + sName;
113 [ # # ]: 0 : OSL_VERIFY(
114 : : osl_getSystemPathFromFileURL(sName.pData, & sPath.pData)
115 : : == osl_File_E_None);
116 [ # # ][ # # ]: 0 : }
[ # # ]
117 : : }
118 : : else
119 : : {
120 : 4 : char sep[] = {SAL_PATHSEPARATOR, 0};
121 [ + - ]: 4 : OUString sName(sLocation + OUSTR("/lib/") + sName1);
122 : 4 : OUString sPath1;
123 : 4 : OUString sPath2;
124 [ + - ][ + - ]: 4 : if (osl_getSystemPathFromFileURL(sName.pData, & sPath1.pData)
125 : : == osl_File_E_None)
126 : : {
127 [ + - ]: 4 : sName = sLocation + OUSTR("/lib/") + sName2;
128 [ + - ][ + - ]: 4 : if (osl_getSystemPathFromFileURL(sName.pData, & sPath2.pData)
129 : : == osl_File_E_None)
130 : : {
131 : 4 : sPath = sPath1 + OUString::createFromAscii(sep) + sPath2;
132 : : }
133 : : }
134 : 4 : OSL_ASSERT(!sPath.isEmpty());
135 : : }
136 [ + - ][ + - ]: 4 : ret = rtl::OUStringToOString(sPath, osl_getThreadTextEncoding());
137 : :
138 : 4 : return ret;
139 : : }
140 : : #endif // UNX
141 : :
142 : :
143 : 6 : JavaInfo* createJavaInfo(const rtl::Reference<VendorBase> & info)
144 : : {
145 : 6 : JavaInfo* pInfo = (JavaInfo*) rtl_allocateMemory(sizeof(JavaInfo));
146 [ - + ]: 6 : if (pInfo == NULL)
147 : 0 : return NULL;
148 [ + - ]: 6 : rtl::OUString sVendor = info->getVendor();
149 : 6 : pInfo->sVendor = sVendor.pData;
150 : 6 : rtl_uString_acquire(sVendor.pData);
151 [ + - ]: 6 : rtl::OUString sHome = info->getHome();
152 : 6 : pInfo->sLocation = sHome.pData;
153 : 6 : rtl_uString_acquire(pInfo->sLocation);
154 [ + - ]: 6 : rtl::OUString sVersion = info->getVersion();
155 : 6 : pInfo->sVersion = sVersion.pData;
156 : 6 : rtl_uString_acquire(pInfo->sVersion);
157 [ + - ][ + - ]: 6 : pInfo->nFeatures = info->supportsAccessibility() ? 1 : 0;
158 [ + - ][ + - ]: 6 : pInfo->nRequirements = info->needsRestart() ? JFW_REQUIRE_NEEDRESTART : 0;
159 : 6 : rtl::OUStringBuffer buf(1024);
160 [ + - ][ + - ]: 6 : buf.append(info->getRuntimeLibrary());
161 [ + - ][ + - ]: 6 : if (!info->getLibraryPaths().isEmpty())
162 : : {
163 [ + - ]: 6 : buf.appendAscii("\n");
164 [ + - ][ + - ]: 6 : buf.append(info->getLibraryPaths());
165 [ + - ]: 6 : buf.appendAscii("\n");
166 : : }
167 : :
168 [ + - ]: 6 : rtl::OUString sVendorData = buf.makeStringAndClear();
169 : : rtl::ByteSequence byteSeq( (sal_Int8*) sVendorData.pData->buffer,
170 [ + - ]: 6 : sVendorData.getLength() * sizeof(sal_Unicode));
171 : 6 : pInfo->arVendorData = byteSeq.get();
172 : 6 : rtl_byte_sequence_acquire(pInfo->arVendorData);
173 : :
174 : 6 : return pInfo;
175 : : }
176 : :
177 : 4 : rtl::OUString getRuntimeLib(const rtl::ByteSequence & data)
178 : : {
179 : 4 : const sal_Unicode* chars = (sal_Unicode*) data.getConstArray();
180 : 4 : sal_Int32 len = data.getLength();
181 : 4 : rtl::OUString sData(chars, len / 2);
182 : : //the runtime lib is on the first line
183 : 4 : sal_Int32 index = 0;
184 : 4 : rtl::OUString aToken = sData.getToken( 0, '\n', index);
185 : :
186 : 4 : return aToken;
187 : : }
188 : :
189 : : jmp_buf jmp_jvm_abort;
190 : : sig_atomic_t g_bInGetJavaVM = 0;
191 : :
192 : 0 : extern "C" void JNICALL abort_handler()
193 : : {
194 : : // If we are within JNI_CreateJavaVM then we jump back into getJavaVM
195 [ # # ]: 0 : if( g_bInGetJavaVM != 0 )
196 : : {
197 : 0 : fprintf( stderr, "JavaVM: JNI_CreateJavaVM called _exit, caught by abort_handler in javavm.cxx\n");
198 : 0 : longjmp( jmp_jvm_abort, 0);
199 : : }
200 : 0 : }
201 : :
202 : : }
203 : :
204 : : extern "C"
205 : 0 : javaPluginError jfw_plugin_getAllJavaInfos(
206 : : rtl_uString *sVendor,
207 : : rtl_uString *sMinVersion,
208 : : rtl_uString *sMaxVersion,
209 : : rtl_uString * *arExcludeList,
210 : : sal_Int32 nLenList,
211 : : JavaInfo*** parJavaInfo,
212 : : sal_Int32 *nLenInfoList)
213 : : {
214 : : OSL_ASSERT(sVendor);
215 : : OSL_ASSERT(sMinVersion);
216 : : OSL_ASSERT(sMaxVersion);
217 : : OSL_ASSERT(parJavaInfo);
218 : : OSL_ASSERT(parJavaInfo);
219 : : OSL_ASSERT(nLenInfoList);
220 [ # # ][ # # ]: 0 : if (!sVendor || !sMinVersion || !sMaxVersion || !parJavaInfo || !nLenInfoList)
[ # # ][ # # ]
[ # # ]
221 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
222 : :
223 : : //nLenlist contains the number of element in arExcludeList.
224 : : //If no exclude list is provided then nLenList must be 0
225 : : OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
226 [ # # ][ # # ]: 0 : if (arExcludeList == NULL && nLenList > 0)
227 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
228 : :
229 : 0 : OUString ouVendor(sVendor);
230 : 0 : OUString ouMinVer(sMinVersion);
231 : 0 : OUString ouMaxVer(sMaxVersion);
232 : :
233 : : OSL_ASSERT(!ouVendor.isEmpty());
234 [ # # ]: 0 : if (ouVendor.isEmpty())
235 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
236 : :
237 : 0 : JavaInfo** arInfo = NULL;
238 : :
239 : : //Find all JREs
240 : : vector<rtl::Reference<VendorBase> > vecInfos =
241 [ # # ]: 0 : getAllJREInfos();
242 [ # # ]: 0 : vector<rtl::Reference<VendorBase> > vecVerifiedInfos;
243 : :
244 : : typedef vector<rtl::Reference<VendorBase> >::iterator it;
245 [ # # ][ # # ]: 0 : for (it i= vecInfos.begin(); i != vecInfos.end(); ++i)
246 : : {
247 : 0 : const rtl::Reference<VendorBase>& cur = *i;
248 : :
249 [ # # ][ # # ]: 0 : if (ouVendor.equals(cur->getVendor()) == sal_False)
250 : 0 : continue;
251 : :
252 [ # # ]: 0 : if (!ouMinVer.isEmpty())
253 : : {
254 : : try
255 : : {
256 [ # # ]: 0 : if (cur->compareVersions(sMinVersion) == -1)
[ # # # # ]
257 : 0 : continue;
258 : : }
259 [ # # ]: 0 : catch (MalformedVersionException&)
260 : : {
261 : : //The minVersion was not recognized as valid for this vendor.
262 : : JFW_ENSURE(
263 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
264 : : + ouMinVer + OUSTR(" for vendor: ") + cur->getVendor()
265 : : + OUSTR(" .Check minimum Version.") );
266 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
267 : : }
268 : : }
269 : :
270 [ # # ]: 0 : if (!ouMaxVer.isEmpty())
271 : : {
272 : : try
273 : : {
274 [ # # ]: 0 : if (cur->compareVersions(sMaxVersion) == 1)
[ # # # # ]
275 : 0 : continue;
276 : : }
277 [ # # # # ]: 0 : catch (MalformedVersionException&)
278 : : {
279 : : //The maxVersion was not recognized as valid for this vendor.
280 : : JFW_ENSURE(
281 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
282 : : + ouMaxVer + OUSTR(" for vendor: ") + cur->getVendor()
283 : : + OUSTR(" .Check maximum Version.") );
284 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
285 : : }
286 : : }
287 : :
288 : 0 : bool bExclude = false;
289 [ # # ]: 0 : for (int j = 0; j < nLenList; j++)
290 : : {
291 : 0 : rtl::OUString sExVer(arExcludeList[j]);
292 : : try
293 : : {
294 [ # # ][ # # ]: 0 : if (cur->compareVersions(sExVer) == 0)
295 : : {
296 : 0 : bExclude = true;
297 : : break;
298 : : }
299 : : }
300 [ # # ]: 0 : catch (MalformedVersionException&)
301 : : {
302 : : //The excluded version was not recognized as valid for this vendor.
303 : : JFW_ENSURE(
304 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
305 : : + sExVer + OUSTR(" for vendor: ") + cur->getVendor()
306 : : + OUSTR(" .Check excluded versions.") );
307 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
308 : : }
309 [ # # # ]: 0 : }
310 [ # # ]: 0 : if (bExclude == true)
311 : 0 : continue;
312 : :
313 [ # # ]: 0 : vecVerifiedInfos.push_back(*i);
314 : : }
315 : : //Now vecVerifiedInfos contains all those JREs which meet the version requirements
316 : : //Transfer them into the array that is passed out.
317 : 0 : arInfo = (JavaInfo**) rtl_allocateMemory(vecVerifiedInfos.size() * sizeof (JavaInfo*));
318 : 0 : int j = 0;
319 : : typedef vector<rtl::Reference<VendorBase> >::const_iterator cit;
320 [ # # ][ # # ]: 0 : for (cit ii = vecVerifiedInfos.begin(); ii != vecVerifiedInfos.end(); ++ii, ++j)
[ # # ]
321 : : {
322 [ # # ]: 0 : arInfo[j] = createJavaInfo(*ii);
323 : : }
324 : 0 : *nLenInfoList = vecVerifiedInfos.size();
325 : :
326 : :
327 : 0 : *parJavaInfo = arInfo;
328 : 0 : return JFW_PLUGIN_E_NONE;
329 : : }
330 : :
331 : : extern "C"
332 : 12 : javaPluginError jfw_plugin_getJavaInfoByPath(
333 : : rtl_uString *path,
334 : : rtl_uString *sVendor,
335 : : rtl_uString *sMinVersion,
336 : : rtl_uString *sMaxVersion,
337 : : rtl_uString * *arExcludeList,
338 : : sal_Int32 nLenList,
339 : : JavaInfo ** ppInfo)
340 : : {
341 : 12 : javaPluginError errorcode = JFW_PLUGIN_E_NONE;
342 : :
343 : : OSL_ASSERT(path);
344 : : OSL_ASSERT(sVendor);
345 : : OSL_ASSERT(sMinVersion);
346 : : OSL_ASSERT(sMaxVersion);
347 [ + - ][ + - ]: 12 : if (!path || !sVendor || !sMinVersion || !sMaxVersion || !ppInfo)
[ + - ][ + - ]
[ - + ]
348 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
349 : 12 : OUString ouPath(path);
350 : : OSL_ASSERT(!ouPath.isEmpty());
351 [ - + ]: 12 : if (ouPath.isEmpty())
352 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
353 : :
354 : : //nLenlist contains the number of element in arExcludeList.
355 : : //If no exclude list is provided then nLenList must be 0
356 : : OSL_ASSERT( ! (arExcludeList == NULL && nLenList > 0));
357 [ - + ][ # # ]: 12 : if (arExcludeList == NULL && nLenList > 0)
358 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
359 : :
360 : 12 : OUString ouVendor(sVendor);
361 : 12 : OUString ouMinVer(sMinVersion);
362 : 12 : OUString ouMaxVer(sMaxVersion);
363 : :
364 : : OSL_ASSERT(!ouVendor.isEmpty());
365 [ - + ]: 12 : if (ouVendor.isEmpty())
366 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
367 : :
368 [ + - ]: 12 : rtl::Reference<VendorBase> aVendorInfo = getJREInfoByPath(ouPath);
369 [ - + ]: 12 : if (aVendorInfo.is() == sal_False)
370 : 0 : return JFW_PLUGIN_E_NO_JRE;
371 : :
372 : : //Check if the detected JRE matches the version requirements
373 [ + - ][ + + ]: 12 : if (ouVendor.equals(aVendorInfo->getVendor()) == sal_False)
374 : 6 : return JFW_PLUGIN_E_NO_JRE;
375 : :
376 [ + - ]: 6 : if (!ouMinVer.isEmpty())
377 : : {
378 : 6 : int nRes = 0;
379 : : try
380 : : {
381 [ + - ]: 6 : nRes = aVendorInfo->compareVersions(ouMinVer);
382 : : }
383 [ # # # # ]: 0 : catch (MalformedVersionException&)
384 : : {
385 : : //The minVersion was not recognized as valid for this vendor.
386 : : JFW_ENSURE(
387 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
388 : : + ouMinVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
389 : : + OUSTR(" .Check minimum Version.") );
390 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
391 : : }
392 [ - + ]: 6 : if (nRes < 0)
393 : 0 : return JFW_PLUGIN_E_FAILED_VERSION;
394 : : }
395 : :
396 [ - + ]: 6 : if (!ouMaxVer.isEmpty())
397 : : {
398 : 0 : int nRes = 0;
399 : : try
400 : : {
401 [ # # ]: 0 : nRes = aVendorInfo->compareVersions(ouMaxVer);
402 : : }
403 [ # # # # ]: 0 : catch (MalformedVersionException&)
404 : : {
405 : : //The maxVersion was not recognized as valid for this vendor.
406 : : JFW_ENSURE(
407 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
408 : : + ouMaxVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
409 : : + OUSTR(" .Check maximum Version.") );
410 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
411 : : }
412 [ # # ]: 0 : if (nRes > 0)
413 : 0 : return JFW_PLUGIN_E_FAILED_VERSION;
414 : : }
415 : :
416 [ - + ]: 6 : for (int i = 0; i < nLenList; i++)
417 : : {
418 : 0 : rtl::OUString sExVer(arExcludeList[i]);
419 : 0 : int nRes = 0;
420 : : try
421 : : {
422 [ # # ]: 0 : nRes = aVendorInfo->compareVersions(sExVer);
423 : : }
424 [ # # ]: 0 : catch (MalformedVersionException&)
425 : : {
426 : : //The excluded version was not recognized as valid for this vendor.
427 : : JFW_ENSURE(
428 : : 0,OUSTR("[Java framework]sunjavaplugin does not know version: ")
429 : : + sExVer + OUSTR(" for vendor: ") + aVendorInfo->getVendor()
430 : : + OUSTR(" .Check excluded versions.") );
431 : 0 : return JFW_PLUGIN_E_WRONG_VERSION_FORMAT;
432 : : }
433 [ # # ]: 0 : if (nRes == 0)
434 : 0 : return JFW_PLUGIN_E_FAILED_VERSION;
435 [ # # ]: 0 : }
436 [ + - ]: 6 : *ppInfo = createJavaInfo(aVendorInfo);
437 : :
438 [ + - ][ # # ]: 12 : return errorcode;
439 : : }
440 : :
441 : : #if defined(WNT)
442 : :
443 : : // Load msvcr71.dll using an explicit full path from where it is
444 : : // present as bundled with the JRE. In case it is not found where we
445 : : // think it should be, do nothing, and just let the implicit loading
446 : : // that happens when loading the JVM take care of it.
447 : :
448 : : static void load_msvcr71(LPCWSTR jvm_dll)
449 : : {
450 : : wchar_t msvcr71_dll[MAX_PATH];
451 : : wchar_t *slash;
452 : :
453 : : if (wcslen(jvm_dll) > MAX_PATH - 15)
454 : : return;
455 : :
456 : : wcscpy(msvcr71_dll, jvm_dll);
457 : :
458 : : // First check if msvcr71.dll is in the same folder as jvm.dll. It
459 : : // normally isn't, at least up to 1.6.0_22, but who knows if it
460 : : // might be in the future.
461 : : slash = wcsrchr(msvcr71_dll, L'\\');
462 : :
463 : : if (!slash)
464 : : {
465 : : // Huh, weird path to jvm.dll. Oh well.
466 : : return;
467 : : }
468 : :
469 : : wcscpy(slash+1, L"msvcr71.dll");
470 : : if (LoadLibraryW(msvcr71_dll))
471 : : return;
472 : :
473 : : // Then check if msvcr71.dll is in the parent folder of where
474 : : // jvm.dll is. That is currently (1.6.0_22) as far as I know the
475 : : // normal case.
476 : : *slash = 0;
477 : : slash = wcsrchr(msvcr71_dll, L'\\');
478 : :
479 : : if (!slash)
480 : : return;
481 : :
482 : : wcscpy(slash+1, L"msvcr71.dll");
483 : : LoadLibraryW(msvcr71_dll);
484 : : }
485 : :
486 : : // Check if the jvm DLL imports msvcr71.dll, and in that case try
487 : : // loading it explicitly. In case something goes wrong, do nothing,
488 : : // and just let the implicit loading try to take care of it.
489 : : static void do_msvcr71_magic(rtl_uString *jvm_dll)
490 : : {
491 : : FILE *f;
492 : : rtl_uString* Module;
493 : : oslFileError nError;
494 : : struct stat st;
495 : : PIMAGE_DOS_HEADER dos_hdr;
496 : : IMAGE_NT_HEADERS *nt_hdr;
497 : : IMAGE_IMPORT_DESCRIPTOR *imports;
498 : :
499 : : nError = osl_getSystemPathFromFileURL(jvm_dll, &Module);
500 : :
501 : : if ( osl_File_E_None != nError )
502 : : rtl_uString_assign(&Module, jvm_dll);
503 : :
504 : : f = _wfopen(reinterpret_cast<LPCWSTR>(Module->buffer), L"rb");
505 : :
506 : : if (fstat(fileno(f), &st) == -1)
507 : : {
508 : : fclose(f);
509 : : return;
510 : : }
511 : :
512 : : dos_hdr = (PIMAGE_DOS_HEADER) malloc(st.st_size);
513 : :
514 : : if (fread(dos_hdr, st.st_size, 1, f) != 1 ||
515 : : memcmp(dos_hdr, "MZ", 2) != 0 ||
516 : : dos_hdr->e_lfanew < 0 ||
517 : : dos_hdr->e_lfanew > (LONG) (st.st_size - sizeof(IMAGE_NT_HEADERS)))
518 : : {
519 : : free(dos_hdr);
520 : : fclose(f);
521 : : return;
522 : : }
523 : :
524 : : fclose(f);
525 : :
526 : : nt_hdr = (IMAGE_NT_HEADERS *) ((char *)dos_hdr + dos_hdr->e_lfanew);
527 : :
528 : : imports = (IMAGE_IMPORT_DESCRIPTOR *) ((char *) dos_hdr + nt_hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
529 : :
530 : : while (imports <= (IMAGE_IMPORT_DESCRIPTOR *) ((char *) dos_hdr + st.st_size - sizeof (IMAGE_IMPORT_DESCRIPTOR)) &&
531 : : imports->Name != 0 &&
532 : : imports->Name < (DWORD) st.st_size)
533 : : {
534 : : // Intentional use of sizeof("msvcr71.dll") here to include the terminating zero byte
535 : : if (strnicmp((char *) dos_hdr + imports->Name, "msvcr71.dll", sizeof("msvcr71.dll")) == 0)
536 : : {
537 : : load_msvcr71(reinterpret_cast<LPCWSTR>(Module->buffer));
538 : : break;
539 : : }
540 : : imports++;
541 : : }
542 : :
543 : : free(dos_hdr);
544 : : }
545 : :
546 : : #endif
547 : :
548 : : /** starts a Java Virtual Machine.
549 : : <p>
550 : : The function shall ensure, that the VM does not abort the process
551 : : during instantiation.
552 : : </p>
553 : : */
554 : : extern "C"
555 : 4 : javaPluginError jfw_plugin_startJavaVirtualMachine(
556 : : const JavaInfo *pInfo,
557 : : const JavaVMOption* arOptions,
558 : : sal_Int32 cOptions,
559 : : JavaVM ** ppVm,
560 : : JNIEnv ** ppEnv)
561 : : {
562 : : // unless guard is volatile the following warning occurs on gcc:
563 : : // warning: variable 't' might be clobbered by `longjmp' or `vfork'
564 [ + - ][ + - ]: 4 : volatile osl::MutexGuard guard(PluginMutex::get());
565 : : // unless errorcode is volatile the following warning occurs on gcc:
566 : : // warning: variable 'errorcode' might be clobbered by `longjmp' or `vfork'
567 : 4 : volatile javaPluginError errorcode = JFW_PLUGIN_E_NONE;
568 [ + - ][ + - ]: 4 : if ( pInfo == NULL || ppVm == NULL || ppEnv == NULL)
[ - + ]
569 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
570 : : //Check if the Vendor (pInfo->sVendor) is supported by this plugin
571 [ + - ][ - + ]: 4 : if ( ! isVendorSupported(pInfo->sVendor))
572 : 0 : return JFW_PLUGIN_E_WRONG_VENDOR;
573 : 4 : rtl::OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
574 : : JFW_TRACE2(OUSTR("[Java framework] Using Java runtime library: ")
575 : : + sRuntimeLib + OUSTR(".\n"));
576 : :
577 : : #ifndef ANDROID
578 : : // On linux we load jvm with RTLD_GLOBAL. This is necessary for debugging, because
579 : : // libjdwp.so need a symbol (fork1) from libjvm which it only gets if the jvm is loaded
580 : : // witd RTLD_GLOBAL. On Solaris libjdwp.so is correctly linked with libjvm.so
581 : 4 : oslModule moduleRt = 0;
582 : : #if defined(LINUX)
583 [ - + ][ + - ]: 4 : if ((moduleRt = osl_loadModule(sRuntimeLib.pData,
584 : 4 : SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_NOW)) == 0 )
585 : : #else
586 : : #if defined(WNT)
587 : : do_msvcr71_magic(sRuntimeLib.pData);
588 : : #endif
589 : : if ((moduleRt = osl_loadModule(sRuntimeLib.pData, SAL_LOADMODULE_DEFAULT)) == 0)
590 : : #endif
591 : : {
592 : : JFW_ENSURE(0, OUSTR("[Java framework]sunjavaplugin" SAL_DLLEXTENSION
593 : : " could not load Java runtime library: \n")
594 : : + sRuntimeLib + OUSTR("\n"));
595 : : JFW_TRACE0(OUSTR("[Java framework]sunjavaplugin" SAL_DLLEXTENSION
596 : : " could not load Java runtime library: \n")
597 : : + sRuntimeLib + OUSTR("\n"));
598 : 0 : return JFW_PLUGIN_E_VM_CREATION_FAILED;
599 : : }
600 : :
601 : : #ifdef UNX
602 : : //Setting the JAVA_HOME is needed for awt
603 [ + - ]: 4 : rtl::OUString javaHome(RTL_CONSTASCII_USTRINGPARAM("JAVA_HOME="));
604 : 4 : rtl::OUString sPathLocation;
605 [ + - ]: 4 : osl_getSystemPathFromFileURL(pInfo->sLocation, & sPathLocation.pData);
606 : 4 : javaHome += sPathLocation;
607 : : rtl::OString osJavaHome = rtl::OUStringToOString(
608 [ + - ][ + - ]: 4 : javaHome, osl_getThreadTextEncoding());
609 : 4 : putenv(strdup(osJavaHome.getStr()));
610 : : #endif
611 : :
612 : : typedef jint JNICALL JNI_InitArgs_Type(void *);
613 : : typedef jint JNICALL JNI_CreateVM_Type(JavaVM **, JNIEnv **, void *);
614 : : rtl::OUString sSymbolCreateJava(
615 [ + - ]: 4 : RTL_CONSTASCII_USTRINGPARAM("JNI_CreateJavaVM"));
616 : :
617 : : JNI_CreateVM_Type * pCreateJavaVM = (JNI_CreateVM_Type *) osl_getFunctionSymbol(
618 [ + - ]: 4 : moduleRt, sSymbolCreateJava.pData);
619 [ - + ]: 4 : if (!pCreateJavaVM)
620 : : {
621 : : OSL_ASSERT(0);
622 : : rtl::OString sLib = rtl::OUStringToOString(
623 [ # # ][ # # ]: 0 : sRuntimeLib, osl_getThreadTextEncoding());
624 : : rtl::OString sSymbol = rtl::OUStringToOString(
625 [ # # ][ # # ]: 0 : sSymbolCreateJava, osl_getThreadTextEncoding());
626 : : fprintf(stderr,"[Java framework]sunjavaplugin" SAL_DLLEXTENSION
627 : : "Java runtime library: %s does not export symbol %s !\n",
628 [ # # ]: 0 : sLib.getStr(), sSymbol.getStr());
629 : 0 : return JFW_PLUGIN_E_VM_CREATION_FAILED;
630 : : }
631 : :
632 : : // Valgrind typically emits many false errors when executing JIT'ed JVM
633 : : // code, so force the JVM into interpreted mode:
634 : 4 : bool forceInterpreted = RUNNING_ON_VALGRIND > 0;
635 : :
636 : : // Some testing with Java 1.4 showed that JavaVMOption.optionString has to
637 : : // be encoded with the system encoding (i.e., osl_getThreadTextEncoding):
638 : : JavaVMInitArgs vm_args;
639 : :
640 [ - + ]: 4 : sal_Int32 nOptions = 1 + cOptions + (forceInterpreted ? 1 : 0);
641 : : //TODO: check for overflow
642 [ + - ]: 4 : boost::scoped_array<JavaVMOption> sarOptions(new JavaVMOption[nOptions]);
643 : 4 : JavaVMOption * options = sarOptions.get();
644 : :
645 : : // We set an abort handler which is called when the VM calls _exit during
646 : : // JNI_CreateJavaVM. This happens when the LD_LIBRARY_PATH does not contain
647 : : // all some directories of the Java installation. This is necessary for
648 : : // all versions below 1.5.1
649 : 4 : int n = 0;
650 : 4 : options[n].optionString= (char *) "abort";
651 : 4 : options[n].extraInfo= (void* )(sal_IntPtr)abort_handler;
652 : 4 : ++n;
653 : 4 : rtl::OString sClassPathProp("-Djava.class.path=");
654 : 4 : rtl::OString sClassPathOption;
655 [ + + ]: 20 : for (int i = 0; i < cOptions; i++)
656 : : {
657 : : #ifdef UNX
658 : : // Until java 1.5 we need to put a plugin.jar or javaplugin.jar (<1.4.2)
659 : : // in the class path in order to have applet support.
660 : 16 : rtl::OString sClassPath = arOptions[i].optionString;
661 [ + + ]: 16 : if (sClassPath.match(sClassPathProp, 0) == sal_True)
662 : : {
663 : 4 : char sep[] = {SAL_PATHSEPARATOR, 0};
664 [ + - ]: 4 : OString sAddPath = getPluginJarPath(pInfo->sVendor, pInfo->sLocation,pInfo->sVersion);
665 [ + - ]: 4 : if (!sAddPath.isEmpty())
666 : 4 : sClassPathOption = sClassPath + rtl::OString(sep) + sAddPath;
667 : : else
668 : 0 : sClassPathOption = sClassPath;
669 : 4 : options[n].optionString = (char *) sClassPathOption.getStr();
670 : 4 : options[n].extraInfo = arOptions[i].extraInfo;
671 : : }
672 : : else
673 : : {
674 : : #endif
675 : 12 : options[n].optionString = arOptions[i].optionString;
676 : 12 : options[n].extraInfo = arOptions[i].extraInfo;
677 : : #ifdef UNX
678 : : }
679 : : #endif
680 : : #if OSL_DEBUG_LEVEL >= 2
681 : : JFW_TRACE2("VM option: " << options[n].optionString << "\n");
682 : : #endif
683 : 16 : ++n;
684 : 16 : }
685 [ - + ]: 4 : if (forceInterpreted) {
686 : 0 : options[n].optionString = const_cast<char *>("-Xint");
687 : 0 : options[n].extraInfo = 0;
688 : 0 : ++n;
689 : : }
690 : :
691 : : #ifdef MACOSX
692 : : vm_args.version= JNI_VERSION_1_4; // issue 88987
693 : : #else
694 : 4 : vm_args.version= JNI_VERSION_1_2;
695 : : #endif
696 : 4 : vm_args.options= options;
697 : 4 : vm_args.nOptions= nOptions;
698 : 4 : vm_args.ignoreUnrecognized= JNI_TRUE;
699 : :
700 : : /* We set a global flag which is used by the abort handler in order to
701 : : determine whether it is should use longjmp to get back into this function.
702 : : That is, the abort handler determines if it is on the same stack as this function
703 : : and then jumps back into this function.
704 : : */
705 : 4 : g_bInGetJavaVM = 1;
706 : : jint err;
707 : 4 : JavaVM * pJavaVM = 0;
708 : 4 : memset( jmp_jvm_abort, 0, sizeof(jmp_jvm_abort));
709 : 4 : int jmpval= setjmp( jmp_jvm_abort );
710 : : /* If jmpval is not "0" then this point was reached by a longjmp in the
711 : : abort_handler, which was called indirectly by JNI_CreateVM.
712 : : */
713 [ + - ]: 4 : if( jmpval == 0)
714 : : {
715 : : //returns negative number on failure
716 [ + - ]: 4 : err= pCreateJavaVM(&pJavaVM, ppEnv, &vm_args);
717 : 4 : g_bInGetJavaVM = 0;
718 : : }
719 : : else
720 : : // set err to a positive number, so as or recognize that an abort (longjmp)
721 : : //occurred
722 : 0 : err= 1;
723 : :
724 [ - + ]: 4 : if(err != 0)
725 : : {
726 [ # # ]: 0 : if( err < 0)
727 : : {
728 : : fprintf(stderr,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
729 [ # # ]: 0 : "Can not create Java Virtual Machine\n");
730 : 0 : errorcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
731 : : }
732 [ # # ]: 0 : else if( err > 0)
733 : : {
734 : : fprintf(stderr,"[Java framework] sunjavaplugin" SAL_DLLEXTENSION
735 [ # # ]: 0 : "Can not create JavaVirtualMachine, abort handler was called.\n");
736 : 0 : errorcode = JFW_PLUGIN_E_VM_CREATION_FAILED;
737 : : }
738 : : }
739 : : else
740 : : {
741 : 4 : *ppVm = pJavaVM;
742 : : JFW_TRACE2("[Java framework] sunjavaplugin" SAL_DLLEXTENSION " has created a VM.\n");
743 : : }
744 : : #else
745 : : (void) arOptions;
746 : : (void) cOptions;
747 : : // On Android we always have a Java VM as we only expect this code
748 : : // to be run in an Android app anyway.
749 : : *ppVm = lo_get_javavm();
750 : : fprintf(stderr, "lo_get_javavm returns %p", *ppVm);
751 : : #endif
752 : :
753 [ + - ][ + - ]: 4 : return errorcode;
754 : : }
755 : :
756 : : extern "C"
757 : 101 : javaPluginError jfw_plugin_existJRE(const JavaInfo *pInfo, sal_Bool *exist)
758 : : {
759 : 101 : javaPluginError ret = JFW_PLUGIN_E_NONE;
760 [ + - ][ - + ]: 101 : if (!pInfo || !exist)
761 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
762 : 101 : ::rtl::OUString sLocation(pInfo->sLocation);
763 : :
764 [ - + ]: 101 : if (sLocation.isEmpty())
765 : 0 : return JFW_PLUGIN_E_INVALID_ARG;
766 : 101 : ::osl::DirectoryItem item;
767 [ + - ]: 101 : ::osl::File::RC rc_item = ::osl::DirectoryItem::get(sLocation, item);
768 [ + - ]: 101 : if (::osl::File::E_None == rc_item)
769 : : {
770 : 101 : *exist = sal_True;
771 : : }
772 [ # # ]: 0 : else if (::osl::File::E_NOENT == rc_item)
773 : : {
774 : 0 : *exist = sal_False;
775 : : }
776 : : else
777 : : {
778 : 0 : ret = JFW_PLUGIN_E_ERROR;
779 : : }
780 : : #ifdef MACOSX
781 : : //We can have the situation that the JavaVM runtime library is not
782 : : //contained within JAVA_HOME. Then the check for JAVA_HOME would return
783 : : //true although the runtime library may not be loadable.
784 : : if (ret == JFW_PLUGIN_E_NONE && *exist == sal_True)
785 : : {
786 : : rtl::OUString sRuntimeLib = getRuntimeLib(pInfo->arVendorData);
787 : : JFW_TRACE2(OUSTR("[Java framework] Checking existence of Java runtime library.\n"));
788 : :
789 : : ::osl::DirectoryItem itemRt;
790 : : ::osl::File::RC rc_itemRt = ::osl::DirectoryItem::get(sRuntimeLib, itemRt);
791 : : if (::osl::File::E_None == rc_itemRt)
792 : : {
793 : : *exist = sal_True;
794 : : JFW_TRACE2(OUSTR("[Java framework] Java runtime library exist: ")
795 : : + sRuntimeLib + OUSTR("\n"));
796 : :
797 : : }
798 : : else if (::osl::File::E_NOENT == rc_itemRt)
799 : : {
800 : : *exist = sal_False;
801 : : JFW_TRACE2(OUSTR("[Java framework] Java runtime library does not exist: ")
802 : : + sRuntimeLib + OUSTR("\n"));
803 : : }
804 : : else
805 : : {
806 : : ret = JFW_PLUGIN_E_ERROR;
807 : : JFW_TRACE2(OUSTR("[Java framework] Error while looking for Java runtime library: ")
808 : : + sRuntimeLib + OUSTR(" \n"));
809 : : }
810 : : }
811 : : #endif
812 [ + - ]: 101 : return ret;
813 : : }
814 : :
815 : :
816 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|