[w32file] Push win32 specific error to win32 specific implementation (#5665)
[mono.git] / mono / metadata / w32file.c
index 8aabbc57537b5ff43a0ce55a56ece6b6628f00ad..03cac78ac1c8e71d6ca5076b44fe5767a24eeaff 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * w32file.c: File IO internal calls
+/**
+ * \file
+ * File IO internal calls
  *
  * Author:
  *     Dick Porter (dick@ximian.com)
@@ -27,8 +28,8 @@
 #endif
 
 #include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
 #include <mono/metadata/w32file.h>
+#include <mono/metadata/w32error.h>
 #include <mono/metadata/w32file-internals.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/appdomain.h>
@@ -36,6 +37,7 @@
 #include <mono/utils/strenc.h>
 #include <utils/mono-io-portability.h>
 #include <mono/metadata/w32handle.h>
+#include <mono/utils/w32api.h>
 
 #undef DEBUG
 
@@ -170,11 +172,6 @@ static guint32 convert_seekorigin(MonoSeekOrigin origin)
        return(w32origin);
 }
 
-static gint64 convert_filetime (const FILETIME *filetime)
-{
-       return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime);
-}
-
 /* Managed file attributes have nearly but not quite the same values
  * as the w32 equivalents.
  */
@@ -187,86 +184,20 @@ static guint32 convert_attrs(MonoFileAttributes attrs)
        return(attrs);
 }
 
