1174 lines
46 KiB
Diff
1174 lines
46 KiB
Diff
|
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";
|