1 /* Async WINSOCK DNS services
3 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
4 * Copyright (C) 1999 Marcus Meissner
5 * Copyright (C) 2009 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
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 * - Add WSACancel* and correct handle management. (works rather well for
28 * - Verify & Check all calls for correctness
29 * (currently only WSAGetHostByName*, WSAGetServByPort* calls)
30 * - Check error returns.
31 * - mirc/mirc32 Finger @linux.kernel.org sometimes fails in threaded mode.
33 * - This implementation did ignore the "NOTE:" section above (since the
34 * whole stuff did not work anyway to other changes).
38 #include "wine/port.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
53 struct async_query_header
55 LPARAM (*func
)( struct async_query_header
*query
);
63 struct async_query_gethostbyname
65 struct async_query_header query
;
69 struct async_query_gethostbyaddr
71 struct async_query_header query
;
77 struct async_query_getprotobyname
79 struct async_query_header query
;
83 struct async_query_getprotobynumber
85 struct async_query_header query
;
89 struct async_query_getservbyname
91 struct async_query_header query
;
96 struct async_query_getservbyport
98 struct async_query_header query
;
104 /* ----------------------------------- helper functions - */
106 static int list_size(char** l
, int item_size
)
111 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
112 j
+= (i
+ 1) * sizeof(char*); }
116 static int list_dup(char** l_src
, char* ref
, int item_size
)
119 char** l_to
= (char**)ref
;
122 for(j
=0;l_src
[j
];j
++) ;
123 p
+= (j
+ 1) * sizeof(char*);
126 k
= ( item_size
) ? item_size
: strlen(l_src
[i
]) + 1;
127 memcpy(p
, l_src
[i
], k
); p
+= k
; }
134 static LPARAM
copy_he(void *base
, int size
, const struct WS_hostent
*he
)
138 struct WS_hostent
*to
= base
;
140 if (!he
) return MAKELPARAM( 0, GetLastError() );
142 needed
= sizeof(struct WS_hostent
) + strlen(he
->h_name
) + 1 +
143 list_size(he
->h_aliases
, 0) +
144 list_size(he
->h_addr_list
, he
->h_length
);
145 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
147 to
->h_addrtype
= he
->h_addrtype
;
148 to
->h_length
= he
->h_length
;
149 p
= (char *)(to
+ 1);
151 strcpy(p
, he
->h_name
); p
+= strlen(p
) + 1;
152 to
->h_aliases
= (char **)p
;
153 p
+= list_dup(he
->h_aliases
, p
, 0);
154 to
->h_addr_list
= (char **)p
;
155 list_dup(he
->h_addr_list
, p
, he
->h_length
);
156 return MAKELPARAM( needed
, 0 );
159 static LPARAM
async_gethostbyname( struct async_query_header
*query
)
161 struct async_query_gethostbyname
*aq
= CONTAINING_RECORD( query
, struct async_query_gethostbyname
, query
);
162 struct WS_hostent
*he
= WS_gethostbyname( aq
->host_name
);
164 return copy_he( query
->sbuf
, query
->sbuflen
, he
);
167 static LPARAM
async_gethostbyaddr( struct async_query_header
*query
)
169 struct async_query_gethostbyaddr
*aq
= CONTAINING_RECORD( query
, struct async_query_gethostbyaddr
, query
);
170 struct WS_hostent
*he
= WS_gethostbyaddr( aq
->host_addr
, aq
->host_len
, aq
->host_type
);
172 return copy_he( query
->sbuf
, query
->sbuflen
, he
);
177 static LPARAM
copy_pe(void *base
, int size
, const struct WS_protoent
* pe
)
181 struct WS_protoent
*to
= base
;
183 if (!pe
) return MAKELPARAM( 0, GetLastError() );
185 needed
= sizeof(struct WS_protoent
) + strlen(pe
->p_name
) + 1 + list_size(pe
->p_aliases
, 0);
186 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
188 to
->p_proto
= pe
->p_proto
;
189 p
= (char *)(to
+ 1);
191 strcpy(p
, pe
->p_name
); p
+= strlen(p
) + 1;
192 to
->p_aliases
= (char **)p
;
193 list_dup(pe
->p_aliases
, p
, 0);
194 return MAKELPARAM( needed
, 0 );
197 static LPARAM
async_getprotobyname( struct async_query_header
*query
)
199 struct async_query_getprotobyname
*aq
= CONTAINING_RECORD( query
, struct async_query_getprotobyname
, query
);
200 struct WS_protoent
*pe
= WS_getprotobyname( aq
->proto_name
);
202 return copy_pe( query
->sbuf
, query
->sbuflen
, pe
);
205 static LPARAM
async_getprotobynumber( struct async_query_header
*query
)
207 struct async_query_getprotobynumber
*aq
= CONTAINING_RECORD( query
, struct async_query_getprotobynumber
, query
);
208 struct WS_protoent
*pe
= WS_getprotobynumber( aq
->proto_number
);
210 return copy_pe( query
->sbuf
, query
->sbuflen
, pe
);
215 static LPARAM
copy_se(void *base
, int size
, const struct WS_servent
* se
)
219 struct WS_servent
*to
= base
;
221 if (!se
) return MAKELPARAM( 0, GetLastError() );
223 needed
= sizeof(struct WS_servent
) + strlen(se
->s_proto
) + strlen(se
->s_name
) + 2 + list_size(se
->s_aliases
, 0);
224 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
226 to
->s_port
= se
->s_port
;
227 p
= (char *)(to
+ 1);
229 strcpy(p
, se
->s_name
); p
+= strlen(p
) + 1;
231 strcpy(p
, se
->s_proto
); p
+= strlen(p
) + 1;
232 to
->s_aliases
= (char **)p
;
233 list_dup(se
->s_aliases
, p
, 0);
234 return MAKELPARAM( needed
, 0 );
237 static LPARAM
async_getservbyname( struct async_query_header
*query
)
239 struct async_query_getservbyname
*aq
= CONTAINING_RECORD( query
, struct async_query_getservbyname
, query
);
240 struct WS_servent
*se
= WS_getservbyname( aq
->serv_name
, aq
->serv_proto
);
242 return copy_se( query
->sbuf
, query
->sbuflen
, se
);
245 static LPARAM
async_getservbyport( struct async_query_header
*query
)
247 struct async_query_getservbyport
*aq
= CONTAINING_RECORD( query
, struct async_query_getservbyport
, query
);
248 struct WS_servent
*se
= WS_getservbyport( aq
->serv_port
, aq
->serv_proto
);
250 return copy_se( query
->sbuf
, query
->sbuflen
, se
);
254 static void WINAPI
async_worker( TP_CALLBACK_INSTANCE
*instance
, void *context
)
256 struct async_query_header
*query
= context
;
257 LPARAM lparam
= query
->func( query
);
258 PostMessageW( query
->hWnd
, query
->uMsg
, (WPARAM
)query
->handle
, lparam
);
259 HeapFree( GetProcessHeap(), 0, query
);
263 /****************************************************************************
264 * The main async help function.
266 * It either starts a thread or just calls the function directly for platforms
267 * with no thread support. This relies on the fact that PostMessage() does
268 * not actually call the windowproc before the function returns.
270 static HANDLE
run_query( HWND hWnd
, UINT uMsg
, LPARAM (*func
)(struct async_query_header
*),
271 struct async_query_header
*query
, void *sbuf
, INT sbuflen
)
273 static LONG next_handle
= 0xdead;
276 handle
= LOWORD( InterlockedIncrement( &next_handle
));
277 while (!handle
); /* avoid handle 0 */
282 query
->handle
= UlongToHandle( handle
);
284 query
->sbuflen
= sbuflen
;
286 if (!TrySubmitThreadpoolCallback( async_worker
, query
, NULL
))
288 SetLastError( WSAEWOULDBLOCK
);
289 HeapFree( GetProcessHeap(), 0, query
);
292 return UlongToHandle( handle
);
296 /***********************************************************************
297 * WSAAsyncGetHostByAddr (WS2_32.102)
299 HANDLE WINAPI
WSAAsyncGetHostByAddr(HWND hWnd
, UINT uMsg
, LPCSTR addr
,
300 INT len
, INT type
, LPSTR sbuf
, INT buflen
)
302 struct async_query_gethostbyaddr
*aq
;
304 TRACE("hwnd %p, msg %04x, addr %p[%i]\n", hWnd
, uMsg
, addr
, len
);
306 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
308 SetLastError( WSAEWOULDBLOCK
);
311 aq
->host_addr
= (char *)(aq
+ 1);
313 aq
->host_type
= type
;
314 memcpy( aq
->host_addr
, addr
, len
);
315 return run_query( hWnd
, uMsg
, async_gethostbyaddr
, &aq
->query
, sbuf
, buflen
);
318 /***********************************************************************
319 * WSAAsyncGetHostByName (WS2_32.103)
321 HANDLE WINAPI
WSAAsyncGetHostByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
322 LPSTR sbuf
, INT buflen
)
324 struct async_query_gethostbyname
*aq
;
325 unsigned int len
= strlen(name
) + 1;
327 TRACE("hwnd %p, msg %04x, host %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
329 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
331 SetLastError( WSAEWOULDBLOCK
);
334 aq
->host_name
= (char *)(aq
+ 1);
335 strcpy( aq
->host_name
, name
);
336 return run_query( hWnd
, uMsg
, async_gethostbyname
, &aq
->query
, sbuf
, buflen
);
339 /***********************************************************************
340 * WSAAsyncGetProtoByName (WS2_32.105)
342 HANDLE WINAPI
WSAAsyncGetProtoByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
343 LPSTR sbuf
, INT buflen
)
345 struct async_query_getprotobyname
*aq
;
346 unsigned int len
= strlen(name
) + 1;
348 TRACE("hwnd %p, msg %04x, proto %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
350 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
352 SetLastError( WSAEWOULDBLOCK
);
355 aq
->proto_name
= (char *)(aq
+ 1);
356 strcpy( aq
->proto_name
, name
);
357 return run_query( hWnd
, uMsg
, async_getprotobyname
, &aq
->query
, sbuf
, buflen
);
361 /***********************************************************************
362 * WSAAsyncGetProtoByNumber (WS2_32.104)
364 HANDLE WINAPI
WSAAsyncGetProtoByNumber(HWND hWnd
, UINT uMsg
, INT number
,
365 LPSTR sbuf
, INT buflen
)
367 struct async_query_getprotobynumber
*aq
;
369 TRACE("hwnd %p, msg %04x, num %i\n", hWnd
, uMsg
, number
);
371 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) )))
373 SetLastError( WSAEWOULDBLOCK
);
376 aq
->proto_number
= number
;
377 return run_query( hWnd
, uMsg
, async_getprotobynumber
, &aq
->query
, sbuf
, buflen
);
380 /***********************************************************************
381 * WSAAsyncGetServByName (WS2_32.107)
383 HANDLE WINAPI
WSAAsyncGetServByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
384 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
386 struct async_query_getservbyname
*aq
;
387 unsigned int len1
= strlen(name
) + 1;
388 unsigned int len2
= proto
? strlen(proto
) + 1 : 0;
390 TRACE("hwnd %p, msg %04x, name %s, proto %s\n", hWnd
, uMsg
, debugstr_a(name
), debugstr_a(proto
));
392 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len1
+ len2
)))
394 SetLastError( WSAEWOULDBLOCK
);
398 aq
->serv_name
= (char *)(aq
+ 1);
399 strcpy( aq
->serv_name
, name
);
403 aq
->serv_proto
= aq
->serv_name
+ len1
;
404 strcpy( aq
->serv_proto
, proto
);
407 aq
->serv_proto
= NULL
;
409 return run_query( hWnd
, uMsg
, async_getservbyname
, &aq
->query
, sbuf
, buflen
);
412 /***********************************************************************
413 * WSAAsyncGetServByPort (WS2_32.106)
415 HANDLE WINAPI
WSAAsyncGetServByPort(HWND hWnd
, UINT uMsg
, INT port
,
416 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
418 struct async_query_getservbyport
*aq
;
419 unsigned int len
= proto
? strlen(proto
) + 1 : 0;
421 TRACE("hwnd %p, msg %04x, port %i, proto %s\n", hWnd
, uMsg
, port
, debugstr_a(proto
));
423 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
425 SetLastError( WSAEWOULDBLOCK
);
431 aq
->serv_proto
= (char *)(aq
+ 1);
432 strcpy( aq
->serv_proto
, proto
);
435 aq
->serv_proto
= NULL
;
437 aq
->serv_port
= port
;
439 return run_query( hWnd
, uMsg
, async_getservbyport
, &aq
->query
, sbuf
, buflen
);
442 /***********************************************************************
443 * WSACancelAsyncRequest (WS2_32.108)
445 INT WINAPI
WSACancelAsyncRequest(HANDLE hAsyncTaskHandle
)
447 FIXME("(%p),stub\n", hAsyncTaskHandle
);
451 /***********************************************************************
452 * WSApSetPostRoutine (WS2_32.24)
454 INT WINAPI
WSApSetPostRoutine(LPWPUPOSTMESSAGE lpPostRoutine
)
456 FIXME("(%p), stub !\n", lpPostRoutine
);
460 /***********************************************************************
461 * WPUCompleteOverlappedRequest (WS2_32.25)
463 WSAEVENT WINAPI
WPUCompleteOverlappedRequest(SOCKET s
, LPWSAOVERLAPPED overlapped
,
464 DWORD error
, DWORD transferred
, LPINT errcode
)
466 FIXME("(0x%08lx,%p,0x%08x,0x%08x,%p), stub !\n", s
, overlapped
, error
, transferred
, errcode
);
469 *errcode
= WSAEINVAL
;