ntdll/kernel32: #30

Eric Pouech pouech-eric at wanadoo.fr
Tue Jun 24 15:13:48 CDT 2003


(here it comes)

ChangeLog:
- made async.h ready for use in ntdll
	+ moved it to include/wine
	+ replaced all calls to kernel32 functions with ntdll equivalent
- replaced status setter/getter for wine async structures with direct 
access to a (now included) IO_STATUS_BLOCK structure
- since we now have a IO_STATUS_BLOCK in async_private, we no longer 
need in most of the user (derivated) structures a field for LPOVERLAPPED 
(it's stored as the IO_STATUS_BLOCK)
- rewrote the async.h users accordingly
- implemented ntdll.Nt{Read|Write}File and let 
kernel32.{Read|Write}File(Ex)? use those new ntdll functions
- rewrote smb read/write interfaces to be more ntdll stylish (no 
overlapped yet)

A+
-- 
Eric Pouech
-------------- next part --------------
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel29/comm.c dlls/kernel/comm.c
--- dlls/kernel29/comm.c	2003-03-15 08:44:52.000000000 +0100
+++ dlls/kernel/comm.c	2003-06-07 11:00:00.000000000 +0200
@@ -84,11 +84,13 @@
 # include <sys/strtio.h>
 #endif
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "winbase.h"
 #include "winerror.h"
 
 #include "wine/server.h"
-#include "async.h"
+#include "wine/async.h"
 #include "file.h"
 #include "heap.h"
 
@@ -104,15 +106,11 @@
  * Asynchronous I/O for asynchronous wait requests                     *
  */
 
-static DWORD commio_get_async_status (const async_private *ovp);
 static DWORD commio_get_async_count (const async_private *ovp);
-static void commio_set_async_status (async_private *ovp, const DWORD status);
 static void commio_async_cleanup  (async_private *ovp);
 
 static async_ops commio_async_ops =
 {
-    commio_get_async_status,       /* get_status */
-    commio_set_async_status,       /* set_status */
     commio_get_async_count,        /* get_count */
     NULL,                          /* call_completion */
     commio_async_cleanup           /* cleanup */
@@ -121,20 +119,9 @@
 typedef struct async_commio
 {
     struct async_private             async;
-    LPOVERLAPPED                     lpOverlapped;
     char                             *buffer;
 } async_commio;
 
-static DWORD commio_get_async_status (const struct async_private *ovp)
-{
-    return ((async_commio*) ovp)->lpOverlapped->Internal;
-}
-
-static void commio_set_async_status (async_private *ovp, const DWORD status)
-{
-    ((async_commio*) ovp)->lpOverlapped->Internal = status;
-}
-
 static DWORD commio_get_async_count (const struct async_private *ovp)
 {
     return 0;
@@ -1664,14 +1651,14 @@
 static void COMM_WaitCommEventService(async_private *ovp)
 {
     async_commio *commio = (async_commio*) ovp;
-    LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
+    IO_STATUS_BLOCK* iosb = commio->async.iosb;
 
-    TRACE("overlapped %p\n",lpOverlapped);
+    TRACE("iosb %p\n",iosb);
 
     /* FIXME: detect other events */
     *commio->buffer = EV_RXCHAR;
 
-    lpOverlapped->Internal = STATUS_SUCCESS;
+    iosb->u.Status = STATUS_SUCCESS;
 }
 
 
@@ -1714,7 +1701,7 @@
     ovp->async.type = ASYNC_TYPE_WAIT;
     ovp->async.func = COMM_WaitCommEventService;
     ovp->async.event = lpOverlapped->hEvent;
-    ovp->lpOverlapped = lpOverlapped;
+    ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
     ovp->buffer = (char *)lpdwEvents;
 
     lpOverlapped->InternalHigh = 0;
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel29/file.c dlls/kernel/file.c
--- dlls/kernel29/file.c	2003-06-24 19:22:51.000000000 +0200
+++ dlls/kernel/file.c	2003-06-24 21:22:15.000000000 +0200
@@ -32,11 +32,12 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winternl.h"
-
+#include "wincon.h"
 #include "kernel_private.h"
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
+#include "wine/async.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(file);
 
@@ -45,6 +46,106 @@
  **************************************************************************/
 
 /***********************************************************************
+ *              GetOverlappedResult     (KERNEL32.@)
+ *
+ * Check the result of an Asynchronous data transfer from a file.
+ *
+ * Parameters
+ *   HANDLE hFile                 [in] handle of file to check on
+ *   LPOVERLAPPED lpOverlapped    [in/out] pointer to overlapped
+ *   LPDWORD lpTransferred        [in/out] number of bytes transferred
+ *   BOOL bWait                   [in] wait for the transfer to complete ?
+ *
+ * RETURNS
+ *   TRUE on success
+ *   FALSE on failure
+ *
+ *  If successful (and relevant) lpTransferred will hold the number of
+ *   bytes transferred during the async operation.
+ *
+ * BUGS
+ *
+ * Currently only works for WaitCommEvent, ReadFile, WriteFile
+ *   with communications ports.
+ *
+ */
+BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
+                                LPDWORD lpTransferred, BOOL bWait)
+{
+    DWORD r;
+
+    TRACE("(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait);
+
+    if (lpOverlapped==NULL)
+    {
+        ERR("lpOverlapped was null\n");
+        return FALSE;
+    }
+    if (!lpOverlapped->hEvent)
+    {
+        ERR("lpOverlapped->hEvent was null\n");
+        return FALSE;
+    }
+
+    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;
+
+    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 = %p\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;
+}
+
+/***********************************************************************
  *           _hread   (KERNEL32.@)
  */
 LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll29/file.c dlls/ntdll/file.c
--- dlls/ntdll29/file.c	2003-06-24 21:41:18.000000000 +0200
+++ dlls/ntdll/file.c	2003-06-24 21:55:27.000000000 +0200
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
+#include <assert.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -35,15 +36,16 @@
 #include "wine/unicode.h"
 #include "wine/debug.h"
 #include "wine/server.h"
+#include "wine/async.h"
 #include "ntdll_misc.h"
 #include "file.h" /* FIXME */
+#include "../files/smb.h"
 
 #include "winternl.h"
 #include "winioctl.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
-
 /**************************************************************************
  *                 NtOpenFile				[NTDLL.@]
  *                 ZwOpenFile				[NTDLL.@]
@@ -154,31 +156,175 @@
     return 0;
 }
 
-/* set the last error depending on errno */
-NTSTATUS NTFILE_errno_to_status(int val)
+/***********************************************************************
+ *                  Asynchronous file I/O                              *
+ */
+static DWORD fileio_get_async_count(const async_private *ovp);
+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_count,        /* get_count */
+    fileio_call_completion_func,   /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+static async_ops fileio_nocomp_async_ops =
+{
+    fileio_get_async_count,        /* get_count */
+    NULL,                          /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+typedef struct async_fileio
+{
+    struct async_private             async;
+    PIO_APC_ROUTINE                  apc;
+    void*                            apc_user;
+    char                             *buffer;
+    unsigned int                     count;
+    unsigned long                    offset;
+    enum fd_type                     fd_type;
+} async_fileio;
+
+static DWORD fileio_get_async_count(const struct async_private *ovp)
+{
+    async_fileio *fileio = (async_fileio*) ovp;
+
+    if (fileio->count < fileio->async.iosb->Information)
+    	return 0;
+    return fileio->count - fileio->async.iosb->Information;
+}
+
+static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
 {
-    switch (val)
+    async_fileio *ovp = (async_fileio*) data;
+    TRACE("data: %p\n", ovp);
+
+    ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
+
+    fileio_async_cleanup( &ovp->async );
+}
+
+static void fileio_async_cleanup( struct async_private *ovp )
+{
+    RtlFreeHeap( ntdll_get_process_heap(), 0, ovp );
+}
+
+/***********************************************************************
+ *           FILE_GetUnixHandleType
+ *
+ * Retrieve the Unix handle corresponding to a file handle.
+ * Returns -1 on failure.
+ */
+static int FILE_GetUnixHandleType( HANDLE handle, DWORD access, enum fd_type *type, int *flags_ptr, int *fd )
+{
+    int ret, flags;
+
+    *fd = -1;
+    ret = wine_server_handle_to_fd( handle, access, fd, type, &flags );
+    if (flags_ptr) *flags_ptr = flags;
+    if (!ret && (((access & GENERIC_READ)  && (flags & FD_FLAG_RECV_SHUTDOWN)) ||
+                 ((access & GENERIC_WRITE) && (flags & FD_FLAG_SEND_SHUTDOWN))))
     {
-    case EAGAIN:    return ( STATUS_SHARING_VIOLATION );
-    case ESPIPE:
-    case EBADF:     return ( STATUS_INVALID_HANDLE );
-    case ENOSPC:    return ( STATUS_DISK_FULL );
-    case EACCES:
-    case ESRCH:
-    case EPERM:     return ( STATUS_ACCESS_DENIED );
-    case EROFS:     return ( STATUS_MEDIA_WRITE_PROTECTED );
-    case EBUSY:     return ( STATUS_FILE_LOCK_CONFLICT );
-    case ENOENT:    return ( STATUS_NO_SUCH_FILE );
-    case EISDIR:    return ( STATUS_FILE_IS_A_DIRECTORY );
-    case ENFILE:
-    case EMFILE:    return ( STATUS_NO_MORE_FILES );
-    case EEXIST:    return ( STATUS_OBJECT_NAME_COLLISION );
-    case EINVAL:    return ( STATUS_INVALID_PARAMETER );
-    case ENOTEMPTY: return ( STATUS_DIRECTORY_NOT_EMPTY );
-    case EIO:       return ( STATUS_ACCESS_VIOLATION );
+        close(*fd);
+        ret = STATUS_PIPE_DISCONNECTED;
     }
-    perror("file_set_error");
-    return ( STATUS_INVALID_PARAMETER );
+    return ret;
+}
+
+/***********************************************************************
+ *           FILE_GetNtStatus(void)
+ *
+ * Retrieve the Nt Status code from errno.
+ * Try to be consistent with FILE_SetDosError().
+ */
+static 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_AsyncReadService      (INTERNAL)
+ *
+ *  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)
+{
+    async_fileio *fileio = (async_fileio*) ovp;
+    IO_STATUS_BLOCK*  io_status = fileio->async.iosb;
+    int result;
+    int already = io_status->Information;
+
+    TRACE("%p %p\n", io_status, fileio->buffer );
+
+    /* check to see if the data is ready (non-blocking) */
+
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
+        result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
+    {
+        result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
+                       fileio->offset + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    }
+
+    if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+    {
+        TRACE("Deferred read %d\n",errno);
+        io_status->u.Status = STATUS_PENDING;
+        return;
+    }
+
+    /* check to see if the transfer is complete */
+    if (result < 0)
+    {
+        io_status->u.Status = FILE_GetNtStatus();
+        return;
+    }
+    else if (result == 0)
+    {
+        io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
+        return;
+    }
+
+    io_status->Information += result;
+    if (io_status->Information >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
+        io_status->u.Status = STATUS_SUCCESS;
+    else
+        io_status->u.Status = STATUS_PENDING;
+
+    TRACE("read %d more bytes %ld/%d so far\n",
+          result, io_status->Information, fileio->count);
 }
 
 
@@ -187,67 +333,163 @@
  *  ZwReadFile					[NTDLL.@]
  *
  * Parameters
- *   HANDLE32 		FileHandle
- *   HANDLE32 		Event 		OPTIONAL
- *   PIO_APC_ROUTINE 	ApcRoutine 	OPTIONAL
- *   PVOID 		ApcContext 	OPTIONAL
- *   PIO_STATUS_BLOCK 	IoStatusBlock
- *   PVOID 		Buffer
- *   ULONG 		Length
- *   PLARGE_INTEGER 	ByteOffset 	OPTIONAL
- *   PULONG 		Key 		OPTIONAL
+ *   HANDLE32 		hFile
+ *   HANDLE32 		hEvent 		OPTIONAL
+ *   PIO_APC_ROUTINE 	apc      	OPTIONAL
+ *   PVOID 		apc_user 	OPTIONAL
+ *   PIO_STATUS_BLOCK 	io_status
+ *   PVOID 		buffer
+ *   ULONG 		length
+ *   PLARGE_INTEGER 	offset   	OPTIONAL
+ *   PULONG 		key 		OPTIONAL
  *
  * IoStatusBlock->Information contains the number of bytes read on return.
  */
-NTSTATUS WINAPI NtReadFile (
-	HANDLE FileHandle,
-	HANDLE EventHandle,
-	PIO_APC_ROUTINE ApcRoutine,
-	PVOID ApcContext,
-	PIO_STATUS_BLOCK IoStatusBlock,
-	PVOID Buffer,
-	ULONG Length,
-	PLARGE_INTEGER ByteOffset,
-	PULONG Key)
+NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, 
+                           PIO_APC_ROUTINE apc, void* apc_user, 
+                           PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
+                           PLARGE_INTEGER offset, PULONG key)
 {
-	int fd, result, flags, ret;
-	enum fd_type type;
+    int unix_handle, flags;
+    enum fd_type type;
 
-	FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
-		FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
+    TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
+          hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
 
-	if (IsBadWritePtr( Buffer, Length ) ||
-	    IsBadWritePtr( IoStatusBlock, sizeof(*IoStatusBlock)) ||
-	    IsBadWritePtr( ByteOffset, sizeof(*ByteOffset)) )
-		return STATUS_ACCESS_VIOLATION;
+    io_status->Information = 0;
+    io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags, &unix_handle );
+    if (io_status->u.Status) return io_status->u.Status;
 
-	IoStatusBlock->Information = 0;
+    if (flags & FD_FLAG_TIMEOUT)
+    {
+        if (hEvent)
+        {
+            /* this shouldn't happen, but check it */
+            FIXME("NIY-hEvent\n");
+            return STATUS_NOT_IMPLEMENTED;
+        }
+        io_status->u.Status = NtCreateEvent(&hEvent, SYNCHRONIZE, NULL, 0, 0);
+        if (io_status->u.Status) return io_status->u.Status;
+    }
+        
+    if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
+    {
+        async_fileio*   ovp;
 
-	ret = wine_server_handle_to_fd( FileHandle, GENERIC_READ, &fd, &type, &flags );
-	if(ret)
-		return ret;
+        if (unix_handle < 0) return STATUS_INVALID_HANDLE;
 
-	/* FIXME: this code only does synchronous reads so far */
+        ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio));
+        if (!ovp) return STATUS_NO_MEMORY;
 
-	/* FIXME: depending on how libc implements this, between two processes
-	      there could be a race condition between the seek and read here */
-	do
-	{
-               	result = pread( fd, Buffer, Length, ByteOffset->QuadPart);
-	}
-	while ( (result == -1) && ((errno == EAGAIN) || (errno == EINTR)) );
+        ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
+        ovp->async.handle = hFile;
+        ovp->async.fd = unix_handle;
+        ovp->async.type = ASYNC_TYPE_READ;
+        ovp->async.func = FILE_AsyncReadService;
+        ovp->async.event = hEvent;
+        ovp->async.iosb = io_status;
+        ovp->count = length;
+        ovp->offset = offset->s.LowPart;
+        if (offset->s.HighPart) FIXME("NIY-high part\n");
+        ovp->apc = apc;
+        ovp->apc_user = apc_user;
+        ovp->buffer = buffer;
+        ovp->fd_type = type;
+
+        io_status->Information = 0;
+        io_status->u.Status = register_new_async(&ovp->async);
+        if (io_status->u.Status == STATUS_PENDING && hEvent)
+        {
+            finish_async(&ovp->async);
+            close(unix_handle);
+        }
+        return io_status->u.Status;
+    }
+    switch (type)
+    {
+    case FD_TYPE_SMB:
+        FIXME("NIY-SMB\n");
+        close(unix_handle);
+        return SMB_ReadFile(hFile, buffer, length, io_status);
+
+    case FD_TYPE_DEFAULT:
+        /* normal unix files */
+        if (unix_handle == -1) return STATUS_INVALID_HANDLE;
+        break;
 
-	close( fd );
+    default:
+        FIXME("Unsupported type of fd %d\n", type);
+	if (unix_handle == -1) close(unix_handle);
+        return STATUS_INVALID_HANDLE;
+    }
 
-	if (result == -1)
-	{
-		return IoStatusBlock->u.Status = NTFILE_errno_to_status(errno);
-	}
+    if (offset)
+    {
+        FILE_POSITION_INFORMATION   fpi;
 
-	IoStatusBlock->Information = result;
-	IoStatusBlock->u.Status = 0;
+        fpi.CurrentByteOffset = *offset;
+        io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi), 
+                                                   FilePositionInformation);
+        if (io_status->u.Status)
+        {
+            close(unix_handle);
+            return io_status->u.Status;
+        }
+    }
+    /* code for synchronous reads */
+    while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
+    {
+	if ((errno == EAGAIN) || (errno == EINTR) || (errno == EFAULT)) continue;
+	io_status->u.Status = FILE_GetNtStatus();
+	break;
+    }
+    close( unix_handle );
+    return io_status->u.Status;
+}
 
