Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / w32file-unix.c
index 734b43b41f629ccad056873ed12050c78d9db1a1..448cd8c2e5a0dbb4615fe283f8c80a904b8c0b87 100644 (file)
@@ -40,6 +40,7 @@
 #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"
@@ -59,14 +60,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;
-} MonoW32HandleFile;
+} FileHandle;
 
 typedef struct {
        gchar **namelist;
@@ -93,6 +94,63 @@ 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)
 {
@@ -102,8 +160,10 @@ 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);
 }
@@ -721,11 +781,6 @@ _wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
 static gboolean
 _wapi_lock_file_region (gint fd, off_t offset, off_t length)
 {
-#if defined(__native_client__)
-       printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
-       // behave as below -- locks are not available
-       return TRUE;
-#else
        struct flock lock_data;
        gint ret;
 
@@ -766,16 +821,11 @@ _wapi_lock_file_region (gint fd, off_t offset, off_t length)
        }
 
        return TRUE;
-#endif /* __native_client__ */
 }
 
 static gboolean
 _wapi_unlock_file_region (gint fd, off_t offset, off_t length)
 {
-#if defined(__native_client__)
-       printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
-       return TRUE;
-#else
        struct flock lock_data;
        gint ret;
 
@@ -811,68 +861,17 @@ _wapi_unlock_file_region (gint fd, off_t offset, off_t length)
        }
 
        return TRUE;
-#endif /* __native_client__ */
 }
 
-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);
-
-/* 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)
+{
+       return "Find";
+}
 
-static const gchar* find_typename (void);
-static gsize find_typesize (void);
+static gsize find_typesize (void)
+{
+       return sizeof (MonoW32HandleFind);
+}
 
 static MonoW32HandleOps _wapi_find_ops = {
        NULL,                   /* close */
@@ -886,85 +885,6 @@ 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.
@@ -1098,88 +1018,18 @@ 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(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       MonoW32HandleFile *file_handle;
-       gboolean ok;
-       gint fd, ret;
+       gint 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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1187,7 +1037,7 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret = read (fd, buffer, numbytes);
+               ret = read (((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -1195,8 +1045,7 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread
        if(ret==-1) {
                gint err = errno;
 
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
-                         handle, strerror(err));
+               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_w32error_set_last (mono_w32error_unix_to_win32 (err));
                return(FALSE);
        }
@@ -1209,32 +1058,18 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread
 }
 
 static gboolean
-file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       MonoW32HandleFile *file_handle;
-       gboolean ok;
-       gint ret, fd;
+       gint ret;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1246,17 +1081,15 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                 * systems
                 */
                MONO_ENTER_GC_SAFE;
-               current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+               current_pos = lseek (((MonoFDHandle*) filehandle)->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: handle %p lseek failed: %s", __func__,
-                                  handle, strerror (errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror (errno));
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
                }
                
-               if (_wapi_lock_file_region (fd, current_pos,
-                                           numbytes) == FALSE) {
+               if (_wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes) == FALSE) {
                        /* The error has already been set */
                        return(FALSE);
                }
@@ -1264,13 +1097,13 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write (fd, buffer, numbytes);
+               ret = write (((MonoFDHandle*) filehandle)->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 (fd, current_pos, numbytes);
+               _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes);
        }
 
        if (ret == -1) {
@@ -1279,8 +1112,7 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                } else {
                        _wapi_set_last_error_from_errno ();
                                
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
-                                 __func__, handle, strerror(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));
 
                        return(FALSE);
                }
@@ -1291,37 +1123,22 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
        return(TRUE);
 }
 
-static gboolean file_flush(gpointer handle)
+static gboolean file_flush(FileHandle *filehandle)
 {
-       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);
-       }
-
-       fd = file_handle->fd;
+       gint ret;
 
-       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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
        MONO_ENTER_GC_SAFE;
-       ret=fsync(fd);
+       ret=fsync(((MonoFDHandle*) filehandle)->fd);
        MONO_EXIT_GC_SAFE;
        if (ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
-                         strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1330,30 +1147,15 @@ static gboolean file_flush(gpointer handle)
        return(TRUE);
 }
 
