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