2005-07-12 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / io-layer / io.c
index 2800306954dd2be8d532f1145de105695931e000..d2c1d06494aaf17f21aa748fc2b2853c31e7c951 100644 (file)
 #include <stdio.h>
 #include <utime.h>
 
-#ifndef PLATFORM_WIN32
-#ifdef HAVE_AIO_H
-#include <aio.h>
-#define USE_AIO        1
-#elif defined(HAVE_SYS_AIO_H)
-#include <sys/aio.h>
-#define USE_AIO 1
-#else
-#undef USE_AIO
-#endif
-#endif
-
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
 #include <mono/io-layer/handles-private.h>
@@ -45,8 +33,7 @@
 static gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length);
 static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length);
 
-static void file_close_shared (gpointer handle);
-static void file_close_private (gpointer handle);
+static void file_close (gpointer handle, gpointer data);
 static WapiFileType file_getfiletype(void);
 static gboolean file_read(gpointer handle, gpointer buffer,
                          guint32 numbytes, guint32 *bytesread,
@@ -69,15 +56,28 @@ static gboolean file_setfiletime(gpointer handle,
 
 /* File handle is only signalled for overlapped IO */
 struct _WapiHandleOps _wapi_file_ops = {
-       file_close_shared,      /* close_shared */
-       file_close_private,     /* close_private */
+       file_close,             /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
        NULL,                   /* is_owned */
 };
 
-static void console_close_shared (gpointer handle);
-static void console_close_private (gpointer handle);
+void _wapi_file_details (gpointer handle_info)
+{
+       struct _WapiHandle_file *file = (struct _WapiHandle_file *)handle_info;
+       
+       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 void console_close (gpointer handle, gpointer data);
 static WapiFileType console_getfiletype(void);
 static gboolean console_read(gpointer handle, gpointer buffer,
                             guint32 numbytes, guint32 *bytesread,
@@ -90,25 +90,27 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
  * input or output
  */
 struct _WapiHandleOps _wapi_console_ops = {
-       console_close_shared,   /* close_shared */
-       console_close_private,  /* close_private */
+       console_close,          /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
        NULL,                   /* is_owned */
 };
 
+void _wapi_console_details (gpointer handle_info)
+{
+       _wapi_file_details (handle_info);
+}
+
 /* Find handle has no ops.
  */
 struct _WapiHandleOps _wapi_find_ops = {
-       NULL,                   /* close_shared */
-       NULL,                   /* close_private */
+       NULL,                   /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
        NULL,                   /* is_owned */
 };
 
-static void pipe_close_shared (gpointer handle);
-static void pipe_close_private (gpointer handle);
+static void pipe_close (gpointer handle, gpointer data);
 static WapiFileType pipe_getfiletype (void);
 static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes,
                           guint32 *bytesread, WapiOverlapped *overlapped);
@@ -119,14 +121,18 @@ static gboolean pipe_write (gpointer handle, gconstpointer buffer,
 /* Pipe handles
  */
 struct _WapiHandleOps _wapi_pipe_ops = {
-       pipe_close_shared,      /* close_shared */
-       pipe_close_private,     /* close_private */
+       pipe_close,             /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
        NULL,                   /* is_owned */
 };
 
-static struct {
+void _wapi_pipe_details (gpointer handle_info)
+{
+       _wapi_file_details (handle_info);
+}
+
+static const struct {
        /* File, console and pipe handles */
        WapiFileType (*getfiletype)(void);
        
@@ -187,6 +193,11 @@ static struct {
         NULL, NULL, NULL, NULL, NULL, NULL},
 };
 
+#define NO_SIGPIPE(x) do {                     \
+               void (*old_sigpipe)(int) = signal (SIGPIPE, SIG_IGN);   \
+               x;                                                      \
+               signal (SIGPIPE, old_sigpipe);                          \
+       }  while (0)
 
 static mono_once_t io_ops_once=MONO_ONCE_INIT;
 
@@ -226,52 +237,20 @@ _wapi_set_last_error_from_errno (void)
 
 /* Handle ops.
  */
-static void file_close_shared (gpointer handle)
+static void file_close (gpointer handle, gpointer data)
 {
-       struct _WapiHandle_file *file_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle, NULL);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
-               return;
-       }
+       struct _WapiHandle_file *file_handle = (struct _WapiHandle_file *)data;
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p", handle);
+       g_message("%s: closing file handle %p [%s]", __func__, handle,
+                 file_handle->filename);
 #endif
-       
-       if(file_handle->filename!=0) {
-               _wapi_handle_scratch_delete (file_handle->filename);
-               file_handle->filename=0;
-       }
-       if(file_handle->security_attributes!=0) {
-               _wapi_handle_scratch_delete (file_handle->security_attributes);
-               file_handle->security_attributes=0;
-       }
-}
 
-static void file_close_private (gpointer handle)
-{
-       struct _WapiHandlePrivate_file *file_private_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL,
-                               (gpointer *)&file_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
-               return;
-       }
+       g_free (file_handle->filename);
        
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing file handle %p with fd %d",
-                 handle, file_private_handle->fd);
-#endif
+       _wapi_handle_share_release (file_handle->share_info);
        
-       close(file_private_handle->fd);
+       close (GPOINTER_TO_UINT(handle));
 }
 
 static WapiFileType file_getfiletype(void)
@@ -279,151 +258,60 @@ static WapiFileType file_getfiletype(void)
        return(FILE_TYPE_DISK);
 }
 
-#ifdef USE_AIO
-typedef struct {
-       struct aiocb *aio;
-       WapiOverlapped *overlapped;
-       WapiOverlappedCB callback;
-} notifier_data_t;
-
-#define SIGPTR(a) a.SIGVAL_PTR
-
-static void
-async_notifier (union sigval sig)
-{
-       notifier_data_t *ndata = SIGPTR (sig);
-       guint32 error;
-       guint32 numbytes;
-
-       error = aio_return (ndata->aio);
-       if (error < 0) {
-               error = _wapi_get_win32_file_error (error);
-               numbytes = 0;
-       } else {
-               numbytes = error;
-               error = 0;
-       }
-
-       ndata->callback (error, numbytes, ndata->overlapped);
-       g_free (ndata->aio);
-       g_free (ndata);
-}
-
-#endif /* USE_AIO */
-
 static gboolean file_read(gpointer handle, gpointer buffer,
                          guint32 numbytes, guint32 *bytesread,
                          WapiOverlapped *overlapped)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
+       int fd = GPOINTER_TO_UINT(handle);
        int ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
-       
+
        if(bytesread!=NULL) {
                *bytesread=0;
        }
        
