linamh/app-emulation/wine/files/acceptex.patch

1174 lines
46 KiB
Diff
Raw Normal View History

diff --git a/dlls/mswsock/mswsock.spec b/dlls/mswsock/mswsock.spec
index 1f2bd78..c0814fb 100644 (file)
--- a/dlls/mswsock/mswsock.spec
+++ b/dlls/mswsock/mswsock.spec
@@ -1,7 +1,7 @@
-@ stdcall AcceptEx(long long ptr long long long ptr ptr)
+@ stdcall AcceptEx(long long ptr long long long ptr ptr) ws2_32.AcceptEx
@ stdcall EnumProtocolsA(ptr ptr ptr) ws2_32.WSAEnumProtocolsA
@ stdcall EnumProtocolsW(ptr ptr ptr) ws2_32.WSAEnumProtocolsW
-@ stdcall GetAcceptExSockaddrs(ptr long long long ptr ptr ptr ptr)
+@ stdcall GetAcceptExSockaddrs(ptr long long long ptr ptr ptr ptr) ws2_32.GetAcceptExSockaddrs
@ stub GetAddressByNameA
@ stub GetAddressByNameW
@ stub GetNameByTypeA
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 96be7ca..aa73f64 100644 (file)
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -196,6 +196,15 @@ typedef struct ws2_async
{
int val; /* for send operations */
int *ptr; /* for recv operations */
+ struct /* for accept operation */
+ {
+ SOCKET s_accept; /* socket to use as connection socket */
+ PVOID buf; /* buffer to write data to */
+ int data_len;
+ int local_len;
+ int remote_len;
+ DWORD *recvd;
+ } acpt;
} addrlen;
DWORD flags;
unsigned int n_iovecs;
@@ -241,6 +250,8 @@ static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
static struct WS_servent *WS_dup_se(const struct servent* p_se);
+static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information );
+
int WSAIOCTL_GetInterfaceCount(void);
int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
@@ -1070,6 +1081,244 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
wsa->flags );
HeapFree( GetProcessHeap(), 0, wsa );
}
+/***********************************************************************
+ * WS2_acceptex_data (INTERNAL)
+ *
+ * This function is used to place the ipaddresses in the buffer.
+ */
+static void WS2_acceptex_data( char* buf, int local_len, int remote_len, int data_len, SOCKET s )
+{
+ int len;
+ buf = buf+data_len;
+ len = local_len - sizeof(int);
+ WS_getpeername(s,(struct WS_sockaddr*)(buf+sizeof(int)),&len);
+ *(int*)buf = len;
+ buf += local_len;
+ len = remote_len - sizeof(int);
+ WS_getsockname(s,(struct WS_sockaddr*)(buf+sizeof(int)),&len);
+ *(int*)buf = len;
+}
+/***********************************************************************
+ * WS2_async_accept (INTERNAL)
+ *
+ * This is the function called to satisfy the AcceptEx callback
+ */
+static NTSTATUS WINAPI WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status )
+{
+ ws2_async *wsa = arg;
+ char *buf;
+ if(status != STATUS_ALERTED){
+ if(status != STATUS_HANDLES_CLOSED)
+ FIXME("Unexpected/Unhandeled status Message= %x \n",status);
+ }
+ TRACE("status Message= %x listen: %lx, accept: %lx\n",status, HANDLE2SOCKET(wsa->hSocket),wsa->addrlen.acpt.s_accept);
+ if(status == STATUS_HANDLES_CLOSED){
+ wsa->user_overlapped->Internal = status;
+ wsa->user_overlapped->InternalHigh = 0;
+ iosb->u.Status = status;
+ iosb->Information = 0;
+ return status;
+ }
+ SERVER_START_REQ( accept_socket )
+ {
+ req->lhandle = wsa->hSocket;
+ req->ahandle = SOCKET2HANDLE(wsa->addrlen.acpt.s_accept);
+ req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
+ req->attributes = OBJ_INHERIT;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ if(status != STATUS_SUCCESS){
+ FIXME("error in getting socket. socket: %lx, status: %x\n",wsa->addrlen.acpt.s_accept,status);
+ wsa->user_overlapped->Internal = status;
+ wsa->user_overlapped->InternalHigh = 0;
+ iosb->u.Status = status;
+ iosb->Information = 0;
+ return status;
+ }
+ /*We now have a connected socket. pull data in/write info to buffer*/
+ buf = (char*)wsa->addrlen.acpt.buf;
+ WS2_acceptex_data( buf, wsa->addrlen.acpt.local_len, wsa->addrlen.acpt.remote_len,wsa->addrlen.acpt.data_len, wsa->addrlen.acpt.s_accept );
+ /*socket address information is written. next pull in data.*/
+ /*we don't pull in data yet... */
+ wsa->addrlen.acpt.recvd = 0;
+ wsa->user_overlapped->Internal = status;
+ wsa->user_overlapped->InternalHigh = 0;
+ iosb->u.Status = status;
+ iosb->Information = 0;
+
+ HeapFree( GetProcessHeap(), 0, wsa );
+ return status;
+
+}
+
+/***********************************************************************
+ * AcceptEx (ws2_32.@)
+ *
+ * Accept a new connection, retrieving the connected addresses and initial data.
+ *
+ * listener [I] Listening socket
+ * acceptor [I] Socket to accept on
+ * dest [O] Destination for inital data
+ * dest_len [I] Size of dest in bytes
+ * local_addr_len [I] Number of bytes reserved in dest for local addrress
+ * rem_addr_len [I] Number of bytes reserved in dest for remote addrress
+ * received [O] Destination for number of bytes of initial data
+ * overlapped [I] For asynchronous execution
+ *
+ * RETURNS
+ * Success: TRUE (We always return false because its simple)
+ * Failure: FALSE. Use WSAGetLastError() for details of the error.
+ */
+BOOL WINAPI AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DWORD dest_len,
+ DWORD local_addr_len, DWORD rem_addr_len, LPDWORD received,
+ LPOVERLAPPED overlapped)
+{
+ DWORD status;
+ struct ws2_async *wsa;
+ IO_STATUS_BLOCK *iosb;
+ char *buf = (char*) dest;
+ TRACE("listen: %lx, accept: %lx\n",listener,acceptor);
+ if(overlapped == NULL){
+ set_error(STATUS_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if(dest_len !=0){
+ FIXME("AcceptEx does not support reciving data yet\n");
+ dest_len = 0;
+ }
+
+ SERVER_START_REQ( accept_socket )
+ {
+ req->lhandle = SOCKET2HANDLE(listener);
+ req->ahandle = SOCKET2HANDLE(acceptor);
+ req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
+ req->attributes = OBJ_INHERIT;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ if (STATUS_SUCCESS == status)
+ {
+ buf = buf+dest_len;
+ WS2_acceptex_data( buf, local_addr_len, rem_addr_len, dest_len, acceptor );
+ *received = 0;
+ overlapped->Internal = status;
+ overlapped->InternalHigh = 0;
+ WS_AddCompletion( listener , (ULONG_PTR)overlapped, STATUS_SUCCESS, 0);
+ set_error(STATUS_PENDING);
+ return FALSE;
+ }
+
+ wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
+ iosb = HeapAlloc( GetProcessHeap(), 0, sizeof(*iosb) );
+ if(!wsa || !iosb){
+ set_error(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+
+ /*Setup the internal data structures!*/
+ overlapped->Internal = STATUS_PENDING;
+ overlapped->InternalHigh = 0;
+ /*Do we need the following? Maybe...*/
+ iosb = &wsa->local_iosb;
+ iosb->u.Status = STATUS_PENDING;
+ iosb->Information = 0;
+
+
+ wsa->hSocket = SOCKET2HANDLE(listener);
+ wsa->flags = 0;
+ wsa->user_overlapped = overlapped;
+ wsa->addrlen.acpt.s_accept = acceptor;
+ wsa->addrlen.acpt.buf = dest;
+ wsa->addrlen.acpt.data_len = dest_len;
+ wsa->addrlen.acpt.local_len = local_addr_len;
+ wsa->addrlen.acpt.remote_len = rem_addr_len;
+ wsa->addrlen.acpt.recvd = received;
+
+ SERVER_START_REQ( set_socket_listener )
+ {
+ req->handle = SOCKET2HANDLE(acceptor);
+ req->hListen = SOCKET2HANDLE(listener);
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ if(status != STATUS_SUCCESS){
+ FIXME("error setting socket listener\n");
+ }
+
+ SERVER_START_REQ( register_async_l )
+ {
+ req->handle = wsa->hSocket;
+ req->type = ASYNC_TYPE_READ;
+ req->locator = SOCKET2HANDLE(acceptor);
+ req->async.callback = WS2_async_accept;
+ req->async.iosb = iosb;
+ req->async.arg = wsa;
+ req->async.event = overlapped->hEvent;
+ req->async.cvalue = (ULONG_PTR)overlapped;
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ if(status != STATUS_PENDING){
+ HeapFree( GetProcessHeap(), 0, wsa );
+ HeapFree( GetProcessHeap(), 0, iosb );
+ set_error(status);
+ return FALSE;
+ }
+ set_error(STATUS_PENDING);
+ return FALSE;
+}
+
+/***********************************************************************
+ * GetAcceptExSockaddrs (WS2_32.@)
+ *
+ * Get infomation about an accepted socket.
+ *
+ * _buf [O] Destination for the first block of data from AcceptEx()
+ * data_size [I] length of data in bytes
+ * local_size [I] Bytes reserved for local addrinfo
+ * remote_size [I] Bytes reserved for remote addrinfo
+ * local_addr [O] Destination for local sockaddr
+ * local_addr_len [I] Size of local_addr
+ * remote_addr [O] Destination for remote sockaddr
+ * remote_addr_len [I] Size of rem_addr
+ *
+ * RETURNS
+ * Nothing.
+ */
+VOID WINAPI GetAcceptExSockaddrs( PVOID _buf, DWORD data_size, DWORD local_size, DWORD remote_size,
+ struct sockaddr ** local_addr, LPINT local_addr_len, struct sockaddr ** remote_addr, LPINT remote_addr_len)
+{
+ int len;
+ char *buf = _buf;
+
+ TRACE("buf=%p, data_size=%d, local_size=%d, remote_size=%d, local_addr=%p (%p), remote_addr=%p (%p)\n", buf, data_size, local_size, remote_size,
+ local_addr, local_addr_len, remote_addr, remote_addr_len );
+
+ buf += data_size;
+ if (local_size)
+ {
+ len = *(int*)buf;
+ *local_addr_len = len;
+ *local_addr = (struct sockaddr*)(buf+sizeof(int));
+ buf += local_size;
+ TRACE("local %d bytes to %p\n", len, local_addr);
+ }
+ else
+ *local_addr_len = 0;
+ if (remote_size)
+ {
+ len = *(int*)buf;
+ *remote_addr_len = len;
+ *remote_addr = (struct sockaddr*)(buf+sizeof(int));
+ TRACE("remote %d bytes to %p\n", len, remote_addr);
+ }
+ else
+ *remote_addr_len = 0;
+}
/***********************************************************************
* WS2_recv (INTERNAL)
diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec
index a77c215..2e20d38 100644 (file)
--- a/dlls/ws2_32/ws2_32.spec
+++ b/dlls/ws2_32/ws2_32.spec
@@ -119,3 +119,5 @@
@ stdcall getaddrinfo(str str ptr ptr) WS_getaddrinfo
@ stdcall getnameinfo(ptr long ptr long ptr long long) WS_getnameinfo
@ stdcall inet_ntop(long ptr ptr long) WS_inet_ntop
+@ stdcall AcceptEx(long long ptr long long long ptr ptr)
+@ stdcall GetAcceptExSockaddrs(ptr long long long ptr ptr ptr ptr)
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index c7566ea..9d3deef 100644 (file)
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -47,7 +47,7 @@ struct reply_header
struct request_max_size
{
- int pad[16];
+ int pad[20];
};
#define FIRST_USER_HANDLE 0x0020
@@ -1274,6 +1274,7 @@ struct accept_socket_request
{
struct request_header __header;
obj_handle_t lhandle;
+ obj_handle_t ahandle;
unsigned int access;
unsigned int attributes;
};
@@ -1301,6 +1302,18 @@ struct set_socket_event_reply
};
+struct set_socket_listener_request
+{
+ struct request_header __header;
+ obj_handle_t handle;
+ obj_handle_t hListen;
+ char __pad_20[4];
+};
+struct set_socket_listener_reply
+{
+ struct reply_header __header;
+};
+
struct get_socket_event_request
{
@@ -2849,6 +2862,21 @@ struct register_async_reply
{
struct reply_header __header;
};
+
+struct register_async_l_request
+{
+ struct request_header __header;
+ obj_handle_t handle;
+ int type;
+ int count;
+ obj_handle_t locator;
+ char __pad_28[4];
+ async_data_t async;
+};
+struct register_async_l_reply
+{
+ struct reply_header __header;
+};
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
@@ -4628,6 +4656,7 @@ enum request
REQ_create_socket,
REQ_accept_socket,
REQ_set_socket_event,
+ REQ_set_socket_listener,
REQ_get_socket_event,
REQ_enable_socket_event,
REQ_set_socket_deferred,
@@ -4718,6 +4747,7 @@ enum request
REQ_get_serial_info,
REQ_set_serial_info,
REQ_register_async,
+ REQ_register_async_l,
REQ_cancel_async,
REQ_ioctl,
REQ_get_ioctl_result,
@@ -4873,6 +4903,7 @@ union generic_request
struct create_socket_request create_socket_request;
struct accept_socket_request accept_socket_request;
struct set_socket_event_request set_socket_event_request;
+ struct set_socket_listener_request set_socket_listener_request;
struct get_socket_event_request get_socket_event_request;
struct enable_socket_event_request enable_socket_event_request;
struct set_socket_deferred_request set_socket_deferred_request;
@@ -4963,6 +4994,7 @@ union generic_request
struct get_serial_info_request get_serial_info_request;
struct set_serial_info_request set_serial_info_request;
struct register_async_request register_async_request;
+ struct register_async_l_request register_async_l_request;
struct cancel_async_request cancel_async_request;
struct ioctl_request ioctl_request;
struct get_ioctl_result_request get_ioctl_result_request;
@@ -5116,6 +5148,7 @@ union generic_reply
struct create_socket_reply create_socket_reply;
struct accept_socket_reply accept_socket_reply;
struct set_socket_event_reply set_socket_event_reply;
+ struct set_socket_listener_reply set_socket_listener_reply;
struct get_socket_event_reply get_socket_event_reply;
struct enable_socket_event_reply enable_socket_event_reply;
struct set_socket_deferred_reply set_socket_deferred_reply;
@@ -5206,6 +5239,7 @@ union generic_reply
struct get_serial_info_reply get_serial_info_reply;
struct set_serial_info_reply set_serial_info_reply;
struct register_async_reply register_async_reply;
+ struct register_async_l_reply register_async_l_reply;
struct cancel_async_reply cancel_async_reply;
struct ioctl_reply ioctl_reply;
struct get_ioctl_result_reply get_ioctl_result_reply;
diff --git a/server/async.c b/server/async.c
index 91f0c44..c30d740 100644 (file)
--- a/server/async.c
+++ b/server/async.c
@@ -45,6 +45,7 @@ struct async
struct completion *completion;
apc_param_t comp_key;
async_data_t data; /* data for async I/O call */
+ obj_handle_t locator; /* handle used to locate this async */
};
static void async_dump( struct object *obj, int verbose );
@@ -117,7 +118,6 @@ static void async_destroy( struct object *obj )
{
struct async *async = (struct async *)obj;
assert( obj->ops == &async_ops );
-
list_remove( &async->queue_entry );
async_reselect( async );
@@ -192,6 +192,7 @@ void free_async_queue( struct async_queue *queue )
release_object( queue );
}
+
/* create an async on a given queue of a fd */
struct async *create_async( struct thread *thread, struct async_queue *queue, const async_data_t *data )
{
@@ -214,6 +215,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
async->timeout = NULL;
async->queue = (struct async_queue *)grab_object( queue );
async->completion = NULL;
+ async->locator = 0;
if (queue->fd) async->completion = fd_get_completion( queue->fd, &async->comp_key );
list_add_tail( &queue->queue, &async->queue_entry );
@@ -224,6 +226,15 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
return async;
}
+/* create an async that you can locate later */
+struct async *create_async_l( struct thread *thread, struct async_queue *queue, const async_data_t *data, obj_handle_t l )
+{
+ struct async *out;
+ out = create_async(thread,queue,data);
+ out->locator = l;
+ return out;
+}
+
/* set the timeout of an async operation */
void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status )
{
@@ -279,26 +290,44 @@ void async_set_result( struct object *obj, unsigned int status, unsigned int tot
/* check if an async operation is waiting to be alerted */
int async_waiting( struct async_queue *queue )
{
- struct list *ptr;
+ struct list *ptr,*next;
struct async *async;
if (!queue) return 0;
if (!(ptr = list_head( &queue->queue ))) return 0;
- async = LIST_ENTRY( ptr, struct async, queue_entry );
- return async->status == STATUS_PENDING;
+ LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
+ {
+ async = LIST_ENTRY( ptr, struct async, queue_entry );
+ if(async->status == STATUS_PENDING)
+ { /*something is pending*/
+ return TRUE;
+ }
+ }
+ return FALSE; /*nothing is pending*/
}
-/* wake up async operations on the queue */
-void async_wake_up( struct async_queue *queue, unsigned int status )
+/* wakes up specific async operations on the queue */
+void async_wake_up_l( struct async_queue *queue, unsigned int status, obj_handle_t l )
{
struct list *ptr, *next;
-
if (!queue) return;
-
LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
{
struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
- async_terminate( async, status );
+ if( (async->locator == l || 0 == l) && /*step one. are we locating?*/
+ (((status == STATUS_ALERTED) && (async->status != STATUS_ALERTED)) || /*don't alert one thats already alerted*/
+ (status != STATUS_ALERTED)) ) /*if we aren't alerting, notify everything*/
+ {
+ async_terminate( async, status );
if (status == STATUS_ALERTED) break; /* only wake up the first one */
+ }
}
}
+
+/* wake up async operations on the queue */
+void async_wake_up( struct async_queue *queue, unsigned int status )
+{
+ async_wake_up_l(queue,status,0);
+}
+
+
diff --git a/server/fd.c b/server/fd.c
index a57001a..b94d5a8 100644 (file)
--- a/server/fd.c
+++ b/server/fd.c
@@ -1863,6 +1863,7 @@ void default_fd_cancel_async( struct fd *fd )
async_wake_up( fd->wait_q, STATUS_CANCELLED );
}
+
/* default flush() routine */
void no_flush( struct fd *fd, struct event **event )
{
@@ -2060,6 +2061,32 @@ DECL_HANDLER(register_async)
}
}
+/* create / reschedule an async I/O */
+DECL_HANDLER(register_async_l)
+{
+ unsigned int access;
+ struct fd *fd;
+
+ switch(req->type)
+ {
+ case ASYNC_TYPE_READ:
+ access = FILE_READ_DATA;
+ break;
+ case ASYNC_TYPE_WRITE:
+ access = FILE_WRITE_DATA;
+ break;
+ default:
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if ((fd = get_handle_fd_obj( current->process, req->handle, access )))
+ {
+ if (get_unix_fd( fd ) != -1) fd->fd_ops->queue_async_l( fd, &req->async, req->type, req->count, req->locator );
+ release_object( fd );
+ }
+}
+
/* cancels all async I/O */
DECL_HANDLER(cancel_async)
{
@@ -2072,6 +2099,7 @@ DECL_HANDLER(cancel_async)
}
}
+
/* attach completion object to a fd */
DECL_HANDLER(set_completion_info)
{
diff --git a/server/file.h b/server/file.h
index aef40f7..74b2548 100644 (file)
--- a/server/file.h
+++ b/server/file.h
@@ -47,6 +47,9 @@ struct fd_ops
void (*reselect_async)( struct fd *, struct async_queue *queue );
/* cancel an async operation */
void (*cancel_async)(struct fd *);
+ /* queue a locatable async operation */
+ void (*queue_async_l)(struct fd *, const async_data_t *data, int type, int count, obj_handle_t locator);
+
};
/* file descriptor functions */
@@ -138,12 +141,15 @@ extern struct async_queue *create_async_queue( struct fd *fd );
extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct thread *thread, struct async_queue *queue,
const async_data_t *data );
+extern struct async *create_async_l( struct thread *thread, struct async_queue *queue,
+ const async_data_t *data, obj_handle_t l );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
extern void async_set_result( struct object *obj, unsigned int status,
unsigned int total, client_ptr_t apc );
extern int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status );
extern void async_wake_up( struct async_queue *queue, unsigned int status );
+extern void async_wake_up_l( struct async_queue *queue, unsigned int status, obj_handle_t l );
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
extern void fd_copy_completion( struct fd *src, struct fd *dst );
diff --git a/server/protocol.def b/server/protocol.def
index e871736..1bbe89e 100644 (file)
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -63,7 +63,7 @@ struct reply_header
/* this is used to construct the generic_request union */
struct request_max_size
{
- int pad[16]; /* the max request size is 16 ints */
+ int pad[20]; /* the max request size is 16 ints */
};
#define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */
@@ -1041,6 +1041,7 @@ enum server_fd_type
/* Accept a socket */
@REQ(accept_socket)
obj_handle_t lhandle; /* handle to the listening socket */
+ obj_handle_t ahandle; /* handle to the accepting socket */
unsigned int access; /* wanted access rights */
unsigned int attributes; /* object attributes */
@REPLY
@@ -1057,6 +1058,11 @@ enum server_fd_type
unsigned int msg; /* message to send */
@END
+/* Set socket listener */
+@REQ(set_socket_listener)
+ obj_handle_t handle; /* handle to the socket */
+ obj_handle_t hListen; /* handle to the socket listening for connections */
+@END
/* Get socket event parameters */
@REQ(get_socket_event)
@@ -2064,6 +2070,14 @@ enum message_type
async_data_t async; /* async I/O parameters */
int count; /* count - usually # of bytes to be read/written */
@END
+/* Create a locatable async I/O */
+@REQ(register_async_l)
+ obj_handle_t handle; /* handle to comm port, socket or file */
+ int type; /* type of queue to look after */
+ int count; /* count - usually # of bytes to be read/written */
+ obj_handle_t locator; /* used to locate a specific async request later */
+ async_data_t async; /* async I/O parameters */
+@END
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
diff --git a/server/request.h b/server/request.h
index 4fc3bd6..8e6fe07 100644 (file)
--- a/server/request.h
+++ b/server/request.h
@@ -155,6 +155,7 @@ DECL_HANDLER(unlock_file);
DECL_HANDLER(create_socket);
DECL_HANDLER(accept_socket);
DECL_HANDLER(set_socket_event);
+DECL_HANDLER(set_socket_listener);
DECL_HANDLER(get_socket_event);
DECL_HANDLER(enable_socket_event);
DECL_HANDLER(set_socket_deferred);
@@ -245,6 +246,7 @@ DECL_HANDLER(is_window_hung);
DECL_HANDLER(get_serial_info);
DECL_HANDLER(set_serial_info);
DECL_HANDLER(register_async);
+DECL_HANDLER(register_async_l);
DECL_HANDLER(cancel_async);
DECL_HANDLER(ioctl);
DECL_HANDLER(get_ioctl_result);
@@ -399,6 +401,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_create_socket,
(req_handler)req_accept_socket,
(req_handler)req_set_socket_event,
+ (req_handler)req_set_socket_listener,
(req_handler)req_get_socket_event,
(req_handler)req_enable_socket_event,
(req_handler)req_set_socket_deferred,
@@ -489,6 +492,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_serial_info,
(req_handler)req_set_serial_info,
(req_handler)req_register_async,
+ (req_handler)req_register_async_l,
(req_handler)req_cancel_async,
(req_handler)req_ioctl,
(req_handler)req_get_ioctl_result,
@@ -876,8 +880,9 @@ C_ASSERT( FIELD_OFFSET(struct create_socket_request, flags) == 32 );
C_ASSERT( FIELD_OFFSET(struct create_socket_reply, handle) == 8 );
C_ASSERT( sizeof(struct create_socket_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct accept_socket_request, lhandle) == 12 );
-C_ASSERT( FIELD_OFFSET(struct accept_socket_request, access) == 16 );
-C_ASSERT( FIELD_OFFSET(struct accept_socket_request, attributes) == 20 );
+C_ASSERT( FIELD_OFFSET(struct accept_socket_request, ahandle) == 16 );
+C_ASSERT( FIELD_OFFSET(struct accept_socket_request, access) == 20 );
+C_ASSERT( FIELD_OFFSET(struct accept_socket_request, attributes) == 24 );
C_ASSERT( FIELD_OFFSET(struct accept_socket_reply, handle) == 8 );
C_ASSERT( sizeof(struct accept_socket_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, handle) == 12 );
@@ -886,6 +891,9 @@ C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, event) == 20 );
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, window) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, msg) == 28 );
C_ASSERT( sizeof(struct set_socket_event_request) == 32 );
+C_ASSERT( FIELD_OFFSET(struct set_socket_listener_request, handle) == 12 );
+C_ASSERT( FIELD_OFFSET(struct set_socket_listener_request, hListen) == 16 );
+C_ASSERT( sizeof(struct set_socket_listener_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_socket_event_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_socket_event_request, service) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_socket_event_request, c_event) == 20 );
@@ -1350,6 +1358,12 @@ C_ASSERT( FIELD_OFFSET(struct register_async_request, type) == 12 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 );
C_ASSERT( sizeof(struct register_async_request) == 64 );
+C_ASSERT( FIELD_OFFSET(struct register_async_l_request, handle) == 12 );
+C_ASSERT( FIELD_OFFSET(struct register_async_l_request, type) == 16 );
+C_ASSERT( FIELD_OFFSET(struct register_async_l_request, count) == 20 );
+C_ASSERT( FIELD_OFFSET(struct register_async_l_request, locator) == 24 );
+C_ASSERT( FIELD_OFFSET(struct register_async_l_request, async) == 32 );
+C_ASSERT( sizeof(struct register_async_l_request) == 72 );
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, handle) == 12 );
C_ASSERT( sizeof(struct cancel_async_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct ioctl_request, code) == 12 );
diff --git a/server/sock.c b/server/sock.c
index baaa9df..96ef50a 100644 (file)
--- a/server/sock.c
+++ b/server/sock.c
@@ -85,6 +85,8 @@ struct sock
struct sock *deferred; /* socket that waits for a deferred accept */
struct async_queue *read_q; /* queue for asynchronous reads */
struct async_queue *write_q; /* queue for asynchronous writes */
+ obj_handle_t hListen; /* socket listening for connections for this one */
+ int incCon; /* number of incomming connect attempts will will try to wake for */
};
static void sock_dump( struct object *obj, int verbose );
@@ -96,8 +98,12 @@ static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event );
static enum server_fd_type sock_get_fd_type( struct fd *fd );
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
+static void sock_queue_async_l( struct fd *fd, const async_data_t *data, int type, int count, obj_handle_t locator );
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
static void sock_cancel_async( struct fd *fd );
+static int sock_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
+static void sock_async_close_l( struct sock *sock, obj_handle_t locator );
+
static int sock_get_error( int err );
static void sock_set_error(void);
@@ -118,7 +124,7 @@ static const struct object_ops sock_ops =
default_set_sd, /* set_sd */
no_lookup_name, /* lookup_name */
no_open_file, /* open_file */
- fd_close_handle, /* close_handle */
+ sock_close_handle, /* close_handle */
sock_destroy /* destroy */
};
@@ -131,7 +137,8 @@ static const struct fd_ops sock_fd_ops =
default_fd_ioctl, /* ioctl */
sock_queue_async, /* queue_async */
sock_reselect_async, /* reselect_async */
- sock_cancel_async /* cancel_async */
+ sock_cancel_async, /* cancel_async */
+ sock_queue_async_l /* quque_async_l */
};
@@ -247,11 +254,15 @@ static void sock_wake_up( struct sock *sock, int pollev )
unsigned int events = sock->pmask & sock->mask;
int i;
int async_active = 0;
-
+
+ /*fprintf(stderr,"sock: %p. pollev & (POLLIN|POLLPRI):%d. async_waiting( sock->read_q ):%d,sock->read_q:%p\n",sock,pollev & (POLLIN|POLLPRI),async_waiting( sock->read_q ),sock->read_q);*/
+ /* fflush(NULL);*/
if ( pollev & (POLLIN|POLLPRI) && async_waiting( sock->read_q ))
{
+ /* fprintf(stderr,"waking_read_queue pending:%d\n",sock->incCon);*/
+ /* fflush(NULL);*/
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
- async_wake_up( sock->read_q, STATUS_ALERTED );
+ async_wake_up( sock->read_q, STATUS_ALERTED );
async_active = 1;
}
if ( pollev & POLLOUT && async_waiting( sock->write_q ))
@@ -332,10 +343,14 @@ static void sock_poll_event( struct fd *fd, int event )
/* listening */
if (event & POLLIN)
{
- /* incoming connection */
+
+ /* incoming connection */
+ sock->incCon += 1;
sock->pmask |= FD_ACCEPT;
sock->errors[FD_ACCEPT_BIT] = 0;
sock->hmask |= FD_ACCEPT;
+ /* fprintf(stderr,"sock: %p. incomming connection. pending: %d\n",sock,sock->incCon);*/
+ /* fflush(NULL);*/
}
else if (event & (POLLERR|POLLHUP))
{
@@ -435,10 +450,17 @@ static void sock_poll_event( struct fd *fd, int event )
}
else
sock_reselect( sock );
-
+
/* wake up anyone waiting for whatever just happened */
- if ( sock->pmask & sock->mask || sock->flags & WSA_FLAG_OVERLAPPED ) sock_wake_up( sock, event );
-
+ if ( sock->pmask & sock->mask || sock->flags & WSA_FLAG_OVERLAPPED )
+ {
+/* fprintf(stderr,"sock: %p. pending: %d. 1st: %d. 2nd: %d.\n",sock,sock->incCon, sock->pmask & sock->mask, sock->flags & WSA_FLAG_OVERLAPPED);*/
+/* fflush(NULL);*/
+ sock_wake_up( sock, event );
+ } else{
+/* fprintf(stderr,"sock: %p. pending: %d. 1st: %d. 2nd: %d.\n",sock,sock->incCon, sock->pmask & sock->mask, sock->flags & WSA_FLAG_OVERLAPPED);*/
+/* fflush(NULL);*/
+ }
/* if anyone is stupid enough to wait on the socket object itself,
* maybe we should wake them up too, just in case? */
wake_up( &sock->obj, 0 );
@@ -466,7 +488,7 @@ static int sock_get_poll_events( struct fd *fd )
struct sock *sock = get_fd_user( fd );
unsigned int mask = sock->mask & sock->state & ~sock->hmask;
int ev = 0;
-
+
assert( sock->obj.ops == &sock_ops );
if (sock->state & FD_CONNECT)
@@ -490,7 +512,7 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd )
return FD_TYPE_SOCKET;
}
-static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
+static void sock_queue_async_l( struct fd *fd, const async_data_t *data, int type, int count, obj_handle_t locator )
{
struct sock *sock = get_fd_user( fd );
struct async_queue *queue;
@@ -514,7 +536,7 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
return;
}
- if ( ( !( sock->state & FD_READ ) && type == ASYNC_TYPE_READ ) ||
+ if ( ( !( sock->state & (FD_READ|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ ) ||
( !( sock->state & FD_WRITE ) && type == ASYNC_TYPE_WRITE ) )
{
set_error( STATUS_PIPE_DISCONNECTED );
@@ -522,7 +544,7 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
else
{
struct async *async;
- if (!(async = create_async( current, queue, data ))) return;
+ if (!(async = create_async_l( current, queue, data, locator ))) return;
release_object( async );
set_error( STATUS_PENDING );
}
@@ -530,6 +552,10 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
pollev = sock_reselect( sock );
if ( pollev ) sock_try_event( sock, pollev );
}
+static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count)
+{
+ sock_queue_async_l(fd,data,type,count,0);
+}
static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
{
@@ -542,11 +568,38 @@ static void sock_cancel_async( struct fd *fd )
{
struct sock *sock = get_fd_user( fd );
assert( sock->obj.ops == &sock_ops );
-
async_wake_up( sock->read_q, STATUS_CANCELLED );
async_wake_up( sock->write_q, STATUS_CANCELLED );
}
+static int sock_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
+{
+ struct sock *sock = (struct sock*) obj;
+ struct sock *l = NULL;
+ assert( sock->obj.ops == &sock_ops );
+ async_wake_up( sock->read_q, STATUS_HANDLES_CLOSED );
+ async_wake_up( sock->write_q, STATUS_HANDLES_CLOSED );
+ if(current && sock){ /*avoid fatal error when updating wine config files*/
+ l = (struct sock *)get_handle_obj( process, sock->hListen, FILE_WRITE_ATTRIBUTES, &sock_ops );
+ if(l)
+ {
+ sock_async_close_l( l, handle );
+ release_object( l );
+ }else{
+ clear_error();
+ }
+ }
+
+ return fd_close_handle(obj,process,handle);
+}
+
+/*Closes all async operations on a socket with the corresponding locator */
+static void sock_async_close_l( struct sock *sock, obj_handle_t locator )
+{
+ async_wake_up_l( sock->read_q, STATUS_HANDLES_CLOSED, locator );
+ async_wake_up_l( sock->write_q, STATUS_HANDLES_CLOSED, locator );
+}
+
static struct fd *sock_get_fd( struct object *obj )
{
struct sock *sock = (struct sock *)obj;
@@ -609,6 +662,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
sock->deferred = NULL;
sock->read_q = NULL;
sock->write_q = NULL;
+ sock->incCon = 0;
if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj,
(flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT )))
{
@@ -621,16 +675,17 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
}
/* accept a socket (creates a new fd) */
-static struct sock *accept_socket( obj_handle_t handle )
+static struct sock *accept_socket( obj_handle_t handle, obj_handle_t ahandle )
{
- struct sock *acceptsock;
+ struct sock *acceptsock = NULL;
struct sock *sock;
int acceptfd;
struct sockaddr saddr;
-
+
sock = (struct sock *)get_handle_obj( current->process, handle, FILE_READ_DATA, &sock_ops );
- if (!sock)
+ if (!sock){
return NULL;
+ }
if ( sock->deferred )
{
@@ -650,46 +705,62 @@ static struct sock *accept_socket( obj_handle_t handle )
{
sock_set_error();
release_object( sock );
- return NULL;
+ return NULL;
}
- if (!(acceptsock = alloc_object( &sock_ops )))
- {
- close( acceptfd );
- release_object( sock );
- return NULL;
- }
-
- /* newly created socket gets the same properties of the listening socket */
- fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
- acceptsock->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->polling = 0;
- acceptsock->type = sock->type;
- acceptsock->family = sock->family;
- acceptsock->event = NULL;
- acceptsock->window = sock->window;
- acceptsock->message = sock->message;
- acceptsock->wparam = 0;
- if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
- acceptsock->flags = sock->flags;
- acceptsock->deferred = NULL;
- acceptsock->read_q = NULL;
- acceptsock->write_q = NULL;
- if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
+
+ if(ahandle){
+ acceptsock = (struct sock *)get_handle_obj(current->process, ahandle, FILE_READ_DATA | FILE_WRITE_DATA, &sock_ops );
+ if(acceptsock){
+ if(acceptsock->event)
+ release_object( acceptsock->event );
+ release_object( acceptsock->fd );
+ }
+ }else{
+ acceptsock = alloc_object( &sock_ops );
+ }
+ if (!acceptsock)
+ {
+ close( acceptfd );
+ release_object( sock );
+ return NULL;
+ }
+
+
+ fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
+ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+ acceptsock->hmask = 0;
+ acceptsock->pmask = 0;
+ acceptsock->polling = 0;
+ acceptsock->event = NULL;
+ acceptsock->deferred = NULL;
+ acceptsock->read_q = NULL;
+ acceptsock->write_q = NULL;
+ acceptsock->wparam = 0;
+ acceptsock->incCon = 0;
+ /* newly created socket gets the same properties of the listening socket */
+ if (sock->state & FD_WINE_NONBLOCKING)
+ acceptsock->state |= FD_WINE_NONBLOCKING;
+ acceptsock->mask = sock->mask;
+ acceptsock->type = sock->type;
+ acceptsock->family = sock->family;
+ acceptsock->window = sock->window;
+ acceptsock->message = sock->message;
+ if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
+ acceptsock->flags = sock->flags;
+ if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
get_fd_options( sock->fd ) )))
- {
- release_object( acceptsock );
- release_object( sock );
- return NULL;
- }
+ {
+ release_object( acceptsock );
+ release_object( sock );
+ return NULL;
+ }
}
clear_error();
- sock->pmask &= ~FD_ACCEPT;
- sock->hmask &= ~FD_ACCEPT;
+ sock->pmask &= ~FD_ACCEPT;
+ sock->hmask &= ~FD_ACCEPT;
+ sock->incCon -= 1;
+ //fprintf(stderr,"accept: pending: %d\n",sock->incCon);
+ //fflush(NULL);
sock_reselect( sock );
release_object( sock );
return acceptsock;
@@ -787,13 +858,35 @@ DECL_HANDLER(accept_socket)
struct sock *sock;
reply->handle = 0;
- if ((sock = accept_socket( req->lhandle )) != NULL)
+ if ((sock = accept_socket( req->lhandle, req->ahandle )) != NULL)
{
- reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->attributes );
- sock->wparam = reply->handle; /* wparam for message is the socket handle */
- sock_reselect( sock );
- release_object( &sock->obj );
+ if (req->ahandle)
+ reply->handle = req->ahandle;
+ else
+ {
+ reply->handle = alloc_handle( current->process, &sock->obj, req->access, req->attributes );
+ sock->wparam = reply->handle; /* wparam for message is the socket handle */
+ sock_reselect( sock );
+ }
+ release_object( &sock->obj );//I think this needs togo in the else. But i want to check.
+ //We can't release the object unless we allocate a handle for it.
+ //Do we need to se the wparam? What is this? No... maybe... i dont know.
+ }
+}
+
+/* Sets which socket is listening for connections for this socket */
+DECL_HANDLER(set_socket_listener)
+{
+ struct sock *sock;
+ sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES, &sock_ops );
+ if(!sock){
+ set_error( STATUS_INVALID_HANDLE );
+ return;
}
+ sock->hListen = req->hListen;
+ release_object( &sock->obj );
+ set_error( STATUS_SUCCESS );
+ return;
}
/* set socket event parameters */
diff --git a/server/trace.c b/server/trace.c
index d24f653..fa23e00 100644 (file)
--- a/server/trace.c
+++ b/server/trace.c
@@ -1553,6 +1553,7 @@ static void dump_create_socket_reply( const struct create_socket_reply *req )
static void dump_accept_socket_request( const struct accept_socket_request *req )
{
fprintf( stderr, " lhandle=%04x", req->lhandle );
+ fprintf( stderr, ", ahandle=%04x", req->ahandle );
fprintf( stderr, ", access=%08x", req->access );
fprintf( stderr, ", attributes=%08x", req->attributes );
}
@@ -1571,6 +1572,12 @@ static void dump_set_socket_event_request( const struct set_socket_event_request
fprintf( stderr, ", msg=%08x", req->msg );
}
+static void dump_set_socket_listener_request( const struct set_socket_listener_request *req )
+{
+ fprintf( stderr, " handle=%04x", req->handle );
+ fprintf( stderr, ", hListen=%04x", req->hListen );
+}
+
static void dump_get_socket_event_request( const struct get_socket_event_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
@@ -2565,6 +2572,15 @@ static void dump_register_async_request( const struct register_async_request *re
fprintf( stderr, ", count=%d", req->count );
}
+static void dump_register_async_l_request( const struct register_async_l_request *req )
+{
+ fprintf( stderr, " handle=%04x", req->handle );
+ fprintf( stderr, ", type=%d", req->type );
+ fprintf( stderr, ", count=%d", req->count );
+ fprintf( stderr, ", locator=%04x", req->locator );
+ dump_async_data( ", async=", &req->async );
+}
+
static void dump_cancel_async_request( const struct cancel_async_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
@@ -3857,6 +3873,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_socket_request,
(dump_func)dump_accept_socket_request,
(dump_func)dump_set_socket_event_request,
+ (dump_func)dump_set_socket_listener_request,
(dump_func)dump_get_socket_event_request,
(dump_func)dump_enable_socket_event_request,
(dump_func)dump_set_socket_deferred_request,
@@ -3947,6 +3964,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_serial_info_request,
(dump_func)dump_set_serial_info_request,
(dump_func)dump_register_async_request,
+ (dump_func)dump_register_async_l_request,
(dump_func)dump_cancel_async_request,
(dump_func)dump_ioctl_request,
(dump_func)dump_get_ioctl_result_request,
@@ -4098,6 +4116,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_socket_reply,
(dump_func)dump_accept_socket_reply,
NULL,
+ NULL,
(dump_func)dump_get_socket_event_reply,
NULL,
NULL,
@@ -4189,6 +4208,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
NULL,
NULL,
+ NULL,
(dump_func)dump_ioctl_reply,
(dump_func)dump_get_ioctl_result_reply,
(dump_func)dump_create_named_pipe_reply,
@@ -4339,6 +4359,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_socket",
"accept_socket",
"set_socket_event",
+ "set_socket_listener",
"get_socket_event",
"enable_socket_event",
"set_socket_deferred",
@@ -4429,6 +4450,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_serial_info",
"set_serial_info",
"register_async",
+ "register_async_l",
"cancel_async",
"ioctl",
"get_ioctl_result",
diff --git a/tools/make_requests b/tools/make_requests
index e7a1ffb..d3a517b 100755 (executable)
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -59,7 +59,7 @@ my @asserts = ();
my @trace_lines = ();
-my $max_req_size = 64;
+my $max_req_size = 80;
my $warnings = scalar(@ARGV) && $ARGV[0] eq "-w";