X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fprocess.c;h=6aa9e66d9f557d8a51392cdb573794d843a18efd;hb=cd0f05d6fd528c0f63327a908e2be2f4a9620933;hp=a91fcc9479eed12861dbc76282ab73b760a0e30b;hpb=75794710173cb11ef4ea195ea2d4e27fa7b66fec;p=mono.git diff --git a/mono/metadata/process.c b/mono/metadata/process.c index a91fcc9479e..6aa9e66d9f5 100644 --- a/mono/metadata/process.c +++ b/mono/metadata/process.c @@ -5,11 +5,13 @@ * Dick Porter (dick@ximian.com) * * (C) 2002 Ximian, Inc. + * Copyright (c) 2002-2006 Novell, Inc. */ #include #include +#include #include #include @@ -18,7 +20,10 @@ #include #include #include +#include #include +/* FIXME: fix this code to not depend so much on the inetrnals */ +#include #undef DEBUG @@ -93,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; @@ -108,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; @@ -127,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; @@ -145,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; @@ -160,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; @@ -188,18 +209,22 @@ typedef struct { static gpointer process_get_versioninfo_block (gpointer data, version_data *block) { - block->data_len=*(((guint16 *)data)++); - block->value_len=*(((guint16 *)data)++); + block->data_len=*((guint16 *)data); + data = (char *)data + sizeof(guint16); + block->value_len=*((guint16 *)data); + data = (char *)data + sizeof(guint16); /* No idea what the type is supposed to indicate */ - block->type=*(((guint16 *)data)++); + block->type=*((guint16 *)data); + data = (char *)data + sizeof(guint16); block->key=((gunichar2 *)data); /* skip over the key (including the terminator) */ 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); } @@ -222,73 +247,19 @@ static gpointer process_read_var_block (MonoObject *filever, gpointer data_ptr, return(data_ptr); } -/* Returns a pointer to the byte following the String block */ +/* Returns a pointer to the byte following the String block, or NULL + * if the data read hits padding. We can't recover from this because + * the data length does not include padding bytes, so it's not + * possible to just return the start position + length. + */ static gpointer process_read_string_block (MonoObject *filever, gpointer data_ptr, guint16 data_len, 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. @@ -297,50 +268,51 @@ 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) { + /* We must have hit padding, so give up + * processing now + */ +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": Hit 0-length block, giving up"); +#endif + return(NULL); + } + string_len=string_len+block.data_len; value=(gunichar2 *)data_ptr; /* Skip over the value */ 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 @@ -353,24 +325,19 @@ static gpointer process_read_string_block (MonoObject *filever, return(data_ptr); } -/* returns a pointer to the byte following the Stringtable block */ +/* returns a pointer to the byte following the Stringtable block, or + * NULL if the data read hits padding. We can't recover from this + * because the data length does not include padding bytes, so it's not + * possible to just return the start position + length + */ static gpointer process_read_stringtable_block (MonoObject *filever, gpointer data_ptr, guint16 data_len) { version_data block; + gchar *language; guint16 string_len=36; /* length of the StringFileInfo block */ - /* Specifies language-neutral unicode string block */ - guchar uni_key[]= {'0', '\0', '0', '\0', '0', '\0', '0', '\0', - '0', '\0', '4', '\0', 'b', '\0', '0', '\0', - '\0', '\0' - }; - guchar uni_key_uc[]= {'0', '\0', '0', '\0', '0', '\0', '0', '\0', - '0', '\0', '4', '\0', 'B', '\0', '0', '\0', - '\0', '\0' - }; - /* data_ptr is pointing at an array of StringTable blocks, * with total length (not including alignment padding) of * data_len. @@ -378,13 +345,30 @@ static gpointer process_read_stringtable_block (MonoObject *filever, while(string_lenimage_info, + data=mono_image_rva_map (image, version_info->rde_data_offset); if(data==NULL) { return; @@ -500,7 +479,7 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image) return; } - if(memcmp (block.key, &vs_key, unicode_bytes (block.key))) { + if (!unicode_string_equals (block.key, "VS_VERSION_INFO")) { #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": VS_VERSION_INFO mismatch"); @@ -508,7 +487,8 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image) return; } - ffi=(((VS_FIXEDFILEINFO *)data_ptr)++); + ffi=((VS_FIXEDFILEINFO *)data_ptr); + data_ptr = (char *)data_ptr + sizeof(VS_FIXEDFILEINFO); if((ffi->dwSignature!=VS_FFI_SIGNATURE) || (ffi->dwStrucVersion!=VS_FFI_STRUCVERSION)) { #ifdef DEBUG @@ -527,16 +507,28 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image) */ while(data_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) { + /* We must have hit padding, so give up + * processing now + */ +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION + ": Hit 0-length block, giving up"); +#endif + return; + } + 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 */ @@ -546,6 +538,14 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image) return; #endif } + + if(data_ptr==NULL) { + /* Child block hit padding */ +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Child block hit 0-length block, giving up"); +#endif + return; + } } } @@ -555,6 +555,7 @@ static void process_add_module (GPtrArray *modules, MonoAssembly *ass) MonoObject *item, *filever; MonoDomain *domain=mono_domain_get (); gchar *modulename; + const char* filename; /* Build a System.Diagnostics.ProcessModule with the data. * Leave BaseAddress and EntryPointAddress set to NULL, @@ -576,13 +577,14 @@ static void process_add_module (GPtrArray *modules, MonoAssembly *ass) g_message (G_GNUC_PRETTY_FUNCTION ": recording assembly: FileName [%s] FileVersionInfo [%d.%d.%d.%d], ModuleName [%s]", ass->image->name, ass->aname.major, ass->aname.minor, ass->aname.build, ass->aname.revision, ass->image->name); #endif - process_get_fileversion (filever, ass->image); + process_get_fileversion (filever, mono_assembly_get_image (ass)); - process_set_field_string_utf8 (filever, "filename", ass->image->name); - process_set_field_string_utf8 (item, "filename", ass->image->name); + filename = mono_image_get_filename (mono_assembly_get_image (ass)); + process_set_field_string_utf8 (filever, "filename", filename); + process_set_field_string_utf8 (item, "filename", filename); process_set_field_object (item, "version_info", filever); - modulename=g_path_get_basename (ass->image->name); + modulename=g_path_get_basename (filename); process_set_field_string_utf8 (item, "modulename", modulename); g_free (modulename); @@ -625,15 +627,14 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject mono_assembly_foreach (process_scan_modules, modules_list); /* Build a MonoArray out of modules_list */ - arr=mono_array_new (mono_domain_get (), mono_defaults.object_class, + arr=mono_array_new (mono_domain_get (), mono_get_object_class (), 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); } @@ -641,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) { @@ -661,17 +662,123 @@ void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoO } process_get_fileversion (this, image); - process_set_field_string_utf8 (this, "filename", image->name); + process_set_field_string_utf8 (this, "filename", mono_image_get_filename (image)); mono_image_close (image); } -MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd, MonoString *dirname, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info) +/* 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, 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 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 TRUE; + } + + found = g_find_program_in_path (utf8app); + if (found == NULL) { + *completed = NULL; + g_free (utf8app); + return FALSE; + } + + *completed = quote_path (found); + g_free (found); + g_free (utf8app); + return TRUE; +} + +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; STARTUPINFO startinfo={0}; PROCESS_INFORMATION procinfo; + 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; @@ -681,22 +788,93 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd startinfo.hStdOutput=stdout_handle; startinfo.hStdError=stderr_handle; + 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 + /* 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 + shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL); +#endif + g_free (spath); + + if (process_info->env_keys != NULL) { + gint i, len; + MonoString *ms; + MonoString *key, *value; + gunichar2 *str, *ptr; + gunichar2 *equals16; + + for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) { + ms = mono_array_get (process_info->env_values, MonoString *, i); + if (ms == NULL) + continue; + + len += mono_string_length (ms) * sizeof (gunichar2); + ms = mono_array_get (process_info->env_keys, MonoString *, i); + len += mono_string_length (ms) * sizeof (gunichar2); + len += 2 * sizeof (gunichar2); + } + + equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL); + ptr = str = g_new0 (gunichar2, len + 1); + for (i = 0; i < mono_array_length (process_info->env_keys); i++) { + value = mono_array_get (process_info->env_values, MonoString *, i); + if (value == NULL) + continue; + + key = mono_array_get (process_info->env_keys, MonoString *, i); + memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2)); + ptr += mono_string_length (key); + + memcpy (ptr, equals16, sizeof (gunichar2)); + ptr++; + + memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2)); + ptr += mono_string_length (value); + ptr++; + } + + g_free (equals16); + env_vars = (gchar *) str; + } + /* 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 (NULL, mono_string_chars (cmd), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, dir, &startinfo, &procinfo); + ret=CreateProcess (shell_path, mono_string_chars (cmd), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, env_vars, dir, &startinfo, &procinfo); - if(ret==TRUE) { + g_free (env_vars); + if (free_shell_path) + g_free (shell_path); + + if(ret) { process_info->process_handle=procinfo.hProcess; - process_info->thread_handle=procinfo.hThread; + /*process_info->thread_handle=procinfo.hThread;*/ + process_info->thread_handle=NULL; + if (procinfo.hThread != NULL) + CloseHandle(procinfo.hThread); process_info->pid=procinfo.dwProcessId; process_info->tid=procinfo.dwThreadId; + } else { + process_info->pid = -GetLastError (); } return(ret); @@ -710,11 +888,10 @@ MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObjec if(ms<0) { /* Wait forever */ - ret=WaitForSingleObject (process, INFINITE); + ret=WaitForSingleObjectEx (process, INFINITE, TRUE); } else { - ret=WaitForSingleObject (process, ms); + ret=WaitForSingleObjectEx (process, ms, TRUE); } - if(ret==WAIT_OBJECT_0) { return(TRUE); } else { @@ -793,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); } @@ -825,7 +1002,7 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void) } count=needed/sizeof(guint32); - procs=mono_array_new (mono_domain_get (), mono_defaults.int_class, + procs=mono_array_new (mono_domain_get (), mono_get_int32_class (), count); for(i=0; i Kill, sig == 2 -> CloseMainWindow */ + + return TerminateProcess (process, -sig); +} +