diff --git a/core/org.eclipse.cdt.core.native/native_src/win/Win32ProcessEx.c b/core/org.eclipse.cdt.core.native/native_src/win/Win32ProcessEx.c index f0a8b732b7a..12c4baf3008 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/Win32ProcessEx.c +++ b/core/org.eclipse.cdt.core.native/native_src/win/Win32ProcessEx.c @@ -62,7 +62,7 @@ typedef struct _procInfo { static int procCounter = 0; // Number of running processes // This is a VM helper -void ThrowByName(JNIEnv *env, const char *name, const char *msg); +void ThrowByName(JNIEnv *env, const char *name, const wchar_t *msg); // Creates _procInfo block for every launched process pProcInfo_t createProcInfo(); @@ -213,7 +213,7 @@ static bool createCommandLine(JNIEnv *env, jobjectArray cmdarray, wchar_t **cmdL } else { // malloc failed, clean up and return va_end(ap); - ThrowByName(env, "java/io/IOException", "Not enough memory"); + ThrowByName(env, "java/io/IOException", L"Not enough memory"); return false; } } while (size <= required); @@ -229,7 +229,7 @@ static bool createCommandLine(JNIEnv *env, jobjectArray cmdarray, wchar_t **cmdL required = nPos + len + 2; // 2 => space + \0 if (required > 32 * 1024) { free(buffer); - ThrowByName(env, "java/io/IOException", "Command line too long"); + ThrowByName(env, "java/io/IOException", L"Command line too long"); return false; } @@ -248,7 +248,7 @@ static bool createCommandLine(JNIEnv *env, jobjectArray cmdarray, wchar_t **cmdL } else { // Failed to realloc memory free(buffer); - ThrowByName(env, "java/io/IOException", "Not enough memory"); + ThrowByName(env, "java/io/IOException", L"Not enough memory"); return false; } } @@ -270,7 +270,7 @@ static bool createCommandLine(JNIEnv *env, jobjectArray cmdarray, wchar_t **cmdL (*env)->ReleaseStringChars(env, item, str); } else { free(buffer); - ThrowByName(env, "java/io/IOException", "Command line contained null string"); + ThrowByName(env, "java/io/IOException", L"Command line contained null string"); return false; } } @@ -307,7 +307,7 @@ static bool createEnvironmentBlock(JNIEnv *env, jobjectArray envp, wchar_t **blo } else { free(buffer); (*env)->ReleaseStringChars(env, item, str); - ThrowByName(env, "java/io/IOException", "Not enough memory"); + ThrowByName(env, "java/io/IOException", L"Not enough memory"); return false; } if (isTraceEnabled(CDT_TRACE_SPAWNER)) { @@ -338,29 +338,29 @@ extern "C" Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv *env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jobjectArray channels) { if (!channels) { - ThrowByName(env, "java/io/IOException", "Channels can't be null"); + ThrowByName(env, "java/io/IOException", L"Channels can't be null"); return 0; } jclass channelClass = (*env)->FindClass(env, "org/eclipse/cdt/utils/spawner/Spawner$WinChannel"); if (!channelClass) { - ThrowByName(env, "java/io/IOException", "Unable to find channel class"); + ThrowByName(env, "java/io/IOException", L"Unable to find channel class"); return 0; } jmethodID channelConstructor = (*env)->GetMethodID(env, channelClass, "", "(J)V"); if (!channelConstructor) { - ThrowByName(env, "java/io/IOException", "Unable to find channel constructor"); + ThrowByName(env, "java/io/IOException", L"Unable to find channel constructor"); return 0; } if ((HIBYTE(LOWORD(GetVersion()))) & 0x80) { - ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me"); + ThrowByName(env, "java/io/IOException", L"Does not support Windows 3.1/95/98/Me"); return 0; } if (!cmdarray) { - ThrowByName(env, "java/lang/NullPointerException", "No command line specified"); + ThrowByName(env, "java/lang/NullPointerException", L"No command line specified"); return 0; } @@ -376,14 +376,14 @@ extern "C" !createStandardNamedPipe(&stdHandles[1], STD_OUTPUT_HANDLE, pid, nLocalCounter) || !createStandardNamedPipe(&stdHandles[2], STD_ERROR_HANDLE, pid, nLocalCounter)) { CLOSE_HANDLES(stdHandles); - ThrowByName(env, "java/io/IOException", "CreatePipe"); + ThrowByName(env, "java/io/IOException", L"CreatePipe"); return 0; } pProcInfo_t pCurProcInfo = createProcInfo(); if (!pCurProcInfo) { CLOSE_HANDLES(stdHandles); - ThrowByName(env, "java/io/IOException", "Too many processes"); + ThrowByName(env, "java/io/IOException", L"Too many processes"); return 0; } @@ -395,7 +395,7 @@ extern "C" !createNamedEvent(&pCurProcInfo->eventCtrlc, FALSE, L"SACtrlc", pid, nLocalCounter)) { cleanUpProcBlock(pCurProcInfo); CLOSE_HANDLES(stdHandles); - ThrowByName(env, "java/io/IOException", "Cannot create event"); + ThrowByName(env, "java/io/IOException", L"Cannot create event"); return 0; } @@ -463,6 +463,8 @@ extern "C" &si, /* (in) startup information */ &pi); /* (out) process information */ + const DWORD error_CreateProcessW = GetLastError(); + free(cwd); free(envBlock); free(cmdLine); @@ -483,7 +485,7 @@ extern "C" } cleanUpProcBlock(pCurProcInfo); CLOSE_HANDLES(stdHandles); - ThrowByName(env, "java/io/IOException", "Launching failed"); + ThrowByName(env, "java/io/IOException", L"Launching failed"); if (isTraceEnabled(CDT_TRACE_SPAWNER)) { cdtTrace(L"Process failed\n"); } @@ -508,14 +510,12 @@ extern "C" } LeaveCriticalSection(&cs); } else { // Launching error - char *lpMsgBuf; + wchar_t *lpMsgBuf; CLOSE_HANDLES(stdHandles); - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (char *)&lpMsgBuf, 0, NULL); + lpMsgBuf = formatWinErrorCode(error_CreateProcessW); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. - LocalFree(lpMsgBuf); + free(lpMsgBuf); cleanUpProcBlock(pCurProcInfo); ret = -1; } @@ -580,6 +580,7 @@ extern "C" cwd, /* change to the new current directory */ &si, /* (in) startup information */ &pi); /* (out) process information */ + const DWORD error_CreateProcessW = GetLastError(); free(cwd); free(cmdLine); @@ -591,14 +592,10 @@ extern "C" CloseHandle(pi.hProcess); ret = (long)pi.dwProcessId; // hProcess; } else { // error - char *lpMsgBuf; - - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (wchar_t *)&lpMsgBuf, 0, NULL); + wchar_t *lpMsgBuf = formatWinErrorCode(error_CreateProcessW); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. - LocalFree(lpMsgBuf); + free(lpMsgBuf); ret = -1; } @@ -730,13 +727,23 @@ extern "C" // Throws Java exception (will be trapped by VM). // Arguments: // [in] name - name of exception class -// [in] message to assign thi event +// [in] message to assign the event ///////////////////////////////////////////////////////////////////////////////////// -void ThrowByName(JNIEnv *env, const char *name, const char *msg) { +void ThrowByName(JNIEnv *env, const char *name, const wchar_t *msg) { jclass cls = (*env)->FindClass(env, name); if (cls) { /* Otherwise an exception has already been thrown */ - (*env)->ThrowNew(env, cls, msg); + size_t msgLen = wcslen(msg); + int nChars = WideCharToMultiByte(CP_UTF8, 0, msg, msgLen, NULL, 0, NULL, NULL); + if (nChars == 0) { + (*env)->ThrowNew(env, cls, ""); + } else { + // ThrowNew expects message to be encoded in "modified UTF-8" + char *buf = (char *)calloc(nChars + 1, sizeof(char)); + WideCharToMultiByte(CP_UTF8, 0, msg, msgLen, buf, nChars, NULL, NULL); + (*env)->ThrowNew(env, cls, buf); + free(buf); + } } /* It's a good practice to clean up the local references. */ diff --git a/core/org.eclipse.cdt.core.native/native_src/win/iostream.c b/core/org.eclipse.cdt.core.native/native_src/win/iostream.c index dfcfb32efbf..64d63415774 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/iostream.c +++ b/core/org.eclipse.cdt.core.native/native_src/win/iostream.c @@ -25,25 +25,25 @@ #include -void ThrowByName(JNIEnv *env, const char *name, const char *msg); +void ThrowByName(JNIEnv *env, const char *name, const wchar_t *msg); #define BUFF_SIZE (1024) static HANDLE channelToHandle(JNIEnv *env, jobject channel) { if (!channel) { - ThrowByName(env, "java/io/IOException", "Invalid channel object"); + ThrowByName(env, "java/io/IOException", L"Invalid channel object"); return NULL; } jclass cls = (*env)->GetObjectClass(env, channel); if (!cls) { - ThrowByName(env, "java/io/IOException", "Unable to get channel class"); + ThrowByName(env, "java/io/IOException", L"Unable to get channel class"); return NULL; } jfieldID fid = (*env)->GetFieldID(env, cls, "handle", "J"); if (!fid) { - ThrowByName(env, "java/io/IOException", "Unable to find handle"); + ThrowByName(env, "java/io/IOException", L"Unable to find handle"); return NULL; } @@ -70,14 +70,10 @@ extern "C" NULL); // unnamed event object if (!overlapped.hEvent) { - char *lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (wchar_t *)&lpMsgBuf, 0, NULL); - + wchar_t *lpMsgBuf = formatWinErrorCode(GetLastError()); ThrowByName(env, "java/io/IOException", lpMsgBuf); // Free the buffer. - LocalFree(lpMsgBuf); + free(lpMsgBuf); } if (isTraceEnabled(CDT_TRACE_SPAWNER) && isTraceEnabled(CDT_TRACE_SPAWNER_READ_REPORT)) { @@ -103,19 +99,14 @@ extern "C" break; } if (err != 0) { - char *lpMsgBuf; if (isTraceEnabled(CDT_TRACE_SPAWNER)) { cdtTrace(L"Read failed - %p, error %i\n", handle, err); } if (err != ERROR_MORE_DATA) { // Otherwise error means just that there are more data than buffer can accept - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (wchar_t *)&lpMsgBuf, 0, NULL); - + wchar_t *lpMsgBuf = formatWinErrorCode(err); ThrowByName(env, "java/io/IOException", lpMsgBuf); - LocalFree(lpMsgBuf); + free(lpMsgBuf); nBuffOffset = 0; break; } else { @@ -200,13 +191,9 @@ extern "C" DWORD nNumberOfBytesWritten; (*env)->GetByteArrayRegion(env, buf, nBuffOffset, nNumberOfBytesToWrite, tmpBuf); if (0 == WriteFile(handle, tmpBuf, nNumberOfBytesToWrite, &nNumberOfBytesWritten, NULL)) { - char *lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (wchar_t *)&lpMsgBuf, 0, NULL); - + wchar_t *lpMsgBuf = formatWinErrorCode(GetLastError()); ThrowByName(env, "java/io/IOException", lpMsgBuf); - LocalFree(lpMsgBuf); + free(lpMsgBuf); return 0; } nBuffOffset += nNumberOfBytesWritten; diff --git a/core/org.eclipse.cdt.core.native/native_src/win/starter.c b/core/org.eclipse.cdt.core.native/native_src/win/starter.c index 85e58f93f50..0e20b9257d4 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/starter.c +++ b/core/org.eclipse.cdt.core.native/native_src/win/starter.c @@ -479,12 +479,9 @@ int main() { } void DisplayErrorMessage() { - wchar_t *lpMsgBuf; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (wchar_t *)&lpMsgBuf, 0, NULL); + wchar_t *lpMsgBuf = formatWinErrorCode(GetLastError()); OutputDebugStringW(lpMsgBuf); // Free the buffer. - LocalFree(lpMsgBuf); + free(lpMsgBuf); } //////////////////////////////// End of File ////////////////////////////////// diff --git a/core/org.eclipse.cdt.core.native/native_src/win/util.c b/core/org.eclipse.cdt.core.native/native_src/win/util.c index 01b1c35521a..13041c39be6 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/util.c +++ b/core/org.eclipse.cdt.core.native/native_src/win/util.c @@ -151,3 +151,39 @@ int copyTo(wchar_t *target, const wchar_t *source, int cpyLength, int availSpace return j; } + +wchar_t *formatWinErrorCode(DWORD messageId) { + const wchar_t *NULL_STR = L"(null)"; + size_t size = 0; + wchar_t *msg = NULL; + + DWORD langId[] = { + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // US English + MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), // Any English + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // User default language + 0 // Let FormatMessage lookup the right language + }; + wchar_t *winBuf = NULL; + + /* Format the message */ + for (size_t i = 0; i < sizeof(langId) / sizeof(langId[0]); i++) { + if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, messageId, langId[i], (wchar_t *)&winBuf, 0, NULL) == 0) { + winBuf = NULL; + } + + if (winBuf != NULL) { + break; + } + } + + /* Prefix the message */ + size = 100 + wcslen(winBuf ? winBuf : NULL_STR); + msg = (wchar_t *)calloc(size + 1, sizeof(wchar_t)); + if (msg) { + snwprintf(msg, size, L"Code 0x%lx: %s", (unsigned long)messageId, (winBuf ? winBuf : NULL_STR)); + } + + LocalFree(winBuf); + return msg; +} diff --git a/core/org.eclipse.cdt.core.native/native_src/win/util.h b/core/org.eclipse.cdt.core.native/native_src/win/util.h index 89b0604671b..1fa1ffd4ffb 100644 --- a/core/org.eclipse.cdt.core.native/native_src/win/util.h +++ b/core/org.eclipse.cdt.core.native/native_src/win/util.h @@ -48,4 +48,7 @@ void cdtTrace(const wchar_t *fmt, ...); int copyTo(wchar_t *target, const wchar_t *source, int cpyLength, int availSpace); +// Returned pointer shall be freed with free(). +wchar_t *formatWinErrorCode(DWORD messageId); + #endif /* UTIL_H */ diff --git a/core/org.eclipse.cdt.core.win32.x86_64/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.win32.x86_64/META-INF/MANIFEST.MF index bc0e7885833..8a6feffc05b 100644 --- a/core/org.eclipse.cdt.core.win32.x86_64/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.win32.x86_64/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %fragmentName.win32.x86_64 Bundle-SymbolicName: org.eclipse.cdt.core.win32.x86_64;singleton:=true -Bundle-Version: 6.0.100.qualifier +Bundle-Version: 6.0.200.qualifier Fragment-Host: org.eclipse.cdt.core.native;bundle-version="[6.0.0,7.0.0)" Eclipse-PlatformFilter: (&(osgi.os=win32)(osgi.arch=x86_64)) Bundle-Vendor: %providerName diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll index 2dc4174a57d..321c33ca84b 100755 Binary files a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/pty.dll differ diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/spawner.dll b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/spawner.dll index df14caadec9..ca657101007 100755 Binary files a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/spawner.dll and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/spawner.dll differ diff --git a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe index 919062dbd93..2add8441589 100755 Binary files a/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe and b/core/org.eclipse.cdt.core.win32.x86_64/os/win32/x86_64/starter.exe differ diff --git a/core/org.eclipse.cdt.core.win32.x86_64/pom.xml b/core/org.eclipse.cdt.core.win32.x86_64/pom.xml index 30d59fefd09..3e87f42408e 100644 --- a/core/org.eclipse.cdt.core.win32.x86_64/pom.xml +++ b/core/org.eclipse.cdt.core.win32.x86_64/pom.xml @@ -21,7 +21,7 @@ ../../pom.xml - 6.0.100-SNAPSHOT + 6.0.200-SNAPSHOT org.eclipse.cdt.core.win32.x86_64 eclipse-plugin