[runtime] Clean up configure.ac a bit.
[mono.git] / mono / metadata / process.c
index a4814c689b193ea9771b23078964927cc49b05bf..02b36b631c612ab69e00fc7ab69a382fe6d5d468 100644 (file)
@@ -20,6 +20,7 @@
 #include <mono/metadata/image.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/exception.h>
+#include <mono/metadata/threadpool-ms-io.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-proclib.h>
 #include <mono/io-layer/io-layer.h>
@@ -34,8 +35,6 @@ HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
 {
        HANDLE handle;
        
-       MONO_ARCH_SAVE_REGS;
-
        /* GetCurrentProcess returns a pseudo-handle, so use
         * OpenProcess instead
         */
@@ -52,18 +51,14 @@ HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
 guint32
 ves_icall_System_Diagnostics_Process_GetPid_internal (void)
 {
-       MONO_ARCH_SAVE_REGS;
-
        return mono_process_current_pid ();
 }
 
-void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this,
+void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this_obj,
                                                                 HANDLE process)
 {
-       MONO_ARCH_SAVE_REGS;
-
 #ifdef THREAD_DEBUG
-       g_message ("%s: Closing process %p, handle %p", __func__, this, process);
+       g_message ("%s: Closing process %p, handle %p", __func__, this_obj, process);
 #endif
 
 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
@@ -73,9 +68,9 @@ void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *thi
 #endif
 }
 
-#define STASH_SYS_ASS(this) \
+#define STASH_SYS_ASS(this_obj) \
        if(system_assembly == NULL) { \
-               system_assembly=this->vtable->klass->image; \
+               system_assembly=this_obj->vtable->klass->image; \
        }
 
 static MonoImage *system_assembly=NULL;
@@ -119,6 +114,20 @@ static void process_set_field_string (MonoObject *obj, const gchar *fieldname,
        mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
 }
 
+static void process_set_field_string_char (MonoObject *obj, const gchar *fieldname,
+                                     const gchar *val)
+{
+       MonoClassField *field;
+       MonoString *string;
+
+       LOGDEBUG (g_message ("%s: Setting field %s to [%s]", __func__, fieldname, val));
+
+       string=mono_string_new (mono_object_domain (obj), val);
+       
+       field=mono_class_get_field_from_name (mono_object_class (obj), fieldname);
+       mono_gc_wbarrier_generic_store (((char *)obj) + field->offset, (MonoObject*)string);
+}
+
 static void process_set_field_int (MonoObject *obj, const gchar *fieldname,
                                   guint32 val)
 {
@@ -356,9 +365,49 @@ static void process_get_fileversion (MonoObject *filever, gunichar2 *filename)
        }
 }
 
