wsock32: Make EnumProtocols a wrapper around WSAEnumProtocols instead of forwarding directly.
Hans Leidekker
hans at codeweavers.com
Thu Oct 30 09:06:25 CDT 2008
Fixes http://bugs.winehq.org/show_bug.cgi?id=14731
-Hans
diff --git a/dlls/wsock32/protocol.c b/dlls/wsock32/protocol.c
index cd2cf71..85cb54b 100644
--- a/dlls/wsock32/protocol.c
+++ b/dlls/wsock32/protocol.c
@@ -2,6 +2,7 @@
* WSOCK32 specific functions
*
* Copyright (C) 2001 Stefan Leichter
+ * Copyright (C) 2008 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -36,9 +37,13 @@
#include "windef.h"
#include "winbase.h"
#include "winsock2.h"
+#include "nspapi.h"
+#include "wine/debug.h"
#include "wine/unicode.h"
+WINE_DEFAULT_DEBUG_CHANNEL(winsock);
+
/*****************************************************************************
* inet_network [WSOCK32.1100]
*/
@@ -62,3 +67,131 @@ struct netent * WINAPI WSOCK32_getnetbyname(const char *name)
return NULL;
#endif
}
+
+static DWORD map_service(DWORD wsaflags)
+{
+ DWORD flags = 0;
+
+ if (wsaflags & XP1_CONNECTIONLESS) flags |= XP_CONNECTIONLESS;
+ if (wsaflags & XP1_GUARANTEED_DELIVERY) flags |= XP_GUARANTEED_DELIVERY;
+ if (wsaflags & XP1_GUARANTEED_ORDER) flags |= XP_GUARANTEED_ORDER;
+ if (wsaflags & XP1_MESSAGE_ORIENTED) flags |= XP_MESSAGE_ORIENTED;
+ if (wsaflags & XP1_PSEUDO_STREAM) flags |= XP_PSEUDO_STREAM;
+ if (wsaflags & XP1_GRACEFUL_CLOSE) flags |= XP_GRACEFUL_CLOSE;
+ if (wsaflags & XP1_EXPEDITED_DATA) flags |= XP_EXPEDITED_DATA;
+ if (wsaflags & XP1_CONNECT_DATA) flags |= XP_CONNECT_DATA;
+ if (wsaflags & XP1_DISCONNECT_DATA) flags |= XP_DISCONNECT_DATA;
+ if (wsaflags & XP1_SUPPORT_BROADCAST) flags |= XP_SUPPORTS_BROADCAST;
+ if (wsaflags & XP1_SUPPORT_MULTIPOINT) flags |= XP_SUPPORTS_MULTICAST;
+ if (wsaflags & XP1_QOS_SUPPORTED) flags |= XP_BANDWITH_ALLOCATION;
+ if (wsaflags & XP1_PARTIAL_MESSAGE) flags |= XP_FRAGMENTATION;
+ return flags;
+}
+
+/*****************************************************************************
+ * EnumProtocolsA [WSOCK32.1111]
+ */
+INT WINAPI EnumProtocolsA(LPINT protocols, LPVOID buffer, LPDWORD buflen)
+{
+ INT ret;
+ DWORD size, string_size = WSAPROTOCOL_LEN + 1;
+
+ TRACE("%p, %p, %p\n", protocols, buffer, buflen);
+
+ if (!buflen) return SOCKET_ERROR;
+
+ size = 0;
+ ret = WSAEnumProtocolsA(protocols, NULL, &size);
+
+ if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS)
+ {
+ DWORD num_protocols = size / sizeof(WSAPROTOCOL_INFOA);
+ if (*buflen < num_protocols * (sizeof(PROTOCOL_INFOA) + string_size))
+ {
+ *buflen = num_protocols * (sizeof(PROTOCOL_INFOA) + string_size);
+ return SOCKET_ERROR;
+ }
+ if (buffer)
+ {
+ WSAPROTOCOL_INFOA *wsabuf;
+ PROTOCOL_INFOA *pi = buffer;
+ unsigned int i, string_offset;
+
+ if (!(wsabuf = HeapAlloc(GetProcessHeap(), 0, size))) return SOCKET_ERROR;
+
+ ret = WSAEnumProtocolsA(protocols, wsabuf, &size);
+ string_offset = ret * sizeof(PROTOCOL_INFOA);
+
+ for (i = 0; i < ret; i++)
+ {
+ pi[i].dwServiceFlags = map_service(wsabuf[i].dwServiceFlags1);
+ pi[i].iAddressFamily = wsabuf[i].iAddressFamily;
+ pi[i].iMaxSockAddr = wsabuf[i].iMaxSockAddr;
+ pi[i].iMinSockAddr = wsabuf[i].iMinSockAddr;
+ pi[i].iSocketType = wsabuf[i].iSocketType;
+ pi[i].iProtocol = wsabuf[i].iProtocol;
+ pi[i].dwMessageSize = wsabuf[i].dwMessageSize;
+
+ memcpy((char *)buffer + string_offset, wsabuf[i].szProtocol, string_size);
+ pi[i].lpProtocol = (char *)buffer + string_offset;
+ string_offset += string_size;
+ }
+ HeapFree(GetProcessHeap(), 0, wsabuf);
+ }
+ }
+ return ret;
+}
+
+/*****************************************************************************
+ * EnumProtocolsW [WSOCK32.1112]
+ */
+INT WINAPI EnumProtocolsW(LPINT protocols, LPVOID buffer, LPDWORD buflen)
+{
+ INT ret;
+ DWORD size, string_size = (WSAPROTOCOL_LEN + 1) * sizeof(WCHAR);
+
+ TRACE("%p, %p, %p\n", protocols, buffer, buflen);
+
+ if (!buflen) return SOCKET_ERROR;
+
+ size = 0;
+ ret = WSAEnumProtocolsW(protocols, NULL, &size);
+
+ if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS)
+ {
+ DWORD num_protocols = size / sizeof(WSAPROTOCOL_INFOW);
+ if (*buflen < num_protocols * (sizeof(PROTOCOL_INFOW) + string_size))
+ {
+ *buflen = num_protocols * (sizeof(PROTOCOL_INFOW) + string_size);
+ return SOCKET_ERROR;
+ }
+ if (buffer)
+ {
+ WSAPROTOCOL_INFOW *wsabuf;
+ PROTOCOL_INFOW *pi = buffer;
+ unsigned int i, string_offset;
+
+ if (!(wsabuf = HeapAlloc(GetProcessHeap(), 0, size))) return SOCKET_ERROR;
+
+ ret = WSAEnumProtocolsW(protocols, wsabuf, &size);
+ string_offset = ret * sizeof(PROTOCOL_INFOW);
+
+ for (i = 0; i < ret; i++)
+ {
+ pi[i].dwServiceFlags = map_service(wsabuf[i].dwServiceFlags1);
+ pi[i].iAddressFamily = wsabuf[i].iAddressFamily;
+ pi[i].iMaxSockAddr = wsabuf[i].iMaxSockAddr;
+ pi[i].iMinSockAddr = wsabuf[i].iMinSockAddr;
+ pi[i].iSocketType = wsabuf[i].iSocketType;
+ pi[i].iProtocol = wsabuf[i].iProtocol;
+ pi[i].dwMessageSize = wsabuf[i].dwMessageSize;
+
+ memcpy((char *)buffer + string_offset, wsabuf[i].szProtocol, string_size);
+ pi[i].lpProtocol = (WCHAR *)(char *)buffer + string_offset;
+ string_offset += string_size;
+ }
+ HeapFree(GetProcessHeap(), 0, wsabuf);
+ }
+ }
+ return ret;
+}
diff --git a/dlls/wsock32/wsock32.spec b/dlls/wsock32/wsock32.spec
index 9297984..db0b76d 100644
--- a/dlls/wsock32/wsock32.spec
+++ b/dlls/wsock32/wsock32.spec
@@ -62,8 +62,8 @@
1108 stdcall s_perror(str)
1109 stdcall GetAddressByNameA(long ptr str ptr long ptr ptr ptr ptr ptr)
1110 stdcall GetAddressByNameW(long ptr wstr ptr long ptr ptr ptr ptr ptr)
-1111 stdcall EnumProtocolsA(ptr ptr ptr) ws2_32.WSAEnumProtocolsA
-1112 stdcall EnumProtocolsW(ptr ptr ptr) ws2_32.WSAEnumProtocolsW
+1111 stdcall EnumProtocolsA(ptr ptr ptr)
+1112 stdcall EnumProtocolsW(ptr ptr ptr)
1113 stdcall GetTypeByNameA(str ptr)
1114 stdcall GetTypeByNameW(wstr ptr)
#1115 stub GetNameByTypeA
More information about the wine-patches
mailing list