Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
April 2002
- 132 participants
- 664 messages
Re: PATCH: accept-deferred.diff (5 in series)
by Dimitrie O. Paun
On April 12, 2002 11:20 am, Martin Wilck wrote:
> /***********************************************************************
> + * WSAConnect (WS2_32.30)
> + */
> +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 )
> + WARN ("unsupported parameters!");
^^^^
Shouldn't this be a FIXME instead?
--
Dimi.
April 12, 2002
Patch: sock-shutdown-file.diff (11 in series)
by Martin Wilck
Patch: sock-shutdown-file.diff
Enables error handling if ReadFile() WriteFile() are called on a socket
after the respective channel of the socket was shut down.
Patch against: CVS 2002-04-12, with my previously submitted patches applied.
Modified files:
files: file.c
--- TMP/wine/files/file.c Fri Apr 12 11:54:50 2002
+++ MW/wine/files/file.c Fri Apr 12 11:54:28 2002
@@ -1514,6 +1514,16 @@
SetLastError ( ERROR_INVALID_PARAMETER );
return FALSE;
}
+ if ( ! (flags & FD_FLAG_OVERLAPPED) ) {
+ WARN ( "fd is not overlapped\n" );
+ SetLastError ( ERROR_INVALID_PARAMETER );
+ goto error;
+ }
+ if ( flags & FD_FLAG_RECV_SHUTDOWN ) {
+ /* Fixme: WSAESHUTDOWN is unavailable */
+ SetLastError ( ERROR_BROKEN_PIPE );
+ goto error;
+ }
ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
@@ -1730,6 +1740,16 @@
{
TRACE( "Couldn't get FD\n" );
return FALSE;
+ }
+ if ( ! (flags & FD_FLAG_OVERLAPPED) ) {
+ WARN ( "fd is not overlapped\n" );
+ SetLastError ( ERROR_INVALID_PARAMETER );
+ goto error;
+ }
+ if ( flags & FD_FLAG_SEND_SHUTDOWN ) {
+ /* Fixme: WSAESHUTDOWN is unavailable */
+ SetLastError ( ERROR_BROKEN_PIPE );
+ goto error;
}
ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
April 12, 2002
Patch: wait-debug.diff (10 in series)
by Martin Wilck
Patch: wait-debug.diff
Introduce a debug channel for WaitForMultipleObjectsEx() in scheduler/synchro.c -
I found this very useful to debug my asynchronous socket code.
Moreover, include "async.h" _after_ declaring debug channels so that
TRACEs can be used in the static functions in async.h.
Patch against:
CVS 2002-04-12, with my async-immediate, async-file patches applied.
Modified files:
dlls/kernel: comm.c
dlls/ntdll: ntdll.spec
files: file.c
include: async.h
scheduler: synchro.c
diff -ruNX ignore TMP/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- TMP/wine/dlls/kernel/comm.c Fri Apr 12 12:31:58 2002
+++ MW/wine/dlls/kernel/comm.c Fri Apr 12 12:32:19 2002
@@ -80,7 +80,6 @@
#include "winerror.h"
#include "wine/server.h"
-#include "async.h"
#include "file.h"
#include "heap.h"
@@ -91,6 +90,7 @@
#endif
WINE_DEFAULT_DEBUG_CHANNEL(comm);
+#include "async.h"
/***********************************************************************
* Asynchronous I/O for asynchronous wait requests *
diff -ruNX ignore TMP/wine/dlls/ntdll/ntdll.spec MW/wine/dlls/ntdll/ntdll.spec
--- TMP/wine/dlls/ntdll/ntdll.spec Tue Apr 2 16:51:27 2002
+++ MW/wine/dlls/ntdll/ntdll.spec Fri Apr 12 12:33:12 2002
@@ -5,7 +5,7 @@
global heap int int21 int31 io loaddll local module ntdll process
profile reg relay resource segment seh selector server snoop
string system tape task thread tid timer toolhelp ver virtual
- vxd win32)
+ vxd wait win32)
#note that the Zw... functions are alternate names for the
#Nt... functions. (see www.sysinternals.com for details)
diff -ruNX ignore TMP/wine/files/file.c MW/wine/files/file.c
--- TMP/wine/files/file.c Fri Apr 12 12:31:58 2002
+++ MW/wine/files/file.c Fri Apr 12 12:32:19 2002
@@ -55,7 +55,6 @@
#include "drive.h"
#include "file.h"
-#include "async.h"
#include "heap.h"
#include "msdos.h"
#include "wincon.h"
@@ -64,6 +63,7 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(file);
+#include "async.h"
#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
#define MAP_ANON MAP_ANONYMOUS
diff -ruNX ignore TMP/wine/include/async.h MW/wine/include/async.h
--- TMP/wine/include/async.h Fri Apr 12 12:31:58 2002
+++ MW/wine/include/async.h Fri Apr 12 12:32:19 2002
@@ -102,6 +102,7 @@
ovp->ops->set_status ( ovp, ret );
}
+ TRACE ("ovp %p, status %lx %lx, ret %x\n", ovp, status, ovp->ops->get_status (ovp), ret);
if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
finish_async (ovp);
diff -ruNX ignore TMP/wine/scheduler/synchro.c MW/wine/scheduler/synchro.c
--- TMP/wine/scheduler/synchro.c Mon Apr 8 10:56:59 2002
+++ MW/wine/scheduler/synchro.c Fri Apr 12 12:33:12 2002
@@ -23,6 +23,7 @@
#include <signal.h>
#include <sys/time.h>
#include <sys/poll.h>
+#include <stdio.h>
#include <unistd.h>
#include <string.h>
@@ -30,6 +31,9 @@
#include "thread.h"
#include "winerror.h"
#include "wine/server.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wait);
#include "async.h"
@@ -225,9 +229,22 @@
BOOL wait_all, DWORD timeout,
BOOL alertable )
{
- int ret, cookie;
+ int ret, cookie,i;
struct timeval tv;
+ if ( TRACE_ON ( __default ) )
+ {
+ const int len = 256;
+ char bf[len], *pp;
+
+ for (i = 0, pp = bf; i < count && pp < bf+len; i++)
+ pp += snprintf (pp, bf + len - pp, " %d", handles[i]);
+ bf[len-1] = 0;
+
+ TRACE ( "n=%ld wait=%c timeout=%ld alertable=%c handles%s\n", count,
+ ( wait_all ? 'y' : 'n' ), timeout, ( alertable ? 'y' : 'n' ), bf );
+ }
+
if (count > MAXIMUM_WAIT_OBJECTS)
{
SetLastError( ERROR_INVALID_PARAMETER );
@@ -259,6 +276,7 @@
call_apcs( alertable );
if (alertable) break;
}
+ TRACE ("status: %d\n", ret);
if (HIWORD(ret)) /* is it an error code? */
{
SetLastError( RtlNtStatusToDosError(ret) );
April 12, 2002
Patch: sock-shutdown.diff (9 in series)
by Martin Wilck
Sorry I got the numbers wrong - there is no number 6 :-/
Patch: sock-shutdown.diff
On overlapped sockets, shutdown() must be done asynchronously too to avoid
premature closing of connections (necessary but unfortunately not sufficient).
This patch queues the shutdown request in the async queue. Moreover it sets
flags for the fd state to prevent calls to send() or recv() after the respective
connection of the socket was shut down.
Patch against: CVS 2002-04-12, with my sock-fd-type, sock-accept-deferred,
async-winsock patches applied.
Modified files:
dlls/winsock: socket.c
include/wine: server_protocol.h
include: winsock.h
server: protocol.def, sock.c
diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c Fri Apr 12 15:29:04 2002
+++ MW/wine/dlls/winsock/socket.c Fri Apr 12 15:29:13 2002
@@ -2258,6 +2258,12 @@
if ( fd == -1 )
goto error;
+ if ( flags & FD_FLAG_SEND_SHUTDOWN )
+ {
+ err = WSAESHUTDOWN;
+ goto err_close;
+ }
+
iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
@@ -2470,55 +2476,168 @@
return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
}
+/***********************************************************************
+ * WS2_async_shutdown (INTERNAL)
+ *
+ * On overlapped sockets, shutdown() must be done asynchronously.
+ */
+static void WS2_async_shutdown ( async_private *as )
+{
+ ws2_async* wsa = (ws2_async*) as;
+ int err = 1;
+
+ TRACE ( "async %p %d\n", wsa, wsa->async.type );
+ switch ( wsa->async.type )
+ {
+ case ASYNC_TYPE_READ:
+ err = shutdown ( wsa->async.fd, 0 );
+ break;
+ case ASYNC_TYPE_WRITE:
+ err = shutdown ( wsa->async.fd, 1 );
+ break;
+ default:
+ WARN ("invalid type: %d\n", wsa->async.type );
+ }
+
+ if ( err )
+ wsa->overlapped->Internal = STATUS_UNSUCCESSFUL;
+ else
+ wsa->overlapped->Internal = STATUS_SUCCESS;
+}
+
+/***********************************************************************
+ * WS2_register_async_shutdown (INTERNAL)
+ */
+static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
+{
+ struct ws2_async *wsa;
+ int ret, err = WSAEFAULT;
+ DWORD dwflags = 0;
+ int len = 0;
+ LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
+
+ TRACE ("s %d fd %d type %d\n", s, fd, type);
+ if (!ovl)
+ goto out;
+
+ 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 );
+ 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 )) )
+ {
+ err = RtlNtStatusToDosError ( ret );
+ ws2_async_cleanup ( &wsa->async );
+ goto out;
+ }
+ return 0;
+
+out_close:
+ WSACloseEvent ( ovl->hEvent );
+out_free:
+ HeapFree ( GetProcessHeap(), 0, ovl );
+out:
+ return err;
+}
/***********************************************************************
* shutdown (WS2_32.22)
*/
int WINAPI WS_shutdown(SOCKET s, int how)
{
- int fd = _get_sock_fd(s);
+ int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
+ enum fd_type type;
+ unsigned int set_flags = 0, clear_flags = 0;
- TRACE("socket %04x, how %i\n", s, how );
- if (fd != -1)
- {
- switch( how )
- {
- case 0: /* drop receives */
- _enable_event(s, 0, 0, FD_READ);
-#ifdef SHUT_RD
- how = SHUT_RD;
-#endif
- break;
+ fd = _get_sock_fd_type ( s, &type, &flags );
+ TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
- case 1: /* drop sends */
- _enable_event(s, 0, 0, FD_WRITE);
-#ifdef SHUT_WR
- how = SHUT_WR;
-#endif
- break;
+ if (fd == -1)
+ goto error;
- case 2: /* drop all */
-#ifdef SHUT_RDWR
- how = SHUT_RDWR;
-#endif
- default:
- WSAAsyncSelect( s, 0, 0, 0 );
- break;
- }
+ if ( flags & FD_FLAG_OVERLAPPED ) {
+
+ switch ( how )
+ {
+ case SD_RECEIVE:
+ fd0 = fd;
+ set_flags |= FD_FLAG_RECV_SHUTDOWN;
+ clear_flags |= FD_READ;
+ break;
+ case SD_SEND:
+ fd1 = fd;
+ set_flags |= FD_FLAG_SEND_SHUTDOWN;
+ clear_flags |= FD_WRITE;
+ break;
+ case SD_BOTH:
+ fd0 = fd;
+ fd1 = _get_sock_fd ( s );
+ set_flags |= FD_FLAG_RECV_SHUTDOWN|FD_FLAG_SEND_SHUTDOWN;
+ clear_flags |= FD_READ|FD_WRITE;
+ default:
+ clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
+ WSAAsyncSelect( s, 0, 0, 0 );
+ }
+ _enable_event( s, 0, set_flags, clear_flags );
- if (shutdown(fd, how) == 0)
- {
- if( how > 1 )
- {
- _enable_event(s, 0, 0, FD_WINE_CONNECTED|FD_WINE_LISTENING);
- }
- close(fd);
- return 0;
- }
- SetLastError(wsaErrno());
- close(fd);
- }
- else SetLastError(WSAENOTSOCK);
+ if ( fd0 != -1 )
+ {
+ err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
+ if ( err )
+ {
+ close ( fd0 );
+ goto error;
+ }
+ }
+ if ( fd1 != -1 )
+ {
+ err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
+ if ( err )
+ {
+ close ( fd1 );
+ goto error;
+ }
+ }
+ return 0;
+ }
+ else /* non-overlapped mode */
+ {
+ switch( how )
+ {
+ case 0: /* drop receives */
+ _enable_event(s, 0, 0, FD_READ);
+ break;
+ case 1: /* drop sends */
+ _enable_event(s, 0, 0, FD_WRITE);
+ break;
+ case 2: /* drop all */
+ default:
+ WSAAsyncSelect( s, 0, 0, 0 );
+ break;
+ }
+
+ if ( shutdown( fd, how ) )
+ {
+ err = wsaErrno ();
+ close ( fd );
+ goto error;
+ }
+ if( how > 1 )
+ _enable_event(s, 0, 0, FD_WINE_CONNECTED|FD_WINE_LISTENING);
+ close(fd);
+ return 0;
+ }
+
+error:
+ WSASetLastError ( err );
return SOCKET_ERROR;
}
@@ -3707,9 +3826,12 @@
TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
if (fd == -1)
- {
- err = WSAENOTSOCK;
goto error;
+
+ if ( flags & FD_FLAG_RECV_SHUTDOWN )
+ {
+ err = WSAESHUTDOWN;
+ goto err_close;
}
iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
@@ -3879,6 +4001,7 @@
SetLastError ( WSATRY_AGAIN );
}
SERVER_END_REQ;
+ /* WS_closesocket ( cs ); */
return SOCKET_ERROR;
case CF_REJECT:
WS_closesocket(cs);
diff -ruNX ignore TMP/wine/include/wine/server_protocol.h MW/wine/include/wine/server_protocol.h
--- TMP/wine/include/wine/server_protocol.h Fri Apr 12 14:38:16 2002
+++ MW/wine/include/wine/server_protocol.h Fri Apr 12 15:29:13 2002
@@ -796,6 +796,9 @@
#define FD_FLAG_OVERLAPPED 0x01
#define FD_FLAG_TIMEOUT 0x02
+#define FD_FLAG_RECV_SHUTDOWN 0x08000000
+#define FD_FLAG_SEND_SHUTDOWN 0x04000000
+#define FD_FLAG_SHUTDOWN_MASK (FD_FLAG_RECV_SHUTDOWN|FD_FLAG_SEND_SHUTDOWN)
struct set_file_pointer_request
@@ -3196,6 +3199,6 @@
struct get_window_properties_reply get_window_properties_reply;
};
-#define SERVER_PROTOCOL_VERSION 79
+#define SERVER_PROTOCOL_VERSION 80
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff -ruNX ignore TMP/wine/include/winsock.h MW/wine/include/winsock.h
--- TMP/wine/include/winsock.h Tue Apr 2 16:51:40 2002
+++ MW/wine/include/winsock.h Fri Apr 12 15:29:13 2002
@@ -728,6 +728,7 @@
#define FD_CLOSE 0x00000020
/* internal per-socket flags */
+/* CAUTION: FD_FLAG_RECV_SHUTDOWN / FD_FLAG_SEND_SHUTDOWN (server/protocol.def) must fit into this mask */
#ifdef __WINE__
#define FD_WINE_LISTENING 0x10000000
#define FD_WINE_NONBLOCKING 0x20000000
diff -ruNX ignore TMP/wine/server/protocol.def MW/wine/server/protocol.def
--- TMP/wine/server/protocol.def Fri Apr 12 14:38:16 2002
+++ MW/wine/server/protocol.def Fri Apr 12 15:29:13 2002
@@ -612,7 +612,10 @@
};
#define FD_FLAG_OVERLAPPED 0x01
#define FD_FLAG_TIMEOUT 0x02
-
+/* These are only for sockets, but must work with ReadFile() etc., too */
+#define FD_FLAG_RECV_SHUTDOWN 0x08000000
+#define FD_FLAG_SEND_SHUTDOWN 0x04000000
+#define FD_FLAG_SHUTDOWN_MASK (FD_FLAG_RECV_SHUTDOWN|FD_FLAG_SEND_SHUTDOWN)
/* Set a file current position */
@REQ(set_file_pointer)
diff -ruNX ignore TMP/wine/server/sock.c MW/wine/server/sock.c
--- TMP/wine/server/sock.c Fri Apr 12 15:29:04 2002
+++ MW/wine/server/sock.c Fri Apr 12 15:29:13 2002
@@ -230,7 +230,6 @@
}
} else
{
-
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
if( IS_READY(sock->read_q) && (POLLIN & event) )
@@ -243,25 +242,26 @@
if (debug_level) fprintf ( stderr, "activating write queue for socket %p\n", sock );
async_notify(sock->write_q.head, STATUS_ALERTED);
}
- }
- /* normal data flow */
- if (event & POLLIN)
- {
- char dummy;
+ } else {
/* Linux 2.4 doesn't report POLLHUP if only one side of the socket
* has been closed, so we need to check for it explicitly here */
- if (!recv( sock->obj.fd, &dummy, 1, MSG_PEEK )) event = POLLHUP;
- else
- {
- /* incoming data */
- sock->pmask |= FD_READ;
- sock->hmask |= FD_READ;
- sock->errors[FD_READ_BIT] = 0;
- if (debug_level)
- fprintf(stderr, "socket %d is readable\n", sock->obj.fd );
- }
+ /* !!!! MW: do that only for non-overlapped sockets ??? */
+ char dummy;
+ if (!recv( sock->obj.fd, &dummy, 1, MSG_PEEK ))
+ event = POLLHUP;
+ }
+ /* normal data flow */
+ if (event & POLLIN)
+ {
+
+ /* incoming data */
+ sock->pmask |= FD_READ;
+ sock->hmask |= FD_READ;
+ sock->errors[FD_READ_BIT] = 0;
+ if (debug_level)
+ fprintf(stderr, "socket %d is readable\n", sock->obj.fd );
}
if (event & POLLOUT)
{
@@ -371,8 +371,8 @@
reply->index_low = 0;
reply->serial = 0;
}
- *flags = 0;
- if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
+ *flags = ( sock->state & FD_FLAG_SHUTDOWN_MASK );
+ if ( sock->flags & WSA_FLAG_OVERLAPPED ) *flags |= FD_FLAG_OVERLAPPED;
return FD_TYPE_DEFAULT;
}
April 12, 2002
Patch: async-winsock.diff (8 in series)
by Martin Wilck
Patch: async-winsock.diff
Basic implementation of asynchronous WSARecvFrom()/WSASendTo()/WSAGetOverlappedResult(),
client side.
Patch against: CVS 2002-04-12, with my sock-fd-type and sock-accept-deferred patches applied.
Also requires the server side patch (async-sock-server).
Modified files:
dlls/winsock: socket.c, ws2_32.spec
include: winsock2.h
diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c Fri Apr 12 14:55:42 2002
+++ MW/wine/dlls/winsock/socket.c Fri Apr 12 15:13:28 2002
@@ -105,6 +105,7 @@
#include "wine/winbase16.h"
#include "wingdi.h"
#include "winuser.h"
+#include "winerror.h"
#include "winsock2.h"
#include "ws2tcpip.h"
#include "wsipx.h"
@@ -126,6 +127,170 @@
inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
ntohs(((struct sockaddr_in *)a)->sin_port))
+/****************************************************************
+ * Async IO declarations and operations
+ ****************************************************************/
+#include "async.h"
+
+static DWORD ws2_async_get_status (const struct async_private *ovp);
+static DWORD ws2_async_get_count (const struct async_private *ovp);
+static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
+static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
+static void ws2_async_cleanup ( struct async_private *ovp );
+
+static struct async_ops ws2_async_ops =
+{
+ ws2_async_get_status,
+ ws2_async_set_status,
+ ws2_async_get_count,
+ ws2_async_call_completion,
+ ws2_async_cleanup
+};
+
+static struct async_ops ws2_nocomp_async_ops =
+{
+ ws2_async_get_status,
+ ws2_async_set_status,
+ ws2_async_get_count,
+ NULL, /* call_completion */
+ ws2_async_cleanup
+};
+
+typedef struct ws2_async
+{
+ async_private async;
+ LPWSAOVERLAPPED overlapped;
+ LPWSAOVERLAPPED user_overlapped;
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
+ struct iovec *iovec;
+ int n_iovecs;
+ struct WS_sockaddr *addr;
+ union {
+ int val; /* for send operations */
+ int *ptr; /* for recv operations */
+ } addrlen;
+ DWORD flags;
+} ws2_async;
+
+static DWORD ws2_async_get_status (const struct async_private *ovp)
+{
+ return ((ws2_async*) ovp)->overlapped->Internal;
+}
+
+static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
+{
+ ((ws2_async*) ovp)->overlapped->Internal = status;
+}
+
+static DWORD ws2_async_get_count (const struct async_private *ovp)
+{
+ return ((ws2_async*) ovp)->overlapped->InternalHigh;
+}
+
+static void ws2_async_cleanup ( struct async_private *ap )
+{
+ struct ws2_async *as = (struct ws2_async*) ap;
+
+ TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
+ if ( !as->user_overlapped )
+ {
+ if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
+ WSACloseEvent ( as->overlapped->hEvent );
+ HeapFree ( GetProcessHeap(), 0, as->overlapped );
+ }
+
+ if ( as->iovec )
+ 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 ( RtlNtStatusToDosError (as->overlapped->Internal),
+ as->overlapped->InternalHigh,
+ as->user_overlapped,
+ as->flags );
+ ws2_async_cleanup ( &as->async );
+}
+
+static void WS2_async_recv (async_private *as);
+static void WS2_async_send (async_private *as);
+
+/***********************************************************************
+ * WS2_make_async (WS2_32.69)
+ */
+inline static struct ws2_async*
+WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
+ LPDWORD lpFlags, struct WS_sockaddr *addr,
+ LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+ struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
+
+ 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)
+ {
+ case ASYNC_TYPE_READ:
+ wsa->flags = *lpFlags;
+ wsa->async.func = WS2_async_recv;
+ wsa->addrlen.ptr = addrlen;
+ break;
+ case ASYNC_TYPE_WRITE:
+ wsa->flags = 0;
+ wsa->async.func = WS2_async_send;
+ wsa->addrlen.val = *addrlen;
+ break;
+ default:
+ ERR ("Invalid async type: %d\n", type);
+ }
+ wsa->user_overlapped = lpOverlapped;
+ wsa->completion_func = lpCompletionRoutine;
+ wsa->iovec = iovec;
+ wsa->n_iovecs = dwBufferCount;
+ wsa->addr = addr;
+
+ if ( lpOverlapped )
+ {
+ wsa->overlapped = lpOverlapped;
+ wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
+ }
+ else
+ {
+ wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
+ sizeof (WSAOVERLAPPED) );
+ if ( !wsa->overlapped )
+ goto error;
+ wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
+ }
+
+ wsa->overlapped->InternalHigh = 0;
+ TRACE ( "wsa %p, ops %p, h %d, ev %d, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
+ wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
+ wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
+
+ return wsa;
+
+error:
+ TRACE ("Error\n");
+ HeapFree ( GetProcessHeap(), 0, wsa );
+ return NULL;
+}
+
+/****************************************************************/
+
/* ----------------------------------- internal data */
/* ws_... struct conversion flags */
@@ -1988,6 +2153,88 @@
}
/***********************************************************************
+ * WS2_send (INTERNAL)
+ */
+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 %p, len %d, flags %lx\n",
+ fd, iov, count, to, tolen, dwFlags);
+
+ hdr.msg_name = NULL;
+
+ if ( to )
+ {
+#if DEBUG_SOCKADDR
+ dump_sockaddr (to);
+#endif
+ hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
+ if ( !hdr.msg_name )
+ {
+ WSASetLastError ( WSAEFAULT );
+ goto out;
+ }
+ }
+ else
+ hdr.msg_namelen = 0;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = count;
+ hdr.msg_control = NULL;
+ hdr.msg_controllen = 0;
+ hdr.msg_flags = 0;
+
+ n = sendmsg (fd, &hdr, dwFlags);
+
+out:
+ ws_sockaddr_free ( hdr.msg_name, to );
+ return n;
+}
+
+/***********************************************************************
+ * WS2_async_send (INTERNAL)
+ */
+static void WS2_async_send ( async_private *as )
+{
+ ws2_async* wsa = (ws2_async*) as;
+ int result, err;
+
+ TRACE ( "async %p\n", wsa );
+
+ if ( wsa->overlapped->Internal != STATUS_PENDING )
+ {
+ TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+ return;
+ }
+
+ result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
+ wsa->addr, wsa->addrlen.val, wsa->flags );
+
+ if (result >= 0)
+ {
+ wsa->overlapped->Internal = STATUS_SUCCESS;
+ wsa->overlapped->InternalHigh = result;
+ TRACE ( "sent %d bytes\n", result );
+ _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
+ return;
+ }
+
+ err = errno;
+ if ( err == EAGAIN || err == EINTR )
+ {
+ wsa->overlapped->Internal = STATUS_PENDING;
+ TRACE ( "still pending\n" );
+ }
+ else
+ {
+ wsa->overlapped->Internal = STATUS_UNSUCCESSFUL;
+ TRACE ( "Error: %d\n", errno );
+ }
+}
+
+/***********************************************************************
* WSASendTo (WS2_32.74)
*/
INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
@@ -1996,9 +2243,9 @@
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
- int i, n, fd, err = WSAENOTSOCK, flags;
+ int i, n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
- struct msghdr msghdr;
+ struct ws2_async *wsa;
enum fd_type type;
TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
@@ -2006,6 +2253,7 @@
to, tolen, lpOverlapped, lpCompletionRoutine);
fd = _get_sock_fd_type( s, &type, &flags );
+ TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
if ( fd == -1 )
goto error;
@@ -2014,7 +2262,7 @@
if ( !iovec )
{
- err = WSAENOBUFS;
+ err = WSAEFAULT;
goto err_close;
}
@@ -2024,30 +2272,46 @@
iovec[i].iov_len = lpBuffers[i].len;
}
- msghdr.msg_name = NULL;
-
- if (to)
+ if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
{
-#if DEBUG_SOCKADDR
- dump_sockaddr (to);
-#endif
- msghdr.msg_name = (void*) ws_sockaddr_ws2u (to, tolen, &msghdr.msg_namelen);
- if ( !msghdr.msg_name )
+ wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
+ &dwFlags, (struct WS_sockaddr*) to, &tolen,
+ lpOverlapped, lpCompletionRoutine );
+ if ( !wsa )
{
err = WSAEFAULT;
goto err_free;
}
- }
- else
- msghdr.msg_namelen = 0;
+
+ if ( ( ret = register_new_async ( &wsa->async )) )
+ {
+ err = RtlNtStatusToDosError ( ret );
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = dwBufferCount;
- msghdr.msg_control = NULL;
- msghdr.msg_controllen = 0;
- msghdr.msg_flags = 0;
+ if ( !lpOverlapped )
+ HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+ HeapFree ( GetProcessHeap(), 0, wsa );
+ goto err_free;
+ }
- /* FIXME: Treat overlapped IO here */
+ _enable_event ( s, FD_WRITE, 0, 0 );
+
+ /* Try immediate completion */
+ if ( lpOverlapped )
+ {
+ if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+ lpNumberOfBytesSent, FALSE, &dwFlags) )
+ return 0;
+
+ if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+ {
+ WARN ("err=%d\n", err);
+ goto err_free;
+ }
+ }
+
+ WSASetLastError (WSA_IO_PENDING);
+ return SOCKET_ERROR;
+ }
if (_is_blocking(s))
{
@@ -2055,9 +2319,8 @@
do_block(fd, 2);
}
- /* FIXME: can we support MSG_PARTIAL ? How does it relate to sendmsg()'s msg_flags ? */
-
- if ((n = sendmsg (fd, &msghdr, dwFlags)) == -1)
+ n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
+ if ( n == -1 )
{
err = wsaErrno();
if ( err == WSAEWOULDBLOCK )
@@ -2065,24 +2328,22 @@
goto err_free;
}
+ TRACE(" -> %i bytes\n", n);
*lpNumberOfBytesSent = n;
- ws_sockaddr_free ( msghdr.msg_name, to );
- WS_FREE ( iovec );
+ HeapFree ( GetProcessHeap(), 0, iovec );
close ( fd );
-
return 0;
err_free:
- ws_sockaddr_free ( msghdr.msg_name, to );
- WS_FREE ( iovec );
+ HeapFree ( GetProcessHeap(), 0, iovec );
err_close:
close ( fd );
error:
WARN (" -> ERROR %d\n", err);
- SetLastError (err);
+ WSASetLastError (err);
return SOCKET_ERROR;
}
@@ -2686,6 +2947,53 @@
return SOCKET_ERROR;
}
+/**********************************************************************
+ * WSAGetOverlappedResult (WS2_32.40)
+ */
+BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
+ LPDWORD lpcbTransfer, BOOL fWait,
+ LPDWORD lpdwFlags )
+{
+ DWORD r;
+
+ TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
+ s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
+
+ if ( !(lpOverlapped && lpOverlapped->hEvent) )
+ {
+ ERR ( "Invalid pointer\n" );
+ WSASetLastError (WSA_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ do {
+ r = WaitForSingleObjectEx (lpOverlapped->hEvent, fWait ? INFINITE : 0, TRUE);
+ } while (r == STATUS_USER_APC);
+
+ if ( lpcbTransfer )
+ *lpcbTransfer = lpOverlapped->InternalHigh;
+
+ if ( lpdwFlags )
+ *lpdwFlags = lpOverlapped->Offset;
+
+ TRACE ("r=%lx, int=%lx inth%ld\n", r, lpOverlapped->Internal, lpOverlapped->InternalHigh);
+
+ if ( r == WAIT_OBJECT_0 )
+ return TRUE;
+
+ if ( lpOverlapped->Internal == STATUS_PENDING )
+ WSASetLastError ( WSA_IO_INCOMPLETE );
+ else
+ {
+ DWORD err = RtlNtStatusToDosError ( lpOverlapped->Internal );
+ WSASetLastError ( err );
+ TRACE ( "Error: %lx\n", err );
+ }
+
+ return FALSE;
+}
+
+
/***********************************************************************
* WSAAsyncSelect (WS2_32.101)
*/
@@ -3278,6 +3586,105 @@
}
/***********************************************************************
+ * WS2_recv (INTERNAL)
+ */
+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 %p, len %p, flags %lx\n",
+ fd, iov, count, lpFrom, lpFromlen, *lpFlags);
+
+ hdr.msg_name = NULL;
+
+ if ( lpFrom )
+ {
+#if DEBUG_SOCKADDR
+ dump_sockaddr (lpFrom);
+#endif
+
+ hdr.msg_namelen = *lpFromlen;
+ hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
+ if ( !hdr.msg_name )
+ {
+ WSASetLastError ( WSAEFAULT );
+ n = -1;
+ goto out;
+ }
+ }
+ else
+ hdr.msg_namelen = 0;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = count;
+ hdr.msg_control = NULL;
+ hdr.msg_controllen = 0;
+ hdr.msg_flags = 0;
+
+ if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
+ goto out;
+
+ if ( lpFrom &&
+ 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" );
+ }
+
+out:
+
+ ws_sockaddr_free ( hdr.msg_name, lpFrom );
+ return n;
+}
+
+/***********************************************************************
+ * WS2_async_recv (INTERNAL)
+ */
+static void WS2_async_recv ( async_private *as )
+{
+ ws2_async* wsa = (ws2_async*) as;
+ int result, err;
+
+ TRACE ( "async %p\n", wsa );
+
+ if ( wsa->overlapped->Internal != STATUS_PENDING )
+ {
+ TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+ return;
+ }
+
+ result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
+ wsa->addr, wsa->addrlen.ptr, &wsa->flags );
+
+ if (result >= 0)
+ {
+ wsa->overlapped->Internal = STATUS_SUCCESS;
+ wsa->overlapped->InternalHigh = result;
+ TRACE ( "received %d bytes\n", result );
+ _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
+ return;
+ }
+
+ err = errno;
+ if ( err == EAGAIN || err == EINTR )
+ {
+ wsa->overlapped->Internal = STATUS_PENDING;
+ TRACE ( "still pending\n" );
+ }
+ else
+ {
+ wsa->overlapped->Internal = STATUS_UNSUCCESSFUL;
+ TRACE ( "Error: %d\n", errno );
+ }
+}
+
+/***********************************************************************
* WSARecvFrom (WS2_32.69)
*/
INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
@@ -3286,11 +3693,9 @@
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
- /* Uses recvmsg() in order to provide scatter-gather I/O */
-
+ int i, n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
- struct msghdr msghdr;
- int fd, i, length, err = WSAENOTSOCK, flags;
+ struct ws2_async *wsa;
enum fd_type type;
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
@@ -3299,6 +3704,7 @@
lpOverlapped, lpCompletionRoutine);
fd = _get_sock_fd_type( s, &type, &flags );
+ TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
if (fd == -1)
{
@@ -3306,11 +3712,10 @@
goto error;
}
- /* FIXME: should this be HeapAlloc() or WS_ALLOC ? */
- iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
+ iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
{
- err = WSAENOBUFS;
+ err = WSAEFAULT;
goto err_close;
}
@@ -3320,67 +3725,69 @@
iovec[i].iov_len = lpBuffers[i].len;
}
- msghdr.msg_name = NULL;
-
- if ( lpFrom )
+ if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
{
-#if DEBUG_SOCKADDR
- dump_sockaddr (lpFrom);
-#endif
+ wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
+ lpFlags, lpFrom, lpFromlen,
+ lpOverlapped, lpCompletionRoutine );
- msghdr.msg_namelen = *lpFromlen;
- msghdr.msg_name = ws_sockaddr_alloc (lpFrom, lpFromlen, &msghdr.msg_namelen);
- }
- else
- msghdr.msg_namelen = 0;
+ if ( !wsa )
+ {
+ err = WSAEFAULT;
+ goto err_free;
+ }
+
+ if ( ( ret = register_new_async ( &wsa->async )) )
+ {
+ err = RtlNtStatusToDosError ( ret );
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = dwBufferCount;
- msghdr.msg_control = NULL;
- msghdr.msg_controllen = 0;
- msghdr.msg_flags = 0;
+ if ( !lpOverlapped )
+ HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+ HeapFree ( GetProcessHeap(), 0, wsa );
+ goto err_free;
+ }
- /* FIXME: Treat overlapped IO here */
+ _enable_event ( s, FD_READ, 0, 0 );
- if (_is_blocking(s))
+ /* Try immediate completion */
+ if ( lpOverlapped )
+ {
+ if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+ lpNumberOfBytesRecvd, FALSE, lpFlags) )
+ return 0;
+
+ if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+ goto err_free;
+ }
+
+ WSASetLastError ( WSA_IO_PENDING );
+ return SOCKET_ERROR;
+ }
+
+ if ( _is_blocking(s) )
{
/* block here */
/* FIXME: OOB and exceptfds? */
do_block(fd, 1);
}
-
- /* FIXME: can we support MSG_PARTIAL ?
- How does it relate to recvmsg()'s msg_flags ? */
-
- if ((length = recvmsg (fd, &msghdr, *lpFlags)) == -1)
+
+ n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
+ if ( n == -1 )
{
err = wsaErrno();
goto err_free;
}
- TRACE(" -> %i bytes\n", length);
+ TRACE(" -> %i bytes\n", n);
+ *lpNumberOfBytesRecvd = n;
- if ( lpFrom && ws_sockaddr_u2ws (msghdr.msg_name, msghdr.msg_namelen, lpFrom, lpFromlen) != 0 )
- {
- /* The from buffer was too small, but we read the data
- * anyway. Is that really bad?
- */
- SetLastError ( WSAEFAULT );
- WARN ( " -> Address buffer too small\n" );
- }
-
- *lpNumberOfBytesRecvd = length;
-
- WS_FREE (iovec);
- ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+ HeapFree (GetProcessHeap(), 0, iovec);
close(fd);
_enable_event(s, FD_READ, 0, 0);
-
return 0;
err_free:
- WS_FREE (iovec);
- ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+ HeapFree (GetProcessHeap(), 0, iovec);
err_close:
close (fd);
diff -ruNX ignore TMP/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- TMP/wine/dlls/winsock/ws2_32.spec Fri Apr 12 14:55:42 2002
+++ MW/wine/dlls/winsock/ws2_32.spec Fri Apr 12 15:05:29 2002
@@ -52,7 +52,7 @@
37 stdcall WSAEnumProtocolsA(ptr ptr ptr) WSAEnumProtocolsA
38 stdcall WSAEnumProtocolsW(ptr ptr ptr) WSAEnumProtocolsW
39 stdcall WSAEventSelect(long long long) WSAEventSelect
-40 stub WSAGetOverlappedResult
+40 stdcall WSAGetOverlappedResult(long ptr ptr long ptr) WSAGetOverlappedResult
41 stub WSAGetQOSByName
42 stub WSAGetServiceClassInfoA
43 stub WSAGetServiceClassInfoW
diff -ruNX ignore TMP/wine/include/winsock2.h MW/wine/include/winsock2.h
--- TMP/wine/include/winsock2.h Tue Apr 2 16:51:40 2002
+++ MW/wine/include/winsock2.h Fri Apr 12 15:05:29 2002
@@ -221,8 +221,7 @@
#define WSAEVENT HANDLE
#define LPWSAEVENT LPHANDLE
-#define WSAOVERLAPPED OVERLAPPED
-typedef struct _OVERLAPPED* LPWSAOVERLAPPED;
+typedef OVERLAPPED WSAOVERLAPPED, *LPWSAOVERLAPPED;
#define WSA_IO_PENDING (ERROR_IO_PENDING)
#define WSA_IO_INCOMPLETE (ERROR_IO_INCOMPLETE)
April 12, 2002
PATCH: async-sock-server.diff (7 in series)
by Martin Wilck
PATCH: async-sock-server.diff
Basic implementation of async IO queues in the server code for sockets.
Patch against: CVS-2002-04-12, with my sock-fd-type patch applied.
Modified files:
server: sock.c
diff -ruNX ignore TMP/wine/server/sock.c MW/wine/server/sock.c
--- TMP/wine/server/sock.c Fri Apr 12 14:38:16 2002
+++ MW/wine/server/sock.c Fri Apr 12 15:26:36 2002
@@ -86,6 +86,7 @@
static void sock_destroy( struct object *obj );
static int sock_get_error( int err );
static void sock_set_error(void);
+static struct async_queue * sock_queue_async(struct object *obj, struct async* async, int type, int count);
static const struct object_ops sock_ops =
{
@@ -100,7 +101,7 @@
sock_get_fd, /* get_fd */
no_flush, /* flush */
sock_get_info, /* get_file_info */
- NULL, /* queue_async */
+ sock_queue_async, /* queue_async */
sock_destroy /* destroy */
};
@@ -229,6 +230,21 @@
}
} else
{
+
+ if ( sock->flags & WSA_FLAG_OVERLAPPED )
+ {
+ if( IS_READY(sock->read_q) && (POLLIN & event) )
+ {
+ if (debug_level) fprintf ( stderr, "activating read queue for socket %p\n", sock );
+ async_notify(sock->read_q.head, STATUS_ALERTED);
+ }
+ if( IS_READY(sock->write_q) && (POLLOUT & event) )
+ {
+ if (debug_level) fprintf ( stderr, "activating write queue for socket %p\n", sock );
+ async_notify(sock->write_q.head, STATUS_ALERTED);
+ }
+ }
+
/* normal data flow */
if (event & POLLIN)
{
@@ -312,6 +328,8 @@
int ev = 0;
assert( obj->ops == &sock_ops );
+ if ( debug_level )
+ fprintf (stderr, "mask: %x %x %x -> %x\n", sock->mask, sock->state, sock->hmask, mask);
if (sock->state & FD_CONNECT)
/* connecting, wait for writable */
@@ -320,8 +338,11 @@
/* listening, wait for readable */
return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
- if (mask & FD_READ) ev |= POLLIN | POLLPRI;
- if (mask & FD_WRITE) ev |= POLLOUT;
+ if (mask & FD_READ || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->read_q)))
+ ev |= POLLIN | POLLPRI;
+ if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->write_q)))
+ ev |= POLLOUT;
+
return ev;
}
@@ -353,6 +374,38 @@
*flags = 0;
if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
return FD_TYPE_DEFAULT;
+}
+
+static struct async_queue *sock_queue_async(struct object *obj, struct async *async, int type, int count)
+{
+ struct sock *sock = (struct sock *)obj;
+ struct async_queue *q;
+
+ assert( obj->ops == &sock_ops );
+
+ if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
+ {
+ set_error ( STATUS_INVALID_HANDLE );
+ return NULL;
+ }
+
+ switch(type)
+ {
+ case ASYNC_TYPE_READ:
+ q = &sock->read_q;
+ break;
+ case ASYNC_TYPE_WRITE:
+ q = &sock->write_q;
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ return NULL;
+ }
+
+ if(async && !async->q)
+ async_insert(q, async);
+
+ return q;
}
static void sock_destroy( struct object *obj )
April 12, 2002
PATCH: accept-deferred.diff (5 in series)
by Martin Wilck
PATCH: accept-deferred.diff
If a connection request is deferred in a call to WSAAccept(),
a subsequent accept()/WSAAccept() call must return the
previously deferred connection rather than a new one.
The current CVS implementation of WSAAccept is wrong in this respect.
This patch fixes this. Furthermore, it includes a trivial implementation
of WSAConnect().
Patch against: CVS 2002-04-12.
Modified files:
dlls/winsock: socket.c, ws2_32.spec
include/wine: server_protocol.h
server: protocol.def, sock.c, request.h, trace.c
diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c Tue Apr 9 13:29:12 2002
+++ MW/wine/dlls/winsock/socket.c Fri Apr 12 14:50:50 2002
@@ -1140,6 +1140,19 @@
}
/***********************************************************************
+ * WSAConnect (WS2_32.30)
+ */
+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 )
+ WARN ("unsupported parameters!");
+ return WS_connect ( s, name, namelen );
+}
+
+
+/***********************************************************************
* getpeername (WS2_32.5)
*/
int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
@@ -3420,7 +3433,7 @@
SOCKET cs;
SOCKADDR src_addr, dst_addr;
- TRACE("Socket %ui, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackD ata %ld\n",
+ TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackD ata %ld\n",
s, addr, addrlen, lpfnCondition, dwCallbackData);
@@ -3451,7 +3464,14 @@
addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
return cs;
case CF_DEFER:
- SetLastError(WSATRY_AGAIN);
+ SERVER_START_REQ ( set_socket_deferred )
+ {
+ req->handle = s;
+ req->deferred = cs;
+ if ( !wine_server_call_err ( req ) )
+ SetLastError ( WSATRY_AGAIN );
+ }
+ SERVER_END_REQ;
return SOCKET_ERROR;
case CF_REJECT:
WS_closesocket(cs);
diff -ruNX ignore TMP/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- TMP/wine/dlls/winsock/ws2_32.spec Mon Apr 8 10:56:59 2002
+++ MW/wine/dlls/winsock/ws2_32.spec Fri Apr 12 14:52:57 2002
@@ -42,7 +42,7 @@
27 stub WSAAddressToStringA
28 stub WSAAddressToStringW
29 stdcall WSACloseEvent(long) WSACloseEvent
-30 stub WSAConnect
+30 stdcall WSAConnect(long ptr long ptr ptr ptr ptr) WSAConnect
31 stdcall WSACreateEvent () WSACreateEvent
32 stub WSADuplicateSocketA
33 stub WSADuplicateSocketW
diff -ruNX ignore TMP/wine/include/wine/server_protocol.h MW/wine/include/wine/server_protocol.h
--- TMP/wine/include/wine/server_protocol.h Mon Apr 8 10:56:59 2002
+++ MW/wine/include/wine/server_protocol.h Fri Apr 12 14:25:47 2002
@@ -1001,6 +1001,16 @@
struct reply_header __header;
};
+struct set_socket_deferred_request
+{
+ struct request_header __header;
+ handle_t handle;
+ handle_t deferred;
+};
+struct set_socket_deferred_reply
+{
+ struct reply_header __header;
+};
struct alloc_console_request
@@ -2758,6 +2768,7 @@
REQ_set_socket_event,
REQ_get_socket_event,
REQ_enable_socket_event,
+ REQ_set_socket_deferred,
REQ_alloc_console,
REQ_free_console,
REQ_get_console_renderer_events,
@@ -2919,6 +2930,7 @@
struct set_socket_event_request set_socket_event_request;
struct get_socket_event_request get_socket_event_request;
struct enable_socket_event_request enable_socket_event_request;
+ struct set_socket_deferred_request set_socket_deferred_request;
struct alloc_console_request alloc_console_request;
struct free_console_request free_console_request;
struct get_console_renderer_events_request get_console_renderer_events_request;
@@ -3078,6 +3090,7 @@
struct set_socket_event_reply set_socket_event_reply;
struct get_socket_event_reply get_socket_event_reply;
struct enable_socket_event_reply enable_socket_event_reply;
+ struct set_socket_deferred_reply set_socket_deferred_reply;
struct alloc_console_reply alloc_console_reply;
struct free_console_reply free_console_reply;
struct get_console_renderer_events_reply get_console_renderer_events_reply;
@@ -3183,6 +3196,6 @@
struct get_window_properties_reply get_window_properties_reply;
};
-#define SERVER_PROTOCOL_VERSION 78
+#define SERVER_PROTOCOL_VERSION 79
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff -ruNX ignore TMP/wine/server/protocol.def MW/wine/server/protocol.def
--- TMP/wine/server/protocol.def Mon Apr 8 10:56:59 2002
+++ MW/wine/server/protocol.def Fri Apr 12 14:18:38 2002
@@ -746,6 +746,10 @@
unsigned int cstate; /* status bits to clear */
@END
+(a)REQ(set_socket_deferred)
+ handle_t handle; /* handle to the socket */
+ handle_t deferred; /* handle to the socket for which accept() is deferred */
+(a)END
/* Allocate a console (only used by a console renderer) */
@REQ(alloc_console)
diff -ruNX ignore TMP/wine/server/request.h MW/wine/server/request.h
--- TMP/wine/server/request.h Fri Apr 5 12:21:25 2002
+++ MW/wine/server/request.h Fri Apr 12 14:16:35 2002
@@ -152,6 +152,7 @@
DECL_HANDLER(set_socket_event);
DECL_HANDLER(get_socket_event);
DECL_HANDLER(enable_socket_event);
+DECL_HANDLER(set_socket_deferred);
DECL_HANDLER(alloc_console);
DECL_HANDLER(free_console);
DECL_HANDLER(get_console_renderer_events);
@@ -312,6 +313,7 @@
(req_handler)req_set_socket_event,
(req_handler)req_get_socket_event,
(req_handler)req_enable_socket_event,
+ (req_handler)req_set_socket_deferred,
(req_handler)req_alloc_console,
(req_handler)req_free_console,
(req_handler)req_get_console_renderer_events,
diff -ruNX ignore TMP/wine/server/sock.c MW/wine/server/sock.c
--- TMP/wine/server/sock.c Tue Apr 2 16:51:51 2002
+++ MW/wine/server/sock.c Fri Apr 12 14:24:35 2002
@@ -72,6 +72,7 @@
unsigned int message; /* message to send */
unsigned int wparam; /* message wparam (socket handle) */
int errors[FD_MAX_EVENTS]; /* event errors */
+ handle_t 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 */
};
@@ -361,6 +362,9 @@
/* FIXME: special socket shutdown stuff? */
+ if ( sock->deferred )
+ close_handle ( current->process, sock->deferred, NULL );
+
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
destroy_async_queue ( &sock->read_q );
@@ -394,18 +398,19 @@
sock->window = 0;
sock->message = 0;
sock->wparam = 0;
- sock_reselect( sock );
- clear_error();
+ sock->deferred = 0;
if (sock->flags & WSA_FLAG_OVERLAPPED)
{
init_async_queue (&sock->read_q);
init_async_queue (&sock->write_q);
}
+ sock_reselect( sock );
+ clear_error();
return &sock->obj;
}
/* accept a socket (creates a new fd) */
-static struct sock *accept_socket( handle_t handle )
+static struct sock *accept_socket( handle_t handle, handle_t *accept_handle, unsigned int access, int inherit )
{
struct sock *acceptsock;
struct sock *sock;
@@ -417,42 +422,52 @@
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
if (!sock)
return NULL;
- /* 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
- * return.
- */
- slen = sizeof(saddr);
- acceptfd = accept(sock->obj.fd,&saddr,&slen);
- if (acceptfd==-1) {
- sock_set_error();
- release_object( sock );
- return NULL;
- }
- if (!(acceptsock = alloc_object( &sock_ops, -1 )))
- {
- release_object( sock );
- return NULL;
- }
+ if ( sock->deferred ) {
+ acceptsock = (struct sock*)get_handle_obj( current->process, sock->deferred,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+ *accept_handle = sock->deferred;
+ sock->deferred = 0;
+ } 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
+ * return.
+ */
+ slen = sizeof(saddr);
+ acceptfd = accept(sock->obj.fd,&saddr,&slen);
+ if (acceptfd==-1) {
+ sock_set_error();
+ release_object( sock );
+ return NULL;
+ }
+ if (!(acceptsock = alloc_object( &sock_ops, -1 )))
+ {
+ release_object( sock );
+ return NULL;
+ }
- /* newly created socket gets the same properties of the listening socket */
- fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
- acceptsock->obj.fd = acceptfd;
- acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
- if (sock->state & FD_WINE_NONBLOCKING)
- acceptsock->state |= FD_WINE_NONBLOCKING;
- acceptsock->mask = sock->mask;
- acceptsock->hmask = 0;
- acceptsock->pmask = 0;
- acceptsock->event = NULL;
- acceptsock->window = sock->window;
- acceptsock->message = sock->message;
- acceptsock->wparam = 0;
- if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
- acceptsock->flags = sock->flags;
- if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
- {
- init_async_queue ( &acceptsock->read_q );
- init_async_queue ( &acceptsock->write_q );
+ /* newly created socket gets the same properties of the listening socket */
+ fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
+ acceptsock->obj.fd = acceptfd;
+ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+ if (sock->state & FD_WINE_NONBLOCKING)
+ acceptsock->state |= FD_WINE_NONBLOCKING;
+ acceptsock->mask = sock->mask;
+ acceptsock->hmask = 0;
+ acceptsock->pmask = 0;
+ acceptsock->event = NULL;
+ acceptsock->window = sock->window;
+ acceptsock->message = sock->message;
+ acceptsock->wparam = 0;
+ if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
+ acceptsock->flags = sock->flags;
+ acceptsock->deferred = 0;
+ if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
+ {
+ init_async_queue ( &acceptsock->read_q );
+ init_async_queue ( &acceptsock->write_q );
+ }
+ *accept_handle = alloc_handle( current->process, &acceptsock->obj, access, inherit );
}
clear_error();
@@ -552,9 +567,8 @@
struct sock *sock;
reply->handle = 0;
- if ((sock = accept_socket( req->lhandle )) != NULL)
+ if ( (sock = accept_socket( req->lhandle, &reply->handle, req->access, req->inherit )) != NULL )
{
- reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->inherit );
sock->wparam = reply->handle; /* wparam for message is the socket handle */
sock_reselect( sock );
release_object( &sock->obj );
@@ -645,4 +659,27 @@
sock->state &= ~req->cstate;
sock_reselect( sock );
release_object( &sock->obj );
+}
+
+DECL_HANDLER(set_socket_deferred)
+{
+ struct sock *sock;
+
+ sock=(struct sock*)get_handle_obj( current->process,req->handle,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+ if (!sock)
+ {
+ set_error ( WSAENOTSOCK );
+ return;
+ }
+ sock->deferred = req->deferred;
+ /* duplicate_handle ( current->process, req->deferred, current->process,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, TRUE, 0 ); */
+ if ( !sock->deferred )
+ {
+ release_object ( sock );
+ set_error ( WSAENOTSOCK );
+ return;
+ }
+ release_object ( sock );
}
diff -ruNX ignore TMP/wine/server/trace.c MW/wine/server/trace.c
--- TMP/wine/server/trace.c Mon Apr 8 10:56:59 2002
+++ MW/wine/server/trace.c Fri Apr 12 14:16:35 2002
@@ -943,6 +943,12 @@
fprintf( stderr, " cstate=%08x", req->cstate );
}
+static void dump_set_socket_deferred_request( const struct set_socket_deferred_request *req )
+{
+ fprintf( stderr, " handle=%d,", req->handle );
+ fprintf( stderr, " deferred=%d", req->deferred );
+}
+
static void dump_alloc_console_request( const struct alloc_console_request *req )
{
fprintf( stderr, " access=%08x,", req->access );
@@ -2215,6 +2221,7 @@
(dump_func)dump_set_socket_event_request,
(dump_func)dump_get_socket_event_request,
(dump_func)dump_enable_socket_event_request,
+ (dump_func)dump_set_socket_deferred_request,
(dump_func)dump_alloc_console_request,
(dump_func)dump_free_console_request,
(dump_func)dump_get_console_renderer_events_request,
@@ -2372,6 +2379,7 @@
(dump_func)0,
(dump_func)dump_get_socket_event_reply,
(dump_func)0,
+ (dump_func)0,
(dump_func)dump_alloc_console_reply,
(dump_func)0,
(dump_func)dump_get_console_renderer_events_reply,
@@ -2529,6 +2537,7 @@
"set_socket_event",
"get_socket_event",
"enable_socket_event",
+ "set_socket_deferred",
"alloc_console",
"free_console",
"get_console_renderer_events",
April 12, 2002
Patch: async-file.diff (4 in series)
by Martin Wilck
Patch: async-file.diff
Some improvements to the async IO API.
- Need a "cleanup" method.
- calling the "call_completion" method unconditionally in finish_async
(introduced by me) was wrong, because the thread may never be in an
alertable wait state -> call it only if user completion function is present.
- We need two constant "ops" objects, one with and one without call_completion
method (the event field may NOT be used to determine whether the completion
must be called or not).
- STATUS_CANCELLED is correct for cancelled requests
( corresponds to ERROR_OPERATION_ABORTED ).
Modified files:
dlls/kernel: comm.c
files: file.c
include: async.h
server: async.c
diff -ruNX ignore TMP/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- TMP/wine/dlls/kernel/comm.c Fri Apr 12 11:47:48 2002
+++ MW/wine/dlls/kernel/comm.c Fri Apr 12 12:27:07 2002
@@ -99,14 +99,15 @@
static DWORD commio_get_async_status (const async_private *ovp);
static DWORD commio_get_async_count (const async_private *ovp);
static void commio_set_async_status (async_private *ovp, const DWORD status);
-static void CALLBACK commio_call_completion_func (ULONG_PTR data);
+static void commio_async_cleanup (async_private *ovp);
static async_ops commio_async_ops =
{
commio_get_async_status, /* get_status */
commio_set_async_status, /* set_status */
commio_get_async_count, /* get_count */
- commio_call_completion_func /* call_completion */
+ NULL, /* call_completion */
+ commio_async_cleanup /* cleanup */
};
typedef struct async_commio
@@ -131,9 +132,9 @@
return 0;
}
-static void CALLBACK commio_call_completion_func (ULONG_PTR data)
+static void commio_async_cleanup (async_private *ovp)
{
- HeapFree(GetProcessHeap(), 0, (void*) data);
+ HeapFree(GetProcessHeap(), 0, ovp );
}
/***********************************************************************/
diff -ruNX ignore TMP/wine/files/file.c MW/wine/files/file.c
--- TMP/wine/files/file.c Fri Apr 12 11:59:51 2002
+++ MW/wine/files/file.c Fri Apr 12 12:28:22 2002
@@ -88,13 +88,24 @@
static DWORD fileio_get_async_count (const async_private *ovp);
static void fileio_set_async_status (async_private *ovp, const DWORD status);
static void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+static void fileio_async_cleanup (async_private *ovp);
static async_ops fileio_async_ops =
{
fileio_get_async_status, /* get_status */
fileio_set_async_status, /* set_status */
fileio_get_async_count, /* get_count */
- fileio_call_completion_func /* call_completion */
+ fileio_call_completion_func, /* call_completion */
+ fileio_async_cleanup /* cleanup */
+};
+
+static async_ops fileio_nocomp_async_ops =
+{
+ fileio_get_async_status, /* get_status */
+ fileio_set_async_status, /* set_status */
+ fileio_get_async_count, /* get_count */
+ NULL, /* call_completion */
+ fileio_async_cleanup /* cleanup */
};
typedef struct async_fileio
@@ -128,12 +139,16 @@
async_fileio *ovp = (async_fileio*) data;
TRACE ("data: %p\n", ovp);
- if (ovp->completion_func)
- ovp->completion_func(ovp->lpOverlapped->Internal,
- ovp->lpOverlapped->InternalHigh,
- ovp->lpOverlapped);
+ ovp->completion_func( ovp->lpOverlapped->Internal,
+ ovp->lpOverlapped->InternalHigh,
+ ovp->lpOverlapped );
+
+ fileio_async_cleanup ( &ovp->async );
+}
- HeapFree(GetProcessHeap(), 0, ovp);
+static void fileio_async_cleanup ( struct async_private *ovp )
+{
+ HeapFree ( GetProcessHeap(), 0, ovp );
}
/***********************************************************************
@@ -1479,6 +1494,8 @@
{
async_fileio *ovp;
int fd;
+ int flags;
+ enum fd_type type;
TRACE("file %d to buf %p num %ld %p func %p\n",
hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
@@ -1490,10 +1507,11 @@
return FALSE;
}
- fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
- if(fd<0)
+ fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
+ if ( fd < 0 )
{
- TRACE("Couldn't get FD\n");
+ WARN ( "Couldn't get FD\n" );
+ SetLastError ( ERROR_INVALID_PARAMETER );
return FALSE;
}
@@ -1502,11 +1520,10 @@
{
TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- close(fd);
- return FALSE;
+ goto error;
}
- ovp->async.ops = &fileio_async_ops;
+ ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile;
ovp->async.fd = fd;
ovp->async.type = ASYNC_TYPE_READ;
@@ -1518,6 +1535,11 @@
ovp->buffer = buffer;
return !register_new_async (&ovp->async);
+
+error:
+ close (fd);
+ return FALSE;
+
}
/***********************************************************************
@@ -1691,6 +1713,8 @@
{
async_fileio *ovp;
int fd;
+ int flags;
+ enum fd_type type;
TRACE("file %d to buf %p num %ld %p func %p stub\n",
hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1701,7 +1725,7 @@
return FALSE;
}
- fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+ fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
if ( fd < 0 )
{
TRACE( "Couldn't get FD\n" );
@@ -1713,8 +1737,7 @@
{
TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- close (fd);
- return FALSE;
+ goto error;
}
ovp->async.ops = &fileio_async_ops;
@@ -1729,6 +1752,10 @@
ovp->completion_func = lpCompletionRoutine;
return !register_new_async (&ovp->async);
+
+error:
+ close (fd);
+ return FALSE;
}
/***********************************************************************
diff -ruNX ignore TMP/wine/include/async.h MW/wine/include/async.h
--- TMP/wine/include/async.h Fri Apr 12 11:47:48 2002
+++ MW/wine/include/async.h Fri Apr 12 12:25:30 2002
@@ -35,6 +35,7 @@
typedef DWORD (*async_get_status)(const struct async_private *ovp);
typedef DWORD (*async_get_count)(const struct async_private *ovp);
typedef void (*async_set_status)(struct async_private *ovp, const DWORD status);
+typedef void (*async_cleanup)(struct async_private *ovp);
typedef struct async_ops
{
@@ -42,6 +43,7 @@
async_set_status set_status;
async_get_count get_count;
async_call_completion_func call_completion;
+ async_cleanup cleanup;
} async_ops;
typedef struct async_private
@@ -74,7 +76,10 @@
if( ovp->event != INVALID_HANDLE_VALUE )
NtSetEvent( ovp->event, NULL );
- QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
+ if ( ovp->ops->call_completion )
+ QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
+ else
+ ovp->ops->cleanup ( ovp );
}
inline static BOOL __register_async( async_private *ovp, const DWORD status )
@@ -92,7 +97,11 @@
}
SERVER_END_REQ;
- if ( ret ) ovp->ops->set_status ( ovp, GetLastError() );
+ if ( ret ) {
+ SetLastError( RtlNtStatusToDosError(ret) );
+ ovp->ops->set_status ( ovp, ret );
+ }
+
if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
finish_async (ovp);
diff -ruNX ignore TMP/wine/server/async.c MW/wine/server/async.c
--- TMP/wine/server/async.c Fri Apr 12 11:47:48 2002
+++ MW/wine/server/async.c Fri Apr 12 12:23:56 2002
@@ -71,7 +71,7 @@
{
while(q->head)
{
- async_notify(q->head, STATUS_HANDLES_CLOSED);
+ async_notify(q->head, STATUS_CANCELLED);
destroy_async(q->head);
}
}
April 12, 2002
PATCH: winemaker.diff (3 in series)
by Martin Wilck
PATCH: winemaker.diff
(identical to:
http://www.winehq.com/hypermail/wine-devel/2002/04/0187.html)
Fix winemaker-generated references to dlls that have changed their names
in configure.ac.
Patch against: Wine CVS 2002-04-12
Modified Files:
tools: winemaker
diff -ruNX ignore TMP/wine/tools/winemaker MW/wine/tools/winemaker
--- TMP/wine/tools/winemaker Tue Apr 9 13:19:57 2002
+++ MW/wine/tools/winemaker Tue Apr 9 13:29:27 2002
@@ -2732,14 +2732,14 @@
WINE_DLL_ROOT="/lib:/lib/dlls:/usr/lib:/usr/lib/dlls:/usr/local/lib:/usr/local/lib/dlls"
fi
fi
-AC_PATH_FILE(WINE_DLL_ROOT,[libntdll.so],[
- AC_MSG_ERROR([Could not find the Wine dlls (libntdll.so)])
+AC_PATH_FILE(WINE_DLL_ROOT,[libntdll.dll.so],[
+ AC_MSG_ERROR([Could not find the Wine dlls (libntdll.dll.so)])
],[$WINE_DLL_ROOT])
-AC_PATH_LIBRARY(WINE_DLL_ROOT,[-lntdll],[$WINE_LIBRARY_PATH -lwine -lwine_unicode],[
- AC_MSG_ERROR([Could not link with the Wine dlls (libntdll.so)])
+AC_PATH_LIBRARY(WINE_DLL_ROOT,[-lntdll.dll],[$WINE_LIBRARY_PATH -lwine -lwine_unicode],[
+ AC_MSG_ERROR([Could not link with the Wine dlls (libntdll.dll.so)])
],[$WINE_DLL_ROOT])
-WINE_DLL_PATH="-L$WINE_DLL_ROOT"
+WINE_DLL_PATH="-L$WINE_DLL_ROOT/wine"
if test -n "$LD_PATH"
then
April 12, 2002
PATCH: sock-fd-type.diff (2 in series)
by Martin Wilck
PATCH: sock-fd-type.diff
Patch against: Wine CVS 2002-04-12
Test status: Compiles (no errors/warnings).
Modified Files:
dlls/winsock : socket.c
Log message:
Martin Wilck <Martin.Wilck(a)Fujitsu-Siemens.com>
_get_sock_fd_type : New function, retrieve fd type and flags like FILE_GetUnixHandleType().
WSASendTo() /WSARecvFrom(): Use _get_sock_fd_type().
diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c Tue Apr 9 13:27:56 2002
+++ MW/wine/dlls/winsock/socket.c Tue Apr 9 13:28:08 2002
@@ -246,6 +246,13 @@
return fd;
}
+inline static int _get_sock_fd_type( SOCKET s, enum fd_type *type, int *flags )
+{
+ int fd;
+ if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, type, flags ) )) return -1;
+ return fd;
+}
+
static void _enable_event(SOCKET s, unsigned int event,
unsigned int sstate, unsigned int cstate)
{
@@ -1976,15 +1983,16 @@
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
- int i, n, fd, err = WSAENOTSOCK;
+ int i, n, fd, err = WSAENOTSOCK, flags;
struct iovec* iovec;
struct msghdr msghdr;
-
+ enum fd_type type;
+
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);
+ fd = _get_sock_fd_type( s, &type, &flags );
if ( fd == -1 )
goto error;
@@ -3269,14 +3277,15 @@
struct iovec* iovec;
struct msghdr msghdr;
- int fd, i, length, err = WSAENOTSOCK;
+ int fd, i, length, err = WSAENOTSOCK, flags;
+ enum fd_type type;
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
(lpFromlen ? *lpFromlen : -1L),
lpOverlapped, lpCompletionRoutine);
- fd = _get_sock_fd(s);
+ fd = _get_sock_fd_type( s, &type, &flags );
if (fd == -1)
{
April 12, 2002