advapi32: Close hTemp on error (Coverity).
[wine] / dlls / ws2_32 / protocol.c
1 /*
2  * Protocol enumeration functions
3  *
4  * Copyright (C) 2001 Stefan Leichter
5  * Copyright (C) 2004 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 /*  02/11/2004
23  *  The protocol enumeration functions were verified to match Win2k versions
24  *  for these protocols: IPX, SPX, SPXII, TCP/IP and UDP/IP.
25  */
26
27 #include "config.h"
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <sys/types.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37 #ifdef HAVE_NETDB_H
38 #include <netdb.h>
39 #endif
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wtypes.h"
44 #include "nspapi.h"
45 #include "winsock2.h"
46 #include "wsipx.h"
47 #include "wshisotp.h"
48 #include "ws2spi.h"
49
50 #include "wine/unicode.h"
51 #include "wine/debug.h"
52
53 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
54
55 /* names of the protocols */
56 static const CHAR NameIpx[]   = "IPX";
57 static const CHAR NameSpx[]   = "SPX";
58 static const CHAR NameSpxII[] = "SPX II";
59 static const CHAR NameTcp[]   = "TCP/IP";
60 static const CHAR NameUdp[]   = "UDP/IP";
61
62 static const WCHAR NameIpxW[]   = {'I', 'P', 'X', '\0'};
63 static const WCHAR NameSpxW[]   = {'S', 'P', 'X', '\0'};
64 static const WCHAR NameSpxIIW[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'};
65 static const WCHAR NameTcpW[]   = {'T', 'C', 'P', '/', 'I', 'P', '\0'};
66 static const WCHAR NameUdpW[]   = {'U', 'D', 'P', '/', 'I', 'P', '\0'};
67
68 /* Taken from Win2k */
69 static const GUID ProviderIdIP = { 0xe70f1aa0, 0xab8b, 0x11cf,
70                                    { 0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
71 static const GUID ProviderIdIPX = { 0x11058240, 0xbe47, 0x11cf,
72                                     { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
73 static const GUID ProviderIdSPX = { 0x11058241, 0xbe47, 0x11cf,
74                                     { 0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 } };
75
76 /*****************************************************************************
77  *          WINSOCK_EnterSingleProtocolW [internal]
78  *
79  *    enters the protocol information of one given protocol into the given
80  *    buffer.
81  *
82  * RETURNS
83  *    1 if a protocol was entered into the buffer.
84  *    SOCKET_ERROR otherwise.
85  *
86  * BUGS
87  *    - only implemented for IPX, SPX, SPXII, TCP, UDP
88  *    - there is no check that the operating system supports the returned
89  *      protocols
90  */
91 static INT WINSOCK_EnterSingleProtocolW( INT protocol, WSAPROTOCOL_INFOW* info )
92 {
93     memset( info, 0, sizeof(WSAPROTOCOL_INFOW) );
94     info->iProtocol = protocol;
95
96     switch (protocol)
97     {
98     case WS_IPPROTO_TCP:
99         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_EXPEDITED_DATA |
100                                 XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
101                                 XP1_GUARANTEED_DELIVERY;
102         info->ProviderId = ProviderIdIP;
103         info->dwCatalogEntryId = 0x3e9;
104         info->ProtocolChain.ChainLen = 1;
105         info->iVersion = 2;
106         info->iAddressFamily = WS_AF_INET;
107         info->iMaxSockAddr = 0x10;
108         info->iMinSockAddr = 0x10;
109         info->iSocketType = WS_SOCK_STREAM;
110         strcpyW( info->szProtocol, NameTcpW );
111         break;
112
113     case WS_IPPROTO_UDP:
114         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
115                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
116                                 XP1_CONNECTIONLESS;
117         info->ProviderId = ProviderIdIP;
118         info->dwCatalogEntryId = 0x3ea;
119         info->ProtocolChain.ChainLen = 1;
120         info->iVersion = 2;
121         info->iAddressFamily = WS_AF_INET;
122         info->iMaxSockAddr = 0x10;
123         info->iMinSockAddr = 0x10;
124         info->iSocketType = WS_SOCK_DGRAM;
125         info->dwMessageSize = 0xffbb;
126         strcpyW( info->szProtocol, NameUdpW );
127         break;
128
129     case NSPROTO_IPX:
130         info->dwServiceFlags1 = XP1_PARTIAL_MESSAGE | XP1_SUPPORT_BROADCAST |
131                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
132                                 XP1_CONNECTIONLESS;
133         info->ProviderId = ProviderIdIPX;
134         info->dwCatalogEntryId = 0x406;
135         info->ProtocolChain.ChainLen = 1;
136         info->iVersion = 2;
137         info->iAddressFamily = WS_AF_IPX;
138         info->iMaxSockAddr = 0x10;
139         info->iMinSockAddr = 0x0e;
140         info->iSocketType = WS_SOCK_DGRAM;
141         info->iProtocolMaxOffset = 0xff;
142         info->dwMessageSize = 0x240;
143         strcpyW( info->szProtocol, NameIpxW );
144         break;
145
146     case NSPROTO_SPX:
147         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
148                                 XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
149                                 XP1_GUARANTEED_DELIVERY;
150         info->ProviderId = ProviderIdSPX;
151         info->dwCatalogEntryId = 0x407;
152         info->ProtocolChain.ChainLen = 1;
153         info->iVersion = 2;
154         info->iAddressFamily = WS_AF_IPX;
155         info->iMaxSockAddr = 0x10;
156         info->iMinSockAddr = 0x0e;
157         info->iSocketType = 5;
158         info->dwMessageSize = 0xffffffff;
159         strcpyW( info->szProtocol, NameSpxW );
160         break;
161
162     case NSPROTO_SPXII:
163         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
164                                 XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
165                                 XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
166         info->ProviderId = ProviderIdSPX;
167         info->dwCatalogEntryId = 0x409;
168         info->ProtocolChain.ChainLen = 1;
169         info->iVersion = 2;
170         info->iAddressFamily = WS_AF_IPX;
171         info->iMaxSockAddr = 0x10;
172         info->iMinSockAddr = 0x0e;
173         info->iSocketType = 5;
174         info->dwMessageSize = 0xffffffff;
175         strcpyW( info->szProtocol, NameSpxIIW );
176         break;
177
178     default:
179         if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
180             FIXME("Protocol <%s> not implemented\n",
181                   (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
182         else
183             FIXME("unknown Protocol <0x%08x>\n", protocol);
184         return SOCKET_ERROR;
185     }
186     return 1;
187 }
188
189 /*****************************************************************************
190  *          WINSOCK_EnterSingleProtocolA [internal]
191  *
192  *    see function WINSOCK_EnterSingleProtocolW
193  *
194  */
195 static INT WINSOCK_EnterSingleProtocolA( INT protocol, WSAPROTOCOL_INFOA* info )
196 {
197     memset( info, 0, sizeof(WSAPROTOCOL_INFOA) );
198     info->iProtocol = protocol;
199
200     switch (protocol)
201     {
202     case WS_IPPROTO_TCP:
203         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_EXPEDITED_DATA |
204                                 XP1_GRACEFUL_CLOSE | XP1_GUARANTEED_ORDER |
205                                 XP1_GUARANTEED_DELIVERY;
206         info->ProviderId = ProviderIdIP;
207         info->dwCatalogEntryId = 0x3e9;
208         info->ProtocolChain.ChainLen = 1;
209         info->iVersion = 2;
210         info->iAddressFamily = WS_AF_INET;
211         info->iMaxSockAddr = 0x10;
212         info->iMinSockAddr = 0x10;
213         info->iSocketType = WS_SOCK_STREAM;
214         strcpy( info->szProtocol, NameTcp );
215         break;
216
217     case WS_IPPROTO_UDP:
218         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
219                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
220                                 XP1_CONNECTIONLESS;
221         info->ProviderId = ProviderIdIP;
222         info->dwCatalogEntryId = 0x3ea;
223         info->ProtocolChain.ChainLen = 1;
224         info->iVersion = 2;
225         info->iAddressFamily = WS_AF_INET;
226         info->iMaxSockAddr = 0x10;
227         info->iMinSockAddr = 0x10;
228         info->iSocketType = WS_SOCK_DGRAM;
229         info->dwMessageSize = 0xffbb;
230         strcpy( info->szProtocol, NameUdp );
231         break;
232
233     case NSPROTO_IPX:
234         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_SUPPORT_BROADCAST |
235                                 XP1_SUPPORT_MULTIPOINT | XP1_MESSAGE_ORIENTED |
236                                 XP1_CONNECTIONLESS;
237         info->ProviderId = ProviderIdIPX;
238         info->dwCatalogEntryId = 0x406;
239         info->ProtocolChain.ChainLen = 1;
240         info->iVersion = 2;
241         info->iAddressFamily = WS_AF_IPX;
242         info->iMaxSockAddr = 0x10;
243         info->iMinSockAddr = 0x0e;
244         info->iSocketType = WS_SOCK_DGRAM;
245         info->iProtocolMaxOffset = 0xff;
246         info->dwMessageSize = 0x240;
247         strcpy( info->szProtocol, NameIpx );
248         break;
249
250     case NSPROTO_SPX:
251         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_PSEUDO_STREAM |
252                                 XP1_MESSAGE_ORIENTED | XP1_GUARANTEED_ORDER |
253                                 XP1_GUARANTEED_DELIVERY;
254         info->ProviderId = ProviderIdSPX;
255         info->dwCatalogEntryId = 0x407;
256         info->ProtocolChain.ChainLen = 1;
257         info->iVersion = 2;
258         info->iAddressFamily = WS_AF_IPX;
259         info->iMaxSockAddr = 0x10;
260         info->iMinSockAddr = 0x0e;
261         info->iSocketType = 5;
262         info->dwMessageSize = 0xffffffff;
263         strcpy( info->szProtocol, NameSpx );
264         break;
265
266     case NSPROTO_SPXII:
267         info->dwServiceFlags1 = XP1_IFS_HANDLES | XP1_GRACEFUL_CLOSE |
268                                 XP1_PSEUDO_STREAM | XP1_MESSAGE_ORIENTED |
269                                 XP1_GUARANTEED_ORDER | XP1_GUARANTEED_DELIVERY;
270         info->ProviderId = ProviderIdSPX;
271         info->dwCatalogEntryId = 0x409;
272         info->ProtocolChain.ChainLen = 1;
273         info->iVersion = 2;
274         info->iAddressFamily = WS_AF_IPX;
275         info->iMaxSockAddr = 0x10;
276         info->iMinSockAddr = 0x0e;
277         info->iSocketType = 5;
278         info->dwMessageSize = 0xffffffff;
279         strcpy( info->szProtocol, NameSpxII );
280         break;
281
282     default:
283         if ((protocol == ISOPROTO_TP4) || (protocol == NSPROTO_SPX))
284             FIXME("Protocol <%s> not implemented\n",
285                   (protocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
286         else
287             FIXME("unknown Protocol <0x%08x>\n", protocol);
288         return SOCKET_ERROR;
289     }
290     return 1;
291 }
292
293 /*****************************************************************************
294  *          WSAEnumProtocolsA       [WS2_32.@]
295  *
296  *    see function WSAEnumProtocolsW
297  */
298 INT WINAPI WSAEnumProtocolsA( LPINT protocols, LPWSAPROTOCOL_INFOA buffer, LPDWORD len )
299 {
300     INT i = 0;
301     DWORD size = 0;
302     INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
303
304     if (!protocols) protocols = local;
305
306     while (protocols[i]) i++;
307
308     size = i * sizeof(WSAPROTOCOL_INFOA);
309
310     if (*len < size || !buffer)
311     {
312         *len = size;
313         WSASetLastError(WSAENOBUFS);
314         return SOCKET_ERROR;
315     }
316
317     for (i = 0; protocols[i]; i++)
318     {
319         if (WINSOCK_EnterSingleProtocolA( protocols[i], &buffer[i] ) == SOCKET_ERROR)
320             return i;
321     }
322     return i;
323 }
324
325 /*****************************************************************************
326  *          WSAEnumProtocolsW       [WS2_32.@]
327  *
328  * Retrieves information about specified set of active network protocols.
329  *
330  * PARAMS
331  *  protocols [I]   Pointer to null-terminated array of protocol id's. NULL
332  *                  retrieves information on all available protocols.
333  *  buffer    [I]   Pointer to a buffer to be filled with WSAPROTOCOL_INFO
334  *                  structures.
335  *  len       [I/O] Pointer to a variable specifying buffer size. On output
336  *                  the variable holds the number of bytes needed when the
337  *                  specified size is too small.
338  *
339  * RETURNS
340  *  Success: number of WSAPROTOCOL_INFO structures in buffer.
341  *  Failure: SOCKET_ERROR
342  *
343  * NOTES
344  *  NT4SP5 does not return SPX if protocols == NULL
345  *
346  * BUGS
347  *  - NT4SP5 returns in addition these list of NETBIOS protocols
348  *    (address family 17), each entry two times one for socket type 2 and 5
349  *
350  *    iProtocol   szProtocol
351  *    0x80000000  \Device\NwlnkNb
352  *    0xfffffffa  \Device\NetBT_CBENT7
353  *    0xfffffffb  \Device\Nbf_CBENT7
354  *    0xfffffffc  \Device\NetBT_NdisWan5
355  *    0xfffffffd  \Device\NetBT_El9202
356  *    0xfffffffe  \Device\Nbf_El9202
357  *    0xffffffff  \Device\Nbf_NdisWan4
358  *
359  *  - there is no check that the operating system supports the returned
360  *    protocols
361  */
362 INT WINAPI WSAEnumProtocolsW( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len )
363 {
364     INT i = 0;
365     DWORD size = 0;
366     INT local[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPX, NSPROTO_SPXII, 0 };
367
368     if (!protocols) protocols = local;
369
370     while (protocols[i]) i++;
371
372     size = i * sizeof(WSAPROTOCOL_INFOW);
373
374     if (*len < size || !buffer)
375     {
376         *len = size;
377         WSASetLastError(WSAENOBUFS);
378         return SOCKET_ERROR;
379     }
380
381     for (i = 0; protocols[i]; i++)
382     {
383         if (WINSOCK_EnterSingleProtocolW( protocols[i], &buffer[i] ) == SOCKET_ERROR)
384             return i;
385     }
386     return i;
387 }
388
389 /*****************************************************************************
390  *          WSCEnumProtocols        [WS2_32.@]
391  *
392  * PARAMS
393  *  protocols [I]   Null-terminated array of iProtocol values.
394  *  buffer    [O]   Buffer of WSAPROTOCOL_INFOW structures.
395  *  len       [I/O] Size of buffer on input/output.
396  *  errno     [O]   Error code.
397  *
398  * RETURNS
399  *  Success: number of protocols to be reported on.
400  *  Failure: SOCKET_ERROR. error is in errno.
401  *
402  * BUGS
403  *  Doesn't supply info on layered protocols.
404  *
405  */
406 INT WINAPI WSCEnumProtocols( LPINT protocols, LPWSAPROTOCOL_INFOW buffer, LPDWORD len, LPINT err )
407 {
408     INT ret = WSAEnumProtocolsW( protocols, buffer, len );
409
410     if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
411
412     return ret;
413 }