2 * 16-bit socket functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka
5 * Copyright (C) 2003 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
23 #include "wine/port.h"
26 #include "wine/winbase16.h"
27 #include "wine/winsock16.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
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
;
42 extern int WINAPI
WS_gethostname(char *name
, int namelen
);
44 static WS_fd_set
*ws_fdset_16_to_32( const ws_fd_set16
*set16
, WS_fd_set
*set32
)
47 set32
->fd_count
= set16
->fd_count
;
48 for (i
= 0; i
< set32
->fd_count
; i
++) set32
->fd_array
[i
] = set16
->fd_array
[i
];
52 static ws_fd_set16
*ws_fdset_32_to_16( const WS_fd_set
*set32
, ws_fd_set16
*set16
)
55 set16
->fd_count
= set32
->fd_count
;
56 for (i
= 0; i
< set16
->fd_count
; i
++) set16
->fd_array
[i
] = set32
->fd_array
[i
];
60 static int list_size(char** l
, int item_size
)
66 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
67 j
+= (i
+ 1) * sizeof(char*);
72 static int list_dup(char** l_src
, SEGPTR base
, int item_size
)
75 char *ref
= MapSL(base
);
76 SEGPTR
*l_to
= (SEGPTR
*)ref
;
78 for (i
= 0; l_src
[i
]; i
++) ;
79 offset
= (i
+ 1) * sizeof(char*);
80 for (i
= 0; l_src
[i
]; i
++)
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
;
91 static SEGPTR
get_buffer_he(int size
)
96 if (he_len
>= size
) return he_buffer_seg
;
97 UnMapLS( he_buffer_seg
);
98 HeapFree( GetProcessHeap(), 0, he_buffer
);
100 he_buffer
= HeapAlloc( GetProcessHeap(), 0, (he_len
= size
) );
101 he_buffer_seg
= MapLS( he_buffer
);
102 return he_buffer_seg
;
105 static SEGPTR
get_buffer_se(int size
)
110 if (se_len
>= size
) return se_buffer_seg
;
111 UnMapLS( se_buffer_seg
);
112 HeapFree( GetProcessHeap(), 0, se_buffer
);
114 se_buffer
= HeapAlloc( GetProcessHeap(), 0, (se_len
= size
) );
115 se_buffer_seg
= MapLS( se_buffer
);
116 return se_buffer_seg
;
119 static SEGPTR
get_buffer_pe(int size
)
124 if (pe_len
>= size
) return pe_buffer_seg
;
125 UnMapLS( pe_buffer_seg
);
126 HeapFree( GetProcessHeap(), 0, pe_buffer
);
128 pe_buffer
= HeapAlloc( GetProcessHeap(), 0, (pe_len
= size
) );
129 pe_buffer_seg
= MapLS( pe_buffer
);
130 return pe_buffer_seg
;
133 /* duplicate hostent entry
134 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
135 * Ditto for protoent and servent.
137 static SEGPTR
ws_hostent_32_to_16( const struct WS_hostent
* he
)
141 struct ws_hostent16
*p_to
;
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
));
148 base
= get_buffer_he(size
);
151 p_to
->h_addrtype
= he
->h_addrtype
;
152 p_to
->h_length
= he
->h_length
;
154 p
= (char *)(p_to
+ 1);
155 p_to
->h_name
= base
+ (p
- (char *)p_to
);
156 strcpy(p
, he
->h_name
);
159 p_to
->h_aliases
= base
+ (p
- (char *)p_to
);
160 p
+= list_dup(he
->h_aliases
, p_to
->h_aliases
, 0);
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
);
168 static SEGPTR
ws_protoent_32_to_16( const struct WS_protoent
*pe
)
172 struct ws_protoent16
*p_to
;
174 int size
= (sizeof(*pe
) +
175 strlen(pe
->p_name
) + 1 +
176 list_size(pe
->p_aliases
, 0));
178 base
= get_buffer_pe(size
);
181 p_to
->p_proto
= pe
->p_proto
;
182 p
= (char *)(p_to
+ 1);
184 p_to
->p_name
= base
+ (p
- (char *)p_to
);
185 strcpy(p
, pe
->p_name
);
188 p_to
->p_aliases
= base
+ (p
- (char *)p_to
);
189 list_dup(pe
->p_aliases
, p_to
->p_aliases
, 0);
194 static SEGPTR
ws_servent_32_to_16( const struct WS_servent
*se
)
198 struct ws_servent16
*p_to
;
200 int size
= (sizeof(*se
) +
201 strlen(se
->s_proto
) + 1 +
202 strlen(se
->s_name
) + 1 +
203 list_size(se
->s_aliases
, 0));
205 base
= get_buffer_se(size
);
208 p_to
->s_port
= se
->s_port
;
209 p
= (char *)(p_to
+ 1);
211 p_to
->s_name
= base
+ (p
- (char *)p_to
);
212 strcpy(p
, se
->s_name
);
215 p_to
->s_proto
= base
+ (p
- (char *)p_to
);
216 strcpy(p
, se
->s_proto
);
219 p_to
->s_aliases
= base
+ (p
- (char *)p_to
);
220 list_dup(se
->s_aliases
, p_to
->s_aliases
, 0);
226 /***********************************************************************
229 SOCKET16 WINAPI
accept16(SOCKET16 s
, struct WS_sockaddr
* addr
, INT16
* addrlen16
)
231 INT addrlen32
= addrlen16
? *addrlen16
: 0;
232 SOCKET retSocket
= WS_accept( s
, addr
, &addrlen32
);
233 if( addrlen16
) *addrlen16
= addrlen32
;
237 /***********************************************************************
240 INT16 WINAPI
bind16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16 namelen
)
242 return WS_bind( s
, name
, namelen
);
245 /***********************************************************************
246 * closesocket (WINSOCK.3)
248 INT16 WINAPI
closesocket16(SOCKET16 s
)
250 return WS_closesocket(s
);
253 /***********************************************************************
254 * connect (WINSOCK.4)
256 INT16 WINAPI
connect16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16 namelen
)
258 return WS_connect( s
, name
, namelen
);
261 /***********************************************************************
262 * getpeername (WINSOCK.5)
264 INT16 WINAPI
getpeername16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16
*namelen16
)
266 INT namelen32
= *namelen16
;
267 INT retVal
= WS_getpeername( s
, name
, &namelen32
);
268 *namelen16
= namelen32
;
272 /***********************************************************************
273 * getsockname (WINSOCK.6)
275 INT16 WINAPI
getsockname16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16
*namelen16
)
281 INT namelen32
= *namelen16
;
282 retVal
= WS_getsockname( s
, name
, &namelen32
);
283 *namelen16
= namelen32
;
285 else retVal
= SOCKET_ERROR
;
289 /***********************************************************************
290 * getsockopt (WINSOCK.7)
292 INT16 WINAPI
getsockopt16(SOCKET16 s
, INT16 level
, INT16 optname
, char *optval
, INT16
*optlen
)
298 if( optlen
) optlen32
= *optlen
; else p
= NULL
;
299 retVal
= WS_getsockopt( s
, (WORD
)level
, optname
, optval
, p
);
300 if( optlen
) *optlen
= optlen32
;
304 /***********************************************************************
305 * inet_ntoa (WINSOCK.11)
307 SEGPTR WINAPI
inet_ntoa16(struct WS_in_addr in
)
310 if (!(retVal
= WS_inet_ntoa( in
))) return 0;
311 if (!dbuffer_seg
) dbuffer_seg
= MapLS( retVal
);
315 /***********************************************************************
316 * ioctlsocket (WINSOCK.12)
318 INT16 WINAPI
ioctlsocket16(SOCKET16 s
, LONG cmd
, ULONG
*argp
)
320 return WS_ioctlsocket( s
, cmd
, argp
);
323 /***********************************************************************
324 * listen (WINSOCK.13)
326 INT16 WINAPI
listen16(SOCKET16 s
, INT16 backlog
)
328 return WS_listen( s
, backlog
);
331 /***********************************************************************
334 INT16 WINAPI
recv16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
336 return WS_recv( s
, buf
, len
, flags
);
339 /***********************************************************************
340 * recvfrom (WINSOCK.17)
342 INT16 WINAPI
recvfrom16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
343 struct WS_sockaddr
*from
, INT16
*fromlen16
)
347 INT fromlen32
= *fromlen16
;
348 INT retVal
= WS_recvfrom( s
, buf
, len
, flags
, from
, &fromlen32
);
349 *fromlen16
= fromlen32
;
352 else return WS_recvfrom( s
, buf
, len
, flags
, from
, NULL
);
355 /***********************************************************************
356 * select (WINSOCK.18)
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
)
362 WS_fd_set read_set
, write_set
, except_set
;
363 WS_fd_set
*pread_set
= NULL
, *pwrite_set
= NULL
, *pexcept_set
= NULL
;
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
);
377 /***********************************************************************
380 INT16 WINAPI
send16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
382 return WS_send( s
, buf
, len
, flags
);
385 /***********************************************************************
386 * sendto (WINSOCK.20)
388 INT16 WINAPI
sendto16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
389 struct WS_sockaddr
*to
, INT16 tolen
)
391 return WS_sendto( s
, buf
, len
, flags
, to
, tolen
);
394 /***********************************************************************
395 * setsockopt (WINSOCK.21)
397 INT16 WINAPI
setsockopt16(SOCKET16 s
, INT16 level
, INT16 optname
,
398 char *optval
, INT16 optlen
)
400 if( !optval
) return SOCKET_ERROR
;
401 return WS_setsockopt( s
, (WORD
)level
, optname
, optval
, optlen
);
404 /***********************************************************************
405 * shutdown (WINSOCK.22)
407 INT16 WINAPI
shutdown16(SOCKET16 s
, INT16 how
)
409 return WS_shutdown( s
, how
);
412 /***********************************************************************
413 * socket (WINSOCK.23)
415 SOCKET16 WINAPI
socket16(INT16 af
, INT16 type
, INT16 protocol
)
417 return WS_socket( af
, type
, protocol
);
420 /***********************************************************************
421 * gethostbyaddr (WINSOCK.51)
423 SEGPTR WINAPI
gethostbyaddr16(const char *addr
, INT16 len
, INT16 type
)
425 struct WS_hostent
*he
;
427 if (!(he
= WS_gethostbyaddr( addr
, len
, type
))) return 0;
428 return ws_hostent_32_to_16( he
);
431 /***********************************************************************
432 * gethostbyname (WINSOCK.52)
434 SEGPTR WINAPI
gethostbyname16(const char *name
)
436 struct WS_hostent
*he
;
438 if (!(he
= WS_gethostbyname( name
))) return 0;
439 return ws_hostent_32_to_16( he
);
442 /***********************************************************************
443 * getprotobyname (WINSOCK.53)
445 SEGPTR WINAPI
getprotobyname16(const char *name
)
447 struct WS_protoent
*pe
;
449 if (!(pe
= WS_getprotobyname( name
))) return 0;
450 return ws_protoent_32_to_16( pe
);
453 /***********************************************************************
454 * getprotobynumber (WINSOCK.54)
456 SEGPTR WINAPI
getprotobynumber16(INT16 number
)
458 struct WS_protoent
*pe
;
460 if (!(pe
= WS_getprotobynumber( number
))) return 0;
461 return ws_protoent_32_to_16( pe
);
464 /***********************************************************************
465 * getservbyname (WINSOCK.55)
467 SEGPTR WINAPI
getservbyname16(const char *name
, const char *proto
)
469 struct WS_servent
*se
;
471 if (!(se
= WS_getservbyname( name
, proto
))) return 0;
472 return ws_servent_32_to_16( se
);
475 /***********************************************************************
476 * getservbyport (WINSOCK.56)
478 SEGPTR WINAPI
getservbyport16(INT16 port
, const char *proto
)
480 struct WS_servent
*se
;
482 if (!(se
= WS_getservbyport( port
, proto
))) return 0;
483 return ws_servent_32_to_16( se
);
486 /***********************************************************************
487 * gethostname (WINSOCK.57)
489 INT16 WINAPI
gethostname16(char *name
, INT16 namelen
)
491 return WS_gethostname(name
, namelen
);
494 /***********************************************************************
495 * WSAAsyncSelect (WINSOCK.101)
497 INT16 WINAPI
WSAAsyncSelect16(SOCKET16 s
, HWND16 hWnd
, UINT16 wMsg
, LONG lEvent
)
499 return WSAAsyncSelect( s
, HWND_32(hWnd
), wMsg
, lEvent
);
502 /***********************************************************************
503 * WSASetBlockingHook (WINSOCK.109)
505 FARPROC16 WINAPI
WSASetBlockingHook16(FARPROC16 lpBlockFunc
)
507 /* FIXME: should deal with 16-bit proc */
508 return (FARPROC16
)WSASetBlockingHook( (FARPROC
)lpBlockFunc
);
511 /***********************************************************************
512 * WSAUnhookBlockingHook (WINSOCK.110)
514 INT16 WINAPI
WSAUnhookBlockingHook16(void)
516 return WSAUnhookBlockingHook();
519 /***********************************************************************
520 * WSASetLastError (WINSOCK.112)
522 void WINAPI
WSASetLastError16(INT16 iError
)
524 WSASetLastError(iError
);
527 /***********************************************************************
528 * WSAStartup (WINSOCK.115)
530 * Create socket control struct, attach it to the global list and
531 * update a pointer in the task struct.
533 INT16 WINAPI
WSAStartup16(UINT16 wVersionRequested
, LPWSADATA16 lpWSAData
)
536 INT ret
= WSAStartup( wVersionRequested
, &data
);
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;
552 /***********************************************************************
553 * WSACleanup (WINSOCK.116)
555 INT WINAPI
WSACleanup16(void)
561 /* delete scratch buffers */
562 UnMapLS( he_buffer_seg
);
563 UnMapLS( se_buffer_seg
);
564 UnMapLS( pe_buffer_seg
);
565 UnMapLS( dbuffer_seg
);
570 HeapFree( GetProcessHeap(), 0, he_buffer
);
571 HeapFree( GetProcessHeap(), 0, se_buffer
);
572 HeapFree( GetProcessHeap(), 0, pe_buffer
);
582 /***********************************************************************
583 * __WSAFDIsSet (WINSOCK.151)
585 INT16 WINAPI
__WSAFDIsSet16(SOCKET16 s
, ws_fd_set16
*set
)
587 int i
= set
->fd_count
;
589 TRACE("(%d,%p(%i))\n", s
, set
, i
);
592 if (set
->fd_array
[i
] == s
) return 1;
596 /***********************************************************************
597 * WSARecvEx (WINSOCK.1107)
599 * See description for WSARecvEx()
601 INT16 WINAPI
WSARecvEx16(SOCKET16 s
, char *buf
, INT16 len
, INT16
*flags
)
603 FIXME("(WSARecvEx16) partial packet return value not set\n");
604 return recv16(s
, buf
, len
, *flags
);