-static guint32 file_seek(gpointer handle, gint32 movedistance,
+static guint32 file_seek(FileHandle *filehandle, gint32 movedistance,
                         gint32 *highmovedistance, gint method)
 {
-       MonoW32HandleFile *file_handle;
-       gboolean ok;
        gint64 offset, newpos;
-       gint whence, fd;
+       gint whence;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(INVALID_SET_FILE_POINTER);
@@ -1379,39 +1181,38 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 #ifdef HAVE_LARGE_FILE_SUPPORT
        if(highmovedistance==NULL) {
                offset=movedistance;
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld (low %d)", __func__,
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %" G_GINT64_FORMAT " (low %" G_GINT32_FORMAT ")", __func__,
                          offset, movedistance);
        } else {
                offset=((gint64) *highmovedistance << 32) | (guint32)movedistance;
                
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %" G_GINT64_FORMAT " 0x%" PRIx64 " (high %" G_GINT32_FORMAT " 0x%" PRIx32 ", low %" G_GINT32_FORMAT " 0x%" PRIx32 ")",
+                         __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
        }
 #else
        offset=movedistance;
 #endif
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %lld bytes from %d", __func__,
-                  handle, (long long)offset, whence);
+       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);
 
-#ifdef PLATFORM_ANDROID
+#ifdef HOST_ANDROID
        /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
        MONO_ENTER_GC_SAFE;
-       newpos=lseek64(fd, offset, whence);
+       newpos=lseek64(((MonoFDHandle*) filehandle)->fd, offset, whence);
        MONO_EXIT_GC_SAFE;
 #else
        MONO_ENTER_GC_SAFE;
-       newpos=lseek(fd, offset, whence);
+       newpos=lseek(((MonoFDHandle*) filehandle)->fd, offset, whence);
        MONO_EXIT_GC_SAFE;
 #endif
        if(newpos==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
-                         __func__, handle, strerror(errno));
+               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));
 
                _wapi_set_last_error_from_errno ();
                return(INVALID_SET_FILE_POINTER);
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %" G_GINT64_FORMAT, __func__, newpos);
 
 #ifdef HAVE_LARGE_FILE_SUPPORT
        ret=newpos & 0xFFFFFFFF;
@@ -1426,34 +1227,20 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        }
 #endif
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %d/%d", __func__,
-                  handle, ret, highmovedistance==NULL?0:*highmovedistance);
+       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);
 
        return(ret);
 }
 
