Revert "[w32handle] Remove use of w32handle for File, Console, Pipe and Socket (...
authorLudovic Henry <ludovic@xamarin.com>
Sat, 5 Aug 2017 16:59:08 +0000 (12:59 -0400)
committerGitHub <noreply@github.com>
Sat, 5 Aug 2017 16:59:08 +0000 (12:59 -0400)
This reverts commit 78735091b62b8d7f65da2c83d36ca314a23009f4.

15 files changed:
mcs/class/System/System.Net.Sockets/Socket.cs
mono/metadata/Makefile.am
mono/metadata/fdhandle.c [deleted file]
mono/metadata/fdhandle.h [deleted file]
mono/metadata/icall-def.h
mono/metadata/w32file-unix.c
mono/metadata/w32file.c
mono/metadata/w32handle.c
mono/metadata/w32handle.h
mono/metadata/w32process-unix.c
mono/metadata/w32socket-internals.h
mono/metadata/w32socket-unix.c
mono/metadata/w32socket-win32.c
mono/metadata/w32socket.c
mono/metadata/w32socket.h

index ae92b8d730bb51f7ad2493ae02351ccd90cbfb36..d19756b6c30013be319b87d94a0747081fc47394 100644 (file)
@@ -2265,9 +2265,6 @@ m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_b
 
 #region DuplicateAndClose
 
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               static extern bool Duplicate_internal(IntPtr handle, int targetProcessId, out IntPtr duplicateHandle, out MonoIOError error);
-
                [MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
                public SocketInformation DuplicateAndClose (int targetProcessId)
                {
@@ -2278,8 +2275,9 @@ m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_b
                                (is_blocking       ? 0 : SocketInformationOptions.NonBlocking) |
                                (useOverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
 
+                       MonoIOError error;
                        IntPtr duplicateHandle;
-                       if (!Duplicate_internal (Handle, targetProcessId, out duplicateHandle, out MonoIOError error))
+                       if (!MonoIO.DuplicateHandle (System.Diagnostics.Process.GetCurrentProcess ().Handle, Handle, new IntPtr (targetProcessId), out duplicateHandle, 0, 0, 0x00000002 /* DUPLICATE_SAME_ACCESS */, out error))
                                throw MonoIO.GetException (error);
 
                        si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)addressFamily, (int)socketType, (int)protocolType, is_bound ? 1 : 0, (long)duplicateHandle);
index 95867a3e4ca4fe233f645b950b6b8e59fbd8fac8..c7fab2db8f3b951d6a952a2d9c521b3d6a4ecbd6 100644 (file)
@@ -281,9 +281,7 @@ common_sources = \
        sre.c   \
        sre-encode.c    \
        sre-save.c      \
-       custom-attrs.c  \
-       fdhandle.h      \
-       fdhandle.c
+       custom-attrs.c
 
 # These source files have compile time dependencies on GC code
 gc_dependent_sources = \
diff --git a/mono/metadata/fdhandle.c b/mono/metadata/fdhandle.c
deleted file mode 100644 (file)
index 39e531b..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-
-#include "fdhandle.h"
-#include "utils/mono-lazy-init.h"
-#include "utils/mono-coop-mutex.h"
-
-static GHashTable *fds;
-static MonoCoopMutex fds_mutex;
-static MonoFDHandleCallback fds_callback[MONO_FDTYPE_COUNT];
-static mono_lazy_init_t fds_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
-
-static const gchar *types_str[] = {
-       "File",
-       "Console",
-       "Pipe",
-       "Socket",
-       NULL
-};
-
-static void
-fds_remove (gpointer data)
-{
-       MonoFDHandle* fdhandle;
-
-       fdhandle = (MonoFDHandle*) data;
-       g_assert (fdhandle);
-
-       g_assert (fds_callback [fdhandle->type].close);
-       fds_callback [fdhandle->type].close (fdhandle);
-
-       mono_refcount_dec (fdhandle);
-}
-
-static void
-initialize (void)
-{
-       fds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, fds_remove);
-       mono_coop_mutex_init (&fds_mutex);
-}
-
-void
-mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback)
-{
-       mono_lazy_initialize (&fds_init, initialize);
-       memcpy (&fds_callback [type], callback, sizeof (MonoFDHandleCallback));
-}
-
-static void
-fdhandle_destroy (gpointer data)
-{
-       MonoFDHandle* fdhandle;
-
-       fdhandle = (MonoFDHandle*) data;
-       g_assert (fdhandle);
-
-       g_assert (fds_callback [fdhandle->type].destroy);
-       fds_callback [fdhandle->type].destroy (fdhandle);
-}
-
-void
-mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd)
-{
-       mono_refcount_init (fdhandle, fdhandle_destroy);
-       fdhandle->type = type;
-       fdhandle->fd = fd;
-}
-
-void
-mono_fdhandle_insert (MonoFDHandle *fdhandle)
-{
-       mono_coop_mutex_lock (&fds_mutex);
-
-       if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL))
-               g_error("%s: duplicate %s fd %d", __func__, types_str [fdhandle->type], fdhandle->fd);
-
-       g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
-
-       mono_coop_mutex_unlock (&fds_mutex);
-}
-
-gboolean
-mono_fdhandle_try_insert (MonoFDHandle *fdhandle)
-{
-       mono_coop_mutex_lock (&fds_mutex);
-
-       if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL)) {
-               /* we raced between 2 invocations of mono_fdhandle_try_insert */
-               mono_coop_mutex_unlock (&fds_mutex);
-
-               return FALSE;
-       }
-
-       g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
-
-       mono_coop_mutex_unlock (&fds_mutex);
-
-       return TRUE;
-}
-
-gboolean
-mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle)
-{
-       mono_coop_mutex_lock (&fds_mutex);
-
-       if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) fdhandle)) {
-               mono_coop_mutex_unlock (&fds_mutex);
-               return FALSE;
-       }
-
-       mono_refcount_inc (*fdhandle);
-
-       mono_coop_mutex_unlock (&fds_mutex);
-
-       return TRUE;
-}
-
-void
-mono_fdhandle_unref (MonoFDHandle *fdhandle)
-{
-       mono_refcount_dec (fdhandle);
-}
-
-gboolean
-mono_fdhandle_close (gint fd)
-{
-       MonoFDHandle *fdhandle;
-       gboolean removed;
-
-       mono_coop_mutex_lock (&fds_mutex);
-
-       if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) &fdhandle)) {
-               mono_coop_mutex_unlock (&fds_mutex);
-
-               return FALSE;
-       }
-
-       removed = g_hash_table_remove (fds, GINT_TO_POINTER(fdhandle->fd));
-       g_assert (removed);
-
-       mono_coop_mutex_unlock (&fds_mutex);
-
-       return TRUE;
-}
diff --git a/mono/metadata/fdhandle.h b/mono/metadata/fdhandle.h
deleted file mode 100644 (file)
index e3d7e5b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-
-#ifndef __MONO_METADATA_FDHANDLE_H__
-#define __MONO_METADATA_FDHANDLE_H__
-
-#include <config.h>
-#include <glib.h>
-
-#include "utils/refcount.h"
-
-typedef enum {
-       MONO_FDTYPE_FILE,
-       MONO_FDTYPE_CONSOLE,
-       MONO_FDTYPE_PIPE,
-       MONO_FDTYPE_SOCKET,
-       MONO_FDTYPE_COUNT
-} MonoFDType;
-
-typedef struct {
-       MonoRefCount ref;
-       MonoFDType type;
-       gint fd;
-} MonoFDHandle;
-
-typedef struct {
-       void (*close) (MonoFDHandle *fdhandle);
-       void (*destroy) (MonoFDHandle *fdhandle);
-} MonoFDHandleCallback;
-
-void
-mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback);
-
-void
-mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd);
-
-void
-mono_fdhandle_insert (MonoFDHandle *fdhandle);
-
-gboolean
-mono_fdhandle_try_insert (MonoFDHandle *fdhandle);
-
-gboolean
-mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle);
-
-void
-mono_fdhandle_unref (MonoFDHandle *fdhandle);
-
-gboolean
-mono_fdhandle_close (gint fd);
-
-#endif /* __MONO_METADATA_FDHANDLE_H__ */
index 2cc591e8c8c7d361548c07e02d52aa0763e43e36..a6a68bde499bd28025b7d763c991735509efc26a 100644 (file)
@@ -459,8 +459,7 @@ HANDLES(ICALL(SOCK_3, "Bind_internal(intptr,System.Net.SocketAddress,int&)", ves
 HANDLES(ICALL(SOCK_4, "Blocking_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Blocking_internal))
 HANDLES(ICALL(SOCK_5, "Close_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Close_internal))
 HANDLES(ICALL(SOCK_6, "Connect_internal(intptr,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_Connect_internal))
-HANDLES(ICALL(SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal))
-HANDLES(ICALL(SOCK_6b, "Duplicate_internal", ves_icall_System_Net_Sockets_Socket_Duplicate_internal))
+HANDLES(ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal))
 HANDLES(ICALL(SOCK_7, "GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal))
 HANDLES(ICALL(SOCK_8, "GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal))
 HANDLES(ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_IOControl_internal))
index a3ac2264f6da7addaebd76807e466a43745ce499..d74520f162cf8edaca9252ee3434bf402e02938e 100644 (file)
@@ -40,7 +40,6 @@
 #include "w32file-unix-glob.h"
 #include "w32handle.h"
 #include "w32error.h"
-#include "fdhandle.h"
 #include "utils/mono-io-portability.h"
 #include "utils/mono-logger-internals.h"
 #include "utils/mono-os-mutex.h"
@@ -60,14 +59,14 @@ typedef struct {
 /* Currently used for both FILE, CONSOLE and PIPE handle types.
  * This may have to change in future. */
 typedef struct {
-       MonoFDHandle fdhandle;
        gchar *filename;
        FileShare *share_info;  /* Pointer into shared mem */
+       gint fd;
        guint32 security_attributes;
        guint32 fileaccess;
        guint32 sharemode;
        guint32 attrs;
-} FileHandle;
+} MonoW32HandleFile;
 
 typedef struct {
        gchar **namelist;
@@ -94,63 +93,6 @@ time_t_to_filetime (time_t timeval, FILETIME *filetime)
        filetime->dwHighDateTime = ticks >> 32;
 }
 
-static FileHandle*
-file_data_create (MonoFDType type, gint fd)
-{
-       FileHandle *filehandle;
-
-       filehandle = g_new0 (FileHandle, 1);
-       mono_fdhandle_init ((MonoFDHandle*) filehandle, type, fd);
-
-       return filehandle;
-}
-
-static gint
-_wapi_unlink (const gchar *pathname);
-
-static void
-file_share_release (FileShare *share_info);
-
-static void
-file_data_close (MonoFDHandle *fdhandle)
-{
-       FileHandle* filehandle;
-
-       filehandle = (FileHandle*) fdhandle;
-       g_assert (filehandle);
-
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) filehandle)->fd);
-
-       if (((MonoFDHandle*) filehandle)->type == MONO_FDTYPE_FILE && (filehandle->attrs & FILE_FLAG_DELETE_ON_CLOSE)) {
-               _wapi_unlink (filehandle->filename);
-       }
-
-       if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_CONSOLE || ((MonoFDHandle*) filehandle)->fd > 2) {
-               if (filehandle->share_info) {
-                       file_share_release (filehandle->share_info);
-                       filehandle->share_info = NULL;
-               }
-
-               MONO_ENTER_GC_SAFE;
-               close (((MonoFDHandle*) filehandle)->fd);
-               MONO_EXIT_GC_SAFE;
-       }
-}
-
-static void
-file_data_destroy (MonoFDHandle *fdhandle)
-{
-       FileHandle *filehandle;
-
-       filehandle = (FileHandle*) fdhandle;
-       g_assert (filehandle);
-
-       if (filehandle->filename)
-               g_free (filehandle->filename);
-
-       g_free (filehandle);
-}
-
 static void
 file_share_release (FileShare *share_info)
 {
@@ -160,10 +102,8 @@ file_share_release (FileShare *share_info)
        g_assert (share_info->handle_refs > 0);
        share_info->handle_refs -= 1;
 
-       if (share_info->handle_refs == 0) {
+       if (share_info->handle_refs == 0)
                g_hash_table_remove (file_share_table, share_info);
-               // g_free (share_info);
-       }
 
        mono_coop_mutex_unlock (&file_share_mutex);
 }
@@ -863,15 +803,65 @@ _wapi_unlock_file_region (gint fd, off_t offset, off_t length)
        return TRUE;
 }
 
-static const gchar* find_typename (void)
-{
-       return "Find";
-}
+static void file_close (gpointer handle, gpointer data);
+static void file_details (gpointer data);
+static const gchar* file_typename (void);
+static gsize file_typesize (void);
+static gint file_getfiletype(void);
+static gboolean file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+static gboolean file_flush(gpointer handle);
+static guint32 file_seek(gpointer handle, gint32 movedistance,
+                        gint32 *highmovedistance, gint method);
+static gboolean file_setendoffile(gpointer handle);
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize);
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+                                FILETIME *access_time,
+                                FILETIME *write_time);
+static gboolean file_setfiletime(gpointer handle,
+                                const FILETIME *create_time,
+                                const FILETIME *access_time,
+                                const FILETIME *write_time);
+static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
 
-static gsize find_typesize (void)
-{
-       return sizeof (MonoW32HandleFind);
-}
+/* File handle is only signalled for overlapped IO */
+static MonoW32HandleOps _wapi_file_ops = {
+       file_close,             /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       file_details,   /* details */
+       file_typename,  /* typename */
+       file_typesize,  /* typesize */
+};
+
+static void console_close (gpointer handle, gpointer data);
+static void console_details (gpointer data);
+static const gchar* console_typename (void);
+static gsize console_typesize (void);
+static gint console_getfiletype(void);
+static gboolean console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Console is mostly the same as file, except it can block waiting for
+ * input or output
+ */
+static MonoW32HandleOps _wapi_console_ops = {
+       console_close,          /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       console_details,        /* details */
+       console_typename,       /* typename */
+       console_typesize,       /* typesize */
+};
+
+static const gchar* find_typename (void);
+static gsize find_typesize (void);
 
 static MonoW32HandleOps _wapi_find_ops = {
        NULL,                   /* close */
@@ -885,6 +875,85 @@ static MonoW32HandleOps _wapi_find_ops = {
        find_typesize,  /* typesize */
 };
 
+static void pipe_close (gpointer handle, gpointer data);
+static void pipe_details (gpointer data);
+static const gchar* pipe_typename (void);
+static gsize pipe_typesize (void);
+static gint pipe_getfiletype (void);
+static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean pipe_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Pipe handles
+ */
+static MonoW32HandleOps _wapi_pipe_ops = {
+       pipe_close,             /* close */
+       NULL,                   /* signal */
+       NULL,                   /* own */
+       NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL,                   /* prewait */
+       pipe_details,   /* details */
+       pipe_typename,  /* typename */
+       pipe_typesize,  /* typesize */
+};
+
+static const struct {
+       /* File, console and pipe handles */
+       gint (*getfiletype)(void);
+       
+       /* File, console and pipe handles */
+       gboolean (*readfile)(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+       gboolean (*writefile)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+       gboolean (*flushfile)(gpointer handle);
+       
+       /* File handles */
+       guint32 (*seek)(gpointer handle, gint32 movedistance,
+                       gint32 *highmovedistance, gint method);
+       gboolean (*setendoffile)(gpointer handle);
+       guint32 (*getfilesize)(gpointer handle, guint32 *highsize);
+       gboolean (*getfiletime)(gpointer handle, FILETIME *create_time,
+                               FILETIME *access_time,
+                               FILETIME *write_time);
+       gboolean (*setfiletime)(gpointer handle,
+                               const FILETIME *create_time,
+                               const FILETIME *access_time,
+                               const FILETIME *write_time);
+} io_ops[MONO_W32HANDLE_COUNT]={
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* file */
+       {file_getfiletype,
+        file_read, file_write,
+        file_flush, file_seek,
+        file_setendoffile,
+        file_getfilesize,
+        file_getfiletime,
+        file_setfiletime},
+       /* console */
+       {console_getfiletype,
+        console_read,
+        console_write,
+        NULL, NULL, NULL, NULL, NULL, NULL},
+       /* thread */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* sem */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* mutex */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* event */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* socket (will need at least read and write) */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* find */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* process */
+       {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+       /* pipe */
+       {pipe_getfiletype,
+        pipe_read,
+        pipe_write,
+        NULL, NULL, NULL, NULL, NULL, NULL},
+};
+
 static gboolean lock_while_writing = FALSE;
 
 /* Some utility functions.
@@ -1018,18 +1087,88 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir,
        }
 }
 
+/* Handle ops.
+ */
+static void file_close (gpointer handle, gpointer data)
+{
+       /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */
+       MONO_ENTER_GC_UNSAFE;
+       MonoW32HandleFile *file_handle = (MonoW32HandleFile *)data;
+       gint fd = file_handle->fd;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle,
+                 file_handle->filename);
+
+       if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
+               _wapi_unlink (file_handle->filename);
+       
+       g_free (file_handle->filename);
+       
+       if (file_handle->share_info)
+               file_share_release (file_handle->share_info);
+       
+       MONO_ENTER_GC_SAFE;
+       close (fd);
+       MONO_EXIT_GC_SAFE;
+       MONO_EXIT_GC_UNSAFE;
+}
+
+static void file_details (gpointer data)
+{
+       MonoW32HandleFile *file = (MonoW32HandleFile *)data;
+       
+       g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
+                file->filename,
+                file->fileaccess&GENERIC_READ?'R':'.',
+                file->fileaccess&GENERIC_WRITE?'W':'.',
+                file->fileaccess&GENERIC_EXECUTE?'X':'.',
+                file->sharemode&FILE_SHARE_READ?'R':'.',
+                file->sharemode&FILE_SHARE_WRITE?'W':'.',
+                file->sharemode&FILE_SHARE_DELETE?'D':'.',
+                file->attrs);
+}
+
+static const gchar* file_typename (void)
+{
+       return "File";
+}
+
+static gsize file_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint file_getfiletype(void)
+{
+       return(FILE_TYPE_DISK);
+}
+
 static gboolean
-file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       gint ret;
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint fd, ret;
        MonoThreadInfo *info = mono_thread_info_current ();
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
 
+       fd = file_handle->fd;
        if(bytesread!=NULL) {
                *bytesread=0;
        }
        
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1037,7 +1176,7 @@ file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *by
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret = read (((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret = read (fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -1045,7 +1184,8 @@ file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *by
        if(ret==-1) {
                gint err = errno;
 
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(err));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+                         handle, strerror(err));
                mono_w32error_set_last (mono_w32error_unix_to_win32 (err));
                return(FALSE);
        }
@@ -1058,18 +1198,32 @@ file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *by
 }
 
 static gboolean
-file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       gint ret;
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint ret, fd;
        off_t current_pos = 0;
        MonoThreadInfo *info = mono_thread_info_current ();
        
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       fd = file_handle->fd;
+       
        if(byteswritten!=NULL) {
                *byteswritten=0;
        }
        
-       if(!(filehandle->fileaccess & GENERIC_WRITE) && !(filehandle->fileaccess & GENERIC_ALL)) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1081,15 +1235,17 @@ file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint
                 * systems
                 */
                MONO_ENTER_GC_SAFE;
-               current_pos = lseek (((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR);
+               current_pos = lseek (fd, (off_t)0, SEEK_CUR);
                MONO_EXIT_GC_SAFE;
                if (current_pos == -1) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror (errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+                                  handle, strerror (errno));
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
                }
                
-               if (_wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes) == FALSE) {
+               if (_wapi_lock_file_region (fd, current_pos,
+                                           numbytes) == FALSE) {
                        /* The error has already been set */
                        return(FALSE);
                }
@@ -1097,13 +1253,13 @@ file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint
                
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret = write (fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
        
        if (lock_while_writing) {
-               _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes);
+               _wapi_unlock_file_region (fd, current_pos, numbytes);
        }
 
        if (ret == -1) {
@@ -1112,7 +1268,8 @@ file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint
                } else {
                        _wapi_set_last_error_from_errno ();
                                
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+                                 __func__, handle, strerror(errno));
 
                        return(FALSE);
                }
@@ -1123,22 +1280,37 @@ file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint
        return(TRUE);
 }
 
-static gboolean file_flush(FileHandle *filehandle)
+static gboolean file_flush(gpointer handle)
 {
-       gint ret;
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
+       gint ret, fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
 
-       if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       fd = file_handle->fd;
+
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
        MONO_ENTER_GC_SAFE;
-       ret=fsync(((MonoFDHandle*) filehandle)->fd);
+       ret=fsync(fd);
        MONO_EXIT_GC_SAFE;
        if (ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
+                         strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1147,15 +1319,30 @@ static gboolean file_flush(FileHandle *filehandle)
        return(TRUE);
 }
 
-static guint32 file_seek(FileHandle *filehandle, gint32 movedistance,
+static guint32 file_seek(gpointer handle, gint32 movedistance,
                         gint32 *highmovedistance, gint method)
 {
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
        gint64 offset, newpos;
-       gint whence;
+       gint whence, fd;
        guint32 ret;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(INVALID_SET_FILE_POINTER);
+       }
+       
+       fd = file_handle->fd;
 
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(INVALID_SET_FILE_POINTER);
@@ -1193,20 +1380,22 @@ static guint32 file_seek(FileHandle *filehandle, gint32 movedistance,
        offset=movedistance;
 #endif
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving fd %d by %" G_GINT64_FORMAT " bytes from %d", __func__, ((MonoFDHandle*) filehandle)->fd, offset, whence);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %" G_GINT64_FORMAT " bytes from %d", __func__,
+                  handle, offset, whence);
 
 #ifdef PLATFORM_ANDROID
        /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
        MONO_ENTER_GC_SAFE;
-       newpos=lseek64(((MonoFDHandle*) filehandle)->fd, offset, whence);
+       newpos=lseek64(fd, offset, whence);
        MONO_EXIT_GC_SAFE;
 #else
        MONO_ENTER_GC_SAFE;
-       newpos=lseek(((MonoFDHandle*) filehandle)->fd, offset, whence);
+       newpos=lseek(fd, offset, whence);
        MONO_EXIT_GC_SAFE;
 #endif
        if(newpos==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on fd %d returned error %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
+                         __func__, handle, strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(INVALID_SET_FILE_POINTER);
@@ -1227,20 +1416,34 @@ static guint32 file_seek(FileHandle *filehandle, gint32 movedistance,
        }
 #endif
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of fd %d returning %" G_GUINT32_FORMAT "/%" G_GINT32_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, ret, highmovedistance==NULL?0:*highmovedistance);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %" G_GUINT32_FORMAT "/%" G_GINT32_FORMAT, __func__,
+                  handle, ret, highmovedistance==NULL?0:*highmovedistance);
 
        return(ret);
 }
 
-static gboolean file_setendoffile(FileHandle *filehandle)
+static gboolean file_setendoffile(gpointer handle)
 {
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
        struct stat statbuf;
        off_t pos;
-       gint ret;
+       gint ret, fd;
        MonoThreadInfo *info = mono_thread_info_current ();
        
-       if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
+       
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1253,20 +1456,22 @@ static gboolean file_setendoffile(FileHandle *filehandle)
         */
        
        MONO_ENTER_GC_SAFE;
-       ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
+       ret=fstat(fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
 
        MONO_ENTER_GC_SAFE;
-       pos=lseek(((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR);
+       pos=lseek(fd, (off_t)0, SEEK_CUR);
        MONO_EXIT_GC_SAFE;
        if(pos==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+                         handle, strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1288,13 +1493,13 @@ static gboolean file_setendoffile(FileHandle *filehandle)
                 */
                do {
                        MONO_ENTER_GC_SAFE;
-                       ret = write (((MonoFDHandle*) filehandle)->fd, "", 1);
+                       ret = write (fd, "", 1);
                        MONO_EXIT_GC_SAFE;
                } while (ret == -1 && errno == EINTR &&
                         !mono_thread_info_is_interrupt_state (info));
 
                if(ret==-1) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d extend write failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
@@ -1302,10 +1507,11 @@ static gboolean file_setendoffile(FileHandle *filehandle)
 
                /* And put the file position back after the write */
                MONO_ENTER_GC_SAFE;
-               ret = lseek (((MonoFDHandle*) filehandle)->fd, pos, SEEK_SET);
+               ret = lseek (fd, pos, SEEK_SET);
                MONO_EXIT_GC_SAFE;
                if (ret == -1) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d second lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
+                                  __func__, handle, strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
@@ -1318,12 +1524,13 @@ static gboolean file_setendoffile(FileHandle *filehandle)
         */
        do {
                MONO_ENTER_GC_SAFE;
-               ret=ftruncate(((MonoFDHandle*) filehandle)->fd, pos);
+               ret=ftruncate(fd, pos);
                MONO_EXIT_GC_SAFE;
        }
        while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); 
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ftruncate failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__,
+                         handle, strerror(errno));
                
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1332,14 +1539,29 @@ static gboolean file_setendoffile(FileHandle *filehandle)
        return(TRUE);
 }
 
-static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize)
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
 {
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
        struct stat statbuf;
        guint32 size;
        gint ret;
+       gint fd;
        
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(INVALID_FILE_SIZE);
+       }
+       fd = file_handle->fd;
+       
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(INVALID_FILE_SIZE);
@@ -1352,10 +1574,11 @@ static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize)
        mono_w32error_set_last (ERROR_SUCCESS);
        
        MONO_ENTER_GC_SAFE;
-       ret = fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
+       ret = fstat(fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if (ret == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(INVALID_FILE_SIZE);
@@ -1367,10 +1590,11 @@ static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize)
                guint64 bigsize;
                gint res;
                MONO_ENTER_GC_SAFE;
-               res = ioctl (((MonoFDHandle*) filehandle)->fd, BLKGETSIZE64, &bigsize);
+               res = ioctl (fd, BLKGETSIZE64, &bigsize);
                MONO_EXIT_GC_SAFE;
                if (res < 0) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ioctl BLKGETSIZE64 failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
+                                  __func__, handle, strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(INVALID_FILE_SIZE);
@@ -1406,26 +1630,41 @@ static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize)
        return(size);
 }
 
-static gboolean file_getfiletime(FileHandle *filehandle, FILETIME *create_time,
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
                                 FILETIME *access_time,
                                 FILETIME *write_time)
 {
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
        struct stat statbuf;
        guint64 create_ticks, access_ticks, write_ticks;
-       gint ret;
+       gint ret, fd;
+       
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
 
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
        MONO_ENTER_GC_SAFE;
-       ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
+       ret=fstat(fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1473,26 +1712,38 @@ static gboolean file_getfiletime(FileHandle *filehandle, FILETIME *create_time,
        return(TRUE);
 }
 
-static gboolean file_setfiletime(FileHandle *filehandle,
+static gboolean file_setfiletime(gpointer handle,
                                 const FILETIME *create_time G_GNUC_UNUSED,
                                 const FILETIME *access_time,
                                 const FILETIME *write_time)
 {
+       MonoW32HandleFile *file_handle;
+       gboolean ok;
        struct utimbuf utbuf;
        struct stat statbuf;
        guint64 access_ticks, write_ticks;
-       gint ret;
+       gint ret, fd;
        
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+                               (gpointer *)&file_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = file_handle->fd;
        
-       if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
-       if(filehandle->filename == NULL) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d unknown filename", __func__, ((MonoFDHandle*) filehandle)->fd);
+       if(file_handle->filename == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
 
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
                return(FALSE);
@@ -1502,10 +1753,11 @@ static gboolean file_setfiletime(FileHandle *filehandle,
         * the event that one of the FileTime structs is NULL
         */
        MONO_ENTER_GC_SAFE;
-       ret=fstat (((MonoFDHandle*) filehandle)->fd, &statbuf);
+       ret=fstat (fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
 
                mono_w32error_set_last (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -1560,12 +1812,13 @@ static gboolean file_setfiletime(FileHandle *filehandle,
                utbuf.modtime=statbuf.st_mtime;
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting fd %d access %ld write %ld", __func__,
-                  ((MonoFDHandle*) filehandle)->fd, utbuf.actime, utbuf.modtime);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
+                  handle, utbuf.actime, utbuf.modtime);
 
-       ret = _wapi_utime (filehandle->filename, &utbuf);
+       ret = _wapi_utime (file_handle->filename, &utbuf);
        if (ret == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d [%s] utime failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->filename, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__,
+                          handle, file_handle->filename, strerror(errno));
 
                mono_w32error_set_last (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -1574,18 +1827,73 @@ static gboolean file_setfiletime(FileHandle *filehandle,
        return(TRUE);
 }
 
+static void console_close (gpointer handle, gpointer data)
+{
+       /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */
+       MONO_ENTER_GC_UNSAFE;
+       MonoW32HandleFile *console_handle = (MonoW32HandleFile *)data;
+       gint fd = console_handle->fd;
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle);
+
+       g_free (console_handle->filename);
+
+       if (fd > 2) {
+               if (console_handle->share_info)
+                       file_share_release (console_handle->share_info);
+               MONO_ENTER_GC_SAFE;
+               close (fd);
+               MONO_EXIT_GC_SAFE;
+       }
+       MONO_EXIT_GC_UNSAFE;
+}
+
+static void console_details (gpointer data)
+{
+       file_details (data);
+}
+
+static const gchar* console_typename (void)
+{
+       return "Console";
+}
+
+static gsize console_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint console_getfiletype(void)
+{
+       return(FILE_TYPE_CHAR);
+}
+
 static gboolean
-console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       gint ret;
+       MonoW32HandleFile *console_handle;
+       gboolean ok;
+       gint ret, fd;
        MonoThreadInfo *info = mono_thread_info_current ();
 
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                               (gpointer *)&console_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = console_handle->fd;
+       
        if(bytesread!=NULL) {
                *bytesread=0;
        }
        
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(console_handle->fileaccess & GENERIC_READ) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                          __func__, handle, console_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1593,12 +1901,13 @@ console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32
        
        do {
                MONO_ENTER_GC_SAFE;
-               ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret=read(fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
 
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle,
+                         strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1612,17 +1921,30 @@ console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32
 }
 
 static gboolean
-console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       gint ret;
+       MonoW32HandleFile *console_handle;
+       gboolean ok;
+       gint ret, fd;
        MonoThreadInfo *info = mono_thread_info_current ();
        
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                               (gpointer *)&console_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = console_handle->fd;
+       
        if(byteswritten!=NULL) {
                *byteswritten=0;
        }
        
-       if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(console_handle->fileaccess & GENERIC_WRITE) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1630,7 +1952,7 @@ console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, gu
        
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write(((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret = write(fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -1641,7 +1963,8 @@ console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, gu
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+                                  __func__, handle, strerror(errno));
 
                        return(FALSE);
                }
@@ -1653,28 +1976,93 @@ console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, gu
        return(TRUE);
 }
 
+static const gchar* find_typename (void)
+{
+       return "Find";
+}
+
+static gsize find_typesize (void)
+{
+       return sizeof (MonoW32HandleFind);
+}
+
+static void pipe_close (gpointer handle, gpointer data)
+{
+       /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */
+       MONO_ENTER_GC_UNSAFE;
+       MonoW32HandleFile *pipe_handle = (MonoW32HandleFile*)data;
+       gint fd = pipe_handle->fd;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd);
+
+       /* No filename with pipe handles */
+
+       if (pipe_handle->share_info)
+               file_share_release (pipe_handle->share_info);
+
+       MONO_ENTER_GC_SAFE;
+       close (fd);
+       MONO_EXIT_GC_SAFE;
+       MONO_EXIT_GC_UNSAFE;
+}
+
+static void pipe_details (gpointer data)
+{
+       file_details (data);
+}
+
+static const gchar* pipe_typename (void)
+{
+       return "Pipe";
+}
+
+static gsize pipe_typesize (void)
+{
+       return sizeof (MonoW32HandleFile);
+}
+
+static gint pipe_getfiletype(void)
+{
+       return(FILE_TYPE_PIPE);
+}
+
 static gboolean
-pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       gint ret;
+       MonoW32HandleFile *pipe_handle;
+       gboolean ok;
+       gint ret, fd;
        MonoThreadInfo *info = mono_thread_info_current ();
 
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+                               (gpointer *)&pipe_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = pipe_handle->fd;
+
        if(bytesread!=NULL) {
                *bytesread=0;
        }
        
-       if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(pipe_handle->fileaccess & GENERIC_READ) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, pipe_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %" G_GUINT32_FORMAT " bytes from pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %" G_GUINT32_FORMAT " bytes from pipe %p", __func__,
+                  numbytes, handle);
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret=read(fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
                
@@ -1684,13 +2072,14 @@ pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *b
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
 
                        return(FALSE);
                }
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %d", __func__, ret, ((MonoFDHandle*) filehandle)->fd);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
 
        if(bytesread!=NULL) {
                *bytesread=ret;
@@ -1700,27 +2089,41 @@ pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *b
 }
 
 static gboolean
-pipe_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       gint ret;
+       MonoW32HandleFile *pipe_handle;
+       gboolean ok;
+       gint ret, fd;
        MonoThreadInfo *info = mono_thread_info_current ();
        
+       ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+                               (gpointer *)&pipe_handle);
+       if(ok==FALSE) {
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       fd = pipe_handle->fd;
+       
        if(byteswritten!=NULL) {
                *byteswritten=0;
        }
        
-       if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %p", __func__,
+                  numbytes, handle);
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
+               ret = write (fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -1731,7 +2134,8 @@ pipe_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
 
                        return(FALSE);
                }
@@ -1822,7 +2226,6 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, fileaccess);
 
                        file_share_release (*share_info);
-                       *share_info = NULL;
                        
                        return(FALSE);
                }
@@ -1835,7 +2238,6 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, fileaccess, file_existing_share);
 
                        file_share_release (*share_info);
-                       *share_info = NULL;
                
                        return(FALSE);
                }
@@ -1848,7 +2250,6 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%" PRIx32 ", file has access: 0x%" PRIx32, __func__, sharemode, file_existing_access);
 
                        file_share_release (*share_info);
-                       *share_info = NULL;
                
                        return(FALSE);
                }
@@ -1878,7 +2279,6 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info)
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, (*share_info)->access);
 
                        file_share_release (*share_info);
-                       *share_info = NULL;
 
                        return(FALSE);
                }
@@ -1888,7 +2288,6 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info)
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, (*share_info)->access, file_existing_share);
 
                        file_share_release (*share_info);
