ws2_32: Add support and tests for WSARecvMsg and IP_PKTINFO.

Mike Kaplinskiy mike.kaplinskiy at
Tue Oct 12 23:12:15 CDT 2010

On Tue, Oct 12, 2010 at 8:01 PM, Erich Hoover <ehoover at> wrote:
> Real Name:
>     Erich Hoover
> Description:
>     While searching for something else I discovered a bug relevant to the
> interface-bound UDP broadcast patches I've been working on.  Apparently,
> IP_PKTINFO does work on Windows when used with the special WSARecvMsg
> function (Bug #19493).  The attached patch addresses this issue by
> implementing WSARecvMsg through WS2_recvfrom and by converting the Unix
> IP_PKTINFO response to the Windows equivalent.
> ChangeLog:
>     ws2_32: Add support and tests for WSARecvMsg and IP_PKTINFO.

Sorry I must have missed the RFC when reading my mail. These comments
are purely mine, and may not have any value for getting your patch in

+static inline WSACMSGHDR *create_control_message(int level, int type,
WSACMSGHDR *current, ULONG *maxsize, void *data, int len)
This doesn't seem like a "create", more like a "fill" or "write".

+    int newsize = (int)*maxsize;
+    /* Make sure there is at least enough room for this entry */
+    newsize -= sizeof(WSACMSGHDR) + CMSG_ALIGN(len);
+    if (newsize < 0)
+        return 0;
+    *maxsize = (ULONG)newsize;
Just declare it as a ULONG/size_t so you don't have to cast.

+static inline int convert_control_headers(struct msghdr *hdr, ULONG *maxsize)
You shouldn't mix using memory as unix-style CMSGs and windows-style
CMSGs. Just allocate something to store the unix messages, read them
in and convert them into the user-passed buffer. This seems similar to
what we do for address conversion.

+    memset(cmsg_win, 0x00, sizeof(WSACMSGHDR)); /* Don't use garbage
data if no headers are found */
I think in general that is discouraged at wine (don't quote me on
that). You should just initialize the values manually.

+    if (wsa->control && !convert_control_headers(&hdr, wsa->controllen))
+    {
+        /* Insufficient room for control headers */
+        errno = EINVAL;
+        return -1;
+    }
This should probably be in an #ifdef of some sort.

+    msg->dwFlags |= WINE_MSG_HASCTRL;
+    memcpy(buftmp, msg->lpBuffers, msg->dwBufferCount * sizeof(WSABUF));
+    buftmp[msg->dwBufferCount] = msg->Control;
+    ret = WS2_recvfrom( s, buftmp, msg->dwBufferCount, lpNumberOfBytesRecvd,
+                        &msg->dwFlags, msg->name, &msg->namelen,
+                        lpOverlapped, lpCompletionRoutine );
You shouldn't add internal flags like that. Just rewrite WS2_recvfrom
to allow returning message headers instead of hacking around it.

+static int    (WINAPI
= 0;
For one reason or another the convention is to get it during your test
function (see AcceptEx & ConnectEx). (This does have some merit as
SIO_GET_EXTENSION_FUNCTION_POINTER can vary with the socket that's

+    s1addr.sin_family      = AF_INET;
+    s1addr.sin_port        = htons(9375);
+    s2addr.sin_family      = AF_INET;
+    s2addr.sin_port        = htons(9375);
You should probably bind to 0 and then use getsockname to get the
actual port you bound to.

+        s1=socket(AF_INET, SOCK_DGRAM, 0);
+        ok(s1!=INVALID_SOCKET, "socket() failed error: %d\n",
Spaces around = & != would make me happy (and below). Also you don't
error out correctly if socket creation fails.

diff --git a/include/mswsock.h b/include/mswsock.h
index 322ab20..5749e59 100644
--- a/include/mswsock.h
+++ b/include/mswsock.h
This should be a separate patch.

diff --git a/include/ws2ipdef.h b/include/ws2ipdef.h
index 11b3689..ec0b85a 100644
--- a/include/ws2ipdef.h
+++ b/include/ws2ipdef.h
Same here.


More information about the wine-devel mailing list