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 * Dito 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
)
297 if( optlen
) optlen32
= *optlen
; else p
= NULL
;
298 retVal
= WS_getsockopt( s
, level
, optname
, optval
, p
);
299 if( optlen
) *optlen
= optlen32
;
303 /***********************************************************************
304 * inet_ntoa (WINSOCK.11)
306 SEGPTR WINAPI
inet_ntoa16(struct WS_in_addr in
)
309 if (!(retVal
= WS_inet_ntoa( in
))) return 0;
310 if (!dbuffer_seg
) dbuffer_seg
= MapLS( retVal
);
314 /***********************************************************************
315 * ioctlsocket (WINSOCK.12)
317 INT16 WINAPI
ioctlsocket16(SOCKET16 s
, LONG cmd
, ULONG
*argp
)
319 return WS_ioctlsocket( s
, cmd
, argp
);
322 /***********************************************************************
323 * listen (WINSOCK.13)
325 INT16 WINAPI
listen16(SOCKET16 s
, INT16 backlog
)
327 return WS_listen( s
, backlog
);
330 /***********************************************************************
333 INT16 WINAPI
recv16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
335 return WS_recv( s
, buf
, len
, flags
);
338 /***********************************************************************
339 * recvfrom (WINSOCK.17)
341 INT16 WINAPI
recvfrom16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
342 struct WS_sockaddr
*from
, INT16
*fromlen16
)
346 INT fromlen32
= *fromlen16
;
347 INT retVal
= WS_recvfrom( s
, buf
, len
, flags
, from
, &fromlen32
);
348 *fromlen16
= fromlen32
;
351 else return WS_recvfrom( s
, buf
, len
, flags
, from
, NULL
);
354 /***********************************************************************
355 * select (WINSOCK.18)
357 INT16 WINAPI
select16(INT16 nfds
, ws_fd_set16
*ws_readfds
,
358 ws_fd_set16
*ws_writefds
, ws_fd_set16
*ws_exceptfds
,
359 struct WS_timeval
* timeout
)
361 WS_fd_set read_set
, write_set
, except_set
;
362 WS_fd_set
*pread_set
= NULL
, *pwrite_set
= NULL
, *pexcept_set
= NULL
;
365 if (ws_readfds
) pread_set
= ws_fdset_16_to_32( ws_readfds
, &read_set
);
366 if (ws_writefds
) pwrite_set
= ws_fdset_16_to_32( ws_writefds
, &write_set
);
367 if (ws_exceptfds
) pexcept_set
= ws_fdset_16_to_32( ws_exceptfds
, &except_set
);
368 /* struct timeval is the same for both 32- and 16-bit code */
369 ret
= WS_select( nfds
, pread_set
, pwrite_set
, pexcept_set
, timeout
);
370 if (ws_readfds
) ws_fdset_32_to_16( &read_set
, ws_readfds
);
371 if (ws_writefds
) ws_fdset_32_to_16( &write_set
, ws_writefds
);
372 if (ws_exceptfds
) ws_fdset_32_to_16( &except_set
, ws_exceptfds
);
376 /***********************************************************************
379 INT16 WINAPI
send16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
381 return WS_send( s
, buf
, len
, flags
);
384 /***********************************************************************
385 * sendto (WINSOCK.20)
387 INT16 WINAPI
sendto16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
388 struct WS_sockaddr
*to
, INT16 tolen
)
390 return WS_sendto( s
, buf
, len
, flags
, to
, tolen
);
393 /***********************************************************************
394 * setsockopt (WINSOCK.21)
396 INT16 WINAPI
setsockopt16(SOCKET16 s
, INT16 level
, INT16 optname
,
397 char *optval
, INT16 optlen
)
399 if( !optval
) return SOCKET_ERROR
;
400 return WS_setsockopt( s
, level
, optname
, optval
, optlen
);
403 /***********************************************************************
404 * shutdown (WINSOCK.22)
406 INT16 WINAPI
shutdown16(SOCKET16 s
, INT16 how
)
408 return WS_shutdown( s
, how
);
411 /***********************************************************************
412 * socket (WINSOCK.23)
414 SOCKET16 WINAPI
socket16(INT16 af
, INT16 type
, INT16 protocol
)
416 return WS_socket( af
, type
, protocol
);
419 /***********************************************************************
420 * gethostbyaddr (WINSOCK.51)
422 SEGPTR WINAPI
gethostbyaddr16(const char *addr
, INT16 len
, INT16 type
)
424 struct WS_hostent
*he
;
426 if (!(he
= WS_gethostbyaddr( addr
, len
, type
))) return 0;
427 return ws_hostent_32_to_16( he
);
430 /***********************************************************************
431 * gethostbyname (WINSOCK.52)
433 SEGPTR WINAPI
gethostbyname16(const char *name
)
435 struct WS_hostent
*he
;
437 if (!(he
= WS_gethostbyname( name
))) return 0;
438 return ws_hostent_32_to_16( he
);
441 /***********************************************************************
442 * getprotobyname (WINSOCK.53)
444 SEGPTR WINAPI
getprotobyname16(const char *name
)
446 struct WS_protoent
*pe
;
448 if (!(pe
= WS_getprotobyname( name
))) return 0;
449 return ws_protoent_32_to_16( pe
);
452 /***********************************************************************
453 * getprotobynumber (WINSOCK.54)
455 SEGPTR WINAPI
getprotobynumber16(INT16 number
)
457 struct WS_protoent
*pe
;
459 if (!(pe
= WS_getprotobynumber( number
))) return 0;
460 return ws_protoent_32_to_16( pe
);
463 /***********************************************************************
464 * getservbyname (WINSOCK.55)
466 SEGPTR WINAPI
getservbyname16(const char *name
, const char *proto
)
468 struct WS_servent
*se
;
470 if (!(se
= WS_getservbyname( name
, proto
))) return 0;
471 return ws_servent_32_to_16( se
);
474 /***********************************************************************
475 * getservbyport (WINSOCK.56)
477 SEGPTR WINAPI
getservbyport16(INT16 port
, const char *proto
)
479 struct WS_servent
*se
;
481 if (!(se
= WS_getservbyport( port
, proto
))) return 0;
482 return ws_servent_32_to_16( se
);
485 /***********************************************************************
486 * gethostname (WINSOCK.57)
488 INT16 WINAPI
gethostname16(char *name
, INT16 namelen
)
490 return WS_gethostname(name
, namelen
);
493 /***********************************************************************
494 * WSAAsyncSelect (WINSOCK.101)
496 INT16 WINAPI
WSAAsyncSelect16(SOCKET16 s
, HWND16 hWnd
, UINT16 wMsg
, LONG lEvent
)
498 return WSAAsyncSelect( s
, HWND_32(hWnd
), wMsg
, lEvent
);
501 /***********************************************************************
502 * WSASetBlockingHook (WINSOCK.109)
504 FARPROC16 WINAPI
WSASetBlockingHook16(FARPROC16 lpBlockFunc
)
506 /* FIXME: should deal with 16-bit proc */
507 return (FARPROC16
)WSASetBlockingHook( (FARPROC
)lpBlockFunc
);
510 /***********************************************************************
511 * WSAUnhookBlockingHook (WINSOCK.110)
513 INT16 WINAPI
WSAUnhookBlockingHook16(void)
515 return WSAUnhookBlockingHook();
518 /***********************************************************************
519 * WSASetLastError (WINSOCK.112)
521 void WINAPI
WSASetLastError16(INT16 iError
)
523 WSASetLastError(iError
);
526 /***********************************************************************
527 * WSAStartup (WINSOCK.115)
529 * Create socket control struct, attach it to the global list and
530 * update a pointer in the task struct.
532 INT16 WINAPI
WSAStartup16(UINT16 wVersionRequested
, LPWSADATA16 lpWSAData
)
535 INT ret
= WSAStartup( wVersionRequested
, &data
);
539 lpWSAData
->wVersion
= 0x0101;
540 lpWSAData
->wHighVersion
= 0x0101;
541 strcpy( lpWSAData
->szDescription
, data
.szDescription
);
542 strcpy( lpWSAData
->szSystemStatus
, data
.szSystemStatus
);
543 lpWSAData
->iMaxSockets
= data
.iMaxSockets
;
544 lpWSAData
->iMaxUdpDg
= data
.iMaxUdpDg
;
545 lpWSAData
->lpVendorInfo
= 0;
551 /***********************************************************************
552 * WSACleanup (WINSOCK.116)
554 INT WINAPI
WSACleanup16(void)
560 /* delete scratch buffers */
561 UnMapLS( he_buffer_seg
);
562 UnMapLS( se_buffer_seg
);
563 UnMapLS( pe_buffer_seg
);
564 UnMapLS( dbuffer_seg
);
569 HeapFree( GetProcessHeap(), 0, he_buffer
);
570 HeapFree( GetProcessHeap(), 0, se_buffer
);
571 HeapFree( GetProcessHeap(), 0, pe_buffer
);
581 /***********************************************************************
582 * __WSAFDIsSet (WINSOCK.151)
584 INT16 WINAPI
__WSAFDIsSet16(SOCKET16 s
, ws_fd_set16
*set
)
586 int i
= set
->fd_count
;
588 TRACE("(%d,%p(%i))\n", s
, set
, i
);
591 if (set
->fd_array
[i
] == s
) return 1;
595 /***********************************************************************
596 * WSARecvEx (WINSOCK.1107)
598 * See description for WSARecvEx()
600 INT16 WINAPI
WSARecvEx16(SOCKET16 s
, char *buf
, INT16 len
, INT16
*flags
)
602 FIXME("(WSARecvEx16) partial packet return value not set\n");
603 return recv16(s
, buf
, len
, *flags
);