Send message for WSAAsyncSelect sockets directly from the server,
instead of using the service thread. Finished separation of ws2_32.

diff --git a/dlls/winsock/Makefile.in b/dlls/winsock/Makefile.in
index d41535c..985562f 100644
--- a/dlls/winsock/Makefile.in
+++ b/dlls/winsock/Makefile.in
@@ -5,7 +5,9 @@
 VPATH     = @srcdir@
 MODULE    = ws2_32.dll
 ALTNAMES  = winsock.dll
-IMPORTS   = user32.dll kernel32.dll ntdll.dll
+
+LDDLLFLAGS = @LDDLLFLAGS@
+SYMBOLFILE = $(MODULE).tmp.o
 
 C_SRCS = \
 	async.c \
diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c
index 379e28d..b2c50ac 100644
--- a/dlls/winsock/socket.c
+++ b/dlls/winsock/socket.c
@@ -104,9 +104,7 @@
 #include "wsipx.h"
 #include "wine/winsock16.h"
 #include "winnt.h"
-#include "services.h"
 #include "wine/server.h"
-#include "file.h"
 #include "wine/debug.h"
 
 
@@ -140,14 +138,10 @@
 #define WS_MAX_SOCKETS_PER_PROCESS      128     /* reasonable guess */
 #define WS_MAX_UDP_DATAGRAM             1024
 
-#define WS_ACCEPT_QUEUE 6
-
 #define PROCFS_NETDEV_FILE   "/proc/net/dev" /* Points to the file in the /proc fs 
                                                 that lists the network devices.
                                                 Do we need an #ifdef LINUX for this? */
 
-static volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
-
 static void *he_buffer;          /* typecast for Win16/32 ws_hostent */
 static SEGPTR he_buffer_seg;
 static void *se_buffer;          /* typecast for Win16/32 ws_servent */
@@ -224,23 +218,6 @@
  */
 static int opentype = 0;
 
