Fixed some NULL pointer handling errors.
[wine] / files / file.c
index 04e3bb7..a3089a2 100644 (file)
@@ -4,12 +4,27 @@
  * Copyright 1993 John Burton
  * Copyright 1996 Alexandre Julliard
  *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
  * TODO:
  *    Fix the CopyFileEx methods to implement the "extended" functionality.
  *    Right now, they simply call the CopyFile method.
  */
 
 #include "config.h"
+#include "wine/port.h"
 
 #include <assert.h>
 #include <ctype.h>
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #endif
-#include <sys/time.h>
-#include <sys/poll.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
 #include <time.h>
-#include <unistd.h>
-#include <utime.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_UTIME_H
+# include <utime.h>
+#endif
 
 #include "winerror.h"
 #include "windef.h"
 #include "winbase.h"
+#include "winternl.h"
 #include "wine/winbase16.h"
-#include "wine/port.h"
+#include "wine/server.h"
+
 #include "drive.h"
 #include "file.h"
+#include "async.h"
 #include "heap.h"
 #include "msdos.h"
 #include "wincon.h"
-#include "debugtools.h"
 
-#include "server.h"
+#include "smb.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
 
-DEFAULT_DEBUG_CHANNEL(file);
+WINE_DEFAULT_DEBUG_CHANNEL(file);
 
 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
 #define MAP_ANON MAP_ANONYMOUS
@@ -55,8 +82,87 @@ DEFAULT_DEBUG_CHANNEL(file);
 /* Size of per-process table of DOS handles */
 #define DOS_TABLE_SIZE 256
 
+/* Macro to derive file offset from OVERLAPPED struct */
+#define OVERLAPPED_OFFSET(overlapped) ((off_t) (overlapped)->Offset + ((off_t) (overlapped)->OffsetHigh << 32))
+
 static HANDLE dos_handles[DOS_TABLE_SIZE];
 
+mode_t FILE_umask;
+
+extern HANDLE WINAPI FILE_SmbOpen(LPCSTR name);
+
+/***********************************************************************
+ *                  Asynchronous file I/O                              *
+ */
+static DWORD fileio_get_async_status (const async_private *ovp);
+static DWORD fileio_get_async_count (const async_private *ovp);
+static void fileio_set_async_status (async_private *ovp, const DWORD status);
+static void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+static void fileio_async_cleanup (async_private *ovp);
+
+static async_ops fileio_async_ops =
+{
+    fileio_get_async_status,       /* get_status */
+    fileio_set_async_status,       /* set_status */
+    fileio_get_async_count,        /* get_count */
+    fileio_call_completion_func,   /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+static async_ops fileio_nocomp_async_ops =
+{
+    fileio_get_async_status,       /* get_status */
+    fileio_set_async_status,       /* set_status */
+    fileio_get_async_count,        /* get_count */
+    NULL,                          /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+typedef struct async_fileio
+{
+    struct async_private             async;
+    LPOVERLAPPED                     lpOverlapped;
+    LPOVERLAPPED_COMPLETION_ROUTINE  completion_func;
+    char                             *buffer;
+    unsigned int                     count;
+    enum fd_type                     fd_type;
+} async_fileio;
+
+static DWORD fileio_get_async_status (const struct async_private *ovp)
+{
+    return ((async_fileio*) ovp)->lpOverlapped->Internal;
+}
+
+static void fileio_set_async_status (async_private *ovp, const DWORD status)
+{
+    ((async_fileio*) ovp)->lpOverlapped->Internal = status;
+}
+
+static DWORD fileio_get_async_count (const struct async_private *ovp)
+{
+    async_fileio *fileio = (async_fileio*) ovp;
+
+    if (fileio->count < fileio->lpOverlapped->InternalHigh)
+       return 0;
+    return fileio->count - fileio->lpOverlapped->InternalHigh;
+}
+
+static void CALLBACK fileio_call_completion_func (ULONG_PTR data)
+{
+    async_fileio *ovp = (async_fileio*) data;
+    TRACE ("data: %p\n", ovp);
+
+    ovp->completion_func( ovp->lpOverlapped->Internal,
+                          ovp->lpOverlapped->InternalHigh,
+                          ovp->lpOverlapped );
+
+    fileio_async_cleanup ( &ovp->async );
+}
+
+static void fileio_async_cleanup ( struct async_private *ovp )
+{
+    HeapFree ( GetProcessHeap(), 0, ovp );
+}
 
 /***********************************************************************
  *              FILE_ConvertOFMode
@@ -91,13 +197,10 @@ static void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing )
  */
 int FILE_strcasecmp( const char *str1, const char *str2 )
 {
-    for (;;)
-    {
-        int ret = FILE_toupper(*str1) - FILE_toupper(*str2);
-        if (ret || !*str1) return ret;
-        str1++;
-        str2++;
-    }
+    int ret = 0;
+    for ( ; ; str1++, str2++)
+        if ((ret = FILE_toupper(*str1) - FILE_toupper(*str2)) || !*str1) break;
+    return ret;
 }
 
 
@@ -115,6 +218,42 @@ int FILE_strncasecmp( const char *str1, const char *str2, int len )
 }
 
 
+/***********************************************************************
+ *           FILE_GetNtStatus(void)
+ *
+ * Retrieve the Nt Status code from errno.
+ * Try to be consistent with FILE_SetDosError().
+ */
+DWORD FILE_GetNtStatus(void)
+{
+    int err = errno;
+    DWORD nt;
+    TRACE ( "errno = %d\n", errno );
+    switch ( err )
+    {
+    case EAGAIN:       nt = STATUS_SHARING_VIOLATION;       break;
+    case EBADF:        nt = STATUS_INVALID_HANDLE;          break;
+    case ENOSPC:       nt = STATUS_DISK_FULL;               break;
+    case EPERM:
+    case EROFS:
+    case EACCES:       nt = STATUS_ACCESS_DENIED;           break;
+    case ENOENT:       nt = STATUS_SHARING_VIOLATION;       break;
+    case EISDIR:       nt = STATUS_FILE_IS_A_DIRECTORY;     break;
+    case EMFILE:
+    case ENFILE:       nt = STATUS_NO_MORE_FILES;           break;
+    case EINVAL:
+    case ENOTEMPTY:    nt = STATUS_DIRECTORY_NOT_EMPTY;     break;
+    case EPIPE:        nt = STATUS_PIPE_BROKEN;             break;
+    case ENOEXEC:      /* ?? */
+    case ESPIPE:       /* ?? */
+    case EEXIST:       /* ?? */
+    default:
+        FIXME ( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
+        nt = STATUS_UNSUCCESSFUL;
+    }
+    return nt;
+}
+
 /***********************************************************************
  *           FILE_SetDosError
  *
@@ -177,29 +316,28 @@ void FILE_SetDosError(void)
 
 
 /***********************************************************************
- *           FILE_DupUnixHandle
+ *           FILE_GetUnixHandleType
  *
- * Duplicate a Unix handle into a task handle.
- * Returns 0 on failure.
+ * Retrieve the Unix handle corresponding to a file handle.
+ * Returns -1 on failure.
  */
-HANDLE FILE_DupUnixHandle( int fd, DWORD access )
+static int FILE_GetUnixHandleType( HANDLE handle, DWORD access, enum fd_type *type, int *flags_ptr )
 {
-    HANDLE ret;
-
-    wine_server_send_fd( fd );
+    int ret, flags, fd = -1;
 
-    SERVER_START_REQ( alloc_file_handle )
+    ret = wine_server_handle_to_fd( handle, access, &fd, type, &flags );
+    if (flags_ptr) *flags_ptr = flags;
+    if (ret) SetLastError( RtlNtStatusToDosError(ret) );
+    else if (((access & GENERIC_READ)  && (flags & FD_FLAG_RECV_SHUTDOWN)) ||
+             ((access & GENERIC_WRITE) && (flags & FD_FLAG_SEND_SHUTDOWN)))
     {
-        req->access  = access;
-        req->fd      = fd;
-        SERVER_CALL();
-        ret = req->handle;
+        close (fd);
+        SetLastError ( ERROR_PIPE_NOT_CONNECTED );
+        return -1;
     }
-    SERVER_END_REQ;
-    return ret;
+    return fd;
 }
 
-
 /***********************************************************************
  *           FILE_GetUnixHandle
  *
@@ -208,56 +346,69 @@ HANDLE FILE_DupUnixHandle( int fd, DWORD access )
  */
 int FILE_GetUnixHandle( HANDLE handle, DWORD access )
 {
-    int ret, fd = -1;
-
-    do
-    {
-        SERVER_START_REQ( get_handle_fd )
-        {
-            req->handle = handle;
-            req->access = access;
-            if (!(ret = SERVER_CALL_ERR())) fd = req->fd;
-        }
-        SERVER_END_REQ;
-        if (ret) return -1;
-
-        if (fd == -1)  /* it wasn't in the cache, get it from the server */
-            fd = wine_server_recv_fd( handle );
-
-    } while (fd == -2);  /* -2 means race condition, so restart from scratch */
-
-    if (fd != -1)
-    {
-        if ((fd = dup(fd)) == -1)
-            SetLastError( ERROR_TOO_MANY_OPEN_FILES );
-    }
-    return fd;
+    return FILE_GetUnixHandleType( handle, access, NULL, NULL );
 }
 
-
 /*************************************************************************
  *             FILE_OpenConsole
  *
  * Open a handle to the current process console.
  * Returns 0 on failure.
  */
-static HANDLE FILE_OpenConsole( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES sa )
+static HANDLE FILE_OpenConsole( BOOL output, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa )
 {
     HANDLE ret;
 
     SERVER_START_REQ( open_console )
     {
-        req->output  = output;
+        req->from    = output;
         req->access  = access;
+       req->share   = sharing;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
 }
 
+/* FIXME: those routines defined as pointers are needed, because this file is
+ * currently compiled into NTDLL whereas it belongs to kernel32.
+ * this shall go away once all the DLL separation process is done
+ */
+typedef BOOL    (WINAPI* pRW)(HANDLE, const void*, DWORD, DWORD*, void*);
+
+static  BOOL FILE_ReadConsole(HANDLE hCon, void* buf, DWORD nb, DWORD* nr, void* p)
+{
+    static      HANDLE  hKernel /* = 0 */;
+    static      pRW     pReadConsole  /* = 0 */;
+
+    if ((!hKernel && !(hKernel = LoadLibraryA("kernel32"))) ||
+        (!pReadConsole &&
+         !(pReadConsole = GetProcAddress(hKernel, "ReadConsoleA"))))
+    {
+        *nr = 0;
+        return 0;
+    }
+    return (pReadConsole)(hCon, buf, nb, nr, p);
+}
+
+static  BOOL FILE_WriteConsole(HANDLE hCon, const void* buf, DWORD nb, DWORD* nr, void* p)
+{
+    static      HANDLE  hKernel /* = 0 */;
+    static      pRW     pWriteConsole  /* = 0 */;
+
+    if ((!hKernel && !(hKernel = LoadLibraryA("kernel32"))) ||
+        (!pWriteConsole &&
+         !(pWriteConsole = GetProcAddress(hKernel, "WriteConsoleA"))))
+    {
+        *nr = 0;
+        return 0;
+    }
+    return (pWriteConsole)(hCon, buf, nb, nr, p);
+}
+/* end of FIXME */
 
 /***********************************************************************
  *           FILE_CreateFile
@@ -267,53 +418,58 @@ static HANDLE FILE_OpenConsole( BOOL output, DWORD access, LPSECURITY_ATTRIBUTES
  */
 HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
                         LPSECURITY_ATTRIBUTES sa, DWORD creation,
-                        DWORD attributes, HANDLE template, BOOL fail_read_only )
+                        DWORD attributes, HANDLE template, BOOL fail_read_only,
+                        UINT drive_type )
 {
-    DWORD err;
+    unsigned int err;
     HANDLE ret;
-    size_t len = strlen(filename);
-
-    if (len > REQUEST_MAX_VAR_SIZE)
-    {
-        FIXME("filename '%s' too long\n", filename );
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
 
- restart:
-    SERVER_START_VAR_REQ( create_file, len )
+    for (;;)
     {
-        req->access  = access;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        req->sharing = sharing;
-        req->create  = creation;
-        req->attrs   = attributes;
-        memcpy( server_data_ptr(req), filename, len );
-        SetLastError(0);
-        err = SERVER_CALL();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
+        SERVER_START_REQ( create_file )
+        {
+            req->access     = access;
+            req->inherit    = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+            req->sharing    = sharing;
+            req->create     = creation;
+            req->attrs      = attributes;
+            req->drive_type = drive_type;
+            wine_server_add_data( req, filename, strlen(filename) );
+            SetLastError(0);
+            err = wine_server_call( req );
+            ret = reply->handle;
+        }
+        SERVER_END_REQ;
 
-    /* If write access failed, retry without GENERIC_WRITE */
+        /* If write access failed, retry without GENERIC_WRITE */
 
-    if (!ret && !fail_read_only && (access & GENERIC_WRITE))
-    {
-       if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
+        if (!ret && !fail_read_only && (access & GENERIC_WRITE))
         {
-           TRACE("Write access failed for file '%s', trying without "
-                 "write access\n", filename);
-            access &= ~GENERIC_WRITE;
-            goto restart;
+            if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
+            {
+                TRACE("Write access failed for file '%s', trying without "
+                      "write access\n", filename);
+                access &= ~GENERIC_WRITE;
+                continue;
+            }
         }
-    }
-
-    if (err) SetLastError( RtlNtStatusToDosError(err) );
 
-    if (!ret)
-        WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
+        if (err)
+        {
+            /* In the case file creation was rejected due to CREATE_NEW flag
+             * was specified and file with that name already exists, correct
+             * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
+             * Note: RtlNtStatusToDosError is not the subject to blame here.
+             */
+            if (err == STATUS_OBJECT_NAME_COLLISION)
+                SetLastError( ERROR_FILE_EXISTS );
+            else
+                SetLastError( RtlNtStatusToDosError(err) );
+        }
 
-    return ret;
+        if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
+        return ret;
+    }
 }
 
 
@@ -332,16 +488,38 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         req->id      = client_id;
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
 }
 
+static HANDLE FILE_OpenPipe(LPCWSTR name, DWORD access)
+{
+    HANDLE ret;
+    DWORD len = 0;
+
+    if (name && (len = strlenW(name)) > MAX_PATH)
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return 0;
+    }
+    SERVER_START_REQ( open_named_pipe )
+    {
+        req->access = access;
+        SetLastError(0);
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
+    }
+    SERVER_END_REQ;
+    TRACE("Returned %d\n",ret);
+    return ret;
+}
 
 /*************************************************************************
- * CreateFileA [KERNEL32.45]  Creates or opens a file or other object
+ * CreateFileW [KERNEL32.@]  Creates or opens a file or other object
  *
  * Creates or opens an object, and returns a handle that can be used to
  * access that object.
@@ -365,22 +543,27 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
  *
  * BUGS
  *
- * Doesn't support character devices, pipes, template files, or a
+ * Doesn't support character devices, template files, or a
  * lot of the 'attributes' flags yet.
  */
-HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
+HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
                               LPSECURITY_ATTRIBUTES sa, DWORD creation,
                               DWORD attributes, HANDLE template )
 {
     DOS_FULL_NAME full_name;
     HANDLE ret;
+    static const WCHAR bkslashes_with_question_markW[] = {'\\','\\','?','\\',0};
+    static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0};
+    static const WCHAR bkslashesW[] = {'\\','\\',0};
+    static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
+    static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
 
     if (!filename)
     {
         SetLastError( ERROR_INVALID_PARAMETER );
         return INVALID_HANDLE_VALUE;
     }
-    TRACE("%s %s%s%s%s%s%s%s\n",filename,
+    TRACE("%s %s%s%s%s%s%s%s attributes 0x%lx\n", debugstr_w(filename),
          ((access & GENERIC_READ)==GENERIC_READ)?"GENERIC_READ ":"",
          ((access & GENERIC_WRITE)==GENERIC_WRITE)?"GENERIC_WRITE ":"",
          (!access)?"QUERY_ACCESS ":"",
@@ -391,22 +574,36 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
          (creation ==CREATE_ALWAYS)?"CREATE_ALWAYS ":
          (creation ==OPEN_EXISTING)?"OPEN_EXISTING ":
          (creation ==OPEN_ALWAYS)?"OPEN_ALWAYS ":
-         (creation ==TRUNCATE_EXISTING)?"TRUNCATE_EXISTING ":"");
+         (creation ==TRUNCATE_EXISTING)?"TRUNCATE_EXISTING ":"", attributes);
 
     /* If the name starts with '\\?\', ignore the first 4 chars. */
-    if (!strncmp(filename, "\\\\?\\", 4))
+    if (!strncmpW(filename, bkslashes_with_question_markW, 4))
     {
+        static const WCHAR uncW[] = {'U','N','C','\\',0};
         filename += 4;
-       if (!strncmp(filename, "UNC\\", 4))
+       if (!strncmpiW(filename, uncW, 4))
        {
-            FIXME("UNC name (%s) not supported.\n", filename );
+            FIXME("UNC name (%s) not supported.\n", debugstr_w(filename) );
             SetLastError( ERROR_PATH_NOT_FOUND );
             return INVALID_HANDLE_VALUE;
        }
     }
 
-    if (!strncmp(filename, "\\\\.\\", 4)) {
-        if (!DOSFS_GetDevice( filename ))
+    if (!strncmpW(filename, bkslashes_with_dotW, 4))
+    {
+        static const WCHAR pipeW[] = {'P','I','P','E','\\',0};
+        if(!strncmpiW(filename + 4, pipeW, 5))
+        {
+            TRACE("Opening a pipe: %s\n", debugstr_w(filename));
+            ret = FILE_OpenPipe(filename,access);
+            goto done;
+        }
+        else if (isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0')
+        {
+            ret = FILE_CreateDevice( (toupperW(filename[4]) - 'A') | 0x20000, access, sa );
+            goto done;
+        }
+        else if (!DOSFS_GetDevice( filename ))
         {
             ret = DEVICE_Open( filename+4, access, sa );
             goto done;
@@ -416,37 +613,36 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
     }
 
     /* If the name still starts with '\\', it's a UNC name. */
-    if (!strncmp(filename, "\\\\", 2))
+    if (!strncmpW(filename, bkslashesW, 2))
     {
-        FIXME("UNC name (%s) not supported.\n", filename );
-        SetLastError( ERROR_PATH_NOT_FOUND );
-        return INVALID_HANDLE_VALUE;
+        ret = SMB_CreateFileW(filename, access, sharing, sa, creation, attributes, template );
+        goto done;
     }
 
     /* If the name contains a DOS wild card (* or ?), do no create a file */
-    if(strchr(filename,'*') || strchr(filename,'?'))
+    if(strchrW(filename, '*') || strchrW(filename, '?'))
         return INVALID_HANDLE_VALUE;
 
     /* Open a console for CONIN$ or CONOUT$ */
-    if (!strcasecmp(filename, "CONIN$"))
+    if (!strcmpiW(filename, coninW))
     {
-        ret = FILE_OpenConsole( FALSE, access, sa );
+        ret = FILE_OpenConsole( FALSE, access, sharing, sa );
         goto done;
     }
-    if (!strcasecmp(filename, "CONOUT$"))
+    if (!strcmpiW(filename, conoutW))
     {
-        ret = FILE_OpenConsole( TRUE, access, sa );
+        ret = FILE_OpenConsole( TRUE, access, sharing, sa );
         goto done;
     }
 
     if (DOSFS_GetDevice( filename ))
     {
-        TRACE("opening device '%s'\n", filename );
+        TRACE("opening device %s\n", debugstr_w(filename) );
 
-        if (!(ret = DOSFS_OpenDevice( filename, access )))
+        if (!(ret = DOSFS_OpenDevice( filename, access, attributes, sa )))
         {
             /* Do not silence this please. It is a critical error. -MM */
-            ERR("Couldn't open device '%s'!\n",filename);
+            ERR("Couldn't open device %s!\n", debugstr_w(filename));
             SetLastError( ERROR_FILE_NOT_FOUND );
         }
         goto done;
@@ -457,32 +653,48 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
                            (creation == OPEN_EXISTING) ||
                            (creation == TRUNCATE_EXISTING),
                            &full_name )) {
-       WARN("Unable to get full filename from '%s' (GLE %ld)\n",
-            filename, GetLastError());
+       WARN("Unable to get full filename from %s (GLE %ld)\n",
+            debugstr_w(filename), GetLastError());
         return INVALID_HANDLE_VALUE;
     }
 
     ret = FILE_CreateFile( full_name.long_name, access, sharing,
                            sa, creation, attributes, template,
-                           DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
+                           DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY,
+                           GetDriveTypeW( full_name.short_name ) );
  done:
     if (!ret) ret = INVALID_HANDLE_VALUE;
+    TRACE("returning %08x\n", ret);
     return ret;
 }
 
 
 
 /*************************************************************************
- *              CreateFileW              (KERNEL32.48)
+ *              CreateFileA              (KERNEL32.@)
  */
-HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
+HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
                               LPSECURITY_ATTRIBUTES sa, DWORD creation,
                               DWORD attributes, HANDLE template)
 {
-    LPSTR afn = HEAP_strdupWtoA( GetProcessHeap(), 0, filename );
-    HANDLE res = CreateFileA( afn, access, sharing, sa, creation, attributes, template );
-    HeapFree( GetProcessHeap(), 0, afn );
-    return res;
+    UNICODE_STRING filenameW;
+    HANDLE ret = INVALID_HANDLE_VALUE;
+
+    if (!filename)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return INVALID_HANDLE_VALUE;
+    }
+
+    if (RtlCreateUnicodeStringFromAsciiz(&filenameW, filename))
+    {
+        ret = CreateFileW(filenameW.Buffer, access, sharing, sa, creation,
+                          attributes, template);
+        RtlFreeUnicodeString(&filenameW);
+    }
+    else
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return ret;
 }
 
 
@@ -500,13 +712,17 @@ static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
     if (!(st->st_mode & S_IWUSR))
         info->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
 
-    RtlSecondsSince1970ToTime( st->st_mtime, &info->ftCreationTime );
-    RtlSecondsSince1970ToTime( st->st_mtime, &info->ftLastWriteTime );
-    RtlSecondsSince1970ToTime( st->st_atime, &info->ftLastAccessTime );
+    RtlSecondsSince1970ToTime( st->st_mtime, (LARGE_INTEGER *)&info->ftCreationTime );
+    RtlSecondsSince1970ToTime( st->st_mtime, (LARGE_INTEGER *)&info->ftLastWriteTime );
+    RtlSecondsSince1970ToTime( st->st_atime, (LARGE_INTEGER *)&info->ftLastAccessTime );
 
     info->dwVolumeSerialNumber = 0;  /* FIXME */
     info->nFileSizeHigh = 0;
-    info->nFileSizeLow  = S_ISDIR(st->st_mode) ? 0 : st->st_size;
+    info->nFileSizeLow  = 0;
+    if (!S_ISDIR(st->st_mode)) {
+       info->nFileSizeHigh = st->st_size >> 32;
+       info->nFileSizeLow  = st->st_size & 0xffffffff;
+    }
     info->nNumberOfLinks = st->st_nlink;
     info->nFileIndexHigh = 0;
     info->nFileIndexLow  = st->st_ino;
@@ -521,14 +737,16 @@ static void FILE_FillInfo( struct stat *st, BY_HANDLE_FILE_INFORMATION *info )
 BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
 {
     struct stat st;
+    int is_symlink;
+    LPCSTR p;
 
     if (lstat( unixName, &st ) == -1)
     {
         FILE_SetDosError();
         return FALSE;
     }
-    if (!S_ISLNK(st.st_mode)) FILE_FillInfo( &st, info );
-    else
+    is_symlink = S_ISLNK(st.st_mode);
+    if (is_symlink)
     {
         /* do a "real" stat to find out
           about the type of the symlink destination */
@@ -537,15 +755,32 @@ BOOL FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info )
             FILE_SetDosError();
             return FALSE;
         }
-        FILE_FillInfo( &st, info );
-        info->dwFileAttributes |= FILE_ATTRIBUTE_SYMLINK;
     }
+    
+    /* fill in the information we gathered so far */
+    FILE_FillInfo( &st, info );
+    if (is_symlink) info->dwFileAttributes |= FILE_ATTRIBUTE_SYMLINK;
+    
+    /* and now see if this is a hidden file, based on the name */
+    p = strrchr( unixName, '/');
+    p = p ? p + 1 : unixName;
+    if (*p == '.' && *(p+1)  && (*(p+1) != '.' || *(p+2)))
+    {
+       static const WCHAR wineW[] = {'w','i','n','e',0};
+       static const WCHAR ShowDotFilesW[] = {'S','h','o','w','D','o','t','F','i','l','e','s',0};
+       static int show_dot_files = -1;
+       if (show_dot_files == -1)
+           show_dot_files = PROFILE_GetWineIniBool(wineW, ShowDotFilesW, 0);
+       if (!show_dot_files)
+           info->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+    }
+    
     return TRUE;
 }
 
 
 /***********************************************************************
- *             GetFileInformationByHandle   (KERNEL32.219)
+ *             GetFileInformationByHandle   (KERNEL32.@)
  */
 DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
                                          BY_HANDLE_FILE_INFORMATION *info )
@@ -553,35 +788,36 @@ DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
     DWORD ret;
     if (!info) return 0;
 
+    TRACE("%08x\n", hFile);
+
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-           /* FIXME: which file types are supported ?
-            * Serial ports (FILE_TYPE_CHAR) are not,
-            * and MSDN also says that pipes are not supported.
-            * FILE_TYPE_REMOTE seems to be supported according to
-            * MSDN q234741.txt */
-           if ((req->type == FILE_TYPE_DISK)
-           ||  (req->type == FILE_TYPE_REMOTE))
-           {
-                RtlSecondsSince1970ToTime( req->write_time, &info->ftCreationTime );
-                RtlSecondsSince1970ToTime( req->write_time, &info->ftLastWriteTime );
-                RtlSecondsSince1970ToTime( req->access_time, &info->ftLastAccessTime );
-                info->dwFileAttributes     = req->attr;
-                info->dwVolumeSerialNumber = req->serial;
-                info->nFileSizeHigh        = req->size_high;
-                info->nFileSizeLow         = req->size_low;
-                info->nNumberOfLinks       = req->links;
-                info->nFileIndexHigh       = req->index_high;
-                info->nFileIndexLow        = req->index_low;
-           }
-           else
-           {
-               SetLastError(ERROR_NOT_SUPPORTED);
-               ret = 0;
-           }
+            /* FIXME: which file types are supported ?
+             * Serial ports (FILE_TYPE_CHAR) are not,
+             * and MSDN also says that pipes are not supported.
+             * FILE_TYPE_REMOTE seems to be supported according to
+             * MSDN q234741.txt */
+            if ((reply->type == FILE_TYPE_DISK) ||  (reply->type == FILE_TYPE_REMOTE))
+            {
+                RtlSecondsSince1970ToTime( reply->write_time, (LARGE_INTEGER *)&info->ftCreationTime );
+                RtlSecondsSince1970ToTime( reply->write_time, (LARGE_INTEGER *)&info->ftLastWriteTime );
+                RtlSecondsSince1970ToTime( reply->access_time, (LARGE_INTEGER *)&info->ftLastAccessTime );
+                info->dwFileAttributes     = reply->attr;
+                info->dwVolumeSerialNumber = reply->serial;
+                info->nFileSizeHigh        = reply->size_high;
+                info->nFileSizeLow         = reply->size_low;
+                info->nNumberOfLinks       = reply->links;
+                info->nFileIndexHigh       = reply->index_high;
+                info->nFileIndexLow        = reply->index_low;
+            }
+            else
+            {
+                SetLastError(ERROR_NOT_SUPPORTED);
+                ret = 0;
+            }
         }
     }
     SERVER_END_REQ;