-static gboolean file_setendoffile(gpointer handle)
+static gboolean file_setendoffile(FileHandle *filehandle)
 {
-       MonoW32HandleFile *file_handle;
-       gboolean ok;
        struct stat statbuf;
        off_t pos;
-       gint ret, fd;
+       gint 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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1466,22 +1253,20 @@ static gboolean file_setendoffile(gpointer handle)
         */
        
        MONO_ENTER_GC_SAFE;
-       ret=fstat(fd, &statbuf);
+       ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
-                          handle, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
 
        MONO_ENTER_GC_SAFE;
-       pos=lseek(fd, (off_t)0, SEEK_CUR);
+       pos=lseek(((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR);
        MONO_EXIT_GC_SAFE;
        if(pos==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
-                         handle, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1503,13 +1288,13 @@ static gboolean file_setendoffile(gpointer handle)
                 */
                do {
                        MONO_ENTER_GC_SAFE;
-                       ret = write (fd, "", 1);
+                       ret = write (((MonoFDHandle*) filehandle)->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: handle %p extend write failed: %s", __func__, handle, strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d extend write failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
@@ -1517,11 +1302,10 @@ static gboolean file_setendoffile(gpointer handle)
 
                /* And put the file position back after the write */
                MONO_ENTER_GC_SAFE;
-               ret = lseek (fd, pos, SEEK_SET);
+               ret = lseek (((MonoFDHandle*) filehandle)->fd, pos, SEEK_SET);
                MONO_EXIT_GC_SAFE;
                if (ret == -1) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
-                                  __func__, handle, strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d second lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(FALSE);
@@ -1529,52 +1313,33 @@ static gboolean file_setendoffile(gpointer handle)
        }
 #endif
 
-/* Native Client has no ftruncate function, even in standalone sel_ldr. */
-#ifndef __native_client__
        /* always truncate, because the extend write() adds an extra
         * byte to the end of the file
         */
        do {
                MONO_ENTER_GC_SAFE;
-               ret=ftruncate(fd, pos);
+               ret=ftruncate(((MonoFDHandle*) filehandle)->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: handle %p ftruncate failed: %s", __func__,
-                         handle, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ftruncate failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
                
                _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
-#endif
                
        return(TRUE);
 }
 
-static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
+static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize)
 {
-       MonoW32HandleFile *file_handle;
-       gboolean ok;
        struct stat statbuf;
        guint32 size;
        gint ret;
-       gint 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(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(INVALID_FILE_SIZE);
@@ -1587,11 +1352,10 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        mono_w32error_set_last (ERROR_SUCCESS);
        
        MONO_ENTER_GC_SAFE;
-       ret = fstat(fd, &statbuf);
+       ret = fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if (ret == -1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
-                          handle, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(INVALID_FILE_SIZE);
@@ -1603,11 +1367,10 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
                guint64 bigsize;
                gint res;
                MONO_ENTER_GC_SAFE;
-               res = ioctl (fd, BLKGETSIZE64, &bigsize);
+               res = ioctl (((MonoFDHandle*) filehandle)->fd, BLKGETSIZE64, &bigsize);
                MONO_EXIT_GC_SAFE;
                if (res < 0) {
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
-                                  __func__, handle, strerror(errno));
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ioctl BLKGETSIZE64 failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                        _wapi_set_last_error_from_errno ();
                        return(INVALID_FILE_SIZE);
@@ -1618,7 +1381,7 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
                        *highsize = bigsize>>32;
                }
 
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT,
                           __func__, size, *highsize);
        
                return(size);
@@ -1638,46 +1401,31 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
        size = statbuf.st_size;
 #endif
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT, __func__, size, *highsize);
        
        return(size);
 }
 
-static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+static gboolean file_getfiletime(FileHandle *filehandle, 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, 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;
+       gint ret;
 
-       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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
        MONO_ENTER_GC_SAFE;
-       ret=fstat(fd, &statbuf);
+       ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
-                         strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1704,7 +1452,7 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
        access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
        write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %" G_GUINT64_FORMAT " cticks: %" G_GUINT64_FORMAT " wticks: %" G_GUINT64_FORMAT, __func__,
                  access_ticks, create_ticks, write_ticks);
 
        if(create_time!=NULL) {
@@ -1725,38 +1473,26 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
        return(TRUE);
 }
 
-static gboolean file_setfiletime(gpointer handle,
+static gboolean file_setfiletime(FileHandle *filehandle,
                                 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, fd;
+       gint 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(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
-       if(file_handle->filename == NULL) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
+       if(filehandle->filename == NULL) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d unknown filename", __func__, ((MonoFDHandle*) filehandle)->fd);
 
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
                return(FALSE);
@@ -1766,11 +1502,10 @@ static gboolean file_setfiletime(gpointer handle,
         * the event that one of the FileTime structs is NULL
         */
        MONO_ENTER_GC_SAFE;
-       ret=fstat (fd, &statbuf);
+       ret=fstat (((MonoFDHandle*) filehandle)->fd, &statbuf);
        MONO_EXIT_GC_SAFE;
        if(ret==-1) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
-                         strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno));
 
                mono_w32error_set_last (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -1825,13 +1560,12 @@ static gboolean file_setfiletime(gpointer handle,
                utbuf.modtime=statbuf.st_mtime;
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
-                  handle, utbuf.actime, utbuf.modtime);
+       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);
 
-       ret = _wapi_utime (file_handle->filename, &utbuf);
+       ret = _wapi_utime (filehandle->filename, &utbuf);
        if (ret == -1) {
-               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_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_w32error_set_last (ERROR_INVALID_PARAMETER);
                return(FALSE);
@@ -1840,73 +1574,18 @@ static gboolean file_setfiletime(gpointer handle,
        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(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       MonoW32HandleFile *console_handle;
-       gboolean ok;
-       gint ret, fd;
+       gint ret;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1914,13 +1593,12 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr
        
        do {
                MONO_ENTER_GC_SAFE;
-               ret=read(fd, buffer, numbytes);
+               ret=read(((MonoFDHandle*) filehandle)->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 handle %p error: %s", __func__, handle,
-                         strerror(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));
 
                _wapi_set_last_error_from_errno ();
                return(FALSE);
@@ -1934,30 +1612,17 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr
 }
 
 static gboolean
-console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       MonoW32HandleFile *console_handle;
-       gboolean ok;
-       gint ret, fd;
+       gint ret;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -1965,7 +1630,7 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *
        
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write(fd, buffer, numbytes);
+               ret = write(((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -1976,8 +1641,7 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
-                                  __func__, handle, strerror(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));
 
                        return(FALSE);
                }
@@ -1989,93 +1653,28 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *
        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 (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       MonoW32HandleFile *pipe_handle;
-       gboolean ok;
-       gint ret, fd;
+       gint ret;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
-                  numbytes, handle);
+       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);
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret=read(fd, buffer, numbytes);
+               ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
                
@@ -2085,14 +1684,13 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
-                                 handle, strerror(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));
 
                        return(FALSE);
                }
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %d", __func__, ret, ((MonoFDHandle*) filehandle)->fd);
 
        if(bytesread!=NULL) {
                *bytesread=ret;
@@ -2102,41 +1700,27 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea
 }
 
 static gboolean
-pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+pipe_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       MonoW32HandleFile *pipe_handle;
-       gboolean ok;
-       gint ret, fd;
+       gint ret;
        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(!(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);
+       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);
 
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
-                  handle);
+       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);
 
        do {
                MONO_ENTER_GC_SAFE;
-               ret = write (fd, buffer, numbytes);
+               ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes);
                MONO_EXIT_GC_SAFE;
        } while (ret == -1 && errno == EINTR &&
                 !mono_thread_info_is_interrupt_state (info));
@@ -2147,8 +1731,7 @@ pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt
                } else {
                        _wapi_set_last_error_from_errno ();
                        
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
-                                 handle, strerror(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));
 
                        return(FALSE);
                }
@@ -2175,7 +1758,7 @@ static gint convert_flags(guint32 fileaccess, guint32 createmode)
                flags=O_RDWR;
                break;
        default:
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%" PRIx32, __func__,
                          fileaccess);
                break;
        }
