mshtml: Implement IHTMLCurrentStyle_get_letterSpacing.
[wine] / dlls / ws2_32 / socket16.c
1 /*
2  * 16-bit socket functions
3  *
4  * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka
5  * Copyright (C) 2003 Alexandre Julliard
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include "winsock2.h"
26 #include "wine/winbase16.h"
27 #include "wine/winsock16.h"
28 #include "wownt32.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
32
33 static INT num_startup;  /* reference counter */
34 static void *he_buffer;
35 static SEGPTR he_buffer_seg;
36 static void *se_buffer;
37 static SEGPTR se_buffer_seg;
38 static void *pe_buffer;
39 static SEGPTR pe_buffer_seg;
40 static SEGPTR dbuffer_seg;
41
42 extern int WINAPI WS_gethostname(char *name, int namelen);
43
44 static WS_fd_set *ws_fdset_16_to_32( const ws_fd_set16 *set16, WS_fd_set *set32 )
45 {
46     UINT i;
47     set32->fd_count = set16->fd_count;
48     for (i = 0; i < set32->fd_count; i++) set32->fd_array[i] = set16->fd_array[i];
49     return set32;
50 }
51
52 static ws_fd_set16 *ws_fdset_32_to_16( const WS_fd_set *set32, ws_fd_set16 *set16 )
53 {
54     UINT i;
55     set16->fd_count = set32->fd_count;
56     for (i = 0; i < set16->fd_count; i++) set16->fd_array[i] = set32->fd_array[i];
57     return set16;
58 }
59
60 static int list_size(char** l, int item_size)
61 {
62     int i,j = 0;
63     if(l)
64     {
65         for(i=0;l[i];i++)
66             j += (item_size) ? item_size : strlen(l[i]) + 1;
67         j += (i + 1) * sizeof(char*);
68     }
69     return j;
70 }
71
72 static int list_dup(char** l_src, SEGPTR base, int item_size)
73 {
74     int i, offset;
75     char *ref = MapSL(base);
76     SEGPTR *l_to = (SEGPTR *)ref;
77
78     for (i = 0; l_src[i]; i++) ;
79     offset = (i + 1) * sizeof(char*);
80     for (i = 0; l_src[i]; i++)
81     {
82         int count = item_size ? item_size : strlen(l_src[i]) + 1;
83         memcpy( ref + offset, l_src[i], count );
84         l_to[i] = base + offset;
85         offset += count;
86     }
87     l_to[i] = 0;
88     return offset;
89 }
90
91 static SEGPTR get_buffer_he(int size)
92 {
93     static int he_len;
94     if (he_buffer)
95     {
96         if (he_len >= size ) return he_buffer_seg;
97         UnMapLS( he_buffer_seg );
98         HeapFree( GetProcessHeap(), 0, he_buffer );
99     }
100     he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
101     he_buffer_seg = MapLS( he_buffer );
102     return he_buffer_seg;
103 }
104
105 static SEGPTR get_buffer_se(int size)
106 {
107     static int se_len;
108     if (se_buffer)
109     {
110         if (se_len >= size ) return se_buffer_seg;
111         UnMapLS( se_buffer_seg );
112         HeapFree( GetProcessHeap(), 0, se_buffer );
113     }
114     se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
115     se_buffer_seg = MapLS( se_buffer );
116     return se_buffer_seg;
117 }
118
119 static SEGPTR get_buffer_pe(int size)
120 {
121     static int pe_len;
122     if (pe_buffer)
123     {
124         if (pe_len >= size ) return pe_buffer_seg;
125         UnMapLS( pe_buffer_seg );
126         HeapFree( GetProcessHeap(), 0, pe_buffer );
127     }
128     pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
129     pe_buffer_seg = MapLS( pe_buffer );
130     return pe_buffer_seg;
131 }
132
133 /* duplicate hostent entry
134  * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
135  * Ditto for protoent and servent.
136  */
137 static SEGPTR ws_hostent_32_to_16( const struct WS_hostent* he )
138 {
139     char *p;
140     SEGPTR base;
141     struct ws_hostent16 *p_to;
142
143     int size = (sizeof(*he) +
144                 strlen(he->h_name) + 1 +
145                 list_size(he->h_aliases, 0) +
146                 list_size(he->h_addr_list, he->h_length));
147
148     base = get_buffer_he(size);
149     p_to = MapSL(base);
150
151     p_to->h_addrtype = he->h_addrtype;
152     p_to->h_length = he->h_length;
153
154     p = (char *)(p_to + 1);
155     p_to->h_name = base + (p - (char *)p_to);
156     strcpy(p, he->h_name);
157     p += strlen(p) + 1;
158
159     p_to->h_aliases = base + (p - (char *)p_to);
160     p += list_dup(he->h_aliases, p_to->h_aliases, 0);
161
162     p_to->h_addr_list = base + (p - (char *)p_to);
163     list_dup(he->h_addr_list, p_to->h_addr_list, he->h_length);
164
165     return base;
166 }
167
168 static SEGPTR ws_protoent_32_to_16( const struct WS_protoent *pe )
169 {
170     char *p;
171     SEGPTR base;
172     struct ws_protoent16 *p_to;
173
174     int size = (sizeof(*pe) +
175                 strlen(pe->p_name) + 1 +
176                 list_size(pe->p_aliases, 0));
177
178     base = get_buffer_pe(size);
179     p_to = MapSL(base);
180
181     p_to->p_proto = pe->p_proto;
182     p = (char *)(p_to + 1);
183
184     p_to->p_name = base + (p - (char *)p_to);
185     strcpy(p, pe->p_name);
186     p += strlen(p) + 1;
187
188     p_to->p_aliases = base + (p - (char *)p_to);
189     list_dup(pe->p_aliases, p_to->p_aliases, 0);
190
191     return base;
192 }
193
194 static SEGPTR ws_servent_32_to_16( const struct WS_servent *se )
195 {
196     char *p;
197     SEGPTR base;
198     struct ws_servent16 *p_to;
199
200     int size = (sizeof(*se) +
201                 strlen(se->s_proto) + 1 +
202                 strlen(se->s_name) + 1 +
203                 list_size(se->s_aliases, 0));
204
205     base = get_buffer_se(size);
206     p_to = MapSL(base);
207
208     p_to->s_port = se->s_port;
209     p = (char *)(p_to + 1);
210
211     p_to->s_name = base + (p - (char *)p_to);
212     strcpy(p, se->s_name);
213     p += strlen(p) + 1;
214
215     p_to->s_proto = base + (p - (char *)p_to);
216     strcpy(p, se->s_proto);
217     p += strlen(p) + 1;
218
219     p_to->s_aliases = base + (p - (char *)p_to);
220     list_dup(se->s_aliases, p_to->s_aliases, 0);
221
222     return base;
223 }
224
225
226 /***********************************************************************
227  *              accept          (WINSOCK.1)
228  */
229 SOCKET16 WINAPI accept16(SOCKET16 s, struct WS_sockaddr* addr, INT16* addrlen16 )
230 {
231     INT addrlen32 = addrlen16 ? *addrlen16 : 0;
232     SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
233     if( addrlen16 ) *addrlen16 = addrlen32;
234     return retSocket;
235 }
236
237 /***********************************************************************
238  *              bind                    (WINSOCK.2)
239  */
240 INT16 WINAPI bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
241 {
242     return WS_bind( s, name, namelen );
243 }
244
245 /***********************************************************************
246  *              closesocket           (WINSOCK.3)
247  */
248 INT16 WINAPI closesocket16(SOCKET16 s)
249 {
250     return WS_closesocket(s);
251 }
252
253 /***********************************************************************
254  *              connect               (WINSOCK.4)
255  */
256 INT16 WINAPI connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
257 {
258     return WS_connect( s, name, namelen );
259 }
260
261 /***********************************************************************
262  *              getpeername             (WINSOCK.5)
263  */
264 INT16 WINAPI getpeername16(SOCKET16 s, struct WS_sockaddr *name, INT16 *namelen16)
265 {
266     INT namelen32 = *namelen16;
267     INT retVal = WS_getpeername( s, name, &namelen32 );
268    *namelen16 = namelen32;
269     return retVal;
270 }
271
272 /***********************************************************************
273  *              getsockname             (WINSOCK.6)
274  */
275 INT16 WINAPI getsockname16(SOCKET16 s, struct WS_sockaddr *name, INT16 *namelen16)
276 {
277     INT retVal;
278
279     if( namelen16 )
280     {
281         INT namelen32 = *namelen16;
282         retVal = WS_getsockname( s, name, &namelen32 );
283        *namelen16 = namelen32;
284     }
285     else retVal = SOCKET_ERROR;
286     return retVal;
287 }
288
289 /***********************************************************************
290  *              getsockopt              (WINSOCK.7)
291  */
292 INT16 WINAPI getsockopt16(SOCKET16 s, INT16 level, INT16 optname, char *optval, INT16 *optlen)
293 {
294     INT optlen32;
295     INT *p = &optlen32;
296     INT retVal;
297
298     if( optlen ) optlen32 = *optlen; else p = NULL;
299     retVal = WS_getsockopt( s, (WORD)level, optname, optval, p );
300     if( optlen ) *optlen = optlen32;
301     return retVal;
302 }
303
304 /***********************************************************************
305  *              inet_ntoa               (WINSOCK.11)
306  */
307 SEGPTR WINAPI inet_ntoa16(struct WS_in_addr in)
308 {
309     char* retVal;
310     if (!(retVal = WS_inet_ntoa( in ))) return 0;
311     if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
312     return dbuffer_seg;
313 }
314
315 /***********************************************************************
316  *              ioctlsocket           (WINSOCK.12)
317  */
318 INT16 WINAPI ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
319 {
320     return WS_ioctlsocket( s, cmd, argp );
321 }
322
323 /***********************************************************************
324  *              listen          (WINSOCK.13)
325  */
326 INT16 WINAPI listen16(SOCKET16 s, INT16 backlog)
327 {
328     return WS_listen( s, backlog );
329 }
330
331 /***********************************************************************
332  *              recv                    (WINSOCK.16)
333  */
334 INT16 WINAPI recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
335 {
336     return WS_recv( s, buf, len, flags );
337 }
338
339 /***********************************************************************
340  *              recvfrom                (WINSOCK.17)
341  */
342 INT16 WINAPI recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
343                         struct WS_sockaddr *from, INT16 *fromlen16)
344 {
345     if (fromlen16)
346     {
347         INT fromlen32 = *fromlen16;
348         INT retVal = WS_recvfrom( s, buf, len, flags, from, &fromlen32 );
349         *fromlen16 = fromlen32;
350         return retVal;
351     }
352     else return WS_recvfrom( s, buf, len, flags, from, NULL );
353 }
354
355 /***********************************************************************
356  *              select                  (WINSOCK.18)
357  */
358 INT16 WINAPI select16(INT16 nfds, ws_fd_set16 *ws_readfds,
359                       ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
360                       struct WS_timeval* timeout)
361 {
362     WS_fd_set read_set, write_set, except_set;
363     WS_fd_set *pread_set = NULL, *pwrite_set = NULL, *pexcept_set = NULL;
364     int ret;
365
366     if (ws_readfds) pread_set = ws_fdset_16_to_32( ws_readfds, &read_set );
367     if (ws_writefds) pwrite_set = ws_fdset_16_to_32( ws_writefds, &write_set );
368     if (ws_exceptfds) pexcept_set = ws_fdset_16_to_32( ws_exceptfds, &except_set );
369     /* struct timeval is the same for both 32- and 16-bit code */
370     ret = WS_select( nfds, pread_set, pwrite_set, pexcept_set, timeout );
371     if (ws_readfds) ws_fdset_32_to_16( &read_set, ws_readfds );
372     if (ws_writefds) ws_fdset_32_to_16( &write_set, ws_writefds );
373     if (ws_exceptfds) ws_fdset_32_to_16( &except_set, ws_exceptfds );
374     return ret;
375 }
376
377 /***********************************************************************
378  *              send                    (WINSOCK.19)
379  */
380 INT16 WINAPI send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
381 {
382     return WS_send( s, buf, len, flags );
383 }
384
385 /***********************************************************************
386  *              sendto          (WINSOCK.20)
387  */
388 INT16 WINAPI sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
389                       struct WS_sockaddr *to, INT16 tolen)
390 {
391     return WS_sendto( s, buf, len, flags, to, tolen );
392 }
393
394 /***********************************************************************
395  *              setsockopt              (WINSOCK.21)
396  */
397 INT16 WINAPI setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
398                           char *optval, INT16 optlen)
399 {
400     if( !optval ) return SOCKET_ERROR;
401     return WS_setsockopt( s, (WORD)level, optname, optval, optlen );
402 }
403
404 /***********************************************************************
405  *              shutdown                (WINSOCK.22)
406  */
407 INT16 WINAPI shutdown16(SOCKET16 s, INT16 how)
408 {
409     return WS_shutdown( s, how );
410 }
411
412 /***********************************************************************
413  *              socket          (WINSOCK.23)
414  */
415 SOCKET16 WINAPI socket16(INT16 af, INT16 type, INT16 protocol)
416 {
417     return WS_socket( af, type, protocol );
418 }
419
420 /***********************************************************************
421  *              gethostbyaddr           (WINSOCK.51)
422  */
423 SEGPTR WINAPI gethostbyaddr16(const char *addr, INT16 len, INT16 type)
424 {
425     struct WS_hostent *he;
426
427     if (!(he = WS_gethostbyaddr( addr, len, type ))) return 0;
428     return ws_hostent_32_to_16( he );
429 }
430
431 /***********************************************************************
432  *              gethostbyname           (WINSOCK.52)
433  */
434 SEGPTR WINAPI gethostbyname16(const char *name)
435 {
436     struct WS_hostent *he;
437
438     if (!(he = WS_gethostbyname( name ))) return 0;
439     return ws_hostent_32_to_16( he );
440 }
441
442 /***********************************************************************
443  *              getprotobyname          (WINSOCK.53)
444  */
445 SEGPTR WINAPI getprotobyname16(const char *name)
446 {
447     struct WS_protoent *pe;
448
449     if (!(pe = WS_getprotobyname( name ))) return 0;
450     return ws_protoent_32_to_16( pe );
451 }
452
453 /***********************************************************************
454  *              getprotobynumber        (WINSOCK.54)
455  */
456 SEGPTR WINAPI getprotobynumber16(INT16 number)
457 {
458     struct WS_protoent *pe;
459
460     if (!(pe = WS_getprotobynumber( number ))) return 0;
461     return ws_protoent_32_to_16( pe );
462 }
463
464 /***********************************************************************
465  *              getservbyname           (WINSOCK.55)
466  */
467 SEGPTR WINAPI getservbyname16(const char *name, const char *proto)
468 {
469     struct WS_servent *se;
470
471     if (!(se = WS_getservbyname( name, proto ))) return 0;
472     return ws_servent_32_to_16( se );
473 }
474
475 /***********************************************************************
476  *              getservbyport           (WINSOCK.56)
477  */
478 SEGPTR WINAPI getservbyport16(INT16 port, const char *proto)
479 {
480     struct WS_servent *se;
481
482     if (!(se = WS_getservbyport( port, proto ))) return 0;
483     return ws_servent_32_to_16( se );
484 }
485
486 /***********************************************************************
487  *              gethostname           (WINSOCK.57)
488  */
489 INT16 WINAPI gethostname16(char *name, INT16 namelen)
490 {
491     return WS_gethostname(name, namelen);
492 }
493
494 /***********************************************************************
495  *      WSAAsyncSelect          (WINSOCK.101)
496  */
497 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
498 {
499     return WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
500 }
501
502 /***********************************************************************
503  *      WSASetBlockingHook              (WINSOCK.109)
504  */
505 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
506 {
507     /* FIXME: should deal with 16-bit proc */
508     return (FARPROC16)WSASetBlockingHook( (FARPROC)lpBlockFunc );
509 }
510
511 /***********************************************************************
512  *      WSAUnhookBlockingHook   (WINSOCK.110)
513  */
514 INT16 WINAPI WSAUnhookBlockingHook16(void)
515 {
516     return WSAUnhookBlockingHook();
517 }
518
519 /***********************************************************************
520  *      WSASetLastError         (WINSOCK.112)
521  */
522 void WINAPI WSASetLastError16(INT16 iError)
523 {
524     WSASetLastError(iError);
525 }
526
527 /***********************************************************************
528  *      WSAStartup                      (WINSOCK.115)
529  *
530  * Create socket control struct, attach it to the global list and
531  * update a pointer in the task struct.
532  */
533 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
534 {
535     WSADATA data;
536     INT ret = WSAStartup( wVersionRequested, &data );
537
538     if (!ret)
539     {
540         lpWSAData->wVersion     = 0x0101;
541         lpWSAData->wHighVersion = 0x0101;
542         strcpy( lpWSAData->szDescription, data.szDescription );
543         strcpy( lpWSAData->szSystemStatus, data.szSystemStatus );
544         lpWSAData->iMaxSockets = data.iMaxSockets;
545         lpWSAData->iMaxUdpDg = data.iMaxUdpDg;
546         lpWSAData->lpVendorInfo = 0;
547         num_startup++;
548    }
549     return ret;
550 }
551
552 /***********************************************************************
553  *      WSACleanup                      (WINSOCK.116)
554  */
555 INT WINAPI WSACleanup16(void)
556 {
557     if (num_startup)
558     {
559         if (!--num_startup)
560         {
561             /* delete scratch buffers */
562             UnMapLS( he_buffer_seg );
563             UnMapLS( se_buffer_seg );
564             UnMapLS( pe_buffer_seg );
565             UnMapLS( dbuffer_seg );
566             he_buffer_seg = 0;
567             se_buffer_seg = 0;
568             pe_buffer_seg = 0;
569             dbuffer_seg = 0;
570             HeapFree( GetProcessHeap(), 0, he_buffer );
571             HeapFree( GetProcessHeap(), 0, se_buffer );
572             HeapFree( GetProcessHeap(), 0, pe_buffer );
573             he_buffer = NULL;
574             se_buffer = NULL;
575             pe_buffer = NULL;
576         }
577     }
578     return WSACleanup();
579 }
580
581
582 /***********************************************************************
583  *      __WSAFDIsSet                    (WINSOCK.151)
584  */
585 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
586 {
587   int i = set->fd_count;
588
589   TRACE("(%d,%p(%i))\n", s, set, i);
590
591   while (i--)
592       if (set->fd_array[i] == s) return 1;
593   return 0;
594 }
595
596 /***********************************************************************
597  *              WSARecvEx                       (WINSOCK.1107)
598  *
599  * See description for WSARecvEx()
600  */
601 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
602 {
603     FIXME("(WSARecvEx16) partial packet return value not set\n");
604     return recv16(s, buf, len, *flags);
605 }