* Dick Porter (dick@ximian.com)
*
* (C) 2002 Ximian, Inc.
+ * Copyright (c) 2002-2006 Novell, Inc.
*/
#include <config.h>
#include <glib.h>
+#include <string.h>
#include <mono/metadata/object.h>
#include <mono/metadata/process.h>
#include <mono/metadata/image.h>
#include <mono/metadata/cil-coff.h>
#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
} 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;
*(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;
}
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;
*(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;
*(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;
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);
}
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.
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
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.
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) {
+ /* 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;
-
- if(!memcmp (block.key, &uni_key, unicode_bytes (block.key)) ||
- !memcmp (block.key, &uni_key_uc, unicode_bytes (block.key))) {
+
+ language = g_utf16_to_utf8 (block.key, unicode_bytes (block.key), NULL, NULL, NULL);
+ g_strdown (language);
+
+ /* 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");
block.data_len,
FALSE);
}
+ g_free (language);
+
+ 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(NULL);
+ }
}
return(data_ptr);
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);
return;
}
- data=mono_cli_rva_map (image->image_info,
+ data=mono_image_rva_map (image,
version_info->rde_data_offset);
if(data==NULL) {
return;
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");
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
*/
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 */
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;
+ }
}
}
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,
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);
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);
}
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) {
}
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;
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);
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 {
return(NULL);
}
- len=GetModuleBaseName (process, mod, name, sizeof(name));
+ len=GetModuleBaseName (process, mod, name, MAX_PATH);
if(len==0) {
return(NULL);
}
}
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]);
MonoBoolean ves_icall_System_Diagnostics_Process_GetWorkingSet_internal (HANDLE process, guint32 *min, guint32 *max)
{
gboolean ret;
+ size_t ws_min, ws_max;
MONO_ARCH_SAVE_REGS;
- ret=GetProcessWorkingSetSize (process, min, max);
+ ret=GetProcessWorkingSetSize (process, &ws_min, &ws_max);
+ *min=(guint32)ws_min;
+ *max=(guint32)ws_max;
return(ret);
}
MonoBoolean ves_icall_System_Diagnostics_Process_SetWorkingSet_internal (HANDLE process, guint32 min, guint32 max, MonoBoolean use_min)
{
gboolean ret;
- guint32 ws_min;
- guint32 ws_max;
+ size_t ws_min;
+ size_t ws_max;
MONO_ARCH_SAVE_REGS;
}
if(use_min==TRUE) {
- max=ws_max;
+ ws_min=min;
} else {
- min=ws_min;
+ ws_max=max;
}
- ret=SetProcessWorkingSetSize (process, min, max);
+ ret=SetProcessWorkingSetSize (process, ws_min, ws_max);
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);
+}
+