-	return STATUS_SUCCESS;
+/***********************************************************************
+ *             FILE_AsyncWriteService      (INTERNAL)
+ *
+ *  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)
+{
+    async_fileio *fileio = (async_fileio *) ovp;
+    PIO_STATUS_BLOCK io_status = fileio->async.iosb;
+    int result;
+    int already = io_status->Information;
+
+    TRACE("(%p %p)\n",io_status,fileio->buffer);
+
+    /* write some data (non-blocking) */
+
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
+        result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
+    {
+        result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
+                        fileio->offset + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    }
+
+    if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+    {
+        io_status->u.Status = STATUS_PENDING;
+        return;
+    }
+
+    /* check to see if the transfer is complete */
+    if (result < 0)
+    {
+        io_status->u.Status = FILE_GetNtStatus();
+        return;
+    }
+
+    io_status->Information += result;
+    io_status->u.Status = (io_status->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
+    TRACE("wrote %d more bytes %ld/%d so far\n",result,io_status->Information,fileio->count);
 }
 
 /******************************************************************************
@@ -255,30 +497,111 @@
  *  ZwWriteFile					[NTDLL.@]
  *
  * Parameters
- *   HANDLE32 		FileHandle
- *   HANDLE32 		Event 		OPTIONAL
- *   PIO_APC_ROUTINE 	ApcRoutine 	OPTIONAL
- *   PVOID 		ApcContext 	OPTIONAL
- *   PIO_STATUS_BLOCK 	IoStatusBlock
- *   PVOID 		Buffer
- *   ULONG 		Length
- *   PLARGE_INTEGER 	ByteOffset 	OPTIONAL
- *   PULONG 		Key 		OPTIONAL
- */
-NTSTATUS WINAPI NtWriteFile (
-	HANDLE FileHandle,
-	HANDLE EventHandle,
-	PIO_APC_ROUTINE ApcRoutine,
-	PVOID ApcContext,
-	PIO_STATUS_BLOCK IoStatusBlock,
-	PVOID Buffer,
-	ULONG Length,
-	PLARGE_INTEGER ByteOffset,
-	PULONG Key)
+ *   HANDLE32 		hFile
+ *   HANDLE32 		hEvent 		OPTIONAL
+ *   PIO_APC_ROUTINE 	apc      	OPTIONAL
+ *   PVOID 		apc_user 	OPTIONAL
+ *   PIO_STATUS_BLOCK 	io_status
+ *   PVOID 		buffer
+ *   ULONG 		length
+ *   PLARGE_INTEGER 	offset   	OPTIONAL
+ *   PULONG 		key 		OPTIONAL
+ */
+NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
+                            PIO_APC_ROUTINE apc, void* apc_user,
+                            PIO_STATUS_BLOCK io_status, 
+                            const void* buffer, ULONG length,
+                            PLARGE_INTEGER offset, PULONG key)
 {
-	FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),stub!\n",
-	FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
-	return 0;
+    int unix_handle, flags;
+    enum fd_type type;
+
+    TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
+          hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
+
+    TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
+          hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
+
+    io_status->Information = 0;
+
+    io_status->u.Status = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags, &unix_handle );
+    if (io_status->u.Status) return io_status->u.Status;
+
+    if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
+    {
+        async_fileio*   ovp;
+
+        if (unix_handle < 0) return STATUS_INVALID_HANDLE;
+
+        ovp = RtlAllocateHeap(ntdll_get_process_heap(), 0, sizeof(async_fileio));
+        if (!ovp) return STATUS_NO_MEMORY;
+
+        ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
+        ovp->async.handle = hFile;
+        ovp->async.fd = unix_handle;
+        ovp->async.type = ASYNC_TYPE_WRITE;
+        ovp->async.func = FILE_AsyncWriteService;
+        ovp->async.event = hEvent;
+        ovp->async.iosb = io_status;
+        ovp->count = length;
+        ovp->offset = offset->s.LowPart;
+        if (offset->s.HighPart) FIXME("NIY-high part\n");
+        ovp->apc = apc;
+        ovp->apc_user = apc_user;
+        ovp->buffer = (void*)buffer;
+        ovp->fd_type = type;
+
+        io_status->Information = 0;
+        io_status->u.Status = register_new_async(&ovp->async);
+        if (io_status->u.Status == STATUS_PENDING && hEvent)
+        {
+            finish_async(&ovp->async);
+            close(unix_handle);
+        }
+        return io_status->u.Status;
+    }
+    switch (type)
+    {
+    case FD_TYPE_SMB:
+        FIXME("NIY-SMB\n");
+        close(unix_handle);
+        return STATUS_NOT_IMPLEMENTED;
+
+    case FD_TYPE_DEFAULT:
+        /* normal unix files */
+        if (unix_handle == -1) return STATUS_INVALID_HANDLE;
+        break;
+
+    default:
+        FIXME("Unsupported type of fd %d\n", type);
+	if (unix_handle == -1) close(unix_handle);
+        return STATUS_INVALID_HANDLE;
+    }
+
+    if (offset)
+    {
+        FILE_POSITION_INFORMATION   fpi;
+
+        fpi.CurrentByteOffset = *offset;
+        io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi), 
+                                                   FilePositionInformation);
+        if (io_status->u.Status)
+        {
+            close(unix_handle);
+            return io_status->u.Status;
+        }
+    }
+
+    /* synchronous file write */
+    while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
+    {
+        if ((errno == EAGAIN) || (errno == EINTR) || (errno == EFAULT)) continue;
+        if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
+        else io_status->u.Status = FILE_GetNtStatus();
+        break;
+    }
+    close( unix_handle );
+    return io_status->u.Status;
 }
 
 /**************************************************************************
@@ -665,7 +988,7 @@
         hEvent = reply->event;
     }
     SERVER_END_REQ;
-    if( !ret && hEvent )
+    if (!ret && hEvent)
     {
         ret = NtWaitForSingleObject( hEvent, FALSE, NULL );
         NtClose( hEvent );
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/ntdll29/sync.c dlls/ntdll/sync.c
--- dlls/ntdll29/sync.c	2003-06-21 10:24:20.000000000 +0200
+++ dlls/ntdll/sync.c	2003-06-07 10:24:38.000000000 +0200
@@ -44,7 +44,7 @@
 #define NONAMELESSSTRUCT
 
 #include "winternl.h"
-#include "async.h"
+#include "wine/async.h"
 #include "thread.h"
 #include "wine/server.h"
 #include "wine/unicode.h"
@@ -446,9 +446,9 @@
     if( status != STATUS_ALERTED )
     {
         ovp_status = status;
-        ovp->ops->set_status (ovp, status);
+        ovp->iosb->u.Status = status;
     }
-    else ovp_status = ovp->ops->get_status (ovp);
+    else ovp_status = ovp->iosb->u.Status;
 
     if( ovp_status == STATUS_PENDING ) ovp->func( ovp );
 
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/winsock29/socket.c dlls/winsock/socket.c
--- dlls/winsock29/socket.c	2003-06-21 10:24:46.000000000 +0200
+++ dlls/winsock/socket.c	2003-06-21 14:30:52.000000000 +0200
@@ -107,6 +107,8 @@
 # include <sys/time.h>
 #endif
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "wine/winbase16.h"
 #include "wingdi.h"
 #include "winuser.h"
@@ -145,18 +147,14 @@
 /****************************************************************
  * Async IO declarations
  ****************************************************************/
-#include "async.h"
+#include "wine/async.h"
 
-static DWORD ws2_async_get_status (const struct async_private *ovp);
 static DWORD ws2_async_get_count  (const struct async_private *ovp);
-static void  ws2_async_set_status (struct async_private *ovp, const DWORD status);
 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
 static void ws2_async_cleanup ( struct async_private *ovp );
 
 static struct async_ops ws2_async_ops =
 {
-    ws2_async_get_status,
-    ws2_async_set_status,
     ws2_async_get_count,
     ws2_async_call_completion,
     ws2_async_cleanup
@@ -164,8 +162,6 @@
 
 static struct async_ops ws2_nocomp_async_ops =
 {
-    ws2_async_get_status,
-    ws2_async_set_status,
     ws2_async_get_count,
     NULL,                     /* call_completion */
     ws2_async_cleanup
@@ -174,12 +170,11 @@
 typedef struct ws2_async
 {
     async_private                       async;
-    LPWSAOVERLAPPED                     overlapped;
     LPWSAOVERLAPPED                     user_overlapped;
     LPWSAOVERLAPPED_COMPLETION_ROUTINE  completion_func;
     struct iovec                        *iovec;
     int                                 n_iovecs;
-    struct WS_sockaddr            *addr;
+    struct WS_sockaddr                  *addr;
     union {
         int val;     /* for send operations */
         int *ptr;    /* for recv operations */
@@ -1021,31 +1016,24 @@
  * Functions for handling overlapped I/O
  **************************************************************************/
 
-static DWORD ws2_async_get_status (const struct async_private *ovp)
-{
-    return ((ws2_async*) ovp)->overlapped->Internal;
-}
-
-static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
-{
-    ((ws2_async*) ovp)->overlapped->Internal = status;
-}
-
 static DWORD ws2_async_get_count (const struct async_private *ovp)
 {
-    return ((ws2_async*) ovp)->overlapped->InternalHigh;
+    return ovp->iosb->Information;
 }
 
 static void ws2_async_cleanup ( struct async_private *ap )
 {
     struct ws2_async *as = (struct ws2_async*) ap;
 
-    TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
+    TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
     if ( !as->user_overlapped )
     {
+#if 0
+        /* FIXME: I don't think this is really used */
         if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
             WSACloseEvent ( as->overlapped->hEvent  );
-        HeapFree ( GetProcessHeap(), 0, as->overlapped );
+#endif
+        HeapFree ( GetProcessHeap(), 0, as->async.iosb );
     }
 
     if ( as->iovec )
@@ -1060,8 +1048,8 @@
 
     TRACE ("data: %p\n", as);
 
-    as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
-                          as->overlapped->InternalHigh,
+    as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
+                          as->async.iosb->Information,
                           as->user_overlapped,
                           as->flags );
     ws2_async_cleanup ( &as->async );
@@ -1114,22 +1102,22 @@
 
     if ( lpOverlapped )
     {
-        wsa->overlapped = lpOverlapped;
+        wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
         wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
     }
     else
     {
-        wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
-                                      sizeof (WSAOVERLAPPED) );
-        if ( !wsa->overlapped )
+        wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
+                                      sizeof (IO_STATUS_BLOCK) );
+        if ( !wsa->async.iosb )
             goto error;
-        wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
+        wsa->async.event = INVALID_HANDLE_VALUE;
     }
 
-    wsa->overlapped->InternalHigh = 0;
-    TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
+    wsa->async.iosb->Information = 0;
+    TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
             wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
-            wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
+            wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
 
     return wsa;
 
@@ -1220,9 +1208,9 @@
 
     TRACE ( "async %p\n", wsa );
 
-    if ( wsa->overlapped->Internal != STATUS_PENDING )
+    if ( wsa->async.iosb->u.Status != STATUS_PENDING )
     {
-        TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+        TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
         return;
     }
 
@@ -1231,8 +1219,8 @@
 
     if (result >= 0)
     {
-        wsa->overlapped->Internal = STATUS_SUCCESS;
-        wsa->overlapped->InternalHigh = result;
+        wsa->async.iosb->u.Status = STATUS_SUCCESS;
+        wsa->async.iosb->Information = result;
         TRACE ( "received %d bytes\n", result );
         _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
         return;
@@ -1241,13 +1229,13 @@
     err = wsaErrno ();
     if ( err == WSAEINTR || err == WSAEWOULDBLOCK )  /* errno: EINTR / EAGAIN */
     {
-        wsa->overlapped->Internal = STATUS_PENDING;
+        wsa->async.iosb->u.Status = STATUS_PENDING;
         _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
         TRACE ( "still pending\n" );
     }
     else
     {
-        wsa->overlapped->Internal = err;
+        wsa->async.iosb->u.Status = err;
         TRACE ( "Error: %x\n", err );
     }
 }
@@ -1312,9 +1300,9 @@
 
     TRACE ( "async %p\n", wsa );
 
-    if ( wsa->overlapped->Internal != STATUS_PENDING )
+    if ( wsa->async.iosb->u.Status != STATUS_PENDING )
     {
-        TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+        TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
         return;
     }
 
@@ -1323,8 +1311,8 @@
 
     if (result >= 0)
     {
-        wsa->overlapped->Internal = STATUS_SUCCESS;
-        wsa->overlapped->InternalHigh = result;
+        wsa->async.iosb->u.Status = STATUS_SUCCESS;
+        wsa->async.iosb->Information = result;
         TRACE ( "sent %d bytes\n", result );
         _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
         return;
@@ -1333,7 +1321,7 @@
     err = wsaErrno ();
     if ( err == WSAEINTR )
     {
-        wsa->overlapped->Internal = STATUS_PENDING;
+        wsa->async.iosb->u.Status = STATUS_PENDING;
         _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
         TRACE ( "still pending\n" );
     }
@@ -1341,7 +1329,7 @@
     {
         /* We set the status to a winsock error code and check for that
            later in NtStatusToWSAError () */
-        wsa->overlapped->Internal = err;
+        wsa->async.iosb->u.Status = err;
         TRACE ( "Error: %x\n", err );
     }
 }
@@ -1370,9 +1358,9 @@
     }
 
     if ( err )
-        wsa->overlapped->Internal = wsaErrno ();
+        wsa->async.iosb->u.Status = wsaErrno ();
     else
-        wsa->overlapped->Internal = STATUS_SUCCESS;
+        wsa->async.iosb->u.Status = STATUS_SUCCESS;
 }
 
 /***********************************************************************
@@ -2461,7 +2449,7 @@
             err = NtStatusToWSAError ( ret );
 
             if ( !lpOverlapped )
-                HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+                HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
             HeapFree ( GetProcessHeap(), 0, wsa );
             goto err_free;
         }
@@ -3918,7 +3906,7 @@
             err = NtStatusToWSAError ( ret );
 
             if ( !lpOverlapped )
-                HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+                HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
             HeapFree ( GetProcessHeap(), 0, wsa );
             goto err_free;
         }
diff -u -N -r -x '*~' -x '.#*' -x CVS files29/file.c files/file.c
--- files29/file.c	2003-06-24 19:20:51.000000000 +0200
+++ files/file.c	2003-06-24 21:16:59.000000000 +0200
@@ -66,7 +66,6 @@
 
 #include "drive.h"
 #include "file.h"
-#include "async.h"
 #include "heap.h"
 #include "msdos.h"
 #include "wincon.h"
@@ -82,87 +81,9 @@
 #define MAP_ANON MAP_ANONYMOUS
 #endif
 
-/* Macro to derive file offset from OVERLAPPED struct */
-#define OVERLAPPED_OFFSET(overlapped) ((off_t) (overlapped)->Offset + ((off_t) (overlapped)->OffsetHigh << 32))
-
 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( RtlNtStatusToDosError ( 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
  *
@@ -218,42 +139,6 @@
 
 
 /***********************************************************************
- *           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
  *
  * Set the DOS error code from errno.
@@ -1533,575 +1418,180 @@
 }
 
 
-/***********************************************************************
- *              GetOverlappedResult     (KERNEL32.@)
- *
- * Check the result of an Asynchronous data transfer from a file.
- *
- * RETURNS
- *   TRUE on success
- *   FALSE on failure
- *
- *  If successful (and relevant) lpTransferred will hold the number of
- *   bytes transferred during the async operation.
- *
- * BUGS
+/******************************************************************
+ *		FILE_ReadWriteApc (internal)
  *
- * 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 transferred  */
-    BOOL bWait                 /* [in] wait for the transfer to complete ? */
-) {
-    DWORD r;
-
-    TRACE("(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait);
-
-    if(lpOverlapped==NULL)
-    {
-        ERR("lpOverlapped was null\n");
-        return FALSE;
-    }
-    if(!lpOverlapped->hEvent)
-    {
-        ERR("lpOverlapped->hEvent was null\n");
-        return FALSE;
-    }
-
-    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;
-
-    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)
+static void WINAPI      FILE_ReadWriteApc(void* apc_user, PIO_STATUS_BLOCK io_status, ULONG len)
 {
-    async_private *ovp,*t;
+    LPOVERLAPPED_COMPLETION_ROUTINE  cr = (LPOVERLAPPED_COMPLETION_ROUTINE)apc_user;
 
-    TRACE("handle = %p\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;
+    cr(RtlNtStatusToDosError(io_status->u.Status), len, (LPOVERLAPPED)io_status);
 }
 
 /***********************************************************************
- *             FILE_AsyncReadService      (INTERNAL)
- *
- *  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)
-{
-    async_fileio *fileio = (async_fileio*) ovp;
-    LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
-    int result, r;
-    int already = lpOverlapped->InternalHigh;
-
-    TRACE("%p %p\n", lpOverlapped, fileio->buffer );
-
-    /* check to see if the data is ready (non-blocking) */
-
-    if ( fileio->fd_type == FD_TYPE_SOCKET )
-        result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
-    else
-    {
-        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);
-    }
-
-    if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
-    {
-        TRACE("Deferred read %d\n",errno);
-        r = STATUS_PENDING;
-        goto async_end;
-    }
-
-    /* check to see if the transfer is complete */
-    if(result<0)
-    {
-        r = FILE_GetNtStatus ();
-        goto async_end;
-    }
-    else if ( result == 0 )
-    {
-        r = ( lpOverlapped->InternalHigh ? STATUS_SUCCESS : STATUS_END_OF_FILE );
-        goto async_end;
-    }
-
-    lpOverlapped->InternalHigh += result;
-    TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
-
-    if(lpOverlapped->InternalHigh >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
-        r = STATUS_SUCCESS;
-    else
-        r = STATUS_PENDING;
-
-async_end:
-    lpOverlapped->Internal = r;
-}
-
-/***********************************************************************
- *              FILE_ReadFileEx                (INTERNAL)
+ *              ReadFileEx                (KERNEL32.@)
  */
-static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
-			 LPOVERLAPPED overlapped,
-			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
-                         HANDLE hEvent)
+BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
+                       LPOVERLAPPED overlapped,
+                       LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
-    async_fileio *ovp;
-    int fd;
-    int flags;
-    enum fd_type type;
+    LARGE_INTEGER       offset;
+    NTSTATUS            status;
+    PIO_STATUS_BLOCK    io_status;
 
-    TRACE("file %p to buf %p num %ld %p func %p\n",
-	  hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
-
-    /* check that there is an overlapped struct */
-    if (overlapped==NULL)
+    if (!overlapped)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
-    if ( fd < 0 )
-    {
-        WARN ( "Couldn't get FD\n" );
-        return FALSE;
-    }
-
-    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_READ;
-    ovp->async.func = FILE_AsyncReadService;
-    ovp->async.event = hEvent;
-    ovp->lpOverlapped = overlapped;
-    ovp->count = bytesToRead;
-    ovp->completion_func = lpCompletionRoutine;
-    ovp->buffer = buffer;
-    ovp->fd_type = type;
-
-    return !register_new_async (&ovp->async);
-
-error:
-    close (fd);
-    return FALSE;
+    offset.s.LowPart = overlapped->Offset;
+    offset.s.HighPart = overlapped->OffsetHigh;
+    io_status = (PIO_STATUS_BLOCK)overlapped;
+    io_status->u.Status = STATUS_PENDING;
 
-}
+    status = NtReadFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine,
+                        io_status, buffer, bytesToRead, &offset, NULL);
 
