2 * 16-bit socket functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka
5 * Copyright (C) 2003 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
26 #include "wine/winbase16.h"
27 #include "wine/winsock16.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
33 static INT num_startup; /* reference counter */
34 static void *he_buffer;
35 static SEGPTR he_buffer_seg;
36 static void *se_buffer;
37 static SEGPTR se_buffer_seg;
38 static void *pe_buffer;
39 static SEGPTR pe_buffer_seg;
40 static SEGPTR dbuffer_seg;
42 extern int WINAPI WS_gethostname(char *name, int namelen);
44 static WS_fd_set *ws_fdset_16_to_32( const ws_fd_set16 *set16, WS_fd_set *set32 )
47 set32->fd_count = set16->fd_count;
48 for (i = 0; i < set32->fd_count; i++) set32->fd_array[i] = set16->fd_array[i];
52 static ws_fd_set16 *ws_fdset_32_to_16( const WS_fd_set *set32, ws_fd_set16 *set16 )
55 set16->fd_count = set32->fd_count;
56 for (i = 0; i < set16->fd_count; i++) set16->fd_array[i] = set32->fd_array[i];
60 static int list_size(char** l, int item_size)
66 j += (item_size) ? item_size : strlen(l[i]) + 1;
67 j += (i + 1) * sizeof(char*);
72 static int list_dup(char** l_src, SEGPTR base, int item_size)
75 char *ref = MapSL(base);
76 SEGPTR *l_to = (SEGPTR *)ref;
78 for (i = 0; l_src[i]; i++) ;
79 offset = (i + 1) * sizeof(char*);
80 for (i = 0; l_src[i]; i++)
82 int count = item_size ? item_size : strlen(l_src[i]) + 1;
83 memcpy( ref + offset, l_src[i], count );
84 l_to[i] = base + offset;
91 static SEGPTR get_buffer_he(int size)
96 if (he_len >= size ) return he_buffer_seg;
97 UnMapLS( he_buffer_seg );
98 HeapFree( GetProcessHeap(), 0, he_buffer );
100 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
101 he_buffer_seg = MapLS( he_buffer );
102 return he_buffer_seg;
105 static SEGPTR get_buffer_se(int size)
110 if (se_len >= size ) return se_buffer_seg;
111 UnMapLS( se_buffer_seg );
112 HeapFree( GetProcessHeap(), 0, se_buffer );
114 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
115 se_buffer_seg = MapLS( se_buffer );
116 return se_buffer_seg;
119 static SEGPTR get_buffer_pe(int size)
124 if (pe_len >= size ) return pe_buffer_seg;
125 UnMapLS( pe_buffer_seg );
126 HeapFree( GetProcessHeap(), 0, pe_buffer );
128 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
129 pe_buffer_seg = MapLS( pe_buffer );
130 return pe_buffer_seg;
133 /* duplicate hostent entry
134 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
135 * Ditto for protoent and servent.
137 static SEGPTR ws_hostent_32_to_16( const struct WS_hostent* he )
141 struct ws_hostent16 *p_to;
143 int size = (sizeof(*he) +
144 strlen(he->h_name) + 1 +
145 list_size(he->h_aliases, 0) +
146 list_size(he->h_addr_list, he->h_length));
148 base = get_buffer_he(size);
151 p_to->h_addrtype = he->h_addrtype;
152 p_to->h_length = he->h_length;
154 p = (char *)(p_to + 1);
155 p_to->h_name = base + (p - (char *)p_to);
156 strcpy(p, he->h_name);
159 p_to->h_aliases = base + (p - (char *)p_to);
160 p += list_dup(he->h_aliases, p_to->h_aliases, 0);
162 p_to->h_addr_list = base + (p - (char *)p_to);
163 list_dup(he->h_addr_list, p_to->h_addr_list, he->h_length);
168 static SEGPTR ws_protoent_32_to_16( const struct WS_protoent *pe )
172 struct ws_protoent16 *p_to;
174 int size = (sizeof(*pe) +
175 strlen(pe->p_name) + 1 +
176 list_size(pe->p_aliases, 0));
178 base = get_buffer_pe(size);
181 p_to->p_proto = pe->p_proto;
182 p = (char *)(p_to + 1);
184 p_to->p_name = base + (p - (char *)p_to);
185 strcpy(p, pe->p_name);
188 p_to->p_aliases = base + (p - (char *)p_to);
189 list_dup(pe->p_aliases, p_to->p_aliases, 0);
194 static SEGPTR ws_servent_32_to_16( const struct WS_servent *se )
198 struct ws_servent16 *p_to;
200 int size = (sizeof(*se) +
201 strlen(se->s_proto) + 1 +
202 strlen(se->s_name) + 1 +
203 list_size(se->s_aliases, 0));
205 base = get_buffer_se(size);
208 p_to->s_port = se->s_port;
209 p = (char *)(p_to + 1);
211 p_to->s_name = base + (p - (char *)p_to);
212 strcpy(p, se->s_name);
215 p_to->s_proto = base + (p - (char *)p_to);
216 strcpy(p, se->s_proto);
219 p_to->s_aliases = base + (p - (char *)p_to);
220 list_dup(se->s_aliases, p_to->s_aliases, 0);
226 /***********************************************************************
229 SOCKET16 WINAPI accept16(SOCKET16 s, struct WS_sockaddr* addr, INT16* addrlen16 )
231 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
232 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
233 if( addrlen16 ) *addrlen16 = addrlen32;
237 /***********************************************************************
240 INT16 WINAPI bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
242 return WS_bind( s, name, namelen );
245 /***********************************************************************
246 * closesocket (WINSOCK.3)
248 INT16 WINAPI closesocket16(SOCKET16 s)
250 return WS_closesocket(s);
253 /***********************************************************************
254 * connect (WINSOCK.4)
256 INT16 WINAPI connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
258 return WS_connect( s, name, namelen );
261 /***********************************************************************
262 * getpeername (WINSOCK.5)
264 INT16 WINAPI getpeername16(SOCKET16 s, struct WS_sockaddr *name, INT16 *namelen16)
266 INT namelen32 = *namelen16;
267 INT retVal = WS_getpeername( s, name, &namelen32 );
268 *namelen16 = namelen32;
272 /***********************************************************************
273 * getsockname (WINSOCK.6)
275 INT16 WINAPI getsockname16(SOCKET16 s, struct WS_sockaddr *name, INT16 *namelen16)
281 INT namelen32 = *namelen16;
282 retVal = WS_getsockname( s, name, &namelen32 );
283 *namelen16 = namelen32;
285 else retVal = SOCKET_ERROR;
289 /***********************************************************************
290 * getsockopt (WINSOCK.7)
292 INT16 WINAPI getsockopt16(SOCKET16 s, INT16 level, INT16 optname, char *optval, INT16 *optlen)
298 if( optlen ) optlen32 = *optlen; else p = NULL;
299 retVal = WS_getsockopt( s, (WORD)level, optname, optval, p );
300 if( optlen ) *optlen = optlen32;
304 /***********************************************************************
305 * inet_ntoa (WINSOCK.11)
307 SEGPTR WINAPI inet_ntoa16(struct WS_in_addr in)
310 if (!(retVal = WS_inet_ntoa( in ))) return 0;
311 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
315 /***********************************************************************
316 * ioctlsocket (WINSOCK.12)
318 INT16 WINAPI ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
320 return WS_ioctlsocket( s, cmd, argp );
323 /***********************************************************************
324 * listen (WINSOCK.13)
326 INT16 WINAPI listen16(SOCKET16 s, INT16 backlog)
328 return WS_listen( s, backlog );
331 /***********************************************************************
334 INT16 WINAPI recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
336 return WS_recv( s, buf, len, flags );
339 /***********************************************************************
340 * recvfrom (WINSOCK.17)
342 INT16 WINAPI recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
343 struct WS_sockaddr *from, INT16 *fromlen16)
347 INT fromlen32 = *fromlen16;
348 INT retVal = WS_recvfrom( s, buf, len, flags, from, &fromlen32 );
349 *fromlen16 = fromlen32;
352 else return WS_recvfrom( s, buf, len, flags, from, NULL );
355 /***********************************************************************
356 * select (WINSOCK.18)
358 INT16 WINAPI select16(INT16 nfds, ws_fd_set16 *ws_readfds,
359 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
360 struct WS_timeval* timeout)
362 WS_fd_set read_set, write_set, except_set;
363 WS_fd_set *pread_set = NULL, *pwrite_set = NULL, *pexcept_set = NULL;
366 if (ws_readfds) pread_set = ws_fdset_16_to_32( ws_readfds, &read_set );
367 if (ws_writefds) pwrite_set = ws_fdset_16_to_32( ws_writefds, &write_set );
368 if (ws_exceptfds) pexcept_set = ws_fdset_16_to_32( ws_exceptfds, &except_set );
369 /* struct timeval is the same for both 32- and 16-bit code */
370 ret = WS_select( nfds, pread_set, pwrite_set, pexcept_set, timeout );
371 if (ws_readfds) ws_fdset_32_to_16( &read_set, ws_readfds );
372 if (ws_writefds) ws_fdset_32_to_16( &write_set, ws_writefds );
373 if (ws_exceptfds) ws_fdset_32_to_16( &except_set, ws_exceptfds );
377 /***********************************************************************
380 INT16 WINAPI send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
382 return WS_send( s, buf, len, flags );
385 /***********************************************************************
386 * sendto (WINSOCK.20)
388 INT16 WINAPI sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
389 struct WS_sockaddr *to, INT16 tolen)
391 return WS_sendto( s, buf, len, flags, to, tolen );
394 /***********************************************************************
395 * setsockopt (WINSOCK.21)
397 INT16 WINAPI setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
398 char *optval, INT16 optlen)
400 if( !optval ) return SOCKET_ERROR;
401 return WS_setsockopt( s, (WORD)level, optname, optval, optlen );
404 /***********************************************************************
405 * shutdown (WINSOCK.22)
407 INT16 WINAPI shutdown16(SOCKET16 s, INT16 how)
409 return WS_shutdown( s, how );
412 /***********************************************************************
413 * socket (WINSOCK.23)
415 SOCKET16 WINAPI socket16(INT16 af, INT16 type, INT16 protocol)
417 return WS_socket( af, type, protocol );
420 /***********************************************************************
421 * gethostbyaddr (WINSOCK.51)
423 SEGPTR WINAPI gethostbyaddr16(const char *addr, INT16 len, INT16 type)
425 struct WS_hostent *he;
427 if (!(he = WS_gethostbyaddr( addr, len, type ))) return 0;
428 return ws_hostent_32_to_16( he );
431 /***********************************************************************
432 * gethostbyname (WINSOCK.52)
434 SEGPTR WINAPI gethostbyname16(const char *name)
436 struct WS_hostent *he;
438 if (!(he = WS_gethostbyname( name ))) return 0;
439 return ws_hostent_32_to_16( he );
442 /***********************************************************************
443 * getprotobyname (WINSOCK.53)
445 SEGPTR WINAPI getprotobyname16(const char *name)
447 struct WS_protoent *pe;
449 if (!(pe = WS_getprotobyname( name ))) return 0;
450 return ws_protoent_32_to_16( pe );
453 /***********************************************************************
454 * getprotobynumber (WINSOCK.54)
456 SEGPTR WINAPI getprotobynumber16(INT16 number)
458 struct WS_protoent *pe;
460 if (!(pe = WS_getprotobynumber( number ))) return 0;
461 return ws_protoent_32_to_16( pe );
464 /***********************************************************************
465 * getservbyname (WINSOCK.55)
467 SEGPTR WINAPI getservbyname16(const char *name, const char *proto)
469 struct WS_servent *se;
471 if (!(se = WS_getservbyname( name, proto ))) return 0;
472 return ws_servent_32_to_16( se );
475 /***********************************************************************
476 * getservbyport (WINSOCK.56)
478 SEGPTR WINAPI getservbyport16(INT16 port, const char *proto)
480 struct WS_servent *se;
482 if (!(se = WS_getservbyport( port, proto ))) return 0;
483 return ws_servent_32_to_16( se );
486 /***********************************************************************
487 * gethostname (WINSOCK.57)
489 INT16 WINAPI gethostname16(char *name, INT16 namelen)
491 return WS_gethostname(name, namelen);
494 /***********************************************************************
495 * WSAAsyncSelect (WINSOCK.101)
497 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
499 return WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
502 /***********************************************************************
503 * WSASetBlockingHook (WINSOCK.109)
505 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
507 /* FIXME: should deal with 16-bit proc */
508 return (FARPROC16)WSASetBlockingHook( (FARPROC)lpBlockFunc );
511 /***********************************************************************
512 * WSAUnhookBlockingHook (WINSOCK.110)
514 INT16 WINAPI WSAUnhookBlockingHook16(void)
516 return WSAUnhookBlockingHook();
519 /***********************************************************************
520 * WSASetLastError (WINSOCK.112)
522 void WINAPI WSASetLastError16(INT16 iError)
524 WSASetLastError(iError);
527 /***********************************************************************
528 * WSAStartup (WINSOCK.115)
530 * Create socket control struct, attach it to the global list and
531 * update a pointer in the task struct.
533 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
536 INT ret = WSAStartup( wVersionRequested, &data );
540 lpWSAData->wVersion = 0x0101;
541 lpWSAData->wHighVersion = 0x0101;
542 strcpy( lpWSAData->szDescription, data.szDescription );
543 strcpy( lpWSAData->szSystemStatus, data.szSystemStatus );
544 lpWSAData->iMaxSockets = data.iMaxSockets;
545 lpWSAData->iMaxUdpDg = data.iMaxUdpDg;
546 lpWSAData->lpVendorInfo = 0;
552 /***********************************************************************
553 * WSACleanup (WINSOCK.116)
555 INT WINAPI WSACleanup16(void)
561 /* delete scratch buffers */
562 UnMapLS( he_buffer_seg );
563 UnMapLS( se_buffer_seg );
564 UnMapLS( pe_buffer_seg );
565 UnMapLS( dbuffer_seg );
570 HeapFree( GetProcessHeap(), 0, he_buffer );
571 HeapFree( GetProcessHeap(), 0, se_buffer );
572 HeapFree( GetProcessHeap(), 0, pe_buffer );
582 /***********************************************************************
583 * __WSAFDIsSet (WINSOCK.151)
585 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
587 int i = set->fd_count;
589 TRACE("(%d,%p(%i))\n", s, set, i);
592 if (set->fd_array[i] == s) return 1;
596 /***********************************************************************
597 * WSARecvEx (WINSOCK.1107)
599 * See description for WSARecvEx()
601 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
603 FIXME("(WSARecvEx16) partial packet return value not set\n");
604 return recv16(s, buf, len, *flags);