mshtml: Move the MessageEvent construction to a helper.
[wine.git] / dlls / ws2_32 / async.c
blobb7f050a445a3e85627461ae2835eb27ad07a5f32
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).
25 * FIXME:
26 * - Add WSACancel* and correct handle management. (works rather well for
27 * now without it.)
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.
32 * (not sure why)
33 * - This implementation did ignore the "NOTE:" section above (since the
34 * whole stuff did not work anyway to other changes).
37 #include "ws2_32_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
42 struct async_query_header
44 LPARAM (*func)( struct async_query_header *query );
45 HWND hWnd;
46 UINT uMsg;
47 void *sbuf;
48 INT sbuflen;
49 HANDLE handle;
52 struct async_query_gethostbyname
54 struct async_query_header query;
55 char *host_name;
58 struct async_query_gethostbyaddr
60 struct async_query_header query;
61 char *host_addr;
62 int host_len;
63 int host_type;
66 struct async_query_getprotobyname
68 struct async_query_header query;
69 char *proto_name;
72 struct async_query_getprotobynumber
74 struct async_query_header query;
75 int proto_number;
78 struct async_query_getservbyname
80 struct async_query_header query;
81 char *serv_name;
82 char *serv_proto;
85 struct async_query_getservbyport
87 struct async_query_header query;
88 char *serv_proto;
89 int serv_port;
93 /* ----------------------------------- helper functions - */
95 static int list_size(char** l, int item_size)
97 int i,j = 0;
98 if(l)
99 { for(i=0;l[i];i++)
100 j += (item_size) ? item_size : strlen(l[i]) + 1;
101 j += (i + 1) * sizeof(char*); }
102 return j;
105 static int list_dup(char** l_src, char* ref, int item_size)
107 char* p = ref;
108 char** l_to = (char**)ref;
109 int i,j,k;
111 for(j=0;l_src[j];j++) ;
112 p += (j + 1) * sizeof(char*);
113 for(i=0;i<j;i++)
114 { l_to[i] = p;
115 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
116 memcpy(p, l_src[i], k); p += k; }
117 l_to[i] = NULL;
118 return (p - ref);
121 /* ----- hostent */
123 static LPARAM copy_he(void *base, int size, const struct hostent *he)
125 char *p;
126 int needed;
127 struct hostent *to = base;
129 if (!he) return MAKELPARAM( 0, GetLastError() );
131 needed = sizeof(struct hostent) + strlen(he->h_name) + 1 +
132 list_size(he->h_aliases, 0) +
133 list_size(he->h_addr_list, he->h_length );
134 if (size < needed) return MAKELPARAM( needed, WSAENOBUFS );
136 to->h_addrtype = he->h_addrtype;
137 to->h_length = he->h_length;
138 p = (char *)(to + 1);
139 to->h_name = p;
140 strcpy(p, he->h_name); p += strlen(p) + 1;
141 to->h_aliases = (char **)p;
142 p += list_dup(he->h_aliases, p, 0);
143 to->h_addr_list = (char **)p;
144 list_dup(he->h_addr_list, p, he->h_length);
145 return MAKELPARAM( needed, 0 );
148 static LPARAM async_gethostbyname( struct async_query_header *query )
150 struct async_query_gethostbyname *aq = CONTAINING_RECORD( query, struct async_query_gethostbyname, query );
151 struct hostent *he = gethostbyname( aq->host_name );
153 return copy_he( query->sbuf, query->sbuflen, he );
156 static LPARAM async_gethostbyaddr( struct async_query_header *query )
158 struct async_query_gethostbyaddr *aq = CONTAINING_RECORD( query, struct async_query_gethostbyaddr, query );
159 struct hostent *he = gethostbyaddr( aq->host_addr, aq->host_len, aq->host_type );
161 return copy_he( query->sbuf, query->sbuflen, he );
164 /* ----- protoent */
166 static LPARAM copy_pe( void *base, int size, const struct protoent *pe )
168 char *p;
169 int needed;
170 struct protoent *to = base;
172 if (!pe) return MAKELPARAM( 0, GetLastError() );
174 needed = sizeof(struct protoent) + strlen( pe->p_name ) + 1 + list_size( pe->p_aliases, 0 );
175 if (size < needed) return MAKELPARAM( needed, WSAENOBUFS );
177 to->p_proto = pe->p_proto;
178 p = (char *)(to + 1);
179 to->p_name = p;
180 strcpy(p, pe->p_name); p += strlen(p) + 1;
181 to->p_aliases = (char **)p;
182 list_dup(pe->p_aliases, p, 0);
183 return MAKELPARAM( needed, 0 );
186 static LPARAM async_getprotobyname( struct async_query_header *query )
188 struct async_query_getprotobyname *aq = CONTAINING_RECORD( query, struct async_query_getprotobyname, query );
189 struct protoent *pe = getprotobyname( aq->proto_name );
191 return copy_pe( query->sbuf, query->sbuflen, pe );
194 static LPARAM async_getprotobynumber( struct async_query_header *query )
196 struct async_query_getprotobynumber *aq = CONTAINING_RECORD( query, struct async_query_getprotobynumber, query );
197 struct protoent *pe = getprotobynumber( aq->proto_number );
199 return copy_pe( query->sbuf, query->sbuflen, pe );
202 /* ----- servent */
204 static LPARAM copy_se( void *base, int size, const struct servent *se )
206 char *p;
207 int needed;
208 struct servent *to = base;
210 if (!se) return MAKELPARAM( 0, GetLastError() );
212 needed = sizeof(struct servent) + strlen( se->s_proto ) + strlen( se->s_name ) + 2 + list_size( se->s_aliases, 0 );
213 if (size < needed) return MAKELPARAM( needed, WSAENOBUFS );
215 to->s_port = se->s_port;
216 p = (char *)(to + 1);
217 to->s_name = p;
218 strcpy(p, se->s_name); p += strlen(p) + 1;
219 to->s_proto = p;
220 strcpy(p, se->s_proto); p += strlen(p) + 1;
221 to->s_aliases = (char **)p;
222 list_dup(se->s_aliases, p, 0);
223 return MAKELPARAM( needed, 0 );
226 static LPARAM async_getservbyname( struct async_query_header *query )
228 struct async_query_getservbyname *aq = CONTAINING_RECORD( query, struct async_query_getservbyname, query );
229 struct servent *se = getservbyname( aq->serv_name, aq->serv_proto );
231 return copy_se( query->sbuf, query->sbuflen, se );
234 static LPARAM async_getservbyport( struct async_query_header *query )
236 struct async_query_getservbyport *aq = CONTAINING_RECORD( query, struct async_query_getservbyport, query );
237 struct servent *se = getservbyport( aq->serv_port, aq->serv_proto );
239 return copy_se( query->sbuf, query->sbuflen, se );
243 static void WINAPI async_worker( TP_CALLBACK_INSTANCE *instance, void *context )
245 struct async_query_header *query = context;
246 LPARAM lparam = query->func( query );
247 PostMessageW( query->hWnd, query->uMsg, (WPARAM)query->handle, lparam );
248 free( query );
252 /****************************************************************************
253 * The main async help function.
255 * It either starts a thread or just calls the function directly for platforms
256 * with no thread support. This relies on the fact that PostMessage() does
257 * not actually call the windowproc before the function returns.
259 static HANDLE run_query( HWND hWnd, UINT uMsg, LPARAM (*func)(struct async_query_header *),
260 struct async_query_header *query, void *sbuf, INT sbuflen )
262 static LONG next_handle = 0xdead;
263 ULONG handle;
265 handle = LOWORD( InterlockedIncrement( &next_handle ));
266 while (!handle); /* avoid handle 0 */
268 query->func = func;
269 query->hWnd = hWnd;
270 query->uMsg = uMsg;
271 query->handle = UlongToHandle( handle );
272 query->sbuf = sbuf;
273 query->sbuflen = sbuflen;
275 if (!TrySubmitThreadpoolCallback( async_worker, query, NULL ))
277 SetLastError( WSAEWOULDBLOCK );
278 free( query );
279 return 0;
281 return UlongToHandle( handle );
285 /***********************************************************************
286 * WSAAsyncGetHostByAddr (WS2_32.102)
288 HANDLE WINAPI WSAAsyncGetHostByAddr(HWND hWnd, UINT uMsg, LPCSTR addr,
289 INT len, INT type, LPSTR sbuf, INT buflen)
291 struct async_query_gethostbyaddr *aq;
293 TRACE("hwnd %p, msg %04x, addr %p[%i]\n", hWnd, uMsg, addr, len );
295 if (!(aq = malloc( sizeof(*aq) + len )))
297 SetLastError( WSAEWOULDBLOCK );
298 return 0;
300 aq->host_addr = (char *)(aq + 1);
301 aq->host_len = len;
302 aq->host_type = type;
303 memcpy( aq->host_addr, addr, len );
304 return run_query( hWnd, uMsg, async_gethostbyaddr, &aq->query, sbuf, buflen );
307 /***********************************************************************
308 * WSAAsyncGetHostByName (WS2_32.103)
310 HANDLE WINAPI WSAAsyncGetHostByName(HWND hWnd, UINT uMsg, LPCSTR name,
311 LPSTR sbuf, INT buflen)
313 struct async_query_gethostbyname *aq;
314 unsigned int len = strlen(name) + 1;
316 TRACE("hwnd %p, msg %04x, host %s, buffer %i\n", hWnd, uMsg, debugstr_a(name), buflen );
318 if (!(aq = malloc( sizeof(*aq) + len )))
320 SetLastError( WSAEWOULDBLOCK );
321 return 0;
323 aq->host_name = (char *)(aq + 1);
324 strcpy( aq->host_name, name );
325 return run_query( hWnd, uMsg, async_gethostbyname, &aq->query, sbuf, buflen );
328 /***********************************************************************
329 * WSAAsyncGetProtoByName (WS2_32.105)
331 HANDLE WINAPI WSAAsyncGetProtoByName(HWND hWnd, UINT uMsg, LPCSTR name,
332 LPSTR sbuf, INT buflen)
334 struct async_query_getprotobyname *aq;
335 unsigned int len = strlen(name) + 1;
337 TRACE("hwnd %p, msg %04x, proto %s, buffer %i\n", hWnd, uMsg, debugstr_a(name), buflen );
339 if (!(aq = malloc( sizeof(*aq) + len )))
341 SetLastError( WSAEWOULDBLOCK );
342 return 0;
344 aq->proto_name = (char *)(aq + 1);
345 strcpy( aq->proto_name, name );
346 return run_query( hWnd, uMsg, async_getprotobyname, &aq->query, sbuf, buflen );
350 /***********************************************************************
351 * WSAAsyncGetProtoByNumber (WS2_32.104)
353 HANDLE WINAPI WSAAsyncGetProtoByNumber(HWND hWnd, UINT uMsg, INT number,
354 LPSTR sbuf, INT buflen)
356 struct async_query_getprotobynumber *aq;
358 TRACE("hwnd %p, msg %04x, num %i\n", hWnd, uMsg, number );
360 if (!(aq = malloc( sizeof(*aq) )))
362 SetLastError( WSAEWOULDBLOCK );
363 return 0;
365 aq->proto_number = number;
366 return run_query( hWnd, uMsg, async_getprotobynumber, &aq->query, sbuf, buflen );
369 /***********************************************************************
370 * WSAAsyncGetServByName (WS2_32.107)
372 HANDLE WINAPI WSAAsyncGetServByName(HWND hWnd, UINT uMsg, LPCSTR name,
373 LPCSTR proto, LPSTR sbuf, INT buflen)
375 struct async_query_getservbyname *aq;
376 unsigned int len1 = strlen(name) + 1;
377 unsigned int len2 = proto ? strlen(proto) + 1 : 0;
379 TRACE("hwnd %p, msg %04x, name %s, proto %s\n", hWnd, uMsg, debugstr_a(name), debugstr_a(proto));
381 if (!(aq = malloc( sizeof(*aq) + len1 + len2 )))
383 SetLastError( WSAEWOULDBLOCK );
384 return 0;
387 aq->serv_name = (char *)(aq + 1);
388 strcpy( aq->serv_name, name );
390 if (proto)
392 aq->serv_proto = aq->serv_name + len1;
393 strcpy( aq->serv_proto, proto );
395 else
396 aq->serv_proto = NULL;
398 return run_query( hWnd, uMsg, async_getservbyname, &aq->query, sbuf, buflen );
401 /***********************************************************************
402 * WSAAsyncGetServByPort (WS2_32.106)
404 HANDLE WINAPI WSAAsyncGetServByPort(HWND hWnd, UINT uMsg, INT port,
405 LPCSTR proto, LPSTR sbuf, INT buflen)
407 struct async_query_getservbyport *aq;
408 unsigned int len = proto ? strlen(proto) + 1 : 0;
410 TRACE("hwnd %p, msg %04x, port %i, proto %s\n", hWnd, uMsg, port, debugstr_a(proto));
412 if (!(aq = malloc( sizeof(*aq) + len )))
414 SetLastError( WSAEWOULDBLOCK );
415 return 0;
418 if (proto)
420 aq->serv_proto = (char *)(aq + 1);
421 strcpy( aq->serv_proto, proto );
423 else
424 aq->serv_proto = NULL;
426 aq->serv_port = port;
428 return run_query( hWnd, uMsg, async_getservbyport, &aq->query, sbuf, buflen );
431 /***********************************************************************
432 * WSACancelAsyncRequest (WS2_32.108)
434 INT WINAPI WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
436 FIXME("(%p),stub\n", hAsyncTaskHandle);
437 return 0;
440 /***********************************************************************
441 * WSApSetPostRoutine (WS2_32.24)
443 INT WINAPI WSApSetPostRoutine(LPWPUPOSTMESSAGE lpPostRoutine)
445 FIXME("(%p), stub !\n", lpPostRoutine);
446 return 0;
449 /***********************************************************************
450 * WPUCompleteOverlappedRequest (WS2_32.25)
452 WSAEVENT WINAPI WPUCompleteOverlappedRequest(SOCKET s, LPWSAOVERLAPPED overlapped,
453 DWORD error, DWORD transferred, LPINT errcode)
455 FIXME( "socket %#Ix, overlapped %p, error %lu, transferred %lu, errcode %p, stub!\n",
456 s, overlapped, error, transferred, errcode );
458 if (errcode)
459 *errcode = WSAEINVAL;
461 return NULL;