-                       *share_info = NULL;
 
                        return(FALSE);
                }
@@ -1902,8 +2301,8 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info)
 gpointer
 mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
 {
-       FileHandle *filehandle;
-       MonoFDType type;
+       MonoW32HandleFile file_handle = {0};
+       gpointer handle;
        gint flags=convert_flags(fileaccess, createmode);
        /*mode_t perms=convert_perms(sharemode);*/
        /* we don't use sharemode, because that relates to sharing of
@@ -1914,6 +2313,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
        mode_t perms=0666;
        gchar *filename;
        gint fd, ret;
+       MonoW32HandleType handle_type;
        struct stat statbuf;
 
        if (attrs & FILE_ATTRIBUTE_TEMPORARY)
@@ -1959,77 +2359,81 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
        }
        
        if (fd == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename,
+                         strerror(errno));
                _wapi_set_last_path_error_from_errno (NULL, filename);
                g_free (filename);
 
                return(INVALID_HANDLE_VALUE);
        }
 
+       if (fd >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+               mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+               
+               MONO_ENTER_GC_SAFE;
+               close (fd);
+               MONO_EXIT_GC_SAFE;
+               g_free (filename);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+
        MONO_ENTER_GC_SAFE;
        ret = fstat (fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if (ret == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, filename, g_strerror (errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
+                          filename, strerror (errno));
                _wapi_set_last_error_from_errno ();
+               g_free (filename);
                MONO_ENTER_GC_SAFE;
                close (fd);
                MONO_EXIT_GC_SAFE;
-
+               
                return(INVALID_HANDLE_VALUE);
        }
 
-#ifndef S_ISFIFO
-#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
-#endif
-       if (S_ISFIFO (statbuf.st_mode)) {
-               type = MONO_FDTYPE_PIPE;
-               /* maintain invariant that pipes have no filename */
-               g_free (filename);
-               filename = NULL;
-       } else if (S_ISCHR (statbuf.st_mode)) {
-               type = MONO_FDTYPE_CONSOLE;
-       } else {
-               type = MONO_FDTYPE_FILE;
-       }
-
-       filehandle = file_data_create (type, fd);
-       filehandle->filename = filename;
-       filehandle->fileaccess = fileaccess;
-       filehandle->sharemode = sharemode;
-       filehandle->attrs = attrs;
-
-       if (!share_allows_open (&statbuf, filehandle->sharemode, filehandle->fileaccess, &filehandle->share_info)) {
+       if (share_allows_open (&statbuf, sharemode, fileaccess,
+                        &file_handle.share_info) == FALSE) {
                mono_w32error_set_last (ERROR_SHARING_VIOLATION);
+               g_free (filename);
                MONO_ENTER_GC_SAFE;
-               close (((MonoFDHandle*) filehandle)->fd);
+               close (fd);
                MONO_EXIT_GC_SAFE;
                
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return (INVALID_HANDLE_VALUE);
        }
-       if (!filehandle->share_info) {
+       if (file_handle.share_info == NULL) {
                /* No space, so no more files can be opened */
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
 
                mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
                MONO_ENTER_GC_SAFE;
-               close (((MonoFDHandle*) filehandle)->fd);
+               close (fd);
                MONO_EXIT_GC_SAFE;
+               g_free (filename);
                
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return(INVALID_HANDLE_VALUE);
        }
+       
+       file_handle.filename = filename;
+       
+       file_handle.fd = fd;
+       file_handle.fileaccess=fileaccess;
+       file_handle.sharemode=sharemode;
+       file_handle.attrs=attrs;
 
 #ifdef HAVE_POSIX_FADVISE
        if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) {
                MONO_ENTER_GC_SAFE;
-               posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+               posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
                MONO_EXIT_GC_SAFE;
        }
        if (attrs & FILE_FLAG_RANDOM_ACCESS) {
                MONO_ENTER_GC_SAFE;
-               posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_RANDOM);
+               posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
                MONO_EXIT_GC_SAFE;
        }
 #endif
