1 /* 2 * Copyright (c) 2004, 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 <stdlib.h> 27 #include <string.h> 28 #include <windows.h> 29 #include <locale.h> 30 31 #include "jni.h" 32 #include "jni_util.h" 33 34 static void getParent(const TCHAR *path, TCHAR *dest) { 35 char* lastSlash = max(strrchr(path, '\\'), strrchr(path, '/')); 36 if (lastSlash == NULL) { 37 *dest = 0; 38 return; 39 } 40 if (path != dest) 41 strcpy(dest, path); 42 *lastSlash = 0; 43 } 44 45 BOOL useNativeConverter(JNIEnv *env) { 46 static BOOL initialized; 47 static BOOL useNative; 48 if (!initialized) { 49 HMODULE jvm = GetModuleHandle("jvm"); 50 useNative = FALSE; 51 if (jvm != NULL) { 52 TCHAR *jvmPath = NULL; 53 int bufferSize = MAX_PATH; 54 while (jvmPath == NULL) { 55 DWORD result; 56 jvmPath = malloc(bufferSize); 57 if (jvmPath == NULL) 58 return FALSE; 59 result = GetModuleFileName(jvm, jvmPath, bufferSize); 60 if (result == 0) 61 return FALSE; 62 if (result == bufferSize) { // didn't fit 63 bufferSize += MAX_PATH; // increase buffer size, try again 64 free(jvmPath); 65 jvmPath = NULL; 66 } 67 } 68 69 getParent(jvmPath, jvmPath); 70 useNative = (!strcmp("kernel", jvmPath + strlen(jvmPath) - 71 strlen("kernel"))); // true if jvm.dll lives in "kernel" 72 if (useNative) 73 setlocale(LC_ALL, ""); 74 free(jvmPath); 75 } 76 initialized = TRUE; 77 } 78 return useNative; 79 } 80 81 jstring nativeNewStringPlatform(JNIEnv *env, const char *str) { 82 static jmethodID String_char_constructor; 83 if (useNativeConverter(env)) { 84 // use native Unicode conversion so Kernel isn't required during 85 // System.initProperties 86 jcharArray chars = 0; 87 wchar_t *utf16; 88 int len; 89 jstring result = NULL; 90 91 if (getFastEncoding() == NO_ENCODING_YET) 92 initializeEncoding(env); 93 94 len = mbstowcs(NULL, str, strlen(str)); 95 if (len == -1) 96 return NULL; 97 utf16 = calloc(len + 1, 2); 98 if (mbstowcs(utf16, str, len) == -1) 99 return NULL; 100 chars = (*env)->NewCharArray(env, len); 101 if (chars == NULL) 102 return NULL; 103 (*env)->SetCharArrayRegion(env, chars, 0, len, utf16); 104 if (String_char_constructor == NULL) 105 String_char_constructor = (*env)->GetMethodID(env, 106 JNU_ClassString(env), "<init>", "([C)V"); 107 result = (*env)->NewObject(env, JNU_ClassString(env), 108 String_char_constructor, chars); 109 free(utf16); 110 return result; 111 } 112 else 113 return NULL; 114 } 115 116 117 char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) { 118 if (useNativeConverter(env)) { 119 // use native Unicode conversion so Kernel isn't required during 120 // System.initProperties 121 char *result = NULL; 122 size_t len; 123 const jchar* utf16 = (*env)->GetStringChars(env, jstr, NULL); 124 len = wcstombs(NULL, utf16, (*env)->GetStringLength(env, jstr) * 4) + 1; 125 if (len == -1) 126 return NULL; 127 result = (char*) malloc(len); 128 if (result != NULL) { 129 if (wcstombs(result, utf16, len) == -1) 130 return NULL; 131 (*env)->ReleaseStringChars(env, jstr, utf16); 132 if (isCopy) 133 *isCopy = JNI_TRUE; 134 } 135 return result; 136 } 137 else 138 return NULL; 139 } 140 141 void* getProcessHandle() { 142 return (void*)GetModuleHandle(NULL); 143 } 144 145 int 146 getErrorString(int err, char *buf, size_t len) 147 { 148 int ret = 0; 149 if (err == 0 || len < 1) return 0; 150 ret = strerror_s(buf, len, err); 151 return ret; 152 } 153 154 /* 155 * Windows symbols can be simple like JNI_OnLoad or __stdcall format 156 * like _JNI_OnLoad@8. We need to handle both. 157 */ 158 void buildJniFunctionName(const char *sym, const char *cname, 159 char *jniEntryName) { 160 if (cname != NULL) { 161 char *p = strrchr(sym, '@'); 162 if (p != NULL && p != sym) { 163 // sym == _JNI_OnLoad@8 164 strncpy(jniEntryName, sym, (p - sym)); 165 jniEntryName[(p-sym)] = '\0'; 166 // jniEntryName == _JNI_OnLoad 167 strcat(jniEntryName, "_"); 168 strcat(jniEntryName, cname); 169 strcat(jniEntryName, p); 170 //jniEntryName == _JNI_OnLoad_cname@8 171 } else { 172 strcpy(jniEntryName, sym); 173 strcat(jniEntryName, "_"); 174 strcat(jniEntryName, cname); 175 } 176 } else { 177 strcpy(jniEntryName, sym); 178 } 179 return; 180 }