@@ -590,7 +826,7 @@ DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
 
 
 /**************************************************************************
- *           GetFileAttributes16   (KERNEL.420)
+ *           GetFileAttributes   (KERNEL.420)
  */
 DWORD WINAPI GetFileAttributes16( LPCSTR name )
 {
@@ -599,9 +835,9 @@ DWORD WINAPI GetFileAttributes16( LPCSTR name )
 
 
 /**************************************************************************
- *           GetFileAttributesA   (KERNEL32.217)
+ *           GetFileAttributesW   (KERNEL32.@)
  */
-DWORD WINAPI GetFileAttributesA( LPCSTR name )
+DWORD WINAPI GetFileAttributesW( LPCWSTR name )
 {
     DOS_FULL_NAME full_name;
     BY_HANDLE_FILE_INFORMATION info;
@@ -619,19 +855,139 @@ DWORD WINAPI GetFileAttributesA( LPCSTR name )
 
 
 /**************************************************************************
- *           GetFileAttributesW   (KERNEL32.218)
+ *           GetFileAttributesA   (KERNEL32.@)
  */
-DWORD WINAPI GetFileAttributesW( LPCWSTR name )
+DWORD WINAPI GetFileAttributesA( LPCSTR name )
+{
+    UNICODE_STRING nameW;
+    DWORD ret = (DWORD)-1;
+
+    if (!name)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return (DWORD)-1;
+    }
+
+    if (RtlCreateUnicodeStringFromAsciiz(&nameW, name))
+    {
+        ret = GetFileAttributesW(nameW.Buffer);
+        RtlFreeUnicodeString(&nameW);
+    }
+    else
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return ret;
+}
+
+
+/**************************************************************************
+ *              SetFileAttributes      (KERNEL.421)
+ */
+BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes )
 {
-    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
-    DWORD res = GetFileAttributesA( nameA );
-    HeapFree( GetProcessHeap(), 0, nameA );
-    return res;
+    return SetFileAttributesA( lpFileName, attributes );
+}
+
+
+/**************************************************************************
+ *              SetFileAttributesW     (KERNEL32.@)
+ */
+BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD attributes)
+{
+    struct stat buf;
+    DOS_FULL_NAME full_name;
+
+    if (!lpFileName)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    TRACE("(%s,%lx)\n", debugstr_w(lpFileName), attributes);
+
+    if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name ))
+        return FALSE;
+
+    if(stat(full_name.long_name,&buf)==-1)
+    {
+        FILE_SetDosError();
+        return FALSE;
+    }
+    if (attributes & FILE_ATTRIBUTE_READONLY)
+    {
+        if(S_ISDIR(buf.st_mode))
+            /* FIXME */
+            WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
+        else
+            buf.st_mode &= ~0222; /* octal!, clear write permission bits */
+        attributes &= ~FILE_ATTRIBUTE_READONLY;
+    }
+    else
+    {
+        /* add write permission */
+        buf.st_mode |= (0600 | ((buf.st_mode & 044) >> 1)) & (~FILE_umask);
+    }
+    if (attributes & FILE_ATTRIBUTE_DIRECTORY)
+    {
+        if (!S_ISDIR(buf.st_mode))
+            FIXME("SetFileAttributes expected the file %s to be a directory\n",
+                  debugstr_w(lpFileName));
+        attributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+    }
+    attributes &= ~(FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
+    if (attributes)
+        FIXME("(%s):%lx attribute(s) not implemented.\n", debugstr_w(lpFileName), attributes);
+    if (-1==chmod(full_name.long_name,buf.st_mode))
+    {
+        if (GetDriveTypeW(lpFileName) == DRIVE_CDROM)
+        {
+           SetLastError( ERROR_ACCESS_DENIED );
+           return FALSE;
+        }
+
+        /*
+        * FIXME: We don't return FALSE here because of differences between
+        *        Linux and Windows privileges. Under Linux only the owner of
+        *        the file is allowed to change file attributes. Under Windows,
+        *        applications expect that if you can write to a file, you can also
+        *        change its attributes (see GENERIC_WRITE). We could try to be
+        *        clever here but that would break multi-user installations where
+        *        users share read-only DLLs. This is because some installers like
+        *        to change attributes of already installed DLLs.
+        */
+        FIXME("Couldn't set file attributes for existing file \"%s\".\n"
+              "Check permissions or set VFAT \"quiet\" mount flag\n", full_name.long_name);
+    }
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *              SetFileAttributesA     (KERNEL32.@)
+ */
+BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD attributes)
+{
+    UNICODE_STRING filenameW;
+    BOOL ret = FALSE;
+
+    if (!lpFileName)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    if (RtlCreateUnicodeStringFromAsciiz(&filenameW, lpFileName))
+    {
+        ret = SetFileAttributesW(filenameW.Buffer, attributes);
+        RtlFreeUnicodeString(&filenameW);
+    }
+    else
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return ret;
 }
 
 
 /***********************************************************************
- *           GetFileSize   (KERNEL32.220)
+ *           GetFileSize   (KERNEL32.@)
  */
 DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD filesizehigh )
 {
@@ -643,7 +999,7 @@ DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD filesizehigh )
 
 
 /***********************************************************************
- *           GetFileTime   (KERNEL32.221)
+ *           GetFileTime   (KERNEL32.@)
  */
 BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime,
                            FILETIME *lpLastAccessTime,
@@ -658,7 +1014,7 @@ BOOL WINAPI GetFileTime( HANDLE hFile, FILETIME *lpCreationTime,
 }
 
 /***********************************************************************
- *           CompareFileTime   (KERNEL32.28)
+ *           CompareFileTime   (KERNEL32.@)
  */
 INT WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
 {
@@ -678,30 +1034,36 @@ INT WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
 /***********************************************************************
  *           FILE_GetTempFileName : utility for GetTempFileName
  */
-static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
-                                  LPSTR buffer, BOOL isWin16 )
+static UINT FILE_GetTempFileName( LPCWSTR path, LPCWSTR prefix, UINT unique,
+                                  LPWSTR buffer )
 {
     static UINT unique_temp;
     DOS_FULL_NAME full_name;
     int i;
-    LPSTR p;
+    LPWSTR p;
     UINT num;
+    char buf[20];
 
-    if ( !path || !prefix || !buffer ) return 0;
+    if ( !path || !prefix || !buffer )
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
 
     if (!unique_temp) unique_temp = time(NULL) & 0xffff;
     num = unique ? (unique & 0xffff) : (unique_temp++ & 0xffff);
 
-    strcpy( buffer, path );
-    p = buffer + strlen(buffer);
+    strcpyW( buffer, path );
+    p = buffer + strlenW(buffer);
 
     /* add a \, if there isn't one and path is more than just the drive letter ... */
-    if ( !((strlen(buffer) == 2) && (buffer[1] == ':')) 
+    if ( !((strlenW(buffer) == 2) && (buffer[1] == ':'))
        && ((p == buffer) || (p[-1] != '\\'))) *p++ = '\\';
 
-    if (isWin16) *p++ = '~';
     for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
-    sprintf( p, "%04x.tmp", num );
+
+    sprintf( buf, "%04x.tmp", num );
+    MultiByteToWideChar(CP_ACP, 0, buf, -1, p, 20);
 
     /* Now try to create it */
 
@@ -709,19 +1071,19 @@ static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
     {
         do
         {
-            HFILE handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
-                                            CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
+            HANDLE handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
+                                         CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
             if (handle != INVALID_HANDLE_VALUE)
             {  /* We created it */
-                TRACE("created %s\n",
-                             buffer);
+                TRACE("created %s\n", debugstr_w(buffer) );
                 CloseHandle( handle );
                 break;
             }
             if (GetLastError() != ERROR_FILE_EXISTS)
                 break;  /* No need to go on */
             num++;
-            sprintf( p, "%04x.tmp", num );
+            sprintf( buf, "%04x.tmp", num );
+            MultiByteToWideChar(CP_ACP, 0, buf, -1, p, 20);
         } while (num != (unique & 0xffff));
     }
 
@@ -729,54 +1091,65 @@ static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
 
     if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
     {
+        char *slash;
         /* Check if we have write access in the directory */
-        if ((p = strrchr( full_name.long_name, '/' ))) *p = '\0';
+        if ((slash = strrchr( full_name.long_name, '/' ))) *slash = '\0';
         if (access( full_name.long_name, W_OK ) == -1)
-            WARN("returns '%s', which doesn't seem to be writeable.\n",
-                buffer);
+            WARN("returns %s, which doesn't seem to be writeable.\n",
+                  debugstr_w(buffer) );
     }
-    TRACE("returning %s\n", buffer );
+    TRACE("returning %s\n", debugstr_w(buffer) );
     return unique ? unique : num;
 }
 
 
 /***********************************************************************
- *           GetTempFileNameA   (KERNEL32.290)
+ *           GetTempFileNameA   (KERNEL32.@)
  */
 UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique,
                                   LPSTR buffer)
 {
-    return FILE_GetTempFileName(path, prefix, unique, buffer, FALSE);
+    UNICODE_STRING pathW, prefixW;
+    WCHAR bufferW[MAX_PATH];
+    UINT ret;
+
+    if ( !path || !prefix || !buffer )
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+
+    RtlCreateUnicodeStringFromAsciiz(&pathW, path);
+    RtlCreateUnicodeStringFromAsciiz(&prefixW, prefix);
+
+    ret = GetTempFileNameW(pathW.Buffer, prefixW.Buffer, unique, bufferW);
+    if (ret)
+        WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL);
+
+    RtlFreeUnicodeString(&pathW);
+    RtlFreeUnicodeString(&prefixW);
+    return ret;
 }
 
 /***********************************************************************
- *           GetTempFileNameW   (KERNEL32.291)
+ *           GetTempFileNameW   (KERNEL32.@)
  */
 UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique,
                                   LPWSTR buffer )
 {
-    LPSTR   patha,prefixa;
-    char    buffera[144];
-    UINT  ret;
-
-    if (!path) return 0;
-    patha   = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
-    prefixa = HEAP_strdupWtoA( GetProcessHeap(), 0, prefix );
-    ret     = FILE_GetTempFileName( patha, prefixa, unique, buffera, FALSE );
-    MultiByteToWideChar( CP_ACP, 0, buffera, -1, buffer, MAX_PATH );
-    HeapFree( GetProcessHeap(), 0, patha );
-    HeapFree( GetProcessHeap(), 0, prefixa );
-    return ret;
+    return FILE_GetTempFileName( path, prefix, unique, buffer );
 }
 
 
 /***********************************************************************
- *           GetTempFileName16   (KERNEL.97)
+ *           GetTempFileName   (KERNEL.97)
  */
 UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
                                  LPSTR buffer )
 {
-    char temppath[144];
+    char temppath[MAX_PATH];
+    char *prefix16 = NULL;
+    UINT16 ret;
 
     if (!(drive & ~TF_FORCEDRIVE)) /* drive 0 means current default drive */
         drive |= DRIVE_GetCurrentDrive() + 'A';
@@ -791,8 +1164,19 @@ UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
     if (drive & TF_FORCEDRIVE)
         sprintf(temppath,"%c:", drive & ~TF_FORCEDRIVE );
     else
-        GetTempPathA( 132, temppath );
-    return (UINT16)FILE_GetTempFileName( temppath, prefix, unique, buffer, TRUE );
+        GetTempPathA( MAX_PATH, temppath );
+
+    if (prefix)
+    {
+        prefix16 = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + 2);
+        *prefix16 = '~';
+        strcpy(prefix16 + 1, prefix);
+    }
+
+    ret = GetTempFileNameA( temppath, prefix16, unique, buffer );
+
+    if (prefix16) HeapFree(GetProcessHeap(), 0, prefix16);
+    return ret;
 }
 
 /***********************************************************************
@@ -804,14 +1188,17 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
                                 BOOL win32 )
 {
     HFILE hFileRet;
+    HANDLE handle;
     FILETIME filetime;
     WORD filedatetime[2];
     DOS_FULL_NAME full_name;
     DWORD access, sharing;
-    char *p;
+    WCHAR *p;
+    WCHAR buffer[MAX_PATH];
+    LPWSTR nameW;
 
     if (!ofs) return HFILE_ERROR;
-    
+
     TRACE("%s %s %s %s%s%s%s%s%s%s%s%s\n",name,
          ((mode & 0x3 )==OF_READ)?"OF_READ":
          ((mode & 0x3 )==OF_WRITE)?"OF_WRITE":
@@ -831,7 +1218,7 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
          ((mode & OF_EXIST )==OF_EXIST)?"OF_EXIST ":"",
          ((mode & OF_REOPEN )==OF_REOPEN)?"OF_REOPEN ":""
          );
-      
+
 
     ofs->cBytes = sizeof(OFSTRUCT);
     ofs->nErrCode = 0;
@@ -845,7 +1232,7 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
     TRACE("%s %04x\n", name, mode );
 
     /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName
-       Are there any cases where getting the path here is wrong? 
+       Are there any cases where getting the path here is wrong?
        Uwe Bonnes 1997 Apr 2 */
     if (!GetFullPathNameA( name, sizeof(ofs->szPathName),
                             ofs->szPathName, NULL )) goto error;
@@ -867,38 +1254,41 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
 
     if (mode & OF_CREATE)
     {
-        if ((hFileRet = CreateFileA( name, GENERIC_READ | GENERIC_WRITE,
-                                       sharing, NULL, CREATE_ALWAYS,
-                                       FILE_ATTRIBUTE_NORMAL, 0 ))== INVALID_HANDLE_VALUE)
+        if ((handle = CreateFileA( name, GENERIC_READ | GENERIC_WRITE,
+                                   sharing, NULL, CREATE_ALWAYS,
+                                   FILE_ATTRIBUTE_NORMAL, 0 ))== INVALID_HANDLE_VALUE)
             goto error;
         goto success;
     }
 