-       if(!(file_handle->fileaccess&GENERIC_READ) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
-       if (file_private_handle->async == FALSE) {
-               do {
-                       ret=read(file_private_handle->fd, buffer, numbytes);
-               }
-               while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+       do {
+               ret = read (fd, buffer, numbytes);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending());
                        
-               if(ret==-1) {
-                       gint err = errno;
-
-#ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": read of handle %p fd %d error: %s", handle,
-                                 file_private_handle->fd, strerror(err));
-#endif
-                       SetLastError (_wapi_get_win32_file_error (err));
-                       return(FALSE);
-               }
-               
-               if(bytesread!=NULL) {
-                       *bytesread=ret;
-               }
-               
-               return(TRUE);
-       }
-
-#ifndef USE_AIO
-       SetLastError (ERROR_NOT_SUPPORTED);
-       return FALSE;
-#else
-       if (overlapped == NULL || file_private_handle->callback == NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-
-       {
-       int fd = file_private_handle->fd;
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->overlapped = overlapped;
-       ndata->aio = aio;
-       ndata->callback = file_private_handle->callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = LIO_READ;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
-       aio->aio_buf = buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       result = aio_read (aio);
-       if (result == -1) {
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
-       }
+       if(ret==-1) {
+               gint err = errno;
 
-       result = aio_error (aio);
 #ifdef DEBUG
-       g_print ("aio_error (read) returned %d for %d\n", result, fd);
+               g_message("%s: read of handle %p error: %s", __func__,
+                         handle, strerror(err));
 #endif
-       if (result == 0) {
-               numbytes = aio_return (aio);
-#ifdef DEBUG
-               g_print ("numbytes %d for %d\n", numbytes, fd);
-#endif
-       } else {
-               errno = result;
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
+               SetLastError (_wapi_get_win32_file_error (err));
+               return(FALSE);
        }
-
-       if (bytesread)
-               *bytesread = numbytes;
-
-       return TRUE;
+               
+       if (bytesread != NULL) {
+               *bytesread = ret;
        }
-#endif
+               
+       return(TRUE);
 }
 
 static gboolean file_write(gpointer handle, gconstpointer buffer,
@@ -431,16 +319,17 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                           WapiOverlapped *overlapped G_GNUC_UNUSED)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        int ret;
+       off_t current_pos;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -448,153 +337,97 @@ static gboolean file_write(gpointer handle, gconstpointer buffer,
                *byteswritten=0;
        }
        
-       if(!(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       if (file_private_handle->async == FALSE) {
-               off_t current_pos;
-               
-               /* Need to lock the region we're about to write to,
-                * because we only do advisory locking on POSIX
-                * systems
-                */
-               current_pos = lseek (file_private_handle->fd, (off_t)0,
-                                    SEEK_CUR);
-               if (current_pos == -1) {
+       /* Need to lock the region we're about to write to, because we
+        * only do advisory locking on POSIX systems
+        */
+       current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+       if (current_pos == -1) {
 #ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d lseek failed: %s", handle, file_private_handle->fd, strerror (errno));
+               g_message ("%s: handle %p lseek failed: %s", __func__, handle,
+                          strerror (errno));
 #endif
-                       _wapi_set_last_error_from_errno ();
-                       return(FALSE);
-               }
+               _wapi_set_last_error_from_errno ();
+               return(FALSE);
+       }
                
-               if (_wapi_lock_file_region (file_private_handle->fd,
-                                           current_pos, numbytes) == FALSE) {
-                       /* The error has already been set */
-                       return(FALSE);
-               }
+       if (_wapi_lock_file_region (fd, current_pos, numbytes) == FALSE) {
+               /* The error has already been set */
+               return(FALSE);
+       }
                
+       NO_SIGPIPE(
                do {
-                       ret=write(file_private_handle->fd, buffer, numbytes);
-               }
-               while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
-
-               _wapi_unlock_file_region (file_private_handle->fd, current_pos,
-                                         numbytes);
+                       ret = write (fd, buffer, numbytes);
+               } while (ret == -1 && errno == EINTR &&
+                        !_wapi_thread_cur_apc_pending());
+               );
+       
+       _wapi_unlock_file_region (fd, current_pos, numbytes);
 
-               if(ret==-1) {
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                               
 #ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": write of handle %p fd %d error: %s", handle,
-                                 file_private_handle->fd, strerror(errno));
+                       g_message("%s: write of handle %p error: %s",
+                                 __func__, handle, strerror(errno));
 #endif
 
                        return(FALSE);
                }
-               if(byteswritten!=NULL) {
-                       *byteswritten=ret;
-               }
-               return(TRUE);
        }
-
-#ifndef USE_AIO
-       SetLastError (ERROR_NOT_SUPPORTED);
-       return FALSE;
-#else
-       if (overlapped == NULL || file_private_handle->callback == NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
-       }
-
-       {
-       int fd = file_private_handle->fd;
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->overlapped = overlapped;
-       ndata->aio = aio;
-       ndata->callback = file_private_handle->callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = LIO_WRITE;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = overlapped->Offset + (((gint64) overlapped->OffsetHigh) << 32);
-       aio->aio_buf = (gpointer) buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       SIGPTR (aio->aio_sigevent.sigev_value) = ndata;
-
-       result = aio_write (aio);
-       if (result == -1) {
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
+       if (byteswritten != NULL) {
+               *byteswritten = ret;
        }
-
-       result = aio_error (aio);
-#ifdef DEBUG
-       g_print ("aio_error (write) returned %d for %d\n", result, fd);
-#endif
-       if (result == 0) {
-               numbytes = aio_return (aio);
-#ifdef DEBUG
-       g_print ("numbytes %d for %d\n", numbytes, fd);
-#endif
-       } else {
-               errno = result;
-               _wapi_set_last_error_from_errno ();
-               return FALSE;
-       }
-
-       if (byteswritten)
-               *byteswritten = numbytes;
-
-       return TRUE;
-       }
-#endif
+       return(TRUE);
 }
 
 static gboolean file_flush(gpointer handle)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
 
-       if(!(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
-       ret=fsync(file_private_handle->fd);
+       ret=fsync(fd);
        if (ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": write of handle %p fd %d error: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message("%s: fsync of handle %p error: %s", __func__, handle,
+                         strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
        
@@ -605,28 +438,29 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
                         gint32 *highmovedistance, WapiSeekMethod method)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        off_t offset, newpos;
        int whence;
        guint32 ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(INVALID_SET_FILE_POINTER);
        }
        
-       if(!(file_handle->fileaccess&GENERIC_READ) &&
-          !(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(INVALID_SET_FILE_POINTER);
        }
 
@@ -642,10 +476,10 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
                break;
        default:
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": invalid seek type %d",
-                         method);
+               g_message("%s: invalid seek type %d", __func__, method);
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(INVALID_SET_FILE_POINTER);
        }
 
@@ -653,15 +487,14 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
        if(highmovedistance==NULL) {
                offset=movedistance;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": setting offset to %lld (low %d)", offset,
-                         movedistance);
+               g_message("%s: setting offset to %lld (low %d)", __func__,
+                         offset, movedistance);
 #endif
        } else {
-               offset=((gint64) *highmovedistance << 32) | movedistance;
+               offset=((gint64) *highmovedistance << 32) | (unsigned long)movedistance;
                
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
+               g_message("%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
 #endif
        }
 #else
@@ -670,32 +503,30 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 
 #ifdef DEBUG
 #ifdef HAVE_LARGE_FILE_SUPPORT
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": moving handle %p fd %d by %lld bytes from %d", handle,
-                 file_private_handle->fd, offset, whence);
+       g_message("%s: moving handle %p by %lld bytes from %d", __func__,
+                 handle, offset, whence);
 #else
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": moving handle %p fd %d by %ld bytes from %d", handle,
-                 file_private_handle->fd, offset, whence);
+       g_message("%s: moving handle %p fd %d by %ld bytes from %d", __func__,
+                 handle, offset, whence);
 #endif
 #endif
 
-       newpos=lseek(file_private_handle->fd, offset, whence);
+       newpos=lseek(fd, offset, whence);
        if(newpos==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": lseek on handle %p fd %d returned error %s",
-                         handle, file_private_handle->fd, strerror(errno));
+               g_message("%s: lseek on handle %p returned error %s",
+                         __func__, handle, strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(INVALID_SET_FILE_POINTER);
        }
 
 #ifdef DEBUG
 #ifdef HAVE_LARGE_FILE_SUPPORT
-       g_message(G_GNUC_PRETTY_FUNCTION ": lseek returns %lld", newpos);
+       g_message("%s: lseek returns %lld", __func__, newpos);
 #else
-       g_message(G_GNUC_PRETTY_FUNCTION ": lseek returns %ld", newpos);
+       g_message ("%s: lseek returns %ld", __func__, newpos);
 #endif
 #endif
 
@@ -713,10 +544,8 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 #endif
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": move of handle %p fd %d returning %d/%d", handle,
-                 file_private_handle->fd, ret,
-                 highmovedistance==NULL?0:*highmovedistance);
+       g_message ("%s: move of handle %p returning %d/%d", __func__,
+                  handle, ret, highmovedistance==NULL?0:*highmovedistance);
 #endif
 
        return(ret);
