New test.
[mono.git] / mono / metadata / process.c
index a0a499b980f7ed1862d77441c330a25b119bccf9..6aa9e66d9f557d8a51392cdb573794d843a18efd 100644 (file)
@@ -5,6 +5,7 @@
  *     Dick Porter (dick@ximian.com)
  *
  * (C) 2002 Ximian, Inc.
+ * Copyright (c) 2002-2006 Novell, Inc.
  */
 
 #include <config.h>
@@ -21,6 +22,8 @@
 #include <mono/metadata/exception.h>
 #include <mono/utils/strenc.h>
 #include <mono/io-layer/io-layer.h>
+/* FIXME: fix this code to not depend so much on the inetrnals */
+#include <mono/metadata/class-internals.h>
 
 #undef DEBUG
 
@@ -95,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;
@@ -110,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;
@@ -129,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;
@@ -147,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;
@@ -162,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;
@@ -204,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);
 }
@@ -238,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.
@@ -306,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) {
@@ -326,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
@@ -394,7 +345,9 @@ static gpointer process_read_stringtable_block (MonoObject *filever,
 
        while(string_len<data_len) {
                /* 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) {
@@ -411,7 +364,11 @@ static gpointer process_read_stringtable_block (MonoObject *filever,
 
                language = g_utf16_to_utf8 (block.key, unicode_bytes (block.key), NULL, NULL, NULL);
                g_strdown (language);
-               if (!strcmp (language, "007f04b0") || !strcmp (language, "000004b0")) {
+
+               /* Kludge: treat en_US as neutral too */
+               if (!strcmp (language, "007f04b0") ||
+                   !strcmp (language, "000004b0") ||
+                   !strcmp (language, "040904b0")) {
                        /* Got the one we're interested in */
                        process_set_field_string_utf8 (filever, "language",
                                                       "Language Neutral");
@@ -486,21 +443,7 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image)
        gpointer data_ptr;
        version_data block;
        gint32 data_len; /* signed to guard against underflow */
-       guchar vs_key[]= {'V', '\0', 'S', '\0', '_', '\0', 'V', '\0',
-                         'E', '\0', 'R', '\0', 'S', '\0', 'I', '\0',
-                         'O', '\0', 'N', '\0', '_', '\0', 'I', '\0',
-                         'N', '\0', 'F', '\0', 'O', '\0', '\0', '\0'
-       };
-       guchar var_key[]= {'V', '\0', 'a', '\0', 'r', '\0', 'F', '\0',
-                          'i', '\0', 'l', '\0', 'e', '\0', 'I', '\0',
-                          'n', '\0', 'f', '\0', 'o', '\0', '\0', '\0', 
-       };
-       guchar str_key[]= {'S', '\0', 't', '\0', 'r', '\0', 'i', '\0',
-                          'n', '\0', 'g', '\0', 'F', '\0', 'i', '\0',
-                          'l', '\0', 'e', '\0', 'I', '\0', 'n', '\0',
-                          'f', '\0', 'o', '\0', '\0', '\0', 
-       };
-       
+
        version_info=mono_image_lookup_resource (image,
                                                 MONO_PE_RESOURCE_ID_VERSION,
                                                 0, NULL);
@@ -513,7 +456,7 @@ static void process_get_fileversion (MonoObject *filever, MonoImage *image)
                return;
        }
        
-       data=mono_cli_rva_map (image->image_info,
+       data=mono_image_rva_map (image,
                               version_info->rde_data_offset);
        if(data==NULL) {
                return;
@@ -536,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");
@@ -564,7 +507,9 @@ 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) {
@@ -580,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 */
@@ -611,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,
@@ -632,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);
 
@@ -681,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; i<modules_list->len; 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);
 }
@@ -697,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) {
@@ -717,12 +662,110 @@ 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;
@@ -730,6 +773,12 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd
        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;
 
@@ -739,28 +788,26 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd
        startinfo.hStdOutput=stdout_handle;
        startinfo.hStdError=stderr_handle;
        
-       if (process_info->use_shell) {
-               const gchar *spath;
-               const gchar *arg;
+       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
-               arg = "/c"; /* This works for cmd and command */
-               spath = g_getenv ("COMSPEC");
+       /* 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
-               arg = "-c"; /* sh, bash, tcsh... any other? */
-               spath = g_getenv ("SHELL");
+       shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
 #endif
-               if (spath != NULL) {
-                       gint dummy;
-                       gchar *newcmd, *tmp;
-
-                       shell_path = mono_unicode_from_external (spath, &dummy);
-                       tmp = mono_string_to_utf8 (cmd);
-                       newcmd = g_strdup_printf ("%s %s", arg, tmp);
-                       g_free (tmp);
-                       cmd = mono_string_new (mono_domain_get (), newcmd);
-                       g_free (newcmd);
-               }
-       }
+       g_free (spath);
 
        if (process_info->env_keys != NULL) {
                gint i, len; 
@@ -806,19 +853,24 @@ MonoBoolean ves_icall_System_Diagnostics_Process_Start_internal (MonoString *cmd
        /* 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);
 
        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 {
@@ -836,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 {
@@ -919,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);
        }
@@ -951,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<count; i++) {
                mono_array_set (procs, guint32, i, pids[i]);
@@ -997,3 +1048,14 @@ MonoBoolean ves_icall_System_Diagnostics_Process_SetWorkingSet_internal (HANDLE
 
        return(ret);
 }
+
+MonoBoolean
+ves_icall_System_Diagnostics_Process_Kill_internal (HANDLE process, gint32 sig)
+{
+       MONO_ARCH_SAVE_REGS;
+
+       /* sig == 1 -> Kill, sig == 2 -> CloseMainWindow */
+
+       return TerminateProcess (process, -sig);
+}
+