wine/dlls/wsock32/protocol.c

198 lines
6.6 KiB
C

/*
* 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);
#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_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;
}