@@ -2037,27 +2441,56 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
 #ifdef F_RDAHEAD
        if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) {
                MONO_ENTER_GC_SAFE;
-               fcntl(((MonoFDHandle*) filehandle)->fd, F_RDAHEAD, 1);
+               fcntl(fd, F_RDAHEAD, 1);
                MONO_EXIT_GC_SAFE;
        }
 #endif
 
-       mono_fdhandle_insert ((MonoFDHandle*) filehandle);
-
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd));
+#ifndef S_ISFIFO
+#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
+#endif
+       if (S_ISFIFO (statbuf.st_mode)) {
+               handle_type = MONO_W32HANDLE_PIPE;
+               /* maintain invariant that pipes have no filename */
+               file_handle.filename = NULL;
+               g_free (filename);
+               filename = NULL;
+       } else if (S_ISCHR (statbuf.st_mode)) {
+               handle_type = MONO_W32HANDLE_CONSOLE;
+       } else {
+               handle_type = MONO_W32HANDLE_FILE;
+       }
 
-       return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd);
+       MONO_ENTER_GC_SAFE; /* FIXME: mono_w32handle_new_fd should be updated with coop transitions */
+       handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
+       MONO_EXIT_GC_SAFE;
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating file handle", __func__);
+               g_free (filename);
+               MONO_ENTER_GC_SAFE;
+               close (fd);
+               MONO_EXIT_GC_SAFE;
+               
+               mono_w32error_set_last (ERROR_GEN_FAILURE);
+               return(INVALID_HANDLE_VALUE);
+       }
+       
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+       
+       return(handle);
 }
 
 gboolean
 mono_w32file_close (gpointer handle)
 {
-       if (!mono_fdhandle_close (GPOINTER_TO_INT (handle))) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       return TRUE;
+       gboolean res;
+       MONO_ENTER_GC_SAFE;
+       /* FIXME: we transition here and not in file_close, pipe_close,
+        * console_close because w32handle_close is not coop aware yet, but it
+        * calls back into w32file. */
+       res = mono_w32handle_close (handle);
+       MONO_EXIT_GC_SAFE;
+       return res;
 }
 
 gboolean mono_w32file_delete(const gunichar2 *name)
@@ -2211,10 +2644,8 @@ MoveFile (gunichar2 *name, gunichar2 *dest_name)
                mono_w32error_set_last (ERROR_SHARING_VIOLATION);
                return FALSE;
        }
-       if (shareinfo) {
+       if (shareinfo)
                file_share_release (shareinfo);
-               shareinfo = NULL;
-       }
 
        result = _wapi_rename (utf8_name, utf8_dest_name);
        errno_copy = errno;
@@ -2448,7 +2879,7 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex
        ret_utime = utime (utf8_dest, &dest_time);
        MONO_EXIT_GC_SAFE;
        if (ret_utime == -1)
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
        
        g_free (utf8_src);
        g_free (utf8_dest);