@@ -725,27 +554,28 @@ static guint32 file_seek(gpointer handle, gint32 movedistance,
 static gboolean file_setendoffile(gpointer handle)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        struct stat statbuf;
        off_t size, pos;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
-       if(!(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
@@ -755,44 +585,50 @@ static gboolean file_setendoffile(gpointer handle)
         * than the length, truncate the file.
         */
        
-       ret=fstat(file_private_handle->fd, &statbuf);
+       ret=fstat(fd, &statbuf);
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d fstat failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message ("%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
        size=statbuf.st_size;
 
-       pos=lseek(file_private_handle->fd, (off_t)0, SEEK_CUR);
+       pos=lseek(fd, (off_t)0, SEEK_CUR);
        if(pos==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d lseek failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message("%s: handle %p lseek failed: %s", __func__,
+                         handle, strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
        
        if(pos>size) {
-               /* extend */
-               do {
-                       ret=write(file_private_handle->fd, "", 1);
-               }
-               while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+               /* Extend the file.  Use write() here, because some
+                * manuals say that ftruncate() behaviour is undefined
+                * when the file needs extending.  The POSIX spec says
+                * that on XSI-conformant systems it extends, so if
+                * every system we care about conforms, then we can
+                * drop this write.
+                */
+               NO_SIGPIPE(
+                       do {
+                               ret = write (fd, "", 1);
+                       } while (ret == -1 && errno == EINTR &&
+                                !_wapi_thread_cur_apc_pending());
+                       );
 
                if(ret==-1) {
 #ifdef DEBUG
-                       g_message(G_GNUC_PRETTY_FUNCTION
-                                 ": handle %p fd %d extend write failed: %s",
-                                 handle, file_private_handle->fd,
-                                 strerror(errno));
+                       g_message("%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
 #endif
 
+                       _wapi_set_last_error_from_errno ();
                        return(FALSE);
                }
        }
@@ -801,17 +637,16 @@ static gboolean file_setendoffile(gpointer handle)
         * byte to the end of the file
         */
        do {
-               ret=ftruncate(file_private_handle->fd, pos);
+               ret=ftruncate(fd, pos);
        }
-       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
-                       
+       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); 
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d ftruncate failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message("%s: handle %p ftruncate failed: %s", __func__,
+                         handle, strerror(errno));
 #endif
                
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
                
@@ -821,58 +656,64 @@ static gboolean file_setendoffile(gpointer handle)
 static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        struct stat statbuf;
        guint32 size;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(INVALID_FILE_SIZE);
        }
        
-       if(!(file_handle->fileaccess&GENERIC_READ) &&
-          !(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(INVALID_FILE_SIZE);
        }
 
-       ret=fstat(file_private_handle->fd, &statbuf);
-       if(ret==-1) {
+       /* If the file has a size with the low bits 0xFFFFFFFF the
+        * caller can't tell if this is an error, so clear the error
+        * value
+        */
+       SetLastError (ERROR_SUCCESS);
+       
+       ret = fstat(fd, &statbuf);
+       if (ret == -1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d fstat failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message ("%s: handle %p fstat failed: %s", __func__,
+                          handle, strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(INVALID_FILE_SIZE);
        }
        
 #ifdef HAVE_LARGE_FILE_SUPPORT
-       size=statbuf.st_size & 0xFFFFFFFF;
-       if(highsize!=NULL) {
-               *highsize=statbuf.st_size>>32;
+       size = statbuf.st_size & 0xFFFFFFFF;
+       if (highsize != NULL) {
+               *highsize = statbuf.st_size>>32;
        }
 #else
-       if(highsize!=NULL) {
+       if (highsize != NULL) {
                /* Accurate, but potentially dodgy :-) */
-               *highsize=0;
+               *highsize = 0;
        }
-       size=statbuf.st_size;
+       size = statbuf.st_size;
 #endif
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Returning size %d/%d", size,
-                 *highsize);
+       g_message ("%s: Returning size %d/%d", __func__, size, *highsize);
 #endif
        
        return(size);
@@ -883,44 +724,45 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
                                 WapiFileTime *last_write)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        struct stat statbuf;
        guint64 create_ticks, access_ticks, write_ticks;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
-       
-       if(!(file_handle->fileaccess&GENERIC_READ) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+
+       if(!(file_handle->fileaccess & GENERIC_READ) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       ret=fstat(file_private_handle->fd, &statbuf);
+       ret=fstat(fd, &statbuf);
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d fstat failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message("%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": atime: %ld ctime: %ld mtime: %ld",
+       g_message("%s: atime: %ld ctime: %ld mtime: %ld", __func__,
                  statbuf.st_atime, statbuf.st_ctime,
                  statbuf.st_mtime);
 #endif
@@ -943,9 +785,8 @@ static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
        write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
        
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": aticks: %llu cticks: %llu wticks: %llu",
-                         access_ticks, create_ticks, write_ticks);
+       g_message("%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+                 access_ticks, create_ticks, write_ticks);
 #endif
 
        if(create_time!=NULL) {
@@ -972,59 +813,70 @@ static gboolean file_setfiletime(gpointer handle,
                                 const WapiFileTime *last_write)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
-       guchar *name;
        struct utimbuf utbuf;
        struct stat statbuf;
        guint64 access_ticks, write_ticks;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
+                               (gpointer *)&file_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
-       if(!(file_handle->fileaccess&GENERIC_WRITE) &&
-          !(file_handle->fileaccess&GENERIC_ALL)) {
+       if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+          !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
 
-       if(file_handle->filename==0) {
+       if(file_handle->filename == NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d unknown filename", handle,
-                         file_private_handle->fd);
+               g_message("%s: handle %p unknown filename", __func__, handle);
 #endif
 
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
        /* Get the current times, so we can put the same times back in
         * the event that one of the FileTime structs is NULL
         */
-       ret=fstat(file_private_handle->fd, &statbuf);
+       ret=fstat (fd, &statbuf);
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p fd %d fstat failed: %s", handle,
-                         file_private_handle->fd, strerror(errno));
+               g_message("%s: handle %p fstat failed: %s", __func__, handle,
+                         strerror(errno));
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
        }
 
        if(last_access!=NULL) {
                access_ticks=((guint64)last_access->dwHighDateTime << 32) +
                        last_access->dwLowDateTime;
+               /* This is (time_t)0.  We can actually go to INT_MIN,
+                * but this will do for now.
+                */
+               if (access_ticks < 116444736000000000ULL) {
+#ifdef DEBUG
+                       g_message ("%s: attempt to set access time too early",
+                                  __func__);
+#endif
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+               
                utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000;
        } else {
                utbuf.actime=statbuf.st_atime;
@@ -1033,83 +885,53 @@ static gboolean file_setfiletime(gpointer handle,
        if(last_write!=NULL) {
                write_ticks=((guint64)last_write->dwHighDateTime << 32) +
                        last_write->dwLowDateTime;
+               /* This is (time_t)0.  We can actually go to INT_MIN,
+                * but this will do for now.
+                */
+               if (write_ticks < 116444736000000000ULL) {
+#ifdef DEBUG
+                       g_message ("%s: attempt to set write time too early",
+                                  __func__);
+#endif
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+               
                utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000;
        } else {
                utbuf.modtime=statbuf.st_mtime;
        }
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": setting handle %p access %ld write %ld", handle,
-                 utbuf.actime, utbuf.modtime);
+       g_message("%s: setting handle %p access %ld write %ld", __func__,
+                 handle, utbuf.actime, utbuf.modtime);
 #endif
 
-       name=_wapi_handle_scratch_lookup (file_handle->filename);
-
-       ret=utime(name, &utbuf);
+       ret=utime(file_handle->filename, &utbuf);
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": handle %p [%s] fd %d utime failed: %s", handle,
-                         name, file_private_handle->fd, strerror(errno));
+               g_message("%s: handle %p [%s] utime failed: %s", __func__,
+                         handle, file_handle->filename, strerror(errno));
 
 #endif
-               g_free (name);
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
        }
-
-       g_free (name);
        
        return(TRUE);
 }
 
-static void console_close_shared (gpointer handle)
+static void console_close (gpointer handle, gpointer data)
 {
-       struct _WapiHandle_file *console_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
-                               (gpointer *)&console_handle, NULL);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up console handle %p", handle);
-               return;
-       }
+       struct _WapiHandle_file *console_handle = (struct _WapiHandle_file *)data;
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing console handle %p", handle);
+       g_message("%s: closing console handle %p", __func__, handle);
 #endif
-       
-       if(console_handle->filename!=0) {
-               _wapi_handle_scratch_delete (console_handle->filename);
-               console_handle->filename=0;
-       }
-       if(console_handle->security_attributes!=0) {
-               _wapi_handle_scratch_delete (console_handle->security_attributes);
-               console_handle->security_attributes=0;
-       }
-}
 
-static void console_close_private (gpointer handle)
-{
-       struct _WapiHandlePrivate_file *console_private_handle;
-       gboolean ok;
+       g_free (console_handle->filename);
        
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE, NULL,
-                               (gpointer *)&console_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up console handle %p", handle);
-               return;
-       }
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": closing console handle %p with fd %d", handle,
-                 console_private_handle->fd);
-#endif
-       
-       close(console_private_handle->fd);
+       close (GPOINTER_TO_UINT(handle));
 }
 
 static WapiFileType console_getfiletype(void)
@@ -1122,16 +944,16 @@ static gboolean console_read(gpointer handle, gpointer buffer,
                             WapiOverlapped *overlapped G_GNUC_UNUSED)
 {
        struct _WapiHandle_file *console_handle;
-       struct _WapiHandlePrivate_file *console_private_handle;
        gboolean ok;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
-                               (gpointer *)&console_handle,
-                               (gpointer *)&console_private_handle);
+                               (gpointer *)&console_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up console handle %p", handle);
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -1139,27 +961,28 @@ static gboolean console_read(gpointer handle, gpointer buffer,
                *bytesread=0;
        }
        
-       if(!(console_handle->fileaccess&GENERIC_READ) &&
-          !(console_handle->fileaccess&GENERIC_ALL)) {
+       if(!(console_handle->fileaccess & GENERIC_READ) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, console_private_handle->fd, console_handle->fileaccess);
+               g_message ("%s: handle %p doesn't have GENERIC_READ access: %u",
+                          __func__, handle, console_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
        do {
-               ret=read(console_private_handle->fd, buffer, numbytes);
-       }
-       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+               ret=read(fd, buffer, numbytes);
+       } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
 
        if(ret==-1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": read of handle %p fd %d error: %s", handle,
-                         console_private_handle->fd, strerror(errno));
+               g_message("%s: read of handle %p error: %s", __func__, handle,
+                         strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
        
@@ -1175,16 +998,16 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
                              WapiOverlapped *overlapped G_GNUC_UNUSED)
 {
        struct _WapiHandle_file *console_handle;
-       struct _WapiHandlePrivate_file *console_private_handle;
        gboolean ok;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
-                               (gpointer *)&console_handle,
-                               (gpointer *)&console_private_handle);
+                               (gpointer *)&console_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up console handle %p", handle);
+               g_warning ("%s: error looking up console handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -1192,28 +1015,36 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
                *byteswritten=0;
        }
        
-       if(!(console_handle->fileaccess&GENERIC_WRITE) &&
-          !(console_handle->fileaccess&GENERIC_ALL)) {
+       if(!(console_handle->fileaccess & GENERIC_WRITE) &&
+          !(console_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, console_private_handle->fd, console_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
-       do {
-               ret=write(console_private_handle->fd, buffer, numbytes);
-       }
-       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+       NO_SIGPIPE(
+               do {
+                       ret = write(fd, buffer, numbytes);
+               } while (ret == -1 && errno == EINTR &&
+                        !_wapi_thread_cur_apc_pending());
+               );
 
-       if(ret==-1) {
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": write of handle %p fd %d error: %s", handle,
-                         console_private_handle->fd, strerror(errno));
+                       g_message ("%s: write of handle %p error: %s",
+                                  __func__, handle, strerror(errno));
 #endif
 
-               return(FALSE);
+                       return(FALSE);
+               }
        }
        if(byteswritten!=NULL) {
                *byteswritten=ret;
@@ -1222,53 +1053,15 @@ static gboolean console_write(gpointer handle, gconstpointer buffer,
        return(TRUE);
 }
 
-static void pipe_close_shared (gpointer handle)
+static void pipe_close (gpointer handle, gpointer data G_GNUC_UNUSED)
 {
-       struct _WapiHandle_file *pipe_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
-                               (gpointer *)&pipe_handle, NULL);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up pipe handle %p", handle);
-               return;
-       }
-       
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing pipe handle %p", handle);
+       g_message("%s: closing pipe handle %p", __func__, handle);
 #endif
-       
-       if(pipe_handle->filename!=0) {
-               _wapi_handle_scratch_delete (pipe_handle->filename);
-               pipe_handle->filename=0;
-       }
-       if(pipe_handle->security_attributes!=0) {
-               _wapi_handle_scratch_delete (pipe_handle->security_attributes);
-               pipe_handle->security_attributes=0;
-       }
-}
 
-static void pipe_close_private (gpointer handle)
-{
-       struct _WapiHandlePrivate_file *pipe_private_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL,
-                               (gpointer *)&pipe_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up pipe handle %p", handle);
-               return;
-       }
-       
-#ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": closing pipe handle %p with fd %d", handle,
-                 pipe_private_handle->fd);
-#endif
-       
-       close(pipe_private_handle->fd);
+       /* No filename with pipe handles */
+
+       close(GPOINTER_TO_UINT(handle));
 }
 
 static WapiFileType pipe_getfiletype(void)
@@ -1281,55 +1074,60 @@ static gboolean pipe_read (gpointer handle, gpointer buffer,
                           WapiOverlapped *overlapped G_GNUC_UNUSED)
 {
        struct _WapiHandle_file *pipe_handle;
-       struct _WapiHandlePrivate_file *pipe_private_handle;
        gboolean ok;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
-                               (gpointer *)&pipe_handle,
-                               (gpointer *)&pipe_private_handle);
+                               (gpointer *)&pipe_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up pipe handle %p", handle);
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
-       
+
        if(bytesread!=NULL) {
                *bytesread=0;
        }
        
-       if(!(pipe_handle->fileaccess&GENERIC_READ) &&
-          !(pipe_handle->fileaccess&GENERIC_ALL)) {
+       if(!(pipe_handle->fileaccess & GENERIC_READ) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION": handle %p fd %d doesn't have GENERIC_READ access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_READ access: %u",
+                         __func__, handle, pipe_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": reading up to %d bytes from pipe %p (fd %d)", numbytes,
-                  handle, pipe_private_handle->fd);
+       g_message ("%s: reading up to %d bytes from pipe %p", __func__,
+                  numbytes, handle);
 #endif
 
        do {
-               ret=read(pipe_private_handle->fd, buffer, numbytes);
-       }
-       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+               ret=read(fd, buffer, numbytes);
+       } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
                
-       if(ret==-1) {
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": read of handle %p fd %d error: %s", handle,
-                         pipe_private_handle->fd, strerror(errno));
+                       g_message("%s: read of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
 #endif
 
-               return(FALSE);
+                       return(FALSE);
+               }
        }
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": read %d bytes from pipe", ret);
+       g_message ("%s: read %d bytes from pipe", __func__, ret);
 #endif
 
        if(bytesread!=NULL) {
@@ -1344,16 +1142,16 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
                           WapiOverlapped *overlapped G_GNUC_UNUSED)
 {
        struct _WapiHandle_file *pipe_handle;
-       struct _WapiHandlePrivate_file *pipe_private_handle;
        gboolean ok;
        int ret;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
-                               (gpointer *)&pipe_handle,
-                               (gpointer *)&pipe_private_handle);
+                               (gpointer *)&pipe_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up pipe handle %p", handle);
+               g_warning ("%s: error looking up pipe handle %p", __func__,
+                          handle);
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -1361,34 +1159,41 @@ static gboolean pipe_write(gpointer handle, gconstpointer buffer,
                *byteswritten=0;
        }
        
-       if(!(pipe_handle->fileaccess&GENERIC_WRITE) &&
-          !(pipe_handle->fileaccess&GENERIC_ALL)) {
+       if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
+          !(pipe_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_WRITE access: %u", handle, pipe_private_handle->fd, pipe_handle->fileaccess);
+               g_message("%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
 #endif
 
+               SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
        }
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": writing up to %d bytes to pipe %p (fd %d)", numbytes,
-                  handle, pipe_private_handle->fd);
+       g_message ("%s: writing up to %d bytes to pipe %p", __func__, numbytes,
+                  handle);
 #endif
 
-       do {
-               ret=write(pipe_private_handle->fd, buffer, numbytes);
-       }
-       while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+       NO_SIGPIPE(
+               do {
+                       ret = write (fd, buffer, numbytes);
+               } while (ret == -1 && errno == EINTR &&
+                        !_wapi_thread_cur_apc_pending());
+               );
 
-       if(ret==-1) {
+       if (ret == -1) {
+               if (errno == EINTR) {
+                       ret = 0;
+               } else {
+                       _wapi_set_last_error_from_errno ();
+                       
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": write of handle %p fd %d error: %s", handle,
-                         pipe_private_handle->fd, strerror(errno));
+                       g_message("%s: write of handle %p error: %s", __func__,
+                                 handle, strerror(errno));
 #endif
 
-               return(FALSE);
+                       return(FALSE);
+               }
        }
        if(byteswritten!=NULL) {
                *byteswritten=ret;
@@ -1413,7 +1218,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                break;
        default:
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": Unknown access type 0x%x",
+               g_message("%s: Unknown access type 0x%x", __func__,
                          fileaccess);
 #endif
                break;
@@ -1436,7 +1241,7 @@ static int convert_flags(guint32 fileaccess, guint32 createmode)
                break;
        default:
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": Unknown create mode 0x%x",
+               g_message("%s: Unknown create mode 0x%x", __func__,
                          createmode);
 #endif
                break;
@@ -1461,8 +1266,7 @@ static guint32 convert_from_flags(int flags)
                fileaccess=GENERIC_READ|GENERIC_WRITE;
        } else {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": Can't figure out flags 0x%x", flags);
+               g_message("%s: Can't figure out flags 0x%x", __func__, flags);
 #endif
        }
 
@@ -1471,6 +1275,7 @@ static guint32 convert_from_flags(int flags)
        return(fileaccess);
 }
 
+#if 0 /* unused */
 static mode_t convert_perms(guint32 sharemode)
 {
        mode_t perms=0600;
@@ -1484,7 +1289,102 @@ static mode_t convert_perms(guint32 sharemode)
 
        return(perms);
 }
+#endif
 
+static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
+                                  guint32 fileaccess,
+                                  struct _WapiFileShare **share_info)
+{
+       gboolean file_already_shared;
+       guint32 file_existing_share, file_existing_access;
+
+       file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
+       
+       if (file_already_shared) {
+               /* The reference to this share info was incremented
+                * when we looked it up, so be careful to put it back
+                * if we conclude we can't use this file.
+                */
+               if (file_existing_share == 0) {
+                       /* Quick and easy, no possibility to share */
+#ifdef DEBUG
+                       g_message ("%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+#endif
+
+                       _wapi_handle_share_release (*share_info);
+                       
+                       return(FALSE);
+               }
+
+               if (((file_existing_share == FILE_SHARE_READ) &&
+                    (fileaccess != GENERIC_READ)) ||
+                   ((file_existing_share == FILE_SHARE_WRITE) &&
+                    (fileaccess != GENERIC_WRITE))) {
+                       /* New access mode doesn't match up */
+#ifdef DEBUG
+                       g_message ("%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+#endif
+
+                       _wapi_handle_share_release (*share_info);
+               
+                       return(FALSE);
+               }
+
+               if (((file_existing_access & GENERIC_READ) &&
+                    !(sharemode & FILE_SHARE_READ)) ||
+                   ((file_existing_access & GENERIC_WRITE) &&
+                    !(sharemode & FILE_SHARE_WRITE))) {
+                       /* New share mode doesn't match up */
+#ifdef DEBUG
+                       g_message ("%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+#endif
+
+                       _wapi_handle_share_release (*share_info);
+               
+                       return(FALSE);
+               }
+       } else {
+#ifdef DEBUG
+               g_message ("%s: New file!", __func__);
+#endif
+       }
+
+       return(TRUE);
+}
+
+static gboolean share_check (struct stat *statbuf, guint32 sharemode,
+                            guint32 fileaccess,
+                            struct _WapiFileShare **share_info, int fd)
+{
+       if (share_allows_open (statbuf, sharemode, fileaccess,
+                              share_info) == TRUE) {
+               return (TRUE);
+       }
+       
+       /* Got a share violation.  Double check that the file is still
+        * open by someone, in case a process crashed while still
+        * holding a file handle.  This will also cope with someone
+        * using Mono.Posix to close the file.  This is cheaper and
+        * less intrusive to other processes than initiating a handle
+        * collection.
+        */
+
+       _wapi_handle_check_share (*share_info, fd);
+       if (share_allows_open (statbuf, sharemode, fileaccess,
+                              share_info) == TRUE) {
+               return (TRUE);
+       }
+       
+       /* Still violating.  It's possible that a process crashed
+        * while still holding a file handle, and that a non-mono
+        * process has the file open.  (For example, C-c mcs while
+        * editing a source file.)  As a last resort, run a handle
+        * collection, which will remove stale share entries.
+        */
+       _wapi_handle_collect ();
+
+       return(share_allows_open (statbuf, sharemode, fileaccess, share_info));
+}
 
 /**
  * CreateFile:
@@ -1516,42 +1416,44 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                    guint32 createmode, guint32 attrs,
                    gpointer template G_GNUC_UNUSED)
 {
-       struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
+       struct _WapiHandle_file file_handle = {0};
        gpointer handle;
-       gboolean ok;
        int flags=convert_flags(fileaccess, createmode);
-       mode_t perms=convert_perms(sharemode);
+       /*mode_t perms=convert_perms(sharemode);*/
+       /* we don't use sharemode, because that relates to sharing of
+        * the file when the file is open and is already handled by
+        * other code, perms instead are the on-disk permissions and
+        * this is a sane default.
+        */
+       mode_t perms=0644;
        gchar *filename;
        int fd, ret;
-       int thr_ret;
-       gpointer cf_ret = INVALID_HANDLE_VALUE;
        struct stat statbuf;
-       gboolean file_already_shared;
-       guint32 file_existing_share, file_existing_access;
        
        mono_once (&io_ops_once, io_ops_init);
 
-       if(name==NULL) {
+       if (name == NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+               g_message ("%s: name is NULL", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_NAME);
                return(INVALID_HANDLE_VALUE);
        }
 
-       filename=mono_unicode_to_external (name);
-       if(filename==NULL) {
+       filename = mono_unicode_to_external (name);
+       if (filename == NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": unicode conversion returned NULL");
+               g_message("%s: unicode conversion returned NULL", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_NAME);
                return(INVALID_HANDLE_VALUE);
        }
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": Opening %s with share 0x%x and access 0x%x", filename, sharemode, fileaccess);
+       g_message ("%s: Opening %s with share 0x%x and access 0x%x", __func__,
+                  filename, sharemode, fileaccess);
 #endif
        
        fd = open(filename, flags, perms);
@@ -1572,8 +1474,8 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        
        if (fd == -1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": Error opening file %s: %s",
-                         filename, strerror(errno));
+               g_message("%s: Error opening file %s: %s", __func__, filename,
+                         strerror(errno));
 #endif
                _wapi_set_last_error_from_errno ();
                g_free (filename);
@@ -1581,10 +1483,24 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                return(INVALID_HANDLE_VALUE);
        }
 
+       if (fd >= _wapi_fd_reserve) {
+#ifdef DEBUG
+               g_message ("%s: File descriptor is too big", __func__);
+#endif
+
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+               
+               close (fd);
+               g_free (filename);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
+
        ret = fstat (fd, &statbuf);
        if (ret == -1) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": fstat error of file %s: %s", filename, strerror (errno));
+               g_message ("%s: fstat error of file %s: %s", __func__,
+                          filename, strerror (errno));
 #endif
                _wapi_set_last_error_from_errno ();
                g_free (filename);
@@ -1593,112 +1509,53 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                return(INVALID_HANDLE_VALUE);
        }
 
-       file_already_shared = _wapi_handle_get_or_set_share (statbuf.st_dev, statbuf.st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access);
-       
-       if (file_already_shared) {
-               if (file_existing_share == 0) {
-                       /* Quick and easy, no possibility to share */
-#ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": Share mode prevents open: requested access: 0x%x, file has sharing = NONE", fileaccess);
-#endif
-                       SetLastError (ERROR_SHARING_VIOLATION);
-                       g_free (filename);
-                       close (fd);
+       if (share_check (&statbuf, sharemode, fileaccess,
+                        &file_handle.share_info, fd) == FALSE) {
+               SetLastError (ERROR_SHARING_VIOLATION);
+               g_free (filename);
+               close (fd);
                
-                       return(INVALID_HANDLE_VALUE);
-               }
-
-               if (((file_existing_share == FILE_SHARE_READ) &&
-                    (fileaccess != GENERIC_READ)) ||
-                   ((file_existing_share == FILE_SHARE_WRITE) &&
-                    (fileaccess != GENERIC_WRITE))) {
-                       /* New access mode doesn't match up */
+               return (INVALID_HANDLE_VALUE);
+       }
+       if (file_handle.share_info == NULL) {
+               /* No space, so no more files can be opened */
 #ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", fileaccess, file_existing_share);
+               g_message ("%s: No space in the share table", __func__);
 #endif
-                       SetLastError (ERROR_SHARING_VIOLATION);
-                       g_free (filename);
-                       close (fd);
-               
-                       return(INVALID_HANDLE_VALUE);
-               }
 
-               if (((file_existing_access & GENERIC_READ) &&
-                    !(sharemode & FILE_SHARE_READ)) ||
-                   ((file_existing_access & GENERIC_WRITE) &&
-                    !(sharemode & FILE_SHARE_WRITE))) {
-                       /* New share mode doesn't match up */
-#ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": Access mode prevents open: requested share: 0x%x, file has access: 0x%x", sharemode, file_existing_access);
-#endif
-                       SetLastError (ERROR_SHARING_VIOLATION);
-                       g_free (filename);
-                       close (fd);
-               
-                       return(INVALID_HANDLE_VALUE);
-               }
-       } else {
-#ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": New file!");
-#endif
-       }
-       
-       handle=_wapi_handle_new (WAPI_HANDLE_FILE);
-       if(handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating file handle");
-               g_free (filename);
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
                close (fd);
+               g_free (filename);
                
                return(INVALID_HANDLE_VALUE);
        }
-
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
        
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
-               close (fd);
-               goto cleanup;
-       }
-       cf_ret = handle;
+       file_handle.filename = filename;
 
-       file_private_handle->fd=fd;
-       file_private_handle->assigned=TRUE;
-       file_private_handle->async = ((attrs & FILE_FLAG_OVERLAPPED) != 0);
-       file_handle->filename=_wapi_handle_scratch_store (filename,
-                                                         strlen (filename));
        if(security!=NULL) {
-               file_handle->security_attributes=_wapi_handle_scratch_store (
-                       security, sizeof(WapiSecurityAttributes));
+               //file_handle->security_attributes=_wapi_handle_scratch_store (
+               //security, sizeof(WapiSecurityAttributes));
        }
        
-       file_handle->fileaccess=fileaccess;
-       file_handle->sharemode=sharemode;
-       file_handle->attrs=attrs;
-       file_handle->device = statbuf.st_dev;
-       file_handle->inode = statbuf.st_ino;
+       file_handle.fileaccess=fileaccess;
+       file_handle.sharemode=sharemode;
+       file_handle.attrs=attrs;
+       
+       handle = _wapi_handle_new_fd (WAPI_HANDLE_FILE, fd, &file_handle);
+       if (handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating file handle", __func__);
+               g_free (filename);
+               close (fd);
+               
+               SetLastError (ERROR_GEN_FAILURE);
+               return(INVALID_HANDLE_VALUE);
+       }
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": returning handle %p with fd %d", handle,
-                 file_private_handle->fd);
+       g_message("%s: returning handle %p", __func__, handle);
 #endif
-
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-       
-       g_free (filename);
        
-       return(cf_ret);
+       return(handle);
 }
 
 /**
@@ -1717,19 +1574,20 @@ gboolean DeleteFile(const gunichar2 *name)
        
        if(name==NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": name is NULL");
+               g_message("%s: name is NULL", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
        }
 
        filename=mono_unicode_to_external(name);
        if(filename==NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": unicode conversion returned NULL");
+               g_message("%s: unicode conversion returned NULL", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_NAME);
                return(FALSE);
        }
        
@@ -1752,7 +1610,9 @@ gboolean DeleteFile(const gunichar2 *name)
  * @dest_name: a pointer to a NULL-terminated unicode string, that is the
  * new name for the file.
  *
- * Renames file @name to @dest_name
+ * Renames file @name to @dest_name.
+ * MoveFile sets ERROR_ALREADY_EXISTS if the destination exists, except
+ * when it is the same file as the source.  In that case it silently succeeds.
  *
  * Return value: %TRUE on success, %FALSE otherwise.
  */
@@ -1760,26 +1620,60 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
 {
        gchar *utf8_name, *utf8_dest_name;
        int result;
+       struct stat stat_src, stat_dest;
+       
+       if(name==NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
                
+               SetLastError (ERROR_INVALID_NAME);
                return FALSE;
        }
+       
+       if(dest_name==NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               g_free (utf8_name);
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
 
        utf8_dest_name = mono_unicode_to_external (dest_name);
        if (utf8_dest_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
 
                g_free (utf8_name);
+               SetLastError (ERROR_INVALID_NAME);
                return FALSE;
        }
 
+       /*
+        * In C# land we check for the existence of src, but not for dest.
+        * We check it here and return the failure if dest exists and is not
+        * the same file as src.
+        */
+       if (!stat (utf8_dest_name, &stat_dest) && !stat (utf8_name, &stat_src)) {
+               if (stat_dest.st_dev != stat_src.st_dev || stat_dest.st_ino != stat_src.st_ino) {
+                       SetLastError (ERROR_ALREADY_EXISTS);
+                       return FALSE;
+               }       
+       }
+
        result = rename (utf8_name, utf8_dest_name);
        g_free (utf8_name);
        g_free (utf8_dest_name);
@@ -1787,6 +1681,7 @@ gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
        if (result != 0 && errno == EXDEV) {
                /* Try a copy to the new location, and delete the source */
                if (CopyFile (name, dest_name, TRUE)==FALSE) {
+                       /* CopyFile will set the error */
                        return(FALSE);
                }
                
@@ -1832,20 +1727,41 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
        int remain, n;
        struct stat st;
        
+       if(name==NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
        utf8_src = mono_unicode_to_external (name);
        if (utf8_src == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion of source returned NULL");
+               g_message ("%s: unicode conversion of source returned NULL",
+                          __func__);
 #endif
 
                SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
        }
        
+       if(dest_name==NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               g_free (utf8_src);
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
        utf8_dest = mono_unicode_to_external (dest_name);
        if (utf8_dest == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion of dest returned NULL");
+               g_message ("%s: unicode conversion of dest returned NULL",
+                          __func__);
 #endif
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -1929,7 +1845,7 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
 
                                _wapi_set_last_error_from_errno ();
 #ifdef DEBUG
-                               g_message (G_GNUC_PRETTY_FUNCTION ": write failed.");
+                               g_message ("%s: write failed.", __func__);
 #endif
 
                                g_free (utf8_src);
@@ -1953,84 +1869,58 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
 }
 
 static mono_once_t stdhandle_once=MONO_ONCE_INIT;
-static gpointer stdin_handle=NULL;
-static gpointer stdout_handle=NULL;
-static gpointer stderr_handle=NULL;
+static gpointer stdin_handle=INVALID_HANDLE_VALUE;
+static gpointer stdout_handle=INVALID_HANDLE_VALUE;
+static gpointer stderr_handle=INVALID_HANDLE_VALUE;
 
 static gpointer stdhandle_create (int fd, const guchar *name)
 {
-       struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
-       gboolean ok;
-       gpointer handle, ret = NULL;
+       struct _WapiHandle_file file_handle = {0};
+       gpointer handle;
        int flags;
-       int thr_ret;
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": creating standard handle type %s",
-                 name);
+       g_message("%s: creating standard handle type %s, fd %d", __func__,
+                 name, fd);
 #endif
        
        /* Check if fd is valid */
        do {
                flags=fcntl(fd, F_GETFL);
-       }
-       while (flags==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+       } while (flags == -1 && errno == EINTR);
 
        if(flags==-1) {
                /* Invalid fd.  Not really much point checking for EBADF
                 * specifically
                 */
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": fcntl error on fd %d: %s",
-                         fd, strerror(errno));
+               g_message("%s: fcntl error on fd %d: %s", __func__, fd,
+                         strerror(errno));
 #endif
 
+               _wapi_set_last_error_from_errno ();
                return(INVALID_HANDLE_VALUE);
        }
 
-       handle=_wapi_handle_new (WAPI_HANDLE_CONSOLE);
-       if(handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating file handle");
-               return(NULL);
-       }
-
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
-                               (gpointer *)&file_handle,
-                               (gpointer *)&file_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up console handle %p", handle);
-               goto cleanup;
-       }
-       ret = handle;
-       
-       file_private_handle->fd=fd;
-       file_private_handle->assigned=TRUE;
-       file_handle->filename=_wapi_handle_scratch_store (name, strlen (name));
+       file_handle.filename = g_strdup(name);
        /* some default security attributes might be needed */
-       file_handle->security_attributes=0;
-       file_handle->fileaccess=convert_from_flags(flags);
-       file_handle->sharemode=0;
-       file_handle->attrs=0;
+       file_handle.security_attributes=0;
+       file_handle.fileaccess=convert_from_flags(flags);
+       file_handle.sharemode=0;
+       file_handle.attrs=0;
+
+       handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle);
+       if (handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating file handle", __func__);
+               SetLastError (ERROR_GEN_FAILURE);
+               return(INVALID_HANDLE_VALUE);
+       }
        
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": returning handle %p with fd %d",
-                 handle, file_private_handle->fd);
+       g_message("%s: returning handle %p", __func__, handle);
 #endif
 
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-
-       return(ret);
+       return(handle);
 }
 
 static void stdhandle_init (void)
@@ -2072,13 +1962,18 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
 
        default:
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": unknown standard handle type");
+               g_message("%s: unknown standard handle type", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(INVALID_HANDLE_VALUE);
        }
 
+       if (handle == INVALID_HANDLE_VALUE) {
+               SetLastError (ERROR_NO_MORE_FILES);
+               return(INVALID_HANDLE_VALUE);
+       }
+       
        /* Add a reference to this handle */
        _wapi_handle_ref (handle);
        
@@ -2115,9 +2010,12 @@ gpointer GetStdHandle(WapiStdHandle stdhandle)
 gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
                  guint32 *bytesread, WapiOverlapped *overlapped)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
        if(io_ops[type].readfile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2153,9 +2051,12 @@ gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
 gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
                   guint32 *byteswritten, WapiOverlapped *overlapped)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
        if(io_ops[type].writefile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2175,9 +2076,12 @@ gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
  */
 gboolean FlushFileBuffers(gpointer handle)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
        if(io_ops[type].flushfile==NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2196,9 +2100,12 @@ gboolean FlushFileBuffers(gpointer handle)
  */
 gboolean SetEndOfFile(gpointer handle)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].setendoffile==NULL) {
+       if (io_ops[type].setendoffile == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2237,10 +2144,13 @@ gboolean SetEndOfFile(gpointer handle)
 guint32 SetFilePointer(gpointer handle, gint32 movedistance,
                       gint32 *highmovedistance, WapiSeekMethod method)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].seek==NULL) {
-               return(FALSE);
+       if (io_ops[type].seek == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_SET_FILE_POINTER);
        }
        
        return(io_ops[type].seek (handle, movedistance, highmovedistance,
@@ -2260,9 +2170,17 @@ guint32 SetFilePointer(gpointer handle, gint32 movedistance,
  */
 WapiFileType GetFileType(gpointer handle)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       if (!_WAPI_PRIVATE_HAVE_SLOT (handle)) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FILE_TYPE_UNKNOWN);
+       }
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].getfiletype==NULL) {
+       if (io_ops[type].getfiletype == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FILE_TYPE_UNKNOWN);
        }
        