+    MultiByteToWideChar(CP_ACP, 0, name, -1, buffer, MAX_PATH);
+    nameW = buffer;
+
     /* If OF_SEARCH is set, ignore the given path */
 
     if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
     {
         /* First try the file name as is */
-        if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
+        if (DOSFS_GetFullName( nameW, TRUE, &full_name )) goto found;
         /* Now remove the path */
-        if (name[0] && (name[1] == ':')) name += 2;
-        if ((p = strrchr( name, '\\' ))) name = p + 1;
-        if ((p = strrchr( name, '/' ))) name = p + 1;
-        if (!name[0]) goto not_found;
+        if (nameW[0] && (nameW[1] == ':')) nameW += 2;
+        if ((p = strrchrW( nameW, '\\' ))) nameW = p + 1;
+        if ((p = strrchrW( nameW, '/' ))) nameW = p + 1;
+        if (!nameW[0]) goto not_found;
     }
 
     /* Now look for the file */
 
-    if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
+    if (!DIR_SearchPath( NULL, nameW, NULL, &full_name, win32 )) goto not_found;
 
 found:
     TRACE("found %s = %s\n",
-                  full_name.long_name, full_name.short_name );
-    lstrcpynA( ofs->szPathName, full_name.short_name,
-                 sizeof(ofs->szPathName) );
+          full_name.long_name, debugstr_w(full_name.short_name) );
+    WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1,
+                        ofs->szPathName, sizeof(ofs->szPathName), NULL, NULL);
 
     if (mode & OF_SHARE_EXCLUSIVE)
-      /* Some InstallShield version uses OF_SHARE_EXCLUSIVE 
+      /* Some InstallShield version uses OF_SHARE_EXCLUSIVE
         on the file <tempdir>/_ins0432._mp to determine how
         far installation has proceeded.
         _ins0432._mp is an executable and while running the
@@ -926,18 +1316,19 @@ found:
         return 1;
     }
 
-    hFileRet = FILE_CreateFile( full_name.long_name, access, sharing,
+    handle = FILE_CreateFile( full_name.long_name, access, sharing,
                                 NULL, OPEN_EXISTING, 0, 0,
-                                DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY );
-    if (!hFileRet) goto not_found;
+                                DRIVE_GetFlags(full_name.drive) & DRIVE_FAIL_READ_ONLY,
+                                GetDriveTypeW( full_name.short_name ) );
+    if (!handle) goto not_found;
 
-    GetFileTime( hFileRet, NULL, NULL, &filetime );
+    GetFileTime( handle, NULL, NULL, &filetime );
     FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
     if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
     {
         if (memcmp( ofs->reserved, filedatetime, sizeof(ofs->reserved) ))
         {
-            CloseHandle( hFileRet );
+            CloseHandle( handle );
             WARN("(%s): OF_VERIFY failed\n", name );
             /* FIXME: what error here? */
             SetLastError( ERROR_FILE_NOT_FOUND );
@@ -947,15 +1338,16 @@ found:
     memcpy( ofs->reserved, filedatetime, sizeof(ofs->reserved) );
 
 success:  /* We get here if the open was successful */
-    TRACE("(%s): OK, return = %d\n", name, hFileRet );
+    TRACE("(%s): OK, return = %x\n", name, handle );
     if (win32)
     {
+        hFileRet = (HFILE)handle;
         if (mode & OF_EXIST) /* Return the handle, but close it first */
-            CloseHandle( hFileRet );
+            CloseHandle( handle );
     }
     else
     {
-        hFileRet = Win32HandleToDosFileHandle( hFileRet );
+        hFileRet = Win32HandleToDosFileHandle( handle );
         if (hFileRet == HFILE_ERROR16) goto error;
         if (mode & OF_EXIST) /* Return the handle, but close it first */
             _lclose16( hFileRet );
@@ -969,14 +1361,15 @@ not_found:  /* We get here if the file does not exist */
 
 error:  /* We get here if there was an error opening the file */
     ofs->nErrCode = GetLastError();
-    WARN("(%s): return = HFILE_ERROR error= %d\n", 
+    WARN("(%s): return = HFILE_ERROR error= %d\n",
                  name,ofs->nErrCode );
     return HFILE_ERROR;
 }
 
 
 /***********************************************************************
- *           OpenFile16   (KERNEL.74)
+ *           OpenFile   (KERNEL.74)
+ *           OpenFileEx (KERNEL.360)
  */
 HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
 {
@@ -985,7 +1378,7 @@ HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode )
 
 
 /***********************************************************************
- *           OpenFile   (KERNEL32.396)
+ *           OpenFile   (KERNEL32.@)
  */
 HFILE WINAPI OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
 {
@@ -1001,11 +1394,17 @@ HFILE WINAPI OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode )
  */
 static void FILE_InitProcessDosHandles( void )
 {
-    dos_handles[0] = GetStdHandle(STD_INPUT_HANDLE);
-    dos_handles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
-    dos_handles[2] = GetStdHandle(STD_ERROR_HANDLE);
-    dos_handles[3] = GetStdHandle(STD_ERROR_HANDLE);
-    dos_handles[4] = GetStdHandle(STD_ERROR_HANDLE);
+    HANDLE cp = GetCurrentProcess();
+    DuplicateHandle(cp, GetStdHandle(STD_INPUT_HANDLE), cp, &dos_handles[0],
+                    0, TRUE, DUPLICATE_SAME_ACCESS);
+    DuplicateHandle(cp, GetStdHandle(STD_OUTPUT_HANDLE), cp, &dos_handles[1],
+                    0, TRUE, DUPLICATE_SAME_ACCESS);
+    DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[2],
+                    0, TRUE, DUPLICATE_SAME_ACCESS);
+    DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[3],
+                    0, TRUE, DUPLICATE_SAME_ACCESS);
+    DuplicateHandle(cp, GetStdHandle(STD_ERROR_HANDLE), cp, &dos_handles[4],
+                    0, TRUE, DUPLICATE_SAME_ACCESS);
 }
 
 /***********************************************************************
@@ -1100,12 +1499,6 @@ HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 )
         SetLastError( ERROR_INVALID_HANDLE );
         return HFILE_ERROR16;
     }
-    if (hFile2 < 5)
-    {
-        FIXME("stdio handle closed, need proper conversion\n" );
-        SetLastError( ERROR_INVALID_HANDLE );
-        return HFILE_ERROR16;
-    }
     if (!DuplicateHandle( GetCurrentProcess(), dos_handles[hFile1],
                           GetCurrentProcess(), &new_handle,
                           0, FALSE, DUPLICATE_SAME_ACCESS ))
@@ -1117,16 +1510,10 @@ HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 )
 
 
 /***********************************************************************
- *           _lclose16   (KERNEL.81)
+ *           _lclose   (KERNEL.81)
  */
 HFILE16 WINAPI _lclose16( HFILE16 hFile )
 {
-    if (hFile < 5)
-    {
-        FIXME("stdio handle closed, need proper conversion\n" );
-        SetLastError( ERROR_INVALID_HANDLE );
-        return HFILE_ERROR16;
-    }
     if ((hFile >= DOS_TABLE_SIZE) || !dos_handles[hFile])
     {
         SetLastError( ERROR_INVALID_HANDLE );
@@ -1140,16 +1527,16 @@ HFILE16 WINAPI _lclose16( HFILE16 hFile )
 
 
 /***********************************************************************
- *           _lclose   (KERNEL32.592)
+ *           _lclose   (KERNEL32.@)
  */
 HFILE WINAPI _lclose( HFILE hFile )
 {
     TRACE("handle %d\n", hFile );
-    return CloseHandle( hFile ) ? 0 : HFILE_ERROR;
+    return CloseHandle( (HANDLE)hFile ) ? 0 : HFILE_ERROR;
 }
 
 /***********************************************************************
- *              GetOverlappedResult     (KERNEL32.360)
+ *              GetOverlappedResult     (KERNEL32.@)
  *
  * Check the result of an Asynchronous data transfer from a file.
  *
@@ -1157,19 +1544,19 @@ HFILE WINAPI _lclose( HFILE hFile )
  *   TRUE on success
  *   FALSE on failure
  *
- *  If successful (and relevant) lpTransfered will hold the number of
- *   bytes transfered during the async operation.
+ *  If successful (and relevant) lpTransferred will hold the number of
+ *   bytes transferred during the async operation.
  *
  * BUGS
  *
- * Currently only works for WaitCommEvent, ReadFile, WriteFile 
+ * Currently only works for WaitCommEvent, ReadFile, WriteFile
  *   with communications ports.
  *
  */
 BOOL WINAPI GetOverlappedResult(
     HANDLE hFile,              /* [in] handle of file to check on */
     LPOVERLAPPED lpOverlapped, /* [in/out] pointer to overlapped  */
-    LPDWORD lpTransferred,     /* [in/out] number of bytes transfered  */
+    LPDWORD lpTransferred,     /* [in/out] number of bytes transferred  */
     BOOL bWait                 /* [in] wait for the transfer to complete ? */
 ) {
     DWORD r;
@@ -1187,20 +1574,63 @@ BOOL WINAPI GetOverlappedResult(
         return FALSE;
     }
 
-    do {
-        TRACE("waiting on %p\n",lpOverlapped);
-        r = WaitForSingleObjectEx(lpOverlapped->hEvent, bWait?INFINITE:0, TRUE);
-        TRACE("wait on %p returned %ld\n",lpOverlapped,r);
-    } while (r==STATUS_USER_APC);
+    if ( bWait )
+    {
+        do {
+            TRACE("waiting on %p\n",lpOverlapped);
+            r = WaitForSingleObjectEx(lpOverlapped->hEvent, INFINITE, TRUE);
+            TRACE("wait on %p returned %ld\n",lpOverlapped,r);
+        } while (r==STATUS_USER_APC);
+    }
+    else if ( lpOverlapped->Internal == STATUS_PENDING )
+    {
+        /* Wait in order to give APCs a chance to run. */
+        /* This is cheating, so we must set the event again in case of success -
+           it may be a non-manual reset event. */
+        do {
+            TRACE("waiting on %p\n",lpOverlapped);
+            r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE);
+            TRACE("wait on %p returned %ld\n",lpOverlapped,r);
+        } while (r==STATUS_USER_APC);
+        if ( r == WAIT_OBJECT_0 )
+            NtSetEvent ( lpOverlapped->hEvent, NULL );
+    }
 
     if(lpTransferred)
         *lpTransferred = lpOverlapped->InternalHigh;
 
-    SetLastError(lpOverlapped->Internal);
-
-    return (r==WAIT_OBJECT_0);
+    switch ( lpOverlapped->Internal )
+    {
+    case STATUS_SUCCESS:
+        return TRUE;
+    case STATUS_PENDING:
+        SetLastError ( ERROR_IO_INCOMPLETE );
+        if ( bWait ) ERR ("PENDING status after waiting!\n");
+        return FALSE;
+    default:
+        SetLastError ( RtlNtStatusToDosError ( lpOverlapped->Internal ) );
+        return FALSE;
+    }
 }
 
+/***********************************************************************
+ *             CancelIo                   (KERNEL32.@)
+ */
+BOOL WINAPI CancelIo(HANDLE handle)
+{
+    async_private *ovp,*t;
+
+    TRACE("handle = %x\n",handle);
+
+    for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t)
+    {
+        t = ovp->next;
+        if ( ovp->handle == handle )
+             cancel_async ( ovp );
+    }
+    WaitForMultipleObjectsEx(0,NULL,FALSE,1,TRUE);
+    return TRUE;
+}
 
 /***********************************************************************
  *             FILE_AsyncReadService      (INTERNAL)
@@ -1208,33 +1638,27 @@ BOOL WINAPI GetOverlappedResult(
  *  This function is called while the client is waiting on the
  *  server, so we can't make any server calls here.
  */
-static void FILE_AsyncReadService(async_private *ovp, int events)
+static void FILE_AsyncReadService(async_private *ovp)
 {
-    LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+    async_fileio *fileio = (async_fileio*) ovp;
+    LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
     int result, r;
+    int already = lpOverlapped->InternalHigh;
 
-    TRACE("%p %p %08x\n", lpOverlapped, ovp->buffer, events );
+    TRACE("%p %p\n", lpOverlapped, fileio->buffer );
 
-    /* if POLLNVAL, then our fd was closed or we have the wrong fd */
-    if(events&POLLNVAL)
-    {
-        ERR("fd %d invalid for %p\n",ovp->fd,ovp);
-        r = STATUS_UNSUCCESSFUL;
-        goto async_end;
-    }
+    /* check to see if the data is ready (non-blocking) */
 
-    /* if there are no events, it must be a timeout */
-    if(events==0)
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
+        result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
     {
-        TRACE("read timed out\n");
-        r = STATUS_TIMEOUT;
-        goto async_end;
+        result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
+                        OVERLAPPED_OFFSET (lpOverlapped) + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
     }
 
-    /* check to see if the data is ready (non-blocking) */
-    result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
-                  lpOverlapped->OffsetHigh - lpOverlapped->InternalHigh);
-
     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
         TRACE("Deferred read %d\n",errno);
@@ -1245,154 +1669,205 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
     /* check to see if the transfer is complete */
     if(result<0)
     {
-        TRACE("read returned errno %d\n",errno);
-        r = STATUS_UNSUCCESSFUL;
+        r = FILE_GetNtStatus ();
         goto async_end;
     }
 
     lpOverlapped->InternalHigh += result;
-    TRACE("read %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh);
+    TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
 
-    if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh)
-        r = STATUS_PENDING;
-    else
+    if(lpOverlapped->InternalHigh >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
         r = STATUS_SUCCESS;
+    else
+        r = STATUS_PENDING;
 
 async_end:
     lpOverlapped->Internal = r;
 }
 
-/* flogged from wineserver */
-/* add a timeout in milliseconds to an absolute time */
-static void add_timeout( struct timeval *when, int timeout )
-{
-    if (timeout)
-    {
-        long sec = timeout / 1000;
-        if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000)
-        {
-            when->tv_usec -= 1000000;
-            when->tv_sec++;
-        }
-        when->tv_sec += sec;
-    }
-}
-
 /***********************************************************************
- *             FILE_StartAsyncRead      (INTERNAL)
- *
- * Don't need thread safety, because the list of asyncs 
- * will only be modified in this thread.
+ *              FILE_ReadFileEx                (INTERNAL)
  */