-/***********************************************************************
- *              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("%p %p %ld %p\n", hFile, buffer, bytesToRead, bytesRead );
-
-    ZeroMemory(&ov, sizeof (OVERLAPPED));
-    if(STATUS_SUCCESS==NtCreateEvent(&ov.hEvent, SYNCHRONIZE, NULL, 0, 0))
+    if (status)
     {
-        if(FILE_ReadFileEx(hFile, buffer, bytesToRead, &ov, NULL, ov.hEvent))
-        {
-            r = GetOverlappedResult(hFile, &ov, bytesRead, TRUE);
-        }
+        SetLastError( RtlNtStatusToDosError(status) );
+        return FALSE;
     }
-    CloseHandle(ov.hEvent);
-    return r;
+    return TRUE;
 }
 
 /***********************************************************************
  *              ReadFile                (KERNEL32.@)
  */
 BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
-                        LPDWORD bytesRead, LPOVERLAPPED overlapped )
+                      LPDWORD bytesRead, LPOVERLAPPED overlapped )
 {
-    int unix_handle, result, flags;
-    enum fd_type type;
-
+    LARGE_INTEGER       offset;
+    PLARGE_INTEGER      poffset = NULL;
+    IO_STATUS_BLOCK     iosb;
+    PIO_STATUS_BLOCK    io_status = &iosb;
+    HANDLE              hEvent = 0;
+    NTSTATUS            status;
+        
     TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToRead,
           bytesRead, overlapped );
 
     if (bytesRead) *bytesRead = 0;  /* Do this before anything else */
     if (!bytesToRead) return TRUE;
 
