4947220: (process)Runtime.exec() cannot invoke applications with unicode parameters(win)
Summary: to use CreateProcessW on Windowns platform
Reviewed-by: martin
--- a/jdk/src/share/native/java/lang/System.c Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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/jdk/src/share/native/java/lang/java_props.h Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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/jdk/src/solaris/native/java/lang/java_props_md.c Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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/jdk/src/windows/native/java/lang/ProcessImpl_md.c Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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/jdk/src/windows/native/java/lang/java_props_md.c Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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/jdk/test/java/lang/ProcessBuilder/Basic.java Tue Mar 30 19:10:47 2010 -0700
+++ b/jdk/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
//----------------------------------------------------------------