1 /* 2 * Copyright (c) 2004, 2018, 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 void* getProcessHandle() { 46 return (void*)GetModuleHandle(NULL); 47 } 48 49 /* 50 * Windows symbols can be simple like JNI_OnLoad or __stdcall format 51 * like _JNI_OnLoad@8. We need to handle both. 52 */ 53 void buildJniFunctionName(const char *sym, const char *cname, 54 char *jniEntryName) { 55 if (cname != NULL) { 56 char *p = strrchr(sym, '@'); 57 if (p != NULL && p != sym) { 58 // sym == _JNI_OnLoad@8 59 strncpy(jniEntryName, sym, (p - sym)); 60 jniEntryName[(p-sym)] = '\0'; 61 // jniEntryName == _JNI_OnLoad 62 strcat(jniEntryName, "_"); 63 strcat(jniEntryName, cname); 64 strcat(jniEntryName, p); 65 //jniEntryName == _JNI_OnLoad_cname@8 66 } else { 67 strcpy(jniEntryName, sym); 68 strcat(jniEntryName, "_"); 69 strcat(jniEntryName, cname); 70 } 71 } else { 72 strcpy(jniEntryName, sym); 73 } 74 return; 75 } 76 77 JNIEXPORT size_t JNICALL 78 getLastErrorString(char *utf8_jvmErrorMsg, size_t cbErrorMsg) 79 { 80 size_t n = 0; 81 if (cbErrorMsg > 0) { 82 BOOLEAN noError = FALSE; 83 WCHAR *utf16_osErrorMsg = (WCHAR *)malloc(cbErrorMsg*sizeof(WCHAR)); 84 if (utf16_osErrorMsg == NULL) { 85 // OOM accident 86 strncpy(utf8_jvmErrorMsg, "Out of memory", cbErrorMsg); 87 // truncate if too long 88 utf8_jvmErrorMsg[cbErrorMsg - 1] = '\0'; 89 n = strlen(utf8_jvmErrorMsg); 90 } else { 91 DWORD errval = GetLastError(); 92 if (errval != 0) { 93 // WIN32 error 94 n = (size_t)FormatMessageW( 95 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 96 NULL, 97 errval, 98 0, 99 utf16_osErrorMsg, 100 (DWORD)cbErrorMsg, 101 NULL); 102 if (n > 3) { 103 // Drop final '.', CR, LF 104 if (utf16_osErrorMsg[n - 1] == L'\n') --n; 105 if (utf16_osErrorMsg[n - 1] == L'\r') --n; 106 if (utf16_osErrorMsg[n - 1] == L'.') --n; 107 utf16_osErrorMsg[n] = L'\0'; 108 } 109 } else if (errno != 0) { 110 // C runtime error that has no corresponding WIN32 error code 111 int ret = _wcserror_s(utf16_osErrorMsg, cbErrorMsg, errno); 112 if (ret == 0) 113 n = wcslen(utf16_osErrorMsg); 114 } else 115 noError = TRUE; //OS has no error to report 116 117 if (!noError) { 118 if (n > 0) { 119 n = WideCharToMultiByte( 120 CP_UTF8, 121 0, 122 utf16_osErrorMsg, 123 (int)n, 124 utf8_jvmErrorMsg, 125 (int)cbErrorMsg, 126 NULL, 127 NULL); 128 129 // no way to die 130 if (n > 0) 131 utf8_jvmErrorMsg[min(cbErrorMsg - 1, n)] = '\0'; 132 } 133 134 if (n <= 0) { 135 strncpy(utf8_jvmErrorMsg, "Secondary error while OS message extraction", cbErrorMsg); 136 // truncate if too long 137 utf8_jvmErrorMsg[cbErrorMsg - 1] = '\0'; 138 n = strlen(utf8_jvmErrorMsg); 139 } 140 } 141 free(utf16_osErrorMsg); 142 } 143 } 144 return n; 145 } 146 147 JNIEXPORT int JNICALL 148 getErrorString(int err, char *buf, size_t len) 149 { 150 int ret = 0; 151 if (err == 0 || len < 1) return 0; 152 ret = strerror_s(buf, len, err); 153 return ret; 154 }