Module: wine Branch: master Commit: 4d6982e6845d69070ed05baf157a59ebb5ba0347 URL: http://source.winehq.org/git/wine.git/?a=commit;h=4d6982e6845d69070ed05baf15...
Author: Mike Kaplinskiy mike.kaplinskiy@gmail.com Date: Sat Jul 31 23:21:34 2010 -0400
ws2_32: Implement ConnectEx.
---
dlls/ws2_32/socket.c | 106 +++++++++++++++++++++++++++++++++++++++++++++- dlls/ws2_32/tests/sock.c | 4 +- 2 files changed, 107 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 2db34a5..22c72f3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1899,6 +1899,109 @@ int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen, return WS_connect( s, name, namelen ); }
+/*********************************************************************** + * ConnectEx + */ +BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int namelen, + PVOID sendBuf, DWORD sendBufLen, LPDWORD sent, LPOVERLAPPED ov) +{ + int fd = get_sock_fd( s, FILE_READ_DATA, NULL ); + int ret, status; + if (fd == -1) + { + SetLastError( WSAENOTSOCK ); + return FALSE; + } + if (!ov) + { + release_sock_fd(s, fd); + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + TRACE("socket %04lx, ptr %p %s, length %d, sendptr %p, len %d, ov %p\n", + s, name, debugstr_sockaddr(name), namelen, sendBuf, sendBufLen, ov); + + /* FIXME: technically the socket has to be bound */ + ret = do_connect(fd, name, namelen); + if (ret == 0) + { + WSABUF wsabuf; + + _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE, + FD_WINE_CONNECTED|FD_READ|FD_WRITE, + FD_CONNECT|FD_WINE_LISTENING); + + wsabuf.len = sendBufLen; + wsabuf.buf = (char*) sendBuf; + + /* WSASend takes care of completion if need be */ + if (WSASend(s, &wsabuf, sendBuf ? 1 : 0, sent, 0, ov, NULL) != SOCKET_ERROR) + goto connection_success; + } + else if (ret == WSAEINPROGRESS) + { + struct ws2_async *wsa; + ULONG_PTR cvalue = (((ULONG_PTR)ov->hEvent & 1) == 0) ? (ULONG_PTR)ov : 0; + + _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE, + FD_CONNECT, + FD_WINE_CONNECTED|FD_WINE_LISTENING); + + /* Indirectly call WSASend */ + if (!(wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) ))) + { + SetLastError(WSAEFAULT); + } + else + { + IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)ov; + iosb->u.Status = STATUS_PENDING; + iosb->Information = 0; + + wsa->hSocket = SOCKET2HANDLE(s); + wsa->addr = NULL; + wsa->addrlen.val = 0; + wsa->flags = 0; + wsa->n_iovecs = sendBuf ? 1 : 0; + wsa->first_iovec = 0; + wsa->iovec[0].iov_base = sendBuf; + wsa->iovec[0].iov_len = sendBufLen; + + SERVER_START_REQ( register_async ) + { + req->type = ASYNC_TYPE_WRITE; + req->async.handle = wine_server_obj_handle( wsa->hSocket ); + req->async.callback = wine_server_client_ptr( WS2_async_send ); + req->async.iosb = wine_server_client_ptr( iosb ); + req->async.arg = wine_server_client_ptr( wsa ); + req->async.event = wine_server_obj_handle( ov->hEvent ); + req->async.cvalue = cvalue; + status = wine_server_call( req ); + } + SERVER_END_REQ; + + if (status != STATUS_PENDING) HeapFree(GetProcessHeap(), 0, wsa); + + /* If the connect already failed */ + if (status == STATUS_PIPE_DISCONNECTED) + status = _get_sock_error(s, FD_CONNECT_BIT); + SetLastError( NtStatusToWSAError(status) ); + } + } + else + { + SetLastError(ret); + } + + release_sock_fd( s, fd ); + return FALSE; + +connection_success: + release_sock_fd( s, fd ); + return TRUE; +} +
/*********************************************************************** * getpeername (WS2_32.5) @@ -2742,7 +2845,8 @@ INT WINAPI WSAIoctl(SOCKET s,
if ( IsEqualGUID(&connectex_guid, lpvInBuffer) ) { - FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented ConnectEx\n"); + *(LPFN_CONNECTEX *)lpbOutBuffer = WS2_ConnectEx; + return 0; } else if ( IsEqualGUID(&disconnectex_guid, lpvInBuffer) ) { diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 58b02b9..b2a3153 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3558,7 +3558,7 @@ static void test_ConnectEx(void) iret = WSAIoctl(connector, SIO_GET_EXTENSION_FUNCTION_POINTER, &connectExGuid, sizeof(connectExGuid), &pConnectEx, sizeof(pConnectEx), &bytesReturned, NULL, NULL); if (iret) { - skip("WSAIoctl failed to get ConnectEx with ret %d + errno %d\n", iret, WSAGetLastError()); + win_skip("WSAIoctl failed to get ConnectEx with ret %d + errno %d\n", iret, WSAGetLastError()); goto end; }
@@ -3567,7 +3567,7 @@ static void test_ConnectEx(void) "returned %d + errno %d\n", bret, WSAGetLastError());
bret = pConnectEx(connector, (struct sockaddr*)&address, addrlen, NULL, 0, &bytesReturned, &overlapped); - ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "ConnectEx on a unbound socket " + todo_wine ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "ConnectEx on a unbound socket " "returned %d + errno %d\n", bret, WSAGetLastError()); if (bret == TRUE || WSAGetLastError() != WSAEINVAL) {