Release 1.5.29.
[wine] / dlls / wsock32 / protocol.c
1 /*
2  * WSOCK32 specific functions
3  *
4  * Copyright (C) 2001 Stefan Leichter
5  * Copyright (C) 2008 Hans Leidekker
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define USE_WS_PREFIX
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
32 #endif
33 #ifdef HAVE_NETDB_H
34 #include <netdb.h>
35 #endif
36
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winsock2.h"
40 #include "nspapi.h"
41
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
46
47 /*****************************************************************************
48  *          inet_network       [WSOCK32.1100]
49  */
50 UINT WINAPI WSOCK32_inet_network(const char *cp)
51 {
52 #ifdef HAVE_INET_NETWORK
53     return inet_network(cp);
54 #else
55     return 0;
56 #endif
57 }
58
59 /*****************************************************************************
60  *          getnetbyname       [WSOCK32.1101]
61  */
62 struct netent * WINAPI WSOCK32_getnetbyname(const char *name)
63 {
64 #ifdef HAVE_GETNETBYNAME
65     return getnetbyname(name);
66 #else
67     return NULL;
68 #endif
69 }
70
71 static DWORD map_service(DWORD wsaflags)
72 {
73     DWORD flags = 0;
74
75     if (wsaflags & XP1_CONNECTIONLESS)      flags |= XP_CONNECTIONLESS;
76     if (wsaflags & XP1_GUARANTEED_DELIVERY) flags |= XP_GUARANTEED_DELIVERY;
77     if (wsaflags & XP1_GUARANTEED_ORDER)    flags |= XP_GUARANTEED_ORDER;
78     if (wsaflags & XP1_MESSAGE_ORIENTED)    flags |= XP_MESSAGE_ORIENTED;
79     if (wsaflags & XP1_PSEUDO_STREAM)       flags |= XP_PSEUDO_STREAM;
80     if (wsaflags & XP1_GRACEFUL_CLOSE)      flags |= XP_GRACEFUL_CLOSE;
81     if (wsaflags & XP1_EXPEDITED_DATA)      flags |= XP_EXPEDITED_DATA;
82     if (wsaflags & XP1_CONNECT_DATA)        flags |= XP_CONNECT_DATA;
83     if (wsaflags & XP1_DISCONNECT_DATA)     flags |= XP_DISCONNECT_DATA;
84     if (wsaflags & XP1_SUPPORT_BROADCAST)   flags |= XP_SUPPORTS_BROADCAST;
85     if (wsaflags & XP1_SUPPORT_MULTIPOINT)  flags |= XP_SUPPORTS_MULTICAST;
86     if (wsaflags & XP1_QOS_SUPPORTED)       flags |= XP_BANDWIDTH_ALLOCATION;
87     if (wsaflags & XP1_PARTIAL_MESSAGE)     flags |= XP_FRAGMENTATION;
88     return flags;
89 }
90
91 /*****************************************************************************
92  *          EnumProtocolsA       [WSOCK32.1111]
93  */
94 INT WINAPI EnumProtocolsA(LPINT protocols, LPVOID buffer, LPDWORD buflen)
95 {
96     INT ret;
97     DWORD size, string_size = WSAPROTOCOL_LEN + 1;
98
99     TRACE("%p, %p, %p\n", protocols, buffer, buflen);
100
101     if (!buflen) return SOCKET_ERROR;
102
103     size = 0;
104     ret = WSAEnumProtocolsA(protocols, NULL, &size);
105
106     if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS)
107     {
108         DWORD num_protocols = size / sizeof(WSAPROTOCOL_INFOA);
109         if (*buflen < num_protocols * (sizeof(PROTOCOL_INFOA) + string_size))
110         {
111             *buflen = num_protocols * (sizeof(PROTOCOL_INFOA) + string_size);
112             return SOCKET_ERROR;
113         }
114         if (buffer)
115         {
116             WSAPROTOCOL_INFOA *wsabuf;
117             PROTOCOL_INFOA *pi = buffer;
118             unsigned int string_offset;
119             INT i;
120
121             if (!(wsabuf = HeapAlloc(GetProcessHeap(), 0, size))) return SOCKET_ERROR;
122
123             ret = WSAEnumProtocolsA(protocols, wsabuf, &size);
124             string_offset = ret * sizeof(PROTOCOL_INFOA);
125
126             for (i = 0; i < ret; i++)
127             {
128                 pi[i].dwServiceFlags = map_service(wsabuf[i].dwServiceFlags1);
129                 pi[i].iAddressFamily = wsabuf[i].iAddressFamily;
130                 pi[i].iMaxSockAddr   = wsabuf[i].iMaxSockAddr;
131                 pi[i].iMinSockAddr   = wsabuf[i].iMinSockAddr;
132                 pi[i].iSocketType    = wsabuf[i].iSocketType;
133                 pi[i].iProtocol      = wsabuf[i].iProtocol;
134                 pi[i].dwMessageSize  = wsabuf[i].dwMessageSize;
135
136                 memcpy((char *)buffer + string_offset, wsabuf[i].szProtocol, string_size);
137                 pi[i].lpProtocol = (char *)buffer + string_offset;
138                 string_offset += string_size;
139             }
140             HeapFree(GetProcessHeap(), 0, wsabuf);
141         }
142     }
143     return ret;
144 }
145
146 /*****************************************************************************
147  *          EnumProtocolsW       [WSOCK32.1112]
148  */
149 INT WINAPI EnumProtocolsW(LPINT protocols, LPVOID buffer, LPDWORD buflen)
150 {
151     INT ret;
152     DWORD size, string_size = (WSAPROTOCOL_LEN + 1) * sizeof(WCHAR);
153
154     TRACE("%p, %p, %p\n", protocols, buffer, buflen);
155
156     if (!buflen) return SOCKET_ERROR;
157
158     size = 0;
159     ret = WSAEnumProtocolsW(protocols, NULL, &size);
160
161     if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS)
162     {
163         DWORD num_protocols = size / sizeof(WSAPROTOCOL_INFOW);
164         if (*buflen < num_protocols * (sizeof(PROTOCOL_INFOW) + string_size))
165         {
166             *buflen = num_protocols * (sizeof(PROTOCOL_INFOW) + string_size);
167             return SOCKET_ERROR;
168         }
169         if (buffer)
170         {
171             WSAPROTOCOL_INFOW *wsabuf;
172             PROTOCOL_INFOW *pi = buffer;
173             unsigned int string_offset;
174             INT i;
175
176             if (!(wsabuf = HeapAlloc(GetProcessHeap(), 0, size))) return SOCKET_ERROR;
177
178             ret = WSAEnumProtocolsW(protocols, wsabuf, &size);
179             string_offset = ret * sizeof(PROTOCOL_INFOW);
180
181             for (i = 0; i < ret; i++)
182             {
183                 pi[i].dwServiceFlags = map_service(wsabuf[i].dwServiceFlags1);
184                 pi[i].iAddressFamily = wsabuf[i].iAddressFamily;
185                 pi[i].iMaxSockAddr   = wsabuf[i].iMaxSockAddr;
186                 pi[i].iMinSockAddr   = wsabuf[i].iMinSockAddr;
187                 pi[i].iSocketType    = wsabuf[i].iSocketType;
188                 pi[i].iProtocol      = wsabuf[i].iProtocol;
189                 pi[i].dwMessageSize  = wsabuf[i].dwMessageSize;
190
191                 memcpy((char *)buffer + string_offset, wsabuf[i].szProtocol, string_size);
192                 pi[i].lpProtocol = (WCHAR *)(char *)buffer + string_offset;
193                 string_offset += string_size;
194             }
195             HeapFree(GetProcessHeap(), 0, wsabuf);
196         }
197     }
198     return ret;
199 }