-static BOOL FILE_StartAsyncRead( HANDLE hFile, LPOVERLAPPED overlapped, LPVOID buffer, DWORD count)
+static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
+                        LPOVERLAPPED overlapped,
+                        LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
+                         HANDLE hEvent)
 {
-    async_private *ovp;
-    int fd, timeout, ret;
+    async_fileio *ovp;
+    int fd;
+    int flags;
+    enum fd_type type;
 
-    /* 
-     * Although the overlapped transfer will be done in this thread
-     * we still need to register the operation with the server, in
-     * case it is cancelled and to get a file handle and the timeout info.
-     */
-    SERVER_START_REQ(create_async)
-    {
-        req->count = count;
-        req->type = ASYNC_TYPE_READ;
-        req->file_handle = hFile;
-        ret = SERVER_CALL();
-        timeout = req->timeout;
-    }
-    SERVER_END_REQ;
-    if (ret)
+    TRACE("file %d to buf %p num %ld %p func %p\n",
+         hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
+
+    /* check that there is an overlapped struct */
+    if (overlapped==NULL)
     {
-        TRACE("server call failed\n");
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
-    if(fd<0)
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
+    if ( fd < 0 )
     {
-        TRACE("Couldn't get FD\n");
+        WARN ( "Couldn't get FD\n" );
         return FALSE;
     }
 
-    ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+    ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
     if(!ovp)
     {
         TRACE("HeapAlloc Failed\n");
-        close(fd);
-        return FALSE;
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto error;
     }
+
+    ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
+    ovp->async.handle = hFile;
+    ovp->async.fd = fd;
+    ovp->async.type = ASYNC_TYPE_READ;
+    ovp->async.func = FILE_AsyncReadService;
+    ovp->async.event = hEvent;
     ovp->lpOverlapped = overlapped;
-    ovp->timeout = timeout;
-    gettimeofday(&ovp->tv,NULL);
-    add_timeout(&ovp->tv,timeout);
-    ovp->event = POLLIN;
-    ovp->func = FILE_AsyncReadService;
+    ovp->count = bytesToRead;
+    ovp->completion_func = lpCompletionRoutine;
     ovp->buffer = buffer;
-    ovp->fd = fd;
+    ovp->fd_type = type;
 
-    /* hook this overlap into the pending async operation list */
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if(ovp->next)
-        ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
+    return !register_new_async (&ovp->async);
 
-    SetLastError(ERROR_IO_PENDING);
+error:
+    close (fd);
+    return FALSE;
 
-    return TRUE;
 }
 
+/***********************************************************************
+ *              ReadFileEx                (KERNEL32.@)
+ */
+BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
+                        LPOVERLAPPED overlapped,
+                        LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    overlapped->InternalHigh = 0;
+    return FILE_ReadFileEx(hFile,buffer,bytesToRead,overlapped,lpCompletionRoutine, INVALID_HANDLE_VALUE);
+}
+
+static BOOL FILE_TimeoutRead(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead)
+{
+    OVERLAPPED ov;
+    BOOL r = FALSE;
+
+    TRACE("%d %p %ld %p\n", hFile, buffer, bytesToRead, bytesRead );
+
+    ZeroMemory(&ov, sizeof (OVERLAPPED));
+    if(STATUS_SUCCESS==NtCreateEvent(&ov.hEvent, SYNCHRONIZE, NULL, 0, 0))
+    {
+        if(FILE_ReadFileEx(hFile, buffer, bytesToRead, &ov, NULL, ov.hEvent))
+        {
+            r = GetOverlappedResult(hFile, &ov, bytesRead, TRUE);
+        }
+    }
+    CloseHandle(ov.hEvent);
+    return r;
+}
 
 /***********************************************************************
- *              ReadFile                (KERNEL32.577)
+ *              ReadFile                (KERNEL32.@)
  */
 BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
                         LPDWORD bytesRead, LPOVERLAPPED overlapped )
 {
-    int unix_handle, result;
+    int unix_handle, result, flags;
+    enum fd_type type;
 
-    TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToRead, 
+    TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToRead,
           bytesRead, overlapped );
 
     if (bytesRead) *bytesRead = 0;  /* Do this before anything else */
     if (!bytesToRead) return TRUE;
 
-    /* this will only have impact if the overlapped structure is specified */
-    if ( overlapped )
+    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags );
+
+    if (flags & FD_FLAG_OVERLAPPED)
     {
-        /* if overlapped, check that there is an event flag */
-        if ( (overlapped->hEvent == 0) ||
-           (overlapped->hEvent == INVALID_HANDLE_VALUE) )
+       if (unix_handle == -1) return FALSE;
+        if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) )
         {
+            TRACE("Overlapped not specified or invalid event flag\n");
+           close(unix_handle);
             SetLastError(ERROR_INVALID_PARAMETER);
             return FALSE;
         }
 
-        overlapped->Offset       = 0;
-        overlapped->OffsetHigh   = bytesToRead;
-        overlapped->Internal = STATUS_PENDING;
+        close(unix_handle);
         overlapped->InternalHigh = 0;
 
-        NtResetEvent( overlapped->hEvent, NULL );
+        if(!FILE_ReadFileEx(hFile, buffer, bytesToRead, overlapped, NULL, overlapped->hEvent))
+            return FALSE;
+
+        if ( !GetOverlappedResult (hFile, overlapped, bytesRead, FALSE) )
+        {
+            if ( GetLastError() == ERROR_IO_INCOMPLETE )
+                SetLastError ( ERROR_IO_PENDING );
+            return FALSE;
+        }
+
+        return TRUE;
+    }
+    if (flags & FD_FLAG_TIMEOUT)
+    {
+        close(unix_handle);
+        return FILE_TimeoutRead(hFile, buffer, bytesToRead, bytesRead);
+    }
+    switch(type)
+    {
+    case FD_TYPE_SMB:
+        return SMB_ReadFile(hFile, buffer, bytesToRead, bytesRead, NULL);
+
+    case FD_TYPE_CONSOLE:
+       return FILE_ReadConsole(hFile, buffer, bytesToRead, bytesRead, NULL);
 
-        FILE_StartAsyncRead(hFile, overlapped, buffer, bytesToRead);
+    case FD_TYPE_DEFAULT:
+        /* normal unix files */
+        if (unix_handle == -1) return FALSE;
+        if (overlapped)
+        {
+            DWORD highOffset = overlapped->OffsetHigh;
+            if ( (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, overlapped->Offset,
+                                                             &highOffset, FILE_BEGIN)) &&
+                 (GetLastError() != NO_ERROR) )
+            {
+              close(unix_handle);
+              return FALSE;
+            }
+        }
+        break;
 
-        /* always fail on return, either ERROR_IO_PENDING or other error */
-        return FALSE;
+    default:
+       if (unix_handle == -1)
+           return FALSE;
     }
 
-    unix_handle = FILE_GetUnixHandle( hFile, GENERIC_READ );
-    if (unix_handle == -1) return FALSE;
+    if(overlapped)
+    {
+       off_t offset = OVERLAPPED_OFFSET(overlapped);
+       if(lseek(unix_handle, offset, SEEK_SET) == -1)
+       {
+           close(unix_handle);
+           SetLastError(ERROR_INVALID_PARAMETER);
+           return FALSE;
+       }
+    }
 
     /* code for synchronous reads */
     while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
     {
-        if ((errno == EAGAIN) || (errno == EINTR)) continue;
-        if ((errno == EFAULT) && !IsBadWritePtr( buffer, bytesToRead )) continue;
-        FILE_SetDosError();
-        break;
+       if ((errno == EAGAIN) || (errno == EINTR)) continue;
+       if ((errno == EFAULT) && !IsBadWritePtr( buffer, bytesToRead )) continue;
+       FILE_SetDosError();
+       break;
     }
     close( unix_handle );
     if (result == -1) return FALSE;
@@ -1407,33 +1882,27 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
  *  This function is called while the client is waiting on the
  *  server, so we can't make any server calls here.
  */
-static void FILE_AsyncWriteService(struct async_private *ovp, int events)
+static void FILE_AsyncWriteService(struct async_private *ovp)
 {
-    LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+    async_fileio *fileio = (async_fileio *) ovp;
+    LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
     int result, r;
+    int already = lpOverlapped->InternalHigh;
 
-    TRACE("(%p %p %08x)\n",lpOverlapped,ovp->buffer,events);
+    TRACE("(%p %p)\n",lpOverlapped,fileio->buffer);
 
-    /* if POLLNVAL, then our fd was closed or we have the wrong fd */
-    if(events&POLLNVAL)
-    {
-        ERR("fd %d invalid for %p\n",ovp->fd,ovp);
-        r = STATUS_UNSUCCESSFUL;
-        goto async_end;
-    }
+    /* write some data (non-blocking) */
 
-    /* if there are no events, it must be a timeout */
-    if(events==0)
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
+        result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
     {
-        TRACE("write timed out\n");
-        r = STATUS_TIMEOUT;
-        goto async_end;
+        result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
+                    OVERLAPPED_OFFSET (lpOverlapped) + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
     }
 
-    /* write some data (non-blocking) */
-    result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
-                  lpOverlapped->OffsetHigh-lpOverlapped->InternalHigh);
-
     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
         r = STATUS_PENDING;
@@ -1443,15 +1912,15 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
     /* check to see if the transfer is complete */
     if(result<0)
     {
-        r = STATUS_UNSUCCESSFUL;
+        r = FILE_GetNtStatus ();
         goto async_end;
     }
 
     lpOverlapped->InternalHigh += result;
 
-    TRACE("wrote %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh);
+    TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
 
-    if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh)
+    if(lpOverlapped->InternalHigh < fileio->count)
         r = STATUS_PENDING;
     else
         r = STATUS_SUCCESS;
@@ -1461,93 +1930,162 @@ async_end:
 }
 
 /***********************************************************************
- *             FILE_StartAsyncWrite      (INTERNAL)
+ *              FILE_WriteFileEx
  */
-static BOOL FILE_StartAsyncWrite(HANDLE hFile, LPOVERLAPPED overlapped, LPCVOID buffer,DWORD count)
+static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
+                             LPOVERLAPPED overlapped,
+                             LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
+                             HANDLE hEvent)
 {
-    /* don't need thread safety, because the list will only be modified in this thread */
-    async_private *ovp = (async_private*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
-    int timeout,ret;
+    async_fileio *ovp;
+    int fd;
+    int flags;
+    enum fd_type type;
 
-    SERVER_START_REQ(create_async)
+    TRACE("file %d to buf %p num %ld %p func %p handle %d\n",
+         hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine, hEvent);
+
+    if (overlapped == NULL)
     {
-        req->count = count;
-        req->type = ASYNC_TYPE_WRITE;
-        req->file_handle = hFile;
-        ret = SERVER_CALL();
-        timeout = req->timeout;
-    }
-    SERVER_END_REQ;
-    if (ret)
+        SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
+    }
 
-    /* need to register the overlapped with the server, get a file handle and the timeout info */
-    ovp->lpOverlapped = overlapped;
-    ovp->timeout = timeout;
-    gettimeofday(&ovp->tv,NULL);
-    add_timeout(&ovp->tv,timeout);
-    ovp->event = POLLOUT;
-    ovp->func = FILE_AsyncWriteService;
-    ovp->buffer = (LPVOID) buffer;
-    ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
-    if(ovp->fd <0)
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
+    if ( fd < 0 )
     {
-        HeapFree(GetProcessHeap(), 0, ovp);
+        TRACE( "Couldn't get FD\n" );
         return FALSE;
     }
 
-    /* hook this overlap into the pending async operation list */
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if(ovp->next)
-        ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
+    ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
+    if(!ovp)
+    {
+        TRACE("HeapAlloc Failed\n");
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto error;
+    }
+
+    ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
+    ovp->async.handle = hFile;
+    ovp->async.fd = fd;
+    ovp->async.type = ASYNC_TYPE_WRITE;
+    ovp->async.func = FILE_AsyncWriteService;
+    ovp->lpOverlapped = overlapped;
+    ovp->async.event = hEvent;
+    ovp->buffer = (LPVOID) buffer;
+    ovp->count = bytesToWrite;
+    ovp->completion_func = lpCompletionRoutine;
+    ovp->fd_type = type;
 
-    SetLastError(ERROR_IO_PENDING);
+    return !register_new_async (&ovp->async);
 
-    return TRUE;
+error:
+    close (fd);
+    return FALSE;
 }
 
+/***********************************************************************
+ *              WriteFileEx                (KERNEL32.@)
+ */
+BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
+                        LPOVERLAPPED overlapped,
+                        LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    overlapped->InternalHigh = 0;
+
+    return FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine, INVALID_HANDLE_VALUE);
+}
 
 /***********************************************************************
- *             WriteFile               (KERNEL32.738)
+ *             WriteFile               (KERNEL32.@)
  */
 BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
                          LPDWORD bytesWritten, LPOVERLAPPED overlapped )
 {
-    int unix_handle, result;
+    int unix_handle, result, flags;
+    enum fd_type type;
 
-    TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite, 
+    TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite,
           bytesWritten, overlapped );
 
     if (bytesWritten) *bytesWritten = 0;  /* Do this before anything else */
     if (!bytesToWrite) return TRUE;
 
-    /* this will only have impact if the overlappd structure is specified */
-    if ( overlapped )
+    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags );
+
+    if (flags & FD_FLAG_OVERLAPPED)
     {
-        if ( (overlapped->hEvent == 0) ||
-             (overlapped->hEvent == INVALID_HANDLE_VALUE) )
+       if (unix_handle == -1) return FALSE;
+        if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) )
         {
+            TRACE("Overlapped not specified or invalid event flag\n");
+           close(unix_handle);
             SetLastError(ERROR_INVALID_PARAMETER);
             return FALSE;
         }
 
-        overlapped->Offset       = 0;
-        overlapped->OffsetHigh   = bytesToWrite;
-        overlapped->Internal = STATUS_PENDING;
+        close(unix_handle);
         overlapped->InternalHigh = 0;
 
-        NtResetEvent( overlapped->hEvent, NULL );
+        if(!FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL, overlapped->hEvent))
+            return FALSE;
 
-        FILE_StartAsyncWrite(hFile, overlapped, buffer, bytesToWrite);
+        if ( !GetOverlappedResult (hFile, overlapped, bytesWritten, FALSE) )
+        {
+            if ( GetLastError() == ERROR_IO_INCOMPLETE )
+                SetLastError ( ERROR_IO_PENDING );
+            return FALSE;
+        }
 
