diff --git a/src/afd.c b/src/afd.c index 1b6e8fe..8c32333 100644 --- a/src/afd.c +++ b/src/afd.c @@ -71,7 +71,7 @@ int afd_global_init(void) { /* Load the winsock catalog. */ infos_count = ws_get_protocol_catalog(&infos); if (infos_count < 0) - return_error(-1); + return_map_error(-1); /* Find a WSAPROTOCOL_INFOW structure that we can use to create an MSAFD * socket. Preferentially we pick a UDP socket, otherwise try TCP or any @@ -90,7 +90,7 @@ int afd_global_init(void) { break; free(infos); - return_error(-1, WSAENETDOWN); /* No suitable protocol found. */ + return_set_error(-1, WSAENETDOWN); /* No suitable protocol found. */ } /* Copy found protocol information from the catalog to a static buffer. */ @@ -110,7 +110,7 @@ int afd_create_driver_socket(HANDLE iocp, SOCKET* driver_socket_out) { 0, WSA_FLAG_OVERLAPPED); if (socket == INVALID_SOCKET) - return_error(-1); + return_map_error(-1); /* TODO: use WSA_FLAG_NOINHERIT on Windows versions that support it. */ if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) @@ -125,7 +125,7 @@ int afd_create_driver_socket(HANDLE iocp, SOCKET* driver_socket_out) { error:; DWORD error = GetLastError(); closesocket(socket); - return_error(-1, error); + return_set_error(-1, error); } int afd_poll(SOCKET driver_socket, @@ -155,7 +155,7 @@ int afd_poll(SOCKET driver_socket, iosb_ptr = &iosb; event = CreateEventW(NULL, FALSE, FALSE, NULL); if (event == NULL) - return_error(-1); + return_map_error(-1); apc_context = NULL; } @@ -180,7 +180,7 @@ int afd_poll(SOCKET driver_socket, if (r == WAIT_FAILED) { DWORD error = GetLastError(); CloseHandle(event); - return_error(-1, error); + return_set_error(-1, error); } status = iosb_ptr->Status; @@ -192,7 +192,7 @@ int afd_poll(SOCKET driver_socket, if (status == STATUS_SUCCESS) return 0; else if (status == STATUS_PENDING) - return_error(-1, ERROR_IO_PENDING); + return_set_error(-1, ERROR_IO_PENDING); else - return_error(-1, RtlNtStatusToDosError(status)); + return_set_error(-1, RtlNtStatusToDosError(status)); } diff --git a/src/api.c b/src/api.c index 76f95a5..ad9b1f1 100644 --- a/src/api.c +++ b/src/api.c @@ -36,7 +36,7 @@ static HANDLE _epoll_create(void) { (uintptr_t) ephnd) < 0) { /* This should never happen. */ ep_port_delete(port_info); - return_error(NULL, ERROR_ALREADY_EXISTS); + return_set_error(NULL, ERROR_ALREADY_EXISTS); } return ephnd; @@ -44,14 +44,14 @@ static HANDLE _epoll_create(void) { HANDLE epoll_create(int size) { if (size <= 0) - return_error(NULL, ERROR_INVALID_PARAMETER); + return_set_error(NULL, ERROR_INVALID_PARAMETER); return _epoll_create(); } HANDLE epoll_create1(int flags) { if (flags != 0) - return_error(NULL, ERROR_INVALID_PARAMETER); + return_set_error(NULL, ERROR_INVALID_PARAMETER); return _epoll_create(); } @@ -122,7 +122,7 @@ int epoll_wait(HANDLE ephnd, int num_events; if (maxevents <= 0) - return_error(-1, ERROR_INVALID_PARAMETER); + return_set_error(-1, ERROR_INVALID_PARAMETER); if (init() < 0) return -1; diff --git a/src/error.c b/src/error.c index afb7af1..958061f 100644 --- a/src/error.c +++ b/src/error.c @@ -117,11 +117,12 @@ static errno_t _err_map_win_error_to_errno(DWORD error) { return EINVAL; } +void err_map_win_error(void) { + errno = _err_map_win_error_to_errno(GetLastError()); +} + void err_set_win_error(DWORD error) { - if (error == 0) - error = GetLastError(); - else - SetLastError(error); + SetLastError(error); errno = _err_map_win_error_to_errno(error); } @@ -131,10 +132,10 @@ int err_check_handle(HANDLE handle) { /* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check * for this condition explicitly. */ if (handle == INVALID_HANDLE_VALUE) - return_error(-1, ERROR_INVALID_HANDLE); + return_set_error(-1, ERROR_INVALID_HANDLE); if (!GetHandleInformation(handle, &flags)) - return_error(-1); + return_map_error(-1); return 0; } diff --git a/src/error.h b/src/error.h index dd1f290..6efc258 100644 --- a/src/error.h +++ b/src/error.h @@ -4,14 +4,19 @@ #include "internal.h" #include "win.h" -#define _return_error_helper(error, value) \ - do { \ - err_set_win_error(error); \ - return (value); \ +#define return_map_error(value) \ + do { \ + err_map_win_error(); \ + return (value); \ } while (0) -#define return_error(value, ...) _return_error_helper(__VA_ARGS__ + 0, value) +#define return_set_error(value, error) \ + do { \ + err_set_win_error(error); \ + return (value); \ + } while (0) +WEPOLL_INTERNAL void err_map_win_error(void); WEPOLL_INTERNAL void err_set_win_error(DWORD error); WEPOLL_INTERNAL int err_check_handle(HANDLE handle); diff --git a/src/poll-group.c b/src/poll-group.c index 9a40e11..d1b379c 100644 --- a/src/poll-group.c +++ b/src/poll-group.c @@ -20,7 +20,7 @@ typedef struct poll_group { static poll_group_t* _poll_group_new(ep_port_t* port_info) { poll_group_t* poll_group = malloc(sizeof *poll_group); if (poll_group == NULL) - return_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); memset(poll_group, 0, sizeof *poll_group); diff --git a/src/port.c b/src/port.c index 7d42a87..32d2db7 100644 --- a/src/port.c +++ b/src/port.c @@ -19,7 +19,7 @@ static ep_port_t* _ep_port_alloc(void) { ep_port_t* port_info = malloc(sizeof *port_info); if (port_info == NULL) - return_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); return port_info; } @@ -32,7 +32,7 @@ static void _ep_port_free(ep_port_t* port) { static HANDLE _ep_port_create_iocp(void) { HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (iocp == NULL) - return_error(NULL); + return_map_error(NULL); return iocp; } @@ -73,7 +73,7 @@ static int _ep_port_close_iocp(ep_port_t* port_info) { port_info->iocp = NULL; if (!CloseHandle(iocp)) - return_error(-1); + return_map_error(-1); return 0; } @@ -185,7 +185,7 @@ static int _ep_port_poll(ep_port_t* port_info, port_info->active_poll_count--; if (!r) - return_error(-1); + return_map_error(-1); return _ep_port_feed_events( port_info, epoll_events, iocp_events, completion_count); @@ -203,7 +203,7 @@ int ep_port_wait(ep_port_t* port_info, /* Check whether `maxevents` is in range. */ if (maxevents <= 0) - return_error(-1, ERROR_INVALID_PARAMETER); + return_set_error(-1, ERROR_INVALID_PARAMETER); /* Decide whether the IOCP completion list can live on the stack, or allocate * memory for it on the heap. */ @@ -322,7 +322,7 @@ static int _ep_port_ctl_op(ep_port_t* port_info, case EPOLL_CTL_DEL: return _ep_port_ctl_del(port_info, sock); default: - return_error(-1, ERROR_INVALID_PARAMETER); + return_set_error(-1, ERROR_INVALID_PARAMETER); } } @@ -344,7 +344,7 @@ int ep_port_register_socket_handle(ep_port_t* port_info, SOCKET socket) { if (tree_add( &port_info->sock_tree, ep_sock_to_tree_node(sock_info), socket) < 0) - return_error(-1, ERROR_ALREADY_EXISTS); + return_set_error(-1, ERROR_ALREADY_EXISTS); return 0; } @@ -356,7 +356,7 @@ void ep_port_unregister_socket_handle(ep_port_t* port_info, ep_sock_t* ep_port_find_socket(ep_port_t* port_info, SOCKET socket) { tree_node_t* tree_node = tree_find(&port_info->sock_tree, socket); if (tree_node == NULL) - return_error(NULL, ERROR_NOT_FOUND); + return_set_error(NULL, ERROR_NOT_FOUND); return ep_sock_from_tree_node(tree_node); } diff --git a/src/reflock.c b/src/reflock.c index 3c3db68..c4f10e7 100644 --- a/src/reflock.c +++ b/src/reflock.c @@ -22,7 +22,7 @@ int reflock_global_init(void) { NTSTATUS status = NtCreateKeyedEvent(&_keyed_event, ~(ACCESS_MASK) 0, NULL, 0); if (status != STATUS_SUCCESS) - return_error(-1, RtlNtStatusToDosError(status)); + return_set_error(-1, RtlNtStatusToDosError(status)); return 0; } diff --git a/src/sock.c b/src/sock.c index 0f1ab8b..3f6d871 100644 --- a/src/sock.c +++ b/src/sock.c @@ -38,7 +38,7 @@ typedef struct ep_sock { static inline ep_sock_t* _ep_sock_alloc(void) { ep_sock_t* sock_info = malloc(sizeof *sock_info); if (sock_info == NULL) - return_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); return sock_info; } @@ -54,7 +54,7 @@ static int _ep_sock_cancel_poll(ep_sock_t* sock_info) { * already completed. This is not a problem and we proceed normally. */ if (!CancelIoEx(driver_handle, &sock_info->overlapped) && GetLastError() != ERROR_NOT_FOUND) - return_error(-1); + return_map_error(-1); sock_info->poll_status = _POLL_CANCELLED; sock_info->pending_events = 0; @@ -67,7 +67,7 @@ ep_sock_t* ep_sock_new(ep_port_t* port_info, SOCKET socket) { ep_sock_t* sock_info; if (socket == 0 || socket == INVALID_SOCKET) - return_error(NULL, ERROR_INVALID_HANDLE); + return_set_error(NULL, ERROR_INVALID_HANDLE); base_socket = ws_get_base_socket(socket); if (base_socket == INVALID_SOCKET) @@ -243,7 +243,7 @@ int ep_sock_update(ep_port_t* port_info, ep_sock_t* sock_info) { return _ep_sock_delete(port_info, sock_info, false); default: /* Other errors are propagated to the caller. */ - return_error(-1); + return_map_error(-1); } } diff --git a/src/ws.c b/src/ws.c index 857b7f0..73aa86a 100644 --- a/src/ws.c +++ b/src/ws.c @@ -18,7 +18,7 @@ int ws_global_init(void) { r = WSAStartup(MAKEWORD(2, 2), &wsa_data); if (r != 0) - return_error(-1, r); + return_set_error(-1, r); return 0; } @@ -36,7 +36,7 @@ SOCKET ws_get_base_socket(SOCKET socket) { &bytes, NULL, NULL) == SOCKET_ERROR) - return_error(INVALID_SOCKET); + return_map_error(INVALID_SOCKET); return base_socket; } @@ -51,7 +51,7 @@ ssize_t ws_get_protocol_catalog(WSAPROTOCOL_INFOW** infos_out) { for (;;) { infos = malloc(buffer_size); if (infos == NULL) - return_error(-1, ERROR_NOT_ENOUGH_MEMORY); + return_set_error(-1, ERROR_NOT_ENOUGH_MEMORY); count = WSAEnumProtocolsW(NULL, infos, &buffer_size); if (count == SOCKET_ERROR) { @@ -59,7 +59,7 @@ ssize_t ws_get_protocol_catalog(WSAPROTOCOL_INFOW** infos_out) { if (WSAGetLastError() == WSAENOBUFS) continue; /* Try again with bigger buffer size. */ else - return_error(-1); + return_map_error(-1); } *infos_out = infos;