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;
274 handle
= LOWORD( InterlockedIncrement( &next_handle
));
275 while (!handle
); /* avoid handle 0 */
279 query
->handle
= UlongToHandle( handle
);
281 query
->sbuflen
= sbuflen
;
283 thread
= CreateThread( NULL
, 0, func
, query
, 0, NULL
);
286 SetLastError( WSAEWOULDBLOCK
);
287 HeapFree( GetProcessHeap(), 0, query
);
290 CloseHandle( thread
);
291 return UlongToHandle( handle
);
295 /***********************************************************************
296 * WSAAsyncGetHostByAddr (WS2_32.102)
298 HANDLE WINAPI
WSAAsyncGetHostByAddr(HWND hWnd
, UINT uMsg
, LPCSTR addr
,
299 INT len
, INT type
, LPSTR sbuf
, INT buflen
)
301 struct async_query_gethostbyaddr
*aq
;
303 TRACE("hwnd %p, msg %04x, addr %p[%i]\n", hWnd
, uMsg
, addr
, len
);
305 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
307 SetLastError( WSAEWOULDBLOCK
);
310 aq
->host_addr
= (char *)(aq
+ 1);
312 aq
->host_type
= type
;
313 memcpy( aq
->host_addr
, addr
, len
);
314 return run_query( hWnd
, uMsg
, async_gethostbyaddr
, &aq
->query
, sbuf
, buflen
);
317 /***********************************************************************
318 * WSAAsyncGetHostByName (WS2_32.103)
320 HANDLE WINAPI
WSAAsyncGetHostByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
321 LPSTR sbuf
, INT buflen
)
323 struct async_query_gethostbyname
*aq
;
324 unsigned int len
= strlen(name
) + 1;
326 TRACE("hwnd %p, msg %04x, host %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
328 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
330 SetLastError( WSAEWOULDBLOCK
);
333 aq
->host_name
= (char *)(aq
+ 1);
334 strcpy( aq
->host_name
, name
);
335 return run_query( hWnd
, uMsg
, async_gethostbyname
, &aq
->query
, sbuf
, buflen
);
338 /***********************************************************************
339 * WSAAsyncGetProtoByName (WS2_32.105)
341 HANDLE WINAPI
WSAAsyncGetProtoByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
342 LPSTR sbuf
, INT buflen
)
344 struct async_query_getprotobyname
*aq
;
345 unsigned int len
= strlen(name
) + 1;
347 TRACE("hwnd %p, msg %04x, proto %s, buffer %i\n", hWnd
, uMsg
, debugstr_a(name
), buflen
);
349 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
351 SetLastError( WSAEWOULDBLOCK
);
354 aq
->proto_name
= (char *)(aq
+ 1);
355 strcpy( aq
->proto_name
, name
);
356 return run_query( hWnd
, uMsg
, async_getprotobyname
, &aq
->query
, sbuf
, buflen
);
360 /***********************************************************************
361 * WSAAsyncGetProtoByNumber (WS2_32.104)
363 HANDLE WINAPI
WSAAsyncGetProtoByNumber(HWND hWnd
, UINT uMsg
, INT number
,
364 LPSTR sbuf
, INT buflen
)
366 struct async_query_getprotobynumber
*aq
;
368 TRACE("hwnd %p, msg %04x, num %i\n", hWnd
, uMsg
, number
);
370 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) )))
372 SetLastError( WSAEWOULDBLOCK
);
375 aq
->proto_number
= number
;
376 return run_query( hWnd
, uMsg
, async_getprotobynumber
, &aq
->query
, sbuf
, buflen
);
379 /***********************************************************************
380 * WSAAsyncGetServByName (WS2_32.107)
382 HANDLE WINAPI
WSAAsyncGetServByName(HWND hWnd
, UINT uMsg
, LPCSTR name
,
383 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
385 struct async_query_getservbyname
*aq
;
386 unsigned int len1
= strlen(name
) + 1;
387 unsigned int len2
= proto
? strlen(proto
) + 1 : 0;
389 TRACE("hwnd %p, msg %04x, name %s, proto %s\n", hWnd
, uMsg
, debugstr_a(name
), debugstr_a(proto
));
391 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len1
+ len2
)))
393 SetLastError( WSAEWOULDBLOCK
);
397 aq
->serv_name
= (char *)(aq
+ 1);
398 strcpy( aq
->serv_name
, name
);
402 aq
->serv_proto
= aq
->serv_name
+ len1
;
403 strcpy( aq
->serv_proto
, proto
);
406 aq
->serv_proto
= NULL
;
408 return run_query( hWnd
, uMsg
, async_getservbyname
, &aq
->query
, sbuf
, buflen
);
411 /***********************************************************************
412 * WSAAsyncGetServByPort (WS2_32.106)
414 HANDLE WINAPI
WSAAsyncGetServByPort(HWND hWnd
, UINT uMsg
, INT port
,
415 LPCSTR proto
, LPSTR sbuf
, INT buflen
)
417 struct async_query_getservbyport
*aq
;
418 unsigned int len
= proto
? strlen(proto
) + 1 : 0;
420 TRACE("hwnd %p, msg %04x, port %i, proto %s\n", hWnd
, uMsg
, port
, debugstr_a(proto
));
422 if (!(aq
= HeapAlloc( GetProcessHeap(), 0, sizeof(*aq
) + len
)))
424 SetLastError( WSAEWOULDBLOCK
);
430 aq
->serv_proto
= (char *)(aq
+ 1);
431 strcpy( aq
->serv_proto
, proto
);
434 aq
->serv_proto
= NULL
;
436 aq
->serv_port
= port
;
438 return run_query( hWnd
, uMsg
, async_getservbyport
, &aq
->query
, sbuf
, buflen
);
441 /***********************************************************************
442 * WSACancelAsyncRequest (WS2_32.108)
444 INT WINAPI
WSACancelAsyncRequest(HANDLE hAsyncTaskHandle
)
446 FIXME("(%p),stub\n", hAsyncTaskHandle
);
450 /***********************************************************************
451 * WSApSetPostRoutine (WS2_32.24)
453 INT WINAPI
WSApSetPostRoutine(LPWPUPOSTMESSAGE lpPostRoutine
)
455 FIXME("(%p), stub !\n", lpPostRoutine
);
459 /***********************************************************************
460 * WPUCompleteOverlappedRequest (WS2_32.25)
462 WSAEVENT WINAPI
WPUCompleteOverlappedRequest(SOCKET s
, LPWSAOVERLAPPED overlapped
,
463 DWORD error
, DWORD transferred
, LPINT errcode
)
465 FIXME("(0x%08lx,%p,0x%08x,0x%08x,%p), stub !\n", s
, overlapped
, error
, transferred
, errcode
);
468 *errcode
= WSAEINVAL
;