Commit 798c9e51 authored by Mike Kaplinskiy's avatar Mike Kaplinskiy Committed by Alexandre Julliard

ws2_32: Use ntstatus in overlapped functions.

parent 1181762f
...@@ -424,12 +424,53 @@ static const char magic_loopback_addr[] = {127, 12, 34, 56}; ...@@ -424,12 +424,53 @@ static const char magic_loopback_addr[] = {127, 12, 34, 56};
/* ----------------------------------- error handling */ /* ----------------------------------- error handling */
static UINT wsaErrno(void) static NTSTATUS sock_get_ntstatus( int err )
{ {
int loc_errno = errno; switch ( err )
WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno)); {
case EBADF: return STATUS_INVALID_HANDLE;
case EBUSY: return STATUS_DEVICE_BUSY;
case EPERM:
case EACCES: return STATUS_ACCESS_DENIED;
case EFAULT: return STATUS_NO_MEMORY;
case EINVAL: return STATUS_INVALID_PARAMETER;
case ENFILE:
case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
case EWOULDBLOCK: return STATUS_CANT_WAIT;
case EINPROGRESS: return STATUS_PENDING;
case EALREADY: return STATUS_NETWORK_BUSY;
case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
case EPROTONOSUPPORT:
case ESOCKTNOSUPPORT:
case EPFNOSUPPORT:
case EAFNOSUPPORT:
case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
case EADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
case ENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
case ETIMEDOUT: return STATUS_IO_TIMEOUT;
case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
case ENETDOWN: return STATUS_NETWORK_BUSY;
case EPIPE:
case ECONNRESET: return STATUS_CONNECTION_RESET;
case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
switch(loc_errno) case 0: return STATUS_SUCCESS;
default:
WARN("Unknown errno %d!\n", err);
return STATUS_UNSUCCESSFUL;
}
}
static UINT sock_get_error( int err )
{
switch(err)
{ {
case EINTR: return WSAEINTR; case EINTR: return WSAEINTR;
case EBADF: return WSAEBADF; case EBADF: return WSAEBADF;
...@@ -490,14 +531,30 @@ static UINT wsaErrno(void) ...@@ -490,14 +531,30 @@ static UINT wsaErrno(void)
/* just in case we ever get here and there are no problems */ /* just in case we ever get here and there are no problems */
case 0: return 0; case 0: return 0;
default: default:
WARN("Unknown errno %d!\n", loc_errno); WARN("Unknown errno %d!\n", err);
return WSAEOPNOTSUPP; return WSAEOPNOTSUPP;
} }
} }
static UINT wsaHerrno(int loc_errno) static UINT wsaErrno(void)
{
int loc_errno = errno;
WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
return sock_get_error( loc_errno );
}
/* most ws2 overlapped functions return an ntstatus-based error code */
static NTSTATUS wsaErrStatus(void)
{ {
int loc_errno = errno;
WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
return sock_get_ntstatus(loc_errno);
}
static UINT wsaHerrno(int loc_errno)
{
WARN("h_errno %d.\n", loc_errno); WARN("h_errno %d.\n", loc_errno);
switch(loc_errno) switch(loc_errno)
...@@ -527,19 +584,27 @@ static inline DWORD NtStatusToWSAError( const DWORD status ) ...@@ -527,19 +584,27 @@ static inline DWORD NtStatusToWSAError( const DWORD status )
case STATUS_INVALID_HANDLE: wserr = WSAEBADF; break; case STATUS_INVALID_HANDLE: wserr = WSAEBADF; break;
case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break; case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break; case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
case STATUS_NETWORK_BUSY: wserr = WSAEALREADY; break;
case STATUS_NETWORK_UNREACHABLE: wserr = WSAENETUNREACH; break;
case STATUS_CONNECTION_REFUSED: wserr = WSAECONNREFUSED; break;
case STATUS_CONNECTION_DISCONNECTED: wserr = WSAENOTCONN; break;
case STATUS_CONNECTION_RESET: wserr = WSAECONNRESET; break;
case STATUS_CONNECTION_ABORTED: wserr = WSAECONNABORTED; break;
case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break; case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
case STATUS_ADDRESS_ALREADY_ASSOCIATED: wserr = WSAEADDRINUSE; break;
case STATUS_IO_TIMEOUT:
case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break; case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
case STATUS_NO_MEMORY: wserr = WSAEFAULT; break; case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
case STATUS_ACCESS_DENIED: wserr = WSAEACCES; break;
case STATUS_TOO_MANY_OPENED_FILES: wserr = WSAEMFILE; break;
case STATUS_CANT_WAIT: wserr = WSAEWOULDBLOCK; break;
case STATUS_BUFFER_OVERFLOW: wserr = WSAEMSGSIZE; break;
case STATUS_NOT_SUPPORTED: wserr = WSAEOPNOTSUPP; break;
default: default:
if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
/* It is not an NT status code but a winsock error */
wserr = status;
else
{
wserr = RtlNtStatusToDosError( status ); wserr = RtlNtStatusToDosError( status );
FIXME( "Status code %08x converted to DOS error code %x\n", status, wserr ); FIXME( "Status code %08x converted to DOS error code %x\n", status, wserr );
} }
}
return wserr; return wserr;
} }
...@@ -1365,7 +1430,7 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat ...@@ -1365,7 +1430,7 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat
else else
{ {
result = 0; result = 0;
status = wsaErrno(); /* FIXME: is this correct ???? */ status = wsaErrStatus();
} }
} }
break; break;
...@@ -1473,9 +1538,7 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu ...@@ -1473,9 +1538,7 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu
} }
else else
{ {
/* We set the status to a winsock error code and check for that status = wsaErrStatus();
later in NtStatusToWSAError () */
status = wsaErrno();
result = 0; result = 0;
} }
} }
...@@ -1511,8 +1574,8 @@ static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS ...@@ -1511,8 +1574,8 @@ static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS
case ASYNC_TYPE_READ: err = shutdown( fd, 0 ); break; case ASYNC_TYPE_READ: err = shutdown( fd, 0 ); break;
case ASYNC_TYPE_WRITE: err = shutdown( fd, 1 ); break; case ASYNC_TYPE_WRITE: err = shutdown( fd, 1 ); break;
} }
status = err ? wsaErrStatus() : STATUS_SUCCESS;
wine_server_release_fd( wsa->hSocket, fd ); wine_server_release_fd( wsa->hSocket, fd );
status = err ? wsaErrno() : STATUS_SUCCESS;
break; break;
} }
iosb->u.Status = status; iosb->u.Status = status;
...@@ -1590,7 +1653,7 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr, ...@@ -1590,7 +1653,7 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
if (addr) WS_getpeername(as, addr, addrlen32); if (addr) WS_getpeername(as, addr, addrlen32);
return as; return as;
} }
if (is_blocking && status == WSAEWOULDBLOCK) if (is_blocking && status == STATUS_CANT_WAIT)
{ {
int fd = get_sock_fd( s, FILE_READ_DATA, NULL ); int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
/* block here */ /* block here */
...@@ -1598,7 +1661,7 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr, ...@@ -1598,7 +1661,7 @@ SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
_sync_sock_state(s); /* let wineserver notice connection */ _sync_sock_state(s); /* let wineserver notice connection */
release_sock_fd( s, fd ); release_sock_fd( s, fd );
} }
} while (is_blocking && status == WSAEWOULDBLOCK); } while (is_blocking && status == STATUS_CANT_WAIT);
set_error(status); set_error(status);
return INVALID_SOCKET; return INVALID_SOCKET;
...@@ -1747,7 +1810,7 @@ int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen) ...@@ -1747,7 +1810,7 @@ int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
/* retrieve any error codes from it */ /* retrieve any error codes from it */
result = _get_sock_error(s, FD_CONNECT_BIT); result = _get_sock_error(s, FD_CONNECT_BIT);
if (result) if (result)
SetLastError(result); SetLastError(NtStatusToWSAError(result));
else else
{ {
goto connect_success; goto connect_success;
...@@ -3044,8 +3107,9 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -3044,8 +3107,9 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
} }
if (n == -1 && errno != EAGAIN) if (n == -1 && errno != EAGAIN)
{ {
int loc_errno = errno;
err = wsaErrno(); err = wsaErrno();
if (cvalue) WS_AddCompletion( s, cvalue, err, 0 ); if (cvalue) WS_AddCompletion( s, cvalue, sock_get_ntstatus(loc_errno), 0 );
goto error; goto error;
} }
...@@ -4227,6 +4291,8 @@ int WINAPI WS_gethostname(char *name, int namelen) ...@@ -4227,6 +4291,8 @@ int WINAPI WS_gethostname(char *name, int namelen)
int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent) int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
{ {
int ret; int ret;
int i;
int errors[FD_MAX_EVENTS];
TRACE("%08lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent ); TRACE("%08lx, hEvent %p, lpEvent %p\n", s, hEvent, lpEvent );
...@@ -4235,11 +4301,16 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp ...@@ -4235,11 +4301,16 @@ int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lp
req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) ); req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
req->service = TRUE; req->service = TRUE;
req->c_event = wine_server_obj_handle( hEvent ); req->c_event = wine_server_obj_handle( hEvent );
wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) ); wine_server_set_reply( req, errors, sizeof(errors) );
if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask; if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
} }
SERVER_END_REQ; SERVER_END_REQ;
if (!ret) return 0; if (!ret)
{
for (i = 0; i < FD_MAX_EVENTS; i++)
lpEvent->iErrorCode[i] = NtStatusToWSAError(errors[i]);
return 0;
}
SetLastError(WSAEINVAL); SetLastError(WSAEINVAL);
return SOCKET_ERROR; return SOCKET_ERROR;
} }
...@@ -4794,8 +4865,9 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4794,8 +4865,9 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if (errno == EINTR) continue; if (errno == EINTR) continue;
if (errno != EAGAIN) if (errno != EAGAIN)
{ {
int loc_errno = errno;
err = wsaErrno(); err = wsaErrno();
if (cvalue) WS_AddCompletion( s, cvalue, err, 0 ); if (cvalue) WS_AddCompletion( s, cvalue, sock_get_ntstatus(loc_errno), 0 );
goto error; goto error;
} }
} }
......
...@@ -123,6 +123,7 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, ...@@ -123,6 +123,7 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
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 void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ); static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
static int sock_get_ntstatus( int err );
static int sock_get_error( int err ); static int sock_get_error( int err );
static void sock_set_error(void); static void sock_set_error(void);
...@@ -302,7 +303,7 @@ static void sock_wake_up( struct sock *sock, int pollev ) ...@@ -302,7 +303,7 @@ static void sock_wake_up( struct sock *sock, int pollev )
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->errors[event] << 16); lparam_t lparam = (1 << event) | (sock_get_error(sock->errors[event]) << 16);
post_message( sock->window, sock->message, sock->wparam, lparam ); post_message( sock->window, sock->message, sock->wparam, lparam );
} }
} }
...@@ -317,7 +318,7 @@ static inline int sock_error( struct fd *fd ) ...@@ -317,7 +318,7 @@ static inline int sock_error( struct fd *fd )
optlen = sizeof(optval); optlen = sizeof(optval);
getsockopt( get_unix_fd(fd), SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen); getsockopt( get_unix_fd(fd), SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
return optval ? sock_get_error(optval) : 0; return optval;
} }
static void sock_poll_event( struct fd *fd, int event ) static void sock_poll_event( struct fd *fd, int event )
...@@ -636,6 +637,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne ...@@ -636,6 +637,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
sock->deferred = NULL; sock->deferred = NULL;
sock->read_q = NULL; sock->read_q = NULL;
sock->write_q = NULL; sock->write_q = NULL;
memset( sock->errors, 0, sizeof(sock->errors) );
if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj,
(flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT )))
{ {
...@@ -706,6 +708,7 @@ static struct sock *accept_socket( obj_handle_t handle ) ...@@ -706,6 +708,7 @@ static struct sock *accept_socket( obj_handle_t handle )
acceptsock->deferred = NULL; acceptsock->deferred = NULL;
acceptsock->read_q = NULL; acceptsock->read_q = NULL;
acceptsock->write_q = NULL; acceptsock->write_q = NULL;
memset( acceptsock->errors, 0, sizeof(acceptsock->errors) );
if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj, if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
get_fd_options( sock->fd ) ))) get_fd_options( sock->fd ) )))
{ {
...@@ -782,6 +785,8 @@ static int sock_get_error( int err ) ...@@ -782,6 +785,8 @@ static int sock_get_error( int err )
#ifdef EREMOTE #ifdef EREMOTE
case EREMOTE: return WSAEREMOTE; case EREMOTE: return WSAEREMOTE;
#endif #endif
case 0: return 0;
default: default:
errno = err; errno = err;
perror("wineserver: sock_get_error() can't map error"); perror("wineserver: sock_get_error() can't map error");
...@@ -789,10 +794,55 @@ static int sock_get_error( int err ) ...@@ -789,10 +794,55 @@ static int sock_get_error( int err )
} }
} }
static int sock_get_ntstatus( int err )
{
switch ( err )
{
case EBADF: return STATUS_INVALID_HANDLE;
case EBUSY: return STATUS_DEVICE_BUSY;
case EPERM:
case EACCES: return STATUS_ACCESS_DENIED;
case EFAULT: return STATUS_NO_MEMORY;
case EINVAL: return STATUS_INVALID_PARAMETER;
case ENFILE:
case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
case EWOULDBLOCK: return STATUS_CANT_WAIT;
case EINPROGRESS: return STATUS_PENDING;
case EALREADY: return STATUS_NETWORK_BUSY;
case ENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH;
case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
case EPROTONOSUPPORT:
case ESOCKTNOSUPPORT:
case EPFNOSUPPORT:
case EAFNOSUPPORT:
case EPROTOTYPE: return STATUS_NOT_SUPPORTED;
case ENOPROTOOPT: return STATUS_INVALID_PARAMETER;
case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
case EADDRINUSE: return STATUS_ADDRESS_ALREADY_ASSOCIATED;
case EADDRNOTAVAIL: return STATUS_INVALID_PARAMETER;
case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
case ESHUTDOWN: return STATUS_PIPE_DISCONNECTED;
case ENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
case ETIMEDOUT: return STATUS_IO_TIMEOUT;
case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
case ENETDOWN: return STATUS_NETWORK_BUSY;
case EPIPE:
case ECONNRESET: return STATUS_CONNECTION_RESET;
case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
case 0: return STATUS_SUCCESS;
default:
errno = err;
perror("wineserver: sock_get_ntstatus() can't map error");
return STATUS_UNSUCCESSFUL;
}
}
/* set the last error depending on errno */ /* set the last error depending on errno */
static void sock_set_error(void) static void sock_set_error(void)
{ {
set_error( sock_get_error( errno ) ); set_error( sock_get_ntstatus( errno ) );
} }
/* create a socket */ /* create a socket */
...@@ -863,6 +913,8 @@ DECL_HANDLER(set_socket_event) ...@@ -863,6 +913,8 @@ 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 ); sock = (struct sock *)get_handle_obj( current->process, req->handle, FILE_READ_ATTRIBUTES, &sock_ops );
if (!sock) if (!sock)
...@@ -870,13 +922,15 @@ DECL_HANDLER(get_socket_event) ...@@ -870,13 +922,15 @@ DECL_HANDLER(get_socket_event)
reply->mask = 0; reply->mask = 0;
reply->pmask = 0; reply->pmask = 0;
reply->state = 0; reply->state = 0;
set_error( WSAENOTSOCK );
return; 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;
set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) )); for (i = 0; i < FD_MAX_EVENTS; i++)
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)
{ {
...@@ -926,15 +980,12 @@ DECL_HANDLER(set_socket_deferred) ...@@ -926,15 +980,12 @@ DECL_HANDLER(set_socket_deferred)
sock=(struct sock *)get_handle_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES, &sock_ops ); sock=(struct sock *)get_handle_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES, &sock_ops );
if ( !sock ) if ( !sock )
{
set_error( WSAENOTSOCK );
return; return;
}
acceptsock = (struct sock *)get_handle_obj( current->process, req->deferred, 0, &sock_ops ); acceptsock = (struct sock *)get_handle_obj( current->process, req->deferred, 0, &sock_ops );
if ( !acceptsock ) if ( !acceptsock )
{ {
release_object( sock ); release_object( sock );
set_error( WSAENOTSOCK );
return; return;
} }
sock->deferred = acceptsock; sock->deferred = acceptsock;
......
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