提交 fbcdf38e 编写于 作者: S sherman

4947220: (process)Runtime.exec() cannot invoke applications with unicode parameters(win)

Summary: to use CreateProcessW on Windowns platform
Reviewed-by: martin
上级 97982092
...@@ -67,10 +67,13 @@ Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x) ...@@ -67,10 +67,13 @@ Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x)
(*env)->DeleteLocalRef(env, r); \ (*env)->DeleteLocalRef(env, r); \
} else ((void) 0) } 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) { \ if (1) { \
jstring jkey = JNU_NewStringPlatform(env, key); \ jstring jkey = (*env)->NewStringUTF(env, key); \
jstring jval = JNU_NewStringPlatform(env, val); \ jstring jval = GetStringPlatform(env, val); \
jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \ jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \
if ((*env)->ExceptionOccurred(env)) return NULL; \ if ((*env)->ExceptionOccurred(env)) return NULL; \
(*env)->DeleteLocalRef(env, jkey); \ (*env)->DeleteLocalRef(env, jkey); \
...@@ -150,7 +153,7 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) ...@@ -150,7 +153,7 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
(sprops->cpu_isalist ? sprops->cpu_isalist : "")); (sprops->cpu_isalist ? sprops->cpu_isalist : ""));
PUTPROP(props, "sun.cpu.endian", sprops->cpu_endian); 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 !!! * !!! I18n properties have not been set up yet !!!
*/ */
...@@ -195,18 +198,18 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) ...@@ -195,18 +198,18 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
*/ */
PUTPROP(props, "java.awt.graphicsenv", sprops->graphics_env); PUTPROP(props, "java.awt.graphicsenv", sprops->graphics_env);
if (sprops->font_dir != NULL) { if (sprops->font_dir != NULL) {
PUTPROP_ForPlatformCString(props, PUTPROP_ForPlatformNString(props,
"sun.java2d.fontpath", sprops->font_dir); "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_ForPlatformNString(props, "user.name", sprops->user_name);
PUTPROP_ForPlatformCString(props, "user.home", sprops->user_home); PUTPROP_ForPlatformNString(props, "user.home", sprops->user_home);
PUTPROP(props, "user.timezone", sprops->timezone); 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 /* This is a sun. property as it is currently only set for Gnome and
* Windows desktops. * Windows desktops.
......
...@@ -28,21 +28,29 @@ ...@@ -28,21 +28,29 @@
#include <jni_util.h> #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 { typedef struct {
char *os_name; char *os_name;
char *os_version; char *os_version;
char *os_arch; char *os_arch;
char *tmp_dir; nchar *tmp_dir;
char *font_dir; nchar *font_dir;
char *user_dir; nchar *user_dir;
char *file_separator; char *file_separator;
char *path_separator; char *path_separator;
char *line_separator; char *line_separator;
char *user_name; nchar *user_name;
char *user_home; nchar *user_home;
char *language; char *language;
char *country; char *country;
...@@ -71,5 +79,6 @@ typedef struct { ...@@ -71,5 +79,6 @@ typedef struct {
} java_props_t; } java_props_t;
java_props_t *GetJavaProperties(JNIEnv *env); java_props_t *GetJavaProperties(JNIEnv *env);
jstring GetStringPlatform(JNIEnv *env, nchar* str);
#endif /* _JAVA_PROPS_H */ #endif /* _JAVA_PROPS_H */
...@@ -416,3 +416,9 @@ GetJavaProperties(JNIEnv *env) ...@@ -416,3 +416,9 @@ GetJavaProperties(JNIEnv *env)
return &sprops; return &sprops;
} }
jstring
GetStringPlatform(JNIEnv *env, nchar* cstr)
{
return JNU_NewStringPlatform(env, cstr);
}
...@@ -145,11 +145,11 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, ...@@ -145,11 +145,11 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
HANDLE errWrite = INVALID_HANDLE_VALUE; HANDLE errWrite = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
STARTUPINFO si; STARTUPINFOW si;
LPTSTR pcmd = NULL; const jchar* pcmd = NULL;
LPCTSTR pdir = NULL; const jchar* pdir = NULL;
LPVOID penvBlock = NULL; const jchar* penvBlock = NULL;
jlong *handles = NULL; jlong *handles = NULL;
jlong ret = 0; jlong ret = 0;
OSVERSIONINFO ver; OSVERSIONINFO ver;
jboolean onNT = JNI_FALSE; jboolean onNT = JNI_FALSE;
...@@ -161,22 +161,17 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, ...@@ -161,22 +161,17 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
onNT = JNI_TRUE; onNT = JNI_TRUE;
assert(cmd != NULL); assert(cmd != NULL);
pcmd = (LPTSTR) JNU_GetStringPlatformChars(env, cmd, NULL); pcmd = (*env)->GetStringChars(env, cmd, NULL);
if (pcmd == NULL) goto Catch; if (pcmd == NULL) goto Catch;
if (dir != 0) { if (dir != 0) {
pdir = (LPCTSTR) JNU_GetStringPlatformChars(env, dir, NULL); pdir = (*env)->GetStringChars(env, dir, NULL);
if (pdir == NULL) goto Catch; if (pdir == NULL) goto Catch;
pdir = (LPCTSTR) JVM_NativePath((char *)pdir);
} }
if (envBlock != NULL) { if (envBlock != NULL) {
penvBlock = onNT penvBlock = ((*env)->GetStringChars(env, envBlock, NULL));
? (LPVOID) ((*env)->GetStringChars(env, envBlock, NULL))
: (LPVOID) JNU_GetStringPlatformChars(env, envBlock, NULL);
if (penvBlock == NULL) goto Catch; if (penvBlock == NULL) goto Catch;
} }
assert(stdHandles != NULL); assert(stdHandles != NULL);
handles = (*env)->GetLongArrayElements(env, stdHandles, NULL); handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
if (handles == NULL) goto Catch; if (handles == NULL) goto Catch;
...@@ -237,30 +232,17 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, ...@@ -237,30 +232,17 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if (onNT) if (onNT)
processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
else else
processFlag = selectProcessFlag(env, cmd); processFlag = selectProcessFlag(env, cmd) | CREATE_UNICODE_ENVIRONMENT;
ret = CreateProcessW(0, /* executable name */
/* Java and Windows are both pure Unicode systems at heart. (LPWSTR)pcmd, /* command line */
* Windows has both a legacy byte-based API and a 16-bit Unicode 0, /* process security attribute */
* "W" API. The Right Thing here is to call CreateProcessW, since 0, /* thread security attribute */
* that will allow all process-related information like command TRUE, /* inherits system handles */
* line arguments to be passed properly to the child. We don't do processFlag, /* selected based on exe type */
* that currently, since we would first have to have "W" versions (LPVOID)penvBlock,/* environment block */
* of JVM_NativePath and perhaps other functions. In the (LPCWSTR)pdir, /* change to the new current directory */
* meantime, we can call CreateProcess with the magic flag &si, /* (in) startup information */
* CREATE_UNICODE_ENVIRONMENT, which passes only the environment &pi); /* (out) process information */
* 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 */
if (!ret) { if (!ret) {
win32Error(env, "CreateProcess"); win32Error(env, "CreateProcess");
goto Catch; goto Catch;
...@@ -276,18 +258,13 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, ...@@ -276,18 +258,13 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
closeSafely(errWrite); closeSafely(errWrite);
if (pcmd != NULL) if (pcmd != NULL)
JNU_ReleaseStringPlatformChars(env, cmd, (char *) pcmd); (*env)->ReleaseStringChars(env, cmd, pcmd);
if (pdir != NULL) if (pdir != NULL)
JNU_ReleaseStringPlatformChars(env, dir, (char *) pdir); (*env)->ReleaseStringChars(env, dir, pdir);
if (penvBlock != NULL) { if (penvBlock != NULL)
if (onNT) (*env)->ReleaseStringChars(env, envBlock, penvBlock);
(*env)->ReleaseStringChars(env, envBlock, (jchar *) penvBlock);
else
JNU_ReleaseStringPlatformChars(env, dir, (char *) penvBlock);
}
if (handles != NULL) if (handles != NULL)
(*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
return ret; return ret;
Catch: Catch:
......
...@@ -513,14 +513,14 @@ getJavaIDFromLangID(LANGID langID) ...@@ -513,14 +513,14 @@ getJavaIDFromLangID(LANGID langID)
/* /*
* Code to figure out the user's home directory using the registry * Code to figure out the user's home directory using the registry
*/ */
static char * static WCHAR*
getHomeFromRegistry() getHomeFromRegistry()
{ {
HKEY key; HKEY key;
int rc; int rc;
DWORD type; DWORD type;
char *p; WCHAR *p;
char path[MAX_PATH+1]; WCHAR path[MAX_PATH+1];
int size = MAX_PATH+1; int size = MAX_PATH+1;
rc = RegOpenKeyEx(HKEY_CURRENT_USER, SHELL_KEY, 0, KEY_READ, &key); rc = RegOpenKeyEx(HKEY_CURRENT_USER, SHELL_KEY, 0, KEY_READ, &key);
...@@ -530,18 +530,18 @@ getHomeFromRegistry() ...@@ -530,18 +530,18 @@ getHomeFromRegistry()
} }
path[0] = 0; 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) { if (rc != ERROR_SUCCESS || type != REG_SZ) {
return NULL; return NULL;
} }
RegCloseKey(key); RegCloseKey(key);
/* Get the parent of Desktop directory */ /* Get the parent of Desktop directory */
p = strrchr(path, '\\'); p = wcsrchr(path, L'\\');
if (p == NULL) { if (p == NULL) {
return NULL; return NULL;
} }
*p = '\0'; *p = L'\0';
return strdup(path); return _wcsdup(path);
} }
/* /*
...@@ -550,16 +550,16 @@ getHomeFromRegistry() ...@@ -550,16 +550,16 @@ getHomeFromRegistry()
typedef HRESULT (WINAPI *GetSpecialFolderType)(HWND, int, LPITEMIDLIST *); typedef HRESULT (WINAPI *GetSpecialFolderType)(HWND, int, LPITEMIDLIST *);
typedef BOOL (WINAPI *GetPathFromIDListType)(LPCITEMIDLIST, LPSTR); typedef BOOL (WINAPI *GetPathFromIDListType)(LPCITEMIDLIST, LPSTR);
char * WCHAR*
getHomeFromShell32() getHomeFromShell32()
{ {
HMODULE lib = LoadLibrary("SHELL32.DLL"); HMODULE lib = LoadLibraryW(L"SHELL32.DLL");
GetSpecialFolderType do_get_folder; GetSpecialFolderType do_get_folder;
GetPathFromIDListType do_get_path; GetPathFromIDListType do_get_path;
HRESULT rc; HRESULT rc;
LPITEMIDLIST item_list = 0; LPITEMIDLIST item_list = 0;
char *p; WCHAR *p;
char path[MAX_PATH+1]; WCHAR path[MAX_PATH+1];
int size = MAX_PATH+1; int size = MAX_PATH+1;
if (lib == 0) { if (lib == 0) {
...@@ -568,7 +568,7 @@ getHomeFromShell32() ...@@ -568,7 +568,7 @@ getHomeFromShell32()
} }
do_get_folder = (GetSpecialFolderType)GetProcAddress(lib, "SHGetSpecialFolderLocation"); 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) { if (do_get_folder == 0 || do_get_path == 0) {
// the library doesn't hold the right functions !!?? // the library doesn't hold the right functions !!??
...@@ -582,10 +582,10 @@ getHomeFromShell32() ...@@ -582,10 +582,10 @@ getHomeFromShell32()
} }
path[0] = 0; path[0] = 0;
(*do_get_path)(item_list, path); (*do_get_path)(item_list, (LPSTR)path);
/* Get the parent of Desktop directory */ /* Get the parent of Desktop directory */
p = strrchr(path, '\\'); p = wcsrchr(path, L'\\');
if (p) { if (p) {
*p = 0; *p = 0;
} }
...@@ -598,8 +598,7 @@ getHomeFromShell32() ...@@ -598,8 +598,7 @@ getHomeFromShell32()
* We also don't unload the SHELL32 DLL. We've paid the hit for loading * We also don't unload the SHELL32 DLL. We've paid the hit for loading
* it and we may need it again later. * it and we may need it again later.
*/ */
return _wcsdup(path);
return strdup(path);
} }
static boolean static boolean
...@@ -661,10 +660,10 @@ GetJavaProperties(JNIEnv* env) ...@@ -661,10 +660,10 @@ GetJavaProperties(JNIEnv* env)
/* tmp dir */ /* tmp dir */
{ {
char tmpdir[MAX_PATH + 1]; WCHAR tmpdir[MAX_PATH + 1];
/* we might want to check that this succeed */ /* we might want to check that this succeed */
GetTempPath(MAX_PATH + 1, tmpdir); GetTempPathW(MAX_PATH + 1, tmpdir);
sprops.tmp_dir = strdup(tmpdir); sprops.tmp_dir = _wcsdup(tmpdir);
} }
/* Printing properties */ /* Printing properties */
...@@ -674,11 +673,10 @@ GetJavaProperties(JNIEnv* env) ...@@ -674,11 +673,10 @@ GetJavaProperties(JNIEnv* env)
sprops.graphics_env = "sun.awt.Win32GraphicsEnvironment"; sprops.graphics_env = "sun.awt.Win32GraphicsEnvironment";
{ /* This is used only for debugging of font problems. */ { /* This is used only for debugging of font problems. */
char *path = getenv("JAVA2D_FONTPATH"); WCHAR *path = _wgetenv(L"JAVA2D_FONTPATH");
sprops.font_dir = (path != 0) ? strdup(path) : NULL; sprops.font_dir = (path != NULL) ? _wcsdup(path) : NULL;
} }
/* OS properties */ /* OS properties */
{ {
char buf[100]; char buf[100];
...@@ -830,14 +828,14 @@ GetJavaProperties(JNIEnv* env) ...@@ -830,14 +828,14 @@ GetJavaProperties(JNIEnv* env)
* 100 K of footprint. * 100 K of footprint.
*/ */
{ {
char *uname = getenv("USERNAME"); WCHAR *uname = _wgetenv(L"USERNAME");
if (uname != NULL && strlen(uname) > 0) { if (uname != NULL && wcslen(uname) > 0) {
sprops.user_name = strdup(uname); sprops.user_name = _wcsdup(uname);
} else { } else {
char buf[100]; WCHAR buf[100];
int buflen = sizeof(buf); int buflen = sizeof(buf);
sprops.user_name = sprops.user_name =
GetUserName(buf, &buflen) ? strdup(buf) : "unknown"; GetUserNameW(buf, &buflen) ? _wcsdup(buf) : L"unknown";
} }
} }
...@@ -858,14 +856,13 @@ GetJavaProperties(JNIEnv* env) ...@@ -858,14 +856,13 @@ GetJavaProperties(JNIEnv* env)
* On single-user Win95, user.home gets set to c:\windows. * On single-user Win95, user.home gets set to c:\windows.
*/ */
{ {
char *homep = getHomeFromRegistry(); WCHAR *homep = getHomeFromRegistry();
if (homep == NULL) { if (homep == NULL) {
homep = getHomeFromShell32(); homep = getHomeFromShell32();
if (homep == NULL) { if (homep == NULL)
homep = "C:\\"; homep = L"C:\\";
}
} }
sprops.user_home = homep; sprops.user_home = _wcsdup(homep);
} }
/* /*
...@@ -963,9 +960,9 @@ GetJavaProperties(JNIEnv* env) ...@@ -963,9 +960,9 @@ GetJavaProperties(JNIEnv* env)
/* Current directory */ /* Current directory */
{ {
char buf[MAX_PATH]; WCHAR buf[MAX_PATH];
GetCurrentDirectory(sizeof(buf), buf); GetCurrentDirectoryW(sizeof(buf), buf);
sprops.user_dir = strdup(buf); sprops.user_dir = _wcsdup(buf);
} }
sprops.file_separator = "\\"; sprops.file_separator = "\\";
...@@ -974,3 +971,9 @@ GetJavaProperties(JNIEnv* env) ...@@ -974,3 +971,9 @@ GetJavaProperties(JNIEnv* env)
return &sprops; return &sprops;
} }
jstring
GetStringPlatform(JNIEnv *env, nchar* wcstr)
{
return (*env)->NewString(env, wcstr, wcslen(wcstr));
}
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
* 4947220
* @summary Basic tests for Process and Environment Variable code * @summary Basic tests for Process and Environment Variable code
* @run main/othervm Basic * @run main/othervm Basic
* @author Martin Buchholz * @author Martin Buchholz
...@@ -1456,13 +1457,14 @@ public class Basic { ...@@ -1456,13 +1457,14 @@ public class Basic {
new File(System.getProperty("user.dir")).getCanonicalPath(); new File(System.getProperty("user.dir")).getCanonicalPath();
String[] sdirs = new String[] String[] sdirs = new String[]
{".", "..", "/", "/bin", {".", "..", "/", "/bin",
"C:", "c:", "C:/", "c:\\", "\\", "\\bin" }; "C:", "c:", "C:/", "c:\\", "\\", "\\bin",
"c:\\windows ", "c:\\Program Files", "c:\\Program Files\\" };
for (String sdir : sdirs) { for (String sdir : sdirs) {
File dir = new File(sdir); File dir = new File(sdir);
if (! (dir.isDirectory() && dir.exists())) if (! (dir.isDirectory() && dir.exists()))
continue; continue;
out.println("Testing directory " + dir); out.println("Testing directory " + dir);
dir = new File(dir.getCanonicalPath()); //dir = new File(dir.getCanonicalPath());
ProcessBuilder pb = new ProcessBuilder(); ProcessBuilder pb = new ProcessBuilder();
equal(pb.directory(), null); equal(pb.directory(), null);
...@@ -1470,7 +1472,7 @@ public class Basic { ...@@ -1470,7 +1472,7 @@ public class Basic {
pb.directory(dir); pb.directory(dir);
equal(pb.directory(), dir); equal(pb.directory(), dir);
equal(pwdInChild(pb), dir.toString()); equal(pwdInChild(pb), dir.getCanonicalPath());
pb.directory(null); pb.directory(null);
equal(pb.directory(), null); equal(pb.directory(), null);
...@@ -1480,6 +1482,27 @@ public class Basic { ...@@ -1480,6 +1482,27 @@ public class Basic {
} }
} catch (Throwable t) { unexpected(t); } } 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 // OOME in child allocating maximally sized array
// Test for hotspot/jvmti bug 6850957 // Test for hotspot/jvmti bug 6850957
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册