Commit f670a162 authored by Alexandre Julliard's avatar Alexandre Julliard

server: Return WSA error codes in socket events.

parent f4b07ee8
...@@ -1038,41 +1038,74 @@ static UINT wsaHerrno(int loc_errno) ...@@ -1038,41 +1038,74 @@ static UINT wsaHerrno(int loc_errno)
} }
} }
static inline DWORD NtStatusToWSAError( const DWORD status ) static NTSTATUS sock_error_to_ntstatus( DWORD err )
{
switch (err)
{
case 0: return STATUS_SUCCESS;
case WSAEBADF: return STATUS_INVALID_HANDLE;
case WSAEACCES: return STATUS_ACCESS_DENIED;
case WSAEFAULT: return STATUS_NO_MEMORY;
case WSAEINVAL: return STATUS_INVALID_PARAMETER;
case WSAEMFILE: return STATUS_TOO_MANY_OPENED_FILES;
case WSAEWOULDBLOCK: return STATUS_CANT_WAIT;
case WSAEINPROGRESS: return STATUS_PENDING;
case WSAEALREADY: return STATUS_NETWORK_BUSY;
case WSAENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
case WSAEDESTADDRREQ: return STATUS_INVALID_PARAMETER;
case WSAEMSGSIZE: return STATUS_BUFFER_OVERFLOW;
case WSAEPROTONOSUPPORT:
case WSAESOCKTNOSUPPORT:
case WSAEPFNOSUPPORT:
case WSAEAFNOSUPPORT:
case WSAEPROTOTYPE: return STATUS_NOT_SUPPORTED;
case WSAENOPROTOOPT: return STATUS_INVALID_PARAMETER;
case WSAEOPNOTSUPP: return STATUS_NOT_SUPPORTED;
case WSAEADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
case WSAEADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
case WSAECONNREFUSED: return STATUS_CONNECTION_REFUSED;
case WSAESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
case WSAENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
case WSAETIMEDOUT: return STATUS_IO_TIMEOUT;
case WSAENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
case WSAENETDOWN: return STATUS_NETWORK_BUSY;
case WSAECONNRESET: return STATUS_CONNECTION_RESET;
case WSAECONNABORTED: return STATUS_CONNECTION_ABORTED;
default:
FIXME("unmapped error %u\n", err);
return STATUS_UNSUCCESSFUL;
}
}
static DWORD NtStatusToWSAError( DWORD status )
{ {
/* We only need to cover the status codes set by server async request handling */
DWORD wserr;
switch ( status ) switch ( status )
{ {
case STATUS_SUCCESS: wserr = 0; break; case STATUS_SUCCESS: return 0;
case STATUS_PENDING: wserr = WSA_IO_PENDING; break; case STATUS_PENDING: return WSA_IO_PENDING;
case STATUS_OBJECT_TYPE_MISMATCH: wserr = WSAENOTSOCK; break; case STATUS_OBJECT_TYPE_MISMATCH: return WSAENOTSOCK;
case STATUS_INVALID_HANDLE: wserr = WSAEBADF; break; case STATUS_INVALID_HANDLE: return WSAEBADF;
case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break; case STATUS_INVALID_PARAMETER: return WSAEINVAL;
case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break; case STATUS_PIPE_DISCONNECTED: return WSAESHUTDOWN;
case STATUS_NETWORK_BUSY: wserr = WSAEALREADY; break; case STATUS_NETWORK_BUSY: return WSAEALREADY;
case STATUS_NETWORK_UNREACHABLE: wserr = WSAENETUNREACH; break; case STATUS_NETWORK_UNREACHABLE: return WSAENETUNREACH;
case STATUS_CONNECTION_REFUSED: wserr = WSAECONNREFUSED; break; case STATUS_CONNECTION_REFUSED: return WSAECONNREFUSED;
case STATUS_CONNECTION_DISCONNECTED: wserr = WSAENOTCONN; break; case STATUS_CONNECTION_DISCONNECTED: return WSAENOTCONN;
case STATUS_CONNECTION_RESET: wserr = WSAECONNRESET; break; case STATUS_CONNECTION_RESET: return WSAECONNRESET;
case STATUS_CONNECTION_ABORTED: wserr = WSAECONNABORTED; break; case STATUS_CONNECTION_ABORTED: return WSAECONNABORTED;
case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break; case STATUS_CANCELLED: return WSA_OPERATION_ABORTED;
case STATUS_ADDRESS_ALREADY_ASSOCIATED: wserr = WSAEADDRINUSE; break; case STATUS_ADDRESS_ALREADY_ASSOCIATED: return WSAEADDRINUSE;
case STATUS_IO_TIMEOUT: case STATUS_IO_TIMEOUT:
case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break; case STATUS_TIMEOUT: return WSAETIMEDOUT;
case STATUS_NO_MEMORY: wserr = WSAEFAULT; break; case STATUS_NO_MEMORY: return WSAEFAULT;
case STATUS_ACCESS_DENIED: wserr = WSAEACCES; break; case STATUS_ACCESS_DENIED: return WSAEACCES;
case STATUS_TOO_MANY_OPENED_FILES: wserr = WSAEMFILE; break; case STATUS_TOO_MANY_OPENED_FILES: return WSAEMFILE;
case STATUS_CANT_WAIT: wserr = WSAEWOULDBLOCK; break; case STATUS_CANT_WAIT: return WSAEWOULDBLOCK;
case STATUS_BUFFER_OVERFLOW: wserr = WSAEMSGSIZE; break; case STATUS_BUFFER_OVERFLOW: return WSAEMSGSIZE;
case STATUS_NOT_SUPPORTED: wserr = WSAEOPNOTSUPP; break; case STATUS_NOT_SUPPORTED: return WSAEOPNOTSUPP;
case STATUS_HOST_UNREACHABLE: wserr = WSAEHOSTUNREACH; break; case STATUS_HOST_UNREACHABLE: return WSAEHOSTUNREACH;
default: return RtlNtStatusToDosError( status );
default:
wserr = RtlNtStatusToDosError( status );
FIXME( "Status code %08x converted to DOS error code %x\n", status, wserr );
} }
return wserr;
} }
/* set last error code from NT status without mapping WSA errors */ /* set last error code from NT status without mapping WSA errors */
...@@ -1164,7 +1197,7 @@ static void _get_sock_errors(SOCKET s, int *events) ...@@ -1164,7 +1197,7 @@ static void _get_sock_errors(SOCKET s, int *events)
SERVER_END_REQ; SERVER_END_REQ;
} }
static int _get_sock_error(SOCKET s, unsigned int bit) static int get_sock_error(SOCKET s, unsigned int bit)
{ {
int events[FD_MAX_EVENTS]; int events[FD_MAX_EVENTS];
_get_sock_errors(s, events); _get_sock_errors(s, events);
...@@ -3460,13 +3493,8 @@ int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen) ...@@ -3460,13 +3493,8 @@ int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
do_block(fd, POLLIN | POLLOUT, -1); do_block(fd, POLLIN | POLLOUT, -1);
_sync_sock_state(s); /* let wineserver notice connection */ _sync_sock_state(s); /* let wineserver notice connection */
/* retrieve any error codes from it */ /* retrieve any error codes from it */
result = _get_sock_error(s, FD_CONNECT_BIT); if (!(result = get_sock_error(s, FD_CONNECT_BIT))) goto connect_success;
if (result) SetLastError(result);
SetLastError(NtStatusToWSAError(result));
else
{
goto connect_success;
}
} }
else else
{ {
...@@ -3589,7 +3617,7 @@ static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int n ...@@ -3589,7 +3617,7 @@ static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int n
/* If the connect already failed */ /* If the connect already failed */
if (status == STATUS_PIPE_DISCONNECTED) if (status == STATUS_PIPE_DISCONNECTED)
{ {
ov->Internal = _get_sock_error(s, FD_CONNECT_BIT); ov->Internal = sock_error_to_ntstatus( get_sock_error( s, FD_CONNECT_BIT ));
ov->InternalHigh = 0; ov->InternalHigh = 0;
if (cvalue) WS_AddCompletion( s, cvalue, ov->Internal, ov->InternalHigh, FALSE ); if (cvalue) WS_AddCompletion( s, cvalue, ov->Internal, ov->InternalHigh, FALSE );
if (ov->hEvent) NtSetEvent( ov->hEvent, NULL ); if (ov->hEvent) NtSetEvent( ov->hEvent, NULL );
...@@ -3983,7 +4011,6 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, ...@@ -3983,7 +4011,6 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
{ {
if(events[i]) if(events[i])
{ {
events[i] = NtStatusToWSAError(events[i]);
TRACE("returning SO_ERROR %d from wine server\n", events[i]); TRACE("returning SO_ERROR %d from wine server\n", events[i]);
*(int*) optval = events[i]; *(int*) optval = events[i];
break; break;
...@@ -5079,10 +5106,10 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID ...@@ -5079,10 +5106,10 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
else if (overlapped) else if (overlapped)
{ {
ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0; ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0;
overlapped->Internal = status; overlapped->Internal = sock_error_to_ntstatus( status );
overlapped->InternalHigh = total; overlapped->InternalHigh = total;
if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, overlapped->Internal, total, FALSE );
if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL ); if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL );
if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, status, total, FALSE );
} }
if (!status) if (!status)
...@@ -7333,7 +7360,7 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp ...@@ -7333,7 +7360,7 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp
for (i = 0; i < FD_MAX_EVENTS; i++) for (i = 0; i < FD_MAX_EVENTS; i++)
{ {
if (lpEvent->lNetworkEvents & (1 << i)) if (lpEvent->lNetworkEvents & (1 << i))
lpEvent->iErrorCode[i] = NtStatusToWSAError(errors[i]); lpEvent->iErrorCode[i] = errors[i];
} }
return 0; return 0;
} }
......
...@@ -109,7 +109,7 @@ struct sock ...@@ -109,7 +109,7 @@ struct sock
user_handle_t window; /* window to send the message to */ user_handle_t window; /* window to send the message to */
unsigned int message; /* message to send */ unsigned int message; /* message to send */
obj_handle_t wparam; /* message wparam (socket handle) */ obj_handle_t wparam; /* message wparam (socket handle) */
int errors[FD_MAX_EVENTS]; /* event errors */ unsigned int errors[FD_MAX_EVENTS]; /* event errors */
timeout_t connect_time;/* time the socket was connected */ timeout_t connect_time;/* time the socket was connected */
struct sock *deferred; /* socket that waits for a deferred accept */ struct sock *deferred; /* socket that waits for a deferred accept */
struct async_queue read_q; /* queue for asynchronous reads */ struct async_queue read_q; /* queue for asynchronous reads */
...@@ -134,7 +134,7 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int ...@@ -134,7 +134,7 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int
static void sock_reselect_async( struct fd *fd, struct async_queue *queue ); static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
static int sock_get_ntstatus( int err ); static int sock_get_ntstatus( int err );
static int sock_get_error( int err ); static unsigned int sock_get_error( int err );
static void sock_set_error(void); static void sock_set_error(void);
static const struct object_ops sock_ops = static const struct object_ops sock_ops =
...@@ -292,7 +292,7 @@ static void sock_wake_up( struct sock *sock ) ...@@ -292,7 +292,7 @@ static void sock_wake_up( struct sock *sock )
int event = event_bitorder[i]; int event = event_bitorder[i];
if (sock->pmask & (1 << event)) if (sock->pmask & (1 << event))
{ {
lparam_t lparam = (1 << event) | (sock_get_error(sock->errors[event]) << 16); lparam_t lparam = (1 << event) | (sock->errors[event] << 16);
post_message( sock->window, sock->message, sock->wparam, lparam ); post_message( sock->window, sock->message, sock->wparam, lparam );
} }
} }
...@@ -345,14 +345,14 @@ static void sock_dispatch_events( struct sock *sock, int prevstate, int event, i ...@@ -345,14 +345,14 @@ static void sock_dispatch_events( struct sock *sock, int prevstate, int event, i
{ {
sock->pmask |= FD_CONNECT; sock->pmask |= FD_CONNECT;
sock->hmask |= FD_CONNECT; sock->hmask |= FD_CONNECT;
sock->errors[FD_CONNECT_BIT] = error; sock->errors[FD_CONNECT_BIT] = sock_get_error( error );
goto end; goto end;
} }
if (prevstate & FD_WINE_LISTENING) if (prevstate & FD_WINE_LISTENING)
{ {
sock->pmask |= FD_ACCEPT; sock->pmask |= FD_ACCEPT;
sock->hmask |= FD_ACCEPT; sock->hmask |= FD_ACCEPT;
sock->errors[FD_ACCEPT_BIT] = error; sock->errors[FD_ACCEPT_BIT] = sock_get_error( error );
goto end; goto end;
} }
...@@ -381,7 +381,7 @@ static void sock_dispatch_events( struct sock *sock, int prevstate, int event, i ...@@ -381,7 +381,7 @@ static void sock_dispatch_events( struct sock *sock, int prevstate, int event, i
{ {
sock->pmask |= FD_CLOSE; sock->pmask |= FD_CLOSE;
sock->hmask |= FD_CLOSE; sock->hmask |= FD_CLOSE;
sock->errors[FD_CLOSE_BIT] = error; sock->errors[FD_CLOSE_BIT] = sock_get_error( error );
} }
end: end:
sock_wake_up( sock ); sock_wake_up( sock );
...@@ -823,7 +823,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock ) ...@@ -823,7 +823,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
} }
/* return an errno value mapped to a WSA error */ /* return an errno value mapped to a WSA error */
static int sock_get_error( int err ) static unsigned int sock_get_error( int err )
{ {
switch (err) switch (err)
{ {
...@@ -1265,24 +1265,13 @@ DECL_HANDLER(set_socket_event) ...@@ -1265,24 +1265,13 @@ DECL_HANDLER(set_socket_event)
DECL_HANDLER(get_socket_event) DECL_HANDLER(get_socket_event)
{ {
struct sock *sock; struct sock *sock;
int i;
int errors[FD_MAX_EVENTS];
sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_READ_ATTRIBUTES, &sock_ops ); if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle,
if (!sock) FILE_READ_ATTRIBUTES, &sock_ops ))) return;
{
reply->mask = 0;
reply->pmask = 0;
reply->state = 0;
return;
}
reply->mask = sock->mask; reply->mask = sock->mask;
reply->pmask = sock->pmask; reply->pmask = sock->pmask;
reply->state = sock->state; reply->state = sock->state;
for (i = 0; i < FD_MAX_EVENTS; i++) set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) ));
errors[i] = sock_get_ntstatus(sock->errors[i]);
set_reply_data( errors, min( get_reply_max_size(), sizeof(errors) ));
if (req->service) if (req->service)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment