Bruno Jesus : ws2_32: Implement WSASendMsg().
Alexandre Julliard
julliard at winehq.org
Tue Oct 1 14:54:27 CDT 2013
Module: wine
Branch: master
Commit: adb8fb115a11598779c0188ef1535783acc2bdf8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=adb8fb115a11598779c0188ef1535783acc2bdf8
Author: Bruno Jesus <00cpxxx at gmail.com>
Date: Mon Sep 30 23:56:53 2013 -0300
ws2_32: Implement WSASendMsg().
---
dlls/ws2_32/socket.c | 21 +++++-
dlls/ws2_32/tests/sock.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/ws2_32/ws2_32.spec | 1 +
3 files changed, 197 insertions(+), 1 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index c606659..a5837cf 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2427,6 +2427,24 @@ static void WINAPI WS2_GetAcceptExSockaddrs(PVOID buffer, DWORD data_size, DWORD
}
/***********************************************************************
+ * WSASendMsg
+ */
+int WINAPI WSASendMsg( SOCKET s, LPWSAMSG msg, DWORD dwFlags, LPDWORD lpNumberOfBytesSent,
+ LPWSAOVERLAPPED lpOverlapped,
+ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+ if (!msg)
+ {
+ SetLastError( WSAEFAULT );
+ return SOCKET_ERROR;
+ }
+
+ return WS2_sendto( s, msg->lpBuffers, msg->dwBufferCount, lpNumberOfBytesSent,
+ dwFlags, msg->name, msg->namelen,
+ lpOverlapped, lpCompletionRoutine );
+}
+
+/***********************************************************************
* WSARecvMsg
*
* Perform a receive operation that is capable of returning message
@@ -3905,7 +3923,8 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
}
else if ( IsEqualGUID(&wsasendmsg_guid, in_buff) )
{
- FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER: unimplemented WSASendMsg\n");
+ *(LPFN_WSASENDMSG *)out_buff = WSASendMsg;
+ break;
}
else
FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff));
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 705981d..fddb820 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -4755,6 +4755,181 @@ end:
closesocket(v6);
}
+static void test_WSASendMsg(void)
+{
+ SOCKET sock, dst;
+ struct sockaddr_in sendaddr, sockaddr;
+ GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
+ LPFN_WSASENDMSG pWSASendMsg = NULL;
+ char teststr[12] = "hello world", buffer[32];
+ WSABUF iovec[2];
+ WSAMSG msg;
+ DWORD bytesSent, err;
+ int ret, addrlen;
+
+ /* FIXME: Missing OVERLAPPED and OVERLAPPED COMPLETION ROUTINE tests */
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ok(sock != INVALID_SOCKET, "socket() failed\n");
+
+ /* Obtain the WSASendMsg function */
+ WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
+ &pWSASendMsg, sizeof(pWSASendMsg), &err, NULL, NULL);
+ if (!pWSASendMsg)
+ {
+ closesocket(sock);
+ win_skip("WSASendMsg is unsupported, some tests will be skipped.\n");
+ return;
+ }
+
+ /* fake address for now */
+ sendaddr.sin_family = AF_INET;
+ sendaddr.sin_port = htons(139);
+ sendaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ memset(&msg, 0, sizeof(msg));
+ iovec[0].buf = teststr;
+ iovec[0].len = sizeof(teststr);
+ iovec[1].buf = teststr;
+ iovec[1].len = sizeof(teststr) / 2;
+ msg.name = (struct sockaddr *) &sendaddr;
+ msg.namelen = sizeof(sendaddr);
+ msg.lpBuffers = iovec;
+ msg.dwBufferCount = 1; /* send only one buffer for now */
+
+ WSASetLastError(0xdeadbeef);
+ ret = pWSASendMsg(INVALID_SOCKET, &msg, 0, NULL, NULL, NULL);
+ ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
+
+ WSASetLastError(0xdeadbeef);
+ ret = pWSASendMsg(sock, NULL, 0, NULL, NULL, NULL);
+ ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+ WSASetLastError(0xdeadbeef);
+ ret = pWSASendMsg(sock, NULL, 0, &bytesSent, NULL, NULL);
+ ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+ WSASetLastError(0xdeadbeef);
+ ret = pWSASendMsg(sock, &msg, 0, NULL, NULL, NULL);
+ ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+ closesocket(sock);
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ok(sock != INVALID_SOCKET, "socket() failed\n");
+
+ dst = socket(AF_INET, SOCK_DGRAM, 0);
+ ok(dst != INVALID_SOCKET, "socket() failed\n");
+
+ memset(&sockaddr, 0, sizeof(sockaddr));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ ok(!bind(dst, (struct sockaddr*)&sockaddr, sizeof(sockaddr)),
+ "bind should have worked\n");
+
+ /* read address to find out the port number to be used in send */
+ memset(&sendaddr, 0, sizeof(sendaddr));
+ addrlen = sizeof(sendaddr);
+ ok(!getsockname(dst, (struct sockaddr *) &sendaddr, &addrlen),
+ "getsockname should have worked\n");
+ ok(sendaddr.sin_port, "socket port should be != 0\n");
+
+ /* ensure the sending socket is not bound */
+ WSASetLastError(0xdeadbeef);
+ addrlen = sizeof(sockaddr);
+ ret = getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen);
+ ok(ret == SOCKET_ERROR, "getsockname should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAEINVAL, "expected 10022, got %d instead\n", err);
+
+ set_blocking(sock, TRUE);
+
+ bytesSent = 0;
+ ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+ ok(!ret, "WSASendMsg should have worked\n");
+ ok(bytesSent == iovec[0].len, "incorret bytes sent, expected %d, sent %d\n",
+ iovec[0].len, bytesSent);
+
+ /* receive data */
+ addrlen = sizeof(sockaddr);
+ memset(buffer, 0, sizeof(buffer));
+ ret = recvfrom(dst, buffer, sizeof(buffer), 0, (struct sockaddr *) &sockaddr, &addrlen);
+ ok(ret == bytesSent, "got %d, expected %d\n",
+ ret, bytesSent);
+
+ /* A successful call to WSASendMsg must have bound the socket */
+ addrlen = sizeof(sockaddr);
+ sockaddr.sin_port = 0;
+ sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ ret = getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen);
+ ok(!ret, "getsockname should have worked\n");
+ ok(sockaddr.sin_addr.s_addr == htonl(INADDR_ANY), "expected 0.0.0.0, got %s\n",
+ inet_ntoa(sockaddr.sin_addr));
+ ok(sockaddr.sin_port, "sin_port should be != 0\n");
+
+ msg.dwBufferCount = 2; /* send both buffers */
+
+ bytesSent = 0;
+ ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+ ok(!ret, "WSASendMsg should have worked\n");
+ ok(bytesSent == iovec[0].len + iovec[1].len, "incorret bytes sent, expected %d, sent %d\n",
+ iovec[0].len + iovec[1].len, bytesSent);
+
+ /* receive data */
+ addrlen = sizeof(sockaddr);
+ memset(buffer, 0, sizeof(buffer));
+ ret = recvfrom(dst, buffer, sizeof(buffer), 0, (struct sockaddr *) &sockaddr, &addrlen);
+ ok(ret == bytesSent, "got %d, expected %d\n",
+ ret, bytesSent);
+
+ closesocket(sock);
+ closesocket(dst);
+
+ /* a bad call to WSASendMsg will also bind the socket */
+ addrlen = sizeof(sockaddr);
+ sockaddr.sin_port = 0;
+ sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ok(sock != INVALID_SOCKET, "socket() failed\n");
+ ok(pWSASendMsg(sock, &msg, 0, NULL, NULL, NULL) == SOCKET_ERROR, "WSASendMsg should have failed\n");
+todo_wine {
+ ok(!getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen), "getsockname should have worked\n");
+ ok(sockaddr.sin_addr.s_addr == htonl(INADDR_ANY), "expected 0.0.0.0, got %s\n",
+ inet_ntoa(sockaddr.sin_addr));
+ ok(sockaddr.sin_port, "sin_port should be > 0\n");
+}
+ closesocket(sock);
+
+ /* a bad call without msg parameter will not trigger the auto-bind */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ ok(sock != INVALID_SOCKET, "socket() failed\n");
+ ok(pWSASendMsg(sock, NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ ok(getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen), "getsockname should have failed\n");
+ err = WSAGetLastError();
+ ok(err == WSAEINVAL, "expected 10022, got %d instead\n", err);
+ closesocket(sock);
+
+ /* SOCK_STREAM sockets are not supported */
+ bytesSent = 0;
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ ok(sock != INVALID_SOCKET, "socket() failed\n");
+ SetLastError(0xdeadbeef);
+ ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+ ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+ err = WSAGetLastError();
+todo_wine
+ ok(err == WSAEINVAL, "expected 10014, got %d instead\n", err);
+ closesocket(sock);
+}
+
static void test_WSASendTo(void)
{
SOCKET s;
@@ -6750,6 +6925,7 @@ START_TEST( sock )
test_dns();
test_gethostbyname_hack();
+ test_WSASendMsg();
test_WSASendTo();
test_WSARecv();
diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec
index ccec106..0811b74 100644
--- a/dlls/ws2_32/ws2_32.spec
+++ b/dlls/ws2_32/ws2_32.spec
@@ -97,6 +97,7 @@
@ stdcall WSAResetEvent(long) kernel32.ResetEvent
@ stdcall WSASend(long ptr long ptr long ptr ptr)
@ stdcall WSASendDisconnect(long ptr)
+@ stdcall WSASendMsg(long ptr long ptr ptr ptr)
@ stdcall WSASendTo(long ptr long ptr long ptr long ptr ptr)
@ stdcall WSASetEvent(long) kernel32.SetEvent
@ stdcall WSASetServiceA(ptr long long)
More information about the wine-cvs
mailing list