Fix a couple of warnings and a typo.
[wine] / dlls / winsock / async.c
1 /* Async WINSOCK DNS services
2  * 
3  * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
4  * (C) 1999 Marcus Meissner
5  *
6  * NOTE: If you make any changes to fix a particular app, make sure
7  * they don't break something else like Netscape or telnet and ftp
8  * clients and servers (www.winsite.com got a lot of those).
9  * 
10  * FIXME:
11  *      - Add WSACancel* and correct handle management. (works rather well for
12  *        now without it.)
13  *      - Verify & Check all calls for correctness
14  *        (currently only WSAGetHostByName*, WSAGetServByPort* calls)
15  *      - Check error returns.
16  *      - mirc/mirc32 Finger @linux.kernel.org sometimes fails in threaded mode.
17  *        (not sure why)
18  *      - This implementation did ignore the "NOTE:" section above (since the
19  *        whole stuff did not work anyway to other changes).
20  */
21  
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <string.h>
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_IPC_H
28 # include <sys/ipc.h>
29 #endif
30 #include <sys/ioctl.h>
31 #ifdef HAVE_SYS_FILIO_H
32 # include <sys/filio.h>
33 #endif
34 #if defined(__svr4__)
35 #include <sys/ioccom.h>
36 #ifdef HAVE_SYS_SOCKIO_H
37 # include <sys/sockio.h>
38 #endif
39 #endif
40
41 #if defined(__EMX__)
42 # include <sys/so_ioctl.h>
43 #endif
44
45 #ifdef HAVE_SYS_PARAM_H
46 # include <sys/param.h>
47 #endif
48
49 #ifdef HAVE_SYS_MSG_H
50 # include <sys/msg.h>
51 #endif
52 #ifdef HAVE_SYS_WAIT_H
53 #include <sys/wait.h>
54 #endif
55 #ifdef HAVE_SYS_SOCKET_H
56 #include <sys/socket.h>
57 #endif
58 #ifdef HAVE_NETINET_IN_H
59 # include <netinet/in.h>
60 #endif
61 #ifdef HAVE_ARPA_INET_H
62 # include <arpa/inet.h>
63 #endif
64 #include <ctype.h>
65 #include <fcntl.h>
66 #include <errno.h>
67 #ifdef HAVE_SYS_ERRNO_H
68 #include <sys/errno.h>
69 #endif
70 #ifdef HAVE_NETDB_H
71 #include <netdb.h>
72 #endif
73 #include <unistd.h>
74 #include <stdlib.h>
75 #ifdef HAVE_ARPA_NAMESER_H
76 # include <arpa/nameser.h>
77 #endif
78 #ifdef HAVE_RESOLV_H
79 # include <resolv.h>
80 #endif
81
82 #include "wine/winbase16.h"
83 #include "wingdi.h"
84 #include "winuser.h"
85 #include "winsock2.h"
86 #include "ws2spi.h"
87 #include "wine/winsock16.h"
88 #include "winnt.h"
89
90 #include "debugtools.h"
91
92 DEFAULT_DEBUG_CHANNEL(winsock);
93
94
95 /* critical section to protect some non-rentrant net function */
96 CRITICAL_SECTION csWSgetXXXbyYYY = CRITICAL_SECTION_INIT("csWSgetXXXbyYYY");
97
98 /* protoptypes of some functions in socket.c
99  */
100 UINT16 wsaErrno(void);
101 UINT16 wsaHerrno(int errnr);
102
103 #define AQ_WIN16        0x00
104 #define AQ_WIN32        0x04
105 #define HB_WIN32(hb) (hb->flags & AQ_WIN32)
106 #define AQ_NUMBER       0x00
107 #define AQ_NAME         0x08
108 #define AQ_COPYPTR1     0x10
109 #define AQ_DUPLOWPTR1   0x20
110 #define AQ_MASKPTR1     0x30
111 #define AQ_COPYPTR2     0x40
112 #define AQ_DUPLOWPTR2   0x80
113 #define AQ_MASKPTR2     0xC0
114
115 #define AQ_GETHOST      0
116 #define AQ_GETPROTO     1
117 #define AQ_GETSERV      2
118 #define AQ_GETMASK      3
119
120 /* ----------------------------------- helper functions - */
121
122 static int list_size(char** l, int item_size)
123 {
124   int i,j = 0;
125   if(l)
126   { for(i=0;l[i];i++) 
127         j += (item_size) ? item_size : strlen(l[i]) + 1;
128     j += (i + 1) * sizeof(char*); }
129   return j;
130 }
131
132 static int list_dup(char** l_src, char* ref, char* base, int item_size)
133
134    /* base is either either equal to ref or 0 or SEGPTR */
135
136    char*                p = ref;
137    char**               l_to = (char**)ref;
138    int                  i,j,k;
139
140    for(j=0;l_src[j];j++) ;
141    p += (j + 1) * sizeof(char*);
142    for(i=0;i<j;i++)
143    { l_to[i] = base + (p - ref);
144      k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
145      memcpy(p, l_src[i], k); p += k; }
146    l_to[i] = NULL;
147    return (p - ref);
148 }
149
150 /* ----- hostent */
151
152 static int hostent_size(struct hostent* p_he)
153 {
154   int size = 0;
155   if( p_he )
156   { size  = sizeof(struct hostent); 
157     size += strlen(p_he->h_name) + 1;
158     size += list_size(p_he->h_aliases, 0);  
159     size += list_size(p_he->h_addr_list, p_he->h_length ); }
160   return size;
161 }
162
163 /* Copy hostent to p_to, fix up inside pointers using p_base (different for
164  * Win16 (linear vs. segmented). Return -neededsize on overrun.
165  */
166 static int WS_copy_he(char *p_to,char *p_base,int t_size,struct hostent* p_he, int flag)
167 {
168         char* p_name,*p_aliases,*p_addr,*p;
169         struct ws_hostent16 *p_to16 = (struct ws_hostent16*)p_to;
170         struct WS_hostent *p_to32 = (struct WS_hostent*)p_to;
171         int     size = hostent_size(p_he) +
172                 (
173                 (flag & AQ_WIN16) ? sizeof(struct ws_hostent16) : sizeof(struct WS_hostent)
174                 - sizeof(struct hostent)
175                 );
176
177         if (t_size < size)
178                 return -size;
179         p = p_to;
180         p += (flag & AQ_WIN16) ?
181                 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
182         p_name = p;
183         strcpy(p, p_he->h_name); p += strlen(p) + 1;
184         p_aliases = p;
185         p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)p_to), 0);
186         p_addr = p;
187         list_dup(p_he->h_addr_list, p, p_base + (p - (char*)p_to), p_he->h_length);
188
189         if (flag & AQ_WIN16)
190         {
191             p_to16->h_addrtype = (INT16)p_he->h_addrtype; 
192             p_to16->h_length = (INT16)p_he->h_length;
193             p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
194             p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
195             p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
196         }
197         else
198         {
199             p_to32->h_addrtype = p_he->h_addrtype; 
200             p_to32->h_length = p_he->h_length;
201             p_to32->h_name = (p_base + (p_name - p_to));
202             p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
203             p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
204         }
205
206         return size;
207 }
208
209 /* ----- protoent */
210
211 static int protoent_size(struct protoent* p_pe)
212 {
213   int size = 0;
214   if( p_pe )
215   { size  = sizeof(struct protoent);
216     size += strlen(p_pe->p_name) + 1;
217     size += list_size(p_pe->p_aliases, 0); }
218   return size;
219 }
220
221 /* Copy protoent to p_to, fix up inside pointers using p_base (different for
222  * Win16 (linear vs. segmented). Return -neededsize on overrun.
223  */
224 static int WS_copy_pe(char *p_to,char *p_base,int t_size,struct protoent* p_pe, int flag)
225 {
226         char* p_name,*p_aliases,*p;
227         struct ws_protoent16 *p_to16 = (struct ws_protoent16*)p_to;
228         struct WS_protoent *p_to32 = (struct WS_protoent*)p_to;
229         int     size = protoent_size(p_pe) +
230                 (
231                 (flag & AQ_WIN16) ? sizeof(struct ws_protoent16) : sizeof(struct WS_protoent)
232                 - sizeof(struct protoent)
233                 );
234
235         if (t_size < size)
236                 return -size;
237         p = p_to;
238         p += (flag & AQ_WIN16) ?
239                 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
240         p_name = p;
241         strcpy(p, p_pe->p_name); p += strlen(p) + 1;
242         p_aliases = p;
243         list_dup(p_pe->p_aliases, p, p_base + (p - (char*)p_to), 0);
244
245         if (flag & AQ_WIN16)
246         {
247             p_to16->p_proto = (INT16)p_pe->p_proto;
248             p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
249             p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); 
250         }
251         else
252         {
253             p_to32->p_proto = p_pe->p_proto;
254             p_to32->p_name = (p_base) + (p_name - p_to);
255             p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); 
256         }
257
258         return size;
259 }
260
261 /* ----- servent */
262
263 static int servent_size(struct servent* p_se)
264 {
265         int size = 0;
266         if( p_se ) {
267                 size += sizeof(struct servent);
268                 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
269                 size += list_size(p_se->s_aliases, 0);
270         }
271         return size;
272 }
273
274 /* Copy servent to p_to, fix up inside pointers using p_base (different for
275  * Win16 (linear vs. segmented). Return -neededsize on overrun.
276  * Take care of different Win16/Win32 servent structs (packing !)
277  */
278 static int WS_copy_se(char *p_to,char *p_base,int t_size,struct servent* p_se, int flag)
279 {
280         char* p_name,*p_aliases,*p_proto,*p;
281         struct ws_servent16 *p_to16 = (struct ws_servent16*)p_to;
282         struct WS_servent *p_to32 = (struct WS_servent*)p_to;
283         int     size = servent_size(p_se) +
284                 (
285                 (flag & AQ_WIN16) ? sizeof(struct ws_servent16) : sizeof(struct WS_servent) 
286                 - sizeof(struct servent)
287                 );
288
289         if (t_size < size)
290                 return -size;
291         p = p_to;
292         p += (flag & AQ_WIN16) ?
293                 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
294         p_name = p;
295         strcpy(p, p_se->s_name); p += strlen(p) + 1;
296         p_proto = p;
297         strcpy(p, p_se->s_proto); p += strlen(p) + 1;
298         p_aliases = p;
299         list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
300
301         if (flag & AQ_WIN16)
302         {
303             p_to16->s_port = (INT16)p_se->s_port;
304             p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
305             p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
306             p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to)); 
307         }
308         else
309         {
310             p_to32->s_port = p_se->s_port;
311             p_to32->s_name = (p_base + (p_name - p_to));
312             p_to32->s_proto = (p_base + (p_proto - p_to));
313             p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to)); 
314         }
315
316         return size;
317 }
318
319 static HANDLE __ws_async_handle = 0xdead;
320
321 /* Generic async query struct. we use symbolic names for the different queries
322  * for readability.
323  */
324 typedef struct _async_query {
325         HWND16          hWnd;
326         UINT16          uMsg;
327         LPCSTR          ptr1;
328 #define host_name       ptr1
329 #define host_addr       ptr1
330 #define serv_name       ptr1
331 #define proto_name      ptr1
332         LPCSTR          ptr2;
333 #define serv_proto      ptr2
334         int             int1;
335 #define host_len        int1
336 #define proto_number    int1
337 #define serv_port       int1
338         int             int2;
339 #define host_type       int2
340         SEGPTR          sbuf;
341         INT16           sbuflen;
342
343         HANDLE16        async_handle;
344         int             flags;
345         int             qt;
346     char xbuf[1];
347 } async_query;
348
349
350 /****************************************************************************
351  * The async query function.
352  *
353  * It is either called as a thread startup routine or directly. It has
354  * to free the passed arg from the process heap and PostMessageA the async
355  * result or the error code.
356  * 
357  * FIXME:
358  *      - errorhandling not verified.
359  */
360 static DWORD WINAPI _async_queryfun(LPVOID arg) {
361         async_query     *aq = (async_query*)arg;
362         int             size = 0;
363         WORD            fail = 0;
364         char            *targetptr = (HB_WIN32(aq)?(char*)aq->sbuf:(char*)MapSL(aq->sbuf));
365
366         switch (aq->flags & AQ_GETMASK) {
367         case AQ_GETHOST: {
368                         struct hostent *he;
369                         char *copy_hostent = targetptr;
370 #if HAVE_LINUX_GETHOSTBYNAME_R_6
371                         char *extrabuf;
372                         int ebufsize=1024;
373                         struct hostent hostentry;
374                         int locerr = ENOBUFS;
375                         he = NULL;
376                         extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
377                         while(extrabuf) { 
378                             int res = (aq->flags & AQ_NAME) ?
379                                 gethostbyname_r(aq->host_name,
380                                                 &hostentry, extrabuf, ebufsize, &he, &locerr):
381                                 gethostbyaddr_r(aq->host_addr,aq->host_len,aq->host_type,
382                                                 &hostentry, extrabuf, ebufsize, &he, &locerr);
383                             if( res != ERANGE) break;
384                             ebufsize *=2;
385                             extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
386                         }
387                         if (!he) fail = ((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
388 #else
389                         EnterCriticalSection( &csWSgetXXXbyYYY );
390                         he = (aq->flags & AQ_NAME) ?
391                                 gethostbyname(aq->host_name):
392                                 gethostbyaddr(aq->host_addr,aq->host_len,aq->host_type);
393                         if (!he) fail = ((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
394 #endif
395                         if (he) {
396                                 size = WS_copy_he(copy_hostent,(char*)aq->sbuf,aq->sbuflen,he,aq->flags);
397                                 if (size < 0) {
398                                         fail = WSAENOBUFS;
399                                         size = -size;
400                                 }
401                         }
402 #if HAVE_LINUX_GETHOSTBYNAME_R_6
403                         HeapFree(GetProcessHeap(),0,extrabuf);
404 #else
405                         LeaveCriticalSection( &csWSgetXXXbyYYY );
406 #endif
407                 }
408                 break;
409         case AQ_GETPROTO: {
410                         struct protoent *pe;
411                         char *copy_protoent = targetptr;
412                         EnterCriticalSection( &csWSgetXXXbyYYY );
413                         pe = (aq->flags & AQ_NAME)?
414                                 getprotobyname(aq->proto_name) : 
415                                 getprotobynumber(aq->proto_number);
416                         if (pe) {
417                                 size = WS_copy_pe(copy_protoent,(char*)aq->sbuf,aq->sbuflen,pe,aq->flags);
418                                 if (size < 0) {
419                                         fail = WSAENOBUFS;
420                                         size = -size;
421                                 }
422                         } else {
423                             if (aq->flags & AQ_NAME)
424                                 MESSAGE("protocol %s not found; You might want to add "
425                                         "this to /etc/protocols\n", debugstr_a(aq->proto_name) );
426                             else
427                                 MESSAGE("protocol number %d not found; You might want to add "
428                                         "this to /etc/protocols\n", aq->proto_number );
429                             fail = WSANO_DATA;
430                         }
431                         LeaveCriticalSection( &csWSgetXXXbyYYY );
432                 }
433                 break;
434         case AQ_GETSERV: {
435                         struct servent  *se;
436                         char *copy_servent = targetptr;
437                         EnterCriticalSection( &csWSgetXXXbyYYY );
438                         se = (aq->flags & AQ_NAME)?
439                                 getservbyname(aq->serv_name,aq->serv_proto) : 
440                                 getservbyport(aq->serv_port,aq->serv_proto);
441                         if (se) {
442                                 size = WS_copy_se(copy_servent,(char*)aq->sbuf,aq->sbuflen,se,aq->flags);
443                                 if (size < 0) {
444                                         fail = WSAENOBUFS;
445                                         size = -size;
446                                 }
447                         } else {
448                             if (aq->flags & AQ_NAME)
449                                 MESSAGE("service %s protocol %s not found; You might want to add "
450                                         "this to /etc/services\n", debugstr_a(aq->serv_name) ,
451                                         aq->serv_proto ? debugstr_a(aq->serv_proto ):"*"); 
452                             else
453                                 MESSAGE("service on port %d protocol %s not found; You might want to add "
454                                         "this to /etc/services\n", aq->serv_port,
455                                         aq->serv_proto ? debugstr_a(aq->serv_proto ):"*"); 
456                             fail = WSANO_DATA;
457                         }
458                         LeaveCriticalSection( &csWSgetXXXbyYYY );
459                 }
460                 break;
461         }
462         PostMessageA(aq->hWnd,aq->uMsg,aq->async_handle,size|(fail<<16));
463         HeapFree(GetProcessHeap(),0,arg);
464         return 0;
465 }
466
467 /****************************************************************************
468  * The main async help function. 
469  * 
470  * It either starts a thread or just calls the function directly for platforms
471  * with no thread support. This relies on the fact that PostMessage() does
472  * not actually call the windowproc before the function returns.
473  */
474 static HANDLE16 __WSAsyncDBQuery(
475         HWND hWnd, UINT uMsg,INT int1,LPCSTR ptr1, INT int2, LPCSTR ptr2,
476         void *sbuf, INT sbuflen, UINT flags
477
478 {
479         async_query*    aq;
480         char*           pto;
481         LPCSTR          pfm;
482         int             xbuflen = 0;
483         
484         /* allocate buffer to copy protocol- and service name to */
485         /* note: this is done in the calling thread so we can return */
486         /* a decent error code if the Alloc fails */
487         
488         switch (flags & AQ_MASKPTR1) {
489         case 0:                                                 break;
490         case AQ_COPYPTR1:       xbuflen += int1;                break;
491         case AQ_DUPLOWPTR1:     xbuflen += strlen(ptr1) + 1;    break;
492         }
493         
494         switch (flags & AQ_MASKPTR2) {
495         case 0:                                                 break;
496         case AQ_COPYPTR2:       xbuflen += int2;                break;
497         case AQ_DUPLOWPTR2:     xbuflen += strlen(ptr2) + 1;    break;
498         }
499         
500         if(!(aq = HeapAlloc(GetProcessHeap(),0,sizeof(async_query) + xbuflen))) {
501                 SetLastError(WSAEWOULDBLOCK); /* insufficient resources */
502                 return 0;
503         }
504         
505         pto = aq->xbuf;
506         if (ptr1) switch (flags & AQ_MASKPTR1) {
507         case 0:                                                                                 break;
508         case AQ_COPYPTR1:   memcpy(pto, ptr1, int1); ptr1 = pto; pto += int1;                   break;
509         case AQ_DUPLOWPTR1: pfm = ptr1; ptr1 = pto; do *pto++ = tolower(*pfm); while (*pfm++);  break;
510         }
511         if (ptr2) switch (flags & AQ_MASKPTR2) {
512         case 0:                                                                                 break;
513         case AQ_COPYPTR2:   memcpy(pto, ptr2, int2); ptr2 = pto; pto += int2;                   break;
514         case AQ_DUPLOWPTR2: pfm = ptr2; ptr2 = pto; do *pto++ = tolower(*pfm); while (*pfm++);  break;
515         }
516
517         aq->hWnd        = hWnd;
518         aq->uMsg        = uMsg;
519         aq->int1        = int1;
520         aq->ptr1        = ptr1;
521         aq->int2        = int2;
522         aq->ptr2        = ptr2;
523         aq->async_handle = ++__ws_async_handle;
524         aq->flags       = flags;
525         aq->sbuf        = (SEGPTR)sbuf;
526         aq->sbuflen     = sbuflen;
527
528 #if 1
529         if (CreateThread(NULL,0,_async_queryfun,aq,0,NULL) == INVALID_HANDLE_VALUE)
530 #endif
531                 _async_queryfun(aq);
532         return __ws_async_handle;
533 }
534
535
536 /***********************************************************************
537  *       WSAAsyncGetHostByAddr  (WINSOCK.102)
538  */
539 HANDLE16 WINAPI WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
540                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
541 {
542         TRACE("hwnd %04x, msg %04x, addr %08x[%i]\n",
543                hWnd, uMsg, (unsigned)addr , len );
544         return __WSAsyncDBQuery(hWnd,uMsg,len,addr,type,NULL,(void*)sbuf,buflen,
545                                 AQ_NUMBER|AQ_COPYPTR1|AQ_WIN16|AQ_GETHOST);
546 }
547
548 /***********************************************************************
549  *       WSAAsyncGetHostByAddr        (WS2_32.102)
550  */
551 HANDLE WINAPI WSAAsyncGetHostByAddr(HWND hWnd, UINT uMsg, LPCSTR addr,
552                                INT len, INT type, LPSTR sbuf, INT buflen)
553 {
554         TRACE("hwnd %04x, msg %04x, addr %08x[%i]\n",
555                hWnd, uMsg, (unsigned)addr , len );
556         return __WSAsyncDBQuery(hWnd,uMsg,len,addr,type,NULL,sbuf,buflen,
557                                 AQ_NUMBER|AQ_COPYPTR1|AQ_WIN32|AQ_GETHOST);
558 }
559
560 /***********************************************************************
561  *       WSAAsyncGetHostByName  (WINSOCK.103)
562  */
563 HANDLE16 WINAPI WSAAsyncGetHostByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
564                                       SEGPTR sbuf, INT16 buflen)
565 {
566         TRACE("hwnd %04x, msg %04x, host %s, buffer %i\n", 
567               hWnd, uMsg, (name)?name:"<null>", (int)buflen );
568         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,(void*)sbuf,buflen,
569                                 AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN16|AQ_GETHOST);
570 }                     
571
572 /***********************************************************************
573  *       WSAAsyncGetHostByName  (WS2_32.103)
574  */
575 HANDLE WINAPI WSAAsyncGetHostByName(HWND hWnd, UINT uMsg, LPCSTR name, 
576                                         LPSTR sbuf, INT buflen)
577 {
578         TRACE("hwnd %04x, msg %08x, host %s, buffer %i\n", 
579                (HWND16)hWnd, uMsg, (name)?name:"<null>", (int)buflen );
580         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,sbuf,buflen,
581                                 AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN32|AQ_GETHOST);
582 }
583
584 /***********************************************************************
585  *       WSAAsyncGetProtoByName (WINSOCK.105)
586  */
587 HANDLE16 WINAPI WSAAsyncGetProtoByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
588                                          SEGPTR sbuf, INT16 buflen)
589 {
590         TRACE("hwnd %04x, msg %08x, protocol %s\n",
591                (HWND16)hWnd, uMsg, (name)?name:"<null>" );
592         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,(void*)sbuf,buflen,
593                                 AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN16|AQ_GETPROTO);
594 }
595
596 /***********************************************************************
597  *       WSAAsyncGetProtoByName       (WS2_32.105)
598  */
599 HANDLE WINAPI WSAAsyncGetProtoByName(HWND hWnd, UINT uMsg, LPCSTR name,
600                                          LPSTR sbuf, INT buflen)
601 {
602         TRACE("hwnd %04x, msg %08x, protocol %s\n",
603                (HWND16)hWnd, uMsg, (name)?name:"<null>" );
604         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,sbuf,buflen,
605                                 AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN32|AQ_GETPROTO);
606 }
607
608
609 /***********************************************************************
610  *       WSAAsyncGetProtoByNumber       (WINSOCK.104)
611  */
612 HANDLE16 WINAPI WSAAsyncGetProtoByNumber16(HWND16 hWnd,UINT16 uMsg,INT16 number,
613                                            SEGPTR sbuf, INT16 buflen)
614 {
615         TRACE("hwnd %04x, msg %04x, num %i\n", hWnd, uMsg, number );
616         return __WSAsyncDBQuery(hWnd,uMsg,number,NULL,0,NULL,(void*)sbuf,buflen,
617                                 AQ_GETPROTO|AQ_NUMBER|AQ_WIN16);
618 }
619
620 /***********************************************************************
621  *       WSAAsyncGetProtoByNumber     (WS2_32.104)
622  */
623 HANDLE WINAPI WSAAsyncGetProtoByNumber(HWND hWnd, UINT uMsg, INT number,
624                                            LPSTR sbuf, INT buflen)
625 {
626         TRACE("hwnd %04x, msg %04x, num %i\n", hWnd, uMsg, number );
627         return __WSAsyncDBQuery(hWnd,uMsg,number,NULL,0,NULL,sbuf,buflen,
628                                 AQ_GETPROTO|AQ_NUMBER|AQ_WIN32);
629 }
630
631 /***********************************************************************
632  *       WSAAsyncGetServByName  (WINSOCK.107)
633  */
634 HANDLE16 WINAPI WSAAsyncGetServByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
635                                         LPCSTR proto, SEGPTR sbuf, INT16 buflen)
636 {
637         TRACE("hwnd %04x, msg %04x, name %s, proto %s\n",
638                hWnd, uMsg, (name)?name:"<null>", (proto)?proto:"<null>");
639         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,proto,(void*)sbuf,buflen,
640                                 AQ_GETSERV|AQ_NAME|AQ_DUPLOWPTR1|AQ_DUPLOWPTR2|AQ_WIN16);
641 }
642
643 /***********************************************************************
644  *       WSAAsyncGetServByName        (WS2_32.107)
645  */
646 HANDLE WINAPI WSAAsyncGetServByName(HWND hWnd, UINT uMsg, LPCSTR name,
647                                         LPCSTR proto, LPSTR sbuf, INT buflen)
648 {
649         TRACE("hwnd %04x, msg %04x, name %s, proto %s\n",
650                hWnd, uMsg, (name)?name:"<null>", (proto)?proto:"<null>");
651         return __WSAsyncDBQuery(hWnd,uMsg,0,name,0,proto,sbuf,buflen,
652                                 AQ_GETSERV|AQ_NAME|AQ_DUPLOWPTR1|AQ_DUPLOWPTR2|AQ_WIN32);
653 }
654
655 /***********************************************************************
656  *       WSAAsyncGetServByPort  (WINSOCK.106)
657  */
658 HANDLE16 WINAPI WSAAsyncGetServByPort16(HWND16 hWnd, UINT16 uMsg, INT16 port, 
659                                         LPCSTR proto, SEGPTR sbuf, INT16 buflen)
660 {
661         TRACE("hwnd %04x, msg %04x, port %i, proto %s\n",
662                hWnd, uMsg, port, (proto)?proto:"<null>" );
663         return __WSAsyncDBQuery(hWnd,uMsg,port,NULL,0,proto,(void*)sbuf,buflen,
664                                 AQ_GETSERV|AQ_NUMBER|AQ_DUPLOWPTR2|AQ_WIN16);
665 }
666
667 /***********************************************************************
668  *       WSAAsyncGetServByPort        (WS2_32.106)
669  */
670 HANDLE WINAPI WSAAsyncGetServByPort(HWND hWnd, UINT uMsg, INT port,
671                                         LPCSTR proto, LPSTR sbuf, INT buflen)
672 {
673         TRACE("hwnd %04x, msg %04x, port %i, proto %s\n",
674                hWnd, uMsg, port, (proto)?proto:"<null>" );
675         return __WSAsyncDBQuery(hWnd,uMsg,port,NULL,0,proto,sbuf,buflen,
676                                 AQ_GETSERV|AQ_NUMBER|AQ_DUPLOWPTR2|AQ_WIN32);
677 }
678
679 /***********************************************************************
680  *       WSACancelAsyncRequest  (WS2_32.108)
681  */
682 INT WINAPI WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
683 {
684     FIXME("(%08x),stub\n", hAsyncTaskHandle);
685     return 0;
686 }
687
688 /***********************************************************************
689  *       WSACancelAsyncRequest  (WINSOCK.108)
690  */
691 INT16 WINAPI WSACancelAsyncRequest16(HANDLE16 hAsyncTaskHandle)
692 {
693     return (HANDLE16)WSACancelAsyncRequest((HANDLE)hAsyncTaskHandle);
694 }
695
696 /***********************************************************************
697  *       WSApSetPostRoutine     (WS2_32.24)
698  */
699 INT WINAPI WSApSetPostRoutine(LPWPUPOSTMESSAGE lpPostRoutine)
700 {
701     FIXME("(%p), stub !\n", lpPostRoutine);
702     return 0;
703 }