src/java.base/windows/native/libjli/java_md.c

Print this page


   1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <windows.h>
  27 #include <io.h>
  28 #include <process.h>
  29 #include <stdlib.h>
  30 #include <stdio.h>
  31 #include <stdarg.h>
  32 #include <string.h>
  33 #include <sys/types.h>
  34 #include <sys/stat.h>
  35 #include <wtypes.h>
  36 #include <commctrl.h>
  37 
  38 #include <jni.h>
  39 #include "java.h"
  40 #include "version_comp.h"
  41 
  42 #define JVM_DLL "jvm.dll"
  43 #define JAVA_DLL "java.dll"
  44 
  45 /*
  46  * Prototypes.
  47  */
  48 static jboolean GetPublicJREHome(char *path, jint pathsize);
  49 static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
  50                            char *jvmpath, jint jvmpathsize);
  51 static jboolean GetJREPath(char *path, jint pathsize);
  52 
  53 /* We supports warmup for UI stack that is performed in parallel
  54  * to VM initialization.
  55  * This helps to improve startup of UI application as warmup phase
  56  * might be long due to initialization of OS or hardware resources.
  57  * It is not CPU bound and therefore it does not interfere with VM init.
  58  * Obviously such warmup only has sense for UI apps and therefore it needs
  59  * to be explicitly requested by passing -Dsun.awt.warmup=true property
  60  * (this is always the case for plugin/javaws).


 657 }
 658 
 659 void  JLI_ReportExceptionDescription(JNIEnv * env) {
 660     if (IsJavaw()) {
 661        /*
 662         * This code should be replaced by code which opens a window with
 663         * the exception detail message, for now atleast put a dialog up.
 664         */
 665         MessageBox(NULL, "A Java Exception has occurred.", "Java Virtual Machine Launcher",
 666                (MB_OK|MB_ICONSTOP|MB_APPLMODAL));
 667     } else {
 668         (*env)->ExceptionDescribe(env);
 669     }
 670 }
 671 
 672 jboolean
 673 ServerClassMachine() {
 674     return (GetErgoPolicy() == ALWAYS_SERVER_CLASS) ? JNI_TRUE : JNI_FALSE;
 675 }
 676 
 677 /*
 678  * Determine if there is an acceptable JRE in the registry directory top_key.
 679  * Upon locating the "best" one, return a fully qualified path to it.
 680  * "Best" is defined as the most advanced JRE meeting the constraints
 681  * contained in the manifest_info. If no JRE in this directory meets the
 682  * constraints, return NULL.
 683  *
 684  * It doesn't matter if we get an error reading the registry, or we just
 685  * don't find anything interesting in the directory.  We just return NULL
 686  * in either case.
 687  */
 688 static char *
 689 ProcessDir(manifest_info* info, HKEY top_key) {
 690     DWORD   index = 0;
 691     HKEY    ver_key;
 692     char    name[MAXNAMELEN];
 693     int     len;
 694     char    *best = NULL;
 695 
 696     /*
 697      * Enumerate "<top_key>/SOFTWARE/JavaSoft/Java Runtime Environment"
 698      * searching for the best available version.
 699      */
 700     while (RegEnumKey(top_key, index, name, MAXNAMELEN) == ERROR_SUCCESS) {
 701         index++;
 702         if (JLI_AcceptableRelease(name, info->jre_version))
 703             if ((best == NULL) || (JLI_ExactVersionId(name, best) > 0)) {
 704                 if (best != NULL)
 705                     JLI_MemFree(best);
 706                 best = JLI_StringDup(name);
 707             }
 708     }
 709 
 710     /*
 711      * Extract "JavaHome" from the "best" registry directory and return
 712      * that path.  If no appropriate version was located, or there is an
 713      * error in extracting the "JavaHome" string, return null.
 714      */
 715     if (best == NULL)
 716         return (NULL);
 717     else {
 718         if (RegOpenKeyEx(top_key, best, 0, KEY_READ, &ver_key)
 719           != ERROR_SUCCESS) {
 720             JLI_MemFree(best);
 721             if (ver_key != NULL)
 722                 RegCloseKey(ver_key);
 723             return (NULL);
 724         }
 725         JLI_MemFree(best);
 726         len = MAXNAMELEN;
 727         if (RegQueryValueEx(ver_key, "JavaHome", NULL, NULL, (LPBYTE)name, &len)
 728           != ERROR_SUCCESS) {
 729             if (ver_key != NULL)
 730                 RegCloseKey(ver_key);
 731             return (NULL);
 732         }
 733         if (ver_key != NULL)
 734             RegCloseKey(ver_key);
 735         return (JLI_StringDup(name));
 736     }
 737 }
 738 
 739 /*
 740  * This is the global entry point. It examines the host for the optimal
 741  * JRE to be used by scanning a set of registry entries.  This set of entries
 742  * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment"
 743  * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }".
 744  *
 745  * This routine simply opens each of these registry directories before passing
 746  * control onto ProcessDir().
 747  */
 748 char *
 749 LocateJRE(manifest_info* info) {
 750     HKEY    key = NULL;
 751     char    *path;
 752     int     key_index;
 753     HKEY    root_keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
 754 
 755     for (key_index = 0; key_index <= 1; key_index++) {
 756         if (RegOpenKeyEx(root_keys[key_index], JRE_KEY, 0, KEY_READ, &key)
 757           == ERROR_SUCCESS)
 758             if ((path = ProcessDir(info, key)) != NULL) {
 759                 if (key != NULL)
 760                     RegCloseKey(key);
 761                 return (path);
 762             }
 763         if (key != NULL)
 764             RegCloseKey(key);
 765     }
 766     return NULL;
 767 }
 768 
 769 /*
 770  * Local helper routine to isolate a single token (option or argument)
 771  * from the command line.
 772  *
 773  * This routine accepts a pointer to a character pointer.  The first
 774  * token (as defined by MSDN command-line argument syntax) is isolated
 775  * from that string.
 776  *
 777  * Upon return, the input character pointer pointed to by the parameter s
 778  * is updated to point to the remainding, unscanned, portion of the string,
 779  * or to a null character if the entire string has been consummed.
 780  *
 781  * This function returns a pointer to a null-terminated string which
 782  * contains the isolated first token, or to the null character if no
 783  * token could be isolated.
 784  *
 785  * Note the side effect of modifying the input string s by the insertion
 786  * of a null character, making it two strings.
 787  *
 788  * See "Parsing C Command-Line Arguments" in the MSDN Library for the
 789  * parsing rule details.  The rule summary from that specification is:
 790  *
 791  *  * Arguments are delimited by white space, which is either a space or a tab.
 792  *
 793  *  * A string surrounded by double quotation marks is interpreted as a single
 794  *    argument, regardless of white space contained within. A quoted string can
 795  *    be embedded in an argument. Note that the caret (^) is not recognized as
 796  *    an escape character or delimiter.
 797  *
 798  *  * A double quotation mark preceded by a backslash, \", is interpreted as a
 799  *    literal double quotation mark (").
 800  *
 801  *  * Backslashes are interpreted literally, unless they immediately precede a
 802  *    double quotation mark.
 803  *
 804  *  * If an even number of backslashes is followed by a double quotation mark,
 805  *    then one backslash (\) is placed in the argv array for every pair of
 806  *    backslashes (\\), and the double quotation mark (") is interpreted as a
 807  *    string delimiter.
 808  *
 809  *  * If an odd number of backslashes is followed by a double quotation mark,
 810  *    then one backslash (\) is placed in the argv array for every pair of
 811  *    backslashes (\\) and the double quotation mark is interpreted as an
 812  *    escape sequence by the remaining backslash, causing a literal double
 813  *    quotation mark (") to be placed in argv.
 814  */
 815 static char*
 816 nextarg(char** s) {
 817     char    *p = *s;
 818     char    *head;
 819     int     slashes = 0;
 820     int     inquote = 0;
 821 
 822     /*
 823      * Strip leading whitespace, which MSDN defines as only space or tab.
 824      * (Hence, no locale specific "isspace" here.)
 825      */
 826     while (*p != (char)0 && (*p == ' ' || *p == '\t'))
 827         p++;
 828     head = p;                   /* Save the start of the token to return */
 829 
 830     /*
 831      * Isolate a token from the command line.
 832      */
 833     while (*p != (char)0 && (inquote || !(*p == ' ' || *p == '\t'))) {
 834         if (*p == '\\' && *(p+1) == '"' && slashes % 2 == 0)
 835             p++;
 836         else if (*p == '"')
 837             inquote = !inquote;
 838         slashes = (*p++ == '\\') ? slashes + 1 : 0;
 839     }
 840 
 841     /*
 842      * If the token isolated isn't already terminated in a "char zero",
 843      * then replace the whitespace character with one and move to the
 844      * next character.
 845      */
 846     if (*p != (char)0)
 847         *p++ = (char)0;
 848 
 849     /*
 850      * Update the parameter to point to the head of the remaining string
 851      * reflecting the command line and return a pointer to the leading
 852      * token which was isolated from the command line.
 853      */
 854     *s = p;
 855     return (head);
 856 }
 857 
 858 /*
 859  * Local helper routine to return a string equivalent to the input string
 860  * s, but with quotes removed so the result is a string as would be found
 861  * in argv[].  The returned string should be freed by a call to JLI_MemFree().
 862  *
 863  * The rules for quoting (and escaped quotes) are:
 864  *
 865  *  1 A double quotation mark preceded by a backslash, \", is interpreted as a
 866  *    literal double quotation mark (").
 867  *
 868  *  2 Backslashes are interpreted literally, unless they immediately precede a
 869  *    double quotation mark.
 870  *
 871  *  3 If an even number of backslashes is followed by a double quotation mark,
 872  *    then one backslash (\) is placed in the argv array for every pair of
 873  *    backslashes (\\), and the double quotation mark (") is interpreted as a
 874  *    string delimiter.
 875  *
 876  *  4 If an odd number of backslashes is followed by a double quotation mark,
 877  *    then one backslash (\) is placed in the argv array for every pair of
 878  *    backslashes (\\) and the double quotation mark is interpreted as an
 879  *    escape sequence by the remaining backslash, causing a literal double
 880  *    quotation mark (") to be placed in argv.
 881  */
 882 static char*
 883 unquote(const char *s) {
 884     const char *p = s;          /* Pointer to the tail of the original string */
 885     char *un = (char*)JLI_MemAlloc(JLI_StrLen(s) + 1);  /* Ptr to unquoted string */
 886     char *pun = un;             /* Pointer to the tail of the unquoted string */
 887 
 888     while (*p != '\0') {
 889         if (*p == '"') {
 890             p++;
 891         } else if (*p == '\\') {
 892             const char *q = p + JLI_StrSpn(p,"\\");
 893             if (*q == '"')
 894                 do {
 895                     *pun++ = '\\';
 896                     p += 2;
 897                  } while (*p == '\\' && p < q);
 898             else
 899                 while (p < q)
 900                     *pun++ = *p++;
 901         } else {
 902             *pun++ = *p++;
 903         }
 904     }
 905     *pun = '\0';
 906     return un;
 907 }
 908 
 909 /*
 910  * Given a path to a jre to execute, this routine checks if this process
 911  * is indeed that jre.  If not, it exec's that jre.
 912  *
 913  * We want to actually check the paths rather than just the version string
 914  * built into the executable, so that given version specification will yield
 915  * the exact same Java environment, regardless of the version of the arbitrary
 916  * launcher we start with.
 917  */
 918 void
 919 ExecJRE(char *jre, char **argv) {
 920     jint     len;
 921     char    path[MAXPATHLEN + 1];
 922 
 923     const char *progname = GetProgramName();
 924 
 925     /*
 926      * Resolve the real path to the currently running launcher.
 927      */
 928     len = GetModuleFileName(NULL, path, MAXPATHLEN + 1);
 929     if (len == 0 || len > MAXPATHLEN) {
 930         JLI_ReportErrorMessageSys(JRE_ERROR9, progname);
 931         exit(1);
 932     }
 933 
 934     JLI_TraceLauncher("ExecJRE: old: %s\n", path);
 935     JLI_TraceLauncher("ExecJRE: new: %s\n", jre);
 936 
 937     /*
 938      * If the path to the selected JRE directory is a match to the initial
 939      * portion of the path to the currently executing JRE, we have a winner!
 940      * If so, just return.
 941      */
 942     if (JLI_StrNCaseCmp(jre, path, JLI_StrLen(jre)) == 0)
 943         return;                 /* I am the droid you were looking for */
 944 
 945     /*
 946      * If this isn't the selected version, exec the selected version.
 947      */
 948     JLI_Snprintf(path, sizeof(path), "%s\\bin\\%s.exe", jre, progname);
 949 
 950     /*
 951      * Although Windows has an execv() entrypoint, it doesn't actually
 952      * overlay a process: it can only create a new process and terminate
 953      * the old process.  Therefore, any processes waiting on the initial
 954      * process wake up and they shouldn't.  Hence, a chain of pseudo-zombie
 955      * processes must be retained to maintain the proper wait semantics.
 956      * Fortunately the image size of the launcher isn't too large at this
 957      * time.
 958      *
 959      * If it weren't for this semantic flaw, the code below would be ...
 960      *
 961      *     execv(path, argv);
 962      *     JLI_ReportErrorMessage("Error: Exec of %s failed\n", path);
 963      *     exit(1);
 964      *
 965      * The incorrect exec semantics could be addressed by:
 966      *
 967      *     exit((int)spawnv(_P_WAIT, path, argv));
 968      *
 969      * Unfortunately, a bug in Windows spawn/exec impementation prevents
 970      * this from completely working.  All the Windows POSIX process creation
 971      * interfaces are implemented as wrappers around the native Windows
 972      * function CreateProcess().  CreateProcess() takes a single string
 973      * to specify command line options and arguments, so the POSIX routine
 974      * wrappers build a single string from the argv[] array and in the
 975      * process, any quoting information is lost.
 976      *
 977      * The solution to this to get the original command line, to process it
 978      * to remove the new multiple JRE options (if any) as was done for argv
 979      * in the common SelectVersion() routine and finally to pass it directly
 980      * to the native CreateProcess() Windows process control interface.
 981      */
 982     {
 983         char    *cmdline;
 984         char    *p;
 985         char    *np;
 986         char    *ocl;
 987         char    *ccl;
 988         char    *unquoted;
 989         DWORD   exitCode;
 990         STARTUPINFO si;
 991         PROCESS_INFORMATION pi;
 992 
 993         /*
 994          * The following code block gets and processes the original command
 995          * line, replacing the argv[0] equivalent in the command line with
 996          * the path to the new executable and removing the appropriate
 997          * Multiple JRE support options. Note that similar logic exists
 998          * in the platform independent SelectVersion routine, but is
 999          * replicated here due to the syntax of CreateProcess().
1000          *
1001          * The magic "+ 4" characters added to the command line length are
1002          * 2 possible quotes around the path (argv[0]), a space after the
1003          * path and a terminating null character.
1004          */
1005         ocl = GetCommandLine();
1006         np = ccl = JLI_StringDup(ocl);
1007         p = nextarg(&np);               /* Discard argv[0] */
1008         cmdline = (char *)JLI_MemAlloc(JLI_StrLen(path) + JLI_StrLen(np) + 4);
1009         if (JLI_StrChr(path, (int)' ') == NULL && JLI_StrChr(path, (int)'\t') == NULL)
1010             cmdline = JLI_StrCpy(cmdline, path);
1011         else
1012             cmdline = JLI_StrCat(JLI_StrCat(JLI_StrCpy(cmdline, "\""), path), "\"");
1013 
1014         while (*np != (char)0) {                /* While more command-line */
1015             p = nextarg(&np);
1016             if (*p != (char)0) {                /* If a token was isolated */
1017                 unquoted = unquote(p);
1018                 if (*unquoted == '-') {         /* Looks like an option */
1019                     if (JLI_StrCmp(unquoted, "-classpath") == 0 ||
1020                       JLI_StrCmp(unquoted, "-cp") == 0) {       /* Unique cp syntax */
1021                         cmdline = JLI_StrCat(JLI_StrCat(cmdline, " "), p);
1022                         p = nextarg(&np);
1023                         if (*p != (char)0)      /* If a token was isolated */
1024                             cmdline = JLI_StrCat(JLI_StrCat(cmdline, " "), p);
1025                     } else if (JLI_StrNCmp(unquoted, "-version:", 9) != 0 &&
1026                       JLI_StrCmp(unquoted, "-jre-restrict-search") != 0 &&
1027                       JLI_StrCmp(unquoted, "-no-jre-restrict-search") != 0) {
1028                         cmdline = JLI_StrCat(JLI_StrCat(cmdline, " "), p);
1029                     }
1030                 } else {                        /* End of options */
1031                     cmdline = JLI_StrCat(JLI_StrCat(cmdline, " "), p);
1032                     cmdline = JLI_StrCat(JLI_StrCat(cmdline, " "), np);
1033                     JLI_MemFree((void *)unquoted);
1034                     break;
1035                 }
1036                 JLI_MemFree((void *)unquoted);
1037             }
1038         }
1039         JLI_MemFree((void *)ccl);
1040 
1041         if (JLI_IsTraceLauncher()) {
1042             np = ccl = JLI_StringDup(cmdline);
1043             p = nextarg(&np);
1044             printf("ReExec Command: %s (%s)\n", path, p);
1045             printf("ReExec Args: %s\n", np);
1046             JLI_MemFree((void *)ccl);
1047         }
1048         (void)fflush(stdout);
1049         (void)fflush(stderr);
1050 
1051         /*
1052          * The following code is modeled after a model presented in the
1053          * Microsoft Technical Article "Moving Unix Applications to
1054          * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN
1055          * (Februrary 2005).  It approximates UNIX spawn semantics with
1056          * the parent waiting for termination of the child.
1057          */
1058         memset(&si, 0, sizeof(si));
1059         si.cb =sizeof(STARTUPINFO);
1060         memset(&pi, 0, sizeof(pi));
1061 
1062         if (!CreateProcess((LPCTSTR)path,       /* executable name */
1063           (LPTSTR)cmdline,                      /* command line */
1064           (LPSECURITY_ATTRIBUTES)NULL,          /* process security attr. */
1065           (LPSECURITY_ATTRIBUTES)NULL,          /* thread security attr. */
1066           (BOOL)TRUE,                           /* inherits system handles */
1067           (DWORD)0,                             /* creation flags */
1068           (LPVOID)NULL,                         /* environment block */
1069           (LPCTSTR)NULL,                        /* current directory */
1070           (LPSTARTUPINFO)&si,                   /* (in) startup information */
1071           (LPPROCESS_INFORMATION)&pi)) {        /* (out) process information */
1072             JLI_ReportErrorMessageSys(SYS_ERROR1, path);
1073             exit(1);
1074         }
1075 
1076         if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
1077             if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE)
1078                 exitCode = 1;
1079         } else {
1080             JLI_ReportErrorMessage(SYS_ERROR2);
1081             exitCode = 1;
1082         }
1083 
1084         CloseHandle(pi.hThread);
1085         CloseHandle(pi.hProcess);
1086 
1087         exit(exitCode);
1088     }
1089 }
1090 
1091 /*
1092  * Wrapper for platform dependent unsetenv function.
1093  */
1094 int
1095 UnsetEnv(char *name)
1096 {
1097     int ret;
1098     char *buf = JLI_MemAlloc(JLI_StrLen(name) + 2);
1099     buf = JLI_StrCat(JLI_StrCpy(buf, name), "=");
1100     ret = _putenv(buf);
1101     JLI_MemFree(buf);
1102     return (ret);
1103 }
1104 
1105 /* --- Splash Screen shared library support --- */
1106 
1107 static const char* SPLASHSCREEN_SO = "\\bin\\splashscreen.dll";
1108 
1109 static HMODULE hSplashLib = NULL;
1110 


   1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <windows.h>
  27 #include <io.h>
  28 #include <process.h>
  29 #include <stdlib.h>
  30 #include <stdio.h>
  31 #include <stdarg.h>
  32 #include <string.h>
  33 #include <sys/types.h>
  34 #include <sys/stat.h>
  35 #include <wtypes.h>
  36 #include <commctrl.h>
  37 
  38 #include <jni.h>
  39 #include "java.h"

  40 
  41 #define JVM_DLL "jvm.dll"
  42 #define JAVA_DLL "java.dll"
  43 
  44 /*
  45  * Prototypes.
  46  */
  47 static jboolean GetPublicJREHome(char *path, jint pathsize);
  48 static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
  49                            char *jvmpath, jint jvmpathsize);
  50 static jboolean GetJREPath(char *path, jint pathsize);
  51 
  52 /* We supports warmup for UI stack that is performed in parallel
  53  * to VM initialization.
  54  * This helps to improve startup of UI application as warmup phase
  55  * might be long due to initialization of OS or hardware resources.
  56  * It is not CPU bound and therefore it does not interfere with VM init.
  57  * Obviously such warmup only has sense for UI apps and therefore it needs
  58  * to be explicitly requested by passing -Dsun.awt.warmup=true property
  59  * (this is always the case for plugin/javaws).


 656 }
 657 
 658 void  JLI_ReportExceptionDescription(JNIEnv * env) {
 659     if (IsJavaw()) {
 660        /*
 661         * This code should be replaced by code which opens a window with
 662         * the exception detail message, for now atleast put a dialog up.
 663         */
 664         MessageBox(NULL, "A Java Exception has occurred.", "Java Virtual Machine Launcher",
 665                (MB_OK|MB_ICONSTOP|MB_APPLMODAL));
 666     } else {
 667         (*env)->ExceptionDescribe(env);
 668     }
 669 }
 670 
 671 jboolean
 672 ServerClassMachine() {
 673     return (GetErgoPolicy() == ALWAYS_SERVER_CLASS) ? JNI_TRUE : JNI_FALSE;
 674 }
 675 






























































































































































































































































































































































































































 676 /*
 677  * Wrapper for platform dependent unsetenv function.
 678  */
 679 int
 680 UnsetEnv(char *name)
 681 {
 682     int ret;
 683     char *buf = JLI_MemAlloc(JLI_StrLen(name) + 2);
 684     buf = JLI_StrCat(JLI_StrCpy(buf, name), "=");
 685     ret = _putenv(buf);
 686     JLI_MemFree(buf);
 687     return (ret);
 688 }
 689 
 690 /* --- Splash Screen shared library support --- */
 691 
 692 static const char* SPLASHSCREEN_SO = "\\bin\\splashscreen.dll";
 693 
 694 static HMODULE hSplashLib = NULL;
 695