-/* Permutation of 0..FD_MAX_EVENTS - 1 representing the order in which we post
- * messages if there are multiple events.  Used in WINSOCK_DoAsyncEvent.  The
- * problem is if there is both a FD_CONNECT event and, say, an FD_READ event
- * available on the same socket, we want to notify the app of the connect event
- * first.  Otherwise it may discard the read event because it thinks it hasn't
- * connected yet.
- */
-static const int event_bitorder[FD_MAX_EVENTS] = {
-    FD_CONNECT_BIT,
-    FD_ACCEPT_BIT,
-    FD_OOB_BIT,
-    FD_WRITE_BIT,
-    FD_READ_BIT,
-    FD_CLOSE_BIT,
-    6, 7, 8, 9  /* leftovers */
-};
-
 /* set last error code from NT status without mapping WSA errors */
 inline static unsigned int set_error( unsigned int err )
 {
@@ -255,12 +232,12 @@
 
 static char* check_buffer(int size);
 
-static int _get_sock_fd(SOCKET s)
+inline static int _get_sock_fd(SOCKET s)
 {
-    int fd = FILE_GetUnixHandle( s, GENERIC_READ );
-    if (fd == -1)
-        FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
-    return fd;    
+    int fd;
+
+    if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
+    return fd;
 }
 
 static void _enable_event(SOCKET s, unsigned int event,
@@ -284,7 +261,6 @@
     {
         req->handle  = s;
         req->service = FALSE;
-        req->s_event = 0;
         req->c_event = 0;
         wine_server_call( req );
         ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
@@ -300,7 +276,6 @@
     {
         req->handle  = s;
         req->service = FALSE;
-        req->s_event = 0;
         req->c_event = 0;
         wine_server_call( req );
         ret = reply->mask;
@@ -324,7 +299,6 @@
     {
         req->handle  = s;
         req->service = FALSE;
-        req->s_event = 0;
         req->c_event = 0;
         wine_server_set_reply( req, events, sizeof(events) );
         wine_server_call( req );
@@ -790,20 +764,6 @@
 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
 #endif
 
-static void ws2_async_accept(SOCKET s, SOCKET as)
-{
-    int q;
-    /* queue socket for WSAAsyncSelect */
-    for (q=0; q<WS_ACCEPT_QUEUE; q++)
-	if (InterlockedCompareExchange((LONG *)&accept_old[q], s, 0) == 0)
-	    break;
-    if (q<WS_ACCEPT_QUEUE)
-	accept_new[q] = as;
-    else
-	ERR("accept queue too small\n");
-    /* now signal our AsyncSelect handler */
-    _enable_event(s, FD_WINE_SERVEVENT, 0, 0);
-}
 
 /**********************************************************************/
 
@@ -965,10 +925,7 @@
         SERVER_END_REQ;
 	if (as)
 	{
-	    unsigned omask = _get_sock_mask( s );
 	    WS_getpeername(as, addr, addrlen32);
-	    if (omask & FD_WINE_SERVEVENT)
-		ws2_async_accept(s, as);
 	    return as;
 	}
     }
@@ -2727,7 +2684,6 @@
     {
         req->handle  = s;
         req->service = TRUE;
-        req->s_event = 0;
         req->c_event = hEvent;
         wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
         if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
@@ -2752,6 +2708,8 @@
         req->handle = s;
         req->mask   = lEvent;
         req->event  = hEvent;
+        req->window = 0;
+        req->msg    = 0;
         ret = wine_server_call( req );
     }
     SERVER_END_REQ;
@@ -2761,117 +2719,27 @@
 }
 
 /***********************************************************************
- *      WINSOCK_DoAsyncSelect
- */
-VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
-{
-    ws_select_info *info = (ws_select_info*)ptr;
-    unsigned int i, j, pmask, orphan = FALSE;
-    int errors[FD_MAX_EVENTS];
-
-    TRACE("socket %08x, event %08x\n", info->sock, info->event);
-    SetLastError(0);
-    SERVER_START_REQ( get_socket_event )
-    {
-        req->handle  = info->sock;
-        req->service = TRUE;
-        req->s_event = info->event; /* <== avoid race conditions */
-        req->c_event = info->event;
-        wine_server_set_reply( req, errors, sizeof(errors) );
-        set_error( wine_server_call(req) );
-        pmask = reply->pmask;
-    }
-    SERVER_END_REQ;
-    if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
-    {
-	/* orphaned event (socket closed or something) */
-	pmask = FD_WINE_SERVEVENT;
-	orphan = TRUE;
-    }
-
-    /* check for accepted sockets that needs to inherit WSAAsyncSelect */
-    if (pmask & FD_WINE_SERVEVENT) {
-	int q;
-	for (q=0; q<WS_ACCEPT_QUEUE; q++)
-	    if (accept_old[q] == info->sock) {
-		/* there's only one service thread per process, no lock necessary */
-		HANDLE as = accept_new[q];
-		if (as) {
-		    accept_new[q] = 0;
-		    accept_old[q] = 0;
-		    WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
-		}
-	    }
-	pmask &= ~FD_WINE_SERVEVENT;
-    }
-    /* dispatch network events, but use the order in the event_bitorder
-     * array.
-     */
-    for (i=0; i<FD_MAX_EVENTS; i++) {
-        j = event_bitorder[i];
-        if (pmask & (1<<j)) {
-            TRACE("post: event bit %d, error %d\n", j, errors[j]);
-            PostMessageA(info->hWnd, info->uMsg, info->sock,
-                         WSAMAKESELECTREPLY(1<<j, errors[j]));
-        }
-    }
-    /* cleanup */
-    if (orphan)
-    {
-	TRACE("orphaned event, self-destructing\n");
-	/* SERVICE_Delete closes the event object */
-	SERVICE_Delete( info->service );
-	WS_FREE(info);
-    }
-}
-
-/***********************************************************************
  *      WSAAsyncSelect			(WS2_32.101)
  */
 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
 {
-    int fd = _get_sock_fd(s);
+    int ret;
 
-    TRACE("%04x, hWnd %04x, uMsg %08x, event %08x\n",
-          (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
-    if (fd != -1)
+    TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
+
+    SERVER_START_REQ( set_socket_event )
     {
-        close(fd);
-	if( lEvent )
-	{
-	    ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
-	    if( info )
-	    {
-		HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
-		INT err;
-		
-		info->sock   = s;
-		info->event  = hObj;
-		info->hWnd   = hWnd;
-		info->uMsg   = uMsg;
-		info->lEvent = lEvent;
-		info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
-
-		err = WSAEventSelect( s, hObj, lEvent | FD_WINE_SERVEVENT );
-		if (err) {
-		    /* SERVICE_Delete closes the event object */
-		    SERVICE_Delete( info->service );
-		    WS_FREE(info);
-		    return err;
-		}
-
-		return 0; /* success */
-	    }
-	    else SetLastError(WSAENOBUFS);
-	} 
-	else
-	{
-	    WSAEventSelect(s, 0, 0);
-	    return 0;
-	}
-    } 
-    else SetLastError(WSAEINVAL);
-    return SOCKET_ERROR; 
+        req->handle = s;
+        req->mask   = lEvent;
+        req->event  = 0;
+        req->window = hWnd;
+        req->msg    = uMsg;
+        ret = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+    if (!ret) return 0;
+    SetLastError(WSAEINVAL);
+    return SOCKET_ERROR;
 }
 
 /***********************************************************************
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index d54fb77..d51a10f 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -907,9 +907,11 @@
 struct set_socket_event_request
 {
     struct request_header __header;
-    handle_t     handle;
-    unsigned int mask;
-    handle_t     event;
+    handle_t      handle;
+    unsigned int  mask;
+    handle_t      event;
+    user_handle_t window;
+    unsigned int  msg;
 };
 struct set_socket_event_reply
 {
@@ -923,7 +925,6 @@
     struct request_header __header;
     handle_t     handle;
     int          service;
-    handle_t     s_event;
     handle_t     c_event;
 };
 struct get_socket_event_reply
@@ -3127,6 +3128,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 74
+#define SERVER_PROTOCOL_VERSION 75
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/include/winsock.h b/include/winsock.h
index 23fd585..6b90bf0 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -733,7 +733,6 @@
 #define FD_WINE_NONBLOCKING        0x20000000
 #define FD_WINE_CONNECTED          0x40000000
 #define FD_WINE_RAW                0x80000000
-#define FD_WINE_SERVEVENT          0x01000000
 #define FD_WINE_INTERNAL           0xFFFF0000
 #endif
 
diff --git a/server/protocol.def b/server/protocol.def
index 88415c9..7d3b3e8 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -677,9 +677,11 @@
 
 /* Set socket event parameters */
 @REQ(set_socket_event)
-    handle_t     handle;        /* handle to the socket */
-    unsigned int mask;          /* event mask */
-    handle_t     event;         /* event object */
+    handle_t      handle;        /* handle to the socket */
+    unsigned int  mask;          /* event mask */
+    handle_t      event;         /* event object */
+    user_handle_t window;        /* window to send the message to */
+    unsigned int  msg;           /* message to send */
 @END
 
 
@@ -687,7 +689,6 @@
 @REQ(get_socket_event)
     handle_t     handle;        /* handle to the socket */
     int          service;       /* clear pending? */
-    handle_t     s_event;       /* "expected" event object */
     handle_t     c_event;       /* event to clear */
 @REPLY
     unsigned int mask;          /* event mask */
diff --git a/server/queue.c b/server/queue.c
index 4c3efd3..7ebef98 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -684,6 +684,37 @@
     }
 }
 
+/* post a message to a window; used by socket handling */
+void post_message( user_handle_t win, unsigned int message,
+                   unsigned int wparam, unsigned int lparam )
+{
+    struct message *msg;
+    struct thread *thread = get_window_thread( win );
+
+    if (!thread) return;
+
+    if (thread->queue && (msg = mem_alloc( sizeof(*msg) )))
+    {
+        msg->type      = MSG_POSTED;
+        msg->win       = get_user_full_handle( win );
+        msg->msg       = message;
+        msg->wparam    = wparam;
+        msg->lparam    = lparam;
+        msg->time      = get_tick_count();
+        msg->x         = 0;
+        msg->y         = 0;
+        msg->info      = 0;
+        msg->result    = NULL;
+        msg->data      = NULL;
+        msg->data_size = 0;
+
+        append_message( &thread->queue->msg_list[POST_MESSAGE], msg );
+        set_queue_bits( thread->queue, QS_POSTMESSAGE );
+    }
+    release_object( thread );
+}
+
+
 /* get the message queue of the current thread */
 DECL_HANDLER(get_msg_queue)
 {
diff --git a/server/sock.c b/server/sock.c
index aa17293..3d1e139 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -50,6 +50,7 @@
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
+#include "user.h"
 #include "async.h"
 
 /* To avoid conflicts with the Unix socket headers. Plus we only need a few
@@ -67,6 +68,9 @@
     unsigned int        pmask;       /* pending events */
     unsigned int        flags;       /* socket flags */
     struct event       *event;       /* event object */
+    user_handle_t       window;      /* window to send the message to */
+    unsigned int        message;     /* message to send */
+    unsigned int        wparam;      /* message wparam (socket handle) */
     int                 errors[FD_MAX_EVENTS]; /* event errors */
     struct async_queue  read_q;      /* Queue for asynchronous reads */
     struct async_queue  write_q;     /* Queue for asynchronous writes */
@@ -99,10 +103,29 @@
     sock_destroy                  /* destroy */
 };
 
+
+/* Permutation of 0..FD_MAX_EVENTS - 1 representing the order in which
+ * we post messages if there are multiple events.  Used to send
+ * messages.  The problem is if there is both a FD_CONNECT event and,
+ * say, an FD_READ event available on the same socket, we want to
+ * notify the app of the connect event first.  Otherwise it may
+ * discard the read event because it thinks it hasn't connected yet.
+ */
+static const int event_bitorder[FD_MAX_EVENTS] =
+{
+    FD_CONNECT_BIT,
+    FD_ACCEPT_BIT,
+    FD_OOB_BIT,
+    FD_WRITE_BIT,
+    FD_READ_BIT,
+    FD_CLOSE_BIT,
+    6, 7, 8, 9  /* leftovers */
+};
+
+
 static void sock_reselect( struct sock *sock )
 {
     int ev = sock_get_poll_events( &sock->obj );
-    struct pollfd pfd;
 
     if (debug_level)
         fprintf(stderr,"sock_reselect(%d): new mask %x\n", sock->obj.fd, ev);
@@ -115,14 +138,36 @@
     }
     /* update condition mask */
     set_select_events( &sock->obj, ev );
+}
 
-    /* check whether condition is satisfied already */
-    pfd.fd = sock->obj.fd;
-    pfd.events = ev;
-    pfd.revents = 0;
-    poll( &pfd, 1, 0 );
-    if (pfd.revents)
-        sock_poll_event( &sock->obj, pfd.revents);
+/* wake anybody waiting on the socket event or send the associated message */
+static void sock_wake_up( struct sock *sock )
+{
+    unsigned int events = sock->pmask & sock->mask;
+    int i;
+
+    if (!events) return;
+
+    if (sock->event)
+    {
+        if (debug_level) fprintf(stderr, "signalling events %x ptr %p\n", events, sock->event );
+        set_event( sock->event );
+    }
+    if (sock->window)
+    {
+        if (debug_level) fprintf(stderr, "signalling events %x win %x\n", events, sock->window );
+        for (i = 0; i < FD_MAX_EVENTS; i++)
+        {
+            int event = event_bitorder[i];
+            if (sock->pmask & (1 << event))
+            {
+                unsigned int lparam = (1 << event) | (sock->errors[event] << 16);
+                post_message( sock->window, sock->message, sock->wparam, lparam );
+            }
+        }
+        sock->pmask = 0;
+        sock_reselect( sock );
+    }
 }
 
 inline static int sock_error(int s)
@@ -137,7 +182,7 @@
 static void sock_poll_event( struct object *obj, int event )
 {
     struct sock *sock = (struct sock *)obj;
-    unsigned int emask;
+
     assert( sock->obj.ops == &sock_ops );
     if (debug_level)
         fprintf(stderr, "socket %d select event: %x\n", sock->obj.fd, event);
@@ -233,14 +278,9 @@
         set_select_events( &sock->obj, -1 );
     else
         sock_reselect( sock );
+
     /* wake up anyone waiting for whatever just happened */
-    emask = sock->pmask & sock->mask;
-    if (debug_level && emask)
-        fprintf(stderr, "socket %d pending events: %x\n", sock->obj.fd, emask);
-    if (emask && sock->event) {
-        if (debug_level) fprintf(stderr, "signalling event ptr %p\n", sock->event);
-        set_event(sock->event);
-    }
+    if (sock->pmask & sock->mask) sock_wake_up( sock );
 
     /* if anyone is stupid enough to wait on the socket object itself,
      * maybe we should wake them up too, just in case? */
@@ -326,17 +366,7 @@
         destroy_async_queue ( &sock->read_q );
         destroy_async_queue ( &sock->write_q );
     }
-
-    if (sock->event)
-    {
-        /* if the service thread was waiting for the event object,
-         * we should now signal it, to let the service thread
-         * object detect that it is now orphaned... */
-        if (sock->mask & FD_WINE_SERVEVENT)
-            set_event( sock->event );
-        /* we're through with it */
-        release_object( sock->event );
-    }
+    if (sock->event) release_object( sock->event );
 }
 
 /* create a new and unconnected socket */
@@ -356,11 +386,14 @@
     if (!(sock = alloc_object( &sock_ops, -1 ))) return NULL;
     sock->obj.fd = sockfd;
     sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0;
-    sock->mask  = 0;
-    sock->hmask = 0;
-    sock->pmask = 0;
-    sock->flags = flags;
-    sock->event = NULL;
+    sock->mask    = 0;
+    sock->hmask   = 0;
+    sock->pmask   = 0;
+    sock->flags   = flags;
+    sock->event   = NULL;
+    sock->window  = 0;
+    sock->message = 0;
+    sock->wparam  = 0;
     sock_reselect( sock );
     clear_error();
     if (sock->flags & WSA_FLAG_OVERLAPPED)
@@ -372,7 +405,7 @@
 }
 
 /* accept a socket (creates a new fd) */