+    if (IsBadReadPtr(buffer, bytesToRead))
+    {
+        SetLastError(ERROR_WRITE_FAULT); /* FIXME */
+        return FALSE;
+    }
     if (is_console_handle(hFile))
 	return FILE_ReadConsole(hFile, buffer, bytesToRead, bytesRead, NULL);
 
-    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags );
-
-    if (flags & FD_FLAG_OVERLAPPED)
+    if (overlapped != NULL)
     {
-	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;
-        }
-
-        close(unix_handle);
-        overlapped->InternalHigh = 0;
-
-        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;
+        offset.s.LowPart = overlapped->Offset;
+        offset.s.HighPart = overlapped->OffsetHigh;
+        poffset = &offset;
+        hEvent = overlapped->hEvent;
+        io_status = (PIO_STATUS_BLOCK)overlapped;
     }
-    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);
+    io_status->u.Status = STATUS_PENDING;
+    io_status->Information = 0;
 
-    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;
+    status = NtReadFile(hFile, hEvent, NULL, NULL, io_status, buffer, bytesToRead, poffset, NULL);
 
-    default:
-	if (unix_handle == -1)
-	    return FALSE;
-    }
+    if (status != STATUS_PENDING && bytesRead)
+        *bytesRead = io_status->Information;
 
