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: ALSA driver
by Gavriel State
Ove Kaaven wrote:
> On 19 Apr 2002, Marco Pietrobono wrote:
>
>
>> I'm starting to work on a native ALSA driver for wine. Since I
>>remember that Marcus was working (or was planning to work) an that one
>>too, I would like to know if there is already something to work on or to
>>contribute to, or if I need to start from scratch.
>
> You must be mistaken, Eric Pouech was working on the ALSA driver. This
> driver is also pretty much complete, just bugfixes remain. Unfortunately,
> it's currently in the cold slimy clutches (from the LGPL-Wine perspective)
> of TransGaming staff, who might not want to part with it without getting
> some of that glorious LGPL code in Wine relicensed in exchange...
Actually, we have no official claim over the ALSA driver - we offered to
sponsor Eric Poech's development, but he asked that we put it into another
sponsorship instead. I am going to try to get the details of our proposals
to trade / sponsor some code up next week. We have this DIB engine we've
been working on for a bit, for example....
It is true though that TransGaming's David Hammerton 'has his clutches' on
the code - he's been working on it with Eric in his spare time. That said,
I just checked and while his hands are kind of cold, they didn't appear
to be at all slimy. David said that he might try to check it into the ReWind
tree this weekend.
-Gav
--
Gavriel State, CEO
TransGaming Technologies Inc.
http://www.transgaming.com/
gav(a)transgaming.com
April 19, 2002
(no subject)
by Ann and Jason Edmeades
I've noticed a small bug when using wcmd, in the changing to a directory, eg
c:\windows and doing 'dir \' fails to show the root directory. Its annoyed
me to the point of investigating and the problem seems to lie further down
inside the DOSFS_DoGetFullPathName routine. A simple testpgm shows the
problem:
#include <windows.h>
void main() {
char A[] = "\\";
char B[1024];
int rc;
rc = GetFullPathName (A, sizeof(B), B, NULL);
printf("rc = %d, a=%s, b=%s\n", rc, A, B);
}
(Note: Testpgm run on w2k)
Unfortunately I also noticed how often this routine is called and how many
cases it appears to be trying to handle, so am slightly nervous about
touching it! I am going to do some more investigation but does anyone have
any thoughts in the meantime?
Thanks
Jason
jason @ the-edmeades.demon.co.uk
April 19, 2002
Re: [PATCH] Big winsock2 / overlapped patch
by Sylvain Petreolle
--- Martin Wilck <Martin.Wilck(a)fujitsu-siemens.com> a
écrit : >
> Hi,
>
> This stuff really approaches a usable state!
>
> I know the patch is much too big but I have no time
> now to split it into
> pieces before next week.
If the patch is too big, then gzip it and send it
as an attachment :)
___________________________________________________________
Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français !
Yahoo! Mail : http://fr.mail.yahoo.com
April 19, 2002
Re: toolbar.c problem (ATTN: Duane)
by Dusan Vujosevic
----- Original Message -----
From: "Duane Clark" <dclark(a)akamail.com>
To: <wine-devel(a)winehq.com>
Sent: Friday, April 19, 2002 11:41 AM
Subject: Re: toolbar.c problem (ATTN: Duane)
> I think you misunderstood my explanation. Once the menu is stuck and the
> button released, I slide the mouse into the flying menu and back out
> again, without pressing any mouse buttons. When the cursor leaves the
> flying menu, it disappears, but without calling TOOLBAR_LButtonUp().
> This is the second behavior, which may not be related.
I am working with the latest build of SL and this doesn't happen. I guess
you have the demo and that it does have that problem in which case it is
irrelevant since it has been fixed.
> >>Unfortunately
> >>for me, my real work is once again interfering severely with the amount
> >>of time I have to spend on Wine :-(
> >
> >
> > I'd be all too happy to help. I will take off my own time to test & fix
> > this. I'll try give you something over the weekend (patch).
> >
> >
> >> But I will try to get in a couple
> >>of tests with ControlSpy with the TBSTYLE_DROPDOWN style, since it
> >>should not take much time, perhaps this weekend.
>
> A suggestion I made a couple weeks ago would make things easier, I would
> think. That would be to duplicate your flying menus within ControlSpy. I
> don't know how easy that would be to implement, but once implemented, it
> would likely make debugging much easier.
OK, that's what I'll do. I will implement it (not a big deal) and forward it
to you. Expect it this weekend some time..
Thanks,
Dusan
April 19, 2002
Re: ALSA driver
by Dimitrie O. Paun
On April 19, 2002 12:45 pm, Ove Kaaven wrote:
> it's currently in the cold slimy clutches (from the LGPL-Wine perspective)
as if it's not from the X11-Wine perspective...
--
Dimi.
April 19, 2002
Re: Using WineLib directly
by Marcus Meissner
On Thu, Apr 18, 2002 at 06:45:05AM -0700, Zavada, Ed wrote:
> I've seen this question asked before, but there was never a response to the newsgroup.
>
> We'd like to use WineLib to provide implementations of the Windows
> calls in our application's Linux build while we work on a full blown
> port. So far, all the documentation requires that we use winebuild and
> generate a .so that is loaded by the wine server. Is this truely the
> only way to do this?
The .so is loaded by the 'wine' binary, not the server.
But actually yes, most sublibraries require wineserver to be running
to be used.
> Is there no way to just use the various libraries independent of wine
> server? For instance, I'd like to be able to make a call to MessageBox()
> from a native linux binary, then later eliminate the need for it (since
> this will ultimately be a console app).
I do not think so.
Ciao, Marcus
April 19, 2002
Re: ALSA driver
by Ove Kaaven
On 19 Apr 2002, Marco Pietrobono wrote:
> I'm starting to work on a native ALSA driver for wine. Since I
> remember that Marcus was working (or was planning to work) an that one
> too, I would like to know if there is already something to work on or to
> contribute to, or if I need to start from scratch.
You must be mistaken, Eric Pouech was working on the ALSA driver. This
driver is also pretty much complete, just bugfixes remain. Unfortunately,
it's currently in the cold slimy clutches (from the LGPL-Wine perspective)
of TransGaming staff, who might not want to part with it without getting
some of that glorious LGPL code in Wine relicensed in exchange...
April 19, 2002
[PATCH] Big winsock2 / overlapped patch
by Martin Wilck
Hi,
This stuff really approaches a usable state!
I know the patch is much too big but I have no time now to split it into
pieces before next week.
However, I am so excited to see the close events coming at the right time
that I must post it here and encourage people to try it.
Patch summary:
- Implement overlapped IO on sockets and the necessary changes in
overlapped request handling.
- Fix socket behaviour after FD_CLOSE received, when socket has been taken
out of the server's main select loop.
- Fix some more aspects of FD_CLOSE.
- Fix WSAAccept() deferred accept.
- Implement WSAGetOverlappedResult and WSAConnect().
- Some improvements for error code handling in Winsock2.
Tested: so far with my test programs only, but they really tries to make
things hard for wine.
Patch against yesterday's (2002/04/18) CVS version of wine.
Have fun,
Martin
--
Martin Wilck Phone: +49 5251 8 15113
Fujitsu Siemens Computers Fax: +49 5251 8 20409
Heinz-Nixdorf-Ring 1 mailto:Martin.Wilck(a)Fujitsu-Siemens.com
D-33106 Paderborn http://www.fujitsu-siemens.com/primergy
diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c Thu Apr 18 16:26:02 2002
+++ MW/wine/dlls/winsock/socket.c Fri Apr 19 15:51:52 2002
@@ -104,6 +104,7 @@
#include "wine/winbase16.h"
#include "wingdi.h"
#include "winuser.h"
+#include "winerror.h"
#include "winsock2.h"
#include "ws2tcpip.h"
#include "wsipx.h"
@@ -125,6 +126,53 @@
inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
ntohs(((struct sockaddr_in *)a)->sin_port))
+/****************************************************************
+ * Async IO declarations
+ ****************************************************************/
+#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;
+
+/****************************************************************/
+
/* ----------------------------------- internal data */
/* ws_... struct conversion flags */
@@ -223,13 +271,39 @@
*/
static int opentype = 0;
+inline static DWORD NtStatusToWSAError ( const DWORD status )
+{
+ /* We only need to cover the status codes set by server async request handling */
+ DWORD wserr;
+ switch ( status )
+ {
+ case STATUS_SUCCESS: wserr = 0; break;
+ case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
+ case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
+ case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
+ case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
+ case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
+ case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
+ case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
+ default:
+ if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
+ /* It is not a NT status code but a winsock error */
+ wserr = status;
+ else
+ {
+ wserr = RtlNtStatusToDosError( status );
+ FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
+ }
+ }
+ return wserr;
+}
+
/* set last error code from NT status without mapping WSA errors */
inline static unsigned int set_error( unsigned int err )
{
if (err)
{
- /* do not map WSA errors */
- if ((err < WSABASEERR) || (err >= 0x10000000)) err = RtlNtStatusToDosError(err);
+ err = NtStatusToWSAError ( err );
SetLastError( err );
}
return err;
@@ -245,10 +319,17 @@
return fd;
}
-inline static int _get_sock_fd_type( SOCKET s, enum fd_type *type, int *flags )
+inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
{
int fd;
- if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, type, flags ) )) return -1;
+ if (set_error( wine_server_handle_to_fd( s, access, &fd, type, flags ) )) return -1;
+ if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
+ ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
+ {
+ close (fd);
+ WSASetLastError ( WSAESHUTDOWN );
+ return -1;
+ }
return fd;
}
@@ -904,6 +985,399 @@
free((void*)uaddr);
}
+/**************************************************************************
+ * Functions for handling overlapped I/O
+ **************************************************************************/
+
+static DWORD ws2_async_get_status (const struct async_private *ovp)
+{
+ return ((ws2_async*) ovp)->overlapped->Internal;
+}
+
+static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
+{
+ ((ws2_async*) ovp)->overlapped->Internal = status;
+}
+
+static DWORD ws2_async_get_count (const struct async_private *ovp)
+{
+ return ((ws2_async*) ovp)->overlapped->InternalHigh;
+}
+
+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 ( NtStatusToWSAError (as->overlapped->Internal),
+ as->overlapped->InternalHigh,
+ as->user_overlapped,
+ as->flags );
+ ws2_async_cleanup ( &as->async );
+}
+
+/***********************************************************************
+ * WS2_make_async (INTERNAL)
+ */
+
+static void WS2_async_recv (async_private *as);
+static void WS2_async_send (async_private *as);
+
+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;
+}
+
+/***********************************************************************
+ * WS2_recv (INTERNAL)
+ *
+ * Work horse for both synchronous and asynchronous recv() operations.
+ */
+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 )
+ {
+ TRACE ( "recvmsg error %d\n", errno);
+ 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 );
+ TRACE ("-> %d\n", n);
+ return n;
+}
+
+/***********************************************************************
+ * WS2_async_recv (INTERNAL)
+ *
+ * Handler for overlapped recv() operations.
+ */
+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 = wsaErrno ();
+ if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
+ {
+ wsa->overlapped->Internal = STATUS_PENDING;
+ _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
+ TRACE ( "still pending\n" );
+ }
+ else
+ {
+ wsa->overlapped->Internal = err;
+ TRACE ( "Error: %x\n", err );
+ }
+}
+
+/***********************************************************************
+ * WS2_send (INTERNAL)
+ *
+ * Work horse for both synchronous and asynchronous send() operations.
+ */
+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)
+ *
+ * Handler for overlapped send() operations.
+ */
+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 = wsaErrno ();
+ if ( err == WSAEINTR )
+ {
+ wsa->overlapped->Internal = STATUS_PENDING;
+ _enable_event ( (SOCKET) wsa->async.handle, 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->overlapped->Internal = err;
+ TRACE ( "Error: %x\n", err );
+ }
+}
+
+/***********************************************************************
+ * WS2_async_shutdown (INTERNAL)
+ *
+ * Handler for shutdown() operations on overlapped sockets.
+ */
+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:
+ ERR ("invalid type: %d\n", wsa->async.type );
+ }
+
+ if ( err )
+ wsa->overlapped->Internal = wsaErrno ();
+ else
+ wsa->overlapped->Internal = STATUS_SUCCESS;
+}
+
+/***********************************************************************
+ * WS2_register_async_shutdown (INTERNAL)
+ *
+ * Helper function for WS_shutdown() on overlapped sockets.
+ */
+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 = NtStatusToWSAError ( ret );
+ ws2_async_cleanup ( &wsa->async );
+ goto out;
+ }
+ return 0;
+
+out_close:
+ WSACloseEvent ( ovl->hEvent );
+out_free:
+ HeapFree ( GetProcessHeap(), 0, ovl );
+out:
+ return err;
+}
+
/***********************************************************************
* accept (WS2_32.1)
*/
@@ -1139,6 +1613,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 )
+ FIXME ("unsupported parameters!\n");
+ return WS_connect ( s, name, namelen );
+}
+
+
+/***********************************************************************
* getpeername (WS2_32.5)
*/
int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
@@ -1982,25 +2469,29 @@
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",
s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine);
- fd = _get_sock_fd_type( s, &type, &flags );
+ fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
+ TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
if ( fd == -1 )
+ {
+ err = WSAGetLastError ();
goto error;
+ }
iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
{
- err = WSAENOBUFS;
+ err = WSAEFAULT;
goto err_close;
}
@@ -2010,30 +2501,42 @@
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 = NtStatusToWSAError ( ret );
+
+ if ( !lpOverlapped )
+ HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+ HeapFree ( GetProcessHeap(), 0, wsa );
+ goto err_free;
+ }
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = dwBufferCount;
- msghdr.msg_control = NULL;
- msghdr.msg_controllen = 0;
- msghdr.msg_flags = 0;
+ /* Try immediate completion */
+ if ( lpOverlapped )
+ {
+ if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+ lpNumberOfBytesSent, FALSE, &dwFlags) )
+ return 0;
+
+ if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+ goto error;
- /* FIXME: Treat overlapped IO here */
+ }
+
+ WSASetLastError (WSA_IO_PENDING);
+ return SOCKET_ERROR;
+ }
if (_is_blocking(s))
{
@@ -2041,9 +2544,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 )
@@ -2051,24 +2553,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;
}
@@ -2195,55 +2695,88 @@
return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
}
-
/***********************************************************************
* 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 clear_flags = 0;
- TRACE("socket %04x, how %i\n", s, how );
- if (fd != -1)
+ fd = _get_sock_fd_type ( s, 0, &type, &flags );
+ TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
+
+ if (fd == -1)
+ return SOCKET_ERROR;
+
+ switch( how )
{
- switch( how )
- {
- case 0: /* drop receives */
- _enable_event(s, 0, 0, FD_READ);
-#ifdef SHUT_RD
- how = SHUT_RD;
-#endif
- break;
-
- case 1: /* drop sends */
- _enable_event(s, 0, 0, FD_WRITE);
-#ifdef SHUT_WR
- how = SHUT_WR;
-#endif
- break;
-
- case 2: /* drop all */
-#ifdef SHUT_RDWR
- how = SHUT_RDWR;
-#endif
- default:
- WSAAsyncSelect( s, 0, 0, 0 );
- break;
- }
+ case 0: /* drop receives */
+ clear_flags |= FD_READ;
+ break;
+ case 1: /* drop sends */
+ clear_flags |= FD_WRITE;
+ break;
+ case 2: /* drop all */
+ clear_flags |= FD_READ|FD_WRITE;
+ default:
+ clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
+ }
+
+ if ( flags & FD_FLAG_OVERLAPPED ) {
+
+ switch ( how )
+ {
+ case SD_RECEIVE:
+ fd0 = fd;
+ break;
+ case SD_SEND:
+ fd1 = fd;
+ break;
+ case SD_BOTH:
+ default:
+ fd0 = fd;
+ fd1 = _get_sock_fd ( s );
+ }
- 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;
+ }
+ }
+ }
+ else /* non-overlapped mode */
+ {
+ if ( shutdown( fd, how ) )
+ {
+ err = wsaErrno ();
+ close ( fd );
+ goto error;
+ }
+ close(fd);
+ }
+
+ _enable_event( s, 0, 0, clear_flags );
+ if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
+ return 0;
+
+error:
+ _enable_event( s, 0, 0, clear_flags );
+ WSASetLastError ( err );
return SOCKET_ERROR;
}
@@ -2672,6 +3205,44 @@
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;
+
+ if ( r == WAIT_OBJECT_0 )
+ return TRUE;
+
+ WSASetLastError ( lpOverlapped->Internal == STATUS_PENDING ?
+ WSA_IO_INCOMPLETE : NtStatusToWSAError ( lpOverlapped->Internal ) );
+ return FALSE;
+}
+
+
/***********************************************************************
* WSAAsyncSelect (WS2_32.101)
*/
@@ -3250,7 +3821,6 @@
}
}
-
/***********************************************************************
* WSARecv (WS2_32.67)
*/
@@ -3272,11 +3842,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",
@@ -3284,19 +3852,19 @@
(lpFromlen ? *lpFromlen : -1L),
lpOverlapped, lpCompletionRoutine);
- fd = _get_sock_fd_type( s, &type, &flags );
+ fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
+ TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
if (fd == -1)
{
- err = WSAENOTSOCK;
+ err = WSAGetLastError ();
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;
}
@@ -3306,74 +3874,77 @@
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 = NtStatusToWSAError ( ret );
+
+ if ( !lpOverlapped )
+ HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+ HeapFree ( GetProcessHeap(), 0, wsa );
+ goto err_free;
+ }
- msghdr.msg_iov = iovec;
- msghdr.msg_iovlen = dwBufferCount;
- msghdr.msg_control = NULL;
- msghdr.msg_controllen = 0;
- msghdr.msg_flags = 0;
+ /* Try immediate completion */
+ if ( lpOverlapped )
+ {
+ if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+ lpNumberOfBytesRecvd, FALSE, lpFlags) )
+ return 0;
+
+ if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+ {
+ TRACE ("err: %d\n", err);
+ goto err_free;
+ }
+ }
- /* FIXME: Treat overlapped IO here */
+ WSASetLastError ( WSA_IO_PENDING );
+ return SOCKET_ERROR;
+ }
- if (_is_blocking(s))
+ 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);
error:
WARN(" -> ERROR %d\n", err);
- SetLastError ( err );
+ WSASetLastError ( err );
return SOCKET_ERROR;
}
@@ -3419,7 +3990,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, dwCallbackData %ld\n",
s, addr, addrlen, lpfnCondition, dwCallbackData);
@@ -3450,7 +4021,17 @@
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 );
+ CloseHandle ( cs );
+ }
+ }
+ 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 Thu Apr 18 16:26:02 2002
+++ MW/wine/dlls/winsock/ws2_32.spec Thu Apr 18 16:26:48 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
@@ -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/files/file.c MW/wine/files/file.c
--- TMP/wine/files/file.c Thu Apr 18 15:41:00 2002
+++ MW/wine/files/file.c Fri Apr 19 13:52:52 2002
@@ -306,6 +306,13 @@
ret = wine_server_handle_to_fd( handle, access, &fd, type, flags );
if (ret) SetLastError( RtlNtStatusToDosError(ret) );
+ if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
+ ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
+ {
+ close (fd);
+ SetLastError ( ERROR_PIPE_NOT_CONNECTED );
+ return -1;
+ }
return fd;
}
@@ -1411,7 +1418,7 @@
*lpTransferred = lpOverlapped->InternalHigh;
SetLastError ( lpOverlapped->Internal == STATUS_PENDING ?
- ERROR_IO_INCOMPLETE : lpOverlapped->Internal );
+ ERROR_IO_INCOMPLETE : RtlNtStatusToDosError ( lpOverlapped->Internal ) );
return (r==WAIT_OBJECT_0);
}
@@ -1511,9 +1518,13 @@
if ( fd < 0 )
{
WARN ( "Couldn't get FD\n" );
- SetLastError ( ERROR_INVALID_PARAMETER );
return FALSE;
}
+ if ( ! (flags & FD_FLAG_OVERLAPPED) ) {
+ WARN ( "fd is not overlapped\n" );
+ SetLastError ( ERROR_INVALID_PARAMETER );
+ goto error;
+ }
ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
@@ -1730,6 +1741,11 @@
{
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;
}
ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
diff -ruNX ignore TMP/wine/include/wine/server_protocol.h MW/wine/include/wine/server_protocol.h
--- TMP/wine/include/wine/server_protocol.h Thu Apr 18 16:26:02 2002
+++ MW/wine/include/wine/server_protocol.h Fri Apr 19 13:51:02 2002
@@ -796,6 +796,8 @@
#define FD_FLAG_OVERLAPPED 0x01
#define FD_FLAG_TIMEOUT 0x02
+#define FD_FLAG_RECV_SHUTDOWN 0x04
+#define FD_FLAG_SEND_SHUTDOWN 0x08
struct set_file_pointer_request
@@ -1001,6 +1003,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 +2770,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 +2932,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 +3092,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 +3198,6 @@
struct get_window_properties_reply get_window_properties_reply;
};
-#define SERVER_PROTOCOL_VERSION 78
+#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 Thu Apr 18 15:41:05 2002
+++ MW/wine/include/winsock.h Thu Apr 18 16:26:48 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/include/winsock2.h MW/wine/include/winsock2.h
--- TMP/wine/include/winsock2.h Thu Apr 18 15:41:09 2002
+++ MW/wine/include/winsock2.h Thu Apr 18 16:26:48 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)
diff -ruNX ignore TMP/wine/server/async.c MW/wine/server/async.c
--- TMP/wine/server/async.c Tue Apr 16 11:18:11 2002
+++ MW/wine/server/async.c Fri Apr 19 13:50:30 2002
@@ -150,42 +150,32 @@
DECL_HANDLER(register_async)
{
- struct object *obj;
+ struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL);
- if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL)) )
- return;
-
- if(obj->ops->queue_async)
+ if ( !(obj) || !obj->ops->queue_async )
{
- struct async_queue *q = obj->ops->queue_async(obj, NULL, req->type, 0);
- struct async *async;
-
- async = find_async(q, current, req->overlapped);
- if(req->status==STATUS_PENDING)
- {
- if(!async)
- async = create_async(obj, current, req->overlapped);
-
- if(async)
- {
- async->status = req->status;
- if(!obj->ops->queue_async(obj, async, req->type, req->count))
- destroy_async(async);
- }
- }
- else
- {
- if(async)
- destroy_async(async);
- else
- set_error(STATUS_INVALID_PARAMETER);
- }
-
- set_select_events(obj,obj->ops->get_poll_events(obj));
- }
- else
set_error(STATUS_INVALID_HANDLE);
+ return;
+ }
+
+/*
+ * 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
+ * Usually: set_elect_events (obj, obj->ops->get_poll_events()).
+ *
+ * See also the implementations in file.c, serial.c, and sock.c.
+*/
+ obj->ops->queue_async (obj, req->overlapped, req->status, req->type, req->count);
release_object(obj);
}
diff -ruNX ignore TMP/wine/server/file.c MW/wine/server/file.c
--- TMP/wine/server/file.c Tue Apr 2 16:51:50 2002
+++ MW/wine/server/file.c Thu Apr 18 19:11:13 2002
@@ -69,7 +69,7 @@
static int file_flush( struct object *obj );
static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
static void file_destroy( struct object *obj );
-static struct async_queue * file_queue_async(struct object *obj, struct async* async, int type, int count);
+static void file_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count);
static const struct object_ops file_ops =
{
@@ -358,9 +358,10 @@
return FD_TYPE_DEFAULT;
}
-static struct async_queue *file_queue_async(struct object *obj, struct async *async, int type, int count)
+static void file_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
{
struct file *file = (struct file *)obj;
+ struct async *async;
struct async_queue *q;
assert( obj->ops == &file_ops );
@@ -368,7 +369,7 @@
if ( !(file->flags & FILE_FLAG_OVERLAPPED) )
{
set_error ( STATUS_INVALID_HANDLE );
- return NULL;
+ return;
}
switch(type)
@@ -381,13 +382,26 @@
break;
default:
set_error( STATUS_INVALID_PARAMETER );
- return NULL;
+ return;
}
- if(async && !async->q)
- async_insert(q, async);
+ async = find_async ( q, current, ptr );
+
+ if ( status == STATUS_PENDING )
+ {
+ if ( !async )
+ async = create_async ( obj, current, ptr );
+ if ( !async )
+ return;
+
+ async->status = STATUS_PENDING;
+ if ( !async->q )
+ async_insert( q, async );
+ }
+ else if ( async ) destroy_async ( async );
+ else set_error ( STATUS_INVALID_PARAMETER );
- return q;
+ set_select_events ( obj, file_get_poll_events ( obj ));
}
static void file_destroy( struct object *obj )
diff -ruNX ignore TMP/wine/server/object.h MW/wine/server/object.h
--- TMP/wine/server/object.h Thu Apr 4 09:37:39 2002
+++ MW/wine/server/object.h Fri Apr 19 13:29:37 2002
@@ -63,8 +63,8 @@
int (*flush)(struct object *);
/* get file information */
int (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags);
- /* queue an async operation */
- struct async_queue* (*queue_async)(struct object *, struct async *async, int type, int count);
+ /* queue an async operation - see register_async handler in async.c*/
+ void (*queue_async)(struct object *, void* ptr, unsigned int status, int type, int count);
/* destroy on refcount == 0 */
void (*destroy)(struct object *);
};
diff -ruNX ignore TMP/wine/server/protocol.def MW/wine/server/protocol.def
--- TMP/wine/server/protocol.def Thu Apr 18 16:26:02 2002
+++ MW/wine/server/protocol.def Fri Apr 19 10:49:29 2002
@@ -612,7 +612,9 @@
};
#define FD_FLAG_OVERLAPPED 0x01
#define FD_FLAG_TIMEOUT 0x02
-
+/* Socket flags: see server/sock.c */
+#define FD_FLAG_RECV_SHUTDOWN 0x04
+#define FD_FLAG_SEND_SHUTDOWN 0x08
/* Set a file current position */
@REQ(set_file_pointer)
@@ -746,6 +748,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 Thu Apr 18 16:26:02 2002
+++ MW/wine/server/request.h Fri Apr 19 13:51:02 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/serial.c MW/wine/server/serial.c
--- TMP/wine/server/serial.c Tue Apr 2 16:51:51 2002
+++ MW/wine/server/serial.c Fri Apr 19 13:36:47 2002
@@ -51,7 +51,7 @@
static int serial_get_fd( struct object *obj );
static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
static int serial_get_poll_events( struct object *obj );
-static struct async_queue * serial_queue_async(struct object *obj, struct async* async, int type, int count);
+static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count);
static void destroy_serial(struct object *obj);
static void serial_poll_event( struct object *obj, int event );
@@ -250,24 +250,11 @@
set_select_events(obj,obj->ops->get_poll_events(obj));
}
-/*
- * This function is an abuse of overloading that deserves some explanation.
- *
- * It has three purposes:
- *
- * 1. get the queue for a type of async operation
- * 2. requeue an async operation
- * 3. queue a new async operation
- *
- * It is overloaded so that these three functions only take one function pointer
- * in the object operations list.
- *
- * In all cases, it returns the async queue.
- */
-static struct async_queue *serial_queue_async(struct object *obj, struct async *async, int type, int count)
+static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
{
struct serial *serial = (struct serial *)obj;
struct async_queue *q;
+ struct async *async;
int timeout;
assert(obj->ops == &serial_ops);
@@ -288,19 +275,29 @@
break;
default:
set_error(STATUS_INVALID_PARAMETER);
- return NULL;
+ return;
}
- if(async)
+ async = find_async ( q, current, ptr );
+
+ if ( status == STATUS_PENDING )
{
+ if ( !async )
+ async = create_async ( obj, current, ptr );
+ if ( !async )
+ return;
+
+ async->status = STATUS_PENDING;
if(!async->q)
{
- async_add_timeout(async,timeout);
- async_insert(q, async);
+ async_add_timeout ( async, timeout );
+ async_insert ( q, async );
+ }
}
-}
+ else if ( async ) destroy_async ( async );
+ else set_error ( STATUS_INVALID_PARAMETER );
- return q;
+ set_select_events ( obj, serial_get_poll_events ( obj ));
}
/* create a serial */
diff -ruNX ignore TMP/wine/server/sock.c MW/wine/server/sock.c
--- TMP/wine/server/sock.c Thu Apr 18 16:26:02 2002
+++ MW/wine/server/sock.c Fri Apr 19 16:25:54 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 */
+ 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 */
};
@@ -85,6 +86,7 @@
static void sock_destroy( struct object *obj );
static int sock_get_error( int err );
static void sock_set_error(void);
+static void sock_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count);
static const struct object_ops sock_ops =
{
@@ -99,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 */
};
@@ -123,7 +125,25 @@
};
-static void 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 )
+{
+ struct pollfd pfd;
+
+ pfd.fd = sock->obj.fd;
+ pfd.events = event;
+ pfd.revents = 0;
+ poll (&pfd, 1, 0);
+
+ if ( pfd.revents )
+ {
+ if ( debug_level ) fprintf ( stderr, "sock_try_event: %x\n", pfd.revents );
+ sock_poll_event ( &sock->obj, pfd.revents );
+ }
+}
+
+static int sock_reselect( struct sock *sock )
{
int ev = sock_get_poll_events( &sock->obj );
@@ -132,21 +152,41 @@
if (sock->obj.select == -1) {
/* previously unconnected socket, is this reselect supposed to connect it? */
- if (!(sock->state & ~FD_WINE_NONBLOCKING)) return;
+ if (!(sock->state & ~FD_WINE_NONBLOCKING)) return 0;
/* ok, it is, attach it to the wineserver's main poll loop */
add_select_user( &sock->obj );
}
/* update condition mask */
set_select_events( &sock->obj, ev );
+ return ev;
}
/* wake anybody waiting on the socket event or send the associated message */
-static void sock_wake_up( struct sock *sock )
+static void sock_wake_up( struct sock *sock, int pollev )
{
unsigned int events = sock->pmask & sock->mask;
int i;
+ int async_active = 0;
- if (!events) return;
+ if ( sock->flags & FD_FLAG_OVERLAPPED )
+ {
+ if( pollev & (POLLIN|POLLPRI) && IS_READY( sock->read_q ) )
+ {
+ if (debug_level) fprintf ( stderr, "activating read queue for socket %p\n", sock );
+ async_notify( sock->read_q.head, STATUS_ALERTED );
+ async_active = 1;
+ }
+ if( pollev & POLLOUT && IS_READY( sock->write_q ) )
+ {
+ if (debug_level) fprintf ( stderr, "activating write queue for socket %p\n", sock );
+ async_notify( sock->write_q.head, STATUS_ALERTED );
+ async_active = 1;
+ }
+ }
+
+ /* Do not signal events if there are still pending asynchronous IO requests */
+ /* We need this to delay FD_CLOSE events until all pending overlapped requests are processed */
+ if ( !events || async_active ) return;
if (sock->event)
{
@@ -182,6 +222,7 @@
static void sock_poll_event( struct object *obj, int event )
{
struct sock *sock = (struct sock *)obj;
+ int empty_recv = 0;
assert( sock->obj.ops == &sock_ops );
if (debug_level)
@@ -232,19 +273,37 @@
if (event & POLLIN)
{
char dummy;
+ int nr;
/* 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
+ nr = recv( sock->obj.fd, &dummy, 1, MSG_PEEK );
+
+ if ( nr > 0 )
{
/* 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 );
+ fprintf( stderr, "socket %d is readable\n", sock->obj.fd );
}
+ else if ( nr == 0 )
+ empty_recv = 1;
+ else
+ {
+ /* EAGAIN can happen if an async recv() falls between the server's poll()
+ call and the invocation of this routine */
+ if ( errno == EAGAIN )
+ event &= ~POLLIN;
+ else
+ {
+ if ( debug_level )
+ fprintf ( stderr, "recv error on socket %d: %d\n", sock->obj.fd, errno );
+ event = POLLERR;
+ }
+ }
+
}
if (event & POLLOUT)
{
@@ -262,25 +321,37 @@
if (debug_level)
fprintf(stderr, "socket %d got OOB data\n", sock->obj.fd);
}
- if (((event & POLLERR) || ((event & (POLLIN|POLLHUP)) == POLLHUP))
- && (sock->state & (FD_READ|FD_WRITE))) {
+ if ( (sock->state & (FD_READ|FD_WRITE)) && (event & (POLLERR|POLLHUP)) )
+ {
/* socket closing */
sock->errors[FD_CLOSE_BIT] = sock_error( sock->obj.fd );
- sock->state &= ~(FD_WINE_CONNECTED|FD_READ|FD_WRITE);
+ sock->state &= ~(FD_WINE_CONNECTED|FD_WRITE);
sock->pmask |= FD_CLOSE;
if (debug_level)
fprintf(stderr, "socket %d aborted by error %d\n",
sock->obj.fd, sock->errors[FD_CLOSE_BIT]);
}
+ else if ( empty_recv && (sock->state & FD_READ) )
+ {
+ /* incoming stream closing - do not alter sock->state, reading is still allowed */
+ sock->errors[FD_CLOSE_BIT] = 0;
+ sock->pmask |= FD_CLOSE;
+ if (debug_level)
+ fprintf(stderr, "socket %d incoming stream closed\n", sock->obj.fd);
+ }
}
if (event & (POLLERR|POLLHUP))
+ {
+ if ( debug_level )
+ fprintf ( stderr, "HUP/ERR - removing socket %d from select loop\n", sock->obj.fd );
set_select_events( &sock->obj, -1 );
+ }
else
sock_reselect( sock );
/* wake up anyone waiting for whatever just happened */
- if (sock->pmask & sock->mask) sock_wake_up( sock );
+ if ( sock->pmask & sock->mask || sock->flags & FD_FLAG_OVERLAPPED ) sock_wake_up( sock, event );
/* if anyone is stupid enough to wait on the socket object itself,
* maybe we should wake them up too, just in case? */
@@ -319,8 +390,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;
}
@@ -350,10 +424,70 @@
reply->serial = 0;
}
*flags = 0;
- if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
+ if ( !(sock->state & FD_READ ) ) *flags |= FD_FLAG_RECV_SHUTDOWN;
+ if ( !(sock->state & FD_WRITE ) ) *flags |= FD_FLAG_SEND_SHUTDOWN;
+ if ( sock->flags & WSA_FLAG_OVERLAPPED ) *flags |= FD_FLAG_OVERLAPPED;
return FD_TYPE_DEFAULT;
}
+static void sock_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
+{
+ struct sock *sock = (struct sock *)obj;
+ struct async_queue *q;
+ struct async *async;
+ int pollev;
+
+ assert( obj->ops == &sock_ops );
+
+ if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
+ {
+ set_error ( STATUS_INVALID_HANDLE );
+ return;
+ }
+
+ 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;
+ }
+
+ 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 );
+ }
+ else
+ {
+ if ( !async )
+ async = create_async ( obj, current, ptr );
+ if ( !async )
+ 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 );
+ else if ( sock->pmask & sock->mask ) sock_wake_up ( sock, 0 );
+}
+
static void sock_destroy( struct object *obj )
{
struct sock *sock = (struct sock *)obj;
@@ -361,6 +495,9 @@
/* FIXME: special socket shutdown stuff? */
+ if ( sock->deferred )
+ release_object ( sock->deferred );
+
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
destroy_async_queue ( &sock->read_q );
@@ -394,13 +531,14 @@
sock->window = 0;
sock->message = 0;
sock->wparam = 0;
- sock_reselect( sock );
- clear_error();
+ sock->deferred = NULL;
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;
}
@@ -417,44 +555,51 @@
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;
- }
- /* 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 );
- }
+ if ( sock->deferred ) {
+ acceptsock = sock->deferred;
+ sock->deferred = NULL;
+ } 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;
+ acceptsock->deferred = 0;
+ if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
+ {
+ init_async_queue ( &acceptsock->read_q );
+ init_async_queue ( &acceptsock->write_q );
+ }
+ }
clear_error();
sock->pmask &= ~FD_ACCEPT;
sock->hmask &= ~FD_ACCEPT;
@@ -566,6 +711,7 @@
{
struct sock *sock;
struct event *old_event;
+ int pollev;
if (!(sock = (struct sock*)get_handle_obj( current->process, req->handle,
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &sock_ops)))
@@ -579,7 +725,11 @@
if (req->event) sock->event = get_event_obj( current->process, req->event, EVENT_MODIFY_STATE );
if (debug_level && sock->event) fprintf(stderr, "event ptr: %p\n", sock->event);
- sock_reselect( sock );
+
+ pollev = sock_reselect( sock );
+ if ( pollev ) sock_try_event ( sock, pollev );
+ else if ( sock->pmask & sock->mask ) sock_wake_up ( sock, 0 );
+
if (sock->mask)
sock->state |= FD_WINE_NONBLOCKING;
@@ -587,7 +737,7 @@
it is possible that FD_CONNECT or FD_ACCEPT network events has happened
before a WSAEventSelect() was done on it.
(when dealing with Asynchronous socket) */
- if (sock->pmask & sock->mask) sock_wake_up( sock );
+ if (sock->pmask & sock->mask) sock_wake_up( sock, pollev );
if (old_event) release_object( old_event ); /* we're through with it */
release_object( &sock->obj );
@@ -634,6 +784,7 @@
DECL_HANDLER(enable_socket_event)
{
struct sock *sock;
+ int pollev;
if (!(sock = (struct sock*)get_handle_obj( current->process, req->handle,
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &sock_ops)))
@@ -643,6 +794,33 @@
sock->hmask &= ~req->mask;
sock->state |= req->sstate;
sock->state &= ~req->cstate;
- sock_reselect( sock );
+
+ pollev = sock_reselect( sock );
+ if ( pollev ) sock_try_event ( sock, pollev );
+ else if ( sock->pmask & sock->mask ) sock_wake_up ( sock, 0 );
+
release_object( &sock->obj );
+}
+
+DECL_HANDLER(set_socket_deferred)
+{
+ struct sock *sock, *acceptsock;
+
+ sock=(struct sock*)get_handle_obj( current->process,req->handle,
+ GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+ if ( !sock )
+ {
+ 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 );
+ return;
+ }
+ sock->deferred = acceptsock;
+ release_object ( sock );
}
diff -ruNX ignore TMP/wine/server/trace.c MW/wine/server/trace.c
--- TMP/wine/server/trace.c Thu Apr 18 16:26:02 2002
+++ MW/wine/server/trace.c Fri Apr 19 13:51:02 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 19, 2002
Re: small patch for ./tools/wineinstall
by Tony Lambregts
Speeddymon wrote:
>my first patch fixes that problem and quite a few
>others
>
Please resubmit your patch in proper diff format. I have made proper
diffs for you (attached) but I don't feel right about submitting someone
elses work. I have tested it on my machine and it works fine. I
appreciate the work you put into getting these two programs to work but,
there is no way that your "patch" will get into cvs unless it is in
proper diff format. As I said before I dont feel right about submitting
someone elses work.
Tony Lambregts
Index: wineconf
===================================================================
RCS file: /home/wine/wine/tools/wineconf,v
retrieving revision 1.12
diff -u -r1.12 wineconf
--- wineconf 10 Mar 2002 00:24:22 -0000 1.12
+++ wineconf 17 Apr 2002 23:00:51 -0000
@@ -93,13 +93,20 @@
my ($device, $mntpoint, $type, @rest) = split(' ', $_);
if ($device !~ m"^/dev/fd") {
- if ($type eq "msdos" || $type eq "vfat") {
+ if ($type eq "ntfs") {
+ push(@::FatDrives, [$device, $mntpoint, 'win95']);
+ }
+ elsif ($type eq "msdos" || $type eq "vfat") {
push(@::FatDrives, [$device, $mntpoint, $type]);
}
elsif ($type eq "iso9660" ||
- $mntpoint eq "/cdrom" ||
+ ($mntpoint eq "/cdrom" && ! $type eq 'supermount') ||
($device eq '/dev/cdrom' && $type eq 'auto') ) {
push(@::CdromDrives, [$device, $mntpoint, 'win95']);
+ }
+ elsif ( ($mntpoint eq '/mnt/cdrom' || $mntpoint eq '/cdrom')
+ && $type eq 'supermount') {
+ push(@::CdromDrives, [ '/dev/cdrom', $mntpoint, 'win95']);
}
}
}
Index: wineinstall
===================================================================
RCS file: /home/wine/wine/tools/wineinstall,v
retrieving revision 1.26
diff -u -r1.26 wineinstall
--- wineinstall 1 Apr 2002 20:56:51 -0000 1.26
+++ wineinstall 17 Apr 2002 23:06:39 -0000
@@ -74,6 +74,25 @@
# that require root access
# add text to tell the user we need to run stuff as root so they don't
# think we are trying to pull something funny
+# Apr 14 2002 - Dustin Navea
+# tools/wineconf: fix to find Win2k on ntfs partitions (still read-only
+# tho)
+# tools/wineconf: fix to find non-supermount cd-rom drives (when mounted
+# at /cdrom)
+# tools/wineconf: fix to find supermount cd-rom drives and give it proper
+# device name (long as there is only 1 cd-rom)
+# Fix sed command when finding real-windows registry so it actually
+# accesses a file (~/.wine/config) instead of null ($CONF?!)
+# Added search for clean-install (not upgrade) Win2k registry
+# (next day, after some sleep)
+# Fix sed string when finding real-windows registry to actually find
+# windows partition name in [Drive C] section
+# it should now always find the windows partition and real-windows
+# registry (if not, let me know)
+# Apr 16 2002 - Dustin Navea
+# for some reason everything compiles ok on my setup, but libntdll.dll.so
+# can't be found when I run wine...having $libdir/wine in my
+# ld.config.so and running ldconfig fixed it tho, so I added that.
#--- defaults (change these if you are a packager)
CONFARGS="--enable-opengl" # configure args, e.g. --prefix=/usr --sysconfdir=/etc
@@ -291,6 +310,14 @@
sucommand="echo $libdir>>/etc/ld.so.conf;ldconfig;$sucommand"
}
fi
+ if [ -f /etc/ld.so.conf ] && ! grep -qs "$libdir/wine" /etc.ld.so.conf
+ then {
+ echo
+ echo "$libdir/wine doesn't exist in your /etc/ld.so.conf, it will be"
+ echo " added when we perform the install..."
+ sucommand="echo $libdir/wine>>/etc/ld.so.conf;$sucommand"
+ }
+ fi
echo
@@ -578,12 +605,14 @@
# (not to be done if windows registry exists)
if [ "$DOREG" = 'auto' ]
then {
- CROOT=`sed -n '/^\[Drive C\]$/,/^\[.*\]$/ s/^Path=\(.*\)/\1/p' $CONF`
+ CROOT=`sed -n '/^\[Drive C\]$/,/^\[.*\]$/ s/^\"Path\" = \"\(.*\)\"/\1/p' $LCONF`
echo "Checking for real Windows registry..."
if [ -f "$CROOT/windows/system.dat" ]
then DOREG=no
elif [ -f "$CROOT/windows/system32/config/system" ]
then DOREG=no
+ elif [ -f "$CROOT/WINNT/system32/config/system" ]
+ then DOREG=no
else DOREG=yes
fi
if [ "$DOREG" = 'yes' ]
April 19, 2002
Re: ALSA driver
by David Hammerton
Hi,
Eric has written one which is almost complete, I am in the midst of debugging
it and finising it off.
Contact me directly if you like.
David
On 19 Apr 2002 17:57:07 +0200, Marco Pietrobono wrote:
| Hi,
|
| I'm starting to work on a native ALSA driver for wine. Since I
| remember that Marcus was working (or was planning to work) an that one
| too, I would like to know if there is already something to work on or to
| contribute to, or if I need to start from scratch.
|
| If there is nothing already written, I would like to discuss what kind
| of approach we should use with ALSA programming, since FWIK there should
| be two way to use it: we can use the ALSA devices directly, just like it
| has been done with OSS, or we can use the alsalib to avoid all direct
| references to the kernel devices and ioctl, but this solution will add a
| dependency on the alsalib library itself to wine. Of course, we could
| add a configure option/check to allow its use at compilation time,
| but...
|
| BTW, Alsalib is LGPL, so the license shouldn't be a problem.
|
| bye,
|
| /pietrobo
|
|
| --
| Stud. Marco Pietrobono | Murphy's Law: if something could
| v. del Calice, 39 - 00178 ROMA | go wrong, it does.
| Tel. +39.06.7186329 339.7410893 | Legge di Murphy: se qualcosa può
| http://www.pietrobo.com | andar male, lo farà.
| ------------------------------------------------------------------------
| Strange game.
| The only winning move
| is not to play.
| What about a nice play of chess ?
|
--
David Hammerton
programmer and support
TransGaming Technologies Inc.
http://www.transgaming.com
david(a)transgaming.com
April 19, 2002