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
62 struct async_query_gethostbyname
64 struct async_query_header query
;
68 struct async_query_gethostbyaddr
70 struct async_query_header query
;
76 struct async_query_getprotobyname
78 struct async_query_header query
;
82 struct async_query_getprotobynumber
84 struct async_query_header query
;
88 struct async_query_getservbyname
90 struct async_query_header query
;
95 struct async_query_getservbyport
97 struct async_query_header query
;
103 /* ----------------------------------- helper functions - */
105 static int list_size(char** l
, int item_size
)
110 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
111 j
+= (i
+ 1) * sizeof(char*); }
115 static int list_dup(char** l_src
, char* ref
, int item_size
)
118 char** l_to
= (char**)ref
;
121 for(j
=0;l_src
[j
];j
++) ;
122 p
+= (j
+ 1) * sizeof(char*);
125 k
= ( item_size
) ? item_size
: strlen(l_src
[i
]) + 1;
126 memcpy(p
, l_src
[i
], k
); p
+= k
; }
131 static DWORD
finish_query( struct async_query_header
*query
, LPARAM lparam
)
133 PostMessageW( query
->hWnd
, query
->uMsg
, (WPARAM
)query
->handle
, lparam
);
134 HeapFree( GetProcessHeap(), 0, query
);
140 static LPARAM
copy_he(void *base
, int size
, const struct WS_hostent
*he
)
144 struct WS_hostent
*to
= base
;
146 if (!he
) return MAKELPARAM( 0, GetLastError() );
148 needed
= sizeof(struct WS_hostent
) + strlen(he
->h_name
) + 1 +
149 list_size(he
->h_aliases
, 0) +
150 list_size(he
->h_addr_list
, he
->h_length
);
151 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
153 to
->h_addrtype
= he
->h_addrtype
;
154 to
->h_length
= he
->h_length
;
155 p
= (char *)(to
+ 1);
157 strcpy(p
, he
->h_name
); p
+= strlen(p
) + 1;
158 to
->h_aliases
= (char **)p
;
159 p
+= list_dup(he
->h_aliases
, p
, 0);
160 to
->h_addr_list
= (char **)p
;
161 list_dup(he
->h_addr_list
, p
, he
->h_length
);
162 return MAKELPARAM( needed
, 0 );
165 static DWORD WINAPI
async_gethostbyname(LPVOID arg
)
167 struct async_query_gethostbyname
*aq
= arg
;
168 struct WS_hostent
*he
= WS_gethostbyname( aq
->host_name
);
170 return finish_query( &aq
->query
, copy_he( aq
->query
.sbuf
, aq
->query
.sbuflen
, he
));
173 static DWORD WINAPI
async_gethostbyaddr(LPVOID arg
)
175 struct async_query_gethostbyaddr
*aq
= arg
;
176 struct WS_hostent
*he
= WS_gethostbyaddr( aq
->host_addr
, aq
->host_len
, aq
->host_type
);
178 return finish_query( &aq
->query
, copy_he( aq
->query
.sbuf
, aq
->query
.sbuflen
, he
));
183 static LPARAM
copy_pe(void *base
, int size
, const struct WS_protoent
* pe
)
187 struct WS_protoent
*to
= base
;
189 if (!pe
) return MAKELPARAM( 0, GetLastError() );
191 needed
= sizeof(struct WS_protoent
) + strlen(pe
->p_name
) + 1 + list_size(pe
->p_aliases
, 0);
192 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
194 to
->p_proto
= pe
->p_proto
;
195 p
= (char *)(to
+ 1);
197 strcpy(p
, pe
->p_name
); p
+= strlen(p
) + 1;
198 to
->p_aliases
= (char **)p
;
199 list_dup(pe
->p_aliases
, p
, 0);
200 return MAKELPARAM( needed
, 0 );
203 static DWORD WINAPI
async_getprotobyname(LPVOID arg
)
205 struct async_query_getprotobyname
*aq
= arg
;
206 struct WS_protoent
*pe
= WS_getprotobyname( aq
->proto_name
);
208 return finish_query( &aq
->query
, copy_pe( aq
->query
.sbuf
, aq
->query
.sbuflen
, pe
));
211 static DWORD WINAPI
async_getprotobynumber(LPVOID arg
)
213 struct async_query_getprotobynumber
*aq
= arg
;
214 struct WS_protoent
*pe
= WS_getprotobynumber( aq
->proto_number
);
216 return finish_query( &aq
->query
, copy_pe( aq
->query
.sbuf
, aq
->query
.sbuflen
, pe
));
221 static LPARAM
copy_se(void *base
, int size
, const struct WS_servent
* se
)
225 struct WS_servent
*to
= base
;
227 if (!se
) return MAKELPARAM( 0, GetLastError() );
229 needed
= sizeof(struct WS_servent
) + strlen(se
->s_proto
) + strlen(se
->s_name
) + 2 + list_size(se
->s_aliases
, 0);
230 if (size
< needed
) return MAKELPARAM( needed
, WSAENOBUFS
);
232 to
->s_port
= se
->s_port
;
233 p
= (char *)(to
+ 1);
235 strcpy(p
, se
->s_name
); p
+= strlen(p
) + 1;
237 strcpy(p
, se
->s_proto
); p
+= strlen(p
) + 1;
238 to
->s_aliases
= (char **)p
;
239 list_dup(se
->s_aliases
, p
, 0);
240 return MAKELPARAM( needed
, 0 );
243 static DWORD WINAPI
async_getservbyname(LPVOID arg
)
245 struct async_query_getservbyname
*aq
= arg
;
246 struct WS_servent
*se
= WS_getservbyname( aq
->serv_name
, aq
->serv_proto
);
248 return finish_query( &aq
->query
, copy_se( aq
->query
.sbuf
, aq
->query
.sbuflen
, se
));
251 static DWORD WINAPI
async_getservbyport(LPVOID arg
)
253 struct async_query_getservbyport
*aq
= arg
;
254 struct WS_servent
*se
= WS_getservbyport( aq
->serv_port
, aq
->serv_proto
);
256 return finish_query( &aq
->query
, copy_se( aq
->query
.sbuf
, aq
->query
.sbuflen
, se
));
260 /****************************************************************************
261 * The main async help function.
263 * It either starts a thread or just calls the function directly for platforms
264 * with no thread support. This relies on the fact that PostMessage() does
265 * not actually call the windowproc before the function returns.
267 static HANDLE
run_query( HWND hWnd
, UINT uMsg
, LPTHREAD_START_ROUTINE func
,
268 struct async_query_header
*query
, void *sbuf
, INT sbuflen
)
270 static LONG next_handle
= 0xdead;
272 ULONG handle
= LOWORD( InterlockedIncrement( &next_handle
));
275 while (!handle
) handle
= LOWORD( InterlockedIncrement( &next_handle
));
279 query
->handle
= UlongToHandle( handle
);
281 query
->sbuflen
= sbuflen
;
283 thread
= CreateThread( NULL
, 0, func
, query
, 0, NULL
);
286 SetLastError( WSAEWOULDBLOCK
);
289 CloseHandle( thread
);
290 return UlongToHandle( handle
);
294 /***********************************************************************
295 * WSAAsyncGetHostByAddr (WS2_32.102)
297 HANDLE WINAPI
WSAAsyncGetHostByAddr(HWND hWnd
, UINT uMsg
, LPCSTR addr
,
298 INT len
, INT type
, LPSTR sbuf
, INT buflen
)
300 struct async_query_gethostbyaddr
*aq
;
302 TRACE("hwnd %p, msg %04x, addr %p[%i]\n", hWnd
, uMsg
, addr
, len
);
304 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
306 SetLastError( WSAEWOULDBLOCK
);
309 aq
->host_addr
= (char *)(aq
+ 1);
311 aq
->host_type
= type
;
312 memcpy( aq
->host_addr
, addr
, len
);
313 return run_query( hWnd
, uMsg
, async_gethostbyaddr
, &aq
->query
, sbuf
, buflen
);
316 /***********************************************************************
317 * WSAAsyncGetHostByName (WS2_32.103)
319 HANDLE WINAPI
WSAAsyncGetHostByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
320 LPSTR sbuf
, INT buflen
)
322 struct async_query_gethostbyname
*aq
;
323 unsigned int len
= strlen(name
) + 1;
325 TRACE("hwnd %p, msg %04x, host %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
327 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
329 SetLastError( WSAEWOULDBLOCK
);
332 aq
->host_name
= (char *)(aq
+ 1);
333 strcpy( aq
->host_name
, name
);
334 return run_query( hWnd
, uMsg
, async_gethostbyname
, &aq
->query
, sbuf
, buflen
);
337 /***********************************************************************
338 * WSAAsyncGetProtoByName (WS2_32.105)
340 HANDLE WINAPI
WSAAsyncGetProtoByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
341 LPSTR sbuf
, INT buflen
)
343 struct async_query_getprotobyname
*aq
;
344 unsigned int len
= strlen(name
) + 1;
346 TRACE("hwnd %p, msg %04x, proto %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
348 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
350 SetLastError( WSAEWOULDBLOCK
);
353 aq
->proto_name
= (char *)(aq
+ 1);
354 strcpy( aq
->proto_name
, name
);
355 return run_query( hWnd
, uMsg
, async_getprotobyname
, &aq
->query
, sbuf
, buflen
);
359 /***********************************************************************
360 * WSAAsyncGetProtoByNumber (WS2_32.104)
362 HANDLE WINAPI
WSAAsyncGetProtoByNumber(HWND hWnd
, UINT uMsg
, INT number
,
363 LPSTR sbuf
, INT buflen
)
365 struct async_query_getprotobynumber
*aq
;
367 TRACE("hwnd %p, msg %04x, num %i\n", hWnd
, uMsg
, number
);
369 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) )))
371 SetLastError( WSAEWOULDBLOCK
);
374 aq
->proto_number
= number
;
375 return run_query( hWnd
, uMsg
, async_getprotobynumber
, &aq
->query
, sbuf
, buflen
);
378 /***********************************************************************
379 * WSAAsyncGetServByName (WS2_32.107)
381 HANDLE WINAPI
WSAAsyncGetServByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
382 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
384 struct async_query_getservbyname
*aq
;
385 unsigned int len1
= strlen(name
) + 1;
386 unsigned int len2
= strlen(proto
) + 1;
388 TRACE("hwnd %p, msg %04x, name %s, proto %s\n", hWnd
, uMsg
, debugstr_a(name
), debugstr_a(proto
));
390 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len1
+ len2
)))
392 SetLastError( WSAEWOULDBLOCK
);
395 aq
->serv_name
= (char *)(aq
+ 1);
396 aq
->serv_proto
= aq
->serv_name
+ len1
;
397 strcpy( aq
->serv_name
, name
);
398 strcpy( aq
->serv_proto
, proto
);
399 return run_query( hWnd
, uMsg
, async_getservbyname
, &aq
->query
, sbuf
, buflen
);
402 /***********************************************************************
403 * WSAAsyncGetServByPort (WS2_32.106)
405 HANDLE WINAPI
WSAAsyncGetServByPort(HWND hWnd
, UINT uMsg
, INT port
,
406 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
408 struct async_query_getservbyport
*aq
;
409 unsigned int len
= strlen(proto
) + 1;
411 TRACE("hwnd %p, msg %04x, port %i, proto %s\n", hWnd
, uMsg
, port
, debugstr_a(proto
));
413 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
415 SetLastError( WSAEWOULDBLOCK
);
418 aq
->serv_proto
= (char *)(aq
+ 1);
419 aq
->serv_port
= port
;
420 strcpy( aq
->serv_proto
, proto
);
421 return run_query( hWnd
, uMsg
, async_getservbyport
, &aq
->query
, sbuf
, buflen
);
424 /***********************************************************************
425 * WSACancelAsyncRequest (WS2_32.108)
427 INT WINAPI
WSACancelAsyncRequest(HANDLE hAsyncTaskHandle
)
429 FIXME("(%p),stub\n", hAsyncTaskHandle
);
433 /***********************************************************************
434 * WSApSetPostRoutine (WS2_32.24)
436 INT WINAPI
WSApSetPostRoutine(LPWPUPOSTMESSAGE lpPostRoutine
)
438 FIXME("(%p), stub !\n", lpPostRoutine
);
442 /***********************************************************************
443 * WPUCompleteOverlappedRequest (WS2_32.25)
445 WSAEVENT WINAPI
WPUCompleteOverlappedRequest(SOCKET s
, LPWSAOVERLAPPED overlapped
,
446 DWORD error
, DWORD transferred
, LPINT errcode
)
448 FIXME("(0x%08lx,%p,0x%08x,0x%08x,%p), stub !\n", s
, overlapped
, error
, transferred
, errcode
);
451 *errcode
= WSAEINVAL
;