@@ -2196,7 +1779,7 @@ static gint convert_flags(guint32 fileaccess, guint32 createmode)
                flags|=O_TRUNC;
                break;
        default:
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%" PRIx32, __func__,
                          createmode);
                break;
        }
@@ -2236,9 +1819,10 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                 */
                if (file_existing_share == 0) {
                        /* Quick and easy, no possibility to share */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+                       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);
                }
@@ -2248,9 +1832,10 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                    ((file_existing_share == FILE_SHARE_WRITE) &&
                     (fileaccess != GENERIC_WRITE))) {
                        /* New access mode doesn't match up */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+                       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);
                }
@@ -2260,9 +1845,10 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
                    ((file_existing_access & GENERIC_WRITE) &&
                     !(sharemode & FILE_SHARE_WRITE))) {
                        /* New share mode doesn't match up */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+                       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);
                }
@@ -2289,18 +1875,20 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info)
                 */
                if (file_existing_share == 0) {
                        /* Quick and easy, no possibility to share */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, (*share_info)->access);
+                       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);
                }
 
                if (!(file_existing_share & FILE_SHARE_DELETE)) {
                        /* New access mode doesn't match up */
-                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, (*share_info)->access, file_existing_share);
+                       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);
                }
@@ -2314,8 +1902,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)
 {
-       MonoW32HandleFile file_handle = {0};
-       gpointer handle;
+       FileHandle *filehandle;
+       MonoFDType type;
        gint flags=convert_flags(fileaccess, createmode);
        /*mode_t perms=convert_perms(sharemode);*/
        /* we don't use sharemode, because that relates to sharing of
@@ -2326,7 +1914,6 @@ 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)
@@ -2352,7 +1939,7 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
                return(INVALID_HANDLE_VALUE);
        }
        
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%x and access 0x%x", __func__,
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%" PRIx32 " and access 0x%" PRIx32, __func__,
                   filename, sharemode, fileaccess);
        
        fd = _wapi_open (filename, flags, perms);
@@ -2372,88 +1959,77 @@ 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,
-                         strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, g_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, strerror (errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, filename, g_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);
        }
-#ifdef __native_client__
-       /* Workaround: Native Client currently returns the same fake inode
-        * for all files, so do a simple hash on the filename so we don't
-        * use the same share info for each file.
-        */
-       statbuf.st_ino = g_str_hash(filename);
+
+#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;
+       }
 
-       if (share_allows_open (&statbuf, sharemode, fileaccess,
-                        &file_handle.share_info) == FALSE) {
+       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)) {
                mono_w32error_set_last (ERROR_SHARING_VIOLATION);
-               g_free (filename);
                MONO_ENTER_GC_SAFE;
-               close (fd);
+               close (((MonoFDHandle*) filehandle)->fd);
                MONO_EXIT_GC_SAFE;
                
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return (INVALID_HANDLE_VALUE);
        }