-/*
- * On Win32, mono_w32file_get_attributes|_ex () seems to try opening the file,
- * which might lead to sharing violation errors, whereas mono_w32file_find_first
- * always succeeds. These 2 wrappers resort to mono_w32file_find_first if
- * mono_w32file_get_attributes|_ex () has failed.
- */
-static guint32
-get_file_attributes (const gunichar2 *path)
-{
-       guint32 res;
-       WIN32_FIND_DATA find_data;
-       HANDLE find_handle;
-       gint32 error;
-
-       res = mono_w32file_get_attributes (path);
-       if (res != -1)
-               return res;
-
-       error = GetLastError ();
-
-       if (error != ERROR_SHARING_VIOLATION)
-               return res;
-
-       find_handle = mono_w32file_find_first (path, &find_data);
-
-       if (find_handle == INVALID_HANDLE_VALUE)
-               return res;
-
-       mono_w32file_find_close (find_handle);
-
-       return find_data.dwFileAttributes;
-}
-
-static gboolean
-get_file_attributes_ex (const gunichar2 *path, MonoIOStat *stat)
-{
-       gboolean res;
-       WIN32_FIND_DATA find_data;
-       HANDLE find_handle;
-       gint32 error;
-
-       res = mono_w32file_get_attributes_ex (path, stat);
-       if (res)
-               return TRUE;
-
-       error = GetLastError ();
-       if (error != ERROR_SHARING_VIOLATION)
-               return FALSE;
-
-       find_handle = mono_w32file_find_first (path, &find_data);
-
-       if (find_handle == INVALID_HANDLE_VALUE)
-               return FALSE;
-
-       mono_w32file_find_close (find_handle);
-       
-       stat->attributes = find_data.dwFileAttributes;
-       stat->creation_time = convert_filetime (&find_data.ftCreationTime);
-       stat->last_access_time = convert_filetime (&find_data.ftLastAccessTime);
-       stat->last_write_time = convert_filetime (&find_data.ftLastWriteTime);
-       stat->length = ((gint64)find_data.nFileSizeHigh << 32) | find_data.nFileSizeLow;
-       return TRUE;
-}
-
 /* System.IO.MonoIO internal calls */
 
 MonoBoolean
 ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_create_directory (mono_string_chars (path));
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -274,176 +205,17 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_remove_directory (mono_string_chars (path));
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
-static gchar *
-get_search_dir (const gunichar2 *pattern)
-{
-       gchar *p;
-       gchar *result;
-
-       p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
-       result = g_path_get_dirname (p);
-       g_free (p);
-       return result;
-}
-
-static GPtrArray *
-get_filesystem_entries (const gunichar2 *path,
-                                                const gunichar2 *path_with_pattern,
-                                                gint attrs, gint mask,
-                                                gint32 *error)
-{
-       int i;
-       WIN32_FIND_DATA data;
-       HANDLE find_handle;
-       GPtrArray *names = NULL;
-       gchar *utf8_path = NULL, *utf8_result, *full_name;
-       gint32 attributes;
-
-       mask = convert_attrs ((MonoFileAttributes)mask);
-       attributes = get_file_attributes (path);
-       if (attributes != -1) {
-               if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
-                       *error = ERROR_INVALID_NAME;
-                       goto fail;
-               }
-       } else {
-               *error = GetLastError ();
-               goto fail;
-       }
-       
-       find_handle = mono_w32file_find_first (path_with_pattern, &data);
-       if (find_handle == INVALID_HANDLE_VALUE) {
-               gint32 find_error = GetLastError ();
-               
-               if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
-                       /* No files, so just return an empty array */
-                       goto fail;
-               }
-               
-               *error = find_error;
-               goto fail;
-       }
-
-       utf8_path = get_search_dir (path_with_pattern);
-       names = g_ptr_array_new ();
-
-       do {
-               if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
-                   (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
-                       continue;
-               }
-               
-               if ((data.dwFileAttributes & mask) == attrs) {
-                       utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
-                       if (utf8_result == NULL) {
-                               continue;
-                       }
-                       
-                       full_name = g_build_filename (utf8_path, utf8_result, NULL);
-                       g_ptr_array_add (names, full_name);
-
-                       g_free (utf8_result);
-               }
-       } while(mono_w32file_find_next (find_handle, &data));
-
-       if (mono_w32file_find_close (find_handle) == FALSE) {
-               *error = GetLastError ();
-               goto fail;
-       }
-
-       g_free (utf8_path);
-       return names;
-fail:
-       if (names) {
-               for (i = 0; i < names->len; i++)
-                       g_free (g_ptr_array_index (names, i));
-               g_ptr_array_free (names, TRUE);
-       }
-       g_free (utf8_path);
-       return FALSE;
-}
-
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
-                                                MonoString *path_with_pattern,
-                                                gint attrs, gint mask,
-                                                gint32 *ioerror)
-{
-       MonoError error;
-       MonoDomain *domain = mono_domain_get ();
-       MonoArray *result;
-       int i;
-       GPtrArray *names;
-       
-       *ioerror = ERROR_SUCCESS;
-
-       MONO_ENTER_GC_SAFE;
-       names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
-       MONO_EXIT_GC_SAFE;
-
-       if (!names) {
-               // If there's no array and no error, then return an empty array.
-               if (*ioerror == ERROR_SUCCESS) {
-                       MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
-                       mono_error_set_pending_exception (&error);
-                       return arr;
-               }
-               return NULL;
-       }
-
-       result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
-       if (mono_error_set_pending_exception (&error))
-               goto leave;
-       for (i = 0; i < names->len; i++) {
-               mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
-               g_free (g_ptr_array_index (names, i));
-       }
-leave:
-       g_ptr_array_free (names, TRUE);
-       return result;
-}
-
-typedef struct {
-       MonoDomain *domain;
-       gchar *utf8_path;
-       HANDLE find_handle;
-} IncrementalFind;
-       
-static gboolean
-incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
-{
-       gchar *utf8_result;
-       gchar *full_name;
-       
-       if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
-               return FALSE;
-
-       utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
-       if (utf8_result == NULL) 
-               return FALSE;
-       
-       full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
-       g_free (utf8_result);
-       *result = mono_string_new (mono_domain_get (), full_name);
-       g_free (full_name);
-       
-       return TRUE;
-}
-
 HANDLE
 ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
 {
@@ -456,7 +228,7 @@ ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoStr
        if (hnd == INVALID_HANDLE_VALUE) {
                *file_name = NULL;
                *file_attr = 0;
-               *ioerror = GetLastError ();
+               *ioerror = mono_w32error_get_last ();
                return hnd;
        }
 
@@ -481,7 +253,7 @@ ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gin
        if (res == FALSE) {
                *file_name = NULL;
                *file_attr = 0;
-               *ioerror = GetLastError ();
+               *ioerror = mono_w32error_get_last ();
                return res;
        }
 
@@ -500,100 +272,6 @@ ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
        return mono_w32file_find_close (hnd);
 }
 
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
-                                     MonoString *path_with_pattern,
-                                     gint32 *result_attr, gint32 *ioerror,
-                                     gpointer *handle)
-{
-       MonoError error;
-       WIN32_FIND_DATA data;
-       HANDLE find_handle;
-       IncrementalFind *ifh;
-       MonoString *result;
-       
-       *ioerror = ERROR_SUCCESS;
-       
-       find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
-       
-       if (find_handle == INVALID_HANDLE_VALUE) {
-               gint32 find_error = GetLastError ();
-               *handle = NULL;
-               
-               if (find_error == ERROR_FILE_NOT_FOUND) 
-                       return NULL;
-               
-               *ioerror = find_error;
-               return NULL;
-       }
-
-       ifh = g_new (IncrementalFind, 1);
-       ifh->find_handle = find_handle;
-       ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
-       if (mono_error_set_pending_exception (&error)) {
-               MONO_ENTER_GC_SAFE;
-               mono_w32file_find_close (find_handle);
-               MONO_EXIT_GC_SAFE;
-               g_free (ifh);
-               return NULL;
-       }
-       ifh->domain = mono_domain_get ();
-       *handle = ifh;
-
-       while (incremental_find_check_match (ifh, &data, &result) == 0){
-               if (mono_w32file_find_next (find_handle, &data) == FALSE){
-                       int e = GetLastError ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *ioerror = e;
-                       return NULL;
-               }
-       }
-       *result_attr = data.dwFileAttributes;
-       
-       return result;
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
-{
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       WIN32_FIND_DATA data;
-       MonoString *result;
-
-       *error = ERROR_SUCCESS;
-       do {
-               if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
-                       int e = GetLastError ();
-                       if (e != ERROR_NO_MORE_FILES)
-                               *error = e;
-                       return NULL;
-               }
-       } while (incremental_find_check_match (ifh, &data, &result) == 0);
-
-       *result_attr = data.dwFileAttributes;
-       return result;
-}
-
-int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
-{
-       IncrementalFind *ifh = (IncrementalFind *)handle;
-       gint32 error;
-
-       MONO_ENTER_GC_SAFE;
-       if (mono_w32file_find_close (ifh->find_handle) == FALSE){
-               error = GetLastError ();
-       } else
-               error = ERROR_SUCCESS;
-       g_free (ifh->utf8_path);
-       g_free (ifh);
-       MONO_EXIT_GC_SAFE;
-
-       return error;
-}
-
 MonoString *
 ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
 {
@@ -605,7 +283,7 @@ ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
        len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
        buf = g_new (gunichar2, len);
        
-       mono_error_init (&error);
+       error_init (&error);
        *io_error=ERROR_SUCCESS;
        result = NULL;
 
@@ -624,7 +302,7 @@ ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
 
                result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
        } else {
-               *io_error=GetLastError ();
+               *io_error=mono_w32error_get_last ();
        }
 
        g_free (buf);
