| /* | |
| * 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 | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define USE_WS_PREFIX | |
| #include "config.h" | |
| #include <stdarg.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #ifdef HAVE_ARPA_INET_H | |
| #include <arpa/inet.h> | |
| #endif | |
| #ifdef HAVE_NETDB_H | |
| #include <netdb.h> | |
| #endif | |
| #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] | |
| */ | |
| UINT WINAPI WSOCK32_inet_network(const char *cp) | |
| { | |
| #ifdef HAVE_INET_NETWORK | |
| return inet_network(cp); | |
| #elif defined(HAVE_INET_ADDR) | |
| return ntohl( inet_addr( cp ) ); | |
| #else | |
| return 0; | |
| #endif | |
| } | |
| /***************************************************************************** | |
| * getnetbyname [WSOCK32.1101] | |
| */ | |
| struct netent * WINAPI WSOCK32_getnetbyname(const char *name) | |
| { | |
| #ifdef HAVE_GETNETBYNAME | |
| return getnetbyname(name); | |
| #else | |
| 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_BANDWIDTH_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 string_offset; | |
| INT i; | |
| 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 string_offset; | |
| INT i; | |
| 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; | |
| } |