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