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 )