@@ -2287,10 +2205,13 @@ WapiFileType GetFileType(gpointer handle)
  */
 guint32 GetFileSize(gpointer handle, guint32 *highsize)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].getfilesize==NULL) {
-               return(FALSE);
+       if (io_ops[type].getfilesize == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(INVALID_FILE_SIZE);
        }
        
        return(io_ops[type].getfilesize (handle, highsize));
@@ -2324,9 +2245,12 @@ guint32 GetFileSize(gpointer handle, guint32 *highsize)
 gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
                     WapiFileTime *last_access, WapiFileTime *last_write)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].getfiletime==NULL) {
+       if (io_ops[type].getfiletime == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2361,9 +2285,12 @@ gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
                     const WapiFileTime *last_access,
                     const WapiFileTime *last_write)
 {
-       WapiHandleType type=_wapi_handle_type (handle);
+       WapiHandleType type;
+
+       type = _wapi_handle_type (handle);
        
-       if(io_ops[type].setfiletime==NULL) {
+       if (io_ops[type].setfiletime == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
        
@@ -2407,9 +2334,10 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        
        if(system_time==NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": system_time NULL");
+               g_message("%s: system_time NULL", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
        }
        
@@ -2422,51 +2350,49 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
         */
        if(file_ticks<0) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": file_time too big");
+               g_message("%s: file_time too big", __func__);
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return(FALSE);
        }
 
        totaldays=(file_ticks / TICKS_PER_DAY);
        rem = file_ticks % TICKS_PER_DAY;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld rem: %lld",
-                 totaldays, rem);
+       g_message("%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
 #endif
 
        system_time->wHour=rem/TICKS_PER_HOUR;
        rem %= TICKS_PER_HOUR;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Hour: %d rem: %lld",
-                 system_time->wHour, rem);
+       g_message("%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
 #endif
        
        system_time->wMinute = rem / TICKS_PER_MINUTE;
        rem %= TICKS_PER_MINUTE;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Minute: %d rem: %lld",
-                 system_time->wMinute, rem);
+       g_message("%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
+                 rem);
 #endif
        
        system_time->wSecond = rem / TICKS_PER_SECOND;
        rem %= TICKS_PER_SECOND;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Second: %d rem: %lld",
-                 system_time->wSecond, rem);
+       g_message("%s: Second: %d rem: %lld", __func__, system_time->wSecond,
+                 rem);
 #endif
        
        system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Milliseconds: %d",