-static struct object *accept_socket( handle_t handle )
+static struct sock *accept_socket( handle_t handle )
 {
     struct sock *acceptsock;
     struct sock *sock;
@@ -407,12 +440,14 @@
     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;
-    if (sock->event && !(sock->mask & FD_WINE_SERVEVENT))
-        acceptsock->event = (struct event *)grab_object( sock->event );
+    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 )
     {
@@ -420,13 +455,12 @@
 	init_async_queue ( &acceptsock->write_q );
     }
 
-    sock_reselect( acceptsock );
     clear_error();
     sock->pmask &= ~FD_ACCEPT;
     sock->hmask &= ~FD_ACCEPT;
     sock_reselect( sock );
     release_object( sock );
-    return &acceptsock->obj;
+    return acceptsock;
 }
 
 /* set the last error depending on errno */
@@ -515,13 +549,15 @@
 /* accept a socket */
 DECL_HANDLER(accept_socket)
 {
-    struct object *obj;
+    struct sock *sock;
 
     reply->handle = 0;
-    if ((obj = accept_socket( req->lhandle )) != NULL)
+    if ((sock = accept_socket( req->lhandle )) != NULL)
     {
-        reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
-        release_object( obj );
+        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 );
     }
 }
 
@@ -529,16 +565,19 @@
 DECL_HANDLER(set_socket_event)
 {
     struct sock *sock;
-    struct event *oevent;
-    unsigned int omask;
+    struct event *old_event;
 
-    sock=(struct sock*)get_handle_obj(current->process,req->handle,GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
-    if (!sock)
-	return;
-    oevent = sock->event;
-    omask  = sock->mask;
+    if (!(sock = (struct sock*)get_handle_obj( current->process, req->handle,
+                                               GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &sock_ops)))
+        return;
+    old_event = sock->event;
     sock->mask    = req->mask;
-    sock->event   = get_event_obj( current->process, req->event, EVENT_MODIFY_STATE );
+    sock->event   = NULL;
+    sock->window  = req->window;
+    sock->message = req->msg;
+    sock->wparam  = req->handle;  /* wparam is the socket handle */
+    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 );
     if (sock->mask)
@@ -548,19 +587,9 @@
        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)
