Add support for display of dibs on MSB XServers.
[wine] / dlls / wsock32 / protocol.c
1 /*
2  * WSOCK32 specific functions
3  *
4  * Copyright (C) 2001 Stefan Leichter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /* All we need are a couple constants for EnumProtocols. Once it is
22  * moved to ws2_32 we may no longer need it
23  */
24 #define USE_WS_PREFIX
25
26 #include "config.h"
27
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_SOCKET_H
34 #include <sys/socket.h>
35 #endif
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
38 #endif
39 #ifdef HAVE_ARPA_INET_H
40 #include <arpa/inet.h>
41 #endif
42 #ifdef HAVE_NETDB_H
43 #include <netdb.h>
44 #endif
45
46 #include "windef.h"
47 #include "winbase.h"
48 #include "winnls.h"
49 #include "wtypes.h"
50 #include "nspapi.h"
51 #include "winsock2.h"
52 #include "wsipx.h"
53 #include "wshisotp.h"
54
55 #include "wine/unicode.h"
56 #include "wine/debug.h"
57
58 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
59
60 /* name of the protocols
61  */
62 static WCHAR NameIpx[]   = {'I', 'P', 'X', '\0'};
63 static WCHAR NameSpx[]   = {'S', 'P', 'X', '\0'};
64 static WCHAR NameSpxII[] = {'S', 'P', 'X', ' ', 'I', 'I', '\0'};
65 static WCHAR NameTcp[]   = {'T', 'C', 'P', '/', 'I', 'P', '\0'};
66 static WCHAR NameUdp[]   = {'U', 'D', 'P', '/', 'I', 'P', '\0'};
67
68 /*****************************************************************************
69  *          WSOCK32_EnterSingleProtocol [internal]
70  *
71  *    enters the protocol informations of one given protocol into the
72  *    given buffer. If the given buffer is too small only the required size for
73  *    the protocols are returned.
74  *
75  * RETURNS
76  *    The number of protocols entered into the buffer
77  *
78  * BUGS
79  *    - only implemented for IPX, SPX, SPXII, TCP, UDP
80  *    - there is no check that the operating system supports the returned
81  *      protocols
82  */
83 static INT WSOCK32_EnterSingleProtocol( INT iProtocol,
84                                         PROTOCOL_INFOA* lpBuffer,
85                                         LPDWORD lpSize, BOOL unicode)
86 { DWORD  dwLength = 0, dwOldSize = *lpSize;
87   INT    iAnz = 1;
88   WCHAR  *lpProtName = NULL;
89
90   *lpSize = sizeof( PROTOCOL_INFOA);
91   switch (iProtocol) {
92     case WS_IPPROTO_TCP :
93         dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameTcp)+1) :
94                                WideCharToMultiByte( CP_ACP, 0, NameTcp, -1,
95                                                     NULL, 0, NULL, NULL);
96       break;
97     case WS_IPPROTO_UDP :
98         dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameUdp)+1) :
99                                WideCharToMultiByte( CP_ACP, 0, NameUdp, -1,
100                                                     NULL, 0, NULL, NULL);
101       break;
102     case NSPROTO_IPX :
103         dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameIpx)+1) :
104                                WideCharToMultiByte( CP_ACP, 0, NameIpx, -1,
105                                                     NULL, 0, NULL, NULL);
106       break;
107     case NSPROTO_SPX :
108         dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameSpx)+1) :
109                                WideCharToMultiByte( CP_ACP, 0, NameSpx, -1,
110                                                     NULL, 0, NULL, NULL);
111       break;
112     case NSPROTO_SPXII :
113         dwLength = (unicode) ? sizeof(WCHAR) * (strlenW(NameSpxII)+1) :
114                                WideCharToMultiByte( CP_ACP, 0, NameSpxII, -1,
115                                                     NULL, 0, NULL, NULL);
116       break;
117     default:
118         *lpSize = 0;
119         if ((iProtocol == ISOPROTO_TP4) || (iProtocol == NSPROTO_SPX))
120           FIXME("Protocol <%s> not implemented\n",
121                 (iProtocol == ISOPROTO_TP4) ? "ISOPROTO_TP4" : "NSPROTO_SPX");
122         else
123           FIXME("unknown Protocol <0x%08x>\n", iProtocol);
124       break;
125   }
126   *lpSize += dwLength;
127
128   if ( !lpBuffer || !*lpSize || (*lpSize > dwOldSize))
129      return 0;
130
131   memset( lpBuffer, 0, dwOldSize);
132
133   lpBuffer->lpProtocol = (LPSTR) &lpBuffer[ iAnz];
134   lpBuffer->iProtocol  = iProtocol;
135
136   switch (iProtocol) {
137     case WS_IPPROTO_TCP :
138         lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_EXPEDITED_DATA     |
139                                    XP_GRACEFUL_CLOSE     | XP_GUARANTEED_ORDER   |
140                                    XP_GUARANTEED_DELIVERY;
141         lpBuffer->iAddressFamily = WS_AF_INET;
142         lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
143         lpBuffer->iMinSockAddr   = 0x10;  /* NT4 SP5 */
144         lpBuffer->iSocketType    = SOCK_STREAM;
145         lpBuffer->dwMessageSize  = 0;
146         lpProtName = NameTcp;
147       break;
148     case WS_IPPROTO_UDP :
149         lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_SUPPORTS_BROADCAST |
150                                    XP_SUPPORTS_MULTICAST | XP_MESSAGE_ORIENTED   |
151                                    XP_CONNECTIONLESS;
152         lpBuffer->iAddressFamily = WS_AF_INET;
153         lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
154         lpBuffer->iMinSockAddr   = 0x10;  /* NT4 SP5 */
155         lpBuffer->iSocketType    = SOCK_DGRAM;
156         lpBuffer->dwMessageSize  = 65457; /* NT4 SP5 */
157         lpProtName = NameUdp;
158       break;
159     case NSPROTO_IPX :
160         lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_SUPPORTS_BROADCAST |
161                                    XP_SUPPORTS_MULTICAST | XP_MESSAGE_ORIENTED   |
162                                    XP_CONNECTIONLESS;
163         lpBuffer->iAddressFamily = WS_AF_IPX;
164         lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
165         lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
166         lpBuffer->iSocketType    = SOCK_DGRAM;
167         lpBuffer->dwMessageSize  = 576;   /* NT4 SP5 */
168         lpProtName = NameIpx;
169       break;
170     case NSPROTO_SPX :
171         lpBuffer->dwServiceFlags = XP_FRAGMENTATION      |
172                                    XP_PSEUDO_STREAM      | XP_MESSAGE_ORIENTED   |
173                                    XP_GUARANTEED_ORDER   | XP_GUARANTEED_DELIVERY;
174         lpBuffer->iAddressFamily = WS_AF_IPX;
175         lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
176         lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
177         lpBuffer->iSocketType    = 5;
178         lpBuffer->dwMessageSize  = -1;    /* NT4 SP5 */
179         lpProtName = NameSpx;
180       break;
181     case NSPROTO_SPXII :
182         lpBuffer->dwServiceFlags = XP_FRAGMENTATION      | XP_GRACEFUL_CLOSE     |
183                                    XP_PSEUDO_STREAM      | XP_MESSAGE_ORIENTED   |
184                                    XP_GUARANTEED_ORDER   | XP_GUARANTEED_DELIVERY;
185         lpBuffer->iAddressFamily = WS_AF_IPX;
186         lpBuffer->iMaxSockAddr   = 0x10;  /* NT4 SP5 */
187         lpBuffer->iMinSockAddr   = 0x0e;  /* NT4 SP5 */
188         lpBuffer->iSocketType    = 5;
189         lpBuffer->dwMessageSize  = -1;    /* NT4 SP5 */
190         lpProtName = NameSpxII;
191       break;
192   }
193   if (unicode)
194     strcpyW( (LPWSTR)lpBuffer->lpProtocol, lpProtName);
195   else
196     WideCharToMultiByte( CP_ACP, 0, lpProtName, -1, lpBuffer->lpProtocol,
197                          dwOldSize - iAnz * sizeof( PROTOCOL_INFOA), NULL, NULL);
198
199   return iAnz;
200 }
201
202 /* FIXME: EnumProtocols should be moved to winsock2, and this should be
203  * implemented by calling out to WSAEnumProtocols. See:
204  * http://support.microsoft.com/support/kb/articles/Q129/3/15.asp
205  */
206 /*****************************************************************************
207  *          WSOCK32_EnumProtocol [internal]
208  *
209  *    Enters the information about installed protocols into a given buffer
210  *
211  * RETURNS
212  *    SOCKET_ERROR if the buffer is to small for the requested protocol infos
213  *    on success the number of protocols inside the buffer
214  *
215  * NOTE
216  *    NT4SP5 does not return SPX if lpiProtocols == NULL
217  *
218  * BUGS
219  *    - NT4SP5 returns in addition these list of NETBIOS protocols
220  *      (address family 17), each entry two times one for socket type 2 and 5
221  *
222  *      iProtocol   lpProtocol
223  *      0x80000000  \Device\NwlnkNb
224  *      0xfffffffa  \Device\NetBT_CBENT7
225  *      0xfffffffb  \Device\Nbf_CBENT7
226  *      0xfffffffc  \Device\NetBT_NdisWan5
227  *      0xfffffffd  \Device\NetBT_El9202
228  *      0xfffffffe  \Device\Nbf_El9202
229  *      0xffffffff  \Device\Nbf_NdisWan4
230  *
231  *    - there is no check that the operating system supports the returned
232  *      protocols
233  */
234 static INT WSOCK32_EnumProtocol( LPINT lpiProtocols, PROTOCOL_INFOA* lpBuffer,
235                                  LPDWORD lpdwLength, BOOL unicode)
236 { DWORD dwCurSize, dwOldSize = *lpdwLength, dwTemp;
237   INT   anz = 0, i;
238   INT   iLocal[] = { WS_IPPROTO_TCP, WS_IPPROTO_UDP, NSPROTO_IPX, NSPROTO_SPXII, 0};
239
240   if (!lpiProtocols) lpiProtocols = iLocal;
241
242   *lpdwLength = 0;
243   while ( *lpiProtocols )
244   { dwCurSize = 0;
245     WSOCK32_EnterSingleProtocol( *lpiProtocols, NULL, &dwCurSize, unicode);
246
247     if ( lpBuffer && dwCurSize && ((*lpdwLength + dwCurSize) <= dwOldSize))
248     { /* reserve the required space for the current protocol_info after the
249        * last protocol_info before the start of the string buffer and adjust
250        * the references into the string buffer
251        */
252       memmove( &((char*)&lpBuffer[ anz])[dwCurSize],
253                   &lpBuffer[ anz],
254                *lpdwLength - anz * sizeof( PROTOCOL_INFOA));
255       for (i=0; i < anz; i++)
256         lpBuffer[i].lpProtocol += dwCurSize;
257
258       dwTemp = dwCurSize;
259       anz += WSOCK32_EnterSingleProtocol( *lpiProtocols, &lpBuffer[anz],
260                                           &dwTemp, unicode);
261     }
262
263     *lpdwLength += dwCurSize;
264     lpiProtocols++;
265   }
266
267   if (dwOldSize < *lpdwLength) anz = SOCKET_ERROR;
268
269   return anz;
270 }
271
272 /*****************************************************************************
273  *          EnumProtocolsA       [WSOCK32.1111]
274  *
275  *    see function WSOCK32_EnumProtocol for RETURNS, BUGS
276  */
277 INT WINAPI EnumProtocolsA( LPINT lpiProtocols, LPVOID lpBuffer,
278                            LPDWORD lpdwLength)
279 {
280    return WSOCK32_EnumProtocol( lpiProtocols, (PROTOCOL_INFOA*) lpBuffer,
281                                 lpdwLength, FALSE);
282 }
283
284 /*****************************************************************************
285  *          EnumProtocolsW       [WSOCK32.1112]
286  *
287  *    see function WSOCK32_EnumProtocol for RETURNS, BUGS
288  */
289 INT WINAPI EnumProtocolsW( LPINT lpiProtocols, LPVOID lpBuffer,
290                            LPDWORD lpdwLength)
291 {
292    return WSOCK32_EnumProtocol( lpiProtocols, (PROTOCOL_INFOA*) lpBuffer,
293                                 lpdwLength, TRUE);
294 }
295
296 /*****************************************************************************
297  *          inet_network       [WSOCK32.1100]
298  */
299 UINT WINAPI WSOCK32_inet_network(const char *cp)
300 {
301 #ifdef HAVE_INET_NETWORK
302     return inet_network(cp);
303 #else
304     return 0;
305 #endif
306 }
307
308 /*****************************************************************************
309  *          getnetbyname       [WSOCK32.1101]
310  */
311 struct netent * WINAPI WSOCK32_getnetbyname(const char *name)
312 {
313 #ifdef HAVE_GETNETBYNAME
314     return getnetbyname(name);
315 #else
316     return NULL;
317 #endif
318 }