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