-        set_event(sock->event);
-    
-    if (oevent)
-    {
-        if ((oevent != sock->event) && (omask & FD_WINE_SERVEVENT))
-            /* if the service thread was waiting for the old event object,
-             * we should now signal it, to let the service thread
-             * object detect that it is now orphaned... */
-            set_event( oevent );
-        /* we're through with it */
-        release_object( oevent );
-    }
+    if (sock->pmask & sock->mask) sock_wake_up( sock );
+
+    if (old_event) release_object( old_event ); /* we're through with it */
     release_object( &sock->obj );
 }
 
@@ -585,25 +614,18 @@
 
     if (req->service)
     {
-        handle_t s_event = req->s_event;
-        if (s_event)
+        if (req->c_event)
         {
-            struct event *sevent = get_event_obj(current->process, req->s_event, 0);
-            if (sevent == sock->event) s_event = 0;
-            release_object( sevent );
-        }
-        if (!s_event)
-        {
-            if (req->c_event)
+            struct event *cevent = get_event_obj( current->process, req->c_event,
+                                                  EVENT_MODIFY_STATE );
+            if (cevent)
             {
-                struct event *cevent = get_event_obj(current->process, req->c_event, EVENT_MODIFY_STATE);
                 reset_event( cevent );
                 release_object( cevent );
             }
-            sock->pmask = 0;
-            sock_reselect( sock );
         }
-        else set_error(WSAEINVAL);
+        sock->pmask = 0;
+        sock_reselect( sock );
     }
     release_object( &sock->obj );
 }
