Commit 4634447d authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- got rid of include/async.h

- fixed some overlapped issues in socket handling - moved kernel32.CancelIo implementation to ntdll
parent 3e55df39
......@@ -93,8 +93,8 @@
#include "winerror.h"
#include "wine/server.h"
#include "async.h"
#include "wine/unicode.h"
#include "thread.h"
#include "wine/debug.h"
......@@ -125,32 +125,15 @@ static inline void release_comm_fd( HANDLE handle, int fd )
* Asynchronous I/O for asynchronous wait requests *
*/
static DWORD commio_get_async_count (const async_private *ovp);
static void commio_async_cleanup (async_private *ovp);
static async_ops commio_async_ops =
{
commio_get_async_count, /* get_count */
NULL, /* call_completion */
commio_async_cleanup /* cleanup */
};
typedef struct async_commio
{
struct async_private async;
char *buffer;
HANDLE handle;
PIO_APC_ROUTINE apc_internal;
int type;
char* buffer;
int fd;
} async_commio;
static DWORD commio_get_async_count (const struct async_private *ovp)
{
return 0;
}
static void commio_async_cleanup (async_private *ovp)
{
HeapFree(GetProcessHeap(), 0, ovp );
}
/***********************************************************************/
#if !defined(TIOCINQ) && defined(FIONREAD)
......@@ -1928,17 +1911,27 @@ BOOL WINAPI GetCommModemStatus(
* This function is called while the client is waiting on the
* server, so we can't make any server calls here.
*/
static void COMM_WaitCommEventService(async_private *ovp)
static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
{
async_commio *commio = (async_commio*) ovp;
IO_STATUS_BLOCK* iosb = commio->async.iosb;
TRACE("iosb %p\n",iosb);
TRACE("iosb %p\n", iosb);
switch (status)
{
case STATUS_ALERTED: /* got some new stuff */
/* FIXME: detect other events */
*commio->buffer = EV_RXCHAR;
iosb->u.Status = STATUS_SUCCESS;
break;
default:
iosb->u.Status = status;
break;
}
wine_server_release_fd( commio->handle, commio->fd );
if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE )
NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL );
HeapFree(GetProcessHeap(), 0, commio );
}
......@@ -1953,43 +1946,51 @@ static BOOL COMM_WaitCommEvent(
LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
{
int fd;
async_commio *ovp;
async_commio* commio;
NTSTATUS status;
if(!lpOverlapped)
if (!lpOverlapped)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(NtResetEvent(lpOverlapped->hEvent,NULL))
if (NtResetEvent(lpOverlapped->hEvent,NULL))
return FALSE;
fd = get_comm_fd( hFile, GENERIC_WRITE );
if(fd<0)
return FALSE;
if (fd < 0) return FALSE;
ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
if(!ovp)
commio = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
if (!commio)
{
release_comm_fd( hFile, fd );
return FALSE;
}
ovp->async.ops = &commio_async_ops;
ovp->async.handle = hFile;
ovp->async.fd = fd; /* FIXME */
ovp->async.type = ASYNC_TYPE_WAIT;
ovp->async.func = COMM_WaitCommEventService;
ovp->async.event = lpOverlapped->hEvent;
ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
ovp->buffer = (char *)lpdwEvents;
commio->handle = hFile;
commio->type = ASYNC_TYPE_WAIT;
commio->apc_internal = COMM_WaitCommEventService;
commio->buffer = (char *)lpdwEvents;
commio->fd = fd; /* FIXME */
lpOverlapped->InternalHigh = 0;
lpOverlapped->Offset = 0;
lpOverlapped->OffsetHigh = 0;
if ( !register_new_async (&ovp->async) )
SetLastError( ERROR_IO_PENDING );
SERVER_START_REQ( register_async )
{
req->handle = hFile;
req->io_apc = COMM_WaitCommEventService;
req->io_user = commio;
req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped;
req->count = 0;
status = wine_server_call( req );
}
SERVER_END_REQ;
if ( status ) SetLastError( RtlNtStatusToDosError(status) );
else NtCurrentTeb()->num_async_io++;
return FALSE;
}
......
......@@ -43,7 +43,8 @@
#include "excpt.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "async.h"
#include "thread.h"
#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(file);
......@@ -512,7 +513,7 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
else
{
/* busy loop */
while ( (volatile DWORD)lpOverlapped->Internal == STATUS_PENDING )
while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
Sleep( 10 );
}
}
......@@ -532,7 +533,7 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
}
if ( r == WAIT_FAILED )
{
ERR("wait operation failed\n");
WARN("wait operation failed\n");
return FALSE;
}
if (lpTransferred) *lpTransferred = lpOverlapped->InternalHigh;
......@@ -556,17 +557,14 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
*/
BOOL WINAPI CancelIo(HANDLE handle)
{
async_private *ovp,*t;
IO_STATUS_BLOCK io_status;
TRACE("handle = %p\n",handle);
for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t)
NtCancelIoFile(handle, &io_status);
if (io_status.u.Status)
{
t = ovp->next;
if ( ovp->handle == handle )
cancel_async ( ovp );
SetLastError( RtlNtStatusToDosError( io_status.u.Status ) );
return FALSE;
}
SleepEx(1,TRUE);
return TRUE;
}
......
......@@ -62,7 +62,6 @@
#include "wine/unicode.h"
#include "wine/debug.h"
#include "wine/server.h"
#include "async.h"
#include "ntdll_misc.h"
#include "winternl.h"
......@@ -222,59 +221,66 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
/***********************************************************************
* 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 */
};
static void WINAPI FILE_AsyncReadService(void*, PIO_STATUS_BLOCK, ULONG);
static void WINAPI FILE_AsyncWriteService(void*, PIO_STATUS_BLOCK, ULONG);
typedef struct async_fileio
{
struct async_private async;
HANDLE handle;
PIO_APC_ROUTINE apc;
void* apc_user;
char *buffer;
char* buffer;
unsigned int count;
off_t offset;
int queue_apc_on_error;
BOOL avail_mode;
int fd;
HANDLE event;
} async_fileio;
static DWORD fileio_get_async_count(const struct async_private *ovp)
static void fileio_terminate(async_fileio *fileio, IO_STATUS_BLOCK* iosb)
{
const async_fileio *fileio = (const async_fileio*) ovp;
TRACE("data: %p\n", fileio);
if (fileio->count < fileio->async.iosb->Information)
return 0;
return fileio->count - fileio->async.iosb->Information;
}
wine_server_release_fd( fileio->handle, fileio->fd );
if ( fileio->event != INVALID_HANDLE_VALUE )
NtSetEvent( fileio->event, NULL );
static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
{
async_fileio *ovp = (async_fileio*) data;
TRACE("data: %p\n", ovp);
if (fileio->apc &&
(iosb->u.Status == STATUS_SUCCESS || fileio->queue_apc_on_error))
fileio->apc( fileio->apc_user, iosb, iosb->Information );
if ((ovp->async.iosb->u.Status == STATUS_SUCCESS) || ovp->queue_apc_on_error)
ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
fileio_async_cleanup( &ovp->async );
RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
static void fileio_async_cleanup( struct async_private *ovp )
static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb,
BOOL do_read)
{
RtlFreeHeap( GetProcessHeap(), 0, ovp );
PIO_APC_ROUTINE apc = do_read ? FILE_AsyncReadService : FILE_AsyncWriteService;
NTSTATUS status;
SERVER_START_REQ( register_async )
{
req->handle = fileio->handle;
req->io_apc = apc;
req->io_sb = iosb;
req->io_user = fileio;
req->type = do_read ? ASYNC_TYPE_READ : ASYNC_TYPE_WRITE;
req->count = (fileio->count < iosb->Information) ?
0 : fileio->count - iosb->Information;
status = wine_server_call( req );
}
SERVER_END_REQ;
if ( status ) iosb->u.Status = status;
if ( iosb->u.Status != STATUS_PENDING )
{
(apc)( fileio, iosb, iosb->u.Status );
return iosb->u.Status;
}
NtCurrentTeb()->num_async_io++;
return STATUS_SUCCESS;
}
/***********************************************************************
......@@ -326,55 +332,75 @@ NTSTATUS FILE_GetNtStatus(void)
* 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)
static void WINAPI FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
{
async_fileio *fileio = (async_fileio*) ovp;
IO_STATUS_BLOCK* io_status = fileio->async.iosb;
async_fileio *fileio = (async_fileio*)user;
int result;
int already = io_status->Information;
int already = iosb->Information;
TRACE("%p %p\n", io_status, fileio->buffer );
TRACE("%p %p %lu\n", iosb, fileio->buffer, status);
switch (status)
{
case STATUS_ALERTED: /* got some new data */
if (iosb->u.Status != STATUS_PENDING) FIXME("unexpected status %08lx\n", iosb->u.Status);
/* check to see if the data is ready (non-blocking) */
if ( fileio->avail_mode )
result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
result = read(fileio->fd, &fileio->buffer[already],
fileio->count - already);
else
{
result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
result = pread(fileio->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);
result = read(fileio->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;
if (errno == EAGAIN || errno == EINTR)
{
TRACE("Deferred read %d\n", errno);
iosb->u.Status = STATUS_PENDING;
}
else /* check to see if the transfer is complete */
iosb->u.Status = FILE_GetNtStatus();
}
else if (result == 0)
{
io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
return;
iosb->u.Status = iosb->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
}
TRACE("status before: %s\n", (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
io_status->Information += result;
if (io_status->Information >= fileio->count || fileio->avail_mode )
io_status->u.Status = STATUS_SUCCESS;
else
io_status->u.Status = STATUS_PENDING;
{
iosb->Information += result;
if (iosb->Information >= fileio->count || fileio->avail_mode)
iosb->u.Status = STATUS_SUCCESS;
else
{
/* if we only have to read the available data, and none is available,
* simply cancel the request. If data was available, it has been read
* while in by previous call (NtDelayExecution)
*/
iosb->u.Status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING;
}
TRACE("read %d more bytes %ld/%d so far (%s)\n",
result, io_status->Information, fileio->count, (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
result, iosb->Information, fileio->count,
(iosb->u.Status == STATUS_SUCCESS) ? "success" : "pending");
}
/* queue another async operation ? */
if (iosb->u.Status == STATUS_PENDING)
fileio_queue_async(fileio, iosb, TRUE);
else
fileio_terminate(fileio, iosb);
break;
default:
iosb->u.Status = status;
fileio_terminate(fileio, iosb);
break;
}
}
......@@ -439,44 +465,41 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
{
async_fileio* ovp;
async_fileio* fileio;
NTSTATUS ret;
if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
{
wine_server_release_fd( hFile, unix_handle );
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile;
ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_READ;
ovp->async.func = FILE_AsyncReadService;
ovp->async.event = hEvent;
ovp->async.iosb = io_status;
ovp->count = length;
fileio->handle = hFile;
fileio->count = length;
if ( offset == NULL )
ovp->offset = 0;
fileio->offset = 0;
else
{
ovp->offset = offset->QuadPart;
if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
fileio->offset = offset->QuadPart;
if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
FIXME("High part of offset is lost\n");
}
ovp->apc = apc;
ovp->apc_user = apc_user;
ovp->buffer = buffer;
ovp->queue_apc_on_error = 0;
ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
fileio->apc = apc;
fileio->apc_user = apc_user;
fileio->buffer = buffer;
fileio->queue_apc_on_error = 0;
fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
fileio->fd = unix_handle; /* FIXME */
fileio->event = hEvent;
NtResetEvent(hEvent, NULL);
ret = register_new_async(&ovp->async);
io_status->u.Status = STATUS_PENDING;
ret = fileio_queue_async(fileio, io_status, TRUE);
if (ret != STATUS_SUCCESS)
{
wine_server_release_fd( hFile, unix_handle );
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
RtlFreeHeap(GetProcessHeap(), 0, ovp);
RtlFreeHeap(GetProcessHeap(), 0, fileio);
return ret;
}
if (flags & FD_FLAG_TIMEOUT)
......@@ -484,7 +507,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
NtClose(hEvent);
if (ret != STATUS_USER_APC)
ovp->queue_apc_on_error = 1;
fileio->queue_apc_on_error = 1;
}
else
{
......@@ -499,16 +522,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
* returning errors because apc's are run only during alertable
* waits */
if (ret != STATUS_USER_APC)
ovp->queue_apc_on_error = 1;
/* if we only have to read the available data, and none is available,
* simply cancel the request. If data was available, it has been read
* while in by previous call (NtDelayExecution)
*/
if ((flags & FD_FLAG_AVAILABLE) && io_status->u.Status == STATUS_PENDING)
{
io_status->u.Status = STATUS_SUCCESS;
register_old_async(&ovp->async);
}
fileio->queue_apc_on_error = 1;
}
TRACE("= 0x%08lx\n", io_status->u.Status);
return io_status->u.Status;
......@@ -550,43 +564,50 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
* 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)
static void WINAPI FILE_AsyncWriteService(void *ovp, IO_STATUS_BLOCK *iosb, ULONG status)
{
async_fileio *fileio = (async_fileio *) ovp;
PIO_STATUS_BLOCK io_status = fileio->async.iosb;
int result;
int already = io_status->Information;
int already = iosb->Information;
TRACE("(%p %p)\n",io_status,fileio->buffer);
TRACE("(%p %p %lu)\n",iosb, fileio->buffer, status);
switch (status)
{
case STATUS_ALERTED:
/* write some data (non-blocking) */
if ( fileio->avail_mode )
result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
result = write(fileio->fd, &fileio->buffer[already],
fileio->count - already);
else
{
result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
fileio->offset + already);
result = pwrite(fileio->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);
result = write(fileio->fd, &fileio->buffer[already],
fileio->count - already);
}
if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
if (result < 0)
{
io_status->u.Status = STATUS_PENDING;
return;
if (errno == EAGAIN || errno == EINTR) iosb->u.Status = STATUS_PENDING;
else iosb->u.Status = FILE_GetNtStatus();
}
/* check to see if the transfer is complete */
if (result < 0)
else
{
io_status->u.Status = FILE_GetNtStatus();
return;
iosb->Information += result;
iosb->u.Status = (iosb->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
TRACE("wrote %d more bytes %ld/%d so far\n",
result, iosb->Information, fileio->count);
}
if (iosb->u.Status == STATUS_PENDING)
fileio_queue_async(fileio, iosb, FALSE);
break;
default:
iosb->u.Status = status;
fileio_terminate(fileio, iosb);
break;
}
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);
}
/******************************************************************************
......@@ -651,46 +672,52 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
{
async_fileio* ovp;
async_fileio* fileio;
NTSTATUS ret;
if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
{
wine_server_release_fd( hFile, unix_handle );
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
return STATUS_NO_MEMORY;
}
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile;
ovp->async.fd = unix_handle; /* FIXME */
ovp->async.type = ASYNC_TYPE_WRITE;
ovp->async.func = FILE_AsyncWriteService;
ovp->async.event = hEvent;
ovp->async.iosb = io_status;
ovp->count = length;
if (offset) {
ovp->offset = offset->QuadPart;
if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
fileio->handle = hFile;
fileio->count = length;
if (offset)
{
fileio->offset = offset->QuadPart;
if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
FIXME("High part of offset is lost\n");
} else {
ovp->offset = 0;
}
ovp->apc = apc;
ovp->apc_user = apc_user;
ovp->buffer = (void*)buffer;
ovp->queue_apc_on_error = 0;
ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
}
else
{
fileio->offset = 0;
}
fileio->apc = apc;
fileio->apc_user = apc_user;
fileio->buffer = (void*)buffer;
fileio->queue_apc_on_error = 0;
fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
fileio->fd = unix_handle; /* FIXME */
fileio->event = hEvent;
NtResetEvent(hEvent, NULL);
io_status->Information = 0;
ret = register_new_async(&ovp->async);
io_status->u.Status = STATUS_PENDING;
ret = fileio_queue_async(fileio, io_status, FALSE);
if (ret != STATUS_SUCCESS)
{
wine_server_release_fd( hFile, unix_handle );
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
RtlFreeHeap(GetProcessHeap(), 0, fileio);
return ret;
}
if (flags & FD_FLAG_TIMEOUT)
{
ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
NtClose(hEvent);
if (ret != STATUS_USER_APC)
ovp->queue_apc_on_error = 1;
fileio->queue_apc_on_error = 1;
}
else
{
......@@ -705,7 +732,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
* returning errors because apc's are run only during alertable
* waits */
if (ret != STATUS_USER_APC)
ovp->queue_apc_on_error = 1;
fileio->queue_apc_on_error = 1;
}
return io_status->u.Status;
}
......@@ -1688,9 +1715,23 @@ NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes )
*
*
*/
NTSTATUS WINAPI NtCancelIoFile( HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
{
FIXME("%p %p\n", FileHandle, IoStatusBlock );
return STATUS_NOT_IMPLEMENTED;
LARGE_INTEGER timeout;
TRACE("%p %p\n", hFile, io_status );
SERVER_START_REQ( cancel_async )
{
req->handle = hFile;
wine_server_call( req );
}
SERVER_END_REQ;
/* Let some APC be run, so that we can run the remaining APCs on hFile
* either the cancelation of the pending one, but also the execution
* of the queued APC, but not yet run. This is needed to ensure proper
* clean-up of allocated data.
*/
timeout.u.LowPart = timeout.u.HighPart = 0;
return io_status->u.Status = NtDelayExecution( TRUE, &timeout );
}
......@@ -51,7 +51,6 @@
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "async.h"
#include "thread.h"
#include "wine/server.h"
#include "wine/debug.h"
......@@ -605,35 +604,6 @@ NTSTATUS WINAPI NtSetTimerResolution(IN ULONG resolution,
/***********************************************************************
* check_async_list
*
* Process a status event from the server.
*/
static void WINAPI check_async_list(async_private *asp, DWORD status)
{
async_private *ovp;
DWORD ovp_status;
for( ovp = NtCurrentTeb()->pending_list; ovp && ovp != asp; ovp = ovp->next );
if(!ovp)
return;
if( status != STATUS_ALERTED )
{
ovp_status = status;
ovp->iosb->u.Status = status;
}
else ovp_status = ovp->iosb->u.Status;
if( ovp_status == STATUS_PENDING ) ovp->func( ovp );
/* This will destroy all but PENDING requests */
register_old_async( ovp );
}
/***********************************************************************
* wait_reply
*
* Wait for a reply on the waiting pipe of the current thread.
......@@ -697,7 +667,7 @@ static void call_apcs( BOOL alertable )
}
SERVER_END_REQ;
switch(type)
switch (type)
{
case APC_NONE:
return; /* no more APCs */
......@@ -714,7 +684,8 @@ static void call_apcs( BOOL alertable )
proc( arg3, time.u.LowPart, time.u.HighPart );
break;
case APC_ASYNC_IO:
check_async_list( arg1, (DWORD) arg2 );
NtCurrentTeb()->num_async_io--;
proc( arg1, (IO_STATUS_BLOCK*)arg2, (ULONG)arg3 );
break;
default:
server_protocol_error( "get_apc_request: bad type %d\n", type );
......@@ -810,7 +781,7 @@ NTSTATUS WINAPI NtYieldExecution(void)
NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
{
/* if alertable or async I/O in progress, we need to query the server */
if (alertable || NtCurrentTeb()->pending_list)
if (alertable || NtCurrentTeb()->num_async_io)
{
UINT flags = SELECT_INTERRUPTIBLE;
if (alertable) flags |= SELECT_ALERTABLE;
......
......@@ -128,6 +128,7 @@
#include "thread.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "ntstatus.h"
#include "wine/unicode.h"
#ifdef HAVE_IPX
......@@ -161,39 +162,24 @@ inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
/****************************************************************
* Async IO declarations
****************************************************************/
#include "async.h"
static DWORD ws2_async_get_count (const struct async_private *ovp);
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_count,
ws2_async_call_completion,
ws2_async_cleanup
};
static struct async_ops ws2_nocomp_async_ops =
{
ws2_async_get_count,
NULL, /* call_completion */
ws2_async_cleanup
};
typedef struct ws2_async
{
async_private async;
HANDLE hSocket;
enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
LPWSAOVERLAPPED user_overlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
struct iovec *iovec;
int n_iovecs;
struct WS_sockaddr *addr;
union {
union
{
int val; /* for send operations */
int *ptr; /* for recv operations */
} addrlen;
DWORD flags;
int fd;
HANDLE event;
} ws2_async;
/****************************************************************/
......@@ -290,7 +276,7 @@ static const int ws_ip_map[][2] =
{ 0, 0 }
};
inline static DWORD NtStatusToWSAError ( const DWORD status )
inline static DWORD NtStatusToWSAError( const DWORD status )
{
/* We only need to cover the status codes set by server async request handling */
DWORD wserr;
......@@ -311,7 +297,7 @@ inline static DWORD NtStatusToWSAError ( const DWORD status )
else
{
wserr = RtlNtStatusToDosError( status );
FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
}
}
return wserr;
......@@ -322,7 +308,7 @@ inline static unsigned int set_error( unsigned int err )
{
if (err)
{
err = NtStatusToWSAError ( err );
err = NtStatusToWSAError( err );
SetLastError( err );
}
return err;
......@@ -611,7 +597,7 @@ static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
{
unsigned int i;
for( i = 0; i < wsfds->fd_count; i++ )
for ( i = 0; i < wsfds->fd_count; i++ )
if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
wsfds->fd_count = 0;
}
......@@ -818,7 +804,6 @@ static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr,
*uaddrlen=wsaddrlen;
return (const struct sockaddr*)wsaddr;
}
return NULL;
}
/* Allocates a Unix sockaddr structure to receive the data */
......@@ -916,127 +901,153 @@ inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_socka
* Functions for handling overlapped I/O
**************************************************************************/
static DWORD ws2_async_get_count (const struct async_private *ovp)
static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
{
return ovp->iosb->Information;
}
TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
static void ws2_async_cleanup ( struct async_private *ap )
{
struct ws2_async *as = (struct ws2_async*) ap;
wine_server_release_fd( as->hSocket, as->fd );
if ( as->event != INVALID_HANDLE_VALUE )
NtSetEvent( as->event, NULL );
TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
if (as->completion_func)
as->completion_func( NtStatusToWSAError (iosb->u.Status),
iosb->Information, as->user_overlapped, as->flags );
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 );
WSACloseEvent( as->overlapped->hEvent );
#endif
HeapFree ( GetProcessHeap(), 0, as->async.iosb );
HeapFree( GetProcessHeap(), 0, iosb );
}
HeapFree ( GetProcessHeap(), 0, as->iovec );
HeapFree ( GetProcessHeap(), 0, as );
}
static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
{
ws2_async* as = (ws2_async*) data;
TRACE ("data: %p\n", as);
as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
as->async.iosb->Information,
as->user_overlapped,
as->flags );
ws2_async_cleanup ( &as->async );
HeapFree( GetProcessHeap(), 0, as->iovec );
HeapFree( GetProcessHeap(), 0, as );
}
/***********************************************************************
* WS2_make_async (INTERNAL)
*/
static void WS2_async_recv (async_private *as);
static void WS2_async_send (async_private *as);
static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
inline static struct ws2_async*
WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
LPDWORD lpFlags, struct WS_sockaddr *addr,
LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
IO_STATUS_BLOCK **piosb)
{
struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
TRACE ( "wsa %p\n", wsa );
TRACE( "wsa %p\n", wsa );
if (!wsa)
return NULL;
wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
wsa->async.handle = (HANDLE) s;
wsa->async.fd = fd;
wsa->async.type = type;
switch (type)
wsa->hSocket = (HANDLE) s;
wsa->mode = mode;
switch (mode)
{
case ASYNC_TYPE_READ:
case ws2m_read:
case ws2m_sd_read:
wsa->flags = *lpFlags;
wsa->async.func = WS2_async_recv;
wsa->addrlen.ptr = addrlen;
break;
case ASYNC_TYPE_WRITE:
case ws2m_write:
case ws2m_sd_write:
wsa->flags = 0;
wsa->async.func = WS2_async_send;
wsa->addrlen.val = *addrlen;
break;
default:
ERR ("Invalid async type: %d\n", type);
ERR("Invalid async mode: %d\n", mode);
}
wsa->user_overlapped = lpOverlapped;
wsa->completion_func = lpCompletionRoutine;
wsa->iovec = iovec;
wsa->n_iovecs = dwBufferCount;
wsa->addr = addr;
wsa->fd = fd;
wsa->event = INVALID_HANDLE_VALUE;
if ( lpOverlapped )
{
wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
}
else
*piosb = (IO_STATUS_BLOCK*)lpOverlapped;
if (!lpCompletionRoutine)
{
wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
sizeof (IO_STATUS_BLOCK) );
if ( !wsa->async.iosb )
goto error;
wsa->async.event = INVALID_HANDLE_VALUE;
wsa->event = lpOverlapped->hEvent;
NtResetEvent(wsa->event, NULL);
}
}
else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
goto error;
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->async.iosb, wsa->user_overlapped, wsa->completion_func );
(*piosb)->Information = 0;
(*piosb)->u.Status = STATUS_PENDING;
TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
wsa, wsa->hSocket, wsa->event, wsa->fd,
*piosb, wsa->user_overlapped, wsa->completion_func );
return wsa;
error:
TRACE ("Error\n");
HeapFree ( GetProcessHeap(), 0, wsa );
TRACE("Error\n");
HeapFree( GetProcessHeap(), 0, wsa );
return NULL;
}
static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
{
PIO_APC_ROUTINE apc;
int type;
NTSTATUS status;
switch (wsa->mode)
{
case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
}
SERVER_START_REQ( register_async )
{
req->handle = wsa->hSocket;
req->io_apc = apc;
req->io_sb = iosb;
req->io_user = wsa;
req->type = type;
req->count = iosb->Information;
status = wine_server_call( req );
}
SERVER_END_REQ;
if ( status ) iosb->u.Status = status;
if ( iosb->u.Status != STATUS_PENDING )
{
(apc)( wsa, iosb, iosb->u.Status );
return iosb->u.Status;
}
NtCurrentTeb()->num_async_io++;
return STATUS_SUCCESS;
}
/***********************************************************************
* WS2_recv (INTERNAL)
*
* Workhorse for both synchronous and asynchronous recv() operations.
*/
static int WS2_recv ( int fd, struct iovec* iov, int count,
static int WS2_recv( int fd, struct iovec* iov, int count,
struct WS_sockaddr *lpFrom, LPINT lpFromlen,
LPDWORD lpFlags )
{
struct msghdr hdr;
int n;
TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
hdr.msg_name = NULL;
......@@ -1044,10 +1055,10 @@ static int WS2_recv ( int fd, struct iovec* iov, int count,
if ( lpFrom )
{
hdr.msg_namelen = *lpFromlen;
hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
if ( !hdr.msg_name )
{
WSASetLastError ( WSAEFAULT );
WSASetLastError( WSAEFAULT );
n = -1;
goto out;
}
......@@ -1066,27 +1077,27 @@ static int WS2_recv ( int fd, struct iovec* iov, int count,
hdr.msg_flags = 0;
#endif
if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
{
TRACE ( "recvmsg error %d\n", errno);
TRACE( "recvmsg error %d\n", errno);
goto out;
}
if ( lpFrom &&
ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
lpFrom, lpFromlen ) != 0 )
{
/* The from buffer was too small, but we read the data
* anyway. Is that really bad?
*/
WSASetLastError ( WSAEFAULT );
WARN ( "Address buffer too small\n" );
WSASetLastError( WSAEFAULT );
WARN( "Address buffer too small\n" );
}
out:
ws_sockaddr_free ( hdr.msg_name, lpFrom );
TRACE ("-> %d\n", n);
ws_sockaddr_free( hdr.msg_name, lpFrom );
TRACE("-> %d\n", n);
return n;
}
......@@ -1095,42 +1106,50 @@ out:
*
* Handler for overlapped recv() operations.
*/
static void WS2_async_recv ( async_private *as )
static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
{
ws2_async* wsa = (ws2_async*) as;
ws2_async* wsa = (ws2_async*) ovp;
int result, err;
TRACE ( "async %p\n", wsa );
TRACE( "(%p %p %lx)\n", wsa, iosb, status );
if ( wsa->async.iosb->u.Status != STATUS_PENDING )
switch (status)
{
TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
return;
}
result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
case STATUS_ALERTED:
result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
wsa->addr, wsa->addrlen.ptr, &wsa->flags );
if (result >= 0)
{
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;
iosb->u.Status = STATUS_SUCCESS;
iosb->Information = result;
TRACE( "received %d bytes\n", result );
_enable_event( wsa->hSocket, FD_READ, 0, 0 );
}
err = wsaErrno ();
else
{
err = wsaErrno();
if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
{
wsa->async.iosb->u.Status = STATUS_PENDING;
_enable_event ( wsa->async.handle, FD_READ, 0, 0 );
TRACE ( "still pending\n" );
iosb->u.Status = STATUS_PENDING;
_enable_event( wsa->hSocket, FD_READ, 0, 0 );
TRACE( "still pending\n" );
}
else
{
wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err );
iosb->u.Status = err; /* FIXME: is this correct ???? */
TRACE( "Error: %x\n", err );
}
}
if (iosb->u.Status == STATUS_PENDING)
ws2_queue_async(wsa, iosb);
else
ws2_async_terminate(wsa, iosb);
break;
default:
FIXME( "status: %ld\n", status );
iosb->u.Status = status;
ws2_async_terminate(wsa, iosb);
return;
}
}
......@@ -1139,22 +1158,22 @@ static void WS2_async_recv ( async_private *as )
*
* Workhorse for both synchronous and asynchronous send() operations.
*/
static int WS2_send ( int fd, struct iovec* iov, int count,
static int WS2_send( int fd, struct iovec* iov, int count,
const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
{
struct msghdr hdr;
int n = -1;
TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
hdr.msg_name = NULL;
if ( to )
{
hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
if ( !hdr.msg_name )
{
WSASetLastError ( WSAEFAULT );
WSASetLastError( WSAEFAULT );
goto out;
}
......@@ -1195,10 +1214,10 @@ static int WS2_send ( int fd, struct iovec* iov, int count,
hdr.msg_flags = 0;
#endif
n = sendmsg (fd, &hdr, dwFlags);
n = sendmsg(fd, &hdr, dwFlags);
out:
ws_sockaddr_free ( hdr.msg_name, to );
ws_sockaddr_free( hdr.msg_name, to );
return n;
}
......@@ -1207,45 +1226,57 @@ out:
*
* Handler for overlapped send() operations.
*/
static void WS2_async_send ( async_private *as )
static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
{
ws2_async* wsa = (ws2_async*) as;
int result, err;
int result;
TRACE ( "async %p\n", wsa );
TRACE( "(%p %p %lx)\n", wsa, iosb, status );
if ( wsa->async.iosb->u.Status != STATUS_PENDING )
switch (status)
{
TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
return;
}
result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
case STATUS_ALERTED:
if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
/* check to see if the data is ready (non-blocking) */
result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
wsa->addr, wsa->addrlen.val, wsa->flags );
if (result >= 0)
{
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;
iosb->u.Status = STATUS_SUCCESS;
iosb->Information = result;
TRACE( "sent %d bytes\n", result );
_enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
}
err = wsaErrno ();
else
{
int err = wsaErrno();
if ( err == WSAEINTR )
{
wsa->async.iosb->u.Status = STATUS_PENDING;
_enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
TRACE ( "still pending\n" );
iosb->u.Status = STATUS_PENDING;
_enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
TRACE( "still pending\n" );
}
else
{
/* We set the status to a winsock error code and check for that
later in NtStatusToWSAError () */
wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err );
iosb->u.Status = err;
TRACE( "Error: %x\n", err );
}
}
if (iosb->u.Status == STATUS_PENDING)
ws2_queue_async(wsa, iosb);
else
ws2_async_terminate(wsa, iosb);
break;
default:
FIXME( "status: %ld\n", status );
iosb->u.Status = status;
ws2_async_terminate(wsa, iosb);
return;
}
}
/***********************************************************************
......@@ -1253,28 +1284,33 @@ static void WS2_async_send ( async_private *as )
*
* Handler for shutdown() operations on overlapped sockets.
*/
static void WS2_async_shutdown ( async_private *as )
static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
{
ws2_async* wsa = (ws2_async*) as;
int err = 1;
TRACE ( "async %p %d\n", wsa, wsa->async.type );
switch ( wsa->async.type )
TRACE( "async %p %d\n", wsa, wsa->mode );
switch (status)
{
case ASYNC_TYPE_READ:
err = shutdown ( wsa->async.fd, 0 );
break;
case ASYNC_TYPE_WRITE:
err = shutdown ( wsa->async.fd, 1 );
case STATUS_ALERTED:
switch ( wsa->mode )
{
case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
default: ERR("invalid mode: %d\n", wsa->mode );
}
iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
if (iosb->u.Status == STATUS_PENDING)
ws2_queue_async(wsa, iosb);
else
ws2_async_terminate(wsa, iosb);
break;
default:
ERR ("invalid type: %d\n", wsa->async.type );
iosb->u.Status = status;
ws2_async_terminate(wsa, iosb);
break;
}
if ( err )
wsa->async.iosb->u.Status = wsaErrno ();
else
wsa->async.iosb->u.Status = STATUS_SUCCESS;
}
/***********************************************************************
......@@ -1282,43 +1318,44 @@ static void WS2_async_shutdown ( async_private *as )
*
* Helper function for WS_shutdown() on overlapped sockets.
*/
static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
{
struct ws2_async *wsa;
int ret, err = WSAEFAULT;
DWORD dwflags = 0;
int len = 0;
LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
IO_STATUS_BLOCK *iosb;
TRACE ("s %d fd %d type %d\n", s, fd, type);
TRACE("s %d fd %d mode %d\n", s, fd, mode);
if (!ovl)
goto out;
ovl->hEvent = WSACreateEvent ();
ovl->hEvent = WSACreateEvent();
if ( ovl->hEvent == WSA_INVALID_EVENT )
goto out_free;
wsa = WS2_make_async ( s, fd, type, NULL, 0,
&dwflags, NULL, &len, ovl, NULL );
wsa = WS2_make_async( s, fd, mode, NULL, 0,
&dwflags, NULL, &len, ovl, NULL, &iosb );
if ( !wsa )
goto out_close;
/* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
wsa->user_overlapped = NULL;
wsa->async.func = WS2_async_shutdown;
if ( (ret = register_new_async ( &wsa->async )) )
if ( (ret = ws2_queue_async( wsa, iosb )) )
{
err = NtStatusToWSAError ( ret );
err = NtStatusToWSAError( ret );
goto out;
}
/* Try immediate completion */
while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
return 0;
out_close:
WSACloseEvent ( ovl->hEvent );
WSACloseEvent( ovl->hEvent );
out_free:
HeapFree ( GetProcessHeap(), 0, ovl );
HeapFree( GetProcessHeap(), 0, iosb );
HeapFree( GetProcessHeap(), 0, ovl );
out:
return err;
}
......@@ -1503,13 +1540,13 @@ connect_success:
/***********************************************************************
* WSAConnect (WS2_32.30)
*/
int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
LPQOS lpSQOS, LPQOS lpGQOS )
{
if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
FIXME ("unsupported parameters!\n");
return WS_connect ( s, name, namelen );
FIXME("unsupported parameters!\n");
return WS_connect( s, name, namelen );
}
......@@ -1849,7 +1886,7 @@ char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
*
* FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
*/
INT WINAPI WSAIoctl (SOCKET s,
INT WINAPI WSAIoctl(SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
......@@ -1874,7 +1911,7 @@ INT WINAPI WSAIoctl (SOCKET s,
INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
DWORD size, numInt, apiReturn;
TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
TRACE("-> SIO_GET_INTERFACE_LIST request\n");
if (!lpbOutBuffer)
{
......@@ -1910,7 +1947,7 @@ INT WINAPI WSAIoctl (SOCKET s,
HeapFree(GetProcessHeap(),0,table);
release_sock_fd( s, fd );
WSASetLastError(WSAEFAULT);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
for (ptr = table, numInt = 0; ptr;
ptr = ptr->Next, intArray++, numInt++)
......@@ -1923,11 +1960,11 @@ INT WINAPI WSAIoctl (SOCKET s,
ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
{
ERR ("Error obtaining status flags for socket!\n");
ERR("Error obtaining status flags for socket!\n");
HeapFree(GetProcessHeap(),0,table);
release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
else
{
......@@ -1969,11 +2006,11 @@ INT WINAPI WSAIoctl (SOCKET s,
}
else
{
ERR ("Unable to get interface table!\n");
ERR("Unable to get interface table!\n");
release_sock_fd( s, fd );
HeapFree(GetProcessHeap(),0,table);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
HeapFree(GetProcessHeap(),0,table);
}
......@@ -1981,15 +2018,15 @@ INT WINAPI WSAIoctl (SOCKET s,
{
release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
}
else
{
ERR ("Unable to get interface table!\n");
ERR("Unable to get interface table!\n");
release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
/* Calculate the size of the array being returned */
*lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
......@@ -2006,12 +2043,12 @@ INT WINAPI WSAIoctl (SOCKET s,
WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
release_sock_fd( s, fd );
WSASetLastError(WSAEOPNOTSUPP);
return (SOCKET_ERROR);
return SOCKET_ERROR;
}
/* Function executed with no errors */
release_sock_fd( s, fd );
return (0);
return 0;
}
......@@ -2130,7 +2167,7 @@ int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
wsabuf.len = len;
wsabuf.buf = buf;
if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
......@@ -2148,7 +2185,7 @@ int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
wsabuf.len = len;
wsabuf.buf = buf;
if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
......@@ -2222,7 +2259,7 @@ int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
wsabuf.len = len;
wsabuf.buf = (char*) buf;
if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
......@@ -2236,7 +2273,7 @@ INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
NULL, 0, lpOverlapped, lpCompletionRoutine );
}
......@@ -2245,7 +2282,7 @@ INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
*/
INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
{
return WS_shutdown ( s, SD_SEND );
return WS_shutdown( s, SD_SEND );
}
......@@ -2262,19 +2299,20 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
int n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
struct ws2_async *wsa;
IO_STATUS_BLOCK* iosb;
TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine);
fd = get_sock_fd( s, GENERIC_WRITE, &flags );
TRACE ( "fd=%d, flags=%x\n", fd, flags );
TRACE( "fd=%d, flags=%x\n", fd, flags );
if ( fd == -1 ) return SOCKET_ERROR;
if (flags & FD_FLAG_SEND_SHUTDOWN)
{
WSASetLastError ( WSAESHUTDOWN );
WSASetLastError( WSAESHUTDOWN );
goto err_close;
}
......@@ -2284,7 +2322,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
goto err_close;
}
iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
if ( !iovec )
{
......@@ -2300,37 +2338,37 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
{
wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
&dwFlags, (struct WS_sockaddr*) to, &tolen,
lpOverlapped, lpCompletionRoutine );
lpOverlapped, lpCompletionRoutine, &iosb );
if ( !wsa )
{
err = WSAEFAULT;
goto err_free;
}
if ( ( ret = register_new_async ( &wsa->async )) )
if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
{
err = NtStatusToWSAError ( ret );
err = NtStatusToWSAError( ret );
if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa );
HeapFree( GetProcessHeap(), 0, iosb );
HeapFree( GetProcessHeap(), 0, wsa );
goto err_free;
}
/* Try immediate completion */
if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
if ( lpOverlapped )
{
if ( WSAGetOverlappedResult ( s, lpOverlapped,
if ( WSAGetOverlappedResult( s, lpOverlapped,
lpNumberOfBytesSent, FALSE, &dwFlags) )
return 0;
if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
goto error;
}
WSASetLastError ( WSA_IO_PENDING );
WSASetLastError( WSA_IO_PENDING );
return SOCKET_ERROR;
}
......@@ -2344,31 +2382,31 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
}
}
n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
if ( n == -1 )
{
err = wsaErrno();
if ( err == WSAEWOULDBLOCK )
_enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
_enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
goto err_free;
}
TRACE(" -> %i bytes\n", n);
*lpNumberOfBytesSent = n;
HeapFree ( GetProcessHeap(), 0, iovec );
HeapFree( GetProcessHeap(), 0, iovec );
release_sock_fd( s, fd );
return 0;
err_free:
HeapFree ( GetProcessHeap(), 0, iovec );
HeapFree( GetProcessHeap(), 0, iovec );
err_close:
release_sock_fd( s, fd );
error:
WARN (" -> ERROR %d\n", err);
WSASetLastError (err);
WARN(" -> ERROR %d\n", err);
WSASetLastError(err);
return SOCKET_ERROR;
}
......@@ -2384,7 +2422,7 @@ int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
wsabuf.len = len;
wsabuf.buf = (char*) buf;
if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
......@@ -2460,7 +2498,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
/* Returning 0 is better for now than returning a SOCKET_ERROR */
return 0;
break;
default:
FIXME("opt_name:%x\n", optname);
return SOCKET_ERROR;
......@@ -2587,13 +2624,13 @@ int WINAPI WS_shutdown(SOCKET s, int how)
case SD_BOTH:
default:
fd0 = fd;
fd1 = get_sock_fd ( s, 0, NULL );
fd1 = get_sock_fd( s, 0, NULL );
break;
}
if ( fd0 != -1 )
{
err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
if ( err )
{
release_sock_fd( s, fd0 );
......@@ -2602,7 +2639,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
}
if ( fd1 != -1 )
{
err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
if ( err )
{
release_sock_fd( s, fd1 );
......@@ -2614,7 +2651,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
{
if ( shutdown( fd, how ) )
{
err = wsaErrno ();
err = wsaErrno();
release_sock_fd( s, fd );
goto error;
}
......@@ -2627,7 +2664,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
error:
_enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
WSASetLastError ( err );
WSASetLastError( err );
return SOCKET_ERROR;
}
......@@ -2638,7 +2675,7 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
{
TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
return WSASocketA ( af, type, protocol, NULL, 0,
return WSASocketA( af, type, protocol, NULL, 0,
get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
}
......@@ -2913,34 +2950,40 @@ int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
/**********************************************************************
* WSAGetOverlappedResult (WS2_32.40)
*/
BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
LPDWORD lpcbTransfer, BOOL fWait,
LPDWORD lpdwFlags )
{
DWORD r;
TRACE ( "socket %04x ovl %p trans %p, wait %d flags %p\n",
TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
if ( !(lpOverlapped && lpOverlapped->hEvent) )
if ( lpOverlapped == NULL )
{
ERR ( "Invalid pointer\n" );
WSASetLastError (WSA_INVALID_PARAMETER);
ERR( "Invalid pointer\n" );
WSASetLastError(WSA_INVALID_PARAMETER);
return FALSE;
}
if ( fWait )
{
while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
if (lpOverlapped->hEvent)
while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
INFINITE, TRUE) == STATUS_USER_APC );
else /* busy loop */
while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
Sleep( 10 );
}
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. */
while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
if ( r == WAIT_OBJECT_0 )
NtSetEvent ( lpOverlapped->hEvent, NULL );
while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
NtSetEvent( lpOverlapped->hEvent, NULL );
}
if ( lpcbTransfer )
......@@ -2954,11 +2997,11 @@ BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
case STATUS_SUCCESS:
return TRUE;
case STATUS_PENDING:
WSASetLastError ( WSA_IO_INCOMPLETE );
if (fWait) ERR ("PENDING status after waiting!\n");
WSASetLastError( WSA_IO_INCOMPLETE );
if (fWait) ERR("PENDING status after waiting!\n");
return FALSE;
default:
WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
return FALSE;
}
}
......@@ -3267,7 +3310,7 @@ static int list_dup(char** l_src, char** l_to, int item_size)
p += count;
}
l_to[i] = NULL;
return (p - (char *)l_to);
return p - (char *)l_to;
}
/* ----- hostent */
......@@ -3453,12 +3496,12 @@ UINT wsaHerrno(int loc_errno)
/***********************************************************************
* WSARecv (WS2_32.67)
*/
int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
NULL, NULL, lpOverlapped, lpCompletionRoutine);
}
......@@ -3475,6 +3518,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
int n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
struct ws2_async *wsa;
IO_STATUS_BLOCK* iosb;
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
......@@ -3482,17 +3526,17 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
lpOverlapped, lpCompletionRoutine);
fd = get_sock_fd( s, GENERIC_READ, &flags );
TRACE ( "fd=%d, flags=%x\n", fd, flags );
TRACE( "fd=%d, flags=%x\n", fd, flags );
if (fd == -1) return SOCKET_ERROR;
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
WSASetLastError ( WSAESHUTDOWN );
WSASetLastError( WSAESHUTDOWN );
goto err_close;
}
iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
{
err = WSAEFAULT;
......@@ -3507,9 +3551,9 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
{
wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
lpFlags, lpFrom, lpFromlen,
lpOverlapped, lpCompletionRoutine );
lpOverlapped, lpCompletionRoutine, &iosb );
if ( !wsa )
{
......@@ -3517,28 +3561,28 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
goto err_free;
}
if ( ( ret = register_new_async ( &wsa->async )) )
if ( ( ret = ws2_queue_async( wsa, iosb )) )
{
err = NtStatusToWSAError ( ret );
err = NtStatusToWSAError( ret );
if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa );
HeapFree( GetProcessHeap(), 0, iosb );
HeapFree( GetProcessHeap(), 0, wsa );
goto err_free;
}
/* Try immediate completion */
if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
if ( lpOverlapped )
{
if ( WSAGetOverlappedResult ( s, lpOverlapped,
if ( WSAGetOverlappedResult( s, lpOverlapped,
lpNumberOfBytesRecvd, FALSE, lpFlags) )
return 0;
if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
goto error;
}
WSASetLastError ( WSA_IO_PENDING );
WSASetLastError( WSA_IO_PENDING );
return SOCKET_ERROR;
}
......@@ -3555,7 +3599,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
}
}
n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
if ( n == -1 )
{
err = wsaErrno();
......@@ -3565,21 +3609,21 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
TRACE(" -> %i bytes\n", n);
*lpNumberOfBytesRecvd = n;
HeapFree (GetProcessHeap(), 0, iovec);
HeapFree(GetProcessHeap(), 0, iovec);
release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
return 0;
err_free:
HeapFree (GetProcessHeap(), 0, iovec);
HeapFree(GetProcessHeap(), 0, iovec);
err_close:
release_sock_fd( s, fd );
error:
WARN(" -> ERROR %d\n", err);
WSASetLastError ( err );
WSASetLastError( err );
return SOCKET_ERROR;
}
......@@ -3656,14 +3700,14 @@ SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
return cs;
case CF_DEFER:
SERVER_START_REQ ( set_socket_deferred )
SERVER_START_REQ( set_socket_deferred )
{
req->handle = SOCKET2HANDLE (s);
req->deferred = SOCKET2HANDLE (cs);
req->handle = SOCKET2HANDLE(s);
req->deferred = SOCKET2HANDLE(cs);
if ( !wine_server_call_err ( req ) )
{
SetLastError ( WSATRY_AGAIN );
WS_closesocket ( cs );
SetLastError( WSATRY_AGAIN );
WS_closesocket( cs );
}
}
SERVER_END_REQ;
......
/*
* 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 <thread.h>
#include <ntstatus.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;
wine_server_release_fd( ovp->handle, 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;
}
inline static NTSTATUS register_old_async( async_private *ovp )
{
return __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 */
......@@ -112,7 +112,7 @@ typedef struct _TEB
int wait_fd[2]; /* --3 214 fd for sleeping server requests */
struct debug_info *debug_info; /* --3 21c Info for debugstr functions */
void *pthread_data; /* --3 220 Data for pthread emulation */
struct async_private *pending_list; /* --3 224 list of pending async operations */
DWORD num_async_io; /* --3 224 number of pending async I/O in the server */
void *driver_data; /* --3 228 Graphics driver private data */
DWORD dpmi_vif; /* --3 22c Protected mode virtual interrupt flag */
DWORD vm86_pending; /* --3 230 Data for vm86 mode */
......
......@@ -2282,21 +2282,33 @@ struct register_async_request
struct request_header __header;
obj_handle_t handle;
int type;
void* overlapped;
void* io_apc;
void* io_sb;
void* io_user;
int count;
unsigned int status;
};
struct register_async_reply
{
struct reply_header __header;
};
#define ASYNC_TYPE_NONE 0x00
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
struct cancel_async_request
{
struct request_header __header;
obj_handle_t handle;
};
struct cancel_async_reply
{
struct reply_header __header;
};
struct create_named_pipe_request
{
struct request_header __header;
......@@ -3274,6 +3286,7 @@ enum request
REQ_get_serial_info,
REQ_set_serial_info,
REQ_register_async,
REQ_cancel_async,
REQ_create_named_pipe,
REQ_open_named_pipe,
REQ_connect_named_pipe,
......@@ -3460,6 +3473,7 @@ union generic_request
struct get_serial_info_request get_serial_info_request;
struct set_serial_info_request set_serial_info_request;
struct register_async_request register_async_request;
struct cancel_async_request cancel_async_request;
struct create_named_pipe_request create_named_pipe_request;
struct open_named_pipe_request open_named_pipe_request;
struct connect_named_pipe_request connect_named_pipe_request;
......@@ -3644,6 +3658,7 @@ union generic_reply
struct get_serial_info_reply get_serial_info_reply;
struct set_serial_info_reply set_serial_info_reply;
struct register_async_reply register_async_reply;
struct cancel_async_reply cancel_async_reply;
struct create_named_pipe_reply create_named_pipe_reply;
struct open_named_pipe_reply open_named_pipe_reply;
struct connect_named_pipe_reply connect_named_pipe_reply;
......@@ -3697,6 +3712,6 @@ union generic_reply
struct set_global_windows_reply set_global_windows_reply;
};
#define SERVER_PROTOCOL_VERSION 153
#define SERVER_PROTOCOL_VERSION 154
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -6,7 +6,6 @@ VPATH = @srcdir@
MODULE = none
C_SRCS = \
async.c \
atom.c \
change.c \
class.c \
......
/*
* Server-side support for async i/o operations
*
* Copyright (C) 1998 Alexandre Julliard
* Copyright (C) 2000 Mike McCormack
*
* 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
*/
#include "config.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "handle.h"
#include "file.h"
#include "thread.h"
#include "request.h"
#include "async.h"
void destroy_async( struct async *async )
{
struct async_queue *aq = async->q;
/*fprintf(stderr,"destroyed async %p\n",async->overlapped); */
if(async->timeout)
remove_timeout_user(async->timeout);
async->timeout = NULL;
if(async->prev)
async->prev->next = async->next;
else
aq->head = async->next;
if(async->next)
async->next->prev = async->prev;
else
aq->tail = async->prev;
async->q = NULL;
async->next = NULL;
async->prev = NULL;
release_object( async->thread );
free(async);
}
void async_notify(struct async *async, int status)
{
/* fprintf(stderr,"notifying %p!\n",async->overlapped); */
async->status = status;
thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1,
async->overlapped, (void *)status, NULL );
}
void destroy_async_queue( struct async_queue *q )
{
while(q->head)
{
async_notify(q->head, STATUS_CANCELLED);
destroy_async(q->head);
}
}
struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped)
{
struct async *async;
/* fprintf(stderr,"find_async: %p\n",overlapped); */
if(!q)
return NULL;
for(async = q->head; async; async = async->next)
if((async->overlapped==overlapped) && (async->thread == thread))
return async;
return NULL;
}
void async_insert(struct async_queue *q, struct async *async)
{
async->q = q;
async->prev = q->tail;
async->next = NULL;
if(q->tail)
q->tail->next = async;
else
q->head = async;
q->tail = async;
}
static void async_callback(void *private)
{
struct async *async = (struct async *)private;
/* fprintf(stderr,"%p timeout out\n",async->overlapped); */
async->timeout = NULL;
async_notify(async, STATUS_TIMEOUT);
destroy_async(async);
}
struct async *create_async(struct object *obj, struct thread *thread,
void *overlapped)
{
struct async *async = (struct async *) malloc(sizeof(struct async));
if(!async)
{
set_error(STATUS_NO_MEMORY);
return NULL;
}
async->obj = obj;
async->thread = (struct thread *)grab_object(thread);
async->overlapped = overlapped;
async->next = NULL;
async->prev = NULL;
async->q = NULL;
async->status = STATUS_PENDING;
async->timeout = NULL;
return async;
}
void async_add_timeout(struct async *async, int timeout)
{
if(timeout)
{
gettimeofday( &async->when, 0 );
add_timeout( &async->when, timeout );
async->timeout = add_timeout_user( &async->when, async_callback, async );
}
}
/*
* Async i/o definitions
*
* Copyright (C) 2000 Mike McCormack
*
* 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
*/
#ifndef _SERVER_ASYNC_
#define _SERVER_ASYNC_
#include <sys/time.h>
#include "object.h"
struct async_queue;
struct async
{
struct object *obj;
struct thread *thread;
void *overlapped;
unsigned int status;
struct timeval when;
struct timeout_user *timeout;
struct async *next,*prev;
struct async_queue *q;
};
struct async_queue
{
struct async *head;
struct async *tail;
};
void destroy_async( struct async *async );
void destroy_async_queue( struct async_queue *q );
void async_notify(struct async *async, int status);
struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped);
void async_insert(struct async_queue *q, struct async *async);
struct async *create_async(struct object *obj, struct thread *thread,
void *overlapped);
void async_add_timeout(struct async *async, int timeout);
static inline void init_async_queue(struct async_queue *q)
{
q->head = q->tail = NULL;
}
#define IS_READY(q) (((q).head) && ((q).head->status==STATUS_PENDING))
#endif /* _SERVER_ASYNC_ */
......@@ -980,6 +980,89 @@ void unlock_fd( struct fd *fd, file_pos_t start, file_pos_t count )
/****************************************************************/
/* asynchronous operations support */
struct async
{
struct fd *fd;
struct thread *thread;
void *apc;
void *user;
void *sb;
struct timeval when;
struct timeout_user *timeout;
struct async *next;
struct async **head;
};
/* cb for timeout on an async request */
static void async_callback(void *private)
{
struct async *async = (struct async *)private;
/* fprintf(stderr, "async timeout out %p\n", async); */
async->timeout = NULL;
async_terminate( async, STATUS_TIMEOUT );
}
/* create an async on a given queue of a fd */
struct async *create_async(struct fd *fd, struct thread *thread,
int timeout, struct async **head,
void *io_apc, void *io_user, void* io_sb)
{
struct async *async = mem_alloc( sizeof(struct async) );
struct async **p;
if (!async) return NULL;
async->fd = fd;
async->thread = (struct thread *)grab_object(thread);
async->apc = io_apc;
async->user = io_user;
async->sb = io_sb;
async->head = head;
async->next = NULL;
for (p = head; *p; p = &(*p)->next);
*p = async;
if (timeout)
{
gettimeofday( &async->when, 0 );
add_timeout( &async->when, timeout );
async->timeout = add_timeout_user( &async->when, async_callback, async );
}
else async->timeout = NULL;
return async;
}
/* notifies client thread of new status of its async request */
/* destroys the server side of it */
void async_terminate( struct async *async, int status )
{
struct async** p;
thread_queue_apc( async->thread, NULL, async->apc, APC_ASYNC_IO,
1, async->user, async->sb, (void *)status );
if (async->timeout) remove_timeout_user( async->timeout );
async->timeout = NULL;
for (p = async->head; *p; p = &(*p)->next)
{
if (*p == async)
{
*p = async->next;
break;
}
}
release_object( async->thread );
free( async );
}
/****************************************************************/
/* file descriptor functions */
static void fd_dump( struct object *obj, int verbose )
......@@ -1309,7 +1392,14 @@ int no_get_file_info( struct fd *fd )
}
/* default queue_async() routine */
void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count )
void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb,
int type, int count)
{
set_error( STATUS_OBJECT_TYPE_MISMATCH );
}
/* default cancel_async() routine */
void no_cancel_async( struct fd *fd )
{
set_error( STATUS_OBJECT_TYPE_MISMATCH );
}
......@@ -1338,7 +1428,7 @@ DECL_HANDLER(flush_file)
if (fd)
{
fd->fd_ops->flush( fd, &event );
if( event )
if ( event )
{
reply->event = alloc_handle( current->process, event, SYNCHRONIZE, 0 );
}
......@@ -1372,26 +1462,41 @@ DECL_HANDLER(register_async)
{
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
/*
/*
* The queue_async method must do the following:
*
* 1. Get the async_queue for the request of given type.
* 2. Call find_async() to look for the specific client request in the queue (=> NULL if not found).
* 3. If status is STATUS_PENDING:
* a) If no async request found in step 2 (new request): call create_async() to initialize one.
* b) Set request's status to STATUS_PENDING.
* c) If the "queue" field of the async request is NULL: call async_insert() to put it into the queue.
* Otherwise:
* If the async request was found in step 2, destroy it by calling destroy_async().
* 4. Carry out any operations necessary to adjust the object's poll events
* 2. Create a new asynchronous request for the selected queue
* 3. Carry out any operations necessary to adjust the object's poll events
* Usually: set_elect_events (obj, obj->ops->get_poll_events()).
*
* 4. When the async request is triggered, then send back (with a proper APC)
* the trigger (STATUS_ALERTED) to the thread that posted the request.
* async_destroy() is to be called: it will both notify the sender about
* the trigger and destroy the request by itself
* See also the implementations in file.c, serial.c, and sock.c.
*/
*/
if (fd)
{
fd->fd_ops->queue_async( fd, req->io_apc, req->io_user, req->io_sb,
req->type, req->count );
release_object( fd );
}
}
/* cancels all async I/O */
DECL_HANDLER(cancel_async)
{
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
if (fd)
{
fd->fd_ops->queue_async( fd, req->overlapped, req->status, req->type, req->count );
/* Note: we don't kill the queued APC_ASYNC_IO on this thread because
* NtCancelIoFile() will force the pending APC to be run. Since,
* Windows only guarantees that the current thread will have no async
* operation on the current fd when NtCancelIoFile returns, this shall
* do the work.
*/
fd->fd_ops->cancel_async( fd );
release_object( fd );
}
}
......@@ -50,7 +50,6 @@
#include "handle.h"
#include "thread.h"
#include "request.h"
#include "async.h"
struct file
{
......@@ -58,8 +57,8 @@ struct file
struct fd *fd; /* file descriptor for this file */
unsigned int access; /* file access (GENERIC_READ/WRITE) */
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
struct async_queue read_q;
struct async_queue write_q;
struct async *read_q;
struct async *write_q;
};
static void file_dump( struct object *obj, int verbose );
......@@ -70,7 +69,8 @@ static int file_get_poll_events( struct fd *fd );
static void file_poll_event( struct fd *fd, int event );
static int file_flush( struct fd *fd, struct event **event );
static int file_get_info( struct fd *fd );
static void file_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count );
static void file_queue_async( struct fd *fd, void *apc, void *user, void* iosb, int type, int count );
static void file_cancel_async( struct fd *fd );
static const struct object_ops file_ops =
{
......@@ -90,7 +90,8 @@ static const struct fd_ops file_fd_ops =
file_poll_event, /* poll_event */
file_flush, /* flush */
file_get_info, /* get_file_info */
file_queue_async /* queue_async */
file_queue_async, /* queue_async */
file_cancel_async /* cancel_async */
};
static inline int is_overlapped( const struct file *file )
......@@ -141,6 +142,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
case FILE_OVERWRITE: flags = O_TRUNC; break;
default: set_error( STATUS_INVALID_PARAMETER ); goto error;
}
switch(access & (GENERIC_READ | GENERIC_WRITE))
{
case 0: break;
......@@ -160,8 +162,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
file->options = options;
if (is_overlapped( file ))
{
init_async_queue (&file->read_q);
init_async_queue (&file->write_q);
file->read_q = file->write_q = NULL;
}
/* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
......@@ -236,14 +237,14 @@ static void file_poll_event( struct fd *fd, int event )
assert( file->obj.ops == &file_ops );
if (is_overlapped( file ))
{
if( IS_READY(file->read_q) && (POLLIN & event) )
if ( file->read_q && (POLLIN & event) )
{
async_notify(file->read_q.head, STATUS_ALERTED);
async_terminate( file->read_q, STATUS_ALERTED );
return;
}
if( IS_READY(file->write_q) && (POLLOUT & event) )
if ( file->write_q && (POLLOUT & event) )
{
async_notify(file->write_q.head, STATUS_ALERTED);
async_terminate( file->write_q, STATUS_ALERTED );
return;
}
}
......@@ -266,58 +267,53 @@ static int file_get_info( struct fd *fd )
else return 0;
}
static void file_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
static void file_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
{
struct file *file = get_fd_user( fd );
struct async *async;
struct async_queue *q;
struct async **head;
int events;
assert( file->obj.ops == &file_ops );
if (!is_overlapped( file ))
{
set_error ( STATUS_INVALID_HANDLE );
set_error( STATUS_INVALID_HANDLE );
return;
}
switch(type)
switch (type)
{
case ASYNC_TYPE_READ:
q = &file->read_q;
head = &file->read_q;
break;
case ASYNC_TYPE_WRITE:
q = &file->write_q;
head = &file->write_q;
break;
default:
set_error( STATUS_INVALID_PARAMETER );
return;
}
async = find_async ( q, current, ptr );
if ( status == STATUS_PENDING )
{
int events;
if ( !async )
async = create_async ( &file->obj, current, ptr );
if ( !async )
if (!create_async( fd, current, 0, head, apc, user, iosb ))
return;
async->status = STATUS_PENDING;
if ( !async->q )
async_insert( q, async );
/* Check if the new pending request can be served immediately */
events = check_fd_events( fd, file_get_poll_events( fd ) );
if (events) file_poll_event ( fd, events );
}
else if ( async ) destroy_async ( async );
else set_error ( STATUS_INVALID_PARAMETER );
if (events) file_poll_event( fd, events );
set_fd_events( fd, file_get_poll_events( fd ));
}
static void file_cancel_async( struct fd *fd )
{
struct file *file = get_fd_user( fd );
assert( file->obj.ops == &file_ops );
async_terminate_queue( &file->read_q, STATUS_CANCELLED );
async_terminate_queue( &file->write_q, STATUS_CANCELLED );
}
static struct fd *file_get_fd( struct object *obj )
{
struct file *file = (struct file *)obj;
......@@ -332,8 +328,8 @@ static void file_destroy( struct object *obj )
if (is_overlapped( file ))
{
destroy_async_queue (&file->read_q);
destroy_async_queue (&file->write_q);
async_terminate_queue( &file->read_q, STATUS_CANCELLED );
async_terminate_queue( &file->write_q, STATUS_CANCELLED );
}
if (file->fd) release_object( file->fd );
}
......
......@@ -38,8 +38,10 @@ struct fd_ops
int (*flush)(struct fd *, struct event **);
/* get file information */
int (*get_file_info)(struct fd *);
/* queue an async operation - see register_async handler in async.c*/
void (*queue_async)(struct fd *, void* ptr, unsigned int status, int type, int count);
/* queue an async operation */
void (*queue_async)(struct fd *, void* apc, void* user, void* io_sb, int type, int count);
/* cancel an async operation */
void (*cancel_async)(struct fd *);
};
/* file descriptor functions */
......@@ -65,7 +67,8 @@ extern int default_fd_signaled( struct object *obj, struct thread *thread );
extern void default_poll_event( struct fd *fd, int event );
extern int no_flush( struct fd *fd, struct event **event );
extern int no_get_file_info( struct fd *fd );
extern void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count );
extern void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, int type, int count);
extern void no_cancel_async( struct fd *fd );
extern void main_loop(void);
inline static struct fd *get_obj_fd( struct object *obj ) { return obj->ops->get_fd( obj ); }
......@@ -107,4 +110,14 @@ extern void sigio_callback(void);
extern int is_serial_fd( struct fd *fd );
extern struct object *create_serial( struct fd *fd, unsigned int options );
/* async I/O functions */
extern struct async *create_async( struct fd *fd, struct thread *thread, int timeout,
struct async **head, void *, void *, void *);
extern void async_terminate( struct async *async, int status );
static inline void async_terminate_queue( struct async **head, int status )
{
while (*head) async_terminate( *head, status );
}
#endif /* __WINE_SERVER_FILE_H */
......@@ -151,7 +151,8 @@ static const struct fd_ops pipe_server_fd_ops =
default_poll_event, /* poll_event */
pipe_server_flush, /* flush */
pipe_end_get_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async, /* cancel_async */
};
/* client end functions */
......@@ -178,7 +179,8 @@ static const struct fd_ops pipe_client_fd_ops =
default_poll_event, /* poll_event */
pipe_client_flush, /* flush */
pipe_end_get_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async /* cancel_async */
};
static void named_pipe_dump( struct object *obj, int verbose )
......
......@@ -76,7 +76,8 @@ static const struct fd_ops process_fd_ops =
process_poll_event, /* poll_event */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async /* cancel async */
};
/* process startup info */
......
......@@ -1615,20 +1615,26 @@ enum message_type
#define SERIALINFO_SET_ERROR 0x04
/* Create / reschedule an async I/O */
/* Create an async I/O */
@REQ(register_async)
obj_handle_t handle; /* handle to comm port, socket or file */
int type;
void* overlapped;
int count;
unsigned int status;
int type; /* type of queue to look after */
void* io_apc; /* APC routine to queue upon end of async */
void* io_sb; /* I/O status block (unique across all async on this handle) */
void* io_user; /* data to pass back to caller */
int count; /* count - usually # of bytes to be read/written */
@END
#define ASYNC_TYPE_NONE 0x00
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
/* Cancel all async op on a fd */
@REQ(cancel_async)
obj_handle_t handle; /* handle to comm port, socket or file */
@END
/* Create a named pipe */
@REQ(create_named_pipe)
unsigned int openmode;
......
......@@ -100,7 +100,8 @@ static const struct fd_ops master_socket_fd_ops =
master_socket_poll_event, /* poll_event */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async /* cancel_async */
};
......
......@@ -231,6 +231,7 @@ DECL_HANDLER(kill_win_timer);
DECL_HANDLER(get_serial_info);
DECL_HANDLER(set_serial_info);
DECL_HANDLER(register_async);
DECL_HANDLER(cancel_async);
DECL_HANDLER(create_named_pipe);
DECL_HANDLER(open_named_pipe);
DECL_HANDLER(connect_named_pipe);
......@@ -416,6 +417,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_serial_info,
(req_handler)req_set_serial_info,
(req_handler)req_register_async,
(req_handler)req_cancel_async,
(req_handler)req_create_named_pipe,
(req_handler)req_open_named_pipe,
(req_handler)req_connect_named_pipe,
......
......@@ -53,7 +53,6 @@
#include "handle.h"
#include "thread.h"
#include "request.h"
#include "async.h"
static void serial_dump( struct object *obj, int verbose );
static struct fd *serial_get_fd( struct object *obj );
......@@ -63,7 +62,8 @@ static int serial_get_poll_events( struct fd *fd );
static void serial_poll_event( struct fd *fd, int event );
static int serial_get_info( struct fd *fd );
static int serial_flush( struct fd *fd, struct event **event );
static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count);
static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
static void serial_cancel_async( struct fd *fd );
struct serial
{
......@@ -83,9 +83,9 @@ struct serial
struct termios original;
struct async_queue read_q;
struct async_queue write_q;
struct async_queue wait_q;
struct async *read_q;
struct async *write_q;
struct async *wait_q;
/* FIXME: add dcb, comm status, handler module, sharing */
};
......@@ -108,7 +108,8 @@ static const struct fd_ops serial_fd_ops =
serial_poll_event, /* poll_event */
serial_flush, /* flush */
serial_get_info, /* get_file_info */
serial_queue_async /* queue_async */
serial_queue_async, /* queue_async */
serial_cancel_async /* cancel_async */
};
/* check if the given fd is a serial port */
......@@ -144,9 +145,7 @@ struct object *create_serial( struct fd *fd, unsigned int options )
serial->writeconst = 0;
serial->eventmask = 0;
serial->commerror = 0;
init_async_queue(&serial->read_q);
init_async_queue(&serial->write_q);
init_async_queue(&serial->wait_q);
serial->read_q = serial->write_q = serial->wait_q = NULL;
if (!(serial->fd = create_anonymous_fd( &serial_fd_ops, unix_fd, &serial->obj )))
{
release_object( serial );
......@@ -165,9 +164,9 @@ static void serial_destroy( struct object *obj)
{
struct serial *serial = (struct serial *)obj;
destroy_async_queue(&serial->read_q);
destroy_async_queue(&serial->write_q);
destroy_async_queue(&serial->wait_q);
async_terminate_queue( &serial->read_q, STATUS_CANCELLED );
async_terminate_queue( &serial->write_q, STATUS_CANCELLED );
async_terminate_queue( &serial->wait_q, STATUS_CANCELLED );
if (serial->fd) release_object( serial->fd );
}
......@@ -189,12 +188,9 @@ static int serial_get_poll_events( struct fd *fd )
int events = 0;
assert( serial->obj.ops == &serial_ops );
if(IS_READY(serial->read_q))
events |= POLLIN;
if(IS_READY(serial->write_q))
events |= POLLOUT;
if(IS_READY(serial->wait_q))
events |= POLLIN;
if (serial->read_q) events |= POLLIN;
if (serial->write_q) events |= POLLOUT;
if (serial->wait_q) events |= POLLIN;
/* fprintf(stderr,"poll events are %04x\n",events); */
......@@ -225,39 +221,40 @@ static void serial_poll_event(struct fd *fd, int event)
/* fprintf(stderr,"Poll event %02x\n",event); */
if(IS_READY(serial->read_q) && (POLLIN & event) )
async_notify(serial->read_q.head,STATUS_ALERTED);
if (serial->read_q && (POLLIN & event) )
async_terminate( serial->read_q, STATUS_ALERTED );
if(IS_READY(serial->write_q) && (POLLOUT & event) )
async_notify(serial->write_q.head,STATUS_ALERTED);
if (serial->write_q && (POLLOUT & event) )
async_terminate( serial->write_q, STATUS_ALERTED );
if(IS_READY(serial->wait_q) && (POLLIN & event) )
async_notify(serial->wait_q.head,STATUS_ALERTED);
if (serial->wait_q && (POLLIN & event) )
async_terminate( serial->wait_q, STATUS_ALERTED );
set_fd_events( fd, serial_get_poll_events(fd) );
}
static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
{
struct serial *serial = get_fd_user( fd );
struct async_queue *q;
struct async *async;
struct async **head;
int timeout;
int events;
assert(serial->obj.ops == &serial_ops);
switch(type)
switch (type)
{
case ASYNC_TYPE_READ:
q = &serial->read_q;
head = &serial->read_q;
timeout = serial->readconst + serial->readmult*count;
break;
case ASYNC_TYPE_WAIT:
q = &serial->wait_q;
head = &serial->wait_q;
timeout = 0;
break;
case ASYNC_TYPE_WRITE:
q = &serial->write_q;
head = &serial->write_q;
timeout = serial->writeconst + serial->writemult*count;
break;
default:
......@@ -265,24 +262,9 @@ static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, in
return;
}
async = find_async ( q, current, ptr );
if ( status == STATUS_PENDING )
{
int events;
if ( !async )
async = create_async ( &serial->obj, current, ptr );
if ( !async )
if (!create_async( fd, current, timeout, head, apc, user, iosb ))
return;
async->status = STATUS_PENDING;
if(!async->q)
{
async_add_timeout(async,timeout);
async_insert(q, async);
}
/* Check if the new pending request can be served immediately */
events = check_fd_events( fd, serial_get_poll_events( fd ) );
if (events)
......@@ -291,11 +273,18 @@ static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, in
serial_poll_event( fd, events );
return;
}
}
else if ( async ) destroy_async ( async );
else set_error ( STATUS_INVALID_PARAMETER );
set_fd_events ( fd, serial_get_poll_events( fd ) );
set_fd_events( fd, serial_get_poll_events( fd ) );
}
static void serial_cancel_async( struct fd *fd )
{
struct serial *serial = get_fd_user( fd );
assert(serial->obj.ops == &serial_ops);
async_terminate_queue( &serial->read_q, STATUS_CANCELLED );
async_terminate_queue( &serial->write_q, STATUS_CANCELLED );
async_terminate_queue( &serial->wait_q, STATUS_CANCELLED );
}
static int serial_flush( struct fd *fd, struct event **event )
......@@ -338,7 +327,7 @@ DECL_HANDLER(set_serial_info)
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
{
/* timeouts */
if(req->flags & SERIALINFO_SET_TIMEOUTS)
if (req->flags & SERIALINFO_SET_TIMEOUTS)
{
serial->readinterval = req->readinterval;
serial->readconst = req->readconst;
......@@ -348,21 +337,17 @@ DECL_HANDLER(set_serial_info)
}
/* event mask */
if(req->flags & SERIALINFO_SET_MASK)
if (req->flags & SERIALINFO_SET_MASK)
{
serial->eventmask = req->eventmask;
if(!serial->eventmask)
if (!serial->eventmask)
{
while(serial->wait_q.head)
{
async_notify(serial->wait_q.head, STATUS_SUCCESS);
destroy_async(serial->wait_q.head);
}
async_terminate_queue( &serial->wait_q, STATUS_SUCCESS );
}
}
/* comm port error status */
if(req->flags & SERIALINFO_SET_ERROR)
if (req->flags & SERIALINFO_SET_ERROR)
{
serial->commerror = req->commerror;
}
......
......@@ -71,7 +71,8 @@ static const struct fd_ops handler_fd_ops =
handler_poll_event, /* poll_event */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async /* cancel_async */
};
static struct handler *handler_sighup;
......
......@@ -56,7 +56,6 @@
#include "thread.h"
#include "request.h"
#include "user.h"
#include "async.h"
/* To avoid conflicts with the Unix socket headers. Plus we only need a few
* macros anyway.
......@@ -81,9 +80,9 @@ struct sock
unsigned int message; /* message to send */
obj_handle_t wparam; /* message wparam (socket handle) */
int errors[FD_MAX_EVENTS]; /* event errors */
struct sock* deferred; /* socket that waits for a deferred accept */
struct async_queue read_q; /* Queue for asynchronous reads */
struct async_queue write_q; /* Queue for asynchronous writes */
struct sock *deferred; /* socket that waits for a deferred accept */
struct async *read_q; /* Queue for asynchronous reads */
struct async *write_q; /* Queue for asynchronous writes */
};
static void sock_dump( struct object *obj, int verbose );
......@@ -94,7 +93,8 @@ static void sock_destroy( struct object *obj );
static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event );
static int sock_get_info( struct fd *fd );
static void sock_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count );
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
static void sock_cancel_async( struct fd *fd );
static int sock_get_error( int err );
static void sock_set_error(void);
......@@ -117,7 +117,8 @@ static const struct fd_ops sock_fd_ops =
sock_poll_event, /* poll_event */
no_flush, /* flush */
sock_get_info, /* get_file_info */
sock_queue_async /* queue_async */
sock_queue_async, /* queue_async */
sock_cancel_async /* cancel_async */
};
......@@ -150,48 +151,48 @@ typedef enum {
static sock_shutdown_t sock_shutdown_type = SOCK_SHUTDOWN_ERROR;
static sock_shutdown_t sock_check_pollhup (void)
static sock_shutdown_t sock_check_pollhup(void)
{
sock_shutdown_t ret = SOCK_SHUTDOWN_ERROR;
int fd[2], n;
struct pollfd pfd;
char dummy;
if ( socketpair ( AF_UNIX, SOCK_STREAM, 0, fd ) ) goto out;
if ( shutdown ( fd[0], 1 ) ) goto out;
if ( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) ) goto out;
if ( shutdown( fd[0], 1 ) ) goto out;
pfd.fd = fd[1];
pfd.events = POLLIN;
pfd.revents = 0;
n = poll ( &pfd, 1, 0 );
n = poll( &pfd, 1, 0 );
if ( n != 1 ) goto out; /* error or timeout */
if ( pfd.revents & POLLHUP )
ret = SOCK_SHUTDOWN_POLLHUP;
else if ( pfd.revents & POLLIN &&
read ( fd[1], &dummy, 1 ) == 0 )
read( fd[1], &dummy, 1 ) == 0 )
ret = SOCK_SHUTDOWN_EOF;
out:
close ( fd[0] );
close ( fd[1] );
close( fd[0] );
close( fd[1] );
return ret;
}
void sock_init(void)
{
sock_shutdown_type = sock_check_pollhup ();
sock_shutdown_type = sock_check_pollhup();
switch ( sock_shutdown_type )
{
case SOCK_SHUTDOWN_EOF:
if (debug_level) fprintf ( stderr, "sock_init: shutdown() causes EOF\n" );
if (debug_level) fprintf( stderr, "sock_init: shutdown() causes EOF\n" );
break;
case SOCK_SHUTDOWN_POLLHUP:
if (debug_level) fprintf ( stderr, "sock_init: shutdown() causes POLLHUP\n" );
if (debug_level) fprintf( stderr, "sock_init: shutdown() causes POLLHUP\n" );
break;
default:
fprintf ( stderr, "sock_init: ERROR in sock_check_pollhup()\n" );
fprintf( stderr, "sock_init: ERROR in sock_check_pollhup()\n" );
sock_shutdown_type = SOCK_SHUTDOWN_EOF;
}
}
......@@ -217,13 +218,13 @@ static int sock_reselect( struct sock *sock )
/* After POLLHUP is received, the socket will no longer be in the main select loop.
This function is used to signal pending events nevertheless */
static void sock_try_event ( struct sock *sock, int event )
static void sock_try_event( struct sock *sock, int event )
{
event = check_fd_events( sock->fd, event );
if (event)
{
if ( debug_level ) fprintf ( stderr, "sock_try_event: %x\n", event );
sock_poll_event ( sock->fd, event );
if ( debug_level ) fprintf( stderr, "sock_try_event: %x\n", event );
sock_poll_event( sock->fd, event );
}
}
......@@ -236,16 +237,16 @@ static void sock_wake_up( struct sock *sock, int pollev )
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
if( pollev & (POLLIN|POLLPRI) && IS_READY( sock->read_q ) )
if ( pollev & (POLLIN|POLLPRI) && sock->read_q )
{
if (debug_level) fprintf ( stderr, "activating read queue for socket %p\n", sock );
async_notify( sock->read_q.head, STATUS_ALERTED );
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
async_terminate( sock->read_q, STATUS_ALERTED );
async_active = 1;
}
if( pollev & POLLOUT && IS_READY( sock->write_q ) )
if ( pollev & POLLOUT && sock->write_q )
{
if (debug_level) fprintf ( stderr, "activating write queue for socket %p\n", sock );
async_notify( sock->write_q.head, STATUS_ALERTED );
if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock );
async_terminate( sock->write_q, STATUS_ALERTED );
async_active = 1;
}
}
......@@ -315,8 +316,8 @@ static void sock_poll_event( struct fd *fd, int event )
if (debug_level)
fprintf(stderr, "socket %p connection failure\n", sock);
}
} else
if (sock->state & FD_WINE_LISTENING)
}
else if (sock->state & FD_WINE_LISTENING)
{
/* listening */
if (event & POLLIN)
......@@ -333,7 +334,8 @@ static void sock_poll_event( struct fd *fd, int event )
sock->errors[FD_ACCEPT_BIT] = sock_error( fd );
sock->hmask |= FD_ACCEPT;
}
} else
}
else
{
/* normal data flow */
if ( sock->type == SOCK_STREAM && ( event & POLLIN ) )
......@@ -364,7 +366,7 @@ static void sock_poll_event( struct fd *fd, int event )
else
{
if ( debug_level )
fprintf ( stderr, "recv error on socket %p: %d\n", sock, errno );
fprintf( stderr, "recv error on socket %p: %d\n", sock, errno );
event = POLLERR;
}
}
......@@ -418,7 +420,7 @@ static void sock_poll_event( struct fd *fd, int event )
if ( sock->pmask & FD_CLOSE || event & (POLLERR|POLLHUP) )
{
if ( debug_level )
fprintf ( stderr, "removing socket %p from select loop\n", sock );
fprintf( stderr, "removing socket %p from select loop\n", sock );
set_fd_events( sock->fd, -1 );
}
else
......@@ -464,9 +466,9 @@ static int sock_get_poll_events( struct fd *fd )
/* listening, wait for readable */
return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->read_q)))
if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && sock->read_q))
ev |= POLLIN | POLLPRI;
if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->write_q)))
if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && sock->write_q))
ev |= POLLOUT;
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
if ( sock->type == SOCK_STREAM && ( sock->mask & ~sock->hmask & FD_CLOSE) )
......@@ -479,7 +481,7 @@ static int sock_get_info( struct fd *fd )
{
int flags = FD_FLAG_AVAILABLE;
struct sock *sock = get_fd_user( fd );
assert ( sock->obj.ops == &sock_ops );
assert( sock->obj.ops == &sock_ops );
if (sock->flags & WSA_FLAG_OVERLAPPED) flags |= FD_FLAG_OVERLAPPED;
if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
......@@ -490,62 +492,57 @@ static int sock_get_info( struct fd *fd )
return flags;
}
static void sock_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
int type, int count )
{
struct sock *sock = get_fd_user( fd );
struct async_queue *q;
struct async *async;
struct async **head;
int pollev;
assert( sock->obj.ops == &sock_ops );
if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
{
set_error ( STATUS_INVALID_HANDLE );
set_error( STATUS_INVALID_HANDLE );
return;
}
switch( type )
switch (type)
{
case ASYNC_TYPE_READ:
q = &sock->read_q;
head = &sock->read_q;
sock->hmask &= ~FD_CLOSE;
break;
case ASYNC_TYPE_WRITE:
q = &sock->write_q;
head = &sock->write_q;
break;
default:
set_error( STATUS_INVALID_PARAMETER );
return;
}
async = find_async ( q, current, ptr );
if ( status == STATUS_PENDING )
{
if ( ( !( sock->state & FD_READ ) && type == ASYNC_TYPE_READ ) ||
( !( sock->state & FD_WRITE ) && type == ASYNC_TYPE_WRITE ) )
{
set_error ( STATUS_PIPE_DISCONNECTED );
if ( async ) destroy_async ( async );
set_error( STATUS_PIPE_DISCONNECTED );
}
else
{
if ( !async )
async = create_async ( &sock->obj, current, ptr );
if ( !async )
if (!create_async( fd, current, 0, head, apc, user, iosb ))
return;
async->status = STATUS_PENDING;
if ( !async->q )
async_insert ( q, async );
}
}
else if ( async ) destroy_async ( async );
else set_error ( STATUS_INVALID_PARAMETER );
pollev = sock_reselect ( sock );
if ( pollev ) sock_try_event ( sock, pollev );
pollev = sock_reselect( sock );
if ( pollev ) sock_try_event( sock, pollev );
}
static void sock_cancel_async( struct fd *fd )
{
struct sock *sock = get_fd_user( fd );
assert( sock->obj.ops == &sock_ops );
async_terminate_queue( &sock->read_q, STATUS_CANCELLED );
async_terminate_queue( &sock->write_q, STATUS_CANCELLED );
}
static struct fd *sock_get_fd( struct object *obj )
......@@ -562,12 +559,12 @@ static void sock_destroy( struct object *obj )
/* FIXME: special socket shutdown stuff? */
if ( sock->deferred )
release_object ( sock->deferred );
release_object( sock->deferred );
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
destroy_async_queue ( &sock->read_q );
destroy_async_queue ( &sock->write_q );
async_terminate_queue( &sock->read_q, STATUS_CANCELLED );
async_terminate_queue( &sock->write_q, STATUS_CANCELLED );
}
if (sock->event) release_object( sock->event );
if (sock->fd) release_object( sock->fd );
......@@ -582,7 +579,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
sockfd = socket( family, type, protocol );
if (debug_level)
fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd);
if (sockfd == -1) {
if (sockfd == -1)
{
sock_set_error();
return NULL;
}
......@@ -612,8 +610,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
}
if (sock->flags & WSA_FLAG_OVERLAPPED)
{
init_async_queue (&sock->read_q);
init_async_queue (&sock->write_q);
sock->read_q = sock->write_q = NULL;
}
sock_reselect( sock );
clear_error();
......@@ -634,10 +631,13 @@ static struct sock *accept_socket( obj_handle_t handle )
if (!sock)
return NULL;
if ( sock->deferred ) {
if ( sock->deferred )
{
acceptsock = sock->deferred;
sock->deferred = NULL;
} else {
}
else
{
/* Try to accept(2). We can't be safe that this an already connected socket
* or that accept() is allowed on it. In those cases we will get -1/errno
......@@ -645,7 +645,8 @@ static struct sock *accept_socket( obj_handle_t handle )
*/
slen = sizeof(saddr);
acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen);
if (acceptfd==-1) {
if (acceptfd==-1)
{
sock_set_error();
release_object( sock );
return NULL;
......@@ -683,8 +684,7 @@ static struct sock *accept_socket( obj_handle_t handle )
}
if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
{
init_async_queue ( &acceptsock->read_q );
init_async_queue ( &acceptsock->write_q );
acceptsock->read_q = acceptsock->write_q = NULL;
}
}
clear_error();
......@@ -700,62 +700,62 @@ static int sock_get_error( int err )
{
switch (err)
{
case EINTR: return WSAEINTR; break;
case EBADF: return WSAEBADF; break;
case EINTR: return WSAEINTR;
case EBADF: return WSAEBADF;
case EPERM:
case EACCES: return WSAEACCES; break;
case EFAULT: return WSAEFAULT; break;
case EINVAL: return WSAEINVAL; break;
case EMFILE: return WSAEMFILE; break;
case EWOULDBLOCK: return WSAEWOULDBLOCK; break;
case EINPROGRESS: return WSAEINPROGRESS; break;
case EALREADY: return WSAEALREADY; break;
case ENOTSOCK: return WSAENOTSOCK; break;
case EDESTADDRREQ: return WSAEDESTADDRREQ; break;
case EMSGSIZE: return WSAEMSGSIZE; break;
case EPROTOTYPE: return WSAEPROTOTYPE; break;
case ENOPROTOOPT: return WSAENOPROTOOPT; break;
case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; break;
case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; break;
case EOPNOTSUPP: return WSAEOPNOTSUPP; break;
case EPFNOSUPPORT: return WSAEPFNOSUPPORT; break;
case EAFNOSUPPORT: return WSAEAFNOSUPPORT; break;
case EADDRINUSE: return WSAEADDRINUSE; break;
case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; break;
case ENETDOWN: return WSAENETDOWN; break;
case ENETUNREACH: return WSAENETUNREACH; break;
case ENETRESET: return WSAENETRESET; break;
case ECONNABORTED: return WSAECONNABORTED; break;
case EACCES: return WSAEACCES;
case EFAULT: return WSAEFAULT;
case EINVAL: return WSAEINVAL;
case EMFILE: return WSAEMFILE;
case EWOULDBLOCK: return WSAEWOULDBLOCK;
case EINPROGRESS: return WSAEINPROGRESS;
case EALREADY: return WSAEALREADY;
case ENOTSOCK: return WSAENOTSOCK;
case EDESTADDRREQ: return WSAEDESTADDRREQ;
case EMSGSIZE: return WSAEMSGSIZE;
case EPROTOTYPE: return WSAEPROTOTYPE;
case ENOPROTOOPT: return WSAENOPROTOOPT;
case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
case EOPNOTSUPP: return WSAEOPNOTSUPP;
case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
case EADDRINUSE: return WSAEADDRINUSE;
case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
case ENETDOWN: return WSAENETDOWN;
case ENETUNREACH: return WSAENETUNREACH;
case ENETRESET: return WSAENETRESET;
case ECONNABORTED: return WSAECONNABORTED;
case EPIPE:
case ECONNRESET: return WSAECONNRESET; break;
case ENOBUFS: return WSAENOBUFS; break;
case EISCONN: return WSAEISCONN; break;
case ENOTCONN: return WSAENOTCONN; break;
case ESHUTDOWN: return WSAESHUTDOWN; break;
case ETOOMANYREFS: return WSAETOOMANYREFS; break;
case ETIMEDOUT: return WSAETIMEDOUT; break;
case ECONNREFUSED: return WSAECONNREFUSED; break;
case ELOOP: return WSAELOOP; break;
case ENAMETOOLONG: return WSAENAMETOOLONG; break;
case EHOSTDOWN: return WSAEHOSTDOWN; break;
case EHOSTUNREACH: return WSAEHOSTUNREACH; break;
case ENOTEMPTY: return WSAENOTEMPTY; break;
case ECONNRESET: return WSAECONNRESET;
case ENOBUFS: return WSAENOBUFS;
case EISCONN: return WSAEISCONN;
case ENOTCONN: return WSAENOTCONN;
case ESHUTDOWN: return WSAESHUTDOWN;
case ETOOMANYREFS: return WSAETOOMANYREFS;
case ETIMEDOUT: return WSAETIMEDOUT;
case ECONNREFUSED: return WSAECONNREFUSED;
case ELOOP: return WSAELOOP;
case ENAMETOOLONG: return WSAENAMETOOLONG;
case EHOSTDOWN: return WSAEHOSTDOWN;
case EHOSTUNREACH: return WSAEHOSTUNREACH;
case ENOTEMPTY: return WSAENOTEMPTY;
#ifdef EPROCLIM
case EPROCLIM: return WSAEPROCLIM; break;
case EPROCLIM: return WSAEPROCLIM;
#endif
#ifdef EUSERS
case EUSERS: return WSAEUSERS; break;
case EUSERS: return WSAEUSERS;
#endif
#ifdef EDQUOT
case EDQUOT: return WSAEDQUOT; break;
case EDQUOT: return WSAEDQUOT;
#endif
#ifdef ESTALE
case ESTALE: return WSAESTALE; break;
case ESTALE: return WSAESTALE;
#endif
#ifdef EREMOTE
case EREMOTE: return WSAEREMOTE; break;
case EREMOTE: return WSAEREMOTE;
#endif
default: errno=err; perror("sock_set_error"); return WSAEFAULT; break;
default: errno=err; perror("sock_set_error"); return WSAEFAULT;
}
}
......@@ -814,7 +814,7 @@ DECL_HANDLER(set_socket_event)
if (debug_level && sock->event) fprintf(stderr, "event ptr: %p\n", sock->event);
pollev = sock_reselect( sock );
if ( pollev ) sock_try_event ( sock, pollev );
if ( pollev ) sock_try_event( sock, pollev );
if (sock->mask)
sock->state |= FD_WINE_NONBLOCKING;
......@@ -885,7 +885,7 @@ DECL_HANDLER(enable_socket_event)
if ( sock->type != SOCK_STREAM ) sock->state &= ~STREAM_FLAG_MASK;
pollev = sock_reselect( sock );
if ( pollev ) sock_try_event ( sock, pollev );
if ( pollev ) sock_try_event( sock, pollev );
release_object( &sock->obj );
}
......@@ -898,17 +898,17 @@ DECL_HANDLER(set_socket_deferred)
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
if ( !sock )
{
set_error ( WSAENOTSOCK );
set_error( WSAENOTSOCK );
return;
}
acceptsock = (struct sock*)get_handle_obj( current->process,req->deferred,
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
if ( !acceptsock )
{
release_object ( sock );
set_error ( WSAENOTSOCK );
release_object( sock );
set_error( WSAENOTSOCK );
return;
}
sock->deferred = acceptsock;
release_object ( sock );
release_object( sock );
}
......@@ -100,7 +100,8 @@ static const struct fd_ops thread_fd_ops =
thread_poll_event, /* poll_event */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
no_queue_async /* queue_async */
no_queue_async, /* queue_async */
no_cancel_async /* cancel_async */
};
static struct thread *first_thread;
......
......@@ -1948,9 +1948,15 @@ static void dump_register_async_request( const struct register_async_request *re
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " overlapped=%p,", req->overlapped );
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " status=%08x", req->status );
fprintf( stderr, " io_apc=%p,", req->io_apc );
fprintf( stderr, " io_sb=%p,", req->io_sb );
fprintf( stderr, " io_user=%p,", req->io_user );
fprintf( stderr, " count=%d", req->count );
}
static void dump_cancel_async_request( const struct cancel_async_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
......@@ -2730,6 +2736,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_serial_info_request,
(dump_func)dump_set_serial_info_request,
(dump_func)dump_register_async_request,
(dump_func)dump_cancel_async_request,
(dump_func)dump_create_named_pipe_request,
(dump_func)dump_open_named_pipe_request,
(dump_func)dump_connect_named_pipe_request,
......@@ -2912,6 +2919,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_serial_info_reply,
(dump_func)0,
(dump_func)0,
(dump_func)0,
(dump_func)dump_create_named_pipe_reply,
(dump_func)dump_open_named_pipe_reply,
(dump_func)0,
......@@ -3094,6 +3102,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_serial_info",
"set_serial_info",
"register_async",
"cancel_async",
"create_named_pipe",
"open_named_pipe",
"connect_named_pipe",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment