ws2_32: Make winsock.dll into a stand-alone 16-bit module.
[wine] / dlls / winsock.dll16 / socket.c
1 /*
2  * 16-bit socket functions
3  *
4  * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka
5  * Copyright (C) 2003 Alexandre Julliard
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
24 #include "winsock2.h"
25 #include "wine/winbase16.h"
26 #include "winsock16.h"
27 #include "wownt32.h"
28 #include "winuser.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
32
33 struct async_query_header
34 {
35     HWND     hWnd;
36     UINT     uMsg;
37     SEGPTR   sbuf;
38     INT      sbuflen;
39     HANDLE16 handle;
40 };
41
42 struct async_query_gethostbyname
43 {
44     struct async_query_header query;
45     char *host_name;
46 };
47
48 struct async_query_gethostbyaddr
49 {
50     struct async_query_header query;
51     char *host_addr;
52     int   host_len;
53     int   host_type;
54 };
55
56 struct async_query_getprotobyname
57 {
58     struct async_query_header query;
59     char *proto_name;
60 };
61
62 struct async_query_getprotobynumber
63 {
64     struct async_query_header query;
65     int   proto_number;
66 };
67
68 struct async_query_getservbyname
69 {
70     struct async_query_header query;
71     char *serv_name;
72     char *serv_proto;
73 };
74
75 struct async_query_getservbyport
76 {
77     struct async_query_header query;
78     char *serv_proto;
79     int   serv_port;
80 };
81
82 static INT num_startup;  /* reference counter */
83 static void *he_buffer;
84 static SEGPTR he_buffer_seg;
85 static void *se_buffer;
86 static SEGPTR se_buffer_seg;
87 static void *pe_buffer;
88 static SEGPTR pe_buffer_seg;
89 static SEGPTR dbuffer_seg;
90
91 extern int WINAPI WS_gethostname(char *name, int namelen);
92
93 static fd_set *ws_fdset_16_to_32( const ws_fd_set16 *set16, fd_set *set32 )
94 {
95     UINT i;
96     set32->fd_count = set16->fd_count;
97     for (i = 0; i < set32->fd_count; i++) set32->fd_array[i] = set16->fd_array[i];
98     return set32;
99 }
100
101 static ws_fd_set16 *ws_fdset_32_to_16( const fd_set *set32, ws_fd_set16 *set16 )
102 {
103     UINT i;
104     set16->fd_count = set32->fd_count;
105     for (i = 0; i < set16->fd_count; i++) set16->fd_array[i] = set32->fd_array[i];
106     return set16;
107 }
108
109 static DWORD finish_query( struct async_query_header *query, LPARAM lparam )
110 {
111     PostMessageW( query->hWnd, query->uMsg, (WPARAM)query->handle, lparam );
112     HeapFree( GetProcessHeap(), 0, query );
113     return 0;
114 }
115
116 static int list_size(char** l, int item_size)
117 {
118     int i,j = 0;
119     if(l)
120     {
121         for(i=0;l[i];i++)
122             j += (item_size) ? item_size : strlen(l[i]) + 1;
123         j += (i + 1) * sizeof(char*);
124     }
125     return j;
126 }
127
128 static int list_dup(char** l_src, SEGPTR base, int item_size)
129 {
130     int i, offset;
131     char *ref = MapSL(base);
132     SEGPTR *l_to = (SEGPTR *)ref;
133
134     for (i = 0; l_src[i]; i++) ;
135     offset = (i + 1) * sizeof(char*);
136     for (i = 0; l_src[i]; i++)
137     {
138         int count = item_size ? item_size : strlen(l_src[i]) + 1;
139         memcpy( ref + offset, l_src[i], count );
140         l_to[i] = base + offset;
141         offset += count;
142     }
143     l_to[i] = 0;
144     return offset;
145 }
146
147 static SEGPTR get_buffer_he(int size)
148 {
149     static int he_len;
150     if (he_buffer)
151     {
152         if (he_len >= size ) return he_buffer_seg;
153         UnMapLS( he_buffer_seg );
154         HeapFree( GetProcessHeap(), 0, he_buffer );
155     }
156     he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
157     he_buffer_seg = MapLS( he_buffer );
158     return he_buffer_seg;
159 }
160
161 static SEGPTR get_buffer_se(int size)
162 {
163     static int se_len;
164     if (se_buffer)
165     {
166         if (se_len >= size ) return se_buffer_seg;
167         UnMapLS( se_buffer_seg );
168         HeapFree( GetProcessHeap(), 0, se_buffer );
169     }
170     se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
171     se_buffer_seg = MapLS( se_buffer );
172     return se_buffer_seg;
173 }
174
175 static SEGPTR get_buffer_pe(int size)
176 {
177     static int pe_len;
178     if (pe_buffer)
179     {
180         if (pe_len >= size ) return pe_buffer_seg;
181         UnMapLS( pe_buffer_seg );
182         HeapFree( GetProcessHeap(), 0, pe_buffer );
183     }
184     pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
185     pe_buffer_seg = MapLS( pe_buffer );
186     return pe_buffer_seg;
187 }
188
189 /* duplicate hostent entry
190  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
191  * Ditto for protoent and servent.
192  */
193 static SEGPTR ws_hostent_32_to_16( const struct hostent* he, SEGPTR base, int *buff_size )
194 {
195     char *p;
196     struct ws_hostent16 *p_to;
197
198     int size = (sizeof(*p_to) +
199                 strlen(he->h_name) + 1 +
200                 list_size(he->h_aliases, 0) +
201                 list_size(he->h_addr_list, he->h_length));
202
203     if (buff_size)
204     {
205         if (*buff_size < size)
206         {
207             *buff_size = size;
208             return 0;
209         }
210         *buff_size = size;
211     }
212     else base = get_buffer_he(size);
213     p_to = MapSL(base);
214
215     p_to->h_addrtype = he->h_addrtype;
216     p_to->h_length = he->h_length;
217
218     p = (char *)(p_to + 1);
219     p_to->h_name = base + (p - (char *)p_to);
220     strcpy(p, he->h_name);
221     p += strlen(p) + 1;
222
223     p_to->h_aliases = base + (p - (char *)p_to);
224     p += list_dup(he->h_aliases, p_to->h_aliases, 0);
225
226     p_to->h_addr_list = base + (p - (char *)p_to);
227     list_dup(he->h_addr_list, p_to->h_addr_list, he->h_length);
228
229     return base;
230 }
231
232 static SEGPTR ws_protoent_32_to_16( const struct protoent *pe, SEGPTR base, int *buff_size )
233 {
234     char *p;
235     struct ws_protoent16 *p_to;
236
237     int size = (sizeof(*p_to) +
238                 strlen(pe->p_name) + 1 +
239                 list_size(pe->p_aliases, 0));
240
241     if (buff_size)
242     {
243         if (*buff_size < size)
244         {
245             *buff_size = size;
246             return 0;
247         }
248         *buff_size = size;
249     }
250     else base = get_buffer_pe(size);
251     p_to = MapSL(base);
252
253     p_to->p_proto = pe->p_proto;
254     p = (char *)(p_to + 1);
255
256     p_to->p_name = base + (p - (char *)p_to);
257     strcpy(p, pe->p_name);
258     p += strlen(p) + 1;
259
260     p_to->p_aliases = base + (p - (char *)p_to);
261     list_dup(pe->p_aliases, p_to->p_aliases, 0);
262
263     return base;
264 }
265
266 static SEGPTR ws_servent_32_to_16( const struct servent *se, SEGPTR base, int *buff_size )
267 {
268     char *p;
269     struct ws_servent16 *p_to;
270
271     int size = (sizeof(*p_to) +
272                 strlen(se->s_proto) + 1 +
273                 strlen(se->s_name) + 1 +
274                 list_size(se->s_aliases, 0));
275
276     if (buff_size)
277     {
278         if (*buff_size < size)
279         {
280             *buff_size = size;
281             return 0;
282         }
283         *buff_size = size;
284     }
285     else base = get_buffer_se(size);
286     p_to = MapSL(base);
287
288     p_to->s_port = se->s_port;
289     p = (char *)(p_to + 1);
290
291     p_to->s_name = base + (p - (char *)p_to);
292     strcpy(p, se->s_name);
293     p += strlen(p) + 1;
294
295     p_to->s_proto = base + (p - (char *)p_to);
296     strcpy(p, se->s_proto);
297     p += strlen(p) + 1;
298
299     p_to->s_aliases = base + (p - (char *)p_to);
300     list_dup(se->s_aliases, p_to->s_aliases, 0);
301
302     return base;
303 }
304
305 static DWORD WINAPI async_gethostbyname(LPVOID arg)
306 {
307     struct async_query_gethostbyname *aq = arg;
308     int size = 0;
309     WORD fail = 0;
310     struct hostent *he;
311
312     if ((he = gethostbyname( aq->host_name )))
313     {
314         size = aq->query.sbuflen;
315         if (!ws_hostent_32_to_16( he, aq->query.sbuf, &size )) fail = WSAENOBUFS;
316     }
317     else fail = GetLastError();
318
319     return finish_query( &aq->query, MAKELPARAM( size, fail ));
320 }
321
322 static DWORD WINAPI async_gethostbyaddr(LPVOID arg)
323 {
324     struct async_query_gethostbyaddr *aq = arg;
325     int size = 0;
326     WORD fail = 0;
327     struct hostent *he;
328
329     if ((he = gethostbyaddr(aq->host_addr,aq->host_len,aq->host_type)))
330     {
331         size = aq->query.sbuflen;
332         if (!ws_hostent_32_to_16( he, aq->query.sbuf, &size )) fail = WSAENOBUFS;
333     }
334     else fail = GetLastError();
335
336     return finish_query( &aq->query, MAKELPARAM( size, fail ));
337 }
338
339 static DWORD WINAPI async_getprotobyname(LPVOID arg)
340 {
341     struct async_query_getprotobyname *aq = arg;
342     int size = 0;
343     WORD fail = 0;
344     struct protoent *pe;
345
346     if ((pe = getprotobyname(aq->proto_name)))
347     {
348         size = aq->query.sbuflen;
349         if (!ws_protoent_32_to_16( pe, aq->query.sbuf, &size )) fail = WSAENOBUFS;
350     }
351     else fail = GetLastError();
352
353     return finish_query( &aq->query, MAKELPARAM( size, fail ));
354 }
355
356 static DWORD WINAPI async_getprotobynumber(LPVOID arg)
357 {
358     struct async_query_getprotobynumber *aq = arg;
359     int size = 0;
360     WORD fail = 0;
361     struct protoent *pe;
362
363     if ((pe = getprotobynumber(aq->proto_number)))
364     {
365         size = aq->query.sbuflen;
366         if (!ws_protoent_32_to_16( pe, aq->query.sbuf, &size )) fail = WSAENOBUFS;
367     }
368     else fail = GetLastError();
369
370     return finish_query( &aq->query, MAKELPARAM( size, fail ));
371 }
372
373 static DWORD WINAPI async_getservbyname(LPVOID arg)
374 {
375     struct async_query_getservbyname *aq = arg;
376     int size = 0;
377     WORD fail = 0;
378     struct servent *se;
379
380     if ((se = getservbyname(aq->serv_name,aq->serv_proto)))
381     {
382         size = aq->query.sbuflen;
383         if (!ws_servent_32_to_16( se, aq->query.sbuf, &size )) fail = WSAENOBUFS;
384     }
385     else fail = GetLastError();
386
387     return finish_query( &aq->query, MAKELPARAM( size, fail ));
388 }
389
390 static DWORD WINAPI async_getservbyport(LPVOID arg)
391 {
392     struct async_query_getservbyport *aq = arg;
393     int size = 0;
394     WORD fail = 0;
395     struct servent *se;
396
397     if ((se = getservbyport(aq->serv_port,aq->serv_proto)))
398     {
399         size = aq->query.sbuflen;
400         if (!ws_servent_32_to_16( se, aq->query.sbuf, &size )) fail = WSAENOBUFS;
401     }
402     else fail = GetLastError();
403
404     return finish_query( &aq->query, MAKELPARAM( size, fail ));
405 }
406
407 /****************************************************************************
408  * The main async help function.
409  *
410  * It either starts a thread or just calls the function directly for platforms
411  * with no thread support. This relies on the fact that PostMessage() does
412  * not actually call the windowproc before the function returns.
413  */
414 static HANDLE16 run_query( HWND16 hWnd, UINT uMsg, LPTHREAD_START_ROUTINE func,
415                            struct async_query_header *query, SEGPTR sbuf, INT sbuflen )
416 {
417     static LONG next_handle = 0xdead;
418     HANDLE thread;
419     ULONG handle = LOWORD( InterlockedIncrement( &next_handle ));
420
421     /* avoid handle 0 */
422     while (!handle) handle = LOWORD( InterlockedIncrement( &next_handle ));
423
424     query->hWnd    = HWND_32(hWnd);
425     query->uMsg    = uMsg;
426     query->handle  = handle;
427     query->sbuf    = sbuf;
428     query->sbuflen = sbuflen;
429
430     thread = CreateThread( NULL, 0, func, query, 0, NULL );
431     if (!thread)
432     {
433         SetLastError( WSAEWOULDBLOCK );
434         return 0;
435     }
436     CloseHandle( thread );
437     return handle;
438 }
439
440 /***********************************************************************
441  *              accept          (WINSOCK.1)
442  */
443 SOCKET16 WINAPI accept16(SOCKET16 s, struct sockaddr* addr, INT16* addrlen16 )
444 {
445     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
446     SOCKET retSocket = accept( s, addr, &addrlen32 );
447     if( addrlen16 ) *addrlen16 = addrlen32;
448     return retSocket;
449 }
450
451 /***********************************************************************
452  *              bind                    (WINSOCK.2)
453  */
454 INT16 WINAPI bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
455 {
456     return bind( s, name, namelen );
457 }
458
459 /***********************************************************************
460  *              closesocket           (WINSOCK.3)
461  */
462 INT16 WINAPI closesocket16(SOCKET16 s)
463 {
464     return closesocket(s);
465 }
466
467 /***********************************************************************
468  *              connect               (WINSOCK.4)
469  */
470 INT16 WINAPI connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
471 {
472     return connect( s, name, namelen );
473 }
474
475 /***********************************************************************
476  *              getpeername             (WINSOCK.5)
477  */
478 INT16 WINAPI getpeername16(SOCKET16 s, struct sockaddr *name, INT16 *namelen16)
479 {
480     INT namelen32 = *namelen16;
481     INT retVal = getpeername( s, name, &namelen32 );
482    *namelen16 = namelen32;
483     return retVal;
484 }
485
486 /***********************************************************************
487  *              getsockname             (WINSOCK.6)
488  */
489 INT16 WINAPI getsockname16(SOCKET16 s, struct sockaddr *name, INT16 *namelen16)
490 {
491     INT retVal;
492
493     if( namelen16 )
494     {
495         INT namelen32 = *namelen16;
496         retVal = getsockname( s, name, &namelen32 );
497        *namelen16 = namelen32;
498     }
499     else retVal = SOCKET_ERROR;
500     return retVal;
501 }
502
503 /***********************************************************************
504  *              getsockopt              (WINSOCK.7)
505  */
506 INT16 WINAPI getsockopt16(SOCKET16 s, INT16 level, INT16 optname, char *optval, INT16 *optlen)
507 {
508     INT optlen32;
509     INT *p = &optlen32;
510     INT retVal;
511
512     if( optlen ) optlen32 = *optlen; else p = NULL;
513     retVal = getsockopt( s, (WORD)level, optname, optval, p );
514     if( optlen ) *optlen = optlen32;
515     return retVal;
516 }
517
518 /***********************************************************************
519  *              htonl                   (WINSOCK.8)
520  */
521 u_long WINAPI htonl16(u_long hostlong)
522 {
523     return htonl(hostlong);
524 }
525
526
527 /***********************************************************************
528  *              htons                   (WINSOCK.9)
529  */
530 u_short WINAPI htons16(u_short hostshort)
531 {
532     return htons(hostshort);
533 }
534
535 /***********************************************************************
536  *              inet_addr               (WINSOCK.10)
537  */
538 u_long WINAPI inet_addr16(const char *cp)
539 {
540     if (!cp) return INADDR_NONE;
541     return inet_addr(cp);
542 }
543
544
545 /***********************************************************************
546  *              inet_ntoa               (WINSOCK.11)
547  */
548 SEGPTR WINAPI inet_ntoa16(struct in_addr in)
549 {
550     char* retVal;
551     if (!(retVal = inet_ntoa( in ))) return 0;
552     if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
553     return dbuffer_seg;
554 }
555
556 /***********************************************************************
557  *              ioctlsocket           (WINSOCK.12)
558  */
559 INT16 WINAPI ioctlsocket16(SOCKET16 s, LONG cmd, u_long *argp)
560 {
561     return ioctlsocket( s, cmd, argp );
562 }
563
564 /***********************************************************************
565  *              listen          (WINSOCK.13)
566  */
567 INT16 WINAPI listen16(SOCKET16 s, INT16 backlog)
568 {
569     return listen( s, backlog );
570 }
571
572 /***********************************************************************
573  *              ntohl                   (WINSOCK.14)
574  */
575 u_long WINAPI ntohl16(u_long netlong)
576 {
577     return ntohl(netlong);
578 }
579
580
581 /***********************************************************************
582  *              ntohs                   (WINSOCK.15)
583  */
584 u_short WINAPI ntohs16(u_short netshort)
585 {
586     return ntohs(netshort);
587 }
588
589 /***********************************************************************
590  *              recv                    (WINSOCK.16)
591  */
592 INT16 WINAPI recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
593 {
594     return recv( s, buf, len, flags );
595 }
596
597 /***********************************************************************
598  *              recvfrom                (WINSOCK.17)
599  */
600 INT16 WINAPI recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
601                         struct sockaddr *from, INT16 *fromlen16)
602 {
603     if (fromlen16)
604     {
605         INT fromlen32 = *fromlen16;
606         INT retVal = recvfrom( s, buf, len, flags, from, &fromlen32 );
607         *fromlen16 = fromlen32;
608         return retVal;
609     }
610     else return recvfrom( s, buf, len, flags, from, NULL );
611 }
612
613 /***********************************************************************
614  *              select                  (WINSOCK.18)
615  */
616 INT16 WINAPI select16(INT16 nfds, ws_fd_set16 *ws_readfds,
617                       ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
618                       struct timeval* timeout)
619 {
620     fd_set read_set, write_set, except_set;
621     fd_set *pread_set = NULL, *pwrite_set = NULL, *pexcept_set = NULL;
622     int ret;
623
624     if (ws_readfds) pread_set = ws_fdset_16_to_32( ws_readfds, &read_set );
625     if (ws_writefds) pwrite_set = ws_fdset_16_to_32( ws_writefds, &write_set );
626     if (ws_exceptfds) pexcept_set = ws_fdset_16_to_32( ws_exceptfds, &except_set );
627     /* struct timeval is the same for both 32- and 16-bit code */
628     ret = select( nfds, pread_set, pwrite_set, pexcept_set, timeout );
629     if (ws_readfds) ws_fdset_32_to_16( &read_set, ws_readfds );
630     if (ws_writefds) ws_fdset_32_to_16( &write_set, ws_writefds );
631     if (ws_exceptfds) ws_fdset_32_to_16( &except_set, ws_exceptfds );
632     return ret;
633 }
634
635 /***********************************************************************
636  *              send                    (WINSOCK.19)
637  */
638 INT16 WINAPI send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
639 {
640     return send( s, buf, len, flags );
641 }
642
643 /***********************************************************************
644  *              sendto          (WINSOCK.20)
645  */
646 INT16 WINAPI sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
647                       struct sockaddr *to, INT16 tolen)
648 {
649     return sendto( s, buf, len, flags, to, tolen );
650 }
651
652 /***********************************************************************
653  *              setsockopt              (WINSOCK.21)
654  */
655 INT16 WINAPI setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
656                           char *optval, INT16 optlen)
657 {
658     if( !optval ) return SOCKET_ERROR;
659     return setsockopt( s, (WORD)level, optname, optval, optlen );
660 }
661
662 /***********************************************************************
663  *              shutdown                (WINSOCK.22)
664  */
665 INT16 WINAPI shutdown16(SOCKET16 s, INT16 how)
666 {
667     return shutdown( s, how );
668 }
669
670 /***********************************************************************
671  *              socket          (WINSOCK.23)
672  */
673 SOCKET16 WINAPI socket16(INT16 af, INT16 type, INT16 protocol)
674 {
675     return socket( af, type, protocol );
676 }
677
678 /***********************************************************************
679  *              gethostbyaddr           (WINSOCK.51)
680  */
681 SEGPTR WINAPI gethostbyaddr16(const char *addr, INT16 len, INT16 type)
682 {
683     struct hostent *he;
684
685     if (!(he = gethostbyaddr( addr, len, type ))) return 0;
686     return ws_hostent_32_to_16( he, 0, NULL );
687 }
688
689 /***********************************************************************
690  *              gethostbyname           (WINSOCK.52)
691  */
692 SEGPTR WINAPI gethostbyname16(const char *name)
693 {
694     struct hostent *he;
695
696     if (!(he = gethostbyname( name ))) return 0;
697     return ws_hostent_32_to_16( he, 0, NULL );
698 }
699
700 /***********************************************************************
701  *              getprotobyname          (WINSOCK.53)
702  */
703 SEGPTR WINAPI getprotobyname16(const char *name)
704 {
705     struct protoent *pe;
706
707     if (!(pe = getprotobyname( name ))) return 0;
708     return ws_protoent_32_to_16( pe, 0, NULL );
709 }
710
711 /***********************************************************************
712  *              getprotobynumber        (WINSOCK.54)
713  */
714 SEGPTR WINAPI getprotobynumber16(INT16 number)
715 {
716     struct protoent *pe;
717
718     if (!(pe = getprotobynumber( number ))) return 0;
719     return ws_protoent_32_to_16( pe, 0, NULL );
720 }
721
722 /***********************************************************************
723  *              getservbyname           (WINSOCK.55)
724  */
725 SEGPTR WINAPI getservbyname16(const char *name, const char *proto)
726 {
727     struct servent *se;
728
729     if (!(se = getservbyname( name, proto ))) return 0;
730     return ws_servent_32_to_16( se, 0, NULL );
731 }
732
733 /***********************************************************************
734  *              getservbyport           (WINSOCK.56)
735  */
736 SEGPTR WINAPI getservbyport16(INT16 port, const char *proto)
737 {
738     struct servent *se;
739
740     if (!(se = getservbyport( port, proto ))) return 0;
741     return ws_servent_32_to_16( se, 0, NULL );
742 }
743
744 /***********************************************************************
745  *              gethostname           (WINSOCK.57)
746  */
747 INT16 WINAPI gethostname16(char *name, INT16 namelen)
748 {
749     extern int WINAPI gethostname(char *name, INT namelen);
750     return gethostname(name, namelen);
751 }
752
753 /***********************************************************************
754  *      WSAAsyncSelect          (WINSOCK.101)
755  */
756 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
757 {
758     return WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
759 }
760
761 /***********************************************************************
762  *       WSAAsyncGetHostByAddr  (WINSOCK.102)
763  */
764 HANDLE16 WINAPI WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
765                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
766 {
767     struct async_query_gethostbyaddr *aq;
768
769     TRACE("hwnd %04x, msg %04x, addr %p[%i]\n", hWnd, uMsg, addr, len );
770
771     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) + len )))
772     {
773         SetLastError( WSAEWOULDBLOCK );
774         return 0;
775     }
776     aq->host_addr = (char *)(aq + 1);
777     aq->host_len  = len;
778     aq->host_type = type;
779     memcpy( aq->host_addr, addr, len );
780     return run_query( hWnd, uMsg, async_gethostbyaddr, &aq->query, sbuf, buflen );
781 }
782
783 /***********************************************************************
784  *       WSAAsyncGetHostByName  (WINSOCK.103)
785  */
786 HANDLE16 WINAPI WSAAsyncGetHostByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
787                                       SEGPTR sbuf, INT16 buflen)
788 {
789     struct async_query_gethostbyname *aq;
790     unsigned int len = strlen(name) + 1;
791
792     TRACE("hwnd %04x, msg %04x, host %s, buffer %i\n", hWnd, uMsg, debugstr_a(name), buflen );
793
794     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) + len )))
795     {
796         SetLastError( WSAEWOULDBLOCK );
797         return 0;
798     }
799     aq->host_name = (char *)(aq + 1);
800     strcpy( aq->host_name, name );
801     return run_query( hWnd, uMsg, async_gethostbyname, &aq->query, sbuf, buflen );
802 }
803
804 /***********************************************************************
805  *       WSAAsyncGetProtoByNumber       (WINSOCK.104)
806  */
807 HANDLE16 WINAPI WSAAsyncGetProtoByNumber16(HWND16 hWnd,UINT16 uMsg,INT16 number,
808                                            SEGPTR sbuf, INT16 buflen)
809 {
810     struct async_query_getprotobynumber *aq;
811
812     TRACE("hwnd %04x, msg %04x, num %i\n", hWnd, uMsg, number );
813
814     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) )))
815     {
816         SetLastError( WSAEWOULDBLOCK );
817         return 0;
818     }
819     aq->proto_number = number;
820     return run_query( hWnd, uMsg, async_getprotobynumber, &aq->query, sbuf, buflen );
821 }
822
823 /***********************************************************************
824  *       WSAAsyncGetProtoByName (WINSOCK.105)
825  */
826 HANDLE16 WINAPI WSAAsyncGetProtoByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
827                                          SEGPTR sbuf, INT16 buflen)
828 {
829     struct async_query_getprotobyname *aq;
830     unsigned int len = strlen(name) + 1;
831
832     TRACE("hwnd %04x, msg %04x, proto %s, buffer %i\n", hWnd, uMsg, debugstr_a(name), buflen );
833
834     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) + len )))
835     {
836         SetLastError( WSAEWOULDBLOCK );
837         return 0;
838     }
839     aq->proto_name = (char *)(aq + 1);
840     strcpy( aq->proto_name, name );
841     return run_query( hWnd, uMsg, async_getprotobyname, &aq->query, sbuf, buflen );
842 }
843
844 /***********************************************************************
845  *       WSAAsyncGetServByPort  (WINSOCK.106)
846  */
847 HANDLE16 WINAPI WSAAsyncGetServByPort16(HWND16 hWnd, UINT16 uMsg, INT16 port,
848                                         LPCSTR proto, SEGPTR sbuf, INT16 buflen)
849 {
850     struct async_query_getservbyport *aq;
851     unsigned int len = strlen(proto) + 1;
852
853     TRACE("hwnd %04x, msg %04x, port %i, proto %s\n", hWnd, uMsg, port, debugstr_a(proto));
854
855     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) + len )))
856     {
857         SetLastError( WSAEWOULDBLOCK );
858         return 0;
859     }
860     aq->serv_proto = (char *)(aq + 1);
861     aq->serv_port  = port;
862     strcpy( aq->serv_proto, proto );
863     return run_query( hWnd, uMsg, async_getservbyport, &aq->query, sbuf, buflen );
864 }
865
866 /***********************************************************************
867  *       WSAAsyncGetServByName  (WINSOCK.107)
868  */
869 HANDLE16 WINAPI WSAAsyncGetServByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
870                                         LPCSTR proto, SEGPTR sbuf, INT16 buflen)
871 {
872     struct async_query_getservbyname *aq;
873     unsigned int len1 = strlen(name) + 1;
874     unsigned int len2 = strlen(proto) + 1;
875
876     TRACE("hwnd %04x, msg %04x, name %s, proto %s\n", hWnd, uMsg, debugstr_a(name), debugstr_a(proto));
877
878     if (!(aq = HeapAlloc( GetProcessHeap(), 0, sizeof(*aq) + len1 + len2 )))
879     {
880         SetLastError( WSAEWOULDBLOCK );
881         return 0;
882     }
883     aq->serv_name  = (char *)(aq + 1);
884     aq->serv_proto = aq->serv_name + len1;
885     strcpy( aq->serv_name, name );
886     strcpy( aq->serv_proto, proto );
887     return run_query( hWnd, uMsg, async_getservbyname, &aq->query, sbuf, buflen );
888 }
889
890 /***********************************************************************
891  *       WSACancelAsyncRequest  (WINSOCK.108)
892  */
893 INT16 WINAPI WSACancelAsyncRequest16(HANDLE16 hAsyncTaskHandle)
894 {
895     FIXME("(%04x),stub\n", hAsyncTaskHandle);
896     return 0;
897 }
898
899 /***********************************************************************
900  *      WSASetBlockingHook              (WINSOCK.109)
901  */
902 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
903 {
904     /* FIXME: should deal with 16-bit proc */
905     return (FARPROC16)WSASetBlockingHook( (FARPROC)lpBlockFunc );
906 }
907
908 /***********************************************************************
909  *      WSAUnhookBlockingHook   (WINSOCK.110)
910  */
911 INT16 WINAPI WSAUnhookBlockingHook16(void)
912 {
913     return WSAUnhookBlockingHook();
914 }
915
916 /***********************************************************************
917  *      WSAGetLastError         (WINSOCK.111)
918  */
919 INT WINAPI WSAGetLastError16(void)
920 {
921     return WSAGetLastError();
922 }
923
924 /***********************************************************************
925  *      WSASetLastError         (WINSOCK.112)
926  */
927 void WINAPI WSASetLastError16(INT16 iError)
928 {
929     WSASetLastError(iError);
930 }
931
932 /***********************************************************************
933  *      WSACancelBlockingCall           (WINSOCK.113)
934  */
935 INT WINAPI WSACancelBlockingCall16(void)
936 {
937     return WSACancelBlockingCall();
938 }
939
940 /***********************************************************************
941  *      WSAIsBlocking                   (WINSOCK.114)
942  */
943 BOOL WINAPI WSAIsBlocking16(void)
944 {
945     return WSAIsBlocking();
946 }
947
948 /***********************************************************************
949  *      WSAStartup                      (WINSOCK.115)
950  *
951  * Create socket control struct, attach it to the global list and
952  * update a pointer in the task struct.
953  */
954 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
955 {
956     WSADATA data;
957     INT ret = WSAStartup( wVersionRequested, &data );
958
959     if (!ret)
960     {
961         lpWSAData->wVersion     = 0x0101;
962         lpWSAData->wHighVersion = 0x0101;
963         strcpy( lpWSAData->szDescription, data.szDescription );
964         strcpy( lpWSAData->szSystemStatus, data.szSystemStatus );
965         lpWSAData->iMaxSockets = data.iMaxSockets;
966         lpWSAData->iMaxUdpDg = data.iMaxUdpDg;
967         lpWSAData->lpVendorInfo = 0;
968         num_startup++;
969    }
970     return ret;
971 }
972
973 /***********************************************************************
974  *      WSACleanup                      (WINSOCK.116)
975  */
976 INT WINAPI WSACleanup16(void)
977 {
978     if (num_startup)
979     {
980         if (!--num_startup)
981         {
982             /* delete scratch buffers */
983             UnMapLS( he_buffer_seg );
984             UnMapLS( se_buffer_seg );
985             UnMapLS( pe_buffer_seg );
986             UnMapLS( dbuffer_seg );
987             he_buffer_seg = 0;
988             se_buffer_seg = 0;
989             pe_buffer_seg = 0;
990             dbuffer_seg = 0;
991             HeapFree( GetProcessHeap(), 0, he_buffer );
992             HeapFree( GetProcessHeap(), 0, se_buffer );
993             HeapFree( GetProcessHeap(), 0, pe_buffer );
994             he_buffer = NULL;
995             se_buffer = NULL;
996             pe_buffer = NULL;
997         }
998     }
999     return WSACleanup();
1000 }
1001
1002
1003 /***********************************************************************
1004  *      __WSAFDIsSet                    (WINSOCK.151)
1005  */
1006 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
1007 {
1008   int i = set->fd_count;
1009
1010   TRACE("(%d,%p(%i))\n", s, set, i);
1011
1012   while (i--)
1013       if (set->fd_array[i] == s) return 1;
1014   return 0;
1015 }
1016
1017 /***********************************************************************
1018  *              WSARecvEx                       (WINSOCK.1107)
1019  *
1020  * See description for WSARecvEx()
1021  */
1022 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
1023 {
1024     FIXME("(WSARecvEx16) partial packet return value not set\n");
1025     return recv16(s, buf, len, *flags);
1026 }