@@ -613,24 +635,14 @@
 {
     struct sock *sock;
 
-    sock=(struct sock*)get_handle_obj(current->process,req->handle,GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
-    if (!sock)
-    	return;
+    if (!(sock = (struct sock*)get_handle_obj( current->process, req->handle,
+                                               GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE, &sock_ops)))
+        return;
+
     sock->pmask &= ~req->mask; /* is this safe? */
     sock->hmask &= ~req->mask;
     sock->state |= req->sstate;
     sock->state &= ~req->cstate;
     sock_reselect( sock );
-
-    /* service trigger */
-    if (req->mask & FD_WINE_SERVEVENT)
-    {
-        sock->pmask |= FD_WINE_SERVEVENT;
-        if (sock->event) {
-            if (debug_level) fprintf(stderr, "signalling service event ptr %p\n", sock->event);
-            set_event(sock->event);
-        }
-    }
-
     release_object( &sock->obj );
 }
diff --git a/server/trace.c b/server/trace.c
index 6e0e876..93a33af 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -856,14 +856,15 @@
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " mask=%08x,", req->mask );
-    fprintf( stderr, " event=%d", req->event );
+    fprintf( stderr, " event=%d,", req->event );
+    fprintf( stderr, " window=%08x,", req->window );
+    fprintf( stderr, " msg=%08x", req->msg );
 }
 
 static void dump_get_socket_event_request( const struct get_socket_event_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " service=%d,", req->service );