@@ -2539,11 +2970,14 @@ replace_cleanup:
        return ret;
 }
 
+static MonoCoopMutex stdhandle_mutex;
+
 static gpointer
 _wapi_stdhandle_create (gint fd, const gchar *name)
 {
+       gpointer handle;
        gint flags;
-       FileHandle *filehandle;
+       MonoW32HandleFile file_handle = {0};
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd);
 
@@ -2556,52 +2990,52 @@ _wapi_stdhandle_create (gint fd, const gchar *name)
                /* Invalid fd.  Not really much point checking for EBADF
                 * specifically
                 */
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, g_strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, strerror(errno));
 
                mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
                return INVALID_HANDLE_VALUE;
        }
 
-       filehandle = file_data_create (MONO_FDTYPE_CONSOLE, fd);
-       filehandle->filename = g_strdup(name);
-
        switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
        case O_RDONLY:
-               filehandle->fileaccess = GENERIC_READ;
+               file_handle.fileaccess = GENERIC_READ;
                break;
        case O_WRONLY:
-               filehandle->fileaccess = GENERIC_WRITE;
+               file_handle.fileaccess = GENERIC_WRITE;
                break;
        case O_RDWR:
-               filehandle->fileaccess = GENERIC_READ | GENERIC_WRITE;
+               file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE;
                break;
        default:
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
-               filehandle->fileaccess = 0;
+               file_handle.fileaccess = 0;
                break;
        }
 
+       file_handle.fd = fd;
+       file_handle.filename = g_strdup(name);
        /* some default security attributes might be needed */
-       filehandle->security_attributes = 0;
+       file_handle.security_attributes = 0;
 
        /* Apparently input handles can't be written to.  (I don't
         * know if output or error handles can't be read from.)
         */
        if (fd == 0)
-               filehandle->fileaccess &= ~GENERIC_WRITE;
+               file_handle.fileaccess &= ~GENERIC_WRITE;
 
-       filehandle->sharemode = 0;
-       filehandle->attrs = 0;
+       file_handle.sharemode = 0;
+       file_handle.attrs = 0;
 
-       if (!mono_fdhandle_try_insert ((MonoFDHandle*) filehandle)) {
-               /* we raced between 2 invocations of _wapi_stdhandle_create */
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return GINT_TO_POINTER(fd);
+       handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating file handle", __func__);
+               mono_w32error_set_last (ERROR_GEN_FAILURE);
+               return INVALID_HANDLE_VALUE;
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd));
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
 
-       return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd);
+       return handle;
 }
 
 enum {
@@ -2613,9 +3047,11 @@ enum {
 static gpointer
 mono_w32file_get_std_handle (gint stdhandle)
 {
-       FileHandle **filehandle;
+       MonoW32HandleFile *file_handle;
+       gpointer handle;
        gint fd;
        const gchar *name;
+       gboolean ok;
        
        switch(stdhandle) {
        case STD_INPUT_HANDLE:
@@ -2637,260 +3073,164 @@ mono_w32file_get_std_handle (gint stdhandle)
                g_assert_not_reached ();
        }
 
-       if (!mono_fdhandle_lookup_and_ref(fd, (MonoFDHandle**) &filehandle)) {
-               gpointer handle;
+       handle = GINT_TO_POINTER (fd);
+
+       mono_coop_mutex_lock (&stdhandle_mutex);
 
+       ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+                                 (gpointer *)&file_handle);
+       if (ok == FALSE) {
+               /* Need to create this console handle */
                handle = _wapi_stdhandle_create (fd, name);
+               
                if (handle == INVALID_HANDLE_VALUE) {
                        mono_w32error_set_last (ERROR_NO_MORE_FILES);
-                       return INVALID_HANDLE_VALUE;
+                       goto done;
                }
        }
+       
+  done:
+       mono_coop_mutex_unlock (&stdhandle_mutex);
 
-       return GINT_TO_POINTER (fd);
+       return(handle);
 }
 
 gboolean
 mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       FileHandle *filehandle;
-       gboolean ret;
+       MonoW32HandleType type;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_read(filehandle, buffer, numbytes, bytesread);
-               break;
-       case MONO_FDTYPE_CONSOLE:
-               ret = console_read(filehandle, buffer, numbytes, bytesread);
-               break;
-       case MONO_FDTYPE_PIPE:
-               ret = pipe_read(filehandle, buffer, numbytes, bytesread);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].readfile==NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].readfile (handle, buffer, numbytes, bytesread));
 }
 
 gboolean
 mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       FileHandle *filehandle;
-       gboolean ret;
+       MonoW32HandleType type;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_write(filehandle, buffer, numbytes, byteswritten);
-               break;
-       case MONO_FDTYPE_CONSOLE:
-               ret = console_write(filehandle, buffer, numbytes, byteswritten);
-               break;
-       case MONO_FDTYPE_PIPE:
-               ret = pipe_write(filehandle, buffer, numbytes, byteswritten);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].writefile==NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten));
 }
 
 gboolean
 mono_w32file_flush (gpointer handle)
 {
-       FileHandle *filehandle;
-       gboolean ret;
-
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
+       MonoW32HandleType type;
 
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_flush(filehandle);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if(io_ops[type].flushfile==NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].flushfile (handle));
 }
 
 gboolean
 mono_w32file_truncate (gpointer handle)
 {
-       FileHandle *filehandle;
-       gboolean ret;
-
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
+       MonoW32HandleType type;
 
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_setendoffile(filehandle);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].setendoffile == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].setendoffile (handle));
 }
 
 guint32
 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
 {
-       FileHandle *filehandle;
-       guint32 ret;
-
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return INVALID_SET_FILE_POINTER;
-       }
+       MonoW32HandleType type;
 
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_seek(filehandle, movedistance, highmovedistance, method);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].seek == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return INVALID_SET_FILE_POINTER;
+               return(INVALID_SET_FILE_POINTER);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].seek (handle, movedistance, highmovedistance,
+                                 method));
 }
 
 gint
 mono_w32file_get_type(gpointer handle)
 {
-       FileHandle *filehandle;
-       gint ret;
+       MonoW32HandleType type;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FILE_TYPE_UNKNOWN;
-       }
-
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = FILE_TYPE_DISK;
-               break;
-       case MONO_FDTYPE_CONSOLE:
-               ret = FILE_TYPE_CHAR;
-               break;
-       case MONO_FDTYPE_PIPE:
-               ret = FILE_TYPE_PIPE;
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfiletype == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FILE_TYPE_UNKNOWN;
+               return(FILE_TYPE_UNKNOWN);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].getfiletype ());
 }
 
 static guint32
 GetFileSize(gpointer handle, guint32 *highsize)
 {
-       FileHandle *filehandle;
-       guint32 ret;
+       MonoW32HandleType type;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return INVALID_FILE_SIZE;
-       }
-
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_getfilesize(filehandle, highsize);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfilesize == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return INVALID_FILE_SIZE;
+               return(INVALID_FILE_SIZE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].getfilesize (handle, highsize));
 }
 
 gboolean
 mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
 {
-       FileHandle *filehandle;
-       gboolean ret;
-
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
+       MonoW32HandleType type;
 
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_getfiletime(filehandle, create_time, access_time, write_time);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].getfiletime == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].getfiletime (handle, create_time, access_time,
+                                        write_time));
 }
 
 gboolean
 mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
 {
-       FileHandle *filehandle;
-       gboolean ret;
-
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
+       MonoW32HandleType type;
 
-       switch (((MonoFDHandle*) filehandle)->type) {
-       case MONO_FDTYPE_FILE:
-               ret = file_setfiletime(filehandle, create_time, access_time, write_time);
-               break;
-       default:
+       type = mono_w32handle_get_type (handle);
+       
+       if (io_ops[type].setfiletime == NULL) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
+               return(FALSE);
        }
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       
+       return(io_ops[type].setfiletime (handle, create_time, access_time,
+                                        write_time));
 }
 
 /* A tick is a 100-nanosecond interval.  File time epoch is Midnight,
@@ -3596,7 +3936,10 @@ mono_w32file_set_cwd (const gunichar2 *path)
 gboolean
 mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
 {
-       FileHandle *read_filehandle, *write_filehandle;
+       MonoW32HandleFile pipe_read_handle = {0};
+       MonoW32HandleFile pipe_write_handle = {0};
+       gpointer read_handle;
+       gpointer write_handle;
        gint filedes[2];
        gint ret;
        
@@ -3605,30 +3948,68 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
        MONO_ENTER_GC_SAFE;
        ret=pipe (filedes);
        MONO_EXIT_GC_SAFE;
-       if (ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: (%d) %s",
-                       __func__, errno, g_strerror (errno));
-
+       if(ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
+                          strerror (errno));
+               
                _wapi_set_last_error_from_errno ();
-               return FALSE;
+               return(FALSE);
        }
 
-       /* filedes[0] is open for reading, filedes[1] for writing */
-
-       read_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[0]);
-       read_filehandle->fileaccess = GENERIC_READ;
+       if (filedes[0] >= mono_w32handle_fd_reserve ||
+           filedes[1] >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
 
-       write_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[1]);
-       write_filehandle->fileaccess = GENERIC_WRITE;
+               mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+               
+               MONO_ENTER_GC_SAFE;
+               close (filedes[0]);
+               close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
+               
+               return(FALSE);
+       }
+       
+       /* filedes[0] is open for reading, filedes[1] for writing */
 
-       mono_fdhandle_insert ((MonoFDHandle*) read_filehandle);
-       mono_fdhandle_insert ((MonoFDHandle*) write_filehandle);
+       pipe_read_handle.fd = filedes [0];
+       pipe_read_handle.fileaccess = GENERIC_READ;
+       read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
+                                          &pipe_read_handle);
+       if (read_handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating pipe read handle", __func__);
+               MONO_ENTER_GC_SAFE;
+               close (filedes[0]);
+               close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
+               mono_w32error_set_last (ERROR_GEN_FAILURE);
+               
+               return(FALSE);
+       }
+       
+       pipe_write_handle.fd = filedes [1];
+       pipe_write_handle.fileaccess = GENERIC_WRITE;
+       write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
+                                           &pipe_write_handle);
+       if (write_handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating pipe write handle", __func__);
 
-       *readpipe = GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd);
-       *writepipe = GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd);
+               MONO_ENTER_GC_SAFE;
+               mono_w32handle_close (read_handle);
+               
+               close (filedes[0]);
+               close (filedes[1]);
+               MONO_EXIT_GC_SAFE;
+               mono_w32error_set_last (ERROR_GEN_FAILURE);
+               
+               return(FALSE);
+       }
+       
+       *readpipe = read_handle;
+       *writepipe = write_handle;
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
-               __func__, GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd), GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd));
+                  __func__, read_handle, write_handle);
 
        return(TRUE);
 }
@@ -4182,7 +4563,7 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte
 
        if (ret == -1) {
                _wapi_set_last_error_from_errno ();
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, g_strerror (errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
                return(FALSE);
        }
 
@@ -4571,25 +4952,18 @@ mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumenam
 static gboolean
 LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
 {
-       FileHandle *filehandle;
-       gboolean ret;
+       MonoW32HandleFile *file_handle;
        off_t offset, length;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) {
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+               g_warning ("%s: error looking up file handle %p", __func__, handle);
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
 
-       if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
 
@@ -4597,48 +4971,38 @@ LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 leng
        offset = ((gint64)offset_high << 32) | offset_low;
        length = ((gint64)length_high << 32) | length_low;
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__,
+                 handle, (gint64) offset, (gint64) length);
 #else
        if (offset_high > 0 || length_high > 0) {
                mono_w32error_set_last (ERROR_INVALID_PARAMETER);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
-
        offset = offset_low;
        length = length_low;
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__,
+                 handle, (gint64) offset, (gint64) length);
 #endif
 
-       ret = _wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length);
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length);
 }
 
 static gboolean
 UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
 {
-       FileHandle *filehandle;
-       gboolean ret;
+       MonoW32HandleFile *file_handle;
        off_t offset, length;
 
-       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+               g_warning ("%s: error looking up file handle %p", __func__, handle);
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
                return FALSE;
        }
 
-       if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-               return FALSE;
-       }
-
-       if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess);
+       if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
-               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
 
@@ -4646,35 +5010,33 @@ UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 le
        offset = ((gint64)offset_high << 32) | offset_low;
        length = ((gint64)length_high << 32) | length_low;
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__,
+                 handle, (gint64) offset, (gint64) length);
 #else
        offset = offset_low;
        length = length_low;
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, handle, (gint64) offset, (gint64) length);
 #endif
 
-       ret = _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length);
-
-       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
-       return ret;
+       return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length);
 }
 
 void
 mono_w32file_init (void)
 {
-       MonoFDHandleCallback file_data_callbacks = {
-               .close = file_data_close,
-               .destroy = file_data_destroy
-       };
-
-       mono_fdhandle_register (MONO_FDTYPE_FILE, &file_data_callbacks);
-       mono_fdhandle_register (MONO_FDTYPE_CONSOLE, &file_data_callbacks);
-       mono_fdhandle_register (MONO_FDTYPE_PIPE, &file_data_callbacks);
-
+       mono_coop_mutex_init (&stdhandle_mutex);
        mono_coop_mutex_init (&file_share_mutex);
 
-       mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_FILE,    &_wapi_file_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_FIND,    &_wapi_find_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_PIPE,    &_wapi_pipe_ops);
+
+/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
+/*                                         MONO_W32HANDLE_CAP_WAIT); */
+/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
+/*                                         MONO_W32HANDLE_CAP_WAIT); */
 
        if (g_hasenv ("MONO_STRICT_IO_EMULATION"))
                lock_while_writing = TRUE;