-    if(overlapped)
+    if (status && status != STATUS_END_OF_FILE)
     {
-	off_t offset = OVERLAPPED_OFFSET(overlapped);
-	if(lseek(unix_handle, offset, SEEK_SET) == -1)
-	{
-	    close(unix_handle);
-	    SetLastError(ERROR_INVALID_PARAMETER);
-	    return FALSE;
-	}
+        SetLastError( RtlNtStatusToDosError(status) );
+        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;
-    }
-    close( unix_handle );
-    if (result == -1) return FALSE;
-    if (bytesRead) *bytesRead = result;
     return TRUE;
 }
 
 
 /***********************************************************************
- *             FILE_AsyncWriteService      (INTERNAL)
- *
- *  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)
-{
-    async_fileio *fileio = (async_fileio *) ovp;
-    LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
-    int result, r;
-    int already = lpOverlapped->InternalHigh;
-
-    TRACE("(%p %p)\n",lpOverlapped,fileio->buffer);
-
-    /* write some data (non-blocking) */
-
-    if ( fileio->fd_type == FD_TYPE_SOCKET )
-        result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
-    else
-    {
-        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);
-    }
-
-    if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
-    {
-        r = STATUS_PENDING;
-        goto async_end;
-    }
-
-    /* check to see if the transfer is complete */
-    if(result<0)
-    {
-        r = FILE_GetNtStatus ();
-        goto async_end;
-    }
-
-    lpOverlapped->InternalHigh += result;
-
-    TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
-
-    if(lpOverlapped->InternalHigh < fileio->count)
-        r = STATUS_PENDING;
-    else
-        r = STATUS_SUCCESS;
-
-async_end:
-    lpOverlapped->Internal = r;
-}
-
-/***********************************************************************
- *              FILE_WriteFileEx
+ *              WriteFileEx                (KERNEL32.@)
  */
-static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
-                             LPOVERLAPPED overlapped,
-                             LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
-                             HANDLE hEvent)
+BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
+                        LPOVERLAPPED overlapped,
+                        LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
-    async_fileio *ovp;
-    int fd;
-    int flags;
-    enum fd_type type;
+    LARGE_INTEGER       offset;
+    NTSTATUS            status;
+    PIO_STATUS_BLOCK    io_status;
 
-    TRACE("file %p to buf %p num %ld %p func %p handle %p\n",
-	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine, hEvent);
+    TRACE("%p %p %ld %p %p\n", 
+          hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
 
     if (overlapped == NULL)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
+    offset.s.LowPart = overlapped->Offset;
+    offset.s.HighPart = overlapped->OffsetHigh;
 
-    fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
-    if ( fd < 0 )
-    {
-        TRACE( "Couldn't get FD\n" );
-        return FALSE;
-    }
-
-    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;
-
-    return !register_new_async (&ovp->async);
-
-error:
-    close (fd);
-    return FALSE;
-}
+    io_status = (PIO_STATUS_BLOCK)overlapped;
+    io_status->u.Status = STATUS_PENDING;
 
-/***********************************************************************
- *              WriteFileEx                (KERNEL32.@)
- */
-BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
-			 LPOVERLAPPED overlapped,
-			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
-{
-    overlapped->InternalHigh = 0;
+    status = NtWriteFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine,
+                         io_status, buffer, bytesToWrite, &offset, NULL);
 
-    return FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine, INVALID_HANDLE_VALUE);
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
+    return !status;
 }
 
 /***********************************************************************
  *             WriteFile               (KERNEL32.@)
  */
 BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
-                         LPDWORD bytesWritten, LPOVERLAPPED overlapped )
+                       LPDWORD bytesWritten, LPOVERLAPPED overlapped )
 {
-    int unix_handle, result, flags;
-    enum fd_type type;
-
-    TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToWrite,
-          bytesWritten, overlapped );
+    HANDLE hEvent = NULL;
+    LARGE_INTEGER offset;
+    PLARGE_INTEGER poffset = NULL;
+    NTSTATUS status;
+    IO_STATUS_BLOCK iosb;
+    PIO_STATUS_BLOCK piosb = &iosb;
 
-    if (bytesWritten) *bytesWritten = 0;  /* Do this before anything else */
-    if (!bytesToWrite) return TRUE;
+    TRACE("%p %p %ld %p %p\n", 
+          hFile, buffer, bytesToWrite, bytesWritten, overlapped );
 
     if (is_console_handle(hFile))
 	return FILE_WriteConsole(hFile, buffer, bytesToWrite, bytesWritten, NULL);
-
-    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags );
-
-    if (flags & FD_FLAG_OVERLAPPED)
+    
+    if (IsBadReadPtr(buffer, bytesToWrite))
     {
-	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;
-        }
-
-        close(unix_handle);
-        overlapped->InternalHigh = 0;
-
-        if(!FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL, overlapped->hEvent))
-            return FALSE;
-
-        if ( !GetOverlappedResult (hFile, overlapped, bytesWritten, FALSE) )
-        {
-            if ( GetLastError() == ERROR_IO_INCOMPLETE )
-                SetLastError ( ERROR_IO_PENDING );
-            return FALSE;
-        }
-
-        return TRUE;
+        SetLastError(ERROR_READ_FAULT); /* FIXME */
+        return FALSE;
     }
 
