提交 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)
(*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 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
(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 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
*/
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.
......
......@@ -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 @@ typedef struct {
} java_props_t;
java_props_t *GetJavaProperties(JNIEnv *env);
jstring GetStringPlatform(JNIEnv *env, nchar* str);
#endif /* _JAVA_PROPS_H */
......@@ -416,3 +416,9 @@ GetJavaProperties(JNIEnv *env)
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,
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 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
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 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
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 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
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:
......
......@@ -513,14 +513,14 @@ getJavaIDFromLangID(LANGID langID)
/*
* 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 @@ getHomeFromRegistry()
}
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 @@ getHomeFromRegistry()
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 @@ getHomeFromShell32()
}
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 @@ getHomeFromShell32()
}
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 @@ getHomeFromShell32()
* 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 @@ GetJavaProperties(JNIEnv* env)
/* 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 @@ GetJavaProperties(JNIEnv* env)
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 @@ GetJavaProperties(JNIEnv* env)
* 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 @@ GetJavaProperties(JNIEnv* env)
* 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 @@ GetJavaProperties(JNIEnv* env)
/* 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 @@ GetJavaProperties(JNIEnv* env)
return &sprops;
}
jstring
GetStringPlatform(JNIEnv *env, nchar* wcstr)
{
return (*env)->NewString(env, wcstr, wcslen(wcstr));
}
......@@ -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 @@ public class Basic {
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 @@ public class Basic {
pb.directory(dir);
equal(pb.directory(), dir);
equal(pwdInChild(pb), dir.toString());
equal(pwdInChild(pb), dir.getCanonicalPath());
pb.directory(null);
equal(pb.directory(), null);
......@@ -1480,6 +1482,27 @@ public class Basic {
}
} 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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册