index 325767f52434e9fbcb91aa60963c18d518354651..296a84d6a47055af2eddaecfb48ce827f1b93eb0 100644 (file)
@@ -1065,22 +1065,24 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
                HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
 {
-#ifndef HOST_WIN32
-       *target_handle = mono_w32handle_duplicate (source_handle);
-#else
+       /* This is only used on Windows */
        gboolean ret;
-
+       
+#ifdef HOST_WIN32
        MONO_ENTER_GC_SAFE;
        ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
        MONO_EXIT_GC_SAFE;
+#else
+       *target_handle = mono_w32handle_duplicate (source_handle);
+       ret = TRUE;
+#endif
 
-       if (!ret) {
+       if(ret==FALSE) {
                *error = mono_w32error_get_last ();
                /* FIXME: throw an exception? */
                return(FALSE);
        }
-#endif
-
+       
        return(TRUE);
 }
 
index 98d4ace6d62593b62e3b0e1be6ace694f8333ff6..35a5dd93d87663884e7cb43bd2cfdba27547b8dc 100644 (file)
@@ -51,7 +51,10 @@ static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT];
 #define SLOT_OFFSET(x) (x % HANDLE_PER_SLOT)
 
 static MonoW32HandleBase *private_handles [SLOT_MAX];
-static guint32 private_handles_size = 0;
+static guint32 private_handles_count = 0;
+static guint32 private_handles_slots_count = 0;
+
+guint32 mono_w32handle_fd_reserve;
 
 /*
  * This is an internal handle which is used for handling waiting for multiple handles.
@@ -65,6 +68,20 @@ static mono_mutex_t scan_mutex;
 
 static gboolean shutting_down = FALSE;
 
+static gboolean
+type_is_fd (MonoW32HandleType type)
+{
+       switch (type) {
+       case MONO_W32HANDLE_FILE:
+       case MONO_W32HANDLE_CONSOLE:
+       case MONO_W32HANDLE_SOCKET:
+       case MONO_W32HANDLE_PIPE:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
+
 static gboolean
 mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data)
 {
@@ -262,6 +279,19 @@ mono_w32handle_init (void)
        g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
                  == MONO_W32HANDLE_COUNT);
 
+       /* This is needed by the code in mono_w32handle_new_internal */
+       mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1);
+
+       do {
+               /*
+                * The entries in private_handles reserved for fds are allocated lazily to
+                * save memory.
+                */
+
+               private_handles_count += HANDLE_PER_SLOT;
+               private_handles_slots_count ++;
+       } while(mono_w32handle_fd_reserve > private_handles_count);
+
        mono_os_mutex_init (&scan_mutex);
 
        mono_os_cond_init (&global_signal_cond);
@@ -285,6 +315,22 @@ mono_w32handle_cleanup (void)
 static gsize
 mono_w32handle_ops_typesize (MonoW32HandleType type);
 
+static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
+                              MonoW32HandleType type, gpointer handle_specific)
+{
+       g_assert (handle->ref == 0);
+
+       handle->type = type;
+       handle->signalled = FALSE;
+       handle->ref = 1;
+
+       mono_os_cond_init (&handle->signal_cond);
+       mono_os_mutex_init (&handle->signal_mutex);
+
+       if (handle_specific)
+               handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
+}
+
 /*
  * mono_w32handle_new_internal:
  * @type: Init handle to this type
@@ -306,16 +352,15 @@ static guint32 mono_w32handle_new_internal (MonoW32HandleType type,
         * descriptors
         */
 
-       if (last == 0) {
-               /* We need to go from 1 since a handle of value 0 can be considered invalid in managed code */
-               last = 1;
+       if (last < mono_w32handle_fd_reserve) {
+               last = mono_w32handle_fd_reserve;
        } else {
                retry = TRUE;
        }
 
 again:
        count = last;
-       for(i = SLOT_INDEX (count); i < private_handles_size; i++) {
+       for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) {
                if (private_handles [i]) {
                        for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) {
                                MonoW32HandleBase *handle = &private_handles [i][k];
@@ -323,18 +368,7 @@ again:
                                if(handle->type == MONO_W32HANDLE_UNUSED) {
                                        last = count + 1;
 
-                                       g_assert (handle->ref == 0);
-
-                                       handle->type = type;
-                                       handle->signalled = FALSE;
-                                       handle->ref = 1;
-
-                                       mono_os_cond_init (&handle->signal_cond);
-                                       mono_os_mutex_init (&handle->signal_mutex);
-
-                                       if (handle_specific)
-                                               handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
-
+                                       mono_w32handle_init_handle (handle, type, handle_specific);
                                        return (count);
                                }
                                count++;
@@ -342,50 +376,108 @@ again:
                }
        }
 
-       if (retry) {
+       if(retry && last > mono_w32handle_fd_reserve) {
                /* Try again from the beginning */
-               last = 1;
-               retry = FALSE;
+               last = mono_w32handle_fd_reserve;
                goto again;
        }
 
        /* Will need to expand the array.  The caller will sort it out */
 
-       return G_MAXUINT32;
+       return(0);
 }
 
 gpointer
 mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific)
 {
-       guint32 handle_idx;
+       guint32 handle_idx = 0;
        gpointer handle;
 
        g_assert (!shutting_down);
 
+       g_assert(!type_is_fd(type));
+
        mono_os_mutex_lock (&scan_mutex);
 
-       while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == G_MAXUINT32) {
+       while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) {
                /* Try and expand the array, and have another go */
-               if (private_handles_size >= SLOT_MAX) {
-                       mono_os_mutex_unlock (&scan_mutex);
-
-                       /* We ran out of slots */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
-                       return INVALID_HANDLE_VALUE;
+               int idx = SLOT_INDEX (private_handles_count);
+               if (idx >= SLOT_MAX) {
+                       break;
                }
 
-               private_handles [private_handles_size ++] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+               private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+
+               private_handles_count += HANDLE_PER_SLOT;
+               private_handles_slots_count ++;
        }
 
        mono_os_mutex_unlock (&scan_mutex);
 
+       if (handle_idx == 0) {
+               /* We ran out of slots */
+               handle = INVALID_HANDLE_VALUE;
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
+               goto done;
+       }
+
+       /* Make sure we left the space for fd mappings */
+       g_assert (handle_idx >= mono_w32handle_fd_reserve);
+
        handle = GUINT_TO_POINTER (handle_idx);
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
 
+done:
        return(handle);
 }
 
+gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd,
+                             gpointer handle_specific)
+{
+       MonoW32HandleBase *handle_data;
+       int fd_index, fd_offset;
+
+       g_assert (!shutting_down);
+
+       g_assert(type_is_fd(type));
+
+       if (fd >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is too big", __func__, mono_w32handle_ops_typename (type));
+
+               return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
+       }
+
+       fd_index = SLOT_INDEX (fd);
+       fd_offset = SLOT_OFFSET (fd);
+
+       mono_os_mutex_lock (&scan_mutex);
+       /* Initialize the array entries on demand */
+       if (!private_handles [fd_index]) {
+               if (!private_handles [fd_index])
+                       private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+       }
+
+       handle_data = &private_handles [fd_index][fd_offset];
+
+       if (handle_data->type != MONO_W32HANDLE_UNUSED) {
+               mono_os_mutex_unlock (&scan_mutex);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type));
+               /* FIXME: clean up this handle?  We can't do anything
+                * with the fd, cos thats the new one
+                */
+               return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), GUINT_TO_POINTER(fd));
+
+       mono_w32handle_init_handle (handle_data, type, handle_specific);
+
+       mono_os_mutex_unlock (&scan_mutex);
+
+       return(GUINT_TO_POINTER(fd));
+}
+
 static gboolean
 mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
 
@@ -404,6 +496,8 @@ mono_w32handle_duplicate (gpointer handle)
                return handle;
        if (!mono_w32handle_lookup_data (handle, &handle_data))
                return INVALID_HANDLE_VALUE;
+       if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE)
+               return handle;
 
        if (!mono_w32handle_ref_core (handle, handle_data))
                g_error ("%s: failed to ref handle %p", __func__, handle);
@@ -421,6 +515,14 @@ mono_w32handle_close (gpointer handle)
                return FALSE;
        if (!mono_w32handle_lookup_data (handle, &handle_data))
                return FALSE;
+       if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE) {
+               /* Problem: because we map file descriptors to the
+                * same-numbered handle we can't tell the difference
+                * between a bogus handle and the handle to stdin.
+                * Assume that it's the console handle if that handle
+                * exists... */
+               return FALSE;
+       }
 
        destroy = mono_w32handle_unref_core (handle, handle_data);
        if (destroy)
@@ -460,7 +562,7 @@ mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpoi
 
        mono_os_mutex_lock (&scan_mutex);
 
-       for (i = SLOT_INDEX (0); i < private_handles_size; i++) {
+       for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
                if (!private_handles [i])
                        continue;
                for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
@@ -628,6 +730,15 @@ mono_w32handle_unref (gpointer handle)
                w32handle_destroy (handle);
 }
 
+static void
+mono_w32handle_ops_close (gpointer handle, gpointer data);
+
+void
+mono_w32handle_force_close (gpointer handle, gpointer data)
+{
+       mono_w32handle_ops_close (handle, data);
+}
+
 void
 mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
 {
@@ -668,6 +779,24 @@ static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer
        return (NULL);
 }
 
+static void
+mono_w32handle_ops_close (gpointer handle, gpointer data)
+{
+       MonoW32HandleBase *handle_data;
+       MonoW32HandleType type;
+
+       if (!mono_w32handle_lookup_data (handle, &handle_data)) {
+               return;
+       }
+
+       type = handle_data->type;
+
+       if (handle_ops[type] != NULL &&
+           handle_ops[type]->close != NULL) {
+               handle_ops[type]->close (handle, data);
+       }
+}
+
 static void
 mono_w32handle_ops_details (MonoW32HandleType type, gpointer data)
 {
index 24d547952f7c8039df781a670cb3273d44758e1b..b7df9a8810e50fbd9a1400cbdf9e443e0cbf732e 100644 (file)
 
 typedef enum {
        MONO_W32HANDLE_UNUSED = 0,
+       MONO_W32HANDLE_FILE,
+       MONO_W32HANDLE_CONSOLE,
+       MONO_W32HANDLE_THREAD,
        MONO_W32HANDLE_SEM,
        MONO_W32HANDLE_MUTEX,
        MONO_W32HANDLE_EVENT,
+       MONO_W32HANDLE_SOCKET,
        MONO_W32HANDLE_FIND,
        MONO_W32HANDLE_PROCESS,
+       MONO_W32HANDLE_PIPE,
        MONO_W32HANDLE_NAMEDMUTEX,
        MONO_W32HANDLE_NAMEDSEM,
        MONO_W32HANDLE_NAMEDEVENT,
@@ -94,6 +99,8 @@ typedef enum {
        MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
 } MonoW32HandleCapability;
 
+extern guint32 mono_w32handle_fd_reserve;
+
 void
 mono_w32handle_init (void);
 
@@ -106,6 +113,9 @@ mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops);
 gpointer
 mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific);
 
+gpointer
+mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
+
 gpointer
 mono_w32handle_duplicate (gpointer handle);
 
@@ -133,6 +143,9 @@ mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapab
 gboolean
 mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps);
 
+void
+mono_w32handle_force_close (gpointer handle, gpointer data);
+
 void
 mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
 
index 280c3a9213d0a90fd528961ca4c14d878eba7d76..57340e9ed5ae5420cc572ab06bc88cfee7d0150d 100644 (file)
@@ -1945,7 +1945,7 @@ process_create (const gunichar2 *appname, const gunichar2 *cmdline,
                dup2 (err_fd, 2);
 
                /* Close all file descriptors */
-               for (i = eg_getdtablesize() - 1; i > 2; i--)
+               for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
                        close (i);
 
 #ifdef DEBUG_ENABLED
index cf9fb28e466950607f2eee6c681d9ce86c009f40..5122fdf5ed1573a7dc05d877b8709c1aba11441d 100644 (file)
@@ -148,7 +148,4 @@ mono_w32socket_get_last_error (void);
 gint32
 mono_w32socket_convert_error (gint error);
 
-gboolean
-mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle);
-
 #endif // __MONO_METADATA_W32SOCKET_INTERNALS_H__
index bc1b5ccd818d44f09bfa459f94156f2aaaae2b22..5816b142b051e09e6c784e93518bbd9241dbd643 100644 (file)
 #include "w32socket.h"
 #include "w32socket-internals.h"
 #include "w32error.h"
-#include "fdhandle.h"
+#include "w32handle.h"
 #include "utils/mono-logger-internals.h"
 #include "utils/mono-poll.h"
 
 typedef struct {
-       MonoFDHandle fdhandle;
-       gint domain;
-       gint type;
-       gint protocol;
-       gint saved_error;
-       gint still_readable;
-} SocketHandle;
-
-static SocketHandle*
-socket_data_create (MonoFDType type, gint fd)
-{
-       SocketHandle *sockethandle;
-
-       sockethandle = g_new0 (SocketHandle, 1);
-       mono_fdhandle_init ((MonoFDHandle*) sockethandle, type, fd);
+       int domain;
+       int type;
+       int protocol;
+       int saved_error;
+       int still_readable;
+} MonoW32HandleSocket;
 
-       return sockethandle;
-}
+static guint32 in_cleanup = 0;
 
 static void
-socket_data_close (MonoFDHandle *fdhandle)
+socket_close (gpointer handle, gpointer data)
 {
-       MonoThreadInfo *info;
-       SocketHandle* sockethandle;
-       gint ret;
-
-       sockethandle = (SocketHandle*) fdhandle;
-       g_assert (sockethandle);
-
-       info = mono_thread_info_current ();
+       int ret;
+       MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data;
+       MonoThreadInfo *info = mono_thread_info_current ();
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) sockethandle)->fd);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle);
 
        /* Shutdown the socket for reading, to interrupt any potential
         * receives that may be blocking for data.  See bug 75705. */
