ntdll/kernel32: #30 take II
Eric Pouech
pouech-eric at wanadoo.fr
Wed Jun 25 12:19:10 CDT 2003
(same as take I, but without moving async.h to include/wine)
ChangeLog:
- made async.h ready for use in ntdll: 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-25 07:20:01.000000000 +0200
@@ -84,6 +84,8 @@
# include <sys/strtio.h>
#endif
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "winbase.h"
#include "winerror.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-25 07:20:06.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 "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-25 07:20:13.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 "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-25 07:20:17.000000000 +0200
@@ -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-25 07:20:24.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"
@@ -147,16 +149,12 @@
****************************************************************/
#include "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 2003-06-07 10:25:41.000000000 +0200
@@ -27,20 +27,17 @@
#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_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;
@@ -48,43 +45,50 @@
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;
+ 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)
+ if (ovp->prev)
ovp->prev->next = ovp->next;
else
NtCurrentTeb()->pending_list = ovp->next;
- if(ovp->next)
+ if (ovp->next)
ovp->next->prev = ovp->prev;
ovp->next = ovp->prev = NULL;
- close( ovp->fd );
- if( ovp->event != INVALID_HANDLE_VALUE )
+ 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 );
+ NtQueueApcThread( GetCurrentThread(), call_user_apc,
+ (ULONG_PTR)ovp->ops->call_completion, (ULONG_PTR)ovp, 0 );
else
- ovp->ops->cleanup ( ovp );
+ ovp->ops->cleanup( ovp );
}
-inline static BOOL __register_async( async_private *ovp, const DWORD status )
+inline static NTSTATUS __register_async( async_private *ovp, const DWORD status )
{
- BOOL ret;
+ NTSTATUS ret;
SERVER_START_REQ( register_async )
{
@@ -97,23 +101,20 @@
}
SERVER_END_REQ;
- if ( ret ) {
- SetLastError( RtlNtStatusToDosError(ret) );
- ovp->ops->set_status ( ovp, ret );
- }
+ if (ret) ovp->iosb->u.Status = ret;
- if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
- finish_async (ovp);
+ if ( ovp->iosb->u.Status != STATUS_PENDING )
+ finish_async(ovp);
return ret;
}
#define register_old_async(ovp) \
- __register_async (ovp, ovp->ops->get_status( ovp ));
+ __register_async(ovp, ovp->iosb->u.Status);
-inline static BOOL register_new_async( async_private *ovp )
+inline static NTSTATUS register_new_async( async_private *ovp )
{
- ovp->ops->set_status ( ovp, STATUS_PENDING );
+ ovp->iosb->u.Status = STATUS_PENDING;
ovp->next = NtCurrentTeb()->pending_list;
ovp->prev = NULL;
@@ -123,13 +124,13 @@
return __register_async( ovp, STATUS_PENDING );
}
-inline static BOOL cancel_async ( async_private *ovp )
+inline static NTSTATUS 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 );
+ 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