X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fprocess.c;h=6aa9e66d9f557d8a51392cdb573794d843a18efd;hb=cd0f05d6fd528c0f63327a908e2be2f4a9620933;hp=5fa57bcf0ed71501f3c3101b9a4859d60d867eb6;hpb=5359b46a8d2a74f9eb4f3c9318ca7a0337e38e01;p=mono.git diff --git a/mono/metadata/process.c b/mono/metadata/process.c index 5fa57bcf0ed..6aa9e66d9f5 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -5,6 +5,7 @@ * Dick Porter (dick@ximian.com) * * (C) 2002 Ximian, Inc. + * Copyright (c) 2002-2006 Novell, Inc. */ #include @@ -97,7 +98,23 @@ static guint32 unicode_bytes (const gunichar2 *str) } while(1); } -static void process_set_field_object (MonoObject *obj, const guchar *fieldname, +/* + * compare a null-terminated utf16 string and a normal string. + * Can be used only for ascii or latin1 chars. + */ +static gboolean +unicode_string_equals (const gunichar2 *str1, const gchar *str2) +{ + while (*str1 && *str2) { + if (*str1 != *str2) + return FALSE; + ++str1; + ++str2; + } + return *str1 == *str2; +} + +static void process_set_field_object (MonoObject *obj, const gchar *fieldname, MonoObject *data) { MonoClassField *field; @@ -112,7 +129,7 @@ static void process_set_field_object (MonoObject *obj, const guchar *fieldname, *(MonoObject **)(((char *)obj) + field->offset)=data; } -static void process_set_field_string (MonoObject *obj, const guchar *fieldname, +static void process_set_field_string (MonoObject *obj, const gchar *fieldname, const gunichar2 *val, guint32 len) { MonoClassField *field; @@ -131,8 +148,8 @@ static void process_set_field_string (MonoObject *obj, const guchar *fieldname, } static void process_set_field_string_utf8 (MonoObject *obj, - const guchar *fieldname, - const guchar *val) + const gchar *fieldname, + const gchar *val) { MonoClassField *field; MonoString *string; @@ -149,7 +166,7 @@ static void process_set_field_string_utf8 (MonoObject *obj, *(MonoString **)(((char *)obj) + field->offset)=string; } -static void process_set_field_int (MonoObject *obj, const guchar *fieldname, +static void process_set_field_int (MonoObject *obj, const gchar *fieldname, guint32 val) { MonoClassField *field; @@ -164,7 +181,7 @@ static void process_set_field_int (MonoObject *obj, const guchar *fieldname, *(guint32 *)(((char *)obj) + field->offset)=val; } -static void process_set_field_bool (MonoObject *obj, const guchar *fieldname, +static void process_set_field_bool (MonoObject *obj, const gchar *fieldname, gboolean val) { MonoClassField *field; @@ -206,7 +223,8 @@ static gpointer process_get_versioninfo_block (gpointer data, data=((gunichar2 *)data)+(unicode_chars (block->key)+1); /* align on a 32-bit boundary */ - data=(gpointer)(((unsigned)data+3) & (~3)); + data=(gpointer)((char *)data + 3); + data=(gpointer)((char *)data - (GPOINTER_TO_INT(data) & 3)); return(data); } @@ -240,66 +258,8 @@ static gpointer process_read_string_block (MonoObject *filever, gboolean store) { version_data block; - guint16 string_len=0; - guchar comments_key[]= {'C', '\0', 'o', '\0', 'm', '\0', - 'm', '\0', 'e', '\0', 'n', '\0', - 't', '\0', 's', '\0', '\0', '\0'}; - guchar compname_key[]= {'C', '\0', 'o', '\0', 'm', '\0', - 'p', '\0', 'a', '\0', 'n', '\0', - 'y', '\0', 'N', '\0', 'a', '\0', - 'm', '\0', 'e', '\0', '\0', '\0'}; - guchar filedesc_key[]= {'F', '\0', 'i', '\0', 'l', '\0', - 'e', '\0', 'D', '\0', 'e', '\0', - 's', '\0', 'c', '\0', 'r', '\0', - 'i', '\0', 'p', '\0', 't', '\0', - 'i', '\0', 'o', '\0', 'n', '\0', - '\0', '\0'}; - guchar filever_key[]= {'F', '\0', 'i', '\0', 'l', '\0', - 'e', '\0', 'V', '\0', 'e', '\0', - 'r', '\0', 's', '\0', 'i', '\0', - 'o', '\0', 'n', '\0', '\0', '\0'}; - guchar internal_key[]= {'I', '\0', 'n', '\0', 't', '\0', - 'e', '\0', 'r', '\0', 'n', '\0', - 'a', '\0', 'l', '\0', 'N', '\0', - 'a', '\0', 'm', '\0', 'e', '\0', - '\0', '\0'}; - guchar legalcpy_key[]= {'L', '\0', 'e', '\0', 'g', '\0', - 'a', '\0', 'l', '\0', 'C', '\0', - 'o', '\0', 'p', '\0', 'y', '\0', - 'r', '\0', 'i', '\0', 'g', '\0', - 'h', '\0', 't', '\0', '\0', '\0'}; - guchar legaltrade_key[]= {'L', '\0', 'e', '\0', 'g', '\0', - 'a', '\0', 'l', '\0', 'T', '\0', - 'r', '\0', 'a', '\0', 'd', '\0', - 'e', '\0', 'm', '\0', 'a', '\0', - 'r', '\0', 'k', '\0', 's', '\0', - '\0', '\0'}; - guchar origfile_key[]= {'O', '\0', 'r', '\0', 'i', '\0', - 'g', '\0', 'i', '\0', 'n', '\0', - 'a', '\0', 'l', '\0', 'F', '\0', - 'i', '\0', 'l', '\0', 'e', '\0', - 'n', '\0', 'a', '\0', 'm', '\0', - 'e', '\0', '\0', '\0'}; - guchar privbuild_key[]= {'P', '\0', 'r', '\0', 'i', '\0', - 'v', '\0', 'a', '\0', 't', '\0', - 'e', '\0', 'B', '\0', 'u', '\0', - 'i', '\0', 'l', '\0', 'd', '\0', - '\0', '\0'}; - guchar prodname_key[]= {'P', '\0', 'r', '\0', 'o', '\0', - 'd', '\0', 'u', '\0', 'c', '\0', - 't', '\0', 'N', '\0', 'a', '\0', - 'm', '\0', 'e', '\0', '\0', '\0'}; - guchar prodver_key[]= {'P', '\0', 'r', '\0', 'o', '\0', - 'd', '\0', 'u', '\0', 'c', '\0', - 't', '\0', 'V', '\0', 'e', '\0', - 'r', '\0', 's', '\0', 'i', '\0', - 'o', '\0', 'n', '\0', '\0', '\0'}; - guchar specbuild_key[]= {'S', '\0', 'p', '\0', 'e', '\0', - 'c', '\0', 'i', '\0', 'a', '\0', - 'l', '\0', 'B', '\0', 'u', '\0', - 'i', '\0', 'l', '\0', 'd', '\0', - '\0', '\0'}; - + guint16 string_len=28; /* Length of the StringTable block */ + /* data_ptr is pointing at an array of one or more String * blocks with total length (not including alignment padding) * of data_len. @@ -308,7 +268,9 @@ static gpointer process_read_string_block (MonoObject *filever, gunichar2 *value; /* align on a 32-bit boundary */ - data_ptr=(gpointer)(((unsigned)data_ptr+3) & (~3)); + data_ptr=(gpointer)((char *)data_ptr + 3); + data_ptr=(gpointer)((char *)data_ptr - + (GPOINTER_TO_INT(data_ptr) & 3)); data_ptr=process_get_versioninfo_block (data_ptr, &block); if(block.data_len==0) { @@ -328,42 +290,29 @@ static gpointer process_read_string_block (MonoObject *filever, data_ptr=((gunichar2 *)data_ptr)+block.value_len; if(store==TRUE) { - if(!memcmp (block.key, &comments_key, - unicode_bytes (block.key))) { - + if (unicode_string_equals (block.key, "Comments")) { process_set_field_string (filever, "comments", value, unicode_chars (value)); - } else if (!memcmp (block.key, &compname_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "CompanyName")) { process_set_field_string (filever, "companyname", value, unicode_chars (value)); - } else if (!memcmp (block.key, &filedesc_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "FileDescription")) { process_set_field_string (filever, "filedescription", value, unicode_chars (value)); - } else if (!memcmp (block.key, &filever_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "FileVersion")) { process_set_field_string (filever, "fileversion", value, unicode_chars (value)); - } else if (!memcmp (block.key, &internal_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "InternalName")) { process_set_field_string (filever, "internalname", value, unicode_chars (value)); - } else if (!memcmp (block.key, &legalcpy_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "LegalCopyright")) { process_set_field_string (filever, "legalcopyright", value, unicode_chars (value)); - } else if (!memcmp (block.key, &legaltrade_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "LegalTrademarks")) { process_set_field_string (filever, "legaltrademarks", value, unicode_chars (value)); - } else if (!memcmp (block.key, &origfile_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "OriginalFilename")) { process_set_field_string (filever, "originalfilename", value, unicode_chars (value)); - } else if (!memcmp (block.key, &privbuild_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "PrivateBuild")) { process_set_field_string (filever, "privatebuild", value, unicode_chars (value)); - } else if (!memcmp (block.key, &prodname_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "ProductName")) { process_set_field_string (filever, "productname", value, unicode_chars (value)); - } else if (!memcmp (block.key, &prodver_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "ProductVersion")) { process_set_field_string (filever, "productversion", value, unicode_chars (value)); - } else if (!memcmp (block.key, &specbuild_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "SpecialBuild")) { process_set_field_string (filever, "specialbuild", value, unicode_chars (value)); } else { /* Not an error, just not interesting @@ -396,7 +345,9 @@ static gpointer process_read_stringtable_block (MonoObject *filever, while(string_len 0) { /* align on a 32-bit boundary */ - data_ptr=(gpointer)(((unsigned)data_ptr+3) & (~3)); + data_ptr=(gpointer)((char *)data_ptr + 3); + data_ptr=(gpointer)((char *)data_ptr - + (GPOINTER_TO_INT(data_ptr) & 3)); data_ptr=process_get_versioninfo_block (data_ptr, &block); if(block.data_len==0) { @@ -582,11 +525,10 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image) data_len=data_len-block.data_len; - if(!memcmp (block.key, &var_key, unicode_bytes (block.key))) { + if (unicode_string_equals (block.key, "VarFileInfo")) { data_ptr=process_read_var_block (filever, data_ptr, block.data_len); - } else if (!memcmp (block.key, &str_key, - unicode_bytes (block.key))) { + } else if (unicode_string_equals (block.key, "StringFileInfo")) { data_ptr=process_read_stringtable_block (filever, data_ptr, block.data_len); } else { /* Bogus data */ @@ -689,11 +631,10 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject modules_list->len); for(i=0; ilen; i++) { - mono_array_set (arr, MonoObject *, i, - g_ptr_array_index (modules_list, i)); + mono_array_setref (arr, i, g_ptr_array_index (modules_list, i)); } - g_ptr_array_free (modules_list, FALSE); + g_ptr_array_free (modules_list, TRUE); return(arr); } @@ -701,14 +642,14 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this, MonoString *filename) { MonoImage *image; - guchar *filename_utf8; + gchar *filename_utf8; MONO_ARCH_SAVE_REGS; STASH_SYS_ASS (this); - filename_utf8=mono_string_to_utf8 (filename); - image=mono_image_open (filename_utf8, NULL); + filename_utf8 = mono_string_to_utf8 (filename); + image = mono_pe_file_open (filename_utf8, NULL); g_free (filename_utf8); if(image==NULL) { @@ -726,21 +667,42 @@ void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoO mono_image_close (image); } +/* Only used when UseShellExecute is false */ +static gchar * +quote_path (const gchar *path) +{ + gchar *res = g_shell_quote (path); +#ifdef PLATFORM_WIN32 + { + gchar *q = res; + while (*q) { + if (*q == '\'') + *q = '\"'; + q++; + } + } +#endif + return res; +} + +/* Only used when UseShellExecute is false */ static gboolean -complete_path (const gunichar2 *appname, gunichar2 **completed) +complete_path (const gunichar2 *appname, gchar **completed) { gchar *utf8app; gchar *found; utf8app = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL); if (g_path_is_absolute (utf8app)) { + *completed = quote_path (utf8app); g_free (utf8app); - return FALSE; + return TRUE; } if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) { + *completed = quote_path (utf8app); g_free (utf8app); - return FALSE; + return TRUE; } found = g_find_program_in_path (utf8app); @@ -750,13 +712,60 @@ complete_path (const gunichar2 *appname, gunichar2 **completed) return FALSE; } - *completed = g_utf8_to_utf16 (found, -1, NULL, NULL, NULL); + *completed = quote_path (found); g_free (found); g_free (utf8app); return TRUE; } -MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *appname, MonoString *cmd, MonoString *dirname, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info) +MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info) +{ + SHELLEXECUTEINFO shellex = {0}; + gboolean ret; + + shellex.cbSize = sizeof(SHELLEXECUTEINFO); + shellex.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_UNICODE; + shellex.nShow = SW_SHOWNORMAL; + + if (proc_start_info->filename != NULL) { + shellex.lpFile = mono_string_chars (proc_start_info->filename); + } + + if (proc_start_info->arguments != NULL) { + shellex.lpParameters = mono_string_chars (proc_start_info->arguments); + } + + if (proc_start_info->verb != NULL && + mono_string_length (proc_start_info->verb) != 0) { + shellex.lpVerb = mono_string_chars (proc_start_info->verb); + } + + if (proc_start_info->working_directory != NULL && + mono_string_length (proc_start_info->working_directory) != 0) { + shellex.lpDirectory = mono_string_chars (proc_start_info->working_directory); + } + + ret = ShellExecuteEx (&shellex); + if (ret == FALSE) { + process_info->pid = -GetLastError (); + } else { + process_info->process_handle = shellex.hProcess; + process_info->thread_handle = NULL; + /* It appears that there's no way to get the pid from a + * process handle before windows xp. Really. + */ +#ifdef HAVE_GETPROCESSID + process_info->pid = GetProcessId (shellex.hProcess); +#else + process_info->pid = 0; +#endif + process_info->tid = 0; + } + + return (ret); +} + +MonoBoolean ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info) { gboolean ret; gunichar2 *dir; @@ -765,6 +774,11 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *app gunichar2 *shell_path = NULL; gchar *env_vars = NULL; gboolean free_shell_path = TRUE; +#ifdef PLATFORM_WIN32 + gchar *newcmd, *tmp; +#endif + gchar *spath = NULL; + MonoString *cmd = proc_start_info->arguments; MONO_ARCH_SAVE_REGS; @@ -774,48 +788,26 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *app startinfo.hStdOutput=stdout_handle; startinfo.hStdError=stderr_handle; - if (process_info->use_shell) { - const gchar *spath; - const gchar *shell_args; + shell_path = mono_string_chars (proc_start_info->filename); + complete_path (shell_path, &spath); + if (spath == NULL) { + process_info->pid = -ERROR_FILE_NOT_FOUND; + return FALSE; + } #ifdef PLATFORM_WIN32 - spath = g_getenv ("COMSPEC"); - shell_args = "/c %s"; + /* Seems like our CreateProcess does not work as the windows one. + * This hack is needed to deal with paths containing spaces */ + shell_path = NULL; + free_shell_path = FALSE; + tmp = mono_string_to_utf8 (cmd); + newcmd = g_strdup_printf ("%s %s", spath, tmp); + cmd = mono_string_new_wrapper (newcmd); + g_free (newcmd); + g_free (tmp); #else - spath = g_getenv ("SHELL"); - shell_args = "-c %s"; + shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL); #endif - if (spath != NULL) { - gint dummy; - gchar *newcmd, *tmp; - gchar *quoted; - - shell_path = mono_unicode_from_external (spath, &dummy); - tmp = mono_string_to_utf8 (cmd); - quoted = g_shell_quote (tmp); -#ifdef PLATFORM_WIN32 - { - gchar *q = quoted; - while (*q) { - if (*q == '\'') - *q = '\"'; - q++; - } - } -#endif - newcmd = g_strdup_printf (shell_args, quoted); - g_free (quoted); - g_free (tmp); - cmd = mono_string_new (mono_domain_get (), newcmd); - g_free (newcmd); - } - } else { - shell_path = mono_string_chars (appname); - free_shell_path = complete_path (shell_path, &shell_path); - if (shell_path == NULL) { - process_info->pid = -ERROR_FILE_NOT_FOUND; - return FALSE; - } - } + g_free (spath); if (process_info->env_keys != NULL) { gint i, len; @@ -861,10 +853,10 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *app /* The default dir name is "". Turn that into NULL to mean * "current directory" */ - if(mono_string_length (dirname)==0) { + if(mono_string_length (proc_start_info->working_directory)==0) { dir=NULL; } else { - dir=mono_string_chars (dirname); + dir=mono_string_chars (proc_start_info->working_directory); } ret=CreateProcess (shell_path, mono_string_chars (cmd), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, env_vars, dir, &startinfo, &procinfo); @@ -877,7 +869,8 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *app process_info->process_handle=procinfo.hProcess; /*process_info->thread_handle=procinfo.hThread;*/ process_info->thread_handle=NULL; - CloseHandle(procinfo.hThread); + if (procinfo.hThread != NULL) + CloseHandle(procinfo.hThread); process_info->pid=procinfo.dwProcessId; process_info->tid=procinfo.dwThreadId; } else { @@ -977,7 +970,7 @@ MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE pr return(NULL); } - len=GetModuleBaseName (process, mod, name, sizeof(name)); + len=GetModuleBaseName (process, mod, name, MAX_PATH); if(len==0) { return(NULL); }