-       MONO_ENTER_GC_SAFE;
-       shutdown (((MonoFDHandle*) sockethandle)->fd, SHUT_RD);
-       MONO_EXIT_GC_SAFE;
-
-retry_close:
-       MONO_ENTER_GC_SAFE;
-       ret = close (((MonoFDHandle*) sockethandle)->fd);
-       MONO_EXIT_GC_SAFE;
+       shutdown (GPOINTER_TO_UINT (handle), SHUT_RD);
+
+       do {
+               ret = close (GPOINTER_TO_UINT(handle));
+       } while (ret == -1 && errno == EINTR &&
+                !mono_thread_info_is_interrupt_state (info));
+
        if (ret == -1) {
-               if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
-                       goto retry_close;
+               gint errnum = errno;
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno));
+               if (!in_cleanup)
+                       mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
        }
 
-       sockethandle->saved_error = 0;
+       if (!in_cleanup)
+               socket_handle->saved_error = 0;
 }
 
 static void
-socket_data_destroy (MonoFDHandle *fdhandle)
+socket_details (gpointer data)
 {
-       SocketHandle *sockethandle;
+       /* FIXME: do something */
+}
 
-       sockethandle = (SocketHandle*) fdhandle;
-       g_assert (sockethandle);
+static const gchar*
+socket_typename (void)
+{
+       return "Socket";
+}
 
-       g_free (sockethandle);
+static gsize
+socket_typesize (void)
+{
+       return sizeof (MonoW32HandleSocket);
 }
 
+static MonoW32HandleOps ops = {
+       socket_close,    /* close */
+       NULL,            /* signal */
+       NULL,            /* own */
+       NULL,            /* is_owned */
+       NULL,            /* special_wait */
+       NULL,            /* prewait */
+       socket_details,  /* details */
+       socket_typename, /* typename */
+       socket_typesize, /* typesize */
+};
+
 void
 mono_w32socket_initialize (void)
 {
-       MonoFDHandleCallback socket_data_callbacks = {
-               .close = socket_data_close,
-               .destroy = socket_data_destroy
-       };
+       mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &ops);
+}
+
+static gboolean
+cleanup_close (gpointer handle, gpointer data, gpointer user_data)
+{
+       if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET)
+               mono_w32handle_force_close (handle, data);
 
-       mono_fdhandle_register (MONO_FDTYPE_SOCKET, &socket_data_callbacks);
+       return FALSE;
 }
 
 void
 mono_w32socket_cleanup (void)
 {
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__);
+
+       in_cleanup = 1;
+       mono_w32handle_foreach (cleanup_close, NULL);
+       in_cleanup = 0;
 }
 
 SOCKET
 mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking)
 {
-       SocketHandle *sockethandle, *accepted_socket_data;
+       gpointer handle;
+       gpointer new_handle;
+       MonoW32HandleSocket *socket_handle;
+       MonoW32HandleSocket new_socket_handle;
+       SOCKET new_fd;
        MonoThreadInfo *info;
-       gint accepted_fd;
 
        if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
                mono_w32socket_set_last_error (WSAEFAULT);
                return INVALID_SOCKET;
        }
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return INVALID_SOCKET;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return INVALID_SOCKET;
        }
 
        info = mono_thread_info_current ();
 
        do {
-               MONO_ENTER_GC_SAFE;
-               accepted_fd = accept (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
-               MONO_EXIT_GC_SAFE;
-       } while (accepted_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
+               new_fd = accept (sock, addr, addrlen);
+       } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
-       if (accepted_fd == -1) {
-               gint error = mono_w32socket_convert_error (errno);
+       if (new_fd == -1) {
+               gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno));
-               mono_w32socket_set_last_error (error);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
+               mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
+               return INVALID_SOCKET;
+       }
+
+       if (new_fd >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+               mono_w32socket_set_last_error (WSASYSCALLFAILURE);
+
+               close (new_fd);
+
                return INVALID_SOCKET;
        }
 
-       accepted_socket_data = socket_data_create (MONO_FDTYPE_SOCKET, accepted_fd);
-       accepted_socket_data->domain = sockethandle->domain;
-       accepted_socket_data->type = sockethandle->type;
-       accepted_socket_data->protocol = sockethandle->protocol;
-       accepted_socket_data->still_readable = 1;
+       new_socket_handle.domain = socket_handle->domain;
+       new_socket_handle.type = socket_handle->type;
+       new_socket_handle.protocol = socket_handle->protocol;
+       new_socket_handle.still_readable = 1;
 
-       mono_fdhandle_insert ((MonoFDHandle*) accepted_socket_data);
+       new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd,
+                                         &new_socket_handle);
+       if(new_handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating socket handle", __func__);
+               mono_w32socket_set_last_error (ERROR_GEN_FAILURE);
+               return INVALID_SOCKET;
+       }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning accepted handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) accepted_socket_data)->fd));
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
+                  __func__, new_handle);
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-       return ((MonoFDHandle*) accepted_socket_data)->fd;
+       return new_fd;
 }
 
 int
 mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking)
 {
-       SocketHandle *sockethandle;
-       gint ret;
-
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
+       gpointer handle;
+       MonoW32HandleSocket *socket_handle;
 
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       MONO_ENTER_GC_SAFE;
-       ret = connect (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
-       MONO_EXIT_GC_SAFE;
-       if (ret == -1) {
+       if (connect (sock, addr, addrlen) == -1) {
                MonoThreadInfo *info;
                mono_pollfd fds;
                gint errnum, so_error;
@@ -234,41 +251,29 @@ mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, g
                        if (errnum != WSAEWOULDBLOCK) {
                                /* ECONNRESET means the socket was closed by another thread */
                                /* Async close on mac raises ECONNABORTED. */
-                               sockethandle->saved_error = errnum;
+                               socket_handle->saved_error = errnum;
                        }
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
                info = mono_thread_info_current ();
 
-               fds.fd = ((MonoFDHandle*) sockethandle)->fd;
+               fds.fd = sock;
                fds.events = MONO_POLLOUT;
-               for (;;) {
-                       MONO_ENTER_GC_SAFE;
-                       ret = mono_poll (&fds, 1, -1);
-                       MONO_EXIT_GC_SAFE;
-                       if (ret != -1 || mono_thread_info_is_interrupt_state (info))
-                               break;
-
+               while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) {
                        if (errno != EINTR) {
                                gint errnum = errno;
                                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno));
                                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-                               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                                return SOCKET_ERROR;
                        }
                }
 
                len = sizeof(so_error);
-               MONO_ENTER_GC_SAFE;
-               ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
-               MONO_EXIT_GC_SAFE;
-               if (ret == -1) {
+               if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) {
                        gint errnum = errno;
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno));
                        mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
@@ -276,18 +281,16 @@ mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, g
                        gint errnum = mono_w32socket_convert_error (so_error);
 
                        /* Need to save this socket error */
-                       sockethandle->saved_error = errnum;
+                       socket_handle->saved_error = errnum;
 
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
                                   __func__, g_strerror (so_error));
 
                        mono_w32socket_set_last_error (errnum);
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
@@ -300,27 +303,21 @@ mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocki
 int
 mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
+       MonoW32HandleSocket *socket_handle;
        int ret;
        MonoThreadInfo *info;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
        info = mono_thread_info_current ();
 
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = recvfrom (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, from, fromlen);
-               MONO_EXIT_GC_SAFE;
+               ret = recvfrom (sock, buf, len, flags, from, fromlen);
        } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
        if (ret == 0 && len > 0) {
@@ -342,7 +339,7 @@ mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sock
                 * still_readable != 1 then shutdown
                 * (SHUT_RD|SHUT_RDWR) has been called locally.
                 */
-               if (sockethandle->still_readable != 1) {
+               if (socket_handle->still_readable != 1) {
                        ret = -1;
                        errno = EINTR;
                }
@@ -352,10 +349,8 @@ mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sock
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return ret;
 }
 
@@ -382,22 +377,18 @@ msghdr_iov_free (struct msghdr *hdr)
 int
 mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking)
 {
-       SocketHandle *sockethandle;
+       MonoW32HandleSocket *socket_handle;
        MonoThreadInfo *info;
+       gpointer handle;
        gint ret;
        struct msghdr hdr;
 
        g_assert (overlapped == NULL);
        g_assert (complete == NULL);
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -406,16 +397,14 @@ mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32
        wsabuf_to_msghdr (buffers, count, &hdr);
 
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = recvmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, *flags);
-               MONO_EXIT_GC_SAFE;
+               ret = recvmsg (sock, &hdr, *flags);
        } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
        msghdr_iov_free (&hdr);
 
        if (ret == 0) {
                /* see mono_w32socket_recvfrom */
-               if (sockethandle->still_readable != 1) {
+               if (socket_handle->still_readable != 1) {
                        ret = -1;
                        errno = EINTR;
                }
@@ -425,41 +414,32 @@ mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
        *received = ret;
        *flags = hdr.msg_flags;
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 int
 mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        int ret;
        MonoThreadInfo *info;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
        info = mono_thread_info_current ();
 
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = send (((MonoFDHandle*) sockethandle)->fd, buf, len, flags);
-               MONO_EXIT_GC_SAFE;
+               ret = send (sock, buf, len, flags);
        } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
        if (ret == -1) {
@@ -470,55 +450,42 @@ mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocki
                /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
                 * a blocking socket. See bug #599488 */
                if (errnum == EAGAIN) {
-                       MONO_ENTER_GC_SAFE;
-                       ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
-                       MONO_EXIT_GC_SAFE;
+                       ret = fcntl (sock, F_GETFL, 0);
                        if (ret != -1 && (ret & O_NONBLOCK) == 0)
                                errnum = ETIMEDOUT;
                }
 #endif /* O_NONBLOCK */
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return ret;
 }
 
 int
 mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        int ret;
        MonoThreadInfo *info;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
        info = mono_thread_info_current ();
 
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = sendto (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, to, tolen);
-               MONO_EXIT_GC_SAFE;
+               ret = sendto (sock, buf, len, flags, to, tolen);
        } while (ret == -1 && errno == EINTR &&  !mono_thread_info_is_interrupt_state (info));
 
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return ret;
 }
 
@@ -527,20 +494,15 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32
 {
        struct msghdr hdr;
        MonoThreadInfo *info;
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
 
        g_assert (overlapped == NULL);
        g_assert (complete == NULL);
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -549,9 +511,7 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32
        wsabuf_to_msghdr (buffers, count, &hdr);
 
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = sendmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, flags);
-               MONO_EXIT_GC_SAFE;
+               ret = sendmsg (sock, &hdr, flags);
        } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
        msghdr_iov_free (&hdr);
@@ -560,12 +520,10 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
        *sent = ret;
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
@@ -575,7 +533,7 @@ BOOL
 mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
 {
        MonoThreadInfo *info;
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint file;
        gssize ret;
 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
@@ -584,24 +542,17 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B
        gchar *buffer;
 #endif
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
+               return FALSE;
        }
 
        /* Write the header */
        if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
-               ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Head, buffers->HeadLength, 0, FALSE);
-               if (ret == SOCKET_ERROR) {
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
+               ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE);
+               if (ret == SOCKET_ERROR)
                        return FALSE;
-               }
        }
 
        info = mono_thread_info_current ();
@@ -609,44 +560,35 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B
        file = GPOINTER_TO_INT (file_handle);
 
 #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
-       MONO_ENTER_GC_SAFE;
        ret = fstat (file, &statbuf);
-       MONO_EXIT_GC_SAFE;
        if (ret == -1) {
                gint errnum = errno;
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
        do {
-               MONO_ENTER_GC_SAFE;
 #ifdef __linux__
-               ret = sendfile (((MonoFDHandle*) sockethandle)->fd, file, NULL, statbuf.st_size);
+               ret = sendfile (sock, file, NULL, statbuf.st_size);
 #elif defined(DARWIN)
                /* TODO: header/tail could be sent in the 5th argument */
                /* TODO: Might not send the entire file for non-blocking sockets */
-               ret = sendfile (file, ((MonoFDHandle*) sockethandle)->fd, 0, &statbuf.st_size, NULL, 0);
+               ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0);
 #endif
-               MONO_EXIT_GC_SAFE;
        } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 #else
        buffer = g_malloc (SF_BUFFER_SIZE);
 
        do {
                do {
-                       MONO_ENTER_GC_SAFE;
                        ret = read (file, buffer, SF_BUFFER_SIZE);
-                       MONO_EXIT_GC_SAFE;
                } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
                if (ret == -1 || ret == 0)
                        break;
 
                do {
-                       MONO_ENTER_GC_SAFE;
-                       ret = send (((MonoFDHandle*) sockethandle)->fd, buffer, ret, 0); /* short sends? enclose this in a loop? */
-                       MONO_EXIT_GC_SAFE;
+                       ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */
                } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
        } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
 
@@ -656,55 +598,59 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B
        if (ret == -1) {
                gint errnum = errno;
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return FALSE;
        }
 
        /* Write the tail */
        if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
-               ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Tail, buffers->TailLength, 0, FALSE);
-               if (ret == SOCKET_ERROR) {
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
+               ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE);
+               if (ret == SOCKET_ERROR)
                        return FALSE;
-               }
        }
 
        if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