@@ -642,7 +320,7 @@ ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
        
        ret=mono_w32file_set_cwd (mono_string_chars (path));
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
        
        return(ret);
@@ -691,16 +369,14 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
        
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_delete (mono_string_chars (path));
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -708,11 +384,9 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 {
        gint32 ret;
-       MONO_ENTER_GC_SAFE;
-
        *error=ERROR_SUCCESS;
        
-       ret=get_file_attributes (mono_string_chars (path));
+       ret = mono_w32file_get_attributes (mono_string_chars (path));
 
        /* 
         * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
@@ -722,10 +396,8 @@ ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
         */
        if (ret==-1) {
          /* if(ret==INVALID_FILE_ATTRIBUTES) { */
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
-       
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -734,17 +406,13 @@ ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
                                              gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
-       
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_set_attributes (mono_string_chars (path),
                convert_attrs ((MonoFileAttributes)attrs));
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
-
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -752,7 +420,6 @@ gint32
 ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -761,10 +428,9 @@ ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
                /* Not necessarily an error, but the caller will have
                 * to decide based on the error value.
                 */
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -772,18 +438,16 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
 {
        gboolean result;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
-       result = get_file_attributes_ex (mono_string_chars (path), stat);
+       result = mono_w32file_get_attributes_ex (mono_string_chars (path), stat);
 
        if (!result) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                memset (stat, 0, sizeof (MonoIOStat));
        }
 
-       MONO_EXIT_GC_SAFE;
        return result;
 }
 
@@ -795,7 +459,6 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
        HANDLE ret;
        int attributes, attrs;
        gunichar2 *chars;
-       MONO_ENTER_GC_SAFE;
 
        chars = mono_string_chars (filename);   
        *error=ERROR_SUCCESS;
@@ -822,7 +485,7 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
 
        /* If we're opening a directory we need to set the extra flag
         */
-       attrs = get_file_attributes (chars);
+       attrs = mono_w32file_get_attributes (chars);
        if (attrs != INVALID_FILE_ATTRIBUTES) {
                if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
                        attributes |= FILE_FLAG_BACKUP_SEMANTICS;
@@ -831,10 +494,9 @@ ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
        
        ret=mono_w32file_create (chars, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
        if(ret==INVALID_HANDLE_VALUE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        } 
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -842,16 +504,12 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
-
        *error=ERROR_SUCCESS;
        
-       ret=CloseHandle (handle);
+       ret=mono_w32file_close (handle);
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
-       
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -875,12 +533,10 @@ ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
 
        buffer = mono_array_addr (dest, guchar, dest_offset);
 
-       MONO_ENTER_GC_SAFE;
        result = mono_w32file_read (handle, buffer, count, &n);
-       MONO_EXIT_GC_SAFE;
 
        if (!result) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return -1;
        }
 
@@ -906,12 +562,10 @@ ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
        }
        
        buffer = mono_array_addr (src, guchar, src_offset);
-       MONO_ENTER_GC_SAFE;
        result = mono_w32file_write (handle, buffer, count, &n);
-       MONO_EXIT_GC_SAFE;
 
        if (!result) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return -1;
        }
 
