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