-       if (file_handle.share_info == NULL) {
+       if (!filehandle->share_info) {
                /* 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 (fd);
+               close (((MonoFDHandle*) filehandle)->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 (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+               posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
                MONO_EXIT_GC_SAFE;
        }
        if (attrs & FILE_FLAG_RANDOM_ACCESS) {
                MONO_ENTER_GC_SAFE;
-               posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
+               posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_RANDOM);
                MONO_EXIT_GC_SAFE;
        }
 #endif
@@ -2461,56 +2037,27 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode
 #ifdef F_RDAHEAD
        if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) {
                MONO_ENTER_GC_SAFE;
-               fcntl(fd, F_RDAHEAD, 1);
+               fcntl(((MonoFDHandle*) filehandle)->fd, F_RDAHEAD, 1);
                MONO_EXIT_GC_SAFE;
        }
 #endif
 
-#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;
-       }
+       mono_fdhandle_insert ((MonoFDHandle*) filehandle);
 
-       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);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd));
+
+       return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd);
 }
 
 gboolean
 mono_w32file_close (gpointer handle)
 {
-       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;
+       if (!mono_fdhandle_close (GPOINTER_TO_INT (handle))) {
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       return TRUE;
 }
 
 gboolean mono_w32file_delete(const gunichar2 *name)
@@ -2518,7 +2065,6 @@ gboolean mono_w32file_delete(const gunichar2 *name)
        gchar *filename;
        gint retval;
        gboolean ret = FALSE;
-       guint32 attrs;
 #if 0
        struct stat statbuf;
        FileShare *shareinfo;
@@ -2539,14 +2085,6 @@ gboolean mono_w32file_delete(const gunichar2 *name)
                return(FALSE);
        }
 
-       attrs = mono_w32file_get_attributes (name);
-       if (attrs == INVALID_FILE_ATTRIBUTES) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
-               /* Error set by mono_w32file_get_attributes() */
-               g_free (filename);
-               return(FALSE);
-       }
-
 #if 0
        /* Check to make sure sharing allows us to open the file for
         * writing.  See bug 323389.
@@ -2574,6 +2112,19 @@ gboolean mono_w32file_delete(const gunichar2 *name)
        retval = _wapi_unlink (filename);
        
        if (retval == -1) {
+               /* On linux, calling unlink on an non-existing file in a read-only mount will fail with EROFS.
+                * The expected behavior is for this function to return FALSE and not trigger an exception.
+                * To work around this behavior, we stat the file on failure.
+                *
+                * This was supposedly fixed on kernel 3.0 [1] but we could reproduce it with Ubuntu 16.04 which has kernel 4.4.
+                * We can't remove this workaround until the early 2020's when most Android deviced will have a fix.
+                * [1] https://github.com/torvalds/linux/commit/50338b889dc504c69e0cb316ac92d1b9e51f3c8a
+                */
+               if (errno == EROFS) {
+                       MonoIOStat stat;
+                       if (mono_w32file_get_attributes_ex (name, &stat)) //The file exists, so must be due the RO file system
+                               errno = EROFS;
+               }
                _wapi_set_last_path_error_from_errno (NULL, filename);
        } else {
                ret = TRUE;
@@ -2660,8 +2211,10 @@ 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;
@@ -2895,7 +2448,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, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, g_strerror(errno));
        
        g_free (utf8_src);
        g_free (utf8_dest);
@@ -2986,18 +2539,14 @@ replace_cleanup:
        return ret;
 }
 
-static MonoCoopMutex stdhandle_mutex;
-
 static gpointer
 _wapi_stdhandle_create (gint fd, const gchar *name)
 {
-       gpointer handle;
        gint flags;
-       MonoW32HandleFile file_handle = {0};
+       FileHandle *filehandle;
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd);
 
-#if !defined(__native_client__)
        /* Check if fd is valid */
        do {
                flags = fcntl(fd, F_GETFL);
@@ -3007,59 +2556,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, strerror(errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, g_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:
-               file_handle.fileaccess = GENERIC_READ;
+               filehandle->fileaccess = GENERIC_READ;
                break;
        case O_WRONLY:
-               file_handle.fileaccess = GENERIC_WRITE;
+               filehandle->fileaccess = GENERIC_WRITE;
                break;
        case O_RDWR:
-               file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE;
+               filehandle->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);
-               file_handle.fileaccess = 0;
+               filehandle->fileaccess = 0;
                break;
        }
-#else
-       /*
-        * fcntl will return -1 in nacl, as there is no real file system API.
-        * Yet, standard streams are available.
-        */
-       file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
-#endif
 
-       file_handle.fd = fd;
-       file_handle.filename = g_strdup(name);
        /* some default security attributes might be needed */
-       file_handle.security_attributes = 0;
+       filehandle->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)
-               file_handle.fileaccess &= ~GENERIC_WRITE;
+               filehandle->fileaccess &= ~GENERIC_WRITE;
 
-       file_handle.sharemode = 0;
-       file_handle.attrs = 0;
+       filehandle->sharemode = 0;
+       filehandle->attrs = 0;
 
-       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;
+       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);
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd));
 
