From 5233231e65c421c5c3428a6f5844dcdbe3998c40 Mon Sep 17 00:00:00 2001 From: lateralusX Date: Tue, 4 Oct 2016 14:45:43 +0200 Subject: [PATCH] Build libmonoutils under none desktop Windows API family. Initial work to build libmonoutils under none desktop Windows API families. --- mono/utils/Makefile.am | 7 + mono/utils/atomic.c | 4 + mono/utils/mono-compiler.h | 3 - mono/utils/mono-dl-windows-uwp.c | 44 ++++++ mono/utils/mono-dl-windows.c | 42 ++++-- mono/utils/mono-dl-windows.h | 14 ++ mono/utils/mono-io-portability.c | 7 + mono/utils/mono-log-common.c | 3 +- mono/utils/mono-log-windows.c | 5 +- mono/utils/mono-logger.c | 2 +- mono/utils/mono-mmap-internals.h | 12 +- mono/utils/mono-mmap-windows-uwp.c | 57 +++++++ mono/utils/mono-mmap-windows.c | 204 ++++++++++++++++++++++++++ mono/utils/mono-mmap-windows.h | 15 ++ mono/utils/mono-mmap.c | 198 ++----------------------- mono/utils/mono-proclib-windows-uwp.c | 64 ++++++++ mono/utils/mono-proclib-windows.c | 74 ++++++++++ mono/utils/mono-proclib-windows.h | 13 ++ mono/utils/mono-proclib.c | 47 ++---- mono/utils/mono-rand-windows-uwp.c | 52 +++++++ mono/utils/mono-rand-windows.c | 172 ++++++++++++++++++++++ mono/utils/mono-rand-windows.h | 33 +++++ mono/utils/mono-rand.c | 121 +-------------- mono/utils/networking-missing.c | 6 + msvc/libmonoutils.vcxproj | 9 +- msvc/libmonoutils.vcxproj.filters | 21 +++ 26 files changed, 862 insertions(+), 367 deletions(-) create mode 100644 mono/utils/mono-dl-windows-uwp.c create mode 100644 mono/utils/mono-dl-windows.h create mode 100644 mono/utils/mono-mmap-windows-uwp.c create mode 100644 mono/utils/mono-mmap-windows.c create mode 100644 mono/utils/mono-mmap-windows.h create mode 100644 mono/utils/mono-proclib-windows-uwp.c create mode 100644 mono/utils/mono-proclib-windows.c create mode 100644 mono/utils/mono-proclib-windows.h create mode 100644 mono/utils/mono-rand-windows-uwp.c create mode 100644 mono/utils/mono-rand-windows.c create mode 100644 mono/utils/mono-rand-windows.h diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am index 3e29ab15df46..5bc5bbd60032 100644 --- a/mono/utils/Makefile.am +++ b/mono/utils/Makefile.am @@ -27,6 +27,7 @@ monoutils_sources = \ mono-dl-darwin.c \ mono-dl-posix.c \ mono-dl.h \ + mono-dl-windows.h \ mono-log-windows.c \ mono-log-common.c \ mono-log-posix.c \ @@ -40,8 +41,10 @@ monoutils_sources = \ mono-filemap.c \ mono-math.c \ mono-mmap.c \ + mono-mmap-windows.c \ mono-mmap.h \ mono-mmap-internals.h \ + mono-mmap-windows.h \ mono-os-mutex.h \ mono-coop-mutex.h \ mono-once.h \ @@ -49,7 +52,9 @@ monoutils_sources = \ mono-networkinterfaces.c \ mono-networkinterfaces.h \ mono-proclib.c \ + mono-proclib-windows.c \ mono-proclib.h \ + mono-proclib-windows.h \ mono-publib.c \ mono-string.h \ mono-time.c \ @@ -149,7 +154,9 @@ monoutils_sources = \ networking-windows.c \ networking.h \ mono-rand.c \ + mono-rand-windows.c \ mono-rand.h \ + mono-rand-windows.h \ memfuncs.c \ memfuncs.h \ parse.c \ diff --git a/mono/utils/atomic.c b/mono/utils/atomic.c index 86afad502ffe..2f5e8a8a673a 100644 --- a/mono/utils/atomic.c +++ b/mono/utils/atomic.c @@ -581,6 +581,10 @@ InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp) return(old); } +#endif #endif +#if defined(HOST_WIN32) && defined(_MSC_VER) +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_atomic_lnk4221(void) {} #endif diff --git a/mono/utils/mono-compiler.h b/mono/utils/mono-compiler.h index d03ba8051aa5..0a78e55f8377 100644 --- a/mono/utils/mono-compiler.h +++ b/mono/utils/mono-compiler.h @@ -241,9 +241,6 @@ #include #define mkdir(x) _mkdir(x) -/* GCC specific functions aren't available */ -#define __builtin_return_address(x) NULL - #define __func__ __FUNCTION__ #include diff --git a/mono/utils/mono-dl-windows-uwp.c b/mono/utils/mono-dl-windows-uwp.c new file mode 100644 index 000000000000..8bb8e6c7e08c --- /dev/null +++ b/mono/utils/mono-dl-windows-uwp.c @@ -0,0 +1,44 @@ +/* + * mono-dl-windows-uwp.c: UWP dl support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include + +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#include +#include "mono/utils/mono-dl-windows.h" + +void* +mono_dl_lookup_symbol_in_process (const char *symbol_name) +{ + g_unsupported_api ("EnumProcessModules"); + SetLastError (ERROR_NOT_SUPPORTED); + + return NULL; +} + +char* +mono_dl_current_error_string (void) +{ + char *ret = NULL; + TCHAR buf [1024]; + DWORD code = GetLastError (); + + if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, G_N_ELEMENTS(buf) - 1, NULL)) + buf[0] = TEXT('\0'); + + ret = u16to8 (buf); + return ret; +} + +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_mono_dl_windows_uwp_quiet_lnk4221(void) {} +#endif +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-dl-windows.c b/mono/utils/mono-dl-windows.c index 9e3efa796f7a..04f695d22de3 100644 --- a/mono/utils/mono-dl-windows.c +++ b/mono/utils/mono-dl-windows.c @@ -13,6 +13,7 @@ #if defined(HOST_WIN32) #include "mono/utils/mono-dl.h" +#include "mono/utils/mono-dl-windows.h" #include "mono/utils/mono-embed.h" #include "mono/utils/mono-path.h" @@ -25,7 +26,6 @@ #include #include - const char* mono_dl_get_so_prefix (void) { @@ -48,14 +48,20 @@ mono_dl_open_file (const char *file, int flags) gpointer hModule = NULL; if (file) { gunichar2* file_utf16 = g_utf8_to_utf16 (file, strlen (file), NULL, NULL, NULL); + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) guint last_sem = SetErrorMode (SEM_FAILCRITICALERRORS); +#endif guint32 last_error = 0; hModule = LoadLibrary (file_utf16); if (!hModule) last_error = GetLastError (); +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) SetErrorMode (last_sem); +#endif + g_free (file_utf16); if (!hModule) @@ -73,23 +79,15 @@ mono_dl_close_handle (MonoDl *module) FreeLibrary (module->handle); } +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) void* -mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name) +mono_dl_lookup_symbol_in_process (const char *symbol_name) { HMODULE *modules; DWORD buffer_size = sizeof (HMODULE) * 1024; DWORD needed, i; gpointer proc = NULL; - /* get the symbol directly from the specified module */ - if (!module->main_module) - return GetProcAddress (module->handle, symbol_name); - - /* get the symbol from the main module */ - proc = GetProcAddress (module->handle, symbol_name); - if (proc != NULL) - return proc; - /* get the symbol from the loaded DLLs */ modules = (HMODULE *) g_malloc (buffer_size); if (modules == NULL) @@ -129,6 +127,25 @@ mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name) g_free (modules); return NULL; } +#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ + +void* +mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name) +{ + gpointer proc = NULL; + + /* get the symbol directly from the specified module */ + if (!module->main_module) + return GetProcAddress (module->handle, symbol_name); + + /* get the symbol from the main module */ + proc = GetProcAddress (module->handle, symbol_name); + if (proc != NULL) + return proc; + + /* get the symbol from the loaded DLLs */ + return mono_dl_lookup_symbol_in_process (symbol_name); +} int mono_dl_convert_flags (int flags) @@ -136,6 +153,7 @@ mono_dl_convert_flags (int flags) return 0; } +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) char* mono_dl_current_error_string (void) { @@ -153,6 +171,7 @@ mono_dl_current_error_string (void) } return ret; } +#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ int mono_dl_get_executable_path (char *buf, int buflen) @@ -165,5 +184,4 @@ mono_dl_get_system_dir (void) { return NULL; } - #endif diff --git a/mono/utils/mono-dl-windows.h b/mono/utils/mono-dl-windows.h new file mode 100644 index 000000000000..521541804882 --- /dev/null +++ b/mono/utils/mono-dl-windows.h @@ -0,0 +1,14 @@ +#ifndef __MONO_UTILS_DL_WINDOWS_H__ +#define __MONO_UTILS_DL_WINDOWS_H__ + +#include +#include + +#ifdef HOST_WIN32 +#include "mono/utils/mono-dl.h" + +void* +mono_dl_lookup_symbol_in_process (const char *symbol_name); +#endif /* HOST_WIN32 */ +#endif /* __MONO_UTILS_DL_WINDOWS_H__ */ + diff --git a/mono/utils/mono-io-portability.c b/mono/utils/mono-io-portability.c index 54c6320d2b6f..f423096a7800 100644 --- a/mono/utils/mono-io-portability.c +++ b/mono/utils/mono-io-portability.c @@ -387,4 +387,11 @@ static inline gchar *mono_portability_find_file_internal (GString **report, cons g_free (new_pathname); return(NULL); } + +#else /* DISABLE_PORTABILITY */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_mono_io_portability_quiet_lnk4221(void) {} #endif +#endif /* DISABLE_PORTABILITY */ diff --git a/mono/utils/mono-log-common.c b/mono/utils/mono-log-common.c index 4948b91b80fb..bdb6dffb50e2 100644 --- a/mono/utils/mono-log-common.c +++ b/mono/utils/mono-log-common.c @@ -26,6 +26,7 @@ #include #endif #include "mono-logger-internals.h" +#include "mono-proclib.h" static FILE *logFile = NULL; static void *logUserData = NULL; @@ -119,7 +120,7 @@ mono_log_write_logfile (const char *log_domain, GLogLevelFlags level, mono_bool struct tm *tod; time(&t); tod = localtime(&t); - pid = _getpid(); + pid = mono_process_current_pid (); strftime(logTime, sizeof(logTime), "%F %T", tod); #endif fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message); diff --git a/mono/utils/mono-log-windows.c b/mono/utils/mono-log-windows.c index f6cd987fbba8..ab5db470e194 100644 --- a/mono/utils/mono-log-windows.c +++ b/mono/utils/mono-log-windows.c @@ -24,6 +24,7 @@ #include #include #include "mono-logger-internals.h" +#include "mono-proclib.h" static FILE *logFile = NULL; static void *logUserData = NULL; @@ -88,7 +89,7 @@ void mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, const char *message) { time_t t; - pid_t pid; + int pid; char logTime [80]; if (logFile == NULL) @@ -97,7 +98,7 @@ mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, c struct tm *tod; time(&t); tod = localtime(&t); - pid = _getpid(); + pid = mono_process_current_pid (); strftime(logTime, sizeof(logTime), "%F %T", tod); fprintf (logFile, "%s level[%c] mono[%d]: %s\n", logTime, mapLogFileLevel (level), pid, message); diff --git a/mono/utils/mono-logger.c b/mono/utils/mono-logger.c index b4367a73367d..5cc59c77fbe6 100644 --- a/mono/utils/mono-logger.c +++ b/mono/utils/mono-logger.c @@ -291,7 +291,7 @@ mono_trace_set_mask_string (const char *value) continue; } for (i = 0; valid_flags[i]; i++) { - int len = strlen (valid_flags[i]); + size_t len = strlen (valid_flags[i]); if (strncmp (tok, valid_flags[i], len) == 0 && (tok[len] == 0 || tok[len] == ',')) { flags |= valid_masks[i]; tok += len; diff --git a/mono/utils/mono-mmap-internals.h b/mono/utils/mono-mmap-internals.h index faca70b8ca95..90695609f087 100644 --- a/mono/utils/mono-mmap-internals.h +++ b/mono/utils/mono-mmap-internals.h @@ -11,7 +11,17 @@ #include "mono-compiler.h" -int mono_pages_not_faulted (void *addr, size_t length); +void * +malloc_shared_area (int pid); + +char* +aligned_address (char *mem, size_t size, size_t alignment); + +void +account_mem (MonoMemAccountType type, ssize_t size); + +int +mono_pages_not_faulted (void *addr, size_t length); #endif /* __MONO_UTILS_MMAP_INTERNAL_H__ */ diff --git a/mono/utils/mono-mmap-windows-uwp.c b/mono/utils/mono-mmap-windows-uwp.c new file mode 100644 index 000000000000..55652006d5af --- /dev/null +++ b/mono/utils/mono-mmap-windows-uwp.c @@ -0,0 +1,57 @@ +/* + * mono-dl-windows-uwp.c: UWP dl support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include + +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#include +#include + +void* +mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle) +{ + void *ptr; + int mflags = 0; + HANDLE file, mapping; + int prot = mono_mmap_win_prot_from_flags (flags); + + mflags = FILE_MAP_READ; + if (flags & MONO_MMAP_WRITE) + mflags = FILE_MAP_COPY; + + file = (HANDLE) _get_osfhandle (fd); + mapping = CreateFileMappingFromApp (file, NULL, prot, length, NULL); + + if (mapping == NULL) + return NULL; + + ptr = MapViewOfFileFromApp (mapping, mflags, offset, length); + + if (ptr == NULL) { + CloseHandle (mapping); + return NULL; + } + + *ret_handle = (void*)mapping; + return ptr; +} + +int +mono_file_unmap (void *addr, void *handle) +{ + UnmapViewOfFile (addr); + CloseHandle ((HANDLE)handle); + return 0; +} + +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_mono_mmap_windows_uwp_quiet_lnk4221(void) {} +#endif +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-mmap-windows.c b/mono/utils/mono-mmap-windows.c new file mode 100644 index 000000000000..6fe7766a45af --- /dev/null +++ b/mono/utils/mono-mmap-windows.c @@ -0,0 +1,204 @@ +/* + * mono-mmap-windows.c: Windows support for mapping code into the process address space + * + * Author: + * Mono Team (mono-list@lists.ximian.com) + * + * Copyright 2001-2008 Novell, Inc. + * Licensed under the MIT license. See LICENSE file in the project root for full license information. + */ + +#include +#include + +#if defined(HOST_WIN32) +#include +#include "mono/utils/mono-mmap-windows.h" +#include +#include + +static void *malloced_shared_area = NULL; + +int +mono_pagesize (void) +{ + SYSTEM_INFO info; + static int saved_pagesize = 0; + if (saved_pagesize) + return saved_pagesize; + GetSystemInfo (&info); + saved_pagesize = info.dwAllocationGranularity; + return saved_pagesize; +} + +int +mono_mmap_win_prot_from_flags (int flags) +{ + int prot = flags & (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC); + switch (prot) { + case 0: prot = PAGE_NOACCESS; break; + case MONO_MMAP_READ: prot = PAGE_READONLY; break; + case MONO_MMAP_READ|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READ; break; + case MONO_MMAP_READ|MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; + case MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; + case MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; + case MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; + case MONO_MMAP_EXEC: prot = PAGE_EXECUTE; break; + default: + g_assert_not_reached (); + } + return prot; +} + +void* +mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type) +{ + void *ptr; + int mflags = MEM_RESERVE|MEM_COMMIT; + int prot = mono_mmap_win_prot_from_flags (flags); + /* translate the flags */ + + ptr = VirtualAlloc (addr, length, mflags, prot); + + account_mem (type, (ssize_t)length); + + return ptr; +} + +void* +mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type) +{ + int prot = mono_mmap_win_prot_from_flags (flags); + char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot); + char *aligned; + + if (!mem) + return NULL; + + aligned = aligned_address (mem, length, alignment); + + aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot); + g_assert (aligned); + + account_mem (type, (ssize_t)length); + + return aligned; +} + +int +mono_vfree (void *addr, size_t length, MonoMemAccountType type) +{ + MEMORY_BASIC_INFORMATION mbi; + SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi)); + BOOL res; + + g_assert (query_result); + + res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE); + + g_assert (res); + + account_mem (type, -(ssize_t)length); + + return 0; +} + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +void* +mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle) +{ + void *ptr; + int mflags = 0; + HANDLE file, mapping; + int prot = mono_mmap_win_prot_from_flags (flags); + /* translate the flags */ + /*if (flags & MONO_MMAP_PRIVATE) + mflags |= MAP_PRIVATE; + if (flags & MONO_MMAP_SHARED) + mflags |= MAP_SHARED; + if (flags & MONO_MMAP_ANON) + mflags |= MAP_ANONYMOUS; + if (flags & MONO_MMAP_FIXED) + mflags |= MAP_FIXED; + if (flags & MONO_MMAP_32BIT) + mflags |= MAP_32BIT;*/ + + mflags = FILE_MAP_READ; + if (flags & MONO_MMAP_WRITE) + mflags = FILE_MAP_COPY; + + file = (HANDLE) _get_osfhandle (fd); + + mapping = CreateFileMapping (file, NULL, prot, 0, 0, NULL); + + if (mapping == NULL) + return NULL; + + ptr = MapViewOfFile (mapping, mflags, 0, offset, length); + + if (ptr == NULL) { + CloseHandle (mapping); + return NULL; + } + *ret_handle = (void*)mapping; + return ptr; +} + +int +mono_file_unmap (void *addr, void *handle) +{ + UnmapViewOfFile (addr); + CloseHandle ((HANDLE)handle); + return 0; +} +#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ + +int +mono_mprotect (void *addr, size_t length, int flags) +{ + DWORD oldprot; + int prot = mono_mmap_win_prot_from_flags (flags); + + if (flags & MONO_MMAP_DISCARD) { + VirtualFree (addr, length, MEM_DECOMMIT); + VirtualAlloc (addr, length, MEM_COMMIT, prot); + return 0; + } + return VirtualProtect (addr, length, prot, &oldprot) == 0; +} + +void* +mono_shared_area (void) +{ + if (!malloced_shared_area) + malloced_shared_area = malloc_shared_area (0); + /* get the pid here */ + return malloced_shared_area; +} + +void +mono_shared_area_remove (void) +{ + if (malloced_shared_area) + g_free (malloced_shared_area); + malloced_shared_area = NULL; +} + +void* +mono_shared_area_for_pid (void *pid) +{ + return NULL; +} + +void +mono_shared_area_unload (void *area) +{ +} + +int +mono_shared_area_instances (void **array, int count) +{ + return 0; +} + +#endif diff --git a/mono/utils/mono-mmap-windows.h b/mono/utils/mono-mmap-windows.h new file mode 100644 index 000000000000..44da254692b2 --- /dev/null +++ b/mono/utils/mono-mmap-windows.h @@ -0,0 +1,15 @@ +#ifndef __MONO_UTILS_MMAP_WINDOWS_H__ +#define __MONO_UTILS_MMAP_WINDOWS_H__ + +#include +#include + +#ifdef HOST_WIN32 +#include "mono/utils/mono-mmap.h" +#include "mono/utils/mono-mmap-internals.h" + +int +mono_mmap_win_prot_from_flags (int flags); +#endif /* HOST_WIN32 */ +#endif /* __MONO_UTILS_MMAP_WINDOWS_H__ */ + diff --git a/mono/utils/mono-mmap.c b/mono/utils/mono-mmap.c index 491318465faf..91fe5a12def4 100644 --- a/mono/utils/mono-mmap.c +++ b/mono/utils/mono-mmap.c @@ -8,12 +8,9 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ -#include "config.h" +#include -#ifdef HOST_WIN32 -#include -#include -#else +#ifndef HOST_WIN32 #include #if HAVE_SYS_STAT_H #include @@ -29,7 +26,7 @@ #include #include #include -#endif +#endif /* !HOST_WIN32 */ #include "mono-mmap.h" #include "mono-mmap-internals.h" @@ -38,7 +35,6 @@ #include #include - #define BEGIN_CRITICAL_SECTION do { \ MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \ if (__info) __info->inside_critical_region = TRUE; \ @@ -63,9 +59,7 @@ typedef struct { short stats_end; } SAreaHeader; -static void* malloced_shared_area = NULL; - -static void* +void* malloc_shared_area (int pid) { int size = mono_pagesize (); @@ -78,7 +72,7 @@ malloc_shared_area (int pid) return sarea; } -static char* +char* aligned_address (char *mem, size_t size, size_t alignment) { char *aligned = (char*)((size_t)(mem + (alignment - 1)) & ~(alignment - 1)); @@ -88,7 +82,7 @@ aligned_address (char *mem, size_t size, size_t alignment) static volatile size_t allocation_count [MONO_MEM_ACCOUNT_MAX]; -static void +void account_mem (MonoMemAccountType type, ssize_t size) { #if SIZEOF_VOID_P == 4 @@ -135,186 +129,12 @@ mono_mem_account_register_counters (void) } #ifdef HOST_WIN32 - -int -mono_pagesize (void) -{ - SYSTEM_INFO info; - static int saved_pagesize = 0; - if (saved_pagesize) - return saved_pagesize; - GetSystemInfo (&info); - saved_pagesize = info.dwAllocationGranularity; - return saved_pagesize; -} - -static int -prot_from_flags (int flags) -{ - int prot = flags & (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC); - switch (prot) { - case 0: prot = PAGE_NOACCESS; break; - case MONO_MMAP_READ: prot = PAGE_READONLY; break; - case MONO_MMAP_READ|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READ; break; - case MONO_MMAP_READ|MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; - case MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; - case MONO_MMAP_WRITE: prot = PAGE_READWRITE; break; - case MONO_MMAP_WRITE|MONO_MMAP_EXEC: prot = PAGE_EXECUTE_READWRITE; break; - case MONO_MMAP_EXEC: prot = PAGE_EXECUTE; break; - default: - g_assert_not_reached (); - } - return prot; -} - -void* -mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type) -{ - void *ptr; - int mflags = MEM_RESERVE|MEM_COMMIT; - int prot = prot_from_flags (flags); - /* translate the flags */ - - ptr = VirtualAlloc (addr, length, mflags, prot); - - account_mem (type, (ssize_t)length); - - return ptr; -} - -void* -mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type) -{ - int prot = prot_from_flags (flags); - char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot); - char *aligned; - - if (!mem) - return NULL; - - aligned = aligned_address (mem, length, alignment); - - aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot); - g_assert (aligned); - - account_mem (type, (ssize_t)length); - - return aligned; -} - +// Windows specific implementation in mono-mmap-windows.c #define HAVE_VALLOC_ALIGNED -int -mono_vfree (void *addr, size_t length, MonoMemAccountType type) -{ - MEMORY_BASIC_INFORMATION mbi; - SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi)); - BOOL res; - - g_assert (query_result); - - res = VirtualFree (mbi.AllocationBase, 0, MEM_RELEASE); - - g_assert (res); - - account_mem (type, -(ssize_t)length); - - return 0; -} - -void* -mono_file_map (size_t length, int flags, int fd, guint64 offset, void **ret_handle) -{ - void *ptr; - int mflags = 0; - HANDLE file, mapping; - int prot = prot_from_flags (flags); - /* translate the flags */ - /*if (flags & MONO_MMAP_PRIVATE) - mflags |= MAP_PRIVATE; - if (flags & MONO_MMAP_SHARED) - mflags |= MAP_SHARED; - if (flags & MONO_MMAP_ANON) - mflags |= MAP_ANONYMOUS; - if (flags & MONO_MMAP_FIXED) - mflags |= MAP_FIXED; - if (flags & MONO_MMAP_32BIT) - mflags |= MAP_32BIT;*/ - - mflags = FILE_MAP_READ; - if (flags & MONO_MMAP_WRITE) - mflags = FILE_MAP_COPY; - - file = (HANDLE) _get_osfhandle (fd); - mapping = CreateFileMapping (file, NULL, prot, 0, 0, NULL); - if (mapping == NULL) - return NULL; - ptr = MapViewOfFile (mapping, mflags, 0, offset, length); - if (ptr == NULL) { - CloseHandle (mapping); - return NULL; - } - *ret_handle = (void*)mapping; - return ptr; -} - -int -mono_file_unmap (void *addr, void *handle) -{ - UnmapViewOfFile (addr); - CloseHandle ((HANDLE)handle); - return 0; -} - -int -mono_mprotect (void *addr, size_t length, int flags) -{ - DWORD oldprot; - int prot = prot_from_flags (flags); - - if (flags & MONO_MMAP_DISCARD) { - VirtualFree (addr, length, MEM_DECOMMIT); - VirtualAlloc (addr, length, MEM_COMMIT, prot); - return 0; - } - return VirtualProtect (addr, length, prot, &oldprot) == 0; -} - -void* -mono_shared_area (void) -{ - if (!malloced_shared_area) - malloced_shared_area = malloc_shared_area (0); - /* get the pid here */ - return malloced_shared_area; -} - -void -mono_shared_area_remove (void) -{ - if (malloced_shared_area) - g_free (malloced_shared_area); - malloced_shared_area = NULL; -} - -void* -mono_shared_area_for_pid (void *pid) -{ - return NULL; -} - -void -mono_shared_area_unload (void *area) -{ -} - -int -mono_shared_area_instances (void **array, int count) -{ - return 0; -} - #else + +static void* malloced_shared_area = NULL; #if defined(HAVE_MMAP) /** diff --git a/mono/utils/mono-proclib-windows-uwp.c b/mono/utils/mono-proclib-windows-uwp.c new file mode 100644 index 000000000000..e278eccede20 --- /dev/null +++ b/mono/utils/mono-proclib-windows-uwp.c @@ -0,0 +1,64 @@ +/* + * mono-proclib-windows-uwp.c: UWP proclib support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include + +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#include +#include + +gint32 +mono_cpu_usage (MonoCpuUsageState *prev) +{ + gint32 cpu_usage = 0; + gint64 cpu_total_time; + gint64 cpu_busy_time; + guint64 idle_time; + guint64 kernel_time; + guint64 user_time; + guint64 current_time; + guint64 creation_time; + guint64 exit_time; + + GetSystemTimeAsFileTime ((FILETIME*)¤t_time); + if (!GetProcessTimes (GetCurrentProcess (), (FILETIME*)&creation_time, (FILETIME*)&exit_time, (FILETIME*)&kernel_time, (FILETIME*)&user_time)) { + g_error ("GetProcessTimes() failed, error code is %d\n", GetLastError ()); + return -1; + } + + // GetProcessTimes user_time is a sum of user time spend by all threads in the process. + // This means that the total user time can be more than real time. In order to adjust for this + // the total available time that we can be scheduled depends on the number of available cores. + // For example, having 2 threads running 100% on a 2 core system for 100 ms will return a user_time of 200ms + // but the current_time - creation_time will only be 100ms but by adjusting the available time based on number of + // of availalbe cores will gives use the total load of the process. + guint64 total_available_time = (current_time - creation_time) * mono_cpu_count (); + + idle_time = total_available_time - (kernel_time + user_time); + + cpu_total_time = (gint64)((idle_time - (prev ? prev->idle_time : 0)) + (user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0))); + cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0))); + + if (prev) { + prev->idle_time = idle_time; + prev->kernel_time = kernel_time; + prev->user_time = user_time; + } + + if (cpu_total_time > 0 && cpu_busy_time > 0) + cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time); + + return cpu_usage; +} + +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_mono_proclib_windows_uwp_quiet_lnk4221(void) {} +#endif +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-proclib-windows.c b/mono/utils/mono-proclib-windows.c new file mode 100644 index 000000000000..6386a510d568 --- /dev/null +++ b/mono/utils/mono-proclib-windows.c @@ -0,0 +1,74 @@ +/* + * mono-proclib-windows.c: Windows proclib support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ + +#include +#include + +#ifdef HOST_WIN32 +#include +#include "mono/utils/mono-proclib.h" + +int +mono_process_current_pid () +{ + return (int) GetCurrentProcessId (); +} + +/** + * mono_cpu_count: + * + * Return the number of processors on the system. + */ +int +mono_cpu_count (void) +{ + SYSTEM_INFO info; + GetSystemInfo (&info); + return info.dwNumberOfProcessors; +} + +/* + * This function returns the cpu usage in percentage, + * normalized on the number of cores. + * + * Warning : the percentage returned can be > 100%. This + * might happens on systems like Android which, for + * battery and performance reasons, shut down cores and + * lie about the number of active cores. + */ +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +gint32 +mono_cpu_usage (MonoCpuUsageState *prev) +{ + gint32 cpu_usage = 0; + gint64 cpu_total_time; + gint64 cpu_busy_time; + guint64 idle_time; + guint64 kernel_time; + guint64 user_time; + + if (!GetSystemTimes ((FILETIME*) &idle_time, (FILETIME*) &kernel_time, (FILETIME*) &user_time)) { + g_error ("GetSystemTimes() failed, error code is %d\n", GetLastError ()); + return -1; + } + + cpu_total_time = (gint64)((user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0))); + cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0))); + + if (prev) { + prev->idle_time = idle_time; + prev->kernel_time = kernel_time; + prev->user_time = user_time; + } + + if (cpu_total_time > 0 && cpu_busy_time > 0) + cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time); + + return cpu_usage; +} +#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ +#endif /* HOST_WIN32*/ diff --git a/mono/utils/mono-proclib-windows.h b/mono/utils/mono-proclib-windows.h new file mode 100644 index 000000000000..f14c7a402b61 --- /dev/null +++ b/mono/utils/mono-proclib-windows.h @@ -0,0 +1,13 @@ +#ifndef __MONO_UTILS_PROCLIB_WINDOWS_H__ +#define __MONO_UTILS_PROCLIB_WINDOWS_H__ + +#include +#include + +#ifdef HOST_WIN32 +#include +#include "mono/utils/mono-proclib.h" + +#endif /* HOST_WIN32 */ +#endif /* __MONO_UTILS_PROCLIB_WINDOWS_H__ */ + diff --git a/mono/utils/mono-proclib.c b/mono/utils/mono-proclib.c index 79da32b45118..9c37ccf2ec11 100644 --- a/mono/utils/mono-proclib.c +++ b/mono/utils/mono-proclib.c @@ -19,11 +19,6 @@ #include #endif -#ifdef HOST_WIN32 -#include -#include -#endif - #if defined(_POSIX_VERSION) #include #include @@ -187,7 +182,7 @@ get_pid_status_item_buf (int pid, const char *item, char *rbuf, int blen, MonoPr char buf [256]; char *s; FILE *f; - int len = strlen (item); + size_t len = strlen (item); g_snprintf (buf, sizeof (buf), "/proc/%d/status", pid); f = fopen (buf, "r"); @@ -286,7 +281,7 @@ mono_process_get_name (gpointer pid, char *buf, int len) char fname [128]; FILE *file; char *p; - int r; + size_t r; sprintf (fname, "/proc/%d/cmdline", GPOINTER_TO_INT (pid)); buf [0] = 0; file = fopen (fname, "r"); @@ -443,7 +438,8 @@ get_process_stat_item (int pid, int pos, int sum, MonoProcessError *error) char buf [512]; char *s, *end; FILE *f; - int len, i; + size_t len; + int i; gint64 value; g_snprintf (buf, sizeof (buf), "/proc/%d/stat", pid); @@ -637,31 +633,27 @@ mono_process_get_data (gpointer pid, MonoProcessData data) return mono_process_get_data_with_error (pid, data, &error); } +#ifndef HOST_WIN32 int mono_process_current_pid () { #if defined(HAVE_UNISTD_H) return (int) getpid (); -#elif defined(HOST_WIN32) - return (int) GetCurrentProcessId (); #else #error getpid #endif } +#endif /* !HOST_WIN32 */ /** * mono_cpu_count: * * Return the number of processors on the system. */ +#ifndef HOST_WIN32 int mono_cpu_count (void) { -#ifdef HOST_WIN32 - SYSTEM_INFO info; - GetSystemInfo (&info); - return info.dwNumberOfProcessors; -#else #ifdef PLATFORM_ANDROID /* Android tries really hard to save power by powering off CPUs on SMP phones which * means the normal way to query cpu count returns a wrong value with userspace API. @@ -779,10 +771,10 @@ mono_cpu_count (void) return count; } #endif -#endif /* HOST_WIN32 */ /* FIXME: warn */ return 1; } +#endif /* !HOST_WIN32 */ static void get_cpu_times (int cpu_id, gint64 *user, gint64 *systemt, gint64 *irq, gint64 *sirq, gint64 *idle) @@ -889,14 +881,13 @@ mono_atexit (void (*func)(void)) * battery and performance reasons, shut down cores and * lie about the number of active cores. */ +#ifndef HOST_WIN32 gint32 mono_cpu_usage (MonoCpuUsageState *prev) { gint32 cpu_usage = 0; gint64 cpu_total_time; gint64 cpu_busy_time; - -#ifndef HOST_WIN32 struct rusage resource_usage; gint64 current_time; gint64 kernel_time; @@ -919,28 +910,10 @@ mono_cpu_usage (MonoCpuUsageState *prev) prev->user_time = user_time; prev->current_time = current_time; } -#else - guint64 idle_time; - guint64 kernel_time; - guint64 user_time; - - if (!GetSystemTimes ((FILETIME*) &idle_time, (FILETIME*) &kernel_time, (FILETIME*) &user_time)) { - g_error ("GetSystemTimes() failed, error code is %d\n", GetLastError ()); - return -1; - } - - cpu_total_time = (gint64)((user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0))); - cpu_busy_time = (gint64)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0))); - - if (prev) { - prev->idle_time = idle_time; - prev->kernel_time = kernel_time; - prev->user_time = user_time; - } -#endif if (cpu_total_time > 0 && cpu_busy_time > 0) cpu_usage = (gint32)(cpu_busy_time * 100 / cpu_total_time); return cpu_usage; } +#endif /* !HOST_WIN32 */ diff --git a/mono/utils/mono-rand-windows-uwp.c b/mono/utils/mono-rand-windows-uwp.c new file mode 100644 index 000000000000..e9030fe85511 --- /dev/null +++ b/mono/utils/mono-rand-windows-uwp.c @@ -0,0 +1,52 @@ +/* + * mono-rand-windows-uwp.c: UWP rand support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include + +#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) +#include +#include "mono/utils/mono-rand-windows.h" + +MONO_WIN32_CRYPT_PROVIDER_HANDLE +mono_rand_win_open_provider (void) +{ + MONO_WIN32_CRYPT_PROVIDER_HANDLE provider = 0; + + if (!BCRYPT_SUCCESS (BCryptOpenAlgorithmProvider (&provider, BCRYPT_RNG_ALGORITHM, NULL, 0))) + provider = 0; + + return provider; +} + +gboolean +mono_rand_win_gen (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *buffer, size_t buffer_size) +{ + g_assert (provider != 0 && buffer != 0); + return (BCRYPT_SUCCESS (BCryptGenRandom (provider, buffer, (ULONG) buffer_size, 0))) ? TRUE : FALSE; +} + +gboolean +mono_rand_win_seed (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *seed, size_t seed_size) +{ + g_assert (provider != 0 && seed != 0); + return (BCRYPT_SUCCESS (BCryptGenRandom (provider, seed, (ULONG) seed_size, BCRYPT_RNG_USE_ENTROPY_IN_BUFFER))) ? TRUE : FALSE; +} + +void +mono_rand_win_close_provider (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider) +{ + g_assert (provider != 0); + BCryptCloseAlgorithmProvider (provider, 0); +} + +#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_mono_rand_windows_uwp_quiet_lnk4221(void) {} +#endif +#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */ diff --git a/mono/utils/mono-rand-windows.c b/mono/utils/mono-rand-windows.c new file mode 100644 index 000000000000..2ff32a99fa15 --- /dev/null +++ b/mono/utils/mono-rand-windows.c @@ -0,0 +1,172 @@ +/* + * mono-rand-windows.c: Windows rand support for Mono. + * + * Copyright 2016 Microsoft + * Licensed under the MIT license. See LICENSE file in the project root for full license information. +*/ +#include +#include +#include "mono-error.h" +#include "mono-error-internals.h" +#include "mono-rand.h" + +#if defined(HOST_WIN32) +#include +#include "mono/utils/mono-rand-windows.h" + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +#ifndef PROV_INTEL_SEC +#define PROV_INTEL_SEC 22 +#endif +#ifndef CRYPT_VERIFY_CONTEXT +#define CRYPT_VERIFY_CONTEXT 0xF0000000 +#endif + +MONO_WIN32_CRYPT_PROVIDER_HANDLE +mono_rand_win_open_provider (void) +{ + MONO_WIN32_CRYPT_PROVIDER_HANDLE provider = 0; + + /* There is no need to create a container for just random data, + * so we can use CRYPT_VERIFY_CONTEXT (one call) see: + * http://blogs.msdn.com/dangriff/archive/2003/11/19/51709.aspx */ + + /* We first try to use the Intel PIII RNG if drivers are present */ + if (!CryptAcquireContext (&provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFY_CONTEXT)) { + /* not a PIII or no drivers available, use default RSA CSP */ + if (!CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFY_CONTEXT)) { + /* exception will be thrown in managed code */ + provider = 0; + } + } + + return provider; +} + +void +mono_rand_win_close_provider (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider) +{ + CryptReleaseContext (provider, 0); +} + +gboolean +mono_rand_win_gen (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *buffer, size_t buffer_size) +{ + return CryptGenRandom (provider, (DWORD) buffer_size, buffer); +} + +gboolean +mono_rand_win_seed (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *seed, size_t seed_size) +{ + /* add seeding material to the RNG */ + return CryptGenRandom (provider, (DWORD) seed_size, seed); +} +#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */ + +/** + * mono_rand_open: + * + * Returns: True if random source is global, false if mono_rand_init can be called repeatedly to get randomness instances. + * + * Initializes entire RNG system. Must be called once per process before calling mono_rand_init. + */ +gboolean +mono_rand_open (void) +{ + return FALSE; +} + +/** + * mono_rand_init: + * @seed: A string containing seed data + * @seed_size: Length of seed string + * + * Returns: On success, a non-NULL handle which can be used to fetch random data from mono_rand_try_get_bytes. On failure, NULL. + * + * Initializes an RNG client. + */ +gpointer +mono_rand_init (guchar *seed, gint seed_size) +{ + MONO_WIN32_CRYPT_PROVIDER_HANDLE provider = 0; + + /* try to open crypto provider. */ + provider = mono_rand_win_open_provider (); + + /* seed the CSP with the supplied buffer (if present) */ + if (provider != 0 && seed != NULL) { + /* the call we replace the seed with random - this isn't what is + * expected from the class library user */ + guchar *data = g_malloc (seed_size); + if (data != NULL) { + memcpy (data, seed, seed_size); + /* add seeding material to the RNG */ + mono_rand_win_seed (provider, data, seed_size); + /* zeroize and free */ + memset (data, 0, seed_size); + g_free (data); + } + } + + return (gpointer) provider; +} + +/** + * mono_rand_try_get_bytes: + * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. + * @buffer: A buffer into which to write random data. + * @buffer_size: Number of bytes to write into buffer. + * @error: Set on error. + * + * Returns: FALSE on failure and sets @error, TRUE on success. + * + * Extracts bytes from an RNG handle. + */ +gboolean +mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, MonoError *error) +{ + MONO_WIN32_CRYPT_PROVIDER_HANDLE provider; + + mono_error_init (error); + + g_assert (handle); + provider = (MONO_WIN32_CRYPT_PROVIDER_HANDLE) *handle; + + /* generate random bytes */ + if (!mono_rand_win_gen (provider, buffer, buffer_size)) { + mono_rand_win_close_provider (provider); + /* we may have lost our context with CryptoAPI, but all hope isn't lost yet! */ + provider = mono_rand_win_open_provider (); + if (provider != 0) { + + /* retry generate of random bytes */ + if (!mono_rand_win_gen (provider, buffer, buffer_size)) { + /* failure, close provider */ + mono_rand_win_close_provider (provider); + provider = 0; + } + } + + /* make sure client gets new opened provider handle or NULL on failure */ + *handle = (gpointer) provider; + if (*handle == 0) { + /* exception will be thrown in managed code */ + mono_error_set_execution_engine (error, "Failed to gen random bytes (%d)", GetLastError ()); + return FALSE; + } + } + return TRUE; +} + +/** + * mono_rand_close: + * @handle: An RNG handle. + * + * Releases an RNG handle. + */ +void +mono_rand_close (gpointer handle) +{ + mono_rand_win_close_provider ((MONO_WIN32_CRYPT_PROVIDER_HANDLE) handle); +} +#endif /* HOST_WIN32 */ diff --git a/mono/utils/mono-rand-windows.h b/mono/utils/mono-rand-windows.h new file mode 100644 index 000000000000..f60c121c98d6 --- /dev/null +++ b/mono/utils/mono-rand-windows.h @@ -0,0 +1,33 @@ +#ifndef _MONO_UTILS_RAND_WINDOWS_H_ +#define _MONO_UTILS_RAND_WINDOWS_H_ + +#include +#include + +#ifdef HOST_WIN32 + +#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +#include +#define MONO_WIN32_CRYPT_PROVIDER_HANDLE HCRYPTPROV + +#else + +#include +#define MONO_WIN32_CRYPT_PROVIDER_HANDLE BCRYPT_ALG_HANDLE +#endif + +MONO_WIN32_CRYPT_PROVIDER_HANDLE +mono_rand_win_open_provider (void); + +gboolean +mono_rand_win_gen (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *buffer, size_t buffer_size); + +gboolean +mono_rand_win_seed (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider, guchar *seed, size_t seed_size); + +void +mono_rand_win_close_provider (MONO_WIN32_CRYPT_PROVIDER_HANDLE provider); + +#endif /* HOST_WIN32 */ +#endif /* _MONO_UTILS_RAND_WINDOWS_H_ */ + diff --git a/mono/utils/mono-rand.c b/mono/utils/mono-rand.c index 0e5a85384705..1ac91179382d 100644 --- a/mono/utils/mono-rand.c +++ b/mono/utils/mono-rand.c @@ -13,7 +13,6 @@ * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ - #include #include @@ -26,125 +25,7 @@ #include "metadata/object.h" #ifdef HOST_WIN32 - -#include -#include - -#ifndef PROV_INTEL_SEC -#define PROV_INTEL_SEC 22 -#endif -#ifndef CRYPT_VERIFY_CONTEXT -#define CRYPT_VERIFY_CONTEXT 0xF0000000 -#endif - -/** - * mono_rand_open: - * - * Returns: True if random source is global, false if mono_rand_init can be called repeatedly to get randomness instances. - * - * Initializes entire RNG system. Must be called once per process before calling mono_rand_init. - */ -gboolean -mono_rand_open (void) -{ - return FALSE; -} - -/** - * mono_rand_init: - * @seed: A string containing seed data - * @seed_size: Length of seed string - * - * Returns: On success, a non-NULL handle which can be used to fetch random data from mono_rand_try_get_bytes. On failure, NULL. - * - * Initializes an RNG client. - */ -gpointer -mono_rand_init (guchar *seed, gint seed_size) -{ - HCRYPTPROV provider = 0; - - /* There is no need to create a container for just random data, - * so we can use CRYPT_VERIFY_CONTEXT (one call) see: - * http://blogs.msdn.com/dangriff/archive/2003/11/19/51709.aspx */ - - /* We first try to use the Intel PIII RNG if drivers are present */ - if (!CryptAcquireContext (&provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFY_CONTEXT)) { - /* not a PIII or no drivers available, use default RSA CSP */ - if (!CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFY_CONTEXT)) { - /* exception will be thrown in managed code */ - provider = 0; - } - } - - /* seed the CSP with the supplied buffer (if present) */ - if (provider != 0 && seed) { - /* the call we replace the seed with random - this isn't what is - * expected from the class library user */ - guchar *data = g_malloc (seed_size); - if (data) { - memcpy (data, seed, seed_size); - /* add seeding material to the RNG */ - CryptGenRandom (provider, seed_size, data); - /* zeroize and free */ - memset (data, 0, seed_size); - g_free (data); - } - } - - return (gpointer) provider; -} - -/** - * mono_rand_try_get_bytes: - * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. - * @buffer: A buffer into which to write random data. - * @buffer_size: Number of bytes to write into buffer. - * @error: Set on error. - * - * Returns: FALSE on failure and sets @error, TRUE on success. - * - * Extracts bytes from an RNG handle. - */ -gboolean -mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gint buffer_size, MonoError *error) -{ - HCRYPTPROV provider; - - mono_error_init (error); - - g_assert (handle); - provider = (HCRYPTPROV) *handle; - - if (!CryptGenRandom (provider, buffer_size, buffer)) { - CryptReleaseContext (provider, 0); - /* we may have lost our context with CryptoAPI, but all hope isn't lost yet! */ - provider = (HCRYPTPROV) mono_rand_init (NULL, 0); - if (!CryptGenRandom (provider, buffer_size, buffer)) { - /* exception will be thrown in managed code */ - CryptReleaseContext (provider, 0); - *handle = 0; - mono_error_set_execution_engine (error, "Failed to gen random bytes (%d)", GetLastError ()); - return FALSE; - } - } - return TRUE; -} - -/** - * mono_rand_close: - * @handle: An RNG handle. - * @buffer: A buffer into which to write random data. - * @buffer_size: Number of bytes to write into buffer. - * - * Releases an RNG handle. - */ -void -mono_rand_close (gpointer handle) -{ - CryptReleaseContext ((HCRYPTPROV) handle, 0); -} - +// Windows specific implementation in mono-rand-windows.c #elif defined (HAVE_SYS_UN_H) && !defined(__native_client__) #include diff --git a/mono/utils/networking-missing.c b/mono/utils/networking-missing.c index c3501f25268f..763c85b0d375 100644 --- a/mono/utils/networking-missing.c +++ b/mono/utils/networking-missing.c @@ -53,4 +53,10 @@ inet_pton (int family, const char *address, void *inaddrp) return -1; } +#else /* !HAVE_INET_PTON */ + +#ifdef _MSC_VER +// Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty. +void __mono_win32_networking_missing_lnk4221(void) {} +#endif #endif /* !HAVE_INET_PTON */ diff --git a/msvc/libmonoutils.vcxproj b/msvc/libmonoutils.vcxproj index ca9ce67c4658..5f2d80f47a6d 100644 --- a/msvc/libmonoutils.vcxproj +++ b/msvc/libmonoutils.vcxproj @@ -65,8 +65,11 @@ + + + @@ -153,6 +156,7 @@ + @@ -165,6 +169,7 @@ + @@ -172,9 +177,11 @@ + + @@ -374,4 +381,4 @@ - + \ No newline at end of file diff --git a/msvc/libmonoutils.vcxproj.filters b/msvc/libmonoutils.vcxproj.filters index dae5e304a873..f74ea0cb33c6 100644 --- a/msvc/libmonoutils.vcxproj.filters +++ b/msvc/libmonoutils.vcxproj.filters @@ -187,6 +187,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -396,6 +405,18 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files +