From 81f2a7307b8e3619fb7121f94f6c2d5085c7c528 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 23 Mar 2002 20:43:52 +0000 Subject: [PATCH] Send message for WSAAsyncSelect sockets directly from the server, instead of using the service thread. Finished separation of ws2_32. --- dlls/winsock/Makefile.in | 4 +- dlls/winsock/socket.c | 176 ++++------------------------- include/wine/server_protocol.h | 11 +- include/winsock.h | 1 - server/protocol.def | 9 +- server/queue.c | 31 ++++++ server/sock.c | 198 +++++++++++++++++---------------- server/trace.c | 5 +- server/user.h | 3 + server/window.c | 7 ++ 10 files changed, 185 insertions(+), 260 deletions(-) diff --git a/dlls/winsock/Makefile.in b/dlls/winsock/Makefile.in index d41535cd38a..985562f326a 100644 --- a/dlls/winsock/Makefile.in +++ b/dlls/winsock/Makefile.in @@ -5,7 +5,9 @@ SRCDIR = @srcdir@ 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 379e28d61e6..b2c50ac5e05 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 @@ typedef struct /* WSAAsyncSelect() control struct */ #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 _px_tcp_ops[] = { */ 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 @@ inline static unsigned int set_error( unsigned int err ) 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 @@ static int _is_blocking(SOCKET s) { 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 @@ static unsigned int _get_sock_mask(SOCKET s) { 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 @@ static int _get_sock_error(SOCKET s, unsigned int bit) { 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 @@ static struct ws_protoent* check_buffer_pe(int size) #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; qhandle = 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 @@ int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent) req->handle = s; req->mask = lEvent; req->event = hEvent; + req->window = 0; + req->msg = 0; ret = wine_server_call( req ); } SERVER_END_REQ; @@ -2760,118 +2718,28 @@ int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent) return SOCKET_ERROR; } -/*********************************************************************** - * 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; qsock) { - /* 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; ihWnd, info->uMsg, info->sock, - WSAMAKESELECTREPLY(1<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 d54fb774e1d..d51a10f53ce 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -907,9 +907,11 @@ struct accept_socket_reply 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 get_socket_event_request 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 @@ union generic_reply 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 23fd5856dd2..6b90bf03787 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -733,7 +733,6 @@ typedef struct WS(WSAData) #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 88415c94358..7d3b3e88477 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -677,9 +677,11 @@ enum fd_type /* 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 @@ enum fd_type @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 4c3efd3d24f..7ebef989d5f 100644 --- a/server/queue.c +++ b/server/queue.c @@ -684,6 +684,37 @@ void queue_cleanup_window( struct thread *thread, user_handle_t win ) } } +/* 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 aa17293f0b2..3d1e13969aa 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 @@ struct sock 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 @@ static const struct object_ops sock_ops = 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 @@ static void sock_reselect( struct sock *sock ) } /* 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 @@ inline static int sock_error(int s) 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 @@ static void sock_poll_event( struct object *obj, int event ) 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 @@ static void sock_destroy( struct object *obj ) 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 @@ static struct object *create_socket( int family, int type, int protocol, unsigne 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 @@ static struct object *create_socket( int family, int type, int protocol, unsigne } /* 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 @@ static struct object *accept_socket( handle_t handle ) 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 @@ static struct object *accept_socket( handle_t handle ) 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 @@ DECL_HANDLER(create_socket) /* 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(accept_socket) 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 @@ DECL_HANDLER(set_socket_event) 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 @@ DECL_HANDLER(get_socket_event) 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 @@ DECL_HANDLER(enable_socket_event) { 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 6e0e8763b6f..93a33af2613 100644 --- a/server/trace.c +++ b/server/trace.c @@ -856,14 +856,15 @@ static void dump_set_socket_event_request( const struct set_socket_event_request { 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 d62ced116ce..f3e10604a13 100644 --- a/server/user.h +++ b/server/user.h @@ -45,11 +45,14 @@ extern void *next_user_handle( user_handle_t *handle, enum user_object type ); 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 40790072892..f7fc039cb4e 100644 --- a/server/window.c +++ b/server/window.c @@ -329,6 +329,13 @@ int is_child_window( user_handle_t parent, user_handle_t child ) 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 )