@@ -923,7 +577,6 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                                 gint32 *error)
 {
        gint32 offset_hi;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -932,10 +585,9 @@ ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
                                 convert_seekorigin ((MonoSeekOrigin)origin));
 
        if(offset==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return offset | ((gint64)offset_hi << 32);
 }
 
@@ -943,16 +595,14 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
 {
        gboolean ret;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
        ret=mono_w32file_flush (handle);
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
        
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -980,7 +630,7 @@ ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
        offset_hi = 0;
        offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
        if(offset==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return(FALSE);
        }
 
@@ -990,13 +640,13 @@ ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
        offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
                                   FILE_BEGIN);
        if(offset_set==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return(FALSE);
        }
 
        result = mono_w32file_truncate (handle);
        if(result==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return(FALSE);
        }
 
@@ -1005,7 +655,7 @@ ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
        offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
                                   FILE_BEGIN);
        if(offset_set==INVALID_SET_FILE_POINTER) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
                return(FALSE);
        }
 
@@ -1021,7 +671,6 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
        const FILETIME *creation_filetime;
        const FILETIME *access_filetime;
        const FILETIME *write_filetime;
-       MONO_ENTER_GC_SAFE;
 
        *error=ERROR_SUCCESS;
        
@@ -1042,10 +691,9 @@ ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
 
        ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
        if(ret==FALSE) {
-               *error=GetLastError ();
+               *error=mono_w32error_get_last ();
        }
 
-       MONO_EXIT_GC_SAFE;
        return(ret);
 }
 
@@ -1072,12 +720,10 @@ ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle
 {
        gboolean ret;
 
-       MONO_ENTER_GC_SAFE;
        ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
-       MONO_EXIT_GC_SAFE;
 
        if(ret==FALSE) {
-               *error = GetLastError ();
+               *error = mono_w32error_get_last ();
                /* FIXME: throw an exception? */
                return(FALSE);
        }
@@ -1089,25 +735,22 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
                HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
 {
-       /* This is only used on Windows */
+#ifndef HOST_WIN32
+       *target_handle = mono_w32handle_duplicate (source_handle);
+#else
        gboolean ret;
-       
+
        MONO_ENTER_GC_SAFE;
-#ifdef HOST_WIN32
        ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
-#else
-       mono_w32handle_ref (source_handle);
-       *target_handle = source_handle;
-       ret = TRUE;
-#endif
        MONO_EXIT_GC_SAFE;
 
-       if(ret==FALSE) {
-               *error = GetLastError ();
+       if (!ret) {
+               *error = mono_w32error_get_last ();
                /* FIXME: throw an exception? */
                return(FALSE);
        }
-       
+#endif
+
        return(TRUE);
 }
 
@@ -1208,15 +851,17 @@ mono_filesize_from_path (MonoString *string)
        char *path = mono_string_to_utf8_checked (string, &error);
        mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
 
+       gint stat_res;
        MONO_ENTER_GC_SAFE;
-       if (stat (path, &buf) == -1)
+       stat_res = stat (path, &buf);
+       MONO_EXIT_GC_SAFE;
+       if (stat_res == -1)
                res = -1;
        else
                res = (gint64)buf.st_size;
 
        g_free (path);
 
-       MONO_EXIT_GC_SAFE;
        return res;
 }