+       g_message("%s: Milliseconds: %d", __func__,
                  system_time->wMilliseconds);
 #endif
 
        /* January 1, 1601 was a Monday, according to Emacs calendar */
        system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Day of week: %d",
-                 system_time->wDayOfWeek);
+       g_message("%s: Day of week: %d", __func__, system_time->wDayOfWeek);
 #endif
        
        /* This algorithm to find year and month given days from epoch
@@ -2481,11 +2407,10 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                /* Guess a corrected year, assuming 365 days per year */
                gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": totaldays: %lld yg: %lld y: %lld", totaldays, yg,
+               g_message("%s: totaldays: %lld yg: %lld y: %lld", __func__,
+                         totaldays, yg,
                          y);
-               g_message(G_GNUC_PRETTY_FUNCTION
-                         ": LEAPS(yg): %lld LEAPS(y): %lld",
+               g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
                          LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
 #endif
                
@@ -2494,18 +2419,17 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
                              + LEAPS_THRU_END_OF (yg - 1)
                              - LEAPS_THRU_END_OF (y - 1));
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld",
-                         totaldays);
+               g_message("%s: totaldays: %lld", __func__, totaldays);
 #endif
                y = yg;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": y: %lld", y);
+               g_message("%s: y: %lld", __func__, y);
 #endif
        }
        
        system_time->wYear = y;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Year: %d", system_time->wYear);