-        /* always fail on return, either ERROR_IO_PENDING or other error */
-        return FALSE;
+        return TRUE;
+    }
+
+    switch(type)
+    {
+    case FD_TYPE_CONSOLE:
+       TRACE("%d %s %ld %p %p\n", hFile, debugstr_an(buffer, bytesToWrite), bytesToWrite,
+             bytesWritten, overlapped );
+       return FILE_WriteConsole(hFile, buffer, bytesToWrite, bytesWritten, NULL);
+
+    case FD_TYPE_DEFAULT:
+        if (unix_handle == -1) return FALSE;
+
+        if(overlapped)
+        {
+            DWORD highOffset = overlapped->OffsetHigh;
+            if ( (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, overlapped->Offset,
+                                                             &highOffset, FILE_BEGIN)) &&
+                 (GetLastError() != NO_ERROR) )
+            {
+              close(unix_handle);
+              return FALSE;
+            }
+        }
+        break;
+
+    default:
+        if (unix_handle == -1)
+            return FALSE;
+        if (overlapped)
+        {
+            close(unix_handle);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+        break;
     }
 
-    unix_handle = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
-    if (unix_handle == -1) return FALSE;
+    if(overlapped)
+    {
+       off_t offset = OVERLAPPED_OFFSET(overlapped);
+       if(lseek(unix_handle, offset, SEEK_SET) == -1)
+       {
+           close(unix_handle);
+           SetLastError(ERROR_INVALID_PARAMETER);
+           return FALSE;
+       }
+    }
 
     /* synchronous file write */
     while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
@@ -1566,9 +2104,9 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
     return TRUE;
 }
 
