198 lines
6.6 KiB
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;
|
|
}
|