#include <config.h>
#include <glib.h>
#include <string.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <mono/os/gc_wrapper.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/monitor.h>
#include <mono/metadata/threadpool.h>
+#include <mono/metadata/mono-debug.h>
#include <mono/utils/mono-uri.h>
#include <mono/utils/mono-logger.h>
#include <mono/utils/mono-path.h>
#include <mono/utils/mono-stdlib.h>
+#ifdef PLATFORM_WIN32
+#include <direct.h>
+#endif
-#define MONO_CORLIB_VERSION 54
+#define MONO_CORLIB_VERSION 58
CRITICAL_SECTION mono_delegate_section;
if (ass->image->references) {
for (i = 0; ass->image->references [i] != NULL; i++) {
- if (!g_hash_table_lookup (ht, ass->image->references [i])) {
- add_assemblies_to_domain (domain, ass->image->references [i], ht);
- }
+ if (ass->image->references [i] != REFERENCE_MISSING)
+ if (!g_hash_table_lookup (ht, ass->image->references [i])) {
+ add_assemblies_to_domain (domain, ass->image->references [i], ht);
+ }
}
}
if (destroy_ht)
g_strfreev (pvt_split);
}
+static gboolean
+shadow_copy_sibling (gchar *src, gint srclen, const char *extension, gchar *target, gint targetlen, gint tail_len)
+{
+ guint16 *orig, *dest;
+ gboolean copy_result;
+
+ strcpy (src + srclen - tail_len, extension);
+ if (!g_file_test (src, G_FILE_TEST_IS_REGULAR))
+ return TRUE;
+ orig = g_utf8_to_utf16 (src, strlen (src), NULL, NULL, NULL);
+
+ strcpy (target + targetlen - tail_len, extension);
+ dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL);
+
+ copy_result = CopyFile (orig, dest, FALSE);
+ g_free (orig);
+ g_free (dest);
+
+ return copy_result;
+}
+
+static gint32
+get_cstring_hash (const char *str)
+{
+ int len, i;
+ const char *p;
+ gint32 h = 0;
+
+ if (!str || !str [0])
+ return 0;
+
+ len = strlen (str);
+ p = str;
+ for (i = 0; i < len; i++) {
+ h = (h << 5) - h + *p;
+ p++;
+ }
+
+ return h;
+}
+
+static char *
+get_shadow_assembly_location (const char *filename)
+{
+ gint32 hash = 0, hash2 = 0;
+ guint32 ticks = GetTickCount ();
+ char name_hash [9];
+ char path_hash [30];
+ char *bname = g_path_get_basename (filename);
+ MonoDomain *domain = mono_domain_get ();
+
+ hash = get_cstring_hash (bname);
+ hash2 = get_cstring_hash (g_path_get_dirname (filename));
+ g_snprintf (name_hash, sizeof (name_hash), "%08x", hash);
+ g_snprintf (path_hash, sizeof (path_hash), "%08x_%08x_%08x", hash ^ hash2, hash2, ticks);
+ return g_build_filename (mono_string_to_utf8 (domain->setup->dynamic_base),
+ "assembly",
+ "shadow",
+ name_hash,
+ path_hash,
+ bname,
+ NULL);
+}
+
+static gboolean
+ensure_directory_exists (const char *filename)
+{
+#ifdef PLATFORM_WIN32
+ gchar *dir_utf8 = g_path_get_dirname (filename);
+ gunichar2 *p;
+ gunichar2 *dir_utf16 = NULL;
+ int retval;
+
+ if (!dir_utf8 || !dir_utf8 [0])
+ return FALSE;
+
+ dir_utf16 = g_utf8_to_utf16 (dir_utf8, strlen (dir_utf8), NULL, NULL, NULL);
+ g_free (dir_utf8);
+
+ if (!dir_utf16)
+ return FALSE;
+
+ p = dir_utf16;
+
+ /* make life easy and only use one directory seperator */
+ while (*p != '\0')
+ {
+ if (*p == '/')
+ *p = '\\';
+ p++;
+ }
+
+ p = dir_utf16;
+
+ /* get past C:\ )*/
+ while (*p++ != '\\')
+ {
+ }
+
+ while (1) {
+ BOOL bRet = FALSE;
+ p = wcschr (p, '\\');
+ if (p)
+ *p = '\0';
+ retval = _wmkdir (dir_utf16);
+ if (retval != 0 && errno != EEXIST) {
+ g_free (dir_utf16);
+ return FALSE;
+ }
+ if (!p)
+ break;
+ *p++ = '\\';
+ }
+
+ g_free (dir_utf16);
+ return TRUE;
+#else
+ char *p;
+ gchar *dir = g_path_get_dirname (filename);
+ int retval;
+
+ if (!dir || !dir [0])
+ return FALSE;
+
+ p = dir;
+ while (*p == '/')
+ p++;
+
+ while (1) {
+ p = strchr (p, '/');
+ if (p)
+ *p = '\0';
+ retval = mkdir (dir, 0777);
+ if (retval != 0 && errno != EEXIST) {
+ g_free (dir);
+ return FALSE;
+ }
+ if (!p)
+ break;
+ *p++ = '/';
+ }
+
+ g_free (dir);
+ return TRUE;
+#endif
+}
+
static char *
make_shadow_copy (const char *filename)
{
- gchar *tmp;
+ gchar *sibling_source, *sibling_target;
+ gint sibling_source_len, sibling_target_len;
guint16 *orig, *dest;
- MonoDomain *domain = mono_domain_get ();
- char *db;
- int fd;
+ char *shadow;
gboolean copy_result;
MonoException *exc;
-
- db = mono_string_to_utf8 (domain->setup->dynamic_base);
- tmp = g_build_filename (db, "shadow-XXXXXX", NULL);
- fd = mono_mkstemp (tmp);
- if (fd == -1) {
- exc = mono_get_exception_execution_engine ("Failed to create shadow copy (mkstemp).");
- g_free (tmp);
- g_free (db);
+
+ shadow = get_shadow_assembly_location (filename);
+ if (ensure_directory_exists (shadow) == FALSE) {
+ exc = mono_get_exception_execution_engine ("Failed to create shadow copy (ensure directory exists).");
mono_raise_exception (exc);
- }
- close (fd);
- remove (tmp);
+ }
+
orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL);
- dest = g_utf8_to_utf16 (tmp, strlen (tmp), NULL, NULL, NULL);
- copy_result = CopyFile (orig, dest, TRUE);
+ dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL);
+ copy_result = CopyFile (orig, dest, FALSE);
g_free (dest);
g_free (orig);
- g_free (db);
if (copy_result == FALSE) {
- g_free (tmp);
+ g_free (shadow);
exc = mono_get_exception_execution_engine ("Failed to create shadow copy (CopyFile).");
mono_raise_exception (exc);
}
- return tmp;
+
+ /* attempt to copy .mdb, .config if they exist */
+ sibling_source = g_strconcat (filename, ".config", NULL);
+ sibling_source_len = strlen (sibling_source);
+ sibling_target = g_strconcat (shadow, ".config", NULL);
+ sibling_target_len = strlen (sibling_target);
+
+ copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".mdb", sibling_target, sibling_target_len, 7);
+ if (copy_result == TRUE)
+ copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".config", sibling_target, sibling_target_len, 7);
+
+ g_free (sibling_source);
+ g_free (sibling_target);
+
+ if (copy_result == FALSE) {
+ g_free (shadow);
+ exc = mono_get_exception_execution_engine ("Failed to create shadow copy of sibling data (CopyFile).");
+ mono_raise_exception (exc);
+ }
+
+ return shadow;
}
static gboolean
filename = g_strconcat (name, ".dll", NULL);
len = strlen (filename);
- printf ("Loading %s as %s\n", filename, (search_path && *search_path && **search_path) ? "Publico" : "Privado");
for (path = search_path; *path; path++) {
if (**path == '\0') {
MonoException *exc;
if (status == MONO_IMAGE_IMAGE_INVALID)
- exc = mono_get_exception_bad_image_format (name);
+ exc = mono_get_exception_bad_image_format2 (NULL, fname);
else
- exc = mono_get_exception_file_not_found (fname);
+ exc = mono_get_exception_file_not_found2 (NULL, fname);
g_free (name);
mono_raise_exception (exc);
}
MonoReflectionAssembly *
ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomain *ad,
- MonoArray *raw_assembly,
- MonoArray *raw_symbol_store, MonoObject *evidence,
- MonoBoolean refonly)
+ MonoArray *raw_assembly,
+ MonoArray *raw_symbol_store, MonoObject *evidence,
+ MonoBoolean refonly)
{
MonoAssembly *ass;
MonoReflectionAssembly *refass = NULL;
guint32 raw_assembly_len = mono_array_length (raw_assembly);
MonoImage *image = mono_image_open_from_data_full (mono_array_addr (raw_assembly, gchar, 0), raw_assembly_len, TRUE, NULL, refonly);
- if (raw_symbol_store)
- mono_raise_exception (mono_get_exception_not_implemented ("LoadAssemblyRaw: Raw Symbol Store not Implemented"));
-
if (!image) {
mono_raise_exception (mono_get_exception_bad_image_format (""));
return NULL;
}
+ if (raw_symbol_store != NULL)
+ mono_debug_init_2_memory (image, mono_array_addr (raw_symbol_store, guint8, 0), mono_array_length (raw_symbol_store));
+
ass = mono_assembly_load_from_full (image, "", &status, refonly);
+
if (!ass) {
mono_image_close (image);
mono_raise_exception (mono_get_exception_bad_image_format (""));
MonoException *exc;
/* This is a parse error... */
- exc = mono_get_exception_file_not_found (assRef);
+ exc = mono_get_exception_file_not_found2 (NULL, assRef);
mono_raise_exception (exc);
}
if (!ass && (refass = try_assembly_resolve (domain, assRef, refOnly)) == NULL){
/* FIXME: it doesn't make much sense since we really don't have a filename ... */
- MonoException *exc = mono_get_exception_file_not_found (assRef);
+ MonoException *exc = mono_get_exception_file_not_found2 (NULL, assRef);
mono_raise_exception (exc);
}
g_free (filename);
if (!assembly)
- mono_raise_exception (mono_get_exception_file_not_found (file));
+ mono_raise_exception (mono_get_exception_file_not_found2 (NULL, file));
image = assembly->image;
/* printf ("UNLOADED %s.\n", domain->friendly_name); */
+ /* remove from the handle table the items related to this domain */
+ mono_gchandle_free_domain (domain);
+
mono_domain_free (domain, FALSE);
mono_gc_collect (mono_gc_max_generation ());
thread_handle = CreateThread (NULL, 0, unload_thread_main, &thread_data, 0, &tid);
#else
thread_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)unload_thread_main, &thread_data, CREATE_SUSPENDED, &tid);
+ if (thread_handle == NULL) {
+ return;
+ }
ResumeThread (thread_handle);
#endif