-    fprintf( stderr, " s_event=%d,", req->s_event );
     fprintf( stderr, " c_event=%d", req->c_event );
 }
 
diff --git a/server/user.h b/server/user.h
index d62ced1..f3e1060 100644
--- a/server/user.h
+++ b/server/user.h
@@ -45,11 +45,14 @@
 
 extern void inc_queue_paint_count( struct thread *thread, int incr );
 extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
+extern void post_message( user_handle_t win, unsigned int message,
+                          unsigned int wparam, unsigned int lparam );
 
 /* window functions */
 
 extern void destroy_thread_windows( struct thread *thread );
 extern int is_child_window( user_handle_t parent, user_handle_t child );
+extern struct thread *get_window_thread( user_handle_t handle );
 extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
 
 #endif  /* __WINE_SERVER_USER_H */
diff --git a/server/window.c b/server/window.c
index 4079007..f7fc039 100644
--- a/server/window.c
+++ b/server/window.c
@@ -329,6 +329,13 @@
     return 0;
 }
 
+/* return the thread owning a window */
+struct thread *get_window_thread( user_handle_t handle )
+{
+    struct window *win = get_user_object( handle, USER_WINDOW );
+    if (!win || !win->thread) return NULL;
+    return (struct thread *)grab_object( win->thread );
+}
 
 /* find a child of the specified window that needs repainting */
 static struct window *find_child_to_repaint( struct window *parent, struct thread *thread )