-  
+
 /***********************************************************************
- *           WIN16_hread
+ *           _hread (KERNEL.349)
  */
 LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
 {
@@ -1580,12 +2118,12 @@ LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
     /* Some programs pass a count larger than the allocated buffer */
     maxlen = GetSelectorLimit16( SELECTOROF(buffer) ) - OFFSETOF(buffer) + 1;
     if (count > maxlen) count = maxlen;
-    return _lread(DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
+    return _lread((HFILE)DosFileHandleToWin32Handle(hFile), MapSL(buffer), count );
 }
 
 
 /***********************************************************************
- *           WIN16_lread
+ *           _lread (KERNEL.82)
  */
 UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
 {
@@ -1594,12 +2132,12 @@ UINT16 WINAPI WIN16_lread( HFILE16 hFile, SEGPTR buffer, UINT16 count )
 
 
 /***********************************************************************
- *           _lread   (KERNEL32.596)
+ *           _lread   (KERNEL32.@)
  */
 UINT WINAPI _lread( HFILE handle, LPVOID buffer, UINT count )
 {
     DWORD result;
-    if (!ReadFile( handle, buffer, count, &result, NULL )) return -1;
+    if (!ReadFile( (HANDLE)handle, buffer, count, &result, NULL )) return -1;
     return result;
 }
 
@@ -1609,52 +2147,43 @@ UINT WINAPI _lread( HFILE handle, LPVOID buffer, UINT count )
  */
 UINT16 WINAPI _lread16( HFILE16 hFile, LPVOID buffer, UINT16 count )
 {
-    return (UINT16)_lread(DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
+    return (UINT16)_lread((HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
 }
 
 
 /***********************************************************************
- *           _lcreat16   (KERNEL.83)
+ *           _lcreat   (KERNEL.83)
  */
 HFILE16 WINAPI _lcreat16( LPCSTR path, INT16 attr )
 {
-    return Win32HandleToDosFileHandle( _lcreat( path, attr ) );
+    return Win32HandleToDosFileHandle( (HANDLE)_lcreat( path, attr ) );
 }
 
 
 /***********************************************************************
- *           _lcreat   (KERNEL32.593)
+ *           _lcreat   (KERNEL32.@)
  */
 HFILE WINAPI _lcreat( LPCSTR path, INT attr )
 {
     /* Mask off all flags not explicitly allowed by the doc */
     attr &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
     TRACE("%s %02x\n", path, attr );
-    return CreateFileA( path, GENERIC_READ | GENERIC_WRITE,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
-                        CREATE_ALWAYS, attr, 0 );
+    return (HFILE)CreateFileA( path, GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                               CREATE_ALWAYS, attr, 0 );
 }
 
 
 /***********************************************************************
- *           SetFilePointer   (KERNEL32.492)
+ *           SetFilePointer   (KERNEL32.@)
  */
 DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword,
                              DWORD method )
 {
-    DWORD ret = 0xffffffff;
+    DWORD ret = INVALID_SET_FILE_POINTER;
 
-    if (highword &&
-        ((distance >= 0 && *highword != 0) || (distance < 0 && *highword != -1)))
-    {
-        FIXME("64-bit offsets not supported yet\n"
-              "SetFilePointer(%08x,%08lx,%08lx,%08lx)\n",
-              hFile,distance,*highword,method);
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return ret;
-    }
-    TRACE("handle %d offset %ld origin %ld\n",
-          hFile, distance, method );
+    TRACE("handle %d offset %ld high %ld origin %ld\n",
+          hFile, distance, highword?*highword:0, method );
 
     SERVER_START_REQ( set_file_pointer )
     {
@@ -1664,10 +2193,10 @@ DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword,
         /* FIXME: assumes 1:1 mapping between Windows and Unix seek constants */
         req->whence = method;
         SetLastError( 0 );
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
-            ret = req->new_low;
-            if (highword) *highword = req->new_high;
+            ret = reply->new_low;
+            if (highword) *highword = reply->new_high;
         }
     }
     SERVER_END_REQ;
@@ -1676,7 +2205,7 @@ DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword,
 
 
 /***********************************************************************
- *           _llseek16   (KERNEL.84)
+ *           _llseek   (KERNEL.84)
  *
  * FIXME:
  *   Seeking before the start of the file should be allowed for _llseek16,
@@ -1690,25 +2219,25 @@ LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
 
 
 /***********************************************************************
- *           _llseek   (KERNEL32.594)
+ *           _llseek   (KERNEL32.@)
  */
 LONG WINAPI _llseek( HFILE hFile, LONG lOffset, INT nOrigin )
 {
-    return SetFilePointer( hFile, lOffset, NULL, nOrigin );
+    return SetFilePointer( (HANDLE)hFile, lOffset, NULL, nOrigin );
 }
 
 
 /***********************************************************************
- *           _lopen16   (KERNEL.85)
+ *           _lopen   (KERNEL.85)
  */
 HFILE16 WINAPI _lopen16( LPCSTR path, INT16 mode )
 {
-    return Win32HandleToDosFileHandle( _lopen( path, mode ) );
+    return Win32HandleToDosFileHandle( (HANDLE)_lopen( path, mode ) );
 }
 
 
 /***********************************************************************
- *           _lopen   (KERNEL32.595)
+ *           _lopen   (KERNEL32.@)
  */
 HFILE WINAPI _lopen( LPCSTR path, INT mode )
 {
@@ -1716,20 +2245,20 @@ HFILE WINAPI _lopen( LPCSTR path, INT mode )
 
     TRACE("('%s',%04x)\n", path, mode );
     FILE_ConvertOFMode( mode, &access, &sharing );
-    return CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, 0 );
+    return (HFILE)CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, 0 );
 }
 
 
 /***********************************************************************
- *           _lwrite16   (KERNEL.86)
+ *           _lwrite   (KERNEL.86)
  */
 UINT16 WINAPI _lwrite16( HFILE16 hFile, LPCSTR buffer, UINT16 count )
 {
-    return (UINT16)_hwrite( DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
+    return (UINT16)_hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, (LONG)count );
 }
 
 /***********************************************************************
- *           _lwrite   (KERNEL32.761)
+ *           _lwrite   (KERNEL32.@)
  */
 UINT WINAPI _lwrite( HFILE hFile, LPCSTR buffer, UINT count )
 {
@@ -1742,12 +2271,12 @@ UINT WINAPI _lwrite( HFILE hFile, LPCSTR buffer, UINT count )
  */
 LONG WINAPI _hread16( HFILE16 hFile, LPVOID buffer, LONG count)
 {
-    return _lread( DosFileHandleToWin32Handle(hFile), buffer, count );
+    return _lread( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
 }
 
 
 /***********************************************************************
- *           _hread   (KERNEL32.590)
+ *           _hread   (KERNEL32.@)
  */
 LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
 {
@@ -1756,23 +2285,23 @@ LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
 
 
 /***********************************************************************
- *           _hwrite16   (KERNEL.350)
+ *           _hwrite   (KERNEL.350)
  */
 LONG WINAPI _hwrite16( HFILE16 hFile, LPCSTR buffer, LONG count )
 {
-    return _hwrite( DosFileHandleToWin32Handle(hFile), buffer, count );
+    return _hwrite( (HFILE)DosFileHandleToWin32Handle(hFile), buffer, count );
 }
 
 
 /***********************************************************************
- *           _hwrite   (KERNEL32.591)
+ *           _hwrite   (KERNEL32.@)
  *
  *     experimentation yields that _lwrite:
- *             o truncates the file at the current position with 
+ *             o truncates the file at the current position with
  *               a 0 len write
  *             o returns 0 on a 0 length write
  *             o works with console handles
- *             
+ *
  */
 LONG WINAPI _hwrite( HFILE handle, LPCSTR buffer, LONG count )
 {
@@ -1783,17 +2312,17 @@ LONG WINAPI _hwrite( HFILE handle, LPCSTR buffer, LONG count )
     if (!count)
     {
         /* Expand or truncate at current position */
-        if (!SetEndOfFile( handle )) return HFILE_ERROR;
+        if (!SetEndOfFile( (HANDLE)handle )) return HFILE_ERROR;
         return 0;
     }
-    if (!WriteFile( handle, buffer, count, &result, NULL ))
+    if (!WriteFile( (HANDLE)handle, buffer, count, &result, NULL ))
         return HFILE_ERROR;
     return result;
 }
 
 
 /***********************************************************************
- *           SetHandleCount16   (KERNEL.199)
+ *           SetHandleCount   (KERNEL.199)
  */
 UINT16 WINAPI SetHandleCount16( UINT16 count )
 {
@@ -1802,7 +2331,7 @@ UINT16 WINAPI SetHandleCount16( UINT16 count )
 
 
 /*************************************************************************
- *           SetHandleCount   (KERNEL32.494)
+ *           SetHandleCount   (KERNEL32.@)
  */
 UINT WINAPI SetHandleCount( UINT count )
 {
@@ -1811,7 +2340,7 @@ UINT WINAPI SetHandleCount( UINT count )
 
 
 /***********************************************************************
- *           FlushFileBuffers   (KERNEL32.133)
+ *           FlushFileBuffers   (KERNEL32.@)
  */
 BOOL WINAPI FlushFileBuffers( HANDLE hFile )
 {
@@ -1819,7 +2348,7 @@ BOOL WINAPI FlushFileBuffers( HANDLE hFile )
     SERVER_START_REQ( flush_file )
     {
         req->handle = hFile;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1827,7 +2356,7 @@ BOOL WINAPI FlushFileBuffers( HANDLE hFile )
 
 
 /**************************************************************************
- *           SetEndOfFile   (KERNEL32.483)
+ *           SetEndOfFile   (KERNEL32.@)
  */
 BOOL WINAPI SetEndOfFile( HANDLE hFile )
 {
@@ -1835,7 +2364,7 @@ BOOL WINAPI SetEndOfFile( HANDLE hFile )
     SERVER_START_REQ( truncate_file )
     {
         req->handle = hFile;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1843,7 +2372,7 @@ BOOL WINAPI SetEndOfFile( HANDLE hFile )
 
 
 /***********************************************************************
- *           DeleteFile16   (KERNEL.146)
+ *           DeleteFile   (KERNEL.146)
  */
 BOOL16 WINAPI DeleteFile16( LPCSTR path )
 {
@@ -1852,13 +2381,19 @@ BOOL16 WINAPI DeleteFile16( LPCSTR path )
 
 
 /***********************************************************************
- *           DeleteFileA   (KERNEL32.71)
+ *           DeleteFileW   (KERNEL32.@)
  */
-BOOL WINAPI DeleteFileA( LPCSTR path )
+BOOL WINAPI DeleteFileW( LPCWSTR path )
 {
     DOS_FULL_NAME full_name;
+    HANDLE hFile;
 
-    TRACE("'%s'\n", path );
+    if (!path)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    TRACE("%s\n", debugstr_w(path) );
 
     if (!*path)
     {
@@ -1867,35 +2402,57 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
     }
     if (DOSFS_GetDevice( path ))
     {
-        WARN("cannot remove DOS device '%s'!\n", path);
+        WARN("cannot remove DOS device %s!\n", debugstr_w(path));
         SetLastError( ERROR_FILE_NOT_FOUND );
         return FALSE;
     }
 
     if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+
+    /* check if we are allowed to delete the source */
+    hFile = FILE_CreateFile( full_name.long_name, GENERIC_READ|GENERIC_WRITE, 0,
+                             NULL, OPEN_EXISTING, 0, 0, TRUE,
+                             GetDriveTypeW( full_name.short_name ) );
+    if (!hFile) return FALSE;
+
     if (unlink( full_name.long_name ) == -1)
     {
         FILE_SetDosError();
+        CloseHandle(hFile);
         return FALSE;
     }
+    CloseHandle(hFile);
     return TRUE;
 }
 
 
 /***********************************************************************
- *           DeleteFileW   (KERNEL32.72)
+ *           DeleteFileA   (KERNEL32.@)
  */
-BOOL WINAPI DeleteFileW( LPCWSTR path )
+BOOL WINAPI DeleteFileA( LPCSTR path )
 {
-    LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
-    BOOL ret = DeleteFileA( xpath );
-    HeapFree( GetProcessHeap(), 0, xpath );
+    UNICODE_STRING pathW;
+    BOOL ret = FALSE;
+
+    if (!path)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
+    {
+        ret = DeleteFileW(pathW.Buffer);
+        RtlFreeUnicodeString(&pathW);
+    }
+    else
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
     return ret;
 }
 
 
 /***********************************************************************
- *           GetFileType   (KERNEL32.222)
+ *           GetFileType   (KERNEL32.@)
  */
 DWORD WINAPI GetFileType( HANDLE hFile )
 {
@@ -1903,85 +2460,322 @@ DWORD WINAPI GetFileType( HANDLE hFile )
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
-        if (!SERVER_CALL_ERR()) ret = req->type;
+        if (!wine_server_call_err( req )) ret = reply->type;
     }
     SERVER_END_REQ;
     return ret;
 }
 
 
+/* check if a file name is for an executable file (.exe or .com) */
+inline static BOOL is_executable( const char *name )
+{
+    int len = strlen(name);
+
+    if (len < 4) return FALSE;
+    return (!strcasecmp( name + len - 4, ".exe" ) ||
+            !strcasecmp( name + len - 4, ".com" ));
+}
+
+
+/***********************************************************************
+ *           FILE_AddBootRenameEntry
+ *
+ * Adds an entry to the registry that is loaded when windows boots and
+ * checks if there are some files to be removed or renamed/moved.
+ * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
+ * non-NULL then the file is moved, otherwise it is deleted.  The
+ * entry of the registrykey is always appended with two zero
+ * terminated strings. If <fn2> is NULL then the second entry is
+ * simply a single 0-byte. Otherwise the second filename goes
+ * there. The entries are prepended with \??\ before the path and the
+ * second filename gets also a '!' as the first character if
+ * MOVEFILE_REPLACE_EXISTING is set. After the final string another
+ * 0-byte follows to indicate the end of the strings.
+ * i.e.:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * \??\D:\test\file2[0]
+ * !\??\D:\test\file2_renamed[0]
+ * [0]                        <- indicates end of strings
+ *
+ * or:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * [0]                        <- indicates end of strings
+ *
+ */
+static BOOL FILE_AddBootRenameEntry( LPCWSTR fn1, LPCWSTR fn2, DWORD flags )
+{
+    static const WCHAR PreString[] = {'\\','?','?','\\',0};
+    static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
+                                      'F','i','l','e','R','e','n','a','m','e',
+                                      'O','p','e','r','a','t','i','o','n','s',0};
+    static const WCHAR SessionW[] = {'M','a','c','h','i','n','e','\\',
+                                     'S','y','s','t','e','m','\\',
+                                     'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+                                     'C','o','n','t','r','o','l','\\',
+                                     'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r',0};
+    static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
+
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING nameW;
+    KEY_VALUE_PARTIAL_INFORMATION *info;
+    BOOL rc = FALSE;
+    HKEY Reboot = 0;
+    DWORD len0, len1, len2;
+    DWORD DataSize = 0;
+    BYTE *Buffer = NULL;
+    WCHAR *p;
+
+    attr.Length = sizeof(attr);
+    attr.RootDirectory = 0;
+    attr.ObjectName = &nameW;
+    attr.Attributes = 0;
+    attr.SecurityDescriptor = NULL;
+    attr.SecurityQualityOfService = NULL;
+    RtlInitUnicodeString( &nameW, SessionW );
+
+    if (NtCreateKey( &Reboot, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
+    {
+        WARN("Error creating key for reboot managment [%s]\n",
+             "SYSTEM\\CurrentControlSet\\Control\\Session Manager");
+        return FALSE;
+    }
+
+    len0 = strlenW(PreString);
+    len1 = strlenW(fn1) + len0 + 1;
+    if (fn2)
+    {
+        len2 = strlenW(fn2) + len0 + 1;
+        if (flags & MOVEFILE_REPLACE_EXISTING) len2++; /* Plus 1 because of the leading '!' */
+    }
+    else len2 = 1; /* minimum is the 0 characters for the empty second string */
+
+    /* convert characters to bytes */
+    len0 *= sizeof(WCHAR);
+    len1 *= sizeof(WCHAR);
+    len2 *= sizeof(WCHAR);
+
+    RtlInitUnicodeString( &nameW, ValueName );
+
+    /* First we check if the key exists and if so how many bytes it already contains. */
+    if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
+                         NULL, 0, &DataSize ) == STATUS_BUFFER_OVERFLOW)
+    {
+        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
+            goto Quit;
+        if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
+                             Buffer, DataSize, &DataSize )) goto Quit;
+        info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
+        if (info->Type != REG_MULTI_SZ) goto Quit;
+        if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
+    }
+    else
+    {
+        DataSize = info_size;
+        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
+            goto Quit;
+    }
+
+    p = (WCHAR *)(Buffer + DataSize);
+    strcpyW( p, PreString );
+    strcatW( p, fn1 );
+    DataSize += len1;
+    if (fn2)
+    {
+        p = (WCHAR *)(Buffer + DataSize);
+        if (flags & MOVEFILE_REPLACE_EXISTING)
+            *p++ = '!';
+        strcpyW( p, PreString );
+        strcatW( p, fn2 );
+        DataSize += len2;
+    }
+    else
+    {
+        p = (WCHAR *)(Buffer + DataSize);
+        *p = 0;
+        DataSize += sizeof(WCHAR);
+    }
+
+    /* add final null */
+    p = (WCHAR *)(Buffer + DataSize);
+    *p = 0;
+    DataSize += sizeof(WCHAR);
+
+    rc = !NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size);
+
+ Quit:
+    if (Reboot) NtClose(Reboot);
+    if (Buffer) HeapFree( GetProcessHeap(), 0, Buffer );
+    return(rc);
+}
+
+
 /**************************************************************************
- *           MoveFileExA   (KERNEL32.???)
+ *           MoveFileExW   (KERNEL32.@)
  */
-BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
+BOOL WINAPI MoveFileExW( LPCWSTR fn1, LPCWSTR fn2, DWORD flag )
 {
     DOS_FULL_NAME full_name1, full_name2;
+    HANDLE hFile;
+    DWORD attr = INVALID_FILE_ATTRIBUTES;
+
+    TRACE("(%s,%s,%04lx)\n", debugstr_w(fn1), debugstr_w(fn2), flag);
+
+    /* FIXME: <Gerhard W. Gruber>sparhawk@gmx.at
+       In case of W9x and lesser this function should return 120 (ERROR_CALL_NOT_IMPLEMENTED)
+       to be really compatible. Most programs wont have any problems though. In case
+       you encounter one, this is what you should return here. I don't know what's up
+       with NT 3.5. Is this function available there or not?
+       Does anybody really care about 3.5? :)
+    */
+
+    /* Filename1 has to be always set to a valid path. Filename2 may be NULL
+       if the source file has to be deleted.
+    */
+    if (!fn1) {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-    TRACE("(%s,%s,%04lx)\n", fn1, fn2, flag);
-
-    if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
+    /* This function has to be run through in order to process the name properly.
+       If the BOOTDELAY flag is set, the file doesn't need to exist though. At least
+       that is the behaviour on NT 4.0. The operation accepts the filenames as
+       they are given but it can't reply with a reasonable returncode. Success
+       means in that case success for entering the values into the registry.
+    */
+    if(!DOSFS_GetFullName( fn1, TRUE, &full_name1 ))
+    {
+        if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+            return FALSE;
+    }
 
     if (fn2)  /* !fn2 means delete fn1 */
     {
-        if (DOSFS_GetFullName( fn2, TRUE, &full_name2 )) 
+        if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))
         {
-            /* target exists, check if we may overwrite */
-            if (!(flag & MOVEFILE_REPLACE_EXISTING))
+            if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
             {
-                /* FIXME: Use right error code */
-                SetLastError( ERROR_ACCESS_DENIED );
-                return FALSE;
+                /* target exists, check if we may overwrite */
+                if (!(flag & MOVEFILE_REPLACE_EXISTING))
+                {
+                    SetLastError( ERROR_FILE_EXISTS );
+                    return FALSE;
+                }
+            }
+        }
+        else
+        {
+            if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 ))
+            {
+                if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+                    return FALSE;
             }
         }
-        else if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
 
         /* Source name and target path are valid */
 
         if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
         {
             /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
-               Perhaps we should queue these command and execute it 
+               Perhaps we should queue these command and execute it
                when exiting... What about using on_exit(2)
             */
-            FIXME("Please move existing file '%s' to file '%s' when Wine has finished\n",
-                  full_name1.long_name, full_name2.long_name);
-            return TRUE;
+            FIXME("Please move existing file %s to file %s when Wine has finished\n",
+                  debugstr_w(fn1), debugstr_w(fn2));
+            return FILE_AddBootRenameEntry( fn1, fn2, flag );
         }
 
+        attr = GetFileAttributesW( fn1 );
+        if ( attr == INVALID_FILE_ATTRIBUTES ) return FALSE;
+
+        /* check if we are allowed to rename the source */
+        hFile = FILE_CreateFile( full_name1.long_name, 0, 0,
+                                 NULL, OPEN_EXISTING, 0, 0, TRUE,
+                                 GetDriveTypeW( full_name1.short_name ) );
+        if (!hFile)
+        {
+            if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE;
+            if ( !(attr & FILE_ATTRIBUTE_DIRECTORY) ) return FALSE;
+            /* if it's a directory we can continue */
+        }
+        else CloseHandle(hFile);
+
+        /* check, if we are allowed to delete the destination,
+        **     (but the file not being there is fine) */
+        hFile = FILE_CreateFile( full_name2.long_name, GENERIC_READ|GENERIC_WRITE, 0,
+                                 NULL, OPEN_EXISTING, 0, 0, TRUE,
+                                 GetDriveTypeW( full_name2.short_name ) );
+        if(!hFile && GetLastError() != ERROR_FILE_NOT_FOUND) return FALSE;
+        CloseHandle(hFile);
+
         if (full_name1.drive != full_name2.drive)
         {
-            /* use copy, if allowed */
             if (!(flag & MOVEFILE_COPY_ALLOWED))
             {
-                /* FIXME: Use right error code */
-                SetLastError( ERROR_FILE_EXISTS );
+                SetLastError( ERROR_NOT_SAME_DEVICE );
+                return FALSE;
+            }
+            else if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+            {
+                /* Strange, but that's what Windows returns */
+                SetLastError ( ERROR_ACCESS_DENIED );
                 return FALSE;
             }
-            return CopyFileA( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) );
         }
         if (rename( full_name1.long_name, full_name2.long_name ) == -1)
-       {
-            FILE_SetDosError();
-            return FALSE;
-       }
+            /* Try copy/delete unless it's a directory. */
+            /* FIXME: This does not handle the (unlikely) case that the two locations
+               are on the same Wine drive, but on different Unix file systems. */
+        {
+            if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+            {
+                FILE_SetDosError();
+                return FALSE;
+            }
+            else
+            {
+                if ( ! CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) ))
+                    return FALSE;
+                if ( ! DeleteFileW ( fn1 ) )
+                    return FALSE;
+            }
+        }
+        if (is_executable( full_name1.long_name ) != is_executable( full_name2.long_name ))
+        {
+            struct stat fstat;
+            if (stat( full_name2.long_name, &fstat ) != -1)
+            {
+                if (is_executable( full_name2.long_name ))
+                    /* set executable bit where read bit is set */
+                    fstat.st_mode |= (fstat.st_mode & 0444) >> 2;
+                else
+                    fstat.st_mode &= ~0111;
+                chmod( full_name2.long_name, fstat.st_mode );
+            }
+        }
         return TRUE;
     }
     else /* fn2 == NULL means delete source */
     {
         if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
         {
-            if (flag & MOVEFILE_COPY_ALLOWED) {  
+            if (flag & MOVEFILE_COPY_ALLOWED) {
                 WARN("Illegal flag\n");
                 SetLastError( ERROR_GEN_FAILURE );
                 return FALSE;
             }
             /* FIXME: (bon@elektron.ikp.physik.th-darmstadt.de 970706)
-               Perhaps we should queue these command and execute it 
+               Perhaps we should queue these command and execute it
                when exiting... What about using on_exit(2)
             */
-            FIXME("Please delete file '%s' when Wine has finished\n",
-                  full_name1.long_name);
-            return TRUE;
+            FIXME("Please delete file %s when Wine has finished\n", debugstr_w(fn1));
+            return FILE_AddBootRenameEntry( fn1, NULL, flag );
         }
 
         if (unlink( full_name1.long_name ) == -1)
@@ -1994,113 +2788,152 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
 }
 
 /**************************************************************************
- *           MoveFileExW   (KERNEL32.???)
+ *           MoveFileExA   (KERNEL32.@)
  */
-BOOL WINAPI MoveFileExW( LPCWSTR fn1, LPCWSTR fn2, DWORD flag )
+BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
 {
-    LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
-    LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
-    BOOL res = MoveFileExA( afn1, afn2, flag );
-    HeapFree( GetProcessHeap(), 0, afn1 );
-    HeapFree( GetProcessHeap(), 0, afn2 );
-    return res;
+    UNICODE_STRING fn1W, fn2W;
+    BOOL ret;
+
+    if (!fn1)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    RtlCreateUnicodeStringFromAsciiz(&fn1W, fn1);
+    if (fn2) RtlCreateUnicodeStringFromAsciiz(&fn2W, fn2);
+    else fn2W.Buffer = NULL;
+
+    ret = MoveFileExW( fn1W.Buffer, fn2W.Buffer, flag );
+
+    RtlFreeUnicodeString(&fn1W);
+    RtlFreeUnicodeString(&fn2W);
+    return ret;
 }
 
 
 /**************************************************************************
- *           MoveFileA   (KERNEL32.387)
+ *           MoveFileW   (KERNEL32.@)
  *
  *  Move file or directory
  */
-BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
+BOOL WINAPI MoveFileW( LPCWSTR fn1, LPCWSTR fn2 )
 {
     DOS_FULL_NAME full_name1, full_name2;
     struct stat fstat;
 
-    TRACE("(%s,%s)\n", fn1, fn2 );
+    if (!fn1 || !fn2)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    TRACE("(%s,%s)\n", debugstr_w(fn1), debugstr_w(fn2) );
 
     if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
     if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))  {
-      /* The new name must not already exist */ 
+      /* The new name must not already exist */
       SetLastError(ERROR_ALREADY_EXISTS);
       return FALSE;
     }
     if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
 
     if (full_name1.drive == full_name2.drive) /* move */
-    if (rename( full_name1.long_name, full_name2.long_name ) == -1)
+        return MoveFileExW( fn1, fn2, MOVEFILE_COPY_ALLOWED );
+
+    /* copy */
+    if (stat( full_name1.long_name, &fstat ))
     {
+        WARN("Invalid source file %s\n",
+             full_name1.long_name);
         FILE_SetDosError();
         return FALSE;
     }
-      else return TRUE;
-    else /*copy */ {
-      if (stat(  full_name1.long_name, &fstat ))
-       {
-         WARN("Invalid source file %s\n",
-                       full_name1.long_name);
-         FILE_SetDosError();
-         return FALSE;
-       }
-      if (S_ISDIR(fstat.st_mode)) {
-       /* No Move for directories across file systems */
-       /* FIXME: Use right error code */
-       SetLastError( ERROR_GEN_FAILURE );
-       return FALSE;
-      }
-      else
-       return CopyFileA(fn1, fn2, TRUE); /*fail, if exist */ 
+    if (S_ISDIR(fstat.st_mode)) {
+        /* No Move for directories across file systems */
+        /* FIXME: Use right error code */
+        SetLastError( ERROR_GEN_FAILURE );
+        return FALSE;
     }
+    return CopyFileW(fn1, fn2, TRUE); /*fail, if exist */
 }
 
 
 /**************************************************************************
- *           MoveFileW   (KERNEL32.390)
+ *           MoveFileA   (KERNEL32.@)
  */
-BOOL WINAPI MoveFileW( LPCWSTR fn1, LPCWSTR fn2 )
+BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
 {
-    LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
-    LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
-    BOOL res = MoveFileA( afn1, afn2 );
-    HeapFree( GetProcessHeap(), 0, afn1 );
-    HeapFree( GetProcessHeap(), 0, afn2 );
-    return res;
+    UNICODE_STRING fn1W, fn2W;
+    BOOL ret;
+
+    if (!fn1 || !fn2)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    RtlCreateUnicodeStringFromAsciiz(&fn1W, fn1);
+    RtlCreateUnicodeStringFromAsciiz(&fn2W, fn2);
+
+    ret = MoveFileW( fn1W.Buffer, fn2W.Buffer );
+
+    RtlFreeUnicodeString(&fn1W);
+    RtlFreeUnicodeString(&fn2W);
+    return ret;
 }
 
 
 /**************************************************************************
- *           CopyFileA   (KERNEL32.36)
+ *           CopyFileW   (KERNEL32.@)
  */
-BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists )
+BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists )
 {
-    HFILE h1, h2;
+    HANDLE h1, h2;
     BY_HANDLE_FILE_INFORMATION info;
-    UINT count;
+    DWORD count;
     BOOL ret = FALSE;
-    int mode;
     char buffer[2048];
 
-    if ((h1 = _lopen( source, OF_READ )) == HFILE_ERROR) return FALSE;
+    if (!source || !dest)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    TRACE("%s -> %s\n", debugstr_w(source), debugstr_w(dest));
+
+    if ((h1 = CreateFileW(source, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
+    {
+        WARN("Unable to open source %s\n", debugstr_w(source));
+        return FALSE;
+    }
+
     if (!GetFileInformationByHandle( h1, &info ))
     {
+        WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source));
         CloseHandle( h1 );
         return FALSE;
     }
-    mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
-    if ((h2 = CreateFileA( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+
+    if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                              fail_if_exists ? CREATE_NEW : CREATE_ALWAYS,
                              info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE)
     {
+        WARN("Unable to open dest %s\n", debugstr_w(dest));
         CloseHandle( h1 );
         return FALSE;
     }
-    while ((count = _lread( h1, buffer, sizeof(buffer) )) > 0)
+
+    while (ReadFile( h1, buffer, sizeof(buffer), &count, NULL ) && count)
     {
         char *p = buffer;
-        while (count > 0)
+        while (count != 0)
         {
-            INT res = _lwrite( h2, p, count );
-            if (res <= 0) goto done;
+            DWORD res;
+            if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
             p += res;
             count -= res;
         }
@@ -2114,75 +2947,77 @@ done:
 
 
 /**************************************************************************
- *           CopyFileW   (KERNEL32.37)
+ *           CopyFileA   (KERNEL32.@)
  */
-BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists)
+BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists)
 {
-    LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
-    LPSTR destA   = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
-    BOOL ret = CopyFileA( sourceA, destA, fail_if_exists );
-    HeapFree( GetProcessHeap(), 0, sourceA );
-    HeapFree( GetProcessHeap(), 0, destA );
+    UNICODE_STRING sourceW, destW;
+    BOOL ret;
+
+    if (!source || !dest)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    RtlCreateUnicodeStringFromAsciiz(&sourceW, source);
+    RtlCreateUnicodeStringFromAsciiz(&destW, dest);
+
+    ret = CopyFileW(sourceW.Buffer, destW.Buffer, fail_if_exists);
+
+    RtlFreeUnicodeString(&sourceW);
+    RtlFreeUnicodeString(&destW);
     return ret;
 }
 
 
 /**************************************************************************
- *           CopyFileExA   (KERNEL32.858)
+ *           CopyFileExW   (KERNEL32.@)
  *
  * This implementation ignores most of the extra parameters passed-in into
  * the "ex" version of the method and calls the CopyFile method.
  * It will have to be fixed eventually.
  */
-BOOL WINAPI CopyFileExA(LPCSTR             sourceFilename,
-                           LPCSTR             destFilename,
-                           LPPROGRESS_ROUTINE progressRoutine,
-                           LPVOID             appData,
-                           LPBOOL           cancelFlagPointer,
-                           DWORD              copyFlags)
-{
-  BOOL failIfExists = FALSE;
-
-  /*
-   * Interpret the only flag that CopyFile can interpret.
-   */
-  if ( (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0)
-  {
-    failIfExists = TRUE;
-  }
-
-  return CopyFileA(sourceFilename, destFilename, failIfExists);
+BOOL WINAPI CopyFileExW(LPCWSTR sourceFilename, LPCWSTR destFilename,
+                        LPPROGRESS_ROUTINE progressRoutine, LPVOID appData,
+                        LPBOOL cancelFlagPointer, DWORD copyFlags)
+{
+    /*
+     * Interpret the only flag that CopyFile can interpret.
+     */
+    return CopyFileW(sourceFilename, destFilename, (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0);
 }
 
 /**************************************************************************
- *           CopyFileExW   (KERNEL32.859)
+ *           CopyFileExA   (KERNEL32.@)
  */
-BOOL WINAPI CopyFileExW(LPCWSTR            sourceFilename,
-                           LPCWSTR            destFilename,
-                           LPPROGRESS_ROUTINE progressRoutine,
-                           LPVOID             appData,
-                           LPBOOL           cancelFlagPointer,
-                           DWORD              copyFlags)
+BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename,
+                        LPPROGRESS_ROUTINE progressRoutine, LPVOID appData,
+                        LPBOOL cancelFlagPointer, DWORD copyFlags)
 {
-    LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, sourceFilename );
-    LPSTR destA   = HEAP_strdupWtoA( GetProcessHeap(), 0, destFilename );
+    UNICODE_STRING sourceW, destW;
+    BOOL ret;
+
+    if (!sourceFilename || !destFilename)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-    BOOL ret = CopyFileExA(sourceA,
-                              destA,
-                              progressRoutine,
-                              appData,
-                              cancelFlagPointer,
-                              copyFlags);
+    RtlCreateUnicodeStringFromAsciiz(&sourceW, sourceFilename);
+    RtlCreateUnicodeStringFromAsciiz(&destW, destFilename);
 
-    HeapFree( GetProcessHeap(), 0, sourceA );
-    HeapFree( GetProcessHeap(), 0, destA );
+    ret = CopyFileExW(sourceW.Buffer, destW.Buffer, progressRoutine, appData,
+                      cancelFlagPointer, copyFlags);
 
+    RtlFreeUnicodeString(&sourceW);
+    RtlFreeUnicodeString(&destW);
     return ret;
 }
 
 
 /***********************************************************************
- *              SetFileTime   (KERNEL32.650)
+ *              SetFileTime   (KERNEL32.@)
  */
 BOOL WINAPI SetFileTime( HANDLE hFile,
                            const FILETIME *lpCreationTime,
@@ -2194,14 +3029,14 @@ BOOL WINAPI SetFileTime( HANDLE hFile,
     {
         req->handle = hFile;
         if (lpLastAccessTime)
-            RtlTimeToSecondsSince1970( lpLastAccessTime, (DWORD *)&req->access_time );
+            RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastAccessTime, (DWORD *)&req->access_time );
         else
             req->access_time = 0; /* FIXME */
         if (lpLastWriteTime)
-            RtlTimeToSecondsSince1970( lpLastWriteTime, (DWORD *)&req->write_time );
+            RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastWriteTime, (DWORD *)&req->write_time );
         else
             req->write_time = 0; /* FIXME */
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2209,12 +3044,15 @@ BOOL WINAPI SetFileTime( HANDLE hFile,
 
 
 /**************************************************************************
- *           LockFile   (KERNEL32.511)
+ *           LockFile   (KERNEL32.@)
  */
 BOOL WINAPI LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
                         DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
 {
     BOOL ret;
+
+    FIXME("not implemented in server\n");
+
     SERVER_START_REQ( lock_file )
     {
         req->handle      = hFile;
@@ -2222,14 +3060,14 @@ BOOL WINAPI LockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHig
         req->offset_high = dwFileOffsetHigh;
         req->count_low   = nNumberOfBytesToLockLow;
         req->count_high  = nNumberOfBytesToLockHigh;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
 }
 
 /**************************************************************************
- * LockFileEx [KERNEL32.512]
+ * LockFileEx [KERNEL32.@]
  *
  * Locks a byte range within an open file for shared or exclusive access.
  *
@@ -2260,12 +3098,15 @@ BOOL WINAPI LockFileEx( HANDLE hFile, DWORD flags, DWORD reserved,
 
 
 /**************************************************************************
- *           UnlockFile   (KERNEL32.703)
+ *           UnlockFile   (KERNEL32.@)
  */
 BOOL WINAPI UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
                           DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
 {
     BOOL ret;
+
+    FIXME("not implemented in server\n");
+
     SERVER_START_REQ( unlock_file )
     {
         req->handle      = hFile;
@@ -2273,7 +3114,7 @@ BOOL WINAPI UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetH
         req->offset_high = dwFileOffsetHigh;
         req->count_low   = nNumberOfBytesToUnlockLow;
         req->count_high  = nNumberOfBytesToUnlockHigh;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2281,10 +3122,10 @@ BOOL WINAPI UnlockFile( HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetH
 
 
 /**************************************************************************
- *           UnlockFileEx   (KERNEL32.705)
+ *           UnlockFileEx   (KERNEL32.@)
  */
 BOOL WINAPI UnlockFileEx(
-               HFILE hFile,
+               HANDLE hFile,
                DWORD dwReserved,
                DWORD nNumberOfBytesToUnlockLow,
                DWORD nNumberOfBytesToUnlockHigh,
@@ -2409,10 +3250,10 @@ static BOOL DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
 
 
 /**************************************************************************
- *           LockFile   (KERNEL32.511)
+ *           LockFile   (KERNEL32.@)
  */
 BOOL WINAPI LockFile(
-       HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
+       HANDLE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
        DWORD nNumberOfBytesToLockLow,DWORD nNumberOfBytesToLockHigh )
 {
   struct flock f;
@@ -2460,10 +3301,10 @@ BOOL WINAPI LockFile(
 
 
 /**************************************************************************
- *           UnlockFile   (KERNEL32.703)
+ *           UnlockFile   (KERNEL32.@)
  */
 BOOL WINAPI UnlockFile(
-       HFILE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
+       HANDLE hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
        DWORD nNumberOfBytesToUnlockLow,DWORD nNumberOfBytesToUnlockHigh )
 {
   FILE_OBJECT *file;
@@ -2500,20 +3341,23 @@ BOOL WINAPI UnlockFile(
 #endif
 
 /**************************************************************************
- * GetFileAttributesExA [KERNEL32.874]
+ *           GetFileAttributesExW   (KERNEL32.@)
  */
-BOOL WINAPI GetFileAttributesExA(
-       LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+BOOL WINAPI GetFileAttributesExW(
+       LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
        LPVOID lpFileInformation)
 {
     DOS_FULL_NAME full_name;
     BY_HANDLE_FILE_INFORMATION info;
-    
-    if (lpFileName == NULL) return FALSE;
-    if (lpFileInformation == NULL) return FALSE;
+
+    if (!lpFileName || !lpFileInformation)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
     if (fInfoLevelId == GetFileExInfoStandard) {
-       LPWIN32_FILE_ATTRIBUTE_DATA lpFad = 
+       LPWIN32_FILE_ATTRIBUTE_DATA lpFad =
            (LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
        if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name )) return FALSE;
        if (!FILE_Stat( full_name.long_name, &info )) return FALSE;
@@ -2535,15 +3379,27 @@ BOOL WINAPI GetFileAttributesExA(
 
 
 /**************************************************************************
- * GetFileAttributesExW [KERNEL32.875]
+ *           GetFileAttributesExA   (KERNEL32.@)
  */
-BOOL WINAPI GetFileAttributesExW(
-       LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+BOOL WINAPI GetFileAttributesExA(
+       LPCSTR filename, GET_FILEEX_INFO_LEVELS fInfoLevelId,
        LPVOID lpFileInformation)
 {
-    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFileName );
-    BOOL res = 
-       GetFileAttributesExA( nameA, fInfoLevelId, lpFileInformation);
-    HeapFree( GetProcessHeap(), 0, nameA );
-    return res;
+    UNICODE_STRING filenameW;
+    BOOL ret = FALSE;
+
+    if (!filename || !lpFileInformation)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (RtlCreateUnicodeStringFromAsciiz(&filenameW, filename))
+    {
+        ret = GetFileAttributesExW(filenameW.Buffer, fInfoLevelId, lpFileInformation);
+        RtlFreeUnicodeString(&filenameW);
+    }
+    else
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return ret;
 }