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