-       return handle;
+       return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd);
 }
 
 enum {
@@ -3071,11 +2613,9 @@ enum {
 static gpointer
 mono_w32file_get_std_handle (gint stdhandle)
 {
-       MonoW32HandleFile *file_handle;
-       gpointer handle;
+       FileHandle **filehandle;
        gint fd;
        const gchar *name;
-       gboolean ok;
        
        switch(stdhandle) {
        case STD_INPUT_HANDLE:
@@ -3097,167 +2637,260 @@ mono_w32file_get_std_handle (gint stdhandle)
                g_assert_not_reached ();
        }
 
-       handle = GINT_TO_POINTER (fd);
-
-       mono_coop_mutex_lock (&stdhandle_mutex);
+       if (!mono_fdhandle_lookup_and_ref(fd, (MonoFDHandle**) &filehandle)) {
+               gpointer handle;
 
-       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);
-                       goto done;
+                       return INVALID_HANDLE_VALUE;
                }
-       } else {
-               /* Add a reference to this handle */
-               mono_w32handle_ref (handle);
        }
-       
-  done:
-       mono_coop_mutex_unlock (&stdhandle_mutex);
 
-       return(handle);
+       return GINT_TO_POINTER (fd);
 }
 
 gboolean
 mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].readfile==NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].readfile (handle, buffer, numbytes, bytesread));
+
+       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:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gboolean
 mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].writefile==NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten));
+
+       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:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gboolean
 mono_w32file_flush (gpointer handle)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if(io_ops[type].flushfile==NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].flushfile (handle));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_flush(filehandle);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gboolean
 mono_w32file_truncate (gpointer handle)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].setendoffile == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].setendoffile (handle));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_setendoffile(filehandle);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 guint32
 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       guint32 ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].seek == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(INVALID_SET_FILE_POINTER);
+               return INVALID_SET_FILE_POINTER;
        }
-       
-       return(io_ops[type].seek (handle, movedistance, highmovedistance,
-                                 method));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_seek(filehandle, movedistance, highmovedistance, method);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return INVALID_SET_FILE_POINTER;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gint
 mono_w32file_get_type(gpointer handle)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gint ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfiletype == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FILE_TYPE_UNKNOWN);
+               return FILE_TYPE_UNKNOWN;
        }
-       
-       return(io_ops[type].getfiletype ());
+
+       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:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FILE_TYPE_UNKNOWN;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 static guint32
 GetFileSize(gpointer handle, guint32 *highsize)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       guint32 ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfilesize == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(INVALID_FILE_SIZE);
+               return INVALID_FILE_SIZE;
        }
-       
-       return(io_ops[type].getfilesize (handle, highsize));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_getfilesize(filehandle, highsize);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return INVALID_FILE_SIZE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gboolean
 mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].getfiletime == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].getfiletime (handle, create_time, access_time,
-                                        write_time));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_getfiletime(filehandle, create_time, access_time, write_time);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 gboolean
 mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
 {
-       MonoW32HandleType type;
+       FileHandle *filehandle;
+       gboolean ret;
 
-       type = mono_w32handle_get_type (handle);
-       
-       if (io_ops[type].setfiletime == NULL) {
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
-               return(FALSE);
+               return FALSE;
        }
-       
-       return(io_ops[type].setfiletime (handle, create_time, access_time,
-                                        write_time));
+
+       switch (((MonoFDHandle*) filehandle)->type) {
+       case MONO_FDTYPE_FILE:
+               ret = file_setfiletime(filehandle, create_time, access_time, write_time);
+               break;
+       default:
+               mono_w32error_set_last (ERROR_INVALID_HANDLE);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+               return FALSE;
+       }
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 /* A tick is a 100-nanosecond interval.  File time epoch is Midnight,
@@ -3306,21 +2939,23 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste
 
        totaldays=(file_ticks / TICKS_PER_DAY);
        rem = file_ticks % TICKS_PER_DAY;
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT " rem: %" G_GINT64_FORMAT, __func__,
+                 totaldays, rem);
 
        system_time->wHour=rem/TICKS_PER_HOUR;
        rem %= TICKS_PER_HOUR;
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %" G_GINT64_FORMAT,  __func__,
+                 system_time->wHour, rem);
        
        system_time->wMinute = rem / TICKS_PER_MINUTE;
        rem %= TICKS_PER_MINUTE;
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
-                 rem);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %" G_GINT64_FORMAT, __func__,
+                 system_time->wMinute, rem);
        
        system_time->wSecond = rem / TICKS_PER_SECOND;
        rem %= TICKS_PER_SECOND;
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %lld", __func__, system_time->wSecond,
-                 rem);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %" G_GINT64_FORMAT, __func__,
+                 system_time->wSecond, rem);
        
        system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Milliseconds: %d", __func__,
@@ -3341,19 +2976,19 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste
        while(totaldays < 0 || totaldays >= (isleap(y)?366:365)) {
                /* Guess a corrected year, assuming 365 days per year */
                gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld yg: %lld y: %lld", __func__,
-                         totaldays, yg,
-                         y);
-               g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT " yg: %" G_GINT64_FORMAT " y: %" G_GINT64_FORMAT, __func__,
+                         totaldays, yg, y);
+               g_message("%s: LEAPS(yg): %li LEAPS(y): %li", __func__,
                          LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
                
                /* Adjust days and y to match the guessed year. */
                totaldays -= ((yg - y) * 365
                              + LEAPS_THRU_END_OF (yg - 1)
                              - LEAPS_THRU_END_OF (y - 1));
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT,
+                         __func__, totaldays);
                y = yg;
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %" G_GINT64_FORMAT, __func__, y);
        }
        
        system_time->wYear = y;
