java_md.c revision 0
3909N/A * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Sun designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Sun in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2362N/A * CA 95054 USA or visit www.sun.com if you need additional information or 0N/A * Returns the arch path, to get the current arch use the 0N/A * macro GetArch, nbits here is ignored for now. 0N/A /* Find out where the JRE is that we will be using. */ 0N/A /* Find the specified JVM type */ 0N/A /* If we got here, jvmpath has been correctly initialized. */ 0N/A * Find path to JRE based on .exe's location or registry settings. 0N/A /* Is JRE co-located with the application? */ 0N/A /* Does this app ship a private JRE in <apphome>\jre directory? */ 0N/A /* Look for a public JRE on this machine. */ 2751N/A * Given a JRE location and a JVM type, construct what the name the 2751N/A * JVM shared library will be. Return true, if such a library 0N/A * exists, false otherwise. 0N/A * Load a jvm from "jvmpath" and initialize the invocation functions. 0N/A * The Microsoft C Runtime Library needs to be loaded first. A copy is 0N/A * assumed to be present in the "JRE path" directory. If it is not found 0N/A * there (or "JRE path" fails to resolve), skip the explicit load and let 0N/A * nature take its course, which is likely to be a failure to execute. 2751N/A /* Now get the function addresses */ 0N/A * If app is "c:\foo\bin\javac", then put "c:\foo" into buf. 0N/A /* This happens if the application is in a drive root, and 0N/A * there is no bin directory. */ 0N/A *
cp =
'\0';
/* remove the bin\ part */ 0N/A * Helpers to look in the registry for a public JRE. 0N/A /* Same for 1.5.0, 1.5.1, 1.5.2 etc. */ 0N/A#
define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment" 0N/A * Note: There is a very similar implementation of the following 0N/A * registry reading code in the Windows java control panel (javacp.cpl). 0N/A * If there are bugs here, a similar bug probably exists there. Hence, 0N/A * changes here require inspection there. 0N/A /* Find the current version of the JRE */ 0N/A /* Find directory where the current version is installed. */ 0N/A printf(
"Warning: Can't read MicroVersion\n");
0N/A * Support for doing cheap, accurate interval timing. 0N/A /* get the length of the string we need */ 0N/A * Just like ReportErrorMessage, except that it concatenates the system 0N/A * error message if any, its upto the calling routine to correctly 0N/A * format the separation of the messages. 0N/A if (n >
2) {
/* Drop final CR, LF */ 0N/A }
else {
/* C runtime error that has no corresponding DOS error code */ 0N/A /* get the length of the string we need */ 0N/A * This code should be replaced by code which opens a window with 0N/A * the exception detail message, for now atleast put a dialog up. 0N/A * Determine if there is an acceptable JRE in the registry directory top_key. 0N/A * Upon locating the "best" one, return a fully qualified path to it. 0N/A * "Best" is defined as the most advanced JRE meeting the constraints 0N/A * contained in the manifest_info. If no JRE in this directory meets the 2751N/A * constraints, return NULL. 2751N/A * It doesn't matter if we get an error reading the registry, or we just 2751N/A * don't find anything interesting in the directory. We just return NULL 0N/A * searching for the best available version. 4022N/A * Extract "JavaHome" from the "best" registry directory and return 4022N/A * that path. If no appropriate version was located, or there is an 4022N/A * error in extracting the "JavaHome" string, return null. * This is the global entry point. It examines the host for the optimal * JRE to be used by scanning a set of registry entries. This set of entries * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment" * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }". * This routine simply opens each of these registry directories before passing * control onto ProcessDir(). * Local helper routine to isolate a single token (option or argument) * This routine accepts a pointer to a character pointer. The first * token (as defined by MSDN command-line argument syntax) is isolated * Upon return, the input character pointer pointed to by the parameter s * is updated to point to the remainding, unscanned, portion of the string, * or to a null character if the entire string has been consummed. * This function returns a pointer to a null-terminated string which * contains the isolated first token, or to the null character if no * token could be isolated. * Note the side effect of modifying the input string s by the insertion * of a null character, making it two strings. * See "Parsing C Command-Line Arguments" in the MSDN Library for the * parsing rule details. The rule summary from that specification is: * * Arguments are delimited by white space, which is either a space or a tab. * * A string surrounded by double quotation marks is interpreted as a single * argument, regardless of white space contained within. A quoted string can * be embedded in an argument. Note that the caret (^) is not recognized as * an escape character or delimiter. * * A double quotation mark preceded by a backslash, \", is interpreted as a * literal double quotation mark ("). * * Backslashes are interpreted literally, unless they immediately precede a * * If an even number of backslashes is followed by a double quotation mark, * then one backslash (\) is placed in the argv array for every pair of * backslashes (\\), and the double quotation mark (") is interpreted as a * * If an odd number of backslashes is followed by a double quotation mark, * then one backslash (\) is placed in the argv array for every pair of * backslashes (\\) and the double quotation mark is interpreted as an * escape sequence by the remaining backslash, causing a literal double * quotation mark (") to be placed in argv. * Strip leading whitespace, which MSDN defines as only space or tab. * (Hence, no locale specific "isspace" here.) while (*p != (
char)0 && (*p ==
' ' || *p ==
'\t'))
head = p;
/* Save the start of the token to return */ * Isolate a token from the command line. while (*p != (
char)0 && (
inquote || !(*p ==
' ' || *p ==
'\t'))) {
if (*p ==
'\\' && *(p+
1) ==
'"' &&
slashes %
2 == 0)
* If the token isolated isn't already terminated in a "char zero", * then replace the whitespace character with one and move to the * Update the parameter to point to the head of the remaining string * reflecting the command line and return a pointer to the leading * token which was isolated from the command line. * Local helper routine to return a string equivalent to the input string * s, but with quotes removed so the result is a string as would be found * in argv[]. The returned string should be freed by a call to JLI_MemFree(). * The rules for quoting (and escaped quotes) are: * 1 A double quotation mark preceded by a backslash, \", is interpreted as a * literal double quotation mark ("). * 2 Backslashes are interpreted literally, unless they immediately precede a * 3 If an even number of backslashes is followed by a double quotation mark, * then one backslash (\) is placed in the argv array for every pair of * backslashes (\\), and the double quotation mark (") is interpreted as a * 4 If an odd number of backslashes is followed by a double quotation mark, * then one backslash (\) is placed in the argv array for every pair of * backslashes (\\) and the double quotation mark is interpreted as an * escape sequence by the remaining backslash, causing a literal double * quotation mark (") to be placed in argv. const char *p = s;
/* Pointer to the tail of the original string */ char *
pun =
un;
/* Pointer to the tail of the unquoted string */ }
while (*p ==
'\\' && p < q);
* Given a path to a jre to execute, this routine checks if this process * is indeed that jre. If not, it exec's that jre. * We want to actually check the paths rather than just the version string * built into the executable, so that given version specification will yield * the exact same Java environment, regardless of the version of the arbitrary * launcher we start with. * Resolve the real path to the currently running launcher. * If the path to the selected JRE directory is a match to the initial * portion of the path to the currently executing JRE, we have a winner! return;
/* I am the droid you were looking for */ * If this isn't the selected version, exec the selected version. * Although Windows has an execv() entrypoint, it doesn't actually * overlay a process: it can only create a new process and terminate * the old process. Therefore, any processes waiting on the initial * process wake up and they shouldn't. Hence, a chain of pseudo-zombie * processes must be retained to maintain the proper wait semantics. * Fortunately the image size of the launcher isn't too large at this * If it weren't for this semantic flaw, the code below would be ... * ReportErrorMessage("Error: Exec of %s failed\n", path); * The incorrect exec semantics could be addressed by: * exit((int)spawnv(_P_WAIT, path, argv)); * Unfortunately, a bug in Windows spawn/exec impementation prevents * this from completely working. All the Windows POSIX process creation * interfaces are implemented as wrappers around the native Windows * function CreateProcess(). CreateProcess() takes a single string * to specify command line options and arguments, so the POSIX routine * wrappers build a single string from the argv[] array and in the * process, any quoting information is lost. * The solution to this to get the original command line, to process it * to remove the new multiple JRE options (if any) as was done for argv * in the common SelectVersion() routine and finally to pass it directly * to the native CreateProcess() Windows process control interface. * The following code block gets and processes the original command * line, replacing the argv[0] equivalent in the command line with * the path to the new executable and removing the appropriate * Multiple JRE support options. Note that similar logic exists * in the platform independent SelectVersion routine, but is * replicated here due to the syntax of CreateProcess(). * The magic "+ 4" characters added to the command line length are * 2 possible quotes around the path (argv[0]), a space after the * path and a terminating null character. while (*
np != (
char)0) {
/* While more command-line */ if (*p != (
char)0) {
/* If a token was isolated */ if (*
unquoted ==
'-') {
/* Looks like an option */ if (*p != (
char)0)
/* If a token was isolated */ }
else {
/* End of options */ * The following code is modeled after a model presented in the * Microsoft Technical Article "Moving Unix Applications to * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN * (Februrary 2005). It approximates UNIX spawn semantics with * the parent waiting for termination of the child. (
BOOL)
TRUE,
/* inherits system handles */ (
DWORD)0,
/* creation flags */ * Wrapper for platform dependent unsetenv function. /* --- Splash Screen shared library support --- */ * Block current thread and continue execution in a new thread * STACK_SIZE_PARAM_IS_A_RESERVATION is what we want, but it's not * supported on older version of Windows. Try first with the flag; and * if that fails try again without the flag. See MSDN document or HotSpot /* Linux only, empty on windows. */