+       g_message("%s: Year: %d", __func__, system_time->wYear);
 #endif
 
        ip = mon_yday[isleap(y)];
@@ -2515,17 +2439,17 @@ gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
        }
        totaldays-=ip[y];
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": totaldays: %lld", totaldays);
+       g_message("%s: totaldays: %lld", __func__, totaldays);
 #endif
        
        system_time->wMonth = y + 1;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Month: %d", system_time->wMonth);
+       g_message("%s: Month: %d", __func__, system_time->wMonth);
 #endif
 
        system_time->wDay = totaldays + 1;
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": Day: %d", system_time->wDay);
+       g_message("%s: Day: %d", __func__, system_time->wDay);
 #endif
        
        return(TRUE);
@@ -2705,17 +2629,14 @@ mono_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
 
 gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 {
-       struct _WapiHandlePrivate_find *find_handle;
-       gpointer handle, find_ret = INVALID_HANDLE_VALUE;
-       gboolean ok;
+       struct _WapiHandle_find find_handle = {0};
+       gpointer handle;
        gchar *utf8_pattern = NULL, *dir_part, *entry_part;
        int result;
-       int thr_ret;
-       gboolean unref = FALSE;
        
        if (pattern == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": pattern is NULL");
+               g_message ("%s: pattern is NULL", __func__);
 #endif
 
                SetLastError (ERROR_PATH_NOT_FOUND);
@@ -2725,7 +2646,7 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        utf8_pattern = mono_unicode_to_external (pattern);
        if (utf8_pattern == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
                
                SetLastError (ERROR_INVALID_NAME);
@@ -2733,13 +2654,12 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        }
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": looking for [%s]",
-               utf8_pattern);
+       g_message ("%s: looking for [%s]", __func__, utf8_pattern);
 #endif
        
        /* Figure out which bit of the pattern is the directory */
-       dir_part=g_path_get_dirname (utf8_pattern);
-       entry_part=g_path_get_basename (utf8_pattern);
+       dir_part = g_path_get_dirname (utf8_pattern);
+       entry_part = g_path_get_basename (utf8_pattern);
 
 #if 0
        /* Don't do this check for now, it breaks if directories
@@ -2754,35 +2674,6 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
                return(INVALID_HANDLE_VALUE);
        }
 #endif
-       
-       handle=_wapi_handle_new (WAPI_HANDLE_FIND);
-       if(handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION ": error creating find handle");
-               g_free (dir_part);
-               g_free (entry_part);
-               g_free (utf8_pattern);
-               
-               return(INVALID_HANDLE_VALUE);
-       }
-
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
-                               (gpointer *)&find_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up find handle %p", handle);
-               g_free (dir_part);
-               dir_part = NULL;
-               g_free (entry_part);
-               entry_part = NULL;
-               g_free (utf8_pattern);
-               utf8_pattern = NULL;
-               goto cleanup;
-       }
 
        /* The pattern can specify a directory or a set of files.
         *
@@ -2804,8 +2695,8 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
         * than mess around with regexes.
         */
 