-               mono_w32socket_close (((MonoFDHandle*) sockethandle)->fd);
+               mono_w32handle_close (handle);
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return TRUE;
 }
 
 SOCKET
 mono_w32socket_socket (int domain, int type, int protocol)
 {
-       SocketHandle *sockethandle;
-       gint fd;
-
-retry_socket:
-       MONO_ENTER_GC_SAFE;
-       fd = socket (domain, type, protocol);
-       MONO_EXIT_GC_SAFE;
-       if (fd == -1) {
-               if (domain == AF_INET && type == SOCK_RAW && protocol == 0) {
-                       /* Retry with protocol == 4 (see bug #54565) */
-                       // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
-                       protocol = 4;
-                       goto retry_socket;
-               }
+       MonoW32HandleSocket socket_handle = {0};
+       gpointer handle;
+       SOCKET sock;
+
+       socket_handle.domain = domain;
+       socket_handle.type = type;
+       socket_handle.protocol = protocol;
+       socket_handle.still_readable = 1;
 
+       sock = socket (domain, type, protocol);
+       if (sock == -1 && domain == AF_INET && type == SOCK_RAW &&
+           protocol == 0) {
+               /* Retry with protocol == 4 (see bug #54565) */
+               // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565
+               socket_handle.protocol = 4;
+               sock = socket (AF_INET, SOCK_RAW, 4);
+       }
+
+       if (sock == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
                return INVALID_SOCKET;
        }
 
-       sockethandle = socket_data_create(MONO_FDTYPE_SOCKET, fd);
-       sockethandle->domain = domain;
-       sockethandle->type = type;
-       sockethandle->protocol = protocol;
-       sockethandle->still_readable = 1;
+       if (sock >= mono_w32handle_fd_reserve) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)",
+                          __func__, sock, mono_w32handle_fd_reserve);
+
+               mono_w32socket_set_last_error (WSASYSCALLFAILURE);
+               close (sock);
+
+               return INVALID_SOCKET;
+       }
 
        /* .net seems to set this by default for SOCK_STREAM, not for
         * SOCK_DGRAM (see bug #36322)
@@ -724,142 +670,111 @@ retry_socket:
        {
                int ret, true_ = 1;
 
-               MONO_ENTER_GC_SAFE;
-               ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
-               MONO_EXIT_GC_SAFE;
+               ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_));
                if (ret == -1) {
+                       close (sock);
                        gint errnum = errno;
                        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__);
                        mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-
-                       MONO_ENTER_GC_SAFE;
-                       close (((MonoFDHandle*) sockethandle)->fd);
-                       MONO_EXIT_GC_SAFE;
-
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return INVALID_SOCKET;
                }
        }
 
-       mono_fdhandle_insert ((MonoFDHandle*) sockethandle);
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) sockethandle)->fd));
+       handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, sock, &socket_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating socket handle", __func__);
+               mono_w32socket_set_last_error (WSASYSCALLFAILURE);
+               close (sock);
+               return INVALID_SOCKET;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle);
 
-       return ((MonoFDHandle*) sockethandle)->fd;
+       return sock;
 }
 
 gint
 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        int ret;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       MONO_ENTER_GC_SAFE;
-       ret = bind (((MonoFDHandle*) sockethandle)->fd, addr, addrlen);
-       MONO_EXIT_GC_SAFE;
+       ret = bind (sock, addr, addrlen);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gint
 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       MONO_ENTER_GC_SAFE;
-       ret = getpeername (((MonoFDHandle*) sockethandle)->fd, name, namelen);
-       MONO_EXIT_GC_SAFE;
+       ret = getpeername (sock, name, namelen);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gint
 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       MONO_ENTER_GC_SAFE;
-       ret = getsockname (((MonoFDHandle*) sockethandle)->fd, name, namelen);
-       MONO_EXIT_GC_SAFE;
+       ret = getsockname (sock, name, namelen);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gint
 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
        struct timeval tv;
        gpointer tmp_val;
+       MonoW32HandleSocket *socket_handle;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -870,14 +785,11 @@ mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optva
                *optlen = sizeof (tv);
        }
 
-       MONO_ENTER_GC_SAFE;
-       ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
-       MONO_EXIT_GC_SAFE;
+       ret = getsockopt (sock, level, optname, tmp_val, optlen);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
@@ -889,20 +801,19 @@ mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optva
        if (optname == SO_ERROR) {
                if (*((int *)optval) != 0) {
                        *((int *) optval) = mono_w32socket_convert_error (*((int *)optval));
-                       sockethandle->saved_error = *((int *)optval);
+                       socket_handle->saved_error = *((int *)optval);
                } else {
-                       *((int *)optval) = sockethandle->saved_error;
+                       *((int *)optval) = socket_handle->saved_error;
                }
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gint
 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
        gpointer tmp_val;
 #if defined (__linux__)
@@ -911,14 +822,9 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer
 #endif
        struct timeval tv;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -945,14 +851,11 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer
        }
 #endif
 
-       MONO_ENTER_GC_SAFE;
-       ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen);
-       MONO_EXIT_GC_SAFE;
+       ret = setsockopt (sock, level, optname, tmp_val, optlen);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
@@ -962,94 +865,71 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer
                int type;
                socklen_t type_len = sizeof (type);
 
-               MONO_ENTER_GC_SAFE;
-               ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_TYPE, &type, &type_len);
-               MONO_EXIT_GC_SAFE;
-               if (!ret) {
-                       if (type == SOCK_DGRAM || type == SOCK_STREAM) {
-                               MONO_ENTER_GC_SAFE;
-                               setsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_REUSEPORT, tmp_val, optlen);
-                               MONO_EXIT_GC_SAFE;
-                       }
+               if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) {
+                       if (type == SOCK_DGRAM || type == SOCK_STREAM)
+                               setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen);
                }
        }
 #endif
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return ret;
 }
 
 gint
 mono_w32socket_listen (SOCKET sock, gint backlog)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       MONO_ENTER_GC_SAFE;
-       ret = listen (((MonoFDHandle*) sockethandle)->fd, backlog);
-       MONO_EXIT_GC_SAFE;
+       ret = listen (sock, backlog);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gint
 mono_w32socket_shutdown (SOCKET sock, gint how)
 {
-       SocketHandle *sockethandle;
+       MonoW32HandleSocket *socket_handle;
+       gpointer handle;
        gint ret;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
        if (how == SHUT_RD || how == SHUT_RDWR)
-               sockethandle->still_readable = 0;
+               socket_handle->still_readable = 0;
 
-       MONO_ENTER_GC_SAFE;
-       ret = shutdown (((MonoFDHandle*) sockethandle)->fd, how);
-       MONO_EXIT_GC_SAFE;
+       ret = shutdown (sock, how);
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return ret;
 }
 
 gint
 mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
 {
-       SocketHandle *sockethandle;
+       MonoW32HandleSocket *socket_handle;
+       gpointer handle;
        SOCKET newsock;
        gint ret;
 
@@ -1059,25 +939,17 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
         * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn)
         * if we really wanted to */
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       MONO_ENTER_GC_SAFE;
-       newsock = socket (sockethandle->domain, sockethandle->type, sockethandle->protocol);
-       MONO_EXIT_GC_SAFE;
+       newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol);
        if (newsock == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
@@ -1086,46 +958,32 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
         * should not be a race condition between the old fd being
         * closed and the new socket fd being copied over */
        do {
-               MONO_ENTER_GC_SAFE;
-               ret = dup2 (newsock, ((MonoFDHandle*) sockethandle)->fd);
-               MONO_EXIT_GC_SAFE;
+               ret = dup2 (newsock, sock);
        } while (ret == -1 && errno == EAGAIN);
 
        if (ret == -1) {
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
-       MONO_ENTER_GC_SAFE;
        close (newsock);
-       MONO_EXIT_GC_SAFE;
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 static gboolean
 extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved)
 {
-       gboolean ret;
-       MONO_ENTER_GC_UNSAFE;
-       ret = mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
-       MONO_EXIT_GC_UNSAFE;
-       return ret;
+       return mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0;
 }
 
 static gboolean
 extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send,
        OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags)
 {
-       gboolean ret;
-       MONO_ENTER_GC_UNSAFE;
-       ret = mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
-       MONO_EXIT_GC_UNSAFE;
-       return ret;
+       return mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE);
 }
 
 static struct {
@@ -1140,18 +998,13 @@ static struct {
 gint
 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
 {
-       SocketHandle *sockethandle;
+       gpointer handle;
        gint ret;
        gchar *buffer;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GUINT_TO_POINTER (sock);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -1164,21 +1017,18 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen,
                         * actually set an error here...
                         */
                        mono_w32socket_set_last_error (WSAEINVAL);
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
                if (outputlen < sizeof(gpointer)) {
                        /* Or here... */
                        mono_w32socket_set_last_error (WSAEINVAL);
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
                if (output == NULL) {
                        /* Or here */
                        mono_w32socket_set_last_error (WSAEINVAL);
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
@@ -1187,13 +1037,11 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen,
                        if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
                                memcpy (output, &extension_functions[i].func, sizeof(gpointer));
                                *written = sizeof(gpointer);
-                               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                                return 0;
                        }
                }
 
                mono_w32socket_set_last_error (WSAEINVAL);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
@@ -1202,18 +1050,14 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen,
 
                if (inputlen < 3 * sizeof (guint32)) {
                        mono_w32socket_set_last_error (WSAEINVAL);
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
                onoff = *((guint32*) input);
 
-               MONO_ENTER_GC_SAFE;
-               ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
-               MONO_EXIT_GC_SAFE;
+               ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
                if (ret < 0) {
                        mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return SOCKET_ERROR;
                }
 
@@ -1230,51 +1074,40 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen,
                        keepalivetime /= 1000;
                        if (keepalivetime == 0 || rem >= 500)
                                keepalivetime++;
-                       MONO_ENTER_GC_SAFE;
-                       ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
-                       MONO_EXIT_GC_SAFE;
+                       ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
                        if (ret == 0) {
                                rem = keepaliveinterval % 1000;
                                keepaliveinterval /= 1000;
                                if (keepaliveinterval == 0 || rem >= 500)
                                        keepaliveinterval++;
-                               MONO_ENTER_GC_SAFE;
-                               ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
-                               MONO_EXIT_GC_SAFE;
+                               ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
                        }
                        if (ret != 0) {
                                mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
-                               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                                return SOCKET_ERROR;
                        }
 
-                       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                        return 0;
                }
 #endif
 
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return 0;
        }
 
        buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;
 
-       MONO_ENTER_GC_SAFE;
-       ret = ioctl (((MonoFDHandle*) sockethandle)->fd, command, buffer);
-       MONO_EXIT_GC_SAFE;
+       ret = ioctl (sock, command, buffer);
        if (ret == -1) {
                g_free (buffer);
 
                gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
                mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return SOCKET_ERROR;
        }
 
        if (!buffer) {
                *written = 0;
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
                return 0;
        }
 
@@ -1290,65 +1123,42 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen,
        g_free (buffer);
        *written = inputlen;
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
 gboolean
 mono_w32socket_close (SOCKET sock)
 {
-       if (!mono_fdhandle_close (sock)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       return TRUE;
+       return mono_w32handle_close (GINT_TO_POINTER (sock));
 }
 
 gint
-mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
+mono_w32socket_set_blocking (SOCKET socket, gboolean blocking)
 {
 #ifdef O_NONBLOCK
-       SocketHandle *sockethandle;
        gint ret;
+       gpointer handle;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GINT_TO_POINTER (socket);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
        /* This works better than ioctl(...FIONBIO...)
         * on Linux (it causes connect to return
         * EINPROGRESS, but the ioctl doesn't seem to) */
-       MONO_ENTER_GC_SAFE;
-       ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0);
-       MONO_EXIT_GC_SAFE;
-       if (ret == -1) {
-               gint errnum = mono_w32socket_convert_error (errno);
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_GETFL) error: %s", __func__, g_strerror (errno));
-               mono_w32socket_set_last_error (errnum);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               return SOCKET_ERROR;
-       }
+       ret = fcntl (socket, F_GETFL, 0);
+       if (ret != -1)
+               ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
 
-       MONO_ENTER_GC_SAFE;
-       ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));
-       MONO_EXIT_GC_SAFE;
        if (ret == -1) {
-               gint errnum = mono_w32socket_convert_error (errno);
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_SETFL) error: %s", __func__, g_strerror (errno));
-               mono_w32socket_set_last_error (errnum);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
+               gint errnum = errno;
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
+               mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
                return SOCKET_ERROR;
        }
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 #else
        mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
@@ -1357,19 +1167,14 @@ mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
 }
 
 gint
-mono_w32socket_get_available (SOCKET sock, guint64 *amount)
+mono_w32socket_get_available (SOCKET socket, guint64 *amount)
 {
-       SocketHandle *sockethandle;
        gint ret;
+       gpointer handle;
 
-       if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (WSAENOTSOCK);
-               return SOCKET_ERROR;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (WSAENOTSOCK);
+       handle = GINT_TO_POINTER (socket);
+       if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
+               mono_w32socket_set_last_error (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
@@ -1385,30 +1190,18 @@ mono_w32socket_get_available (SOCKET sock, guint64 *amount)
        // the ip buffer.
 
        socklen_t optlen = sizeof (int);
-       MONO_ENTER_GC_SAFE;
-       ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
-       MONO_EXIT_GC_SAFE;
-       if (ret == -1) {
-               gint errnum = mono_w32socket_convert_error (errno);
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno));
-               mono_w32socket_set_last_error (errnum);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               return SOCKET_ERROR;
-       }
+       ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
 #else
-       MONO_ENTER_GC_SAFE;
-       ret = ioctl (((MonoFDHandle*) sockethandle)->fd, FIONREAD, (gulong*) amount);
-       MONO_EXIT_GC_SAFE;
+       ret = ioctl (socket, FIONREAD, (gulong*) amount);
+#endif
+
        if (ret == -1) {
-               gint errnum = mono_w32socket_convert_error (errno);
+               gint errnum = errno;
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
-               mono_w32socket_set_last_error (errnum);
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
+               mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
                return SOCKET_ERROR;
        }
-#endif
 
-       mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
        return 0;
 }
 
@@ -1555,23 +1348,3 @@ ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, Mo
        return FALSE;
 #endif
 }
-
-gboolean
-mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
-{
-       SocketHandle *sockethandle;
-
-       if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle), (MonoFDHandle**) &sockethandle)) {
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) {
-               mono_fdhandle_unref ((MonoFDHandle*) sockethandle);
-               mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       *duplicate_handle = handle;
-       return TRUE;
-}
index 4f7cc8cdcf555f28ffbf37a6a7c6807192bdeaf6..a3f8d410583248e150c7a930fa068255ad35624f 100644 (file)
@@ -137,19 +137,15 @@ SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrle
 {
        MonoInternalThread *curthread = mono_thread_internal_current ();
        SOCKET newsock = INVALID_SOCKET;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_ACCEPT_BIT, blocking, TRUE, newsock, accept, s, addr, addrlen);
