Mercurial > hg > release > icedtea7-forest-2.2 > jdk
changeset 2374:1105276dbd6a
4947220: (process)Runtime.exec() cannot invoke applications with unicode parameters(win)
Summary: to use CreateProcessW on Windowns platform
Reviewed-by: martin
author | sherman |
---|---|
date | Sat, 03 Apr 2010 18:29:11 -0700 |
parents | 3771ac2a8b3b |
children | a9fdd143a58e |
files | src/share/native/java/lang/System.c src/share/native/java/lang/java_props.h src/solaris/native/java/lang/java_props_md.c src/windows/native/java/lang/ProcessImpl_md.c src/windows/native/java/lang/java_props_md.c test/java/lang/ProcessBuilder/Basic.java |
diffstat | 6 files changed, 119 insertions(+), 98 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/native/java/lang/System.c Tue Mar 30 19:10:47 2010 -0700 +++ b/src/share/native/java/lang/System.c Sat Apr 03 18:29:11 2010 -0700 @@ -67,10 +67,13 @@ (*env)->DeleteLocalRef(env, r); \ } else ((void) 0) -#define PUTPROP_ForPlatformCString(props, key, val) \ +/* "key" is a char type string with only ASCII character in it. + "val" is a nchar (typedefed in java_props.h) type string */ + +#define PUTPROP_ForPlatformNString(props, key, val) \ if (1) { \ - jstring jkey = JNU_NewStringPlatform(env, key); \ - jstring jval = JNU_NewStringPlatform(env, val); \ + jstring jkey = (*env)->NewStringUTF(env, key); \ + jstring jval = GetStringPlatform(env, val); \ jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ if ((*env)->ExceptionOccurred(env)) return NULL; \ (*env)->DeleteLocalRef(env, jkey); \ @@ -150,7 +153,7 @@ (sprops->cpu_isalist ? sprops->cpu_isalist : "")); PUTPROP(props, "sun.cpu.endian", sprops->cpu_endian); - /* !!! DO NOT call PUTPROP_ForPlatformCString before this line !!! + /* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!! * !!! I18n properties have not been set up yet !!! */ @@ -195,18 +198,18 @@ */ PUTPROP(props, "java.awt.graphicsenv", sprops->graphics_env); if (sprops->font_dir != NULL) { - PUTPROP_ForPlatformCString(props, + PUTPROP_ForPlatformNString(props, "sun.java2d.fontpath", sprops->font_dir); } - PUTPROP_ForPlatformCString(props, "java.io.tmpdir", sprops->tmp_dir); + PUTPROP_ForPlatformNString(props, "java.io.tmpdir", sprops->tmp_dir); - PUTPROP_ForPlatformCString(props, "user.name", sprops->user_name); - PUTPROP_ForPlatformCString(props, "user.home", sprops->user_home); + PUTPROP_ForPlatformNString(props, "user.name", sprops->user_name); + PUTPROP_ForPlatformNString(props, "user.home", sprops->user_home); PUTPROP(props, "user.timezone", sprops->timezone); - PUTPROP_ForPlatformCString(props, "user.dir", sprops->user_dir); + PUTPROP_ForPlatformNString(props, "user.dir", sprops->user_dir); /* This is a sun. property as it is currently only set for Gnome and * Windows desktops.
--- a/src/share/native/java/lang/java_props.h Tue Mar 30 19:10:47 2010 -0700 +++ b/src/share/native/java/lang/java_props.h Sat Apr 03 18:29:11 2010 -0700 @@ -28,21 +28,29 @@ #include <jni_util.h> +/* The preferred native type for storing text on the current OS */ +#ifdef WIN32 +#include <tchar.h> +typedef WCHAR nchar; +#else +typedef char nchar; +#endif + typedef struct { char *os_name; char *os_version; char *os_arch; - char *tmp_dir; - char *font_dir; - char *user_dir; + nchar *tmp_dir; + nchar *font_dir; + nchar *user_dir; char *file_separator; char *path_separator; char *line_separator; - char *user_name; - char *user_home; + nchar *user_name; + nchar *user_home; char *language; char *country; @@ -71,5 +79,6 @@ } java_props_t; java_props_t *GetJavaProperties(JNIEnv *env); +jstring GetStringPlatform(JNIEnv *env, nchar* str); #endif /* _JAVA_PROPS_H */
--- a/src/solaris/native/java/lang/java_props_md.c Tue Mar 30 19:10:47 2010 -0700 +++ b/src/solaris/native/java/lang/java_props_md.c Sat Apr 03 18:29:11 2010 -0700 @@ -416,3 +416,9 @@ return &sprops; } + +jstring +GetStringPlatform(JNIEnv *env, nchar* cstr) +{ + return JNU_NewStringPlatform(env, cstr); +}
--- a/src/windows/native/java/lang/ProcessImpl_md.c Tue Mar 30 19:10:47 2010 -0700 +++ b/src/windows/native/java/lang/ProcessImpl_md.c Sat Apr 03 18:29:11 2010 -0700 @@ -145,11 +145,11 @@ HANDLE errWrite = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; - STARTUPINFO si; - LPTSTR pcmd = NULL; - LPCTSTR pdir = NULL; - LPVOID penvBlock = NULL; - jlong *handles = NULL; + STARTUPINFOW si; + const jchar* pcmd = NULL; + const jchar* pdir = NULL; + const jchar* penvBlock = NULL; + jlong *handles = NULL; jlong ret = 0; OSVERSIONINFO ver; jboolean onNT = JNI_FALSE; @@ -161,22 +161,17 @@ onNT = JNI_TRUE; assert(cmd != NULL); - pcmd = (LPTSTR) JNU_GetStringPlatformChars(env, cmd, NULL); + pcmd = (*env)->GetStringChars(env, cmd, NULL); if (pcmd == NULL) goto Catch; if (dir != 0) { - pdir = (LPCTSTR) JNU_GetStringPlatformChars(env, dir, NULL); + pdir = (*env)->GetStringChars(env, dir, NULL); if (pdir == NULL) goto Catch; - pdir = (LPCTSTR) JVM_NativePath((char *)pdir); } - if (envBlock != NULL) { - penvBlock = onNT - ? (LPVOID) ((*env)->GetStringChars(env, envBlock, NULL)) - : (LPVOID) JNU_GetStringPlatformChars(env, envBlock, NULL); + penvBlock = ((*env)->GetStringChars(env, envBlock, NULL)); if (penvBlock == NULL) goto Catch; } - assert(stdHandles != NULL); handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); if (handles == NULL) goto Catch; @@ -237,30 +232,17 @@ if (onNT) processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; else - processFlag = selectProcessFlag(env, cmd); - - /* Java and Windows are both pure Unicode systems at heart. - * Windows has both a legacy byte-based API and a 16-bit Unicode - * "W" API. The Right Thing here is to call CreateProcessW, since - * that will allow all process-related information like command - * line arguments to be passed properly to the child. We don't do - * that currently, since we would first have to have "W" versions - * of JVM_NativePath and perhaps other functions. In the - * meantime, we can call CreateProcess with the magic flag - * CREATE_UNICODE_ENVIRONMENT, which passes only the environment - * in "W" mode. We will fix this later. */ - - ret = CreateProcess(0, /* executable name */ - pcmd, /* command line */ - 0, /* process security attribute */ - 0, /* thread security attribute */ - TRUE, /* inherits system handles */ - processFlag, /* selected based on exe type */ - penvBlock, /* environment block */ - pdir, /* change to the new current directory */ - &si, /* (in) startup information */ - &pi); /* (out) process information */ - + processFlag = selectProcessFlag(env, cmd) | CREATE_UNICODE_ENVIRONMENT; + ret = CreateProcessW(0, /* executable name */ + (LPWSTR)pcmd, /* command line */ + 0, /* process security attribute */ + 0, /* thread security attribute */ + TRUE, /* inherits system handles */ + processFlag, /* selected based on exe type */ + (LPVOID)penvBlock,/* environment block */ + (LPCWSTR)pdir, /* change to the new current directory */ + &si, /* (in) startup information */ + &pi); /* (out) process information */ if (!ret) { win32Error(env, "CreateProcess"); goto Catch; @@ -276,18 +258,13 @@ closeSafely(errWrite); if (pcmd != NULL) - JNU_ReleaseStringPlatformChars(env, cmd, (char *) pcmd); + (*env)->ReleaseStringChars(env, cmd, pcmd); if (pdir != NULL) - JNU_ReleaseStringPlatformChars(env, dir, (char *) pdir); - if (penvBlock != NULL) { - if (onNT) - (*env)->ReleaseStringChars(env, envBlock, (jchar *) penvBlock); - else - JNU_ReleaseStringPlatformChars(env, dir, (char *) penvBlock); - } + (*env)->ReleaseStringChars(env, dir, pdir); + if (penvBlock != NULL) + (*env)->ReleaseStringChars(env, envBlock, penvBlock); if (handles != NULL) (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); - return ret; Catch:
--- a/src/windows/native/java/lang/java_props_md.c Tue Mar 30 19:10:47 2010 -0700 +++ b/src/windows/native/java/lang/java_props_md.c Sat Apr 03 18:29:11 2010 -0700 @@ -513,14 +513,14 @@ /* * Code to figure out the user's home directory using the registry */ -static char * +static WCHAR* getHomeFromRegistry() { HKEY key; int rc; DWORD type; - char *p; - char path[MAX_PATH+1]; + WCHAR *p; + WCHAR path[MAX_PATH+1]; int size = MAX_PATH+1; rc = RegOpenKeyEx(HKEY_CURRENT_USER, SHELL_KEY, 0, KEY_READ, &key); @@ -530,18 +530,18 @@ } path[0] = 0; - rc = RegQueryValueEx(key, "Desktop", 0, &type, path, &size); + rc = RegQueryValueExW(key, L"Desktop", 0, &type, (LPBYTE)path, &size); if (rc != ERROR_SUCCESS || type != REG_SZ) { return NULL; } RegCloseKey(key); /* Get the parent of Desktop directory */ - p = strrchr(path, '\\'); + p = wcsrchr(path, L'\\'); if (p == NULL) { return NULL; } - *p = '\0'; - return strdup(path); + *p = L'\0'; + return _wcsdup(path); } /* @@ -550,16 +550,16 @@ typedef HRESULT (WINAPI *GetSpecialFolderType)(HWND, int, LPITEMIDLIST *); typedef BOOL (WINAPI *GetPathFromIDListType)(LPCITEMIDLIST, LPSTR); -char * +WCHAR* getHomeFromShell32() { - HMODULE lib = LoadLibrary("SHELL32.DLL"); + HMODULE lib = LoadLibraryW(L"SHELL32.DLL"); GetSpecialFolderType do_get_folder; GetPathFromIDListType do_get_path; HRESULT rc; LPITEMIDLIST item_list = 0; - char *p; - char path[MAX_PATH+1]; + WCHAR *p; + WCHAR path[MAX_PATH+1]; int size = MAX_PATH+1; if (lib == 0) { @@ -568,7 +568,7 @@ } do_get_folder = (GetSpecialFolderType)GetProcAddress(lib, "SHGetSpecialFolderLocation"); - do_get_path = (GetPathFromIDListType)GetProcAddress(lib, "SHGetPathFromIDListA"); + do_get_path = (GetPathFromIDListType)GetProcAddress(lib, "SHGetPathFromIDListW"); if (do_get_folder == 0 || do_get_path == 0) { // the library doesn't hold the right functions !!?? @@ -582,10 +582,10 @@ } path[0] = 0; - (*do_get_path)(item_list, path); + (*do_get_path)(item_list, (LPSTR)path); /* Get the parent of Desktop directory */ - p = strrchr(path, '\\'); + p = wcsrchr(path, L'\\'); if (p) { *p = 0; } @@ -598,8 +598,7 @@ * We also don't unload the SHELL32 DLL. We've paid the hit for loading * it and we may need it again later. */ - - return strdup(path); + return _wcsdup(path); } static boolean @@ -661,10 +660,10 @@ /* tmp dir */ { - char tmpdir[MAX_PATH + 1]; + WCHAR tmpdir[MAX_PATH + 1]; /* we might want to check that this succeed */ - GetTempPath(MAX_PATH + 1, tmpdir); - sprops.tmp_dir = strdup(tmpdir); + GetTempPathW(MAX_PATH + 1, tmpdir); + sprops.tmp_dir = _wcsdup(tmpdir); } /* Printing properties */ @@ -674,11 +673,10 @@ sprops.graphics_env = "sun.awt.Win32GraphicsEnvironment"; { /* This is used only for debugging of font problems. */ - char *path = getenv("JAVA2D_FONTPATH"); - sprops.font_dir = (path != 0) ? strdup(path) : NULL; + WCHAR *path = _wgetenv(L"JAVA2D_FONTPATH"); + sprops.font_dir = (path != NULL) ? _wcsdup(path) : NULL; } - /* OS properties */ { char buf[100]; @@ -830,14 +828,14 @@ * 100 K of footprint. */ { - char *uname = getenv("USERNAME"); - if (uname != NULL && strlen(uname) > 0) { - sprops.user_name = strdup(uname); + WCHAR *uname = _wgetenv(L"USERNAME"); + if (uname != NULL && wcslen(uname) > 0) { + sprops.user_name = _wcsdup(uname); } else { - char buf[100]; + WCHAR buf[100]; int buflen = sizeof(buf); sprops.user_name = - GetUserName(buf, &buflen) ? strdup(buf) : "unknown"; + GetUserNameW(buf, &buflen) ? _wcsdup(buf) : L"unknown"; } } @@ -858,14 +856,13 @@ * On single-user Win95, user.home gets set to c:\windows. */ { - char *homep = getHomeFromRegistry(); + WCHAR *homep = getHomeFromRegistry(); if (homep == NULL) { homep = getHomeFromShell32(); - if (homep == NULL) { - homep = "C:\\"; - } + if (homep == NULL) + homep = L"C:\\"; } - sprops.user_home = homep; + sprops.user_home = _wcsdup(homep); } /* @@ -963,9 +960,9 @@ /* Current directory */ { - char buf[MAX_PATH]; - GetCurrentDirectory(sizeof(buf), buf); - sprops.user_dir = strdup(buf); + WCHAR buf[MAX_PATH]; + GetCurrentDirectoryW(sizeof(buf), buf); + sprops.user_dir = _wcsdup(buf); } sprops.file_separator = "\\"; @@ -974,3 +971,9 @@ return &sprops; } + +jstring +GetStringPlatform(JNIEnv *env, nchar* wcstr) +{ + return (*env)->NewString(env, wcstr, wcslen(wcstr)); +}
--- a/test/java/lang/ProcessBuilder/Basic.java Tue Mar 30 19:10:47 2010 -0700 +++ b/test/java/lang/ProcessBuilder/Basic.java Sat Apr 03 18:29:11 2010 -0700 @@ -26,6 +26,7 @@ * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 + * 4947220 * @summary Basic tests for Process and Environment Variable code * @run main/othervm Basic * @author Martin Buchholz @@ -1456,13 +1457,14 @@ new File(System.getProperty("user.dir")).getCanonicalPath(); String[] sdirs = new String[] {".", "..", "/", "/bin", - "C:", "c:", "C:/", "c:\\", "\\", "\\bin" }; + "C:", "c:", "C:/", "c:\\", "\\", "\\bin", + "c:\\windows ", "c:\\Program Files", "c:\\Program Files\\" }; for (String sdir : sdirs) { File dir = new File(sdir); if (! (dir.isDirectory() && dir.exists())) continue; out.println("Testing directory " + dir); - dir = new File(dir.getCanonicalPath()); + //dir = new File(dir.getCanonicalPath()); ProcessBuilder pb = new ProcessBuilder(); equal(pb.directory(), null); @@ -1470,7 +1472,7 @@ pb.directory(dir); equal(pb.directory(), dir); - equal(pwdInChild(pb), dir.toString()); + equal(pwdInChild(pb), dir.getCanonicalPath()); pb.directory(null); equal(pb.directory(), null); @@ -1481,6 +1483,27 @@ } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- + // Working directory with Unicode in child + //---------------------------------------------------------------- + try { + if (UnicodeOS.is()) { + File dir = new File(System.getProperty("test.dir", "."), + "ProcessBuilderDir\u4e00\u4e02"); + try { + if (!dir.exists()) + dir.mkdir(); + out.println("Testing Unicode directory:" + dir); + ProcessBuilder pb = new ProcessBuilder(); + pb.directory(dir); + equal(pwdInChild(pb), dir.getCanonicalPath()); + } finally { + if (dir.exists()) + dir.delete(); + } + } + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- // OOME in child allocating maximally sized array // Test for hotspot/jvmti bug 6850957 //----------------------------------------------------------------