-       find_handle->namelist = NULL;
-       result = mono_io_scandir (dir_part, entry_part, &find_handle->namelist);
+       find_handle.namelist = NULL;
+       result = mono_io_scandir (dir_part, entry_part, &find_handle.namelist);
        
        if (result < 0) {
 #ifdef DEBUG
@@ -2813,56 +2704,50 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 #endif
                _wapi_set_last_error_from_errno ();
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": scandir error: %s", g_strerror (errnum));
+               g_message ("%s: scandir error: %s", __func__,
+                          g_strerror (errnum));
 #endif
                g_free (utf8_pattern);
                g_free (entry_part);
                g_free (dir_part);
-               unref = TRUE;
-               goto cleanup;
+               return (INVALID_HANDLE_VALUE);
        }
 
        g_free (utf8_pattern);
        g_free (entry_part);
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": Got %d matches", result);
+       g_message ("%s: Got %d matches", __func__, result);
 #endif
 
-       find_handle->dir_part = dir_part;
-       find_handle->num = result;
-       find_handle->count = 0;
-
-       find_ret = handle;
-
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
+       find_handle.dir_part = dir_part;
+       find_handle.num = result;
+       find_handle.count = 0;
+       
+       handle = _wapi_handle_new (WAPI_HANDLE_FIND, &find_handle);
+       if (handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating find handle", __func__);
+               g_free (dir_part);
+               g_free (entry_part);
+               g_free (utf8_pattern);
+               SetLastError (ERROR_GEN_FAILURE);
+               
+               return(INVALID_HANDLE_VALUE);
+       }
 
-       /* FindNextFile has to be called after unlocking the handle,
-        * because it wants to lock the handle itself
-        */
-       if (find_ret != INVALID_HANDLE_VALUE &&
+       if (handle != INVALID_HANDLE_VALUE &&
            !FindNextFile (handle, find_data)) {
                FindClose (handle);
                SetLastError (ERROR_NO_MORE_FILES);
-               find_ret = INVALID_HANDLE_VALUE;
+               handle = INVALID_HANDLE_VALUE;
        }
 
-       /* Must not call _wapi_handle_unref() with the handle already
-        * locked
-        */
-       if (unref) {
-               _wapi_handle_unref (handle);
-       }
-       
-       return (find_ret);
+       return (handle);
 }
 
 gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
 {
-       struct _WapiHandlePrivate_find *find_handle;
+       struct _WapiHandle_find *find_handle;
        gboolean ok;
        struct stat buf;
        gchar *filename;
@@ -2873,11 +2758,11 @@ gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
        int thr_ret;
        gboolean ret = FALSE;
        
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
                                (gpointer *)&find_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up find handle %p", handle);
+               g_warning ("%s: error looking up find handle %p", __func__,
+                          handle);
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
@@ -2898,7 +2783,7 @@ retry:
        filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
        if (lstat (filename, &buf) != 0) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": stat failed: %s", filename);
+               g_message ("%s: stat failed: %s", __func__, filename);
 #endif
 
                g_free (filename);
@@ -2917,8 +2802,8 @@ retry:
                }
        }
        
