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";