From 70098c094f7d69f798aa927a8459fee0a1d0fdc8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Korn=C3=A9l=20P=C3=A1l?= Date: Wed, 14 May 2008 09:02:13 +0000 Subject: [PATCH] Mono runtime: Fix support for mixed-mode assemblies. Contributed under MIT/X11 license. svn path=/trunk/mono/; revision=103161 --- mono/metadata/ChangeLog | 31 ++++++ mono/metadata/coree.c | 166 +++++++++++++++++++++++++++---- mono/metadata/coree.h | 15 +-- mono/metadata/domain-internals.h | 3 + mono/metadata/domain.c | 20 ++-- mono/metadata/image.c | 77 +++++++++++--- mono/utils/ChangeLog | 7 ++ mono/utils/mono-path.c | 3 + 8 files changed, 274 insertions(+), 48 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 5b6bf61c7c1..85275b370a3 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,34 @@ +2008-05-14 Kornél Pál + + * domain.c (mono_init_internal): Enable LoadLibrary support. Load EXE image + even when get_runtimes_from_exe didn't load it that allows mono_fixup_exe_image + to fixup the EXE image. + (mono_cleanup): Use mono_close_exe_image. + (mono_close_exe_image): New function. + * image.c: Include "marshal.h". + (mono_image_open_from_module_handle): Add ref_count argument. Return the image. + (mono_image_open_full, mono_image_close): Fix LoadLibrary/FreeLibrary reference + counting when the image is loaded outside of mono_image_open_full. Set status + based on GetLastError. + * coree.c: Include required headers. Add init_from_coree. + (_CorDllMain): Support fix in mono_image_open_full, mono_image_close. Call + mono_assembly_open only when the image has vtfixups. Set init_from_coree. + (_CorExeMain): Set init_from_coree. + (CorExitProcess): Only call ExitProcess for now. + (CorBindToRuntimeEx): New stub implementation. + (CorBindToRuntime): New function. + (MonoFixupCorEE): Fixup CorBindToRuntime and CorBindToRuntimeEx. + (MonoFixupExe): ILONLY executables require no fixups. + (mono_set_act_ctx): New function to set activation context. + (mono_load_coree): Use init_from_coree. Call mono_set_act_ctx. + * coree.h: Move STATUS_SUCCESS and STATUS_INVALID_IMAGE_FORMAT to header. + Declare mono_module_handle, coree_module_handle, mono_get_module_file_name, + mono_load_coree, mono_fixup_exe_image and mono_image_open_from_module_handle + as MONO_INTERNAL. + * domain-internals.h: Add mono_close_exe_image. + + Contributed under MIT/X11 license. + 2008-05-13 Rodrigo Kumpera * metadata.c (mono_metadata_compute_size): Correctly calculate field diff --git a/mono/metadata/coree.c b/mono/metadata/coree.c index c47a159edff..25943e6828c 100644 --- a/mono/metadata/coree.c +++ b/mono/metadata/coree.c @@ -11,12 +11,21 @@ #ifdef PLATFORM_WIN32 +#if _WIN32_WINNT < 0x0501 +/* Required for ACTCTX. */ +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif /* _WIN32_WINNT < 0x0501 */ + #include #include #include +#include +#include "cil-coff.h" #include "metadata-internals.h" #include "image.h" #include "assembly.h" +#include "domain-internals.h" #include "appdomain.h" #include "object.h" #include "loader.h" @@ -24,18 +33,11 @@ #include "environment.h" #include "coree.h" -#define STATUS_SUCCESS 0x00000000L -#define STATUS_INVALID_IMAGE_FORMAT 0xC000007BL - -typedef struct _EXPORT_FIXUP -{ - LPCSTR Name; - DWORD_PTR ProcAddress; -} EXPORT_FIXUP; - HMODULE mono_module_handle = NULL; HMODULE coree_module_handle = NULL; +static gboolean init_from_coree = FALSE; + gchar* mono_get_module_file_name (HMODULE module_handle) { @@ -84,8 +86,9 @@ BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes file_name = mono_get_module_file_name (hInst); if (mono_get_root_domain ()) { - image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), NULL); + image = mono_image_open_from_module_handle (hInst, mono_path_resolve_symlinks (file_name), 0, NULL); } else { + init_from_coree = TRUE; mono_runtime_load (file_name, NULL); error = (gchar*) mono_check_corlib_version (); if (error) { @@ -96,6 +99,10 @@ BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes } image = mono_image_open (file_name, NULL); + mono_close_exe_image (); + if (image) + /* Decrement reference count to zero. (Image will not be closed.) */ + mono_image_close (image); } if (!image) { @@ -108,9 +115,20 @@ BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes * loader trampolines should be used and assembly loading should * probably be delayed until the first call to an exported function. */ - if (image->tables [MONO_TABLE_ASSEMBLY].rows) + if (image->tables [MONO_TABLE_ASSEMBLY].rows && ((MonoCLIImageInfo*) image->image_info)->cli_cli_header.ch_vtable_fixups.rva) assembly = mono_assembly_open (file_name, NULL); + g_free (file_name); + break; + case DLL_PROCESS_DETACH: + if (lpReserved != NULL) + /* The process is terminating. */ + return TRUE; + file_name = mono_get_module_file_name (hInst); + image = mono_image_loaded (file_name); + if (image) + mono_image_close (image); + g_free (file_name); break; } @@ -119,7 +137,7 @@ BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes } /* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */ -__int32 STDMETHODCALLTYPE _CorExeMain() +__int32 STDMETHODCALLTYPE _CorExeMain(void) { MonoDomain* domain; MonoAssembly* assembly; @@ -134,6 +152,7 @@ __int32 STDMETHODCALLTYPE _CorExeMain() int i; file_name = mono_get_module_file_name (GetModuleHandle (NULL)); + init_from_coree = TRUE; domain = mono_runtime_load (file_name, NULL); error = (gchar*) mono_check_corlib_version (); @@ -146,6 +165,7 @@ __int32 STDMETHODCALLTYPE _CorExeMain() } assembly = mono_assembly_open (file_name, NULL); + mono_close_exe_image (); if (!assembly) { g_free (file_name); MessageBox (NULL, L"Cannot open assembly.", NULL, MB_ICONERROR); @@ -189,11 +209,14 @@ __int32 STDMETHODCALLTYPE _CorExeMain() /* Called by msvcrt.dll when shutting down. */ void STDMETHODCALLTYPE CorExitProcess(int exitCode) { - if (!mono_runtime_is_shutting_down ()) { + /* FIXME: This is not currently supported by the runtime. */ +#if 0 + if (mono_get_root_domain () && !mono_runtime_is_shutting_down ()) { mono_runtime_set_shutting_down (); mono_thread_suspend_all_other_threads (); mono_runtime_quit (); } +#endif ExitProcess (exitCode); } @@ -235,11 +258,33 @@ STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase) /* Nothing to do. */ } +STDAPI CorBindToRuntimeEx(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv) +{ + if (ppv == NULL) + return E_POINTER; + + *ppv = NULL; + return E_NOTIMPL; +} + +STDAPI CorBindToRuntime(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv) +{ + return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, riid, ppv); +} + /* Fixup exported functions of mscoree.dll to our implementations. */ STDAPI MonoFixupCorEE(HMODULE ModuleHandle) { + typedef struct _EXPORT_FIXUP + { + LPCSTR Name; + DWORD_PTR ProcAddress; + } EXPORT_FIXUP; + /* Has to be binary ordered. */ const EXPORT_FIXUP ExportFixups[] = { + {"CorBindToRuntime", (DWORD_PTR)&CorBindToRuntime}, + {"CorBindToRuntimeEx", (DWORD_PTR)&CorBindToRuntimeEx}, {"CorExitProcess", (DWORD_PTR)&CorExitProcess}, {"_CorDllMain", (DWORD_PTR)&_CorDllMain}, {"_CorExeMain", (DWORD_PTR)&_CorExeMain}, @@ -258,11 +303,14 @@ STDAPI MonoFixupCorEE(HMODULE ModuleHandle) EXPORT_FIXUP* ExportFixup; DWORD* Address; DWORD dwOldProtect; - DWORD_PTR ProcAddress; + DWORD ProcRVA; DWORD i; DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle; - if (DosHeader == NULL || DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + if (DosHeader == NULL) + return E_POINTER; + + if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) return E_INVALIDARG; NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + DosHeader->e_lfanew); @@ -293,11 +341,11 @@ STDAPI MonoFixupCorEE(HMODULE ModuleHandle) if (cmp == 0) { Address = &Functions[NameOrdinals[i]]; - ProcAddress = (DWORD_PTR)DosHeader + *Address; - if (ProcAddress != ExportFixup->ProcAddress) { + ProcRVA = (DWORD)(ExportFixup->ProcAddress - (DWORD_PTR)DosHeader); + if (*Address != ProcRVA) { if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect)) return E_UNEXPECTED; - *Address = (DWORD)(ExportFixup->ProcAddress - (DWORD_PTR)DosHeader); + *Address = ProcRVA; if (!VirtualProtect(Address, sizeof(DWORD), dwOldProtect, &dwOldProtect)) return E_UNEXPECTED; } @@ -332,6 +380,20 @@ STDAPI MonoFixupExe(HMODULE ModuleHandle) if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) return S_OK; + if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) + { + IMAGE_DATA_DIRECTORY* CliHeaderDir; + MonoCLIHeader* CliHeader; + + CliHeaderDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]; + if (CliHeaderDir->VirtualAddress && CliHeaderDir->Size) + { + CliHeader = (MonoCLIHeader*)((DWORD_PTR)DosHeader + CliHeaderDir->VirtualAddress); + if (CliHeader->ch_flags & CLI_FLAGS_ILONLY) + return S_OK; + } + } + BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase; if (BaseDiff != 0) { @@ -454,8 +516,69 @@ STDAPI MonoFixupExe(HMODULE ModuleHandle) return S_OK; } +static void +mono_set_act_ctx (const char* file_name) +{ + typedef HANDLE (WINAPI* CREATEACTCTXW_PROC) (PCACTCTXW pActCtx); + typedef BOOL (WINAPI* ACTIVATEACTCTX_PROC) (HANDLE hActCtx, ULONG_PTR* lpCookie); + + HMODULE kernel32_handle; + CREATEACTCTXW_PROC CreateActCtx_proc; + ACTIVATEACTCTX_PROC ActivateActCtx_proc; + gchar* full_path; + gunichar2* full_path_utf16; + gchar* dir_name; + gunichar2* dir_name_utf16; + gchar* base_name; + gunichar2* base_name_utf16; + ACTCTX act_ctx; + HANDLE handle; + ULONG_PTR cookie; + + kernel32_handle = GetModuleHandle (L"kernel32.dll"); + if (!kernel32_handle) + return; + CreateActCtx_proc = (CREATEACTCTXW_PROC) GetProcAddress (kernel32_handle, "CreateActCtxW"); + if (!CreateActCtx_proc) + return; + ActivateActCtx_proc = (ACTIVATEACTCTX_PROC) GetProcAddress (kernel32_handle, "ActivateActCtx"); + if (!ActivateActCtx_proc) + return; + + full_path = mono_path_canonicalize (file_name); + full_path_utf16 = g_utf8_to_utf16 (full_path, -1, NULL, NULL, NULL); + dir_name = g_path_get_dirname (full_path); + dir_name_utf16 = g_utf8_to_utf16 (dir_name, -1, NULL, NULL, NULL); + base_name = g_path_get_basename (full_path); + base_name_utf16 = g_utf8_to_utf16 (base_name, -1, NULL, NULL, NULL); + g_free (base_name); + g_free (dir_name); + g_free (full_path); + + memset (&act_ctx, 0, sizeof (ACTCTX)); + act_ctx.cbSize = sizeof (ACTCTX); + act_ctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_APPLICATION_NAME_VALID; + act_ctx.lpSource = full_path_utf16; + act_ctx.lpAssemblyDirectory = dir_name_utf16; + act_ctx.lpResourceName = MAKEINTRESOURCE (CREATEPROCESS_MANIFEST_RESOURCE_ID); + act_ctx.lpApplicationName = base_name_utf16; + + handle = CreateActCtx_proc (&act_ctx); + if (handle == INVALID_HANDLE_VALUE && GetLastError () == ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET) { + act_ctx.dwFlags &= ~ACTCTX_FLAG_SET_PROCESS_DEFAULT; + handle = CreateActCtx_proc (&act_ctx); + } + + g_free (base_name_utf16); + g_free (dir_name_utf16); + g_free (full_path_utf16); + + if (handle != INVALID_HANDLE_VALUE) + ActivateActCtx_proc (handle, &cookie); +} + void -mono_load_coree () +mono_load_coree (const char* exe_file_name) { gunichar2* file_name; UINT required_size; @@ -464,6 +587,9 @@ mono_load_coree () if (coree_module_handle) return; + if (!init_from_coree && exe_file_name) + mono_set_act_ctx (exe_file_name); + /* ntdll.dll loads mscoree.dll from the system32 directory. */ required_size = GetSystemDirectory (NULL, 0); file_name = g_new (gunichar2, required_size + 12); @@ -485,7 +611,7 @@ mono_load_coree () void mono_fixup_exe_image (MonoImage* image) { - if (image && image->is_module_handle && (HMODULE) image->raw_data != GetModuleHandle (NULL)) + if (!init_from_coree && image && image->is_module_handle) MonoFixupExe ((HMODULE) image->raw_data); } diff --git a/mono/metadata/coree.h b/mono/metadata/coree.h index 7420bc37dc0..550ee1c6984 100644 --- a/mono/metadata/coree.h +++ b/mono/metadata/coree.h @@ -17,18 +17,21 @@ #include #include "image.h" +#define STATUS_SUCCESS 0x00000000L +#define STATUS_INVALID_IMAGE_FORMAT 0xC000007BL + STDAPI MonoFixupCorEE(HMODULE ModuleHandle); STDAPI MonoFixupExe(HMODULE ModuleHandle); -extern HMODULE mono_module_handle; -extern HMODULE coree_module_handle; +extern HMODULE mono_module_handle MONO_INTERNAL; +extern HMODULE coree_module_handle MONO_INTERNAL; -gchar* mono_get_module_file_name (HMODULE module_handle); -void mono_load_coree (); -void mono_fixup_exe_image (MonoImage* image); +gchar* mono_get_module_file_name (HMODULE module_handle) MONO_INTERNAL; +void mono_load_coree (const char* file_name) MONO_INTERNAL; +void mono_fixup_exe_image (MonoImage* image) MONO_INTERNAL; /* Declared in image.c. */ -MonoImage* mono_image_open_from_module_handle (HMODULE module_handle, const char* fname, MonoImageOpenStatus* status); +MonoImage* mono_image_open_from_module_handle (HMODULE module_handle, char* fname, int ref_count, MonoImageOpenStatus* status) MONO_INTERNAL; #endif /* PLATFORM_WIN32 */ diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index 43572d711ed..1b88a55c1ba 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -232,6 +232,9 @@ mono_init_com_types (void) MONO_INTERNAL; void mono_cleanup (void) MONO_INTERNAL; +void +mono_close_exe_image (void) MONO_INTERNAL; + void mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) MONO_INTERNAL; diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 07e4e6d27a9..d5526b3758a 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -1161,11 +1161,8 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * if (domain) g_assert_not_reached (); - /* FIXME: This causes Win32 build to break. */ -#if 0 #if defined(PLATFORM_WIN32) && !defined(_WIN64) - mono_load_coree (); -#endif + mono_load_coree (exe_filename); #endif mono_perfcounters_init (); @@ -1205,6 +1202,11 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * */ get_runtimes_from_exe (exe_filename, &exe_image, runtimes); #ifdef PLATFORM_WIN32 + if (!exe_image) { + exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE); + if (!exe_image) + exe_image = mono_image_open (exe_filename, NULL); + } mono_fixup_exe_image (exe_image); #endif } else if (runtime_version != NULL) { @@ -1610,8 +1612,7 @@ mono_init_com_types (void) void mono_cleanup (void) { - if (exe_image) - mono_image_close (exe_image); + mono_close_exe_image (); mono_loader_cleanup (); mono_classes_cleanup (); @@ -1625,6 +1626,13 @@ mono_cleanup (void) DeleteCriticalSection (&appdomains_mutex); } +void +mono_close_exe_image (void) +{ + if (exe_image) + mono_image_close (exe_image); +} + /** * mono_get_root_domain: * diff --git a/mono/metadata/image.c b/mono/metadata/image.c index e138642eda9..f0c4dd290e1 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -24,6 +24,7 @@ #include "metadata-internals.h" #include "profiler-private.h" #include "loader.h" +#include "marshal.h" #include "coree.h" #include #include @@ -1078,11 +1079,10 @@ mono_image_open_from_data (char *data, guint32 data_len, gboolean need_copy, Mon #ifdef PLATFORM_WIN32 /* fname is not duplicated. */ MonoImage* -mono_image_open_from_module_handle (HMODULE module_handle, const char* fname, MonoImageOpenStatus* status) +mono_image_open_from_module_handle (HMODULE module_handle, char* fname, int ref_count, MonoImageOpenStatus* status) { MonoImage* image; MonoCLIImageInfo* iinfo; - guint16* fname_utf16; image = g_new0 (MonoImage, 1); image->raw_data = (char*) module_handle; @@ -1090,10 +1090,10 @@ mono_image_open_from_module_handle (HMODULE module_handle, const char* fname, Mo iinfo = g_new0 (MonoCLIImageInfo, 1); image->image_info = iinfo; image->name = fname; - image->ref_count = 1; + image->ref_count = ref_count; image = do_mono_image_load (image, status, TRUE); - image = register_image (image); + return register_image (image); } #endif @@ -1111,42 +1111,66 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r if (!refonly && coree_module_handle) { HMODULE module_handle; guint16 *fname_utf16; + DWORD last_error; absfname = mono_path_resolve_symlinks (fname); + fname_utf16 = NULL; /* There is little overhead because the OS loader lock is held by LoadLibrary. */ mono_images_lock (); image = g_hash_table_lookup (loaded_images_hash, absfname); if (image) { + g_assert (image->is_module_handle); + if (image->ref_count == 0) { + MonoCLIImageInfo *iinfo = image->image_info; + + if (iinfo->cli_header.coff.coff_attributes & COFF_ATTRIBUTE_LIBRARY_IMAGE) { + /* Increment reference count on images loaded outside of the runtime. */ + fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL); + module_handle = LoadLibrary (fname_utf16); + g_assert (module_handle != NULL); + } + } mono_image_addref (image); mono_images_unlock (); + if (fname_utf16) + g_free (fname_utf16); g_free (absfname); return image; } fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL); module_handle = LoadLibrary (fname_utf16); + if (status && module_handle == NULL) + last_error = GetLastError (); /* mono_image_open_from_module_handle is called by _CorDllMain. */ image = g_hash_table_lookup (loaded_images_hash, absfname); + if (image) + mono_image_addref (image); mono_images_unlock (); g_free (fname_utf16); - if (image) { - /* No mono_image_addref required. */; + if (module_handle == NULL) { + g_assert (!image); g_free (absfname); - return image; + if (status) { + if (last_error == ERROR_BAD_EXE_FORMAT || last_error == STATUS_INVALID_IMAGE_FORMAT) + *status = MONO_IMAGE_IMAGE_INVALID; + else + *status = MONO_IMAGE_ERROR_ERRNO; + } + return NULL; } - if (module_handle == NULL) { + if (image) { + g_assert (image->is_module_handle); g_free (absfname); - if (status) - *status = MONO_IMAGE_ERROR_ERRNO; - return NULL; + return image; } - return mono_image_open_from_module_handle (module_handle, absfname, status); + return mono_image_open_from_module_handle (module_handle, absfname, 1, status); } #endif @@ -1332,6 +1356,23 @@ mono_image_close (MonoImage *image) if (InterlockedDecrement (&image->ref_count) > 0) return; +#ifdef PLATFORM_WIN32 + if (image->is_module_handle) { + MonoCLIImageInfo *iinfo = image->image_info; + + if (iinfo->cli_header.coff.coff_attributes & COFF_ATTRIBUTE_LIBRARY_IMAGE) { + mono_images_lock (); + if (image->ref_count == 0) { + /* Image will be closed by _CorDllMain. */ + FreeLibrary ((HMODULE) image->raw_data); + mono_images_unlock (); + return; + } + mono_images_unlock (); + } + } +#endif + mono_profiler_module_event (image, MONO_PROFILE_START_UNLOAD); mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading image %s [%p].", image->name, image); @@ -1365,13 +1406,17 @@ mono_image_close (MonoImage *image) if (image->assembly_name && (g_hash_table_lookup (loaded_images, image->assembly_name) == image)) g_hash_table_remove (loaded_images, (char *) image->assembly_name); - mono_images_unlock (); - #ifdef PLATFORM_WIN32 - if (image->is_module_handle) - FreeLibrary ((HMODULE) image->raw_data); + if (image->is_module_handle) { + MonoCLIImageInfo *iinfo = image->image_info; + + if (!(iinfo->cli_header.coff.coff_attributes & COFF_ATTRIBUTE_LIBRARY_IMAGE)) + FreeLibrary ((HMODULE) image->raw_data); + } #endif + mono_images_unlock (); + if (image->raw_buffer_used) { if (image->raw_data != NULL) mono_raw_buffer_free (image->raw_data); diff --git a/mono/utils/ChangeLog b/mono/utils/ChangeLog index c836ebb12f8..ef4a198d329 100644 --- a/mono/utils/ChangeLog +++ b/mono/utils/ChangeLog @@ -1,3 +1,10 @@ +2008-05-14 Kornél Pál + + * mono-path.c (mono_path_canonicalize): Convert '/' to '\' on Windows that + fixes path canonicalization for paths containing '/'. + + Contributed under MIT/X11 license. + 2008-05-04 Andreas Faerber * mono-membar.h: Prepare support for OSX/ppc64. diff --git a/mono/utils/mono-path.c b/mono/utils/mono-path.c index 35497a90e43..f13c9b04c82 100644 --- a/mono/utils/mono-path.c +++ b/mono/utils/mono-path.c @@ -39,6 +39,9 @@ mono_path_canonicalize (const char *path) g_free (tmpdir); } +#ifdef PLATFORM_WIN32 + g_strdelimit (abspath, "/", '\\'); +#endif abspath = g_strreverse (abspath); backc = 0; -- 2.25.1