-    switch(type)
+    if (overlapped)
     {
-    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;
+        offset.s.LowPart = overlapped->Offset;
+        offset.s.HighPart = overlapped->OffsetHigh;
+        poffset = &offset;
+        hEvent = overlapped->hEvent;
+        piosb = (PIO_STATUS_BLOCK)overlapped;
     }
+    piosb->u.Status = STATUS_PENDING;
+    piosb->Information = 0;
 
-    if(overlapped)
+    status = NtWriteFile(hFile, hEvent, NULL, NULL, piosb,
+                         buffer, bytesToWrite, poffset, NULL);
+    if (status)
     {
-	off_t offset = OVERLAPPED_OFFSET(overlapped);
-	if(lseek(unix_handle, offset, SEEK_SET) == -1)
-	{
-	    close(unix_handle);
-	    SetLastError(ERROR_INVALID_PARAMETER);
-	    return FALSE;
-	}
+        SetLastError( RtlNtStatusToDosError(status) );
+        return FALSE;
     }
+    if (bytesWritten) *bytesWritten = piosb->Information;
 
-    /* synchronous file write */
-    while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
-    {
-        if ((errno == EAGAIN) || (errno == EINTR)) continue;
-        if ((errno == EFAULT) && !IsBadReadPtr( buffer, bytesToWrite )) continue;
-        if (errno == ENOSPC)
-            SetLastError( ERROR_DISK_FULL );
-        else
-        FILE_SetDosError();
-        break;
-    }
-    close( unix_handle );
-    if (result == -1) return FALSE;
-    if (bytesWritten) *bytesWritten = result;
     return TRUE;
 }
 
diff -u -N -r -x '*~' -x '.#*' -x CVS files29/smb.c files/smb.c
--- files29/smb.c	2003-06-24 21:41:24.000000000 +0200
+++ files/smb.c	2003-06-24 21:35:37.000000000 +0200
@@ -100,6 +100,8 @@
 #include <netdb.h>
 #endif
 
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "winerror.h"
 #include "windef.h"
 #include "winbase.h"
@@ -202,7 +204,7 @@
  * replacing separators with null characters
  */
 
-USHORT SMB_MultiplexId = 0;
+static USHORT SMB_MultiplexId = 0;
 
 struct NB_Buffer
 {
@@ -1532,16 +1534,15 @@
     return handle;
 }
 
-static BOOL SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHORT *dialect, USHORT *file_id, LPDWORD offset)
+static NTSTATUS SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHORT *dialect, USHORT *file_id, LPDWORD offset)
 {
-    int r;
+    NTSTATUS status;
 
     SERVER_START_REQ( get_smb_info )
     {
         req->handle  = hFile;
         req->flags   = 0;
-        SetLastError(0);
-        r = wine_server_call_err( req );
+        status = wine_server_call( req );
         if(tree_id)
             *tree_id = reply->tree_id;
         if(user_id)
@@ -1555,12 +1556,12 @@
     }
     SERVER_END_REQ;
 
-    return !r;
+    return status;
 }
 
-static BOOL SMB_SetOffset(HANDLE hFile, DWORD offset)
+static NTSTATUS SMB_SetOffset(HANDLE hFile, DWORD offset)
 {
-    int r;
+    NTSTATUS status;
 
     TRACE("offset = %08lx\n",offset);
 
@@ -1569,61 +1570,53 @@
         req->handle  = hFile;
         req->flags   = SMBINFO_SET_OFFSET;
         req->offset  = offset;
-        SetLastError(0);
-        r = wine_server_call_err( req );
+        status = wine_server_call( req );
         /* if(offset)
             *offset = reply->offset; */
     }
     SERVER_END_REQ;
 
-    return !r;
+    return status;
 }
 
-BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped)
+NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, 
+                             PIO_STATUS_BLOCK io_status)
 {
     int fd;
-    DWORD total, count, offset;
+    DWORD count, offset;
     USHORT user_id, tree_id, dialect, file_id, read;
-    BOOL r=TRUE;
 
-    TRACE("%p %p %ld %p\n", hFile, buffer, bytesToRead, bytesRead);
+    TRACE("%p %p %ld %p\n", hFile, buffer, bytesToRead, io_status);
 
-    if(!SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset))
-        return FALSE;
+    io_status->Information = 0;
+
+    io_status->u.Status = SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset);
+    if (io_status->u.Status) return io_status->u.Status;
 
     fd = FILE_GetUnixHandle(hFile, GENERIC_READ);
-    if(fd<0)
-        return FALSE;
+    if (fd<0) return io_status->u.Status = STATUS_INVALID_HANDLE;
 
-    total = 0;
     while(1)
     {
-        count = bytesToRead - total;
+        count = bytesToRead - io_status->Information;
         if(count>0x400)
             count = 0x400;
         if(count==0)
             break;
         read = 0;
-        r = SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read);
-        if(!r)
+        if (!SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read))
             break;
         if(!read)
             break;
-        total += read;
+        io_status->Information += read;
         buffer = (char*)buffer + read;
         offset += read;
-        if(total>=bytesToRead)
+        if(io_status->Information >= bytesToRead)
             break;
     }
     close(fd);
 
-    if(bytesRead)
-        *bytesRead = total;
-
-    if(!SMB_SetOffset(hFile, offset))
-        return FALSE;
-
-    return r;
+    return io_status->u.Status = SMB_SetOffset(hFile, offset);
 }
 
 SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR name)
diff -u -N -r -x '*~' -x '.#*' -x CVS files29/smb.h files/smb.h
--- files29/smb.h	2003-06-24 21:41:24.000000000 +0200
+++ files/smb.h	2003-06-24 21:34:54.000000000 +0200
@@ -22,7 +22,8 @@
 extern inline int SMB_isSepW (WCHAR c) {return (c == '\\' || c == '/');}
 extern inline int SMB_isUNCW (LPCWSTR filename) {return (filename && SMB_isSepW (filename[0]) && SMB_isSepW (filename[1]));}
 
-extern BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped);
+NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, 
+                             PIO_STATUS_BLOCK io_status);
 extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
                               LPSECURITY_ATTRIBUTES sa, DWORD creation,
                               DWORD attributes, HANDLE template );