-       utf8_filename=mono_utf8_from_external (filename);
-       if(utf8_filename==NULL) {
+       utf8_filename = mono_utf8_from_external (filename);
+       if (utf8_filename == NULL) {
                /* We couldn't turn this filename into utf8 (eg the
                 * encoding of the name wasn't convertible), so just
                 * ignore it.
@@ -2929,7 +2814,7 @@ retry:
        g_free (filename);
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": Found [%s]", utf8_filename);
+       g_message ("%s: Found [%s]", __func__, utf8_filename);
 #endif
        
        /* fill data block */
@@ -2948,8 +2833,7 @@ retry:
        if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                find_data->nFileSizeHigh = 0;
                find_data->nFileSizeLow = 0;
-       }
-       else {
+       } else {
                find_data->nFileSizeHigh = buf.st_size >> 32;
                find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
        }
@@ -3002,15 +2886,15 @@ cleanup:
  */
 gboolean FindClose (gpointer handle)
 {
-       struct _WapiHandlePrivate_find *find_handle;
+       struct _WapiHandle_find *find_handle;
        gboolean ok;
        int thr_ret;
 
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
+       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND,
                                (gpointer *)&find_handle);
        if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up find handle %p", handle);
+               g_warning ("%s: error looking up find handle %p", __func__,
+                          handle);
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
@@ -3042,19 +2926,30 @@ gboolean FindClose (gpointer handle)
  *
  * Return value: %TRUE on success, %FALSE otherwise.
  */
-gboolean CreateDirectory (const gunichar2 *name, WapiSecurityAttributes *security)
+gboolean CreateDirectory (const gunichar2 *name,
+                         WapiSecurityAttributes *security)
 {
        gchar *utf8_name;
        int result;
        struct stat buf;
        guint32 attrs;
        
+       if (name == NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
        
+               SetLastError (ERROR_INVALID_NAME);
                return FALSE;
        }
 
@@ -3101,13 +2996,23 @@ gboolean RemoveDirectory (const gunichar2 *name)
 {
        gchar *utf8_name;
        int result;
+       
+       if (name == NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
                
+               SetLastError (ERROR_INVALID_NAME);
                return FALSE;
        }
 
@@ -3135,10 +3040,19 @@ guint32 GetFileAttributes (const gunichar2 *name)
        struct stat buf;
        int result;
        
+       if (name == NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
+       
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -3178,16 +3092,27 @@ gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels lev
        
        if (level != GetFileExInfoStandard) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": info level %d not supported.", level);
+               g_message ("%s: info level %d not supported.", __func__,
+                          level);
 #endif
 
+               SetLastError (ERROR_INVALID_PARAMETER);
                return FALSE;
        }
+       
+       if (name == NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
 
        utf8_name = mono_unicode_to_external (name);
        if (utf8_name == NULL) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unicode conversion returned NULL");
+               g_message ("%s: unicode conversion returned NULL", __func__);
 #endif
 
                SetLastError (ERROR_INVALID_PARAMETER);
@@ -3249,15 +3174,33 @@ extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
         * Currently we only handle one *internal* case, with a value that is
         * not standard: 0x80000000, which means `set executable bit'
         */
+       
+       if (name == NULL) {
+#ifdef DEBUG
+               g_message("%s: name is NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return(FALSE);
+       }
 
        utf8_name = mono_unicode_to_external (name);
+       if (utf8_name == NULL) {
+#ifdef DEBUG
+               g_message ("%s: unicode conversion returned NULL", __func__);
+#endif
+
+               SetLastError (ERROR_INVALID_NAME);
+               return FALSE;
+       }
+
        result = stat (utf8_name, &buf);
        if (result != 0) {
                g_free (utf8_name);
                SetLastError (ERROR_FILE_NOT_FOUND);
                return FALSE;
        }
-       
+
        /* Contrary to the documentation, ms allows NORMAL to be
         * specified along with other attributes, so dont bother to
         * catch that case here.
@@ -3362,170 +3305,84 @@ extern gboolean SetCurrentDirectory (const gunichar2 *path)
        return result;
 }
 
-int _wapi_file_handle_to_fd (gpointer handle)
-{
-       struct _WapiHandlePrivate_file *file_private_handle;
-       gboolean ok;
-       
-#ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": looking up fd for %p", handle);
-#endif
-
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE, NULL,
-                               (gpointer *)&file_private_handle);
-       if(ok==FALSE) {
-               ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE, NULL,
-                                       (gpointer *)&file_private_handle);
-               if(ok==FALSE) {
-                       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_PIPE, NULL,
-                                               (gpointer *)&file_private_handle);
-                       if(ok==FALSE) {
-#ifdef DEBUG
-                               g_message (G_GNUC_PRETTY_FUNCTION
-                                          ": returning -1");
-#endif
-                               return(-1);
-                       }
-               }
-       }
-       
-#ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": returning %d",
-                  file_private_handle->fd);
-#endif
-       
-       return(file_private_handle->fd);
-}
-
 gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
                     WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 size)
 {
-       struct _WapiHandle_file *pipe_read_handle;
-       struct _WapiHandle_file *pipe_write_handle;
-       struct _WapiHandlePrivate_file *pipe_read_private_handle;
-       struct _WapiHandlePrivate_file *pipe_write_private_handle;
+       struct _WapiHandle_file pipe_read_handle = {0};
+       struct _WapiHandle_file pipe_write_handle = {0};
        gpointer read_handle;
        gpointer write_handle;
-       gboolean ok;
        int filedes[2];
        int ret;
-       int thr_ret;
-       gboolean unref_read = FALSE, unref_write = FALSE;
-       gboolean cp_ret = FALSE;
        
        mono_once (&io_ops_once, io_ops_init);
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": Creating pipe");
+       g_message ("%s: Creating pipe", __func__);
 #endif
 
        ret=pipe (filedes);
        if(ret==-1) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": Error creating pipe: %s",
+               g_message ("%s: Error creating pipe: %s", __func__,
                           strerror (errno));
 #endif
                
                _wapi_set_last_error_from_errno ();
                return(FALSE);
        }
-       
-       /* filedes[0] is open for reading, filedes[1] for writing */
 
-       read_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
-       if(read_handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating pipe read handle");
+       if (filedes[0] >= _wapi_fd_reserve ||
+           filedes[1] >= _wapi_fd_reserve) {
+#ifdef DEBUG
+               g_message ("%s: File descriptor is too big", __func__);
+#endif
+
+               SetLastError (ERROR_TOO_MANY_OPEN_FILES);
+               
                close (filedes[0]);
                close (filedes[1]);
+               
                return(FALSE);
        }
        
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             read_handle);
-       thr_ret = _wapi_handle_lock_handle (read_handle);
-       g_assert (thr_ret == 0);
+       /* filedes[0] is open for reading, filedes[1] for writing */
 
-       ok=_wapi_lookup_handle (read_handle, WAPI_HANDLE_PIPE,
-                               (gpointer *)&pipe_read_handle,
-                               (gpointer *)&pipe_read_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
+       pipe_read_handle.fileaccess = GENERIC_READ;
+       read_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[0],
+                                          &pipe_read_handle);
+       if (read_handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating pipe read handle", __func__);
                close (filedes[0]);
                close (filedes[1]);
-               goto cleanup;
-       }
-       
-       write_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
-       if(write_handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating pipe write handle");
-               unref_read = TRUE;
+               SetLastError (ERROR_GEN_FAILURE);
                
-               close (filedes[0]);
-               close (filedes[1]);
-               goto cleanup;
+               return(FALSE);
        }
        
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             write_handle);
-       thr_ret = _wapi_handle_lock_handle (write_handle);
-       g_assert (thr_ret == 0);
-
-       ok=_wapi_lookup_handle (write_handle, WAPI_HANDLE_PIPE,
-                               (gpointer *)&pipe_write_handle,
-                               (gpointer *)&pipe_write_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
-               unref_read = TRUE;
-               unref_write = TRUE;
+       pipe_write_handle.fileaccess = GENERIC_WRITE;
+       write_handle = _wapi_handle_new_fd (WAPI_HANDLE_PIPE, filedes[1],
+                                           &pipe_write_handle);
+       if (write_handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating pipe write handle", __func__);
+               _wapi_handle_unref (read_handle);
                
                close (filedes[0]);
                close (filedes[1]);
-               goto write_cleanup;
+               SetLastError (ERROR_GEN_FAILURE);
+               
+               return(FALSE);
        }
-       cp_ret = TRUE;
-       
-       pipe_read_private_handle->fd=filedes[0];
-       pipe_read_private_handle->assigned=TRUE;
-       pipe_read_handle->fileaccess=GENERIC_READ;
-       
-       *readpipe=read_handle;
-
-       pipe_write_private_handle->fd=filedes[1];
-       pipe_write_private_handle->assigned=TRUE;
-       pipe_write_handle->fileaccess=GENERIC_WRITE;
        
-       *writepipe=write_handle;
+       *readpipe = read_handle;
+       *writepipe = write_handle;
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": Returning pipe: read handle %p, write handle %p",
-                  read_handle, write_handle);
+       g_message ("%s: Returning pipe: read handle %p, write handle %p",
+                  __func__, read_handle, write_handle);
 #endif
 
-write_cleanup:
-       thr_ret =_wapi_handle_unlock_handle (write_handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-
-       if (unref_write) {
-               _wapi_handle_unref (write_handle);
-       }
-
-cleanup:
-       thr_ret =_wapi_handle_unlock_handle (read_handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-
-       /* Must not call _wapi_handle_unref() with the handle already
-        * locked
-        */
-       if (unref_read) {
-               _wapi_handle_unref (read_handle);
-       }
-       
-       return(cp_ret);
+       return(TRUE);
 }
 
 guint32 GetTempPath (guint32 len, gunichar2 *buf)
@@ -3550,9 +3407,8 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf)
                
                if(dirlen+1>len) {
 #ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION
-                                  ": Size %d smaller than needed (%ld)", len,
-                                  dirlen+1);
+                       g_message ("%s: Size %d smaller than needed (%ld)",
+                                  __func__, len, dirlen+1);
 #endif
                
                        ret=dirlen+1;
@@ -3573,54 +3429,6 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf)
        return(ret);
 }
 
-gboolean
-_wapi_io_add_callback (gpointer handle,
-                      WapiOverlappedCB callback,
-                      guint64 flags G_GNUC_UNUSED)
-{
-       struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
-       gboolean ok;
-       int thr_ret;
-       gboolean ret = FALSE;
-       
-       ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                                 (gpointer *) &file_handle,
-                                 (gpointer *) &file_private_handle);
-
-       if (ok == FALSE) {
-               ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PIPE,
-                                         (gpointer *) &file_handle,
-                                         (gpointer *) &file_private_handle);
-
-       }
-
-       if (ok == FALSE || file_private_handle->async == FALSE) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-       
-       if (file_private_handle->callback != NULL) {
-               SetLastError (ERROR_INVALID_PARAMETER);
-               goto cleanup;
-       }
-       ret = TRUE;
-       
-       file_private_handle->callback = callback;
-
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-
-       return(ret);
-}
-
 gint32
 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
 {
@@ -3651,12 +3459,15 @@ GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
                        continue;
 
                splitted = g_strsplit (buffer, " ", 0);
-               if (!*splitted || !*(splitted + 1))
+               if (!*splitted || !*(splitted + 1)) {
+                       g_strfreev (splitted);
                        continue;
+               }
 
                dir = g_utf8_to_utf16 (*(splitted + 1), -1, &length, NULL, NULL);
                g_strfreev (splitted);
                if (total + length + 1 > len) {
+                       fclose (fp);
                        return len * 2; /* guess */
                }
 
@@ -3714,14 +3525,28 @@ static gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length)
        
        do {
                ret = fcntl (fd, F_SETLK, &lock_data);
-       }
-       while(ret == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
+       } while(ret == -1 && errno == EINTR);
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": fcntl returns %d", ret);
+       g_message ("%s: fcntl returns %d", __func__, ret);
 #endif
 
        if (ret == -1) {
+               /*
+                * if locks are not available (NFS for example),
+                * ignore the error
+                */
+               if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+                   || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+                   || errno == ENOTSUP
+#endif
+                  ) {
+                       return (TRUE);
+               }
+               
                SetLastError (ERROR_LOCK_VIOLATION);
                return(FALSE);
        }
@@ -3741,14 +3566,28 @@ static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length)
        
        do {
                ret = fcntl (fd, F_SETLK, &lock_data);
-       }
-       while(ret == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending ());
+       } while(ret == -1 && errno == EINTR);
        
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": fcntl returns %d", ret);
+       g_message ("%s: fcntl returns %d", __func__, ret);
 #endif
        
        if (ret == -1) {
+               /*
+                * if locks are not available (NFS for example),
+                * ignore the error
+                */
+               if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+                   || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+                   || errno == ENOTSUP
+#endif
+                  ) {
+                       return (TRUE);
+               }
+               
                SetLastError (ERROR_LOCK_VIOLATION);
                return(FALSE);
        }
@@ -3760,16 +3599,15 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
                   guint32 length_low, guint32 length_high)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        off_t offset, length;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                                 (gpointer *)&file_handle,
-                                 (gpointer *)&file_private_handle);
+                                 (gpointer *)&file_handle);
        if (ok == FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
@@ -3778,7 +3616,7 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
            !(file_handle->fileaccess & GENERIC_WRITE) &&
            !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
                SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -3789,48 +3627,45 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
        length = ((gint64)length_high << 32) | length_low;
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": Locking handle %p fd %d, offset %lld, length %lld",
-                  handle, file_private_handle->fd, offset, length);
+       g_message ("%s: Locking handle %p, offset %lld, length %lld", __func__,
+                  handle, offset, length);
 #endif
 #else
        offset = offset_low;
        length = length_low;
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": Locking handle %p fd %d, offset %ld, length %ld",
-                  handle, file_private_handle->fd, offset, length);
+       g_message ("%s: Locking handle %p, offset %ld, length %ld", __func__,
+                  handle, offset, length);
 #endif
 #endif
 
-       return(_wapi_lock_file_region (file_private_handle->fd, offset,
-                                      length));
+       return(_wapi_lock_file_region (fd, offset, length));
 }
 
-gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
-                    guint32 length_low, guint32 length_high)
+gboolean UnlockFile (gpointer handle, guint32 offset_low,
+                    guint32 offset_high, guint32 length_low,
+                    guint32 length_high)
 {
        struct _WapiHandle_file *file_handle;
-       struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
        off_t offset, length;
+       int fd = GPOINTER_TO_UINT(handle);
        
        ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
-                                 (gpointer *)&file_handle,
-                                 (gpointer *)&file_private_handle);
+                                 (gpointer *)&file_handle);
        if (ok == FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up file handle %p", handle);
+               g_warning ("%s: error looking up file handle %p", __func__,
+                          handle);
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
-
+       
        if (!(file_handle->fileaccess & GENERIC_READ) &&
            !(file_handle->fileaccess & GENERIC_WRITE) &&
            !(file_handle->fileaccess & GENERIC_ALL)) {
 #ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": handle %p fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", handle, file_private_handle->fd, file_handle->fileaccess);
+               g_message ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
 #endif
                SetLastError (ERROR_ACCESS_DENIED);
                return(FALSE);
@@ -3841,21 +3676,18 @@ gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
        length = ((gint64)length_high << 32) | length_low;
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": Unlocking handle %p fd %d, offset %lld, length %lld",
-                  handle, file_private_handle->fd, offset, length);
+       g_message ("%s: Unlocking handle %p, offset %lld, length %lld",
+                  __func__, handle, offset, length);
 #endif
 #else
        offset = offset_low;
        length = length_low;
 
 #ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION
-                  ": Unlocking handle %p fd %d, offset %ld, length %ld",
-                  handle, file_private_handle->fd, offset, length);
+       g_message ("%s: Unlocking handle %p, offset %ld, length %ld", __func__,
+                  handle, offset, length);
 #endif
 #endif
 
-       return(_wapi_unlock_file_region (file_private_handle->fd, offset,
-                                        length));
+       return(_wapi_unlock_file_region (fd, offset, length));
 }