@@ -3365,7 +3000,7 @@ mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *syste
                continue;
        }
        totaldays-=ip[y];
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %" G_GINT64_FORMAT, __func__, totaldays);
        
        system_time->wMonth = y + 1;
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
@@ -3541,7 +3176,6 @@ retry:
                goto retry;
        }
 
-#ifndef __native_client__
        result = _wapi_lstat (filename, &linkbuf);
        if (result != 0) {
                mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
@@ -3549,7 +3183,6 @@ retry:
                g_free (filename);
                goto retry;
        }
-#endif
 
        utf8_filename = mono_utf8_from_external (filename);
        if (utf8_filename == NULL) {
@@ -3573,11 +3206,7 @@ retry:
        else
                create_time = buf.st_ctime;
        
-#ifdef __native_client__
-       find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
-#else
        find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
-#endif
 
        time_t_to_filetime (create_time, &find_data->ftCreationTime);
        time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
@@ -3655,7 +3284,7 @@ mono_w32file_find_close (gpointer handle)
        mono_w32handle_unlock_handle (handle);
        
        MONO_ENTER_GC_SAFE;
-       mono_w32handle_unref (handle);
+       mono_w32handle_close (handle);
        MONO_EXIT_GC_SAFE;
        
        return(TRUE);
@@ -3751,7 +3380,7 @@ mono_w32file_get_attributes (const gunichar2 *name)
        }
 
        result = _wapi_stat (utf8_name, &buf);
-       if (result == -1 && errno == ENOENT) {
+       if (result == -1 && (errno == ENOENT || errno == ELOOP)) {
                /* Might be a dangling symlink... */
                result = _wapi_lstat (utf8_name, &buf);
        }
@@ -3762,20 +3391,14 @@ mono_w32file_get_attributes (const gunichar2 *name)
                return (INVALID_FILE_ATTRIBUTES);
        }
 
-#ifndef __native_client__
        result = _wapi_lstat (utf8_name, &linkbuf);
        if (result != 0) {
                _wapi_set_last_path_error_from_errno (NULL, utf8_name);
                g_free (utf8_name);
                return (INVALID_FILE_ATTRIBUTES);
        }
-#endif
        
-#ifdef __native_client__
-       ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
-#else
        ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
-#endif
        
        g_free (utf8_name);
 
@@ -3920,12 +3543,6 @@ mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
        glong count;
        gsize bytes;
 
-#ifdef __native_client__
-       gchar *path = g_get_current_dir ();
-       if (length < strlen(path) + 1 || path == NULL)
-               return 0;
-       memcpy (buffer, path, strlen(path) + 1);
-#else
        if (getcwd ((gchar*)buffer, length) == NULL) {
                if (errno == ERANGE) { /*buffer length is not big enough */ 
                        gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
@@ -3939,7 +3556,6 @@ mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
                _wapi_set_last_error_from_errno ();
                return 0;
        }
-#endif
 
        utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
        count = (bytes/2)+1;
@@ -3980,10 +3596,7 @@ mono_w32file_set_cwd (const gunichar2 *path)
 gboolean
 mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
 {
-       MonoW32HandleFile pipe_read_handle = {0};
-       MonoW32HandleFile pipe_write_handle = {0};
-       gpointer read_handle;
-       gpointer write_handle;
+       FileHandle *read_filehandle, *write_filehandle;
        gint filedes[2];
        gint ret;
        
@@ -3992,68 +3605,30 @@ 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: %s", __func__,
-                          strerror (errno));
-               
+       if (ret==-1) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: (%d) %s",
+                       __func__, errno, g_strerror (errno));
+
                _wapi_set_last_error_from_errno ();
-               return(FALSE);
+               return FALSE;
        }
 
-       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__);
-
-               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 */
 
-       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__);
+       read_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[0]);
+       read_filehandle->fileaccess = GENERIC_READ;
 
-               MONO_ENTER_GC_SAFE;
-               mono_w32handle_unref (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;
+       write_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[1]);
+       write_filehandle->fileaccess = GENERIC_WRITE;
+
+       mono_fdhandle_insert ((MonoFDHandle*) read_filehandle);
+       mono_fdhandle_insert ((MonoFDHandle*) write_filehandle);
+
+       *readpipe = GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd);
+       *writepipe = GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd);
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
-                  __func__, read_handle, write_handle);
+               __func__, GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd), GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd));
 
        return(TRUE);
 }