diff -u -N -r -x '*~' -x '.#*' -x CVS include29/async.h include/async.h
--- include29/async.h	2002-05-07 23:07:27.000000000 +0200
+++ include/async.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,135 +0,0 @@
-/*
- * Structures and static functions for handling asynchronous I/O.
- *
- * Copyright (C) 2002 Mike McCormack,  Martin Wilck
- *
- * 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
- */
-
-/*
- * This file declares static functions.
- * It should only be included by those source files that implement async I/O requests.
- */
-
-#ifndef __WINE_ASYNC_H
-#define __WINE_ASYNC_H
-
-#include "wine/server.h"
-
-struct async_private;
-
-typedef void (*async_handler)(struct async_private *ovp);
-typedef void (CALLBACK *async_call_completion_func)(ULONG_PTR data);
-typedef DWORD (*async_get_status)(const struct async_private *ovp);
-typedef DWORD (*async_get_count)(const struct async_private *ovp);
-typedef void (*async_set_status)(struct async_private *ovp, const DWORD status);
-typedef void (*async_cleanup)(struct async_private *ovp);
-
-typedef struct async_ops
-{
-    async_get_status            get_status;
-    async_set_status            set_status;
-    async_get_count             get_count;
-    async_call_completion_func  call_completion;
-    async_cleanup               cleanup;
-} async_ops;
-
-typedef struct async_private
-{
-    struct async_ops     *ops;
-    HANDLE        handle;
-    HANDLE        event;
-    int           fd;
-    async_handler func;
-    int           type;
-    struct async_private *next;
-    struct async_private *prev;
-} async_private;
-
-/* All functions declared static for Dll separation purposes */
-
-inline static void finish_async( async_private *ovp )
-{
-    if(ovp->prev)
-        ovp->prev->next = ovp->next;
-    else
-        NtCurrentTeb()->pending_list = ovp->next;
-
-    if(ovp->next)
-        ovp->next->prev = ovp->prev;
-
-    ovp->next = ovp->prev = NULL;
-
-    close( ovp->fd );
-    if( ovp->event != INVALID_HANDLE_VALUE )
-        NtSetEvent( ovp->event, NULL );
-
-    if ( ovp->ops->call_completion )
-        QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
-    else
-        ovp->ops->cleanup ( ovp );
-}
-
-inline static BOOL __register_async( async_private *ovp, const DWORD status )
-{
-    BOOL ret;
-
-    SERVER_START_REQ( register_async )
-    {
-        req->handle = ovp->handle;
-        req->overlapped = ovp;
-        req->type = ovp->type;
-        req->count = ovp->ops->get_count( ovp );
-        req->status = status;
-        ret = wine_server_call( req );
-    }
-    SERVER_END_REQ;
-
-    if ( ret ) {
-        SetLastError( RtlNtStatusToDosError(ret) );
-        ovp->ops->set_status ( ovp, ret );
-    }
-
-    if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
-        finish_async (ovp);
-
-    return ret;
-}
-
-#define register_old_async(ovp) \
-    __register_async (ovp, ovp->ops->get_status( ovp ));
-
-inline static BOOL register_new_async( async_private *ovp )
-{
-    ovp->ops->set_status ( ovp, STATUS_PENDING );
-
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if ( ovp->next ) ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
-
-    return __register_async( ovp, STATUS_PENDING );
-}
-
-inline static BOOL cancel_async ( async_private *ovp )
-{
-     /* avoid multiple cancellations */
-     if ( ovp->ops->get_status( ovp ) != STATUS_PENDING )
-          return 0;
-     ovp->ops->set_status ( ovp, STATUS_CANCELLED );
-     return __register_async ( ovp, STATUS_CANCELLED );
-}
-
-#endif /* __WINE_ASYNC_H */
diff -u -N -r -x '*~' -x '.#*' -x CVS include29/wine/async.h include/wine/async.h
--- include29/wine/async.h	1970-01-01 01:00:00.000000000 +0100
+++ include/wine/async.h	2003-06-07 10:25:41.000000000 +0200
@@ -0,0 +1,136 @@
+/*
+ * Structures and static functions for handling asynchronous I/O.
+ *
+ * Copyright (C) 2002 Mike McCormack,  Martin Wilck
+ *
+ * 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
+ */
+
+/*
+ * This file declares static functions.
+ * It should only be included by those source files that implement async I/O requests.
+ */
+
+#ifndef __WINE_ASYNC_H
+#define __WINE_ASYNC_H
+
+#include "wine/server.h"
+#include "winternl.h"
+
+struct async_private;
+
+typedef void (*async_handler)(struct async_private *ovp);
+typedef void (CALLBACK *async_call_completion_func)(ULONG_PTR data);
+typedef DWORD (*async_get_count)(const struct async_private *ovp);
+typedef void (*async_cleanup)(struct async_private *ovp);
+
+typedef struct async_ops
+{
+    async_get_count             get_count;
+    async_call_completion_func  call_completion;
+    async_cleanup               cleanup;
+} async_ops;
+
+typedef struct async_private
+{
+    struct async_ops*   ops;
+    HANDLE              handle;
+    HANDLE              event;
+    int                 fd;
+    async_handler       func;
+    int                 type;
+    IO_STATUS_BLOCK*    iosb;
+    struct async_private* next;
+    struct async_private* prev;
+} async_private;
+
+/* All functions declared static for Dll separation purposes */
+static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
+{
+    PAPCFUNC func = (PAPCFUNC)arg1;
+    func( arg2 );
+}
+
+inline static void finish_async( async_private *ovp )
+{
+    if (ovp->prev)
+        ovp->prev->next = ovp->next;
+    else
+        NtCurrentTeb()->pending_list = ovp->next;
+
+    if (ovp->next)
+        ovp->next->prev = ovp->prev;
+
+    ovp->next = ovp->prev = NULL;
+
+    close(ovp->fd);
+    if ( ovp->event != INVALID_HANDLE_VALUE )
+        NtSetEvent( ovp->event, NULL );
+
+    if ( ovp->ops->call_completion )
+        NtQueueApcThread( GetCurrentThread(), call_user_apc, 
+                          (ULONG_PTR)ovp->ops->call_completion, (ULONG_PTR)ovp, 0 );
+    else
+        ovp->ops->cleanup( ovp );
+}
+
+inline static NTSTATUS __register_async( async_private *ovp, const DWORD status )
+{
+    NTSTATUS    ret;
+
+    SERVER_START_REQ( register_async )
+    {
+        req->handle = ovp->handle;
+        req->overlapped = ovp;
+        req->type = ovp->type;
+        req->count = ovp->ops->get_count( ovp );
+        req->status = status;
+        ret = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    if (ret) ovp->iosb->u.Status = ret;
+
+    if ( ovp->iosb->u.Status != STATUS_PENDING )
+        finish_async(ovp);
+
+    return ret;
+}
+
+#define register_old_async(ovp) \
+    __register_async(ovp, ovp->iosb->u.Status);
+
+inline static NTSTATUS register_new_async( async_private *ovp )
+{
+    ovp->iosb->u.Status = STATUS_PENDING;
+
+    ovp->next = NtCurrentTeb()->pending_list;
+    ovp->prev = NULL;
+    if ( ovp->next ) ovp->next->prev = ovp;
+    NtCurrentTeb()->pending_list = ovp;
+
+    return __register_async( ovp, STATUS_PENDING );
+}
+
+inline static NTSTATUS cancel_async( async_private *ovp )
+{
+     /* avoid multiple cancellations */
+     if ( ovp->iosb->u.Status != STATUS_PENDING )
+          return STATUS_SUCCESS;
+     ovp->iosb->u.Status = STATUS_CANCELLED;
+     return __register_async( ovp, STATUS_CANCELLED );
+}
+
+#endif /* __WINE_ASYNC_H */
diff -u -N -r -x '*~' -x '.#*' -x CVS include29/winternl.h include/winternl.h
--- include29/winternl.h	2003-06-24 19:19:27.000000000 +0200
+++ include/winternl.h	2003-06-24 21:14:05.000000000 +0200
@@ -991,6 +991,7 @@
 NTSTATUS  WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
 NTSTATUS  WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER);
 NTSTATUS  WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,PLARGE_INTEGER); 
+NTSTATUS  WINAPI NtWriteFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,const void*,ULONG,PLARGE_INTEGER,PULONG);
 
 void      WINAPI RtlAcquirePebLock(void);
 BYTE      WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK,BYTE);


More information about the wine-patches mailing list