-static MonoObject* process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename)
+static void process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
+{
+       process_set_field_int (filever, "filemajorpart", assembly->aname.major);
+       process_set_field_int (filever, "fileminorpart", assembly->aname.minor);
+       process_set_field_int (filever, "filebuildpart", assembly->aname.build);
+}
+
+static MonoObject* get_process_module (MonoAssembly *assembly, MonoClass *proc_class)
+{
+       static MonoClass *filever_class = NULL;
+       MonoObject *item, *filever;
+       MonoDomain *domain = mono_domain_get ();
+       char filename [80] = "[In Memory] ";
+       const char *modulename = assembly->aname.name;
+
+       strncat (filename, modulename, 80);
+
+       /* Build a System.Diagnostics.ProcessModule with the data.
+        */
+       item = mono_object_new (domain, proc_class);
+
+       if (!filever_class)
+               filever_class = mono_class_from_name (system_assembly,
+                                           "System.Diagnostics",
+                                           "FileVersionInfo");
+
+       filever = mono_object_new (domain, filever_class);
+
+       process_get_assembly_fileversion (filever, assembly);
+       process_set_field_string_char (filever, "filename", filename);
+       process_set_field_object (item, "version_info", filever);
+
+       process_set_field_intptr (item, "baseaddr", assembly->image->raw_data);
+       process_set_field_int (item, "memory_size", assembly->image->raw_data_len);
+       process_set_field_string_char (item, "filename", filename);
+       process_set_field_string_char (item, "modulename", modulename);
+
+       return item;
+}
+
+static MonoObject* process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class)
 {
-       MonoClass *proc_class, *filever_class;
+       static MonoClass *filever_class = NULL;
        MonoObject *item, *filever;
        MonoDomain *domain=mono_domain_get ();
        MODULEINFO modinfo;
@@ -366,13 +415,13 @@ static MonoObject* process_add_module (HANDLE process, HMODULE mod, gunichar2 *f
        
        /* Build a System.Diagnostics.ProcessModule with the data.
         */
-       proc_class=mono_class_from_name (system_assembly, "System.Diagnostics",
-                                        "ProcessModule");
        item=mono_object_new (domain, proc_class);
 
-       filever_class=mono_class_from_name (system_assembly,
+       if (!filever_class)
+               filever_class=mono_class_from_name (system_assembly,
                                            "System.Diagnostics",
                                            "FileVersionInfo");
+
        filever=mono_object_new (domain, filever_class);
 
        process_get_fileversion (filever, filename);
@@ -398,8 +447,30 @@ static MonoObject* process_add_module (HANDLE process, HMODULE mod, gunichar2 *f
        return item;
 }
 
+static GPtrArray* get_domain_assemblies (MonoDomain *domain)
+{
+       GSList *tmp;
+       GPtrArray *assemblies;
+
+       /* 
+        * Make a copy of the list of assemblies because we can't hold the assemblies
+        * lock while creating objects etc.
+        */
+       assemblies = g_ptr_array_new ();
+       mono_domain_assemblies_lock (domain);
+       for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
+               MonoAssembly *ass = tmp->data;
+               if (ass->image->fileio_used)
+                       continue;
+               g_ptr_array_add (assemblies, ass);
+       }
+       mono_domain_assemblies_unlock (domain);
+
+       return assemblies;
+}
+
 /* Returns an array of System.Diagnostics.ProcessModule */
-MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this, HANDLE process)
+MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
 {
        MonoArray *temp_arr = NULL;
        MonoArray *arr;
@@ -407,29 +478,67 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject
        gunichar2 filename[MAX_PATH];
        gunichar2 modname[MAX_PATH];
        DWORD needed;
-       guint32 count = 0;
+       guint32 count = 0, module_count = 0, assembly_count = 0;
        guint32 i, num_added = 0;
+       static MonoClass *proc_class = NULL;
+       GPtrArray *assemblies = NULL;
+       static HANDLE current_process = 0;
+       
+       if (current_process == 0) {
+               int pid = mono_process_current_pid ();
+               current_process = ves_icall_System_Diagnostics_Process_GetProcess_internal (pid);
+       }
 
-       STASH_SYS_ASS (this);
+       STASH_SYS_ASS (this_obj);
+
+       if (process == current_process) {
+               assemblies = get_domain_assemblies (mono_domain_get ());
+               assembly_count = assemblies->len;
+       }
 
        if (EnumProcessModules (process, mods, sizeof(mods), &needed)) {
-               count = needed / sizeof(HMODULE);
-               temp_arr = mono_array_new (mono_domain_get (), mono_get_object_class (), count);
-               for (i = 0; i < count; i++) {
-                       if (GetModuleBaseName (process, mods[i], modname, MAX_PATH) &&
-                                       GetModuleFileNameEx (process, mods[i], filename, MAX_PATH)) {
-                               MonoObject *module = process_add_module (process, mods[i],
-                                               filename, modname);
-                               mono_array_setref (temp_arr, num_added++, module);
-                       }
+               module_count += needed / sizeof(HMODULE);
+       }
+
+       count = module_count + assembly_count; 
+       if (!proc_class)
+               proc_class = mono_class_from_name (system_assembly, "System.Diagnostics", "ProcessModule");
+
+       temp_arr = mono_array_new (mono_domain_get (), proc_class, count);
+
+       for (i = 0; i < module_count; i++) {
+               if (GetModuleBaseName (process, mods[i], modname, MAX_PATH) &&
+                               GetModuleFileNameEx (process, mods[i], filename, MAX_PATH)) {
+                       MonoObject *module = process_add_module (process, mods[i],
+                                       filename, modname, proc_class);
+                       mono_array_setref (temp_arr, num_added++, module);
+               }
+       }
+
+       if (assemblies) {
+               for (i = 0; i < assembly_count; i++) {
+                       MonoAssembly *ass = g_ptr_array_index (assemblies, i);
+                       MonoObject *module = get_process_module (ass, proc_class);
+                       mono_array_setref (temp_arr, num_added++, module);
                }
+               g_ptr_array_free (assemblies, TRUE);
+       }
+
+       if (count == num_added) {
+               arr = temp_arr;
+       } else {
+               /* shorter version of the array */
+               arr = mono_array_new (mono_domain_get (), proc_class, num_added);
+
+               for (i = 0; i < num_added; i++)
+                       mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
        }
 
        if (count == num_added) {
                arr = temp_arr;
        } else {
                /* shorter version of the array */
-               arr = mono_array_new (mono_domain_get (), mono_get_object_class (), num_added);
+               arr = mono_array_new (mono_domain_get (), proc_class, num_added);
 
                for (i = 0; i < num_added; i++)
                        mono_array_setref (arr, i, mono_array_get (temp_arr, MonoObject*, i));
@@ -438,14 +547,12 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject
        return arr;
 }
 
-void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this, MonoString *filename)
+void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
 {
-       MONO_ARCH_SAVE_REGS;
-
-       STASH_SYS_ASS (this);
+       STASH_SYS_ASS (this_obj);
        
-       process_get_fileversion (this, mono_string_chars (filename));
-       process_set_field_string (this, "filename",
+       process_get_fileversion (this_obj, mono_string_chars (filename));
+       process_set_field_string (this_obj, "filename",
                                  mono_string_chars (filename),
                                  mono_string_length (filename));
 }
@@ -556,10 +663,7 @@ MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoPr
        } 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.
-                */
-#if defined(HAVE_GETPROCESSID) && !defined(MONO_CROSS_COMPILE)
+#if !defined(MONO_CROSS_COMPILE)
                process_info->pid = GetProcessId (shellex.hProcess);
 #else
                process_info->pid = 0;
@@ -696,18 +800,19 @@ MonoBoolean ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoPro
        return(ret);
 }
 
-MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObject *this, HANDLE process, gint32 ms)
+MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObject *this_obj, HANDLE process, gint32 ms)
 {
        guint32 ret;
        
-       MONO_ARCH_SAVE_REGS;
-
+       MONO_PREPARE_BLOCKING
        if(ms<0) {
                /* Wait forever */
                ret=WaitForSingleObjectEx (process, INFINITE, TRUE);
        } else {
                ret=WaitForSingleObjectEx (process, ms, TRUE);
        }
+       MONO_FINISH_BLOCKING
+
        if(ret==WAIT_OBJECT_0) {
                return(TRUE);
        } else {
@@ -715,12 +820,10 @@ MonoBoolean ves_icall_System_Diagnostics_Process_WaitForExit_internal (MonoObjec
        }
 }
 
-MonoBoolean ves_icall_System_Diagnostics_Process_WaitForInputIdle_internal (MonoObject *this, HANDLE process, gint32 ms)
+MonoBoolean ves_icall_System_Diagnostics_Process_WaitForInputIdle_internal (MonoObject *this_obj, HANDLE process, gint32 ms)
 {
        guint32 ret;
        
-       MONO_ARCH_SAVE_REGS;
-
        if(ms<0) {
                /* Wait forever */
                ret=WaitForInputIdle (process, INFINITE);
@@ -742,8 +845,6 @@ gint64 ves_icall_System_Diagnostics_Process_ExitTime_internal (HANDLE process)
        gboolean ret;
        FILETIME create_time, exit_time, kernel_time, user_time;
        
-       MONO_ARCH_SAVE_REGS;
-
        ret = GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
                                                   &user_time);
        if (ret)
@@ -757,8 +858,6 @@ gint64 ves_icall_System_Diagnostics_Process_StartTime_internal (HANDLE process)
        gboolean ret;
        FILETIME create_time, exit_time, kernel_time, user_time;
        
-       MONO_ARCH_SAVE_REGS;
-
        ret = GetProcessTimes (process, &create_time, &exit_time, &kernel_time,
                                                   &user_time);
        if (ret)
@@ -771,8 +870,6 @@ gint32 ves_icall_System_Diagnostics_Process_ExitCode_internal (HANDLE process)
 {
        DWORD code;
        
-       MONO_ARCH_SAVE_REGS;
-
        GetExitCodeProcess (process, &code);
        
        LOGDEBUG (g_message ("%s: process exit code is %d", __func__, code));
@@ -789,8 +886,6 @@ MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE pr
        DWORD needed;
        guint32 len;
        
-       MONO_ARCH_SAVE_REGS;
-
        ok=EnumProcessModules (process, &mod, sizeof(mod), &needed);
        if(ok==FALSE) {
                return(NULL);
@@ -809,21 +904,22 @@ MonoString *ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE pr
 }
 
 /* Returns an array of pids */
-MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
+MonoArray *
+ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
 {
 #if !defined(HOST_WIN32)
        MonoArray *procs;
        gpointer *pidarray;
        int i, count;
 
-       MONO_ARCH_SAVE_REGS;
-
        pidarray = mono_process_list (&count);
-       if (!pidarray)
-               mono_raise_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
+       if (!pidarray) {
+               mono_set_pending_exception (mono_get_exception_not_supported ("This system does not support EnumProcesses"));
+               return NULL;
+       }
        procs = mono_array_new (mono_domain_get (), mono_get_int32_class (), count);
        if (sizeof (guint32) == sizeof (gpointer)) {
-               memcpy (mono_array_addr (procs, guint32, 0), pidarray, count);
+               memcpy (mono_array_addr (procs, guint32, 0), pidarray, count * sizeof (gint32));
        } else {
                for (i = 0; i < count; ++i)
                        *(mono_array_addr (procs, guint32, i)) = GPOINTER_TO_UINT (pidarray [i]);
@@ -848,8 +944,8 @@ MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
                        g_free (pids);
                        pids = NULL;
                        exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
-                       mono_raise_exception (exc);
-                       g_assert_not_reached ();
+                       mono_set_pending_exception (exc);
+                       return NULL;
                }
                if (needed < (count * sizeof (guint32)))
                        break;
@@ -873,8 +969,6 @@ MonoBoolean ves_icall_System_Diagnostics_Process_GetWorkingSet_internal (HANDLE
        gboolean ret;
        SIZE_T ws_min, ws_max;
        
-       MONO_ARCH_SAVE_REGS;
-
        ret=GetProcessWorkingSetSize (process, &ws_min, &ws_max);
        *min=(guint32)ws_min;
        *max=(guint32)ws_max;
@@ -888,8 +982,6 @@ MonoBoolean ves_icall_System_Diagnostics_Process_SetWorkingSet_internal (HANDLE
        SIZE_T ws_min;
        SIZE_T ws_max;
        
-       MONO_ARCH_SAVE_REGS;
-
        ret=GetProcessWorkingSetSize (process, &ws_min, &ws_max);
        if(ret==FALSE) {
                return(FALSE);
@@ -909,8 +1001,6 @@ MonoBoolean ves_icall_System_Diagnostics_Process_SetWorkingSet_internal (HANDLE
 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);
@@ -956,8 +1046,6 @@ ves_icall_System_Diagnostics_Process_ProcessHandle_duplicate (HANDLE process)
 {
        HANDLE ret;
 
-       MONO_ARCH_SAVE_REGS;
-
        LOGDEBUG (g_message ("%s: Duplicating process handle %p", __func__, process));
        
        DuplicateHandle (GetCurrentProcess (), process, GetCurrentProcess (),
@@ -969,8 +1057,6 @@ ves_icall_System_Diagnostics_Process_ProcessHandle_duplicate (HANDLE process)
 void
 ves_icall_System_Diagnostics_Process_ProcessHandle_close (HANDLE process)
 {
-       MONO_ARCH_SAVE_REGS;
-
        LOGDEBUG (g_message ("%s: Closing process handle %p", __func__, process));
 
        CloseHandle (process);
@@ -988,3 +1074,9 @@ ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type,
        return res;
 }
 
+void
+ves_icall_System_Diagnostics_Process_ProcessAsyncReader_RemoveFromIOThreadPool (HANDLE handle)
+{
+       mono_threadpool_ms_io_remove_socket (GPOINTER_TO_INT (handle));
+}
+