@@ -4607,7 +4182,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__, strerror (errno));
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, g_strerror (errno));
                return(FALSE);
        }
 
@@ -4670,7 +4245,7 @@ typedef struct {
 } _wapi_drive_type;
 
 static _wapi_drive_type _wapi_drive_types[] = {
-#if PLATFORM_MACOSX
+#if HOST_DARWIN
        { DRIVE_REMOTE, "afp" },
        { DRIVE_REMOTE, "autofs" },
        { DRIVE_CDROM, "cddafs" },
@@ -4680,6 +4255,8 @@ static _wapi_drive_type _wapi_drive_types[] = {
        { DRIVE_RAMDISK, "fdesc" },
        { DRIVE_REMOTE, "ftp" },
        { DRIVE_FIXED, "hfs" },
+       { DRIVE_FIXED, "apfs" },
+       { DRIVE_REMOTE, "kbfuse" },
        { DRIVE_FIXED, "msdos" },
        { DRIVE_REMOTE, "nfs" },
        { DRIVE_FIXED, "ntfs" },
@@ -4826,7 +4403,7 @@ static guint32 _wapi_get_drive_type(const gchar* fstype)
 }
 #endif
 
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
+#if defined (HOST_DARWIN) || defined (__linux__)
 static guint32
 GetDriveTypeFromPath (const gchar *utf8_root_path_name)
 {
@@ -4838,7 +4415,7 @@ GetDriveTypeFromPath (const gchar *utf8_root_path_name)
        MONO_EXIT_GC_SAFE;
        if (res == -1)
                return DRIVE_UNKNOWN;
-#if PLATFORM_MACOSX
+#if HOST_DARWIN
        return _wapi_get_drive_type (buf.f_fstypename);
 #else
        return _wapi_get_drive_type (buf.f_type);
@@ -4931,11 +4508,11 @@ mono_w32file_get_drive_type(const gunichar2 *root_path_name)
        return (drive_type);
 }
 
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
+#if defined (HOST_DARWIN) || defined (__linux__) || defined(HOST_BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
 static gchar*
 get_fstypename (gchar *utfpath)
 {
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
+#if defined (HOST_DARWIN) || defined (__linux__)
        struct statfs stat;
 #if __linux__
        _wapi_drive_type *current;
@@ -4946,7 +4523,7 @@ get_fstypename (gchar *utfpath)
        MONO_EXIT_GC_SAFE;
        if (statfs_res == -1)
                return NULL;
-#if PLATFORM_MACOSX
+#if HOST_DARWIN
        return g_strdup (stat.f_fstypename);
 #else
        current = &_wapi_drive_types[0];
@@ -4995,18 +4572,25 @@ 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)
 {
-       MonoW32HandleFile *file_handle;
+       FileHandle *filehandle;
+       gboolean ret;
        off_t offset, length;
 
-       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
-               g_warning ("%s: error looking up file handle %p", __func__, handle);
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
                return FALSE;
        }
 
-       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);
+       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);
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
 
@@ -5014,36 +4598,48 @@ 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 handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+       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);
 #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 handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+       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);
 #endif
 
-       return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+       ret = _wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length);
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 static gboolean
 UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
 {
-       MonoW32HandleFile *file_handle;
+       FileHandle *filehandle;
+       gboolean ret;
        off_t offset, length;
 
-       if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
-               g_warning ("%s: error looking up file handle %p", __func__, handle);
+       if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) {
                mono_w32error_set_last (ERROR_INVALID_HANDLE);
                return FALSE;
        }
 
-       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);
+       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);
                mono_w32error_set_last (ERROR_ACCESS_DENIED);
+               mono_fdhandle_unref ((MonoFDHandle*) filehandle);
                return FALSE;
        }
 
@@ -5051,32 +4647,35 @@ 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 handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+       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);
 #else
        offset = offset_low;
        length = length_low;
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+       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);
 #endif
 
-       return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+       ret = _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length);
+
+       mono_fdhandle_unref ((MonoFDHandle*) filehandle);
+       return ret;
 }
 
 void
 mono_w32file_init (void)
 {
-       mono_coop_mutex_init (&stdhandle_mutex);
-       mono_coop_mutex_init (&file_share_mutex);
+       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_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_coop_mutex_init (&file_share_mutex);
 
-/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
-/*                                         MONO_W32HANDLE_CAP_WAIT); */
-/*     mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
-/*                                         MONO_W32HANDLE_CAP_WAIT); */
+       mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops);
 
        if (g_hasenv ("MONO_STRICT_IO_EMULATION"))
                lock_while_writing = TRUE;