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