-       MONO_EXIT_GC_SAFE;
        return newsock;
 }
 
 int mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_CONNECT_BIT, blocking, FALSE, ret, connect, s, name, namelen);
        ret = WSAGetLastError () != 0 ? SOCKET_ERROR : 0;
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
@@ -157,54 +153,42 @@ int mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean block
 {
        MonoInternalThread *curthread = mono_thread_internal_current ();
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recv, s, buf, len, flags);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
 int mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recvfrom, s, buf, len, flags, from, fromlen);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
 int mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, WSARecv, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
 int mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, send, s, buf, len, flags);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
 int mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, sendto, s, buf, len, flags, to, tolen);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
 int mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking)
 {
        int ret = SOCKET_ERROR;
-       MONO_ENTER_GC_SAFE;
        ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
-       MONO_EXIT_GC_SAFE;
        return ret;
 }
 
@@ -213,17 +197,12 @@ BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE
 {
        LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket));
 
-       int error = 0, ret;
-
-       MONO_ENTER_GC_SAFE;
-
+       int error = 0;
        if (blocking) {
                OVERLAPPED overlapped = { 0 };
                overlapped.hEvent = WSACreateEvent ();
-               if (overlapped.hEvent == WSA_INVALID_EVENT) {
-                       ret = FALSE;
-                       goto done;
-               }
+               if (overlapped.hEvent == WSA_INVALID_EVENT)
+                       return FALSE;
                if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) {
                        error = WSAGetLastError ();
                        if (error == WSA_IO_PENDING) {
@@ -251,11 +230,7 @@ BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE
                blocking ? "blocking" : "non-blocking", hSocket, error == 0, error));
        WSASetLastError (error);
 
-       ret = error == 0;
-
-done:
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return error == 0;
 }
 #endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
@@ -268,8 +243,6 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
        DWORD output_bytes;
        gint ret;
 
-       MONO_ENTER_GC_SAFE;
-
        /* Use the SIO_GET_EXTENSION_FUNCTION_POINTER to determine
         * the address of the disconnect method without taking
         * a hard dependency on a single provider
@@ -286,54 +259,36 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
        GUID disconnect_guid = WSAID_DISCONNECTEX;
        ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnect_guid, sizeof (GUID), &disconnect, sizeof (LPFN_DISCONNECTEX), &output_bytes, NULL, NULL);
        if (ret == 0) {
-               if (!disconnect (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0)) {
-                       ret = WSAGetLastError ();
-                       goto done;
-               }
+               if (!disconnect (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0))
+                       return WSAGetLastError ();
 
-               ret = 0;
-               goto done;
+               return 0;
        }
 
        GUID transmit_file_guid = WSAID_TRANSMITFILE;
        ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmit_file_guid, sizeof (GUID), &transmit_file, sizeof (LPFN_TRANSMITFILE), &output_bytes, NULL, NULL);
        if (ret == 0) {
-               if (!transmit_file (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0))) {
-                       ret = WSAGetLastError ();
-                       goto done;
-               }
+               if (!transmit_file (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0)))
+                       return WSAGetLastError ();
 
-               ret = 0;
-               goto done;
+               return 0;
        }
 
-       ret = ERROR_NOT_SUPPORTED;
-
-done:
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return ERROR_NOT_SUPPORTED;
 }
 #endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
 gint
 mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
 {
-       gint ret;
        gulong nonblocking_long = !blocking;
-       MONO_ENTER_GC_SAFE;
-       ret = ioctlsocket (sock, FIONBIO, &nonblocking_long);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return ioctlsocket (sock, FIONBIO, &nonblocking_long);
 }
 
 gint
 mono_w32socket_get_available (SOCKET sock, guint64 *amount)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = ioctlsocket (sock, FIONREAD, (int*) amount);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return ioctlsocket (sock, FIONREAD, (int*) amount);
 }
 
 void
@@ -360,15 +315,3 @@ ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, Mo
        error_init (error);
        return TRUE;
 }
-
-gboolean
-mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
-{
-       gboolean ret;
-
-       MONO_ENTER_GC_SAFE;
-       ret = DuplicateHandle (GetCurrentProcess(), handle, GINT_TO_POINTER(targetProcessId), duplicate_handle, 0, 0, 0x00000002 /* DUPLICATE_SAME_ACCESS */);
-       MONO_EXIT_GC_SAFE;
-
-       return ret;
-}
index 9c0053455829860be455830da6f617c57ffb73c4..bd802a67bb1c2c1f7c07a14c70e3b1e9f8a8c468 100644 (file)
@@ -116,101 +116,61 @@ create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gin
 static SOCKET
 mono_w32socket_socket (int domain, int type, int protocol)
 {
-       SOCKET ret;
-       MONO_ENTER_GC_SAFE;
-       ret = WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
 }
 
 static gint
 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = bind (sock, addr, addrlen);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return bind (sock, addr, addrlen);
 }
 
 static gint
 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = getpeername (sock, name, namelen);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return getpeername (sock, name, namelen);
 }
 
 static gint
 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = getsockname (sock, name, namelen);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return getsockname (sock, name, namelen);
 }
 
 static gint
 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = getsockopt (sock, level, optname, optval, optlen);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return getsockopt (sock, level, optname, optval, optlen);
 }
 
 static gint
 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = setsockopt (sock, level, optname, optval, optlen);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return setsockopt (sock, level, optname, optval, optlen);
 }
 
 static gint
 mono_w32socket_listen (SOCKET sock, gint backlog)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = listen (sock, backlog);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return listen (sock, backlog);
 }
 
 static gint
 mono_w32socket_shutdown (SOCKET sock, gint how)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = shutdown (sock, how);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return shutdown (sock, how);
 }
 
 static gint
 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
 {
-       gint ret;
-       MONO_ENTER_GC_SAFE;
-       ret = WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL);
 }
 
 static gboolean
 mono_w32socket_close (SOCKET sock)
 {
-       gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       ret = CloseHandle (sock);
-       MONO_EXIT_GC_SAFE;
-       return ret;
+       return CloseHandle (sock);
 }
 
 #endif /* HOST_WIN32 */
@@ -785,7 +745,9 @@ ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror,
         * polling system does not notify when the socket is closed */
        mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock));
 
+       MONO_ENTER_GC_SAFE;
        mono_w32socket_close ((SOCKET) sock);
+       MONO_EXIT_GC_SAFE;
 }
 
 gint32
@@ -843,7 +805,10 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror,
                return NULL;
        }
 
+       MONO_ENTER_GC_SAFE;
        newsock = mono_w32socket_accept (sock, NULL, 0, blocking);
+       MONO_EXIT_GC_SAFE;
+
        if (newsock == INVALID_SOCKET)
                *werror = mono_w32socket_get_last_error ();
 
@@ -865,7 +830,12 @@ ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog,
        error_init (error);
        *werror = 0;
 
+       MONO_ENTER_GC_SAFE;
+
        ret = mono_w32socket_listen (sock, backlog);
+
+       MONO_EXIT_GC_SAFE;
+
        if (ret == SOCKET_ERROR)
                *werror = mono_w32socket_get_last_error ();
 }
@@ -1061,7 +1031,12 @@ ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 a
        }
        sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
 
+       MONO_ENTER_GC_SAFE;
+
        ret = mono_w32socket_getsockname (sock, (struct sockaddr *)sa, &salen);
+
+       MONO_EXIT_GC_SAFE;
+       
        if (ret == SOCKET_ERROR) {
                *werror = mono_w32socket_get_last_error ();
                if (salen > 128)
@@ -1095,7 +1070,12 @@ ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32
        sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
        /* Note: linux returns just 2 for AF_UNIX. Always. */
 
+       MONO_ENTER_GC_SAFE;
+
        ret = mono_w32socket_getpeername (sock, (struct sockaddr *)sa, &salen);
+
+       MONO_EXIT_GC_SAFE;
+
        if (ret == SOCKET_ERROR) {
                *werror = mono_w32socket_get_last_error ();
                if (salen > 128)
@@ -1378,7 +1358,10 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObjectHand
                return;
        }
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_connect (sock, sa, sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
+
        if (ret == SOCKET_ERROR)
                *werror = mono_w32socket_get_last_error ();
 
@@ -1406,7 +1389,9 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean
                return;
        }
 
+       MONO_ENTER_GC_SAFE;
        *werror = mono_w32socket_disconnect (sock, reuse);
+       MONO_EXIT_GC_SAFE;
 
        mono_thread_info_uninstall_interrupt (&interrupted);
        if (interrupted)
@@ -1414,20 +1399,6 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean
 }
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
-MonoBoolean
-ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle, gint32 *werror, MonoError *error)
-{
-       error_init (error);
-
-       *werror = 0;
-       if (!mono_w32socket_duplicate (handle, targetProcessId, duplicate_handle)) {
-               *werror = mono_w32error_get_last ();
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
 gint32
 ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
 {
@@ -1457,7 +1428,9 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandl
        uint32_t gchandle;
        gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_recv (sock, buf, count, recvflags, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
        
@@ -1502,7 +1475,9 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArra
        uint32_t gchandle;
        WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_recvbuffers (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
 
@@ -1559,7 +1534,9 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArrayH
        uint32_t gchandle;
        buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
 
@@ -1629,7 +1606,9 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArrayHandle b
        uint32_t gchandle;
        gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_send (sock, buf, count, sendflags, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
 
@@ -1674,7 +1653,9 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArrayHa
        uint32_t gchandle;
        WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_sendbuffers (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
 
@@ -1734,7 +1715,9 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArrayHandle
        uint32_t gchandle;
        gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_sendto (sock, buf, count, sendflags, sa, sa_size, blocking);
+       MONO_EXIT_GC_SAFE;
 
        mono_gchandle_free (gchandle);
 
@@ -1982,6 +1965,8 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gi
                return;
        }
 
+       MONO_ENTER_GC_SAFE;
+
        /* No need to deal with MulticastOption names here, because
         * you cant getsockopt AddMembership or DropMembership (the
         * int getsockopt will error, causing an exception)
@@ -2007,6 +1992,8 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gi
                ret = mono_w32socket_getsockopt (sock, system_level, system_name, &val, &valsize);
        }
 
+       MONO_EXIT_GC_SAFE;
+
        if (ret == SOCKET_ERROR) {
                *werror = mono_w32socket_get_last_error ();
                return;
@@ -2124,8 +2111,12 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gi
        uint32_t gchandle;
        guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle);
 
+       MONO_ENTER_GC_SAFE;
+
        ret = mono_w32socket_getsockopt (sock, system_level, system_name, buf, &valsize);
 
+       MONO_EXIT_GC_SAFE;
+
        mono_gchandle_free (gchandle);
 
        if (ret == SOCKET_ERROR)
@@ -2434,8 +2425,13 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, g
                return;
        }
 
+       MONO_ENTER_GC_SAFE;
+
        /* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
        ret = mono_w32socket_shutdown (sock, how);
+
+       MONO_EXIT_GC_SAFE;
+
        if (ret == SOCKET_ERROR)
                *werror = mono_w32socket_get_last_error ();
 
@@ -2480,8 +2476,12 @@ ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code,
                o_buffer = MONO_ARRAY_HANDLE_PIN (output, gchar, 0, &o_gchandle);
        }
 
+       MONO_ENTER_GC_SAFE;
+
        ret = mono_w32socket_ioctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes);
 
+       MONO_EXIT_GC_SAFE;
+
        if (i_gchandle)
                mono_gchandle_free (i_gchandle);
        if (o_gchandle)
@@ -2709,14 +2709,14 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
 
        g_free (address);
 
+       MONO_ENTER_GC_SAFE;
+
        switch (family) {
        case AF_INET: {
 #if HAVE_SOCKADDR_IN_SIN_LEN
                saddr.sin_len = sizeof (saddr);
 #endif
-               MONO_ENTER_GC_SAFE;
                ret = getnameinfo ((struct sockaddr*)&saddr, sizeof (saddr), hostname, sizeof (hostname), NULL, 0, 0) == 0;
-               MONO_EXIT_GC_SAFE;
                break;
        }
 #ifdef HAVE_STRUCT_SOCKADDR_IN6
@@ -2724,9 +2724,7 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
 #if HAVE_SOCKADDR_IN6_SIN_LEN
                saddr6.sin6_len = sizeof (saddr6);
 #endif
-               MONO_ENTER_GC_SAFE;
                ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof (saddr6), hostname, sizeof (hostname), NULL, 0, 0) == 0;
-               MONO_EXIT_GC_SAFE;
                break;
        }
 #endif
@@ -2734,6 +2732,8 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
                g_assert_not_reached ();
        }
 
+       MONO_EXIT_GC_SAFE;
+
        if (!ret)
                return FALSE;
 
@@ -2807,7 +2807,9 @@ ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHan
                buffers.TailLength = mono_array_handle_length (post_buffer);
        }
 
+       MONO_ENTER_GC_SAFE;
        ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking);
+       MONO_EXIT_GC_SAFE;
 
        if (pre_buffer_gchandle)
                mono_gchandle_free (pre_buffer_gchandle);
index 9fcd2341d7825e05b7aeb5065ce87acc0d2f94d0..1788e2175bd517655a0c2125a03587ec53b7b38d 100644 (file)
@@ -278,9 +278,6 @@ ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint t
 void
 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror, MonoError *error);
 
-MonoBoolean
-ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle, gint32 *werror, MonoError *error);
-
 gboolean
 ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHandle filename,
                                                       MonoArrayHandle pre_buffer, MonoArrayHandle post_buffer,