mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
Send message for WSAAsyncSelect sockets directly from the server,
instead of using the service thread. Finished separation of ws2_32.
This commit is contained in:
parent
0307f6dc7b
commit
81f2a7307b
10 changed files with 185 additions and 260 deletions
|
@ -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 \
|
||||
|
|
|
@ -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; 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 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
|
|||
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 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp
|
|||
{
|
||||
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 @@ 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; 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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
198
server/sock.c
198
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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in a new issue