Release 970824

Sat Aug 23 00:05:23 1997  Andreas Mohr <100.30936@germany.net>

	* [if1632/kernel.spec] [if1632/mmsystem.spec]
	Added some stubs.

	* [include/neexe.h] [loader/module.c]
	Added warning for OS/2 executables.

	* [multimedia/midi.c]
	Shortened MIDIOUT driver version string to be less than 31 chars.

	* [objects/gdiobj.c]
	Fixed DeleteObject32() to react properly when called with stock object.

Fri Aug 22 18:03:26 1997  Dimitrie O. Paun <dimi@cs.toronto.edu>

	* [controls/updown.c] [include/updown.h]
	First attempt at implementiong the UpDown class.

	* [controls/widgets.c]
	Added the UpDown class to be initialized by InitCommonControls().

Wed Aug 20 18:01:33 1997  Doug Ridgway <ridgway@routh.UCSD.EDU>

	* [graphics/*] [objects/*] [include/gdi.h]
	Made all GDI objects (except DCs) moveable.

Mon Aug 18 03:25:30 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [windows/event.c] [misc/winsock.c] [misc/winsock_dns.c]
	Removed IPC communication to speed up winsock services
	(tested only with 16-bit netscape 3.03).

	* [graphics/x11drv/xfont.c] [documentation/fonts]
	Miscellaneous improvements. Updated docs.

Sun Aug 17 20:39:55 1997  Ingo Schneider <schneidi@informatik.tu-muenchen.de>

	* [misc/comm.c]
	A couple of bug fixes.

Sun Aug 17 19:29:22 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [debugger/dbg.y]
	Display next instruction after stepi/nexti.

	* [if1632/relay.c] [include/callback.h] [tools/build.c]
	Replaced CallTo32_LargeStack with the CALL_LARGE_STACK macro for
	better Winelib support.

	* [include/sigcontext.h]
	Renamed to sig_context.h to avoid conflicts with libc.

	* [*/*]
	All API functions are now prefixed with WINAPI in prevision of
	future Winelib integration.

	* [loader/signal.c] [memory/ldt.c]
	Fixed assembly code to be -fPIC compatible.

Thu Aug 14 14:38:15 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [if1632/crtdll.spec][win32/except.c]
	_global_unwind, _local_unwind stub added.

	* [objects/dib.c]	
	Don't read memory you don't even need for the target bitmap (fixes
	one 'lazy' program).

	* [if1632/relay.c][if1632/thunk.c][if1632/kernel32.spec]
	  [win32/ordinals.c][memory/selector.c][memory/global.c]
	  [include/callback.h]
	Added/moved some more win95 ordinal stuff. Implemented QT_Thunk
	(not 100% correct yet) and some friends.

	* [loader/pe_image.c]
	Add possibility to break at the DLL entrypoint.

	* [controls/static.c][misc/commdlg.c][scheduler/thread.c]
	Misc bugfixes and additions.

	* [misc/registry.c]
	The registry seems to be case-preserving but case-insensitive.

	* [memory/global.c]	
	Adapted to new /proc/meminfo format.

	* [objects/font.c][graphics/x11drv/xfont.c]
	FONT_SelectObject and GetTextMetrics* get passed ranges in logical
 	and not device points (thanks to Marion Reyzl for pointing this
 	out).

	* [windows/caret.c]
	Use the windows own DC if present (The caret coordinates are
	logical coordinates based on it). Fixes another AMIPRO problem.

Wed Aug  6 18:22:22 1997  Morten Welinder  <terra@diku.dk>

	* [controls/menu.c]
	General clean-up and Win32 work: split item_flags into fType and
	fState; split item_id into wID and hSubMenu.  Improved
	debug-printing.  Implemented InsertMenuItem32[AW],
	SetMenuDefaultItem32, and SetMenuItemInfo32[AW].  Fixed
	GetMenuItemInfo32[AW].

	* [if1632/user32.spec]
	Define above new functions.

	* [include/windows.h]
	Define MF_DEFAULT and MF_RIGHTJUSTIFY.  Prototype above functions.

	* [include/menu.h]
	Don't prototype now-static MENU_InitSysMenuPopup.

	* [include/comm.h]
	Reduce MAX_PORTS to 9 (which the profile code can handle).

Tue Aug  5 20:16:22 1997  Victor Schneider <vischne@ibm.net>

	* [library/winestub.c] [libtest/expand.c]
	These patches let people porting Windows apps compile them using
	the same conventions regarding global _argc and _argv as those on
	Windows C/C++ compilers.
diff --git a/misc/winsock.c b/misc/winsock.c
index 159ed1c..3246b41 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -2,14 +2,9 @@
  * based on Windows Sockets 1.1 specs
  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
  * 
- * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka.
+ * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
  *
- * TODO: Merge Async...() handling with X event loop by adding 
- *	 thread/task fdset to select(2) in windows/event.c.
- *       Also fork dns lookup helper during the startup (with a pipe 
- *	 for communication) and make it fork for a database request
- *	 instead of forking the main process (i.e. something like 
- *	 Netscape 4.0).
+ * TODO: 32-bit asynchronous services.
  */
  
 #include <stdio.h>
@@ -41,6 +36,8 @@
 #include "winnt.h"
 #include "heap.h"
 #include "ldt.h"
+#include "task.h"
+#include "message.h"
 #include "winsock.h"
 #include "miscemu.h"
 #include "stddebug.h"
@@ -57,10 +54,6 @@
 /* ----------------------------------- internal data */
 
 extern int h_errno;
-extern void __sigio(int);
-
-ws_async_ctl            async_ctl;
-int                     async_qid = -1;
 
 static HANDLE32 	_WSHeap = 0;
 static unsigned char*	_ws_stub = NULL;
@@ -74,13 +67,13 @@
 #define WS_PTR2HANDLE(ptr) \
         ((short)((int)(ptr) - (int)_ws_stub))
 #define WS_HANDLE2PTR(handle) \
-        ((unsigned)((int)_ws_stub + (int)handle))
+        ((unsigned)((int)_ws_stub + (int)(handle)))
 
 #define WSI_CHECK_RANGE(pwsi, pws) \
 	( ((unsigned)(pws) > (unsigned)(pwsi)) && \
 	  ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
 
-static INT16         _ws_sock_ops[] =
+static INT32         _ws_sock_ops[] =
        { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
          WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
          WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
@@ -89,28 +82,27 @@
          SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
 	 SO_LINGER };
 
-static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
-static int notify_client(ws_socket* pws, unsigned flag);
-
 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
 static int _check_buffer(LPWSINFO pwsi, int size);
 
-static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
-static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
-static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
+extern void EVENT_AddIO( int fd, unsigned flag );
+extern void EVENT_DeleteIO( int fd, unsigned flag );
 
-static int cancel_async_select(ws_socket*);
-
-static void convert_sockopt(INT16 *level, INT16 *optname)
+/***********************************************************************
+ *          convert_sockopt()
+ *
+ * Converts socket flags from Windows format.
+ */
+static void convert_sockopt(INT32 *level, INT32 *optname)
 {
-  int           i;
+  int i;
   switch (*level)
   {
      case WS_SOL_SOCKET:
         *level = SOL_SOCKET;
         for(i=0; _ws_sock_ops[i]; i++)
             if( _ws_sock_ops[i] == *optname ) break;
-        if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
+        if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
         else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
         break;
      case WS_IPPROTO_TCP:
@@ -118,71 +110,63 @@
   }
 }
 
-static void _ws_global_init()
-{
-   if( !_ws_stub )
-   {
-     _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
-     if( !(_ws_stub = WS_ALLOC(0x10)) )
-       fprintf(stderr,"Fatal: failed to create WinSock heap\n");
-   }
-   if( async_qid == -1 ) 
-     if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
-       fprintf(stderr,"Fatal: failed to create WinSock resource\n");
-}
-
-/* ----------------------------------- Per-thread info */
-
-static void wsi_link(LPWSINFO pwsi)
-{ if( _wsi_list ) _wsi_list->prev = pwsi;
-  pwsi->next = _wsi_list; _wsi_list = pwsi; 
-}
-
-static void wsi_unlink(LPWSINFO pwsi)
-{
-  if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
-  else 
-  { pwsi->prev->next = pwsi->next;
-    if( pwsi->next ) pwsi->next->prev = pwsi->prev; } 
-}
+/* ----------------------------------- Per-thread info (or per-process?) */
 
 static LPWSINFO wsi_find(HTASK16 hTask)
-{ LPWSINFO pwsi = _wsi_list;
-  while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
-  return pwsi; 
+{ 
+    TDB*	   pTask = (TDB*)GlobalLock16(hTask);
+    if( pTask )
+    {
+	if( pTask->pwsi ) return pTask->pwsi;
+	else
+	{
+	    LPWSINFO pwsi = _wsi_list;
+	    while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
+	    if( pwsi )
+		fprintf(stderr,"loose wsi struct! pwsi=0x%08x, task=0x%04x\n", 
+					(unsigned)pwsi, hTask );
+	    return pwsi; 
+	}
+    }
+    return NULL;
 }
 
 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
 {
-  if( pwsi->last_free >= 0 )
-  {
-    int i = pwsi->last_free;
+    /* Initialize a new entry in the socket table */
 
-    pwsi->last_free = pwsi->sock[i].flags;
-    pwsi->sock[i].fd = fd;
-    pwsi->sock[i].flags = 0;
-    return &pwsi->sock[i];
-  }
-  return NULL;
+    if( pwsi->last_free >= 0 )
+    {
+	int i = pwsi->last_free;
+
+	pwsi->last_free = pwsi->sock[i].flags;	/* free list */
+	pwsi->sock[i].fd = fd;
+	pwsi->sock[i].flags = 0;
+	return &pwsi->sock[i];
+    }
+    return NULL;
 }
 
 static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
 {
-  FD_ZERO(fds);
-  if(ws) 
-  { 
-    int 	i;
-    ws_socket*  pws;
-    for(i=0;i<(ws->fd_count);i++) 
-    {
-      pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
-      if( _check_ws(pwsi, pws) ) 
-      { 
-        if( pws->fd > *highfd ) *highfd = pws->fd; 
-        FD_SET(pws->fd, fds); 
-      }
+    /* translate Winsock fd set into the normal fd set */
+
+    FD_ZERO(fds);
+    if( ws ) 
+    { 
+	int 	i;
+	ws_socket*  pws;
+
+	for( i = 0; i < (ws->fd_count) ; i++ ) 
+	{
+	    pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+	    if( _check_ws(pwsi, pws) ) 
+	    {
+		if( pws->fd > *highfd ) *highfd = pws->fd; 
+		FD_SET(pws->fd, fds); 
+	    }
+	}
     }
-  }
 }
 
 /*
@@ -229,24 +213,19 @@
     return;
 }
 
-static void fd_set_update_except(LPWSINFO pwsi, fd_set *fds, ws_fd_set *ws,
-				 fd_set *errorfds)
+HANDLE16 __ws_gethandle( void* ptr )
 {
-    if (ws)
-    {
-	int i, j, count = ws->fd_count;
+    return (HANDLE16)WS_PTR2HANDLE(ptr);
+}
 
-	for (i=j=0; i < count; i++)
-	{
-	    ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws->fd_array[i]);
+void* __ws_memalloc( int size )
+{
+    return WS_ALLOC(size);
+}
 
-	    if (_check_ws(pwsi, pws) && (FD_ISSET(pws->fd, fds)
-                                         || FD_ISSET(pws->fd, errorfds)))
-	    ws->fd_array[j++] = ws->fd_array[i];
-	}
-	ws->fd_count = j;
-    }
-    return;
+void __ws_memfree(void* ptr)
+{
+    WS_FREE(ptr);
 }
 
 /* ----------------------------------- API ----- 
@@ -254,9 +233,15 @@
  * Init / cleanup / error checking.
  */
 
-INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
+/***********************************************************************
+ *      WSAStartup16()			(WINSOCK.115)
+ *
+ * Create socket control struct, attach it to the global list and
+ * update a pointer in the task struct.
+ */
+INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
 {
-  WSADATA WINSOCK_data = { 0x0101, 0x0101,
+    WSADATA WINSOCK_data = { 0x0101, 0x0101,
                           "WINE Sockets 1.1",
                         #ifdef linux
                                 "Linux/i386",
@@ -272,191 +257,288 @@
                                 "Unknown",
                         #endif
 			   WS_MAX_SOCKETS_PER_THREAD,
-			   WS_MAX_UDP_DATAGRAM, NULL };
-  HTASK16               tid = GetCurrentTask();
-  LPWSINFO              pwsi;
+			   WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
+    HTASK16             tid = GetCurrentTask();
+    LPWSINFO            pwsi;
 
-  dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
+    dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
 
-  if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
-      HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
+    if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
+        HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
 
-  if (!lpWSAData) return WSAEINVAL;
+    if (!lpWSAData) return WSAEINVAL;
 
-  _ws_global_init();
-  if( _WSHeap == 0 ) return WSASYSNOTREADY;
-  
-  pwsi = wsi_find(GetCurrentTask());
-  if( pwsi == NULL )
-  {
-    if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
+    /* initialize socket heap */
+
+    if( !_ws_stub )
     {
-      int i = 0;
-      pwsi->tid = tid;
-      for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
-      { 
-	pwsi->sock[i].fd = -1; 
-	pwsi->sock[i].flags = i + 1; 
-      }
-      pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
-    } 
-    else return WSASYSNOTREADY;
-    wsi_link(pwsi);
-  } else pwsi->num_startup++;
+	_WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
+	if( !(_ws_stub = WS_ALLOC(0x10)) )
+	{
+	    fprintf(stderr,"Fatal: failed to create WinSock heap\n");
+	    return 0;
+	}
+    }
+    if( _WSHeap == 0 ) return WSASYSNOTREADY;
 
-  /* return winsock information */
-  memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
+    /* create socket array for this task */
+  
+    pwsi = wsi_find(GetCurrentTask());
+    if( pwsi == NULL )
+    {
+	TDB* pTask = (TDB*)GlobalLock16( tid );
 
-  dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
-  return(0);
+	if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
+	{
+	    int i = 0;
+	    pwsi->tid = tid;
+	    for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
+	    {
+		pwsi->sock[i].fd = -1; 
+		pwsi->sock[i].flags = i + 1; 
+	    }
+	    pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
+	}
+	else return WSASYSNOTREADY;
+
+        /* add this control struct to the global list */
+
+	pwsi->prev = NULL;
+	if( _wsi_list ) 
+	    _wsi_list->prev = pwsi;
+	pwsi->next = _wsi_list; 
+	_wsi_list = pwsi;
+	pTask->pwsi = pwsi;
+    }
+    else pwsi->num_startup++;
+
+    /* return winsock information */
+
+    memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
+
+    dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
+    return 0;
 }
 
+/***********************************************************************
+ *      WSAStartup32()			(WSOCK32.115)
+ */
+INT32 WINAPI WSAStartup32(UINT32 wVersionRequested, LPWSADATA lpWSAData)
+{
+    return WSAStartup16( wVersionRequested, lpWSAData );
+}
+
+/***********************************************************************
+ *      WSACleanup()			(WINSOCK.116)
+ *
+ * Cleanup functions of varying impact.
+ */
 void WINSOCK_Shutdown()
 {
-  if( async_qid != -1 )
-    if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
-          fprintf(stderr,"failed to delete WS message queue.\n");
-    else async_qid = -1;
+    /* Called on exit(), has to remove all outstanding async DNS processes.  */
+
+    WINSOCK_cancel_task_aops( 0, __ws_memfree );
 }
 
-INT16 WSACleanup(void)
+INT32 WINSOCK_DeleteTaskWSI( TDB* pTask, LPWSINFO pwsi )
 {
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    /* WSACleanup() backend, called on task termination as well. */
 
-  /* FIXME: do global cleanup if no current task */
+    int	i, j, n;
 
-  dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
-  if( pwsi )
-  {
-      int	i, j, n;
+    if( --pwsi->num_startup > 0 ) return 0;
 
-      if( pwsi->num_startup-- ) return 0;
+    SIGNAL_MaskAsyncEvents( TRUE );
+    if( pTask ) 
+	pTask->pwsi = NULL;
+    WINSOCK_cancel_task_aops( pTask->hSelf, __ws_memfree );
+    SIGNAL_MaskAsyncEvents( FALSE );
 
-      SIGNAL_MaskAsyncEvents( TRUE );
-      WINSOCK_cancel_async_op(GetCurrentTask());
-      SIGNAL_MaskAsyncEvents( FALSE );
+    /* unlink socket control struct */
 
-      wsi_unlink(pwsi);
-      if( _wsi_list == NULL ) WINSOCK_Shutdown();
+    if( pwsi == _wsi_list ) 
+	_wsi_list = pwsi->next;
+    else
+	pwsi->prev->next = pwsi->next;
+    if( pwsi->next ) pwsi->next->prev = pwsi->prev; 
 
-      if( pwsi->flags & WSI_BLOCKINGCALL )
-	  dprintf_winsock(stddeb,"\tinside blocking call!\n");
-      if( pwsi->num_async_rq )
-	  dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
+    if( _wsi_list == NULL ) 
+	WINSOCK_Shutdown();	/* just in case */
 
-      for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
+    if( pwsi->flags & WSI_BLOCKINGCALL )
+	dprintf_winsock(stddeb,"\tinside blocking call!\n");
+
+/* FIXME: aop_control() doesn't decrement pwsi->num_async_rq
+ *
+ *    if( pwsi->num_async_rq )
+ *	  dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
+ */
+
+    for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
 	if( pwsi->sock[i].fd != -1 )
-	{ 
-	  n += cancel_async_select(&pwsi->sock[i]);
-          close(pwsi->sock[i].fd); j++; 
+	{
+	    if( pwsi->sock[i].psop )
+	    {
+		n++;
+		WSAAsyncSelect( (SOCKET16)WS_PTR2HANDLE(pwsi->sock + i), 0, 0, 0 );
+	    }
+            close(pwsi->sock[i].fd); j++; 
         }
-      if( j ) 
+    if( j ) 
 	  dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
 
-      if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
-      if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
-      WS_FREE(pwsi);
-      return 0;
-  }
-  return SOCKET_ERROR;
+    /* delete scratch buffers */
+
+    if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
+    if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
+	
+    memset( pwsi, 0, sizeof(WSINFO) );
+    WS_FREE(pwsi);
+    return 0;
 }
 
-INT16 WSAGetLastError(void)
+INT32 WINAPI WSACleanup(void)
 {
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-  INT16		ret;
+    HTASK16	hTask = GetCurrentTask();
 
-  dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
-
-  ret = (pwsi) ? pwsi->err : WSANOTINITIALISED;
-
-  dprintf_winsock(stddeb, " = %i\n", (int)ret);
-  return ret;
+    dprintf_winsock(stddeb, "WSACleanup(%04x)\n", hTask );
+    if( hTask )
+    {
+	LPWSINFO pwsi = wsi_find(hTask);
+	if( pwsi )
+	    return WINSOCK_DeleteTaskWSI( (TDB*)GlobalLock16(hTask), pwsi );
+	return SOCKET_ERROR;
+    }
+    else
+	WINSOCK_Shutdown(); /* remove all outstanding DNS requests */
+    return 0;
 }
 
-void WSASetLastError(INT16 iError)
+
+/***********************************************************************
+ *      WSAGetLastError()		(WSOCK32.111)(WINSOCK.111)
+ */
+INT32 WINAPI WSAGetLastError(void)
 {
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    INT16		ret;
 
-  dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
+    dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
 
-  if( pwsi ) pwsi->err = iError;
+    ret = (pwsi) ? pwsi->err : WSANOTINITIALISED;
+
+    dprintf_winsock(stddeb, " = %i\n", (int)ret);
+    return ret;
+}
+
+/***********************************************************************
+ *      WSASetLastError32()		(WSOCK32.112)
+ */
+void WINAPI WSASetLastError32(INT32 iError)
+{
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
+    if( pwsi ) pwsi->err = iError;
+}
+
+/***********************************************************************
+ *      WSASetLastError16()		(WINSOCK.112)
+ */
+void WINAPI WSASetLastError16(INT16 iError)
+{
+    WSASetLastError32(iError);
 }
 
 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
 {
-  if( pwsi )
-    if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->err = WSAEINPROGRESS;
-    else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
-    else pwsi->err = WSAENOTSOCK;
-  return 0;
+    if( pwsi )
+	if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->err = WSAEINPROGRESS;
+	else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
+		 else pwsi->err = WSAENOTSOCK;
+    return 0;
 }
 
 int _check_buffer(LPWSINFO pwsi, int size)
 {
-  if( pwsi->buffer && pwsi->buflen >= size ) return 1;
-  else SEGPTR_FREE(pwsi->buffer);
-  pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
-  return (pwsi->buffer != NULL);
+    if( pwsi->buffer && pwsi->buflen >= size ) return 1;
+    else SEGPTR_FREE(pwsi->buffer);
+
+    pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
+    return (pwsi->buffer != NULL);
 }
 
-/* ----- socket operations */
+/* ----------------------------------- i/o APIs */
 
-SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
+/***********************************************************************
+ *		accept()		(WSOCK32.1)
+ */
+SOCKET32 WINAPI WINSOCK_accept32(SOCKET32 s, struct sockaddr *addr,
+                                 INT32 *addrlen32)
 {
-  ws_socket*	pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO	pwsi = wsi_find(GetCurrentTask());
+    ws_socket*	pws  = (ws_socket*)WS_HANDLE2PTR((SOCKET16)s);
+    LPWSINFO	pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
-				   (unsigned)pwsi, (UINT16)s); 
-  if( _check_ws(pwsi, pws) )
-  {
-     int 	sock, fd_flags, addrlen32 = *addrlen16;
+    dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
+				  (unsigned)pwsi, (UINT16)s ); 
+    if( _check_ws(pwsi, pws) )
+    {
+	int 	sock, fd_flags;
 
-     /* this is how block info is supposed to be used -
-      * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
-      */
+	fd_flags = fcntl(pws->fd, F_GETFL, 0);
 
-     fd_flags = fcntl(pws->fd, F_GETFL, 0);
-     if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL; 
+	if( (sock = accept(pws->fd, addr, addrlen32)) >= 0 )
+	{
+	    ws_socket*	pnew = wsi_alloc_socket(pwsi, sock); 
+	    if( pnew )
+	    {
+		s = (SOCKET32)WS_PTR2HANDLE(pnew);
+		if( pws->psop && pws->flags & WS_FD_ACCEPT )
+		{
+		    EVENT_AddIO( pws->fd, EVENT_IO_READ );	/* reenabler */
 
-     if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
-     {
-        ws_socket*	pnew = wsi_alloc_socket(pwsi, sock); 
-	notify_client(pws, WS_FD_ACCEPT);
-        if( pnew )
-        {
-	  if( pws->p_aop )
-	      init_async_select(pnew, pws->p_aop->hWnd,
-				      pws->p_aop->uMsg,
-				      pws->p_aop->flags & ~WS_FD_ACCEPT );
-
-	  pwsi->flags &= ~WSI_BLOCKINGCALL; 
-	  return (SOCKET16)WS_PTR2HANDLE(pnew);
-        } 
-	else pwsi->err = WSAENOBUFS;
-     } 
-     else pwsi->err = wsaErrno();
-
-     pwsi->flags &= ~WSI_BLOCKINGCALL;
-  }
-  return INVALID_SOCKET;
+		    /* async select the accept()'ed socket */
+		    WSAAsyncSelect( s, pws->psop->hWnd, pws->psop->uMsg,
+				    pws->flags & ~WS_FD_ACCEPT );
+		}
+		return s;
+            } 
+	    else pwsi->err = WSAENOBUFS;
+	} 
+	else pwsi->err = wsaErrno();
+    }
+    return INVALID_SOCKET32;
 }
 
-INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+/***********************************************************************
+ *              accept()		(WINSOCK.1)
+ */
+SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
+                                 INT16* addrlen16 )
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    INT32 addrlen32 = *addrlen16;
+    SOCKET32 retSocket = WINSOCK_accept32( s, addr, &addrlen32 );
+   *addrlen16 = (INT16)addrlen32;
+    return (SOCKET16)retSocket;
+}
 
-  dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
+/***********************************************************************
+ *		bind()			(WSOCK32.2)
+ */
+INT32 WINAPI WINSOCK_bind32(SOCKET32 s, struct sockaddr *name, INT32 namelen)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
 			   (unsigned)pwsi, s, (int) name, namelen);
 #if 0
-  dump_sockaddr(name);
+    dump_sockaddr(name);
 #endif
 
-  if ( _check_ws(pwsi, pws) )
-    if (namelen >= sizeof(*name)) 
-       if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
+    if ( _check_ws(pwsi, pws) )
+      if ( namelen >= sizeof(*name) ) 
+	if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
 	  if ( bind(pws->fd, name, namelen) < 0 ) 
 	  {
 	     int	loc_errno = errno;
@@ -469,34 +551,59 @@
 		default: pwsi->err = wsaErrno();
 	     }
 	  }
-	  else return 0;
-       else pwsi->err = WSAEAFNOSUPPORT;
-    else pwsi->err = WSAEFAULT;
-  return SOCKET_ERROR;
+	  else return 0; /* success */
+	else pwsi->err = WSAEAFNOSUPPORT;
+      else pwsi->err = WSAEFAULT;
+    return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_closesocket(SOCKET16 s)
+/***********************************************************************
+ *              bind()			(WINSOCK.2)
+ */
+INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
-
-  if( _check_ws(pwsi, pws) )
-  { 
-    int		fd = pws->fd;
-
-    cancel_async_select(pws);
-    pws->fd = -1;
-    pws->flags = (unsigned)pwsi->last_free;
-    pwsi->last_free = pws - &pwsi->sock[0];
-    if (close(fd) == 0) return 0;
-    pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
-  }
-  return SOCKET_ERROR;
+  return (INT16)WINSOCK_bind32( s, name, namelen );
 }
 
-INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+/***********************************************************************
+ *		closesocket()		(WSOCK32.3)
+ */
+INT32 WINAPI WINSOCK_closesocket32(SOCKET32 s)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
+
+    if( _check_ws(pwsi, pws) )
+    { 
+	int	fd = pws->fd;
+
+	if( pws->psop ) WSAAsyncSelect( s, 0, 0, 0 );
+
+	pws->fd = -1;
+	pws->flags = (unsigned)pwsi->last_free;
+	pwsi->last_free = pws - &pwsi->sock[0]; /* add to free list */
+
+	if( close(fd) == 0 ) 
+	    return 0;
+	pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+    }
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              closesocket()           (WINSOCK.3)
+ */
+INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
+{
+    return (INT16)WINSOCK_closesocket32(s);
+}
+
+/***********************************************************************
+ *		connect()		(WSOCK32.4)
+ */
+INT32 WINAPI WINSOCK_connect32(SOCKET32 s, struct sockaddr *name, INT32 namelen)
 {
   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
@@ -511,13 +618,22 @@
   {
     if (connect(pws->fd, name, namelen) == 0) 
     { 
-	if( pws->p_aop )
-	    /* we need to notify handler process if
-	     * connect() succeeded NOT in response to winsock message
-	     */
-	    notify_client(pws, WS_FD_CONNECTED);
-
-        pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT); 
+	pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT);
+	if( pws->psop && pws->flags & WS_FD_CONNECT )
+	{
+	    if( !(pws->flags & WS_FD_CONNECTED) )
+	    {
+		if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
+		    EVENT_AddIO( pws->fd, EVENT_IO_READ );
+		else
+		    EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
+		if( pws->flags & WS_FD_WRITE )
+		    EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
+		else
+		    EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
+		pws->flags |= WS_FD_CONNECTED;
+	    }
+	}
         return 0; 
     }
     pwsi->err = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
@@ -525,77 +641,142 @@
   return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+/***********************************************************************
+ *              connect()               (WINSOCK.4)
+ */
+INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+  return (INT16)WINSOCK_connect32( s, name, namelen );
+}
 
-  dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
+/***********************************************************************
+ *		getpeername()		(WSOCK32.5)
+ */
+INT32 WINAPI WINSOCK_getpeername32(SOCKET32 s, struct sockaddr *name,
+                                   INT32 *namelen)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
 			   (unsigned)pwsi, s, (int) name, *namelen);
-  if( _check_ws(pwsi, pws) )
-  {
-    int	namelen32 = *namelen;
-    if (getpeername(pws->fd, name, &namelen32) == 0) 
-    { 
+    if( _check_ws(pwsi, pws) )
+    {
+	if (getpeername(pws->fd, name, namelen) == 0) 
+	    return 0; 
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              getpeername()		(WINSOCK.5)
+ */
+INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
+                                   INT16 *namelen16)
+{
+    INT32 namelen32 = *namelen16;
+    INT32 retVal = WINSOCK_getpeername32( s, name, &namelen32 );
+
 #if 0
-	dump_sockaddr(name);
+    dump_sockaddr(name);
 #endif
-       *namelen = (INT16)namelen32; 
-        return 0; 
-    }
-    pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return SOCKET_ERROR;
+
+   *namelen16 = namelen32;
+    return (INT16)retVal;
 }
 
-INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+/***********************************************************************
+ *		getsockname()		(WSOCK32.6)
+ */
+INT32 WINAPI WINSOCK_getsockname32(SOCKET32 s, struct sockaddr *name,
+                                   INT32 *namelen)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
+    dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
 			  (unsigned)pwsi, s, (int) name, (int) *namelen);
-  if( _check_ws(pwsi, pws) )
-  {
-    int namelen32 = *namelen;
-    if (getsockname(pws->fd, name, &namelen32) == 0)
-    { 
-	*namelen = (INT16)namelen32; 
-	 return 0; 
+    if( _check_ws(pwsi, pws) )
+    {
+	if (getsockname(pws->fd, name, namelen) == 0)
+	    return 0; 
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
     }
-    pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return SOCKET_ERROR;
+    return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level, 
-			 INT16 optname, char *optval, INT16 *optlen)
+/***********************************************************************
+ *              getsockname()		(WINSOCK.6)
+ */
+INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
+                                   INT16 *namelen16)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
-			   (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
-
-  if( _check_ws(pwsi, pws) )
-  {
-     int	optlen32 = *optlen;
-
-     convert_sockopt(&level, &optname);
-     if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
-     { *optlen = (INT16)optlen32; return 0; }
-     pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
-  }
-  return SOCKET_ERROR;
+    INT32 namelen32 = *namelen16;
+    INT32 retVal = WINSOCK_getsockname32( s, name, &namelen32 );
+   *namelen16 = namelen32;
+    return (INT16)retVal;
 }
 
-u_long  WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
-u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
-u_long  WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
-u_long  WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
-u_short WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
 
-SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
+/***********************************************************************
+ *		getsockopt()		(WSOCK32.7)
+ */
+INT32 WINAPI WINSOCK_getsockopt32(SOCKET32 s, INT32 level, 
+                                  INT32 optname, char *optval, INT32 *optlen)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
+			   (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
+    if( _check_ws(pwsi, pws) )
+    {
+	convert_sockopt(&level, &optname);
+	if (getsockopt(pws->fd, (int) level, optname, optval, optlen) == 0 )
+	    return 0;
+	pwsi->err = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+    }
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              getsockopt()		(WINSOCK.7)
+ */
+INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
+                                  INT16 optname, char *optval, INT16 *optlen)
+{
+    INT32 optlen32 = *optlen;
+    INT32 retVal = WINSOCK_getsockopt32( s, level, optname, optval, &optlen32 );
+   *optlen = optlen32;
+    return (INT16)retVal;
+}
+
+/***********************************************************************
+ *		htonl()			(WINSOCK.8)(WSOCK32.8)
+ */
+u_long WINAPI WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }
+/***********************************************************************
+ *		htons()			(WINSOCK.9)(WSOCK32.9)
+ */
+u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
+/***********************************************************************
+ *		inet_addr()		(WINSOCK.10)
+ */
+u_long WINAPI WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
+/***********************************************************************
+ *		htohl()			(WINSOCK.14)(WSOCK32.14)
+ */
+u_long WINAPI WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
+/***********************************************************************
+ *		ntohs()			(WINSOCK.15)(WSOCK32.15)
+ */
+u_short WINAPI WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
+
+/***********************************************************************
+ *		inet_ntoa()		(WINSOCK.11)
+ */
+SEGPTR WINAPI WINSOCK_inet_ntoa(struct in_addr in)
 {
   /* use "buffer for dummies" here because some applications have 
    * propensity to decode addresses in ws_hostent structure without 
@@ -623,7 +804,10 @@
   return (SEGPTR)NULL;
 }
 
-INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
+/***********************************************************************
+ *		ioctlsocket()		(WSOCK32.12)
+ */
+INT32 WINAPI WINSOCK_ioctlsocket32(SOCKET32 s, UINT32 cmd, UINT32 *argp)
 {
   ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
@@ -642,8 +826,9 @@
 
 	case WS_FIONBIO:    
 		newcmd=FIONBIO;  
-		if( pws->p_aop && *argp == 0 ) 
+		if( pws->psop && *argp == 0 ) 
 		{
+		    /* AsyncSelect()'ed sockets are always nonblocking */
 		    pwsi->err = WSAEINVAL; 
 		    return SOCKET_ERROR; 
 		}
@@ -668,81 +853,141 @@
   return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
+/***********************************************************************
+ *              ioctlsocket()           (WINSOCK.12)
+ */
+INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, UINT32 cmd, UINT32 *argp)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    return (INT16)WINSOCK_ioctlsocket32( s, cmd, argp );
+}
 
-  dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
-			  (unsigned)pwsi, s, backlog);
-  if( _check_ws(pwsi, pws) )
-  {
-    if( !pws->p_aop )
+
+/***********************************************************************
+ *		listen()		(WSOCK32.13)
+ */
+INT32 WINAPI WINSOCK_listen32(SOCKET32 s, INT32 backlog)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
+			    (unsigned)pwsi, s, backlog);
+    if( _check_ws(pwsi, pws) )
     {
-      int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
-      if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
-    }
-    else notify_client(pws, WS_FD_ACCEPT);
+	if( !pws->psop )
+	{
+	    int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
+	    if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
+	}
 
-    if (listen(pws->fd, backlog) == 0) return 0;
-    pwsi->err = wsaErrno();
-  }
-  return SOCKET_ERROR;
+	if (listen(pws->fd, backlog) == 0) return 0;
+	pwsi->err = wsaErrno();
+    }
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+/***********************************************************************
+ *              listen()		(WINSOCK.13)
+ */
+INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
-                          (unsigned)pwsi, s, (unsigned)buf, len, flags);
-  if( _check_ws(pwsi, pws) )
-  {
-    int length;
-    if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
-    { 
-	dprintf_winsock(stddeb, " -> %i bytes\n", length);
-	notify_client(pws, WS_FD_READ);
-	return (INT16)length;
-    }
-    pwsi->err = wsaErrno();
-  }
-  dprintf_winsock(stddeb, " -> ERROR\n");
-  return SOCKET_ERROR;
+    return (INT16)WINSOCK_listen32( s, backlog );
 }
 
-INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, 
-		struct sockaddr *from, INT16 *fromlen16)
+
+/***********************************************************************
+ *		recv()			(WSOCK32.16)
+ */
+INT32 WINAPI WINSOCK_recv32(SOCKET32 s, char *buf, INT32 len, INT32 flags)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
+    dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
                           (unsigned)pwsi, s, (unsigned)buf, len, flags);
-  if( _check_ws(pwsi, pws) )
-  {
-    int length, fromlen32 = *fromlen16;
+    if( _check_ws(pwsi, pws) )
+    {
+	INT32 length;
+	if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
+	{ 
+	    dprintf_winsock(stddeb, " -> %i bytes\n", length);
 
-    if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0)
-    {   
-      *fromlen16 = fromlen32; 
-       notify_client(pws, WS_FD_READ);
-       return (INT16)length;
+	    if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
+		EVENT_AddIO( pws->fd, EVENT_IO_READ );	/* reenabler */
+
+	    return length;
+	}
+	pwsi->err = wsaErrno();
     }
-    pwsi->err = wsaErrno();
-  }
-  return SOCKET_ERROR;
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    dprintf_winsock(stddeb, " -> ERROR\n");
+    return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
-				 ws_fd_set *ws_writefds,
-				 ws_fd_set *ws_exceptfds, struct timeval *timeout)
+/***********************************************************************
+ *              recv()			(WINSOCK.16)
+ */
+INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+    return (INT16)WINSOCK_recv32( s, buf, len, flags );
+}
+
+
+/***********************************************************************
+ *		recvfrom()		(WSOCK32.17)
+ */
+INT32 WINAPI WINSOCK_recvfrom32(SOCKET32 s, char *buf, INT32 len, INT32 flags, 
+                                struct sockaddr *from, INT32 *fromlen32)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d",
+                          (unsigned)pwsi, s, (unsigned)buf, len, flags);
+    if( _check_ws(pwsi, pws) )
+    {
+	int length;
+
+	if ((length = recvfrom(pws->fd, buf, len, flags, from, fromlen32)) >= 0)
+	{
+	    dprintf_winsock(stddeb, " -> %i bytes\n", length);
+
+	    if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
+		EVENT_AddIO( pws->fd, EVENT_IO_READ );  /* reenabler */
+
+	    return (INT16)length;
+	}
+	pwsi->err = wsaErrno();
+    }
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    dprintf_winsock(stddeb, " -> ERROR\n");
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              recvfrom()		(WINSOCK.17)
+ */
+INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+                                struct sockaddr *from, INT16 *fromlen16)
+{
+    INT32 fromlen32 = *fromlen16;
+    INT32 retVal = WINSOCK_recvfrom32( s, buf, len, flags, from, &fromlen32 );
+   *fromlen16 = fromlen32;
+    return (INT16)retVal;
+}
+
+/***********************************************************************
+ *		select()		(WINSOCK.18)
+ */
+INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set *ws_readfds,
+                              ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
+                              struct timeval *timeout)
 {
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 	
   dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
-	  (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
+  (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
 
   if( pwsi )
   {
@@ -760,7 +1005,23 @@
 	  {
 	    fd_set_update(pwsi, &readfds, ws_readfds, &errorfds);
 	    fd_set_update(pwsi, &writefds, ws_writefds, &errorfds);
-	    fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
+
+	    /* update exception set (see "weirdness" comment in the
+	     * beginning of the file). */
+
+	    if (ws_exceptfds)
+	    {
+		int i, j, count = ws_exceptfds->fd_count;
+
+		for (i = j = 0; i < count; i++)
+		{
+		    ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws_exceptfds->fd_array[i]);
+		    if( _check_ws(pwsi, pws) && 
+			(FD_ISSET(pws->fd, &exceptfds) || FD_ISSET(pws->fd, &errorfds)) )
+			ws_exceptfds->fd_array[j++] = ws_exceptfds->fd_array[i];
+		}
+		ws_exceptfds->fd_count = j;
+	    }
 	  }
 	  return highfd; 
      }
@@ -769,95 +1030,191 @@
   return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+/***********************************************************************
+ *              select()		(WSOCK32.18)
+ */
+INT32 WINAPI WINSOCK_select32(INT32 nfds, ws_fd_set *ws_readfds,
+                              ws_fd_set *ws_writefds, ws_fd_set *ws_exceptfds,
+                              struct timeval *timeout)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    /* struct timeval is the same for both 32- and 16-bit code */
+    return WINSOCK_select16( (INT16)nfds, ws_readfds, ws_writefds, ws_exceptfds, timeout );
+}
 
-  dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
+
+/***********************************************************************
+ *		send()			(WSOCK32.19)
+ */
+INT32 WINAPI WINSOCK_send32(SOCKET32 s, char *buf, INT32 len, INT32 flags)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
 			  (unsigned)pwsi, s, (unsigned) buf, len, flags);
-  if( _check_ws(pwsi, pws) )
-  {
-    int		length;
-    if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
-    {  
-	length = SOCKET_ERROR;
+    if( _check_ws(pwsi, pws) )
+    {
+	int	length;
+
+	if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
+	{
+	    pwsi->err = wsaErrno();
+	    if( pwsi->err == WSAEWOULDBLOCK && 
+		pws->psop && pws->flags & WS_FD_WRITE )
+		EVENT_AddIO( pws->fd, EVENT_IO_WRITE );	/* reenabler */
+	}
+	else return (INT16)length;
+    }
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              send()			(WINSOCK.19)
+ */
+INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+    return WINSOCK_send32( s, buf, len, flags );
+}
+
+/***********************************************************************
+ *		sendto()		(WSOCK32.20)
+ */
+INT32 WINAPI WINSOCK_sendto32(SOCKET32 s, char *buf, INT32 len, INT32 flags,
+                              struct sockaddr *to, INT32 tolen)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
+                          (unsigned)pwsi, s, (unsigned) buf, len, flags);
+    if( _check_ws(pwsi, pws) )
+    {
+	INT32	length;
+
+	if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
+	{
+	    pwsi->err = wsaErrno();
+	    if( pwsi->err == WSAEWOULDBLOCK &&
+		pws->psop && pws->flags & WS_FD_WRITE )
+		EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */
+	} 
+	else return length;
+    }
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              sendto()		(WINSOCK.20)
+ */
+INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+                              struct sockaddr *to, INT16 tolen)
+{
+    return (INT16)WINSOCK_sendto32( s, buf, len, flags, to, tolen );
+}
+
+/***********************************************************************
+ *		setsockopt()		(WSOCK32.21)
+ */
+INT32 WINAPI WINSOCK_setsockopt32(SOCKET16 s, INT32 level, INT32 optname, 
+                                  char *optval, INT32 optlen)
+{
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
+			  (unsigned)pwsi, s, level, optname, (int) optval, optlen);
+    if( _check_ws(pwsi, pws) )
+    {
+	convert_sockopt(&level, &optname);
+	if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
 	pwsi->err = wsaErrno();
     }
-    notify_client(pws, WS_FD_WRITE);
-    return (INT16)length;
-  }
-  return SOCKET_ERROR;
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    return SOCKET_ERROR;
 }
 
-INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
-		     struct sockaddr *to, INT16 tolen)
+/***********************************************************************
+ *              setsockopt()		(WINSOCK.21)
+ */
+INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
+                                  char *optval, INT16 optlen)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
-                          (unsigned)pwsi, s, (unsigned) buf, len, flags);
-  if( _check_ws(pwsi, pws) )
-  {
-    int		length;
-
-    if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
-    {
-	length = SOCKET_ERROR;
-        pwsi->err = wsaErrno();
-    }
-    notify_client(pws, WS_FD_WRITE);
-    return (INT16)length;
-  }
-  return SOCKET_ERROR;
-}
-
-INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname, 
-			 char *optval, INT16 optlen)
-{
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
-			  (unsigned)pwsi, s, level, optname, (int) optval, optlen);
-  if( _check_ws(pwsi, pws) )
-  {
-    int		linger32[2];
-    convert_sockopt(&level, &optname);
+    INT32 linger32[2];
     if( optname == SO_LINGER )
     {
-	INT16*	   ptr = (INT16*)optval;
-        linger32[0] = ptr[0];
-	linger32[1] = ptr[1]; 
+	INT16* ptr = (INT16*)optval;
+	linger32[0] = ptr[0];
+	linger32[1] = ptr[1];
 	optval = (char*)&linger32;
 	optlen = sizeof(linger32);
     }
-    if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
-    pwsi->err = wsaErrno();
-  }
-  return SOCKET_ERROR;
+    return (INT16)WINSOCK_setsockopt32( s, level, optname, optval, optlen );
 }
 
-INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
+
+/***********************************************************************
+ *		shutdown()		(WSOCK32.22)
+ */
+INT32 WINAPI WINSOCK_shutdown32(SOCKET32 s, INT32 how)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
-			   (unsigned)pwsi, s, how );
-  if( _check_ws(pwsi, pws) )
-  {
-    pws->flags |= WS_FD_INACTIVE;
-    cancel_async_select(pws);
+    dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
+			    (unsigned)pwsi, s, how );
+    if( _check_ws(pwsi, pws) )
+    {
+	if( pws->psop )
+	    switch( how )
+	    {
+		case 0: /* drop receives */
+			if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
+			    EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
+			pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE);
+			break;
 
-    if (shutdown(pws->fd, how) == 0) return 0;
-    pwsi->err = wsaErrno();
-  }
-  return SOCKET_ERROR;
+		case 1: /* drop sends */
+			if( pws->flags & WS_FD_WRITE )
+			    EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
+			pws->flags &= ~WS_FD_WRITE;
+			break;
+
+		case 2: /* drop all */
+		default:
+			WSAAsyncSelect( s, 0, 0, 0 );
+			break;
+	    }
+
+	if (shutdown(pws->fd, how) == 0) 
+	{
+	    if( how > 1 ) 
+	    {
+		pws->flags &= ~WS_FD_CONNECTED;
+		pws->flags |= WS_FD_INACTIVE;
+	    }
+	    return 0;
+	}
+	pwsi->err = wsaErrno();
+    } 
+    else if( pwsi ) pwsi->err = WSAENOTSOCK;
+    return SOCKET_ERROR;
 }
 
-SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
+/***********************************************************************
+ *              shutdown()		(WINSOCK.22)
+ */
+INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
+{
+    return (INT16)WINSOCK_shutdown32( s, how );
+}
+
+
+/***********************************************************************
+ *		socket()		(WSOCK32.23)
+ */
+SOCKET32 WINAPI WINSOCK_socket32(INT32 af, INT32 type, INT32 protocol)
 {
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
@@ -873,7 +1230,8 @@
     {
 	case AF_INET:
 	case AF_UNSPEC: break;
-	default:        pwsi->err = WSAEAFNOSUPPORT; return INVALID_SOCKET;
+	default:        pwsi->err = WSAEAFNOSUPPORT; 
+			return INVALID_SOCKET32;
     }
 
     /* check the socket type */
@@ -881,13 +1239,14 @@
     {
 	case SOCK_STREAM:
 	case SOCK_DGRAM:
-	case SOCK_RAW: break;
-	default:       pwsi->err = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
+	case SOCK_RAW:  break;
+	default:        pwsi->err = WSAESOCKTNOSUPPORT; 
+			return INVALID_SOCKET32;
     }
 
     /* check the protocol type */
     if ( protocol < 0 )  /* don't support negative values */
-    { pwsi->err = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
+    { pwsi->err = WSAEPROTONOSUPPORT; return INVALID_SOCKET32; }
 
     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
         switch(protocol) 
@@ -896,7 +1255,7 @@
              if (type == SOCK_STREAM) { af = AF_INET; break; }
           case IPPROTO_UDP:
              if (type == SOCK_DGRAM)  { af = AF_INET; break; }
-          default: pwsi->err = WSAEPROTOTYPE; return INVALID_SOCKET;
+          default: pwsi->err = WSAEPROTOTYPE; return INVALID_SOCKET32;
         }
 
     if ((sock = socket(af, type, protocol)) >= 0) 
@@ -906,11 +1265,10 @@
 	dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
 
         if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
-	{
-          close(sock);
-          pwsi->err = WSAENOBUFS;
-          return INVALID_SOCKET;
-	}
+	
+        close(sock);
+        pwsi->err = WSAENOBUFS;
+        return INVALID_SOCKET32;
     }
 
     if (errno == EPERM) /* raw socket denied */
@@ -921,265 +1279,337 @@
   }
  
   dprintf_winsock(stddeb, "\t\tfailed!\n");
-  return INVALID_SOCKET;
+  return INVALID_SOCKET32;
+}
+
+/***********************************************************************
+ *              socket()		(WINSOCK.23)
+ */
+SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
+{
+    return (SOCKET16)WINSOCK_socket32( af, type, protocol );
 }
     
 
-/* ----- database functions 
+/* ----------------------------------- DNS services
  *
- * Note that ws_...ent structures we return have SEGPTR pointers inside them.
+ * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
+ * Also, we have to use wsock32 stubs to convert error codes from Unix
+ * to WSA, hence no direct mapping in if1632/wsock32.spec.
+ *
+ * FIXME: Win32 may need "short" h_addrtype and h_length in
+ * ...ent structures. If so, use WS_dup_...(pwsi, ..., 0) to
+ * convert.
  */
 
 static char*	NULL_STRING = "NULL";
 
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
-{
-  LPWSINFO      	pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n", 
+/***********************************************************************
+ *		gethostbyaddr()		(WINSOCK.51)
+ *
+ *
+struct WIN_hostent *
+ */
+SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
+{
+    LPWSINFO      	pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetHostByAddr16(%08x): ptr %8x, len %d, type %d\n", 
 			  (unsigned)pwsi, (unsigned) addr, len, type);
-  if( pwsi )
-  {
-    struct hostent* 	host;
-    if( (host = gethostbyaddr(addr, len, type)) != NULL )
-      if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  } 
-  return NULL;
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyname(const char *name)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
-                          (unsigned)pwsi, (name)?name:"NULL");
-  if( pwsi )
-  {
-    struct hostent*     host;
-    if( (host = gethostbyname(name)) != NULL )
-      if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return NULL;
-}
-
-INT16 WINSOCK_gethostname(char *name, INT16 namelen)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
-			  (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
-  if( pwsi )
-  {
-    if (gethostname(name, namelen) == 0) return 0;
-    pwsi->err = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
-  }
-  return SOCKET_ERROR;
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobyname(char *name)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
-                          (unsigned)pwsi, (name)?name:NULL_STRING);
-  if( pwsi )
-  {
-    struct protoent*     proto;
-    if( (proto = getprotobyname(name)) != NULL )
-      if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return NULL;
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobynumber(INT16 number)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
-
-  if( pwsi )
-  {
-    struct protoent*     proto;
-    if( (proto = getprotobynumber(number)) != NULL )
-      if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = WSANO_DATA;
-  }
-  return NULL;
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n", 
-			  (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
-
-  if( pwsi )
-  {
-    struct servent*     serv;
-    if( (serv = getservbyname(name, proto)) != NULL )
-      if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return NULL;
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
-{
-  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
-
-  dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
-                          (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
-  if( pwsi )
-  {
-    struct servent*     serv;
-    if( (serv = getservbyport(port, proto)) != NULL )
-      if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
-          return SEGPTR_GET(pwsi->buffer);
-      else pwsi->err = WSAENOBUFS;
-    else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
-  }
-  return NULL;
-}
-
-
-/* ----------------------------------- Windows sockets extensions -- *
- *								     *
- * ----------------------------------------------------------------- */
-
-static int aop_control(ws_async_op* p_aop, int flag )
-{
-  unsigned	lLength;
-
-  read(p_aop->fd[0], &lLength, sizeof(unsigned));
-  if( LOWORD(lLength) )
-    if( (int)LOWORD(lLength) <= p_aop->buflen )
+    if( pwsi )
     {
-      char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
-      read(p_aop->fd[0], buffer, LOWORD(lLength));
-      switch( p_aop->flags )
-      {
-	case WSMSG_ASYNC_HOSTBYNAME:
-	case WSMSG_ASYNC_HOSTBYADDR: 
-	     fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
-	case WSMSG_ASYNC_PROTOBYNAME:
-	case WSMSG_ASYNC_PROTOBYNUM:
-	     fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
-	case WSMSG_ASYNC_SERVBYNAME:
-	case WSMSG_ASYNC_SERVBYPORT:
-	     fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
-	default:
-	     if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n"); 
-	     return AOP_CONTROL_REMOVE;
-      }
+	struct hostent*	host = gethostbyaddr(addr, len, type);
+	if( host )
+	    if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else 
+		pwsi->err = WSAENOBUFS;
+	else 
+	    pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
     }
-    else lLength =  ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
-
-#if 0
-  printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
-	 p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
-#endif
-
-  PostMessage16(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
-  return AOP_CONTROL_REMOVE;
+    return (SEGPTR)NULL;
 }
 
-
-static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
-				 INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
+/***********************************************************************
+ *              gethostbyaddr()		(WSOCK32.51)
+ */
+struct hostent*  WINAPI WINSOCK_gethostbyaddr32(const char *addr, INT32 len,
+                                                INT32 type)
 {
-  /* queue 'flag' request and fork off its handler */
+    LPWSINFO		pwsi = wsi_find(GetCurrentTask());
 
-  async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
-
-  if( async_ctl.ws_aop )
-  {
-      HANDLE16        handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
-
-      if( pipe(async_ctl.ws_aop->fd) == 0 )
-      {
-	async_ctl.init = (char*)init;
-	async_ctl.lLength = len;
-	async_ctl.lEvent = type;
-
-        async_ctl.ws_aop->hWnd = hWnd;
-        async_ctl.ws_aop->uMsg = uMsg;
-
-	async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
-	async_ctl.ws_aop->flags = flag;
-	async_ctl.ws_aop->aop_control = &aop_control;
-	WINSOCK_link_async_op( async_ctl.ws_aop );
-
-        async_ctl.ws_aop->pid = fork();
-        if( async_ctl.ws_aop->pid )
-        {
-            close(async_ctl.ws_aop->fd[1]);        /* write endpoint */
-
-           /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
-            *
-            * async_io(async_ctl.ws_aop->fd[0], 1);
-            */
-
-            dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
-                                    handle, async_ctl.ws_aop->pid);
-            return handle;
-        } else
-                /* child process */
-                 {
-                   close(async_ctl.ws_aop->fd[0]); /* read endpoint */
-		   switch(flag)
-		   {
-		     case WSMSG_ASYNC_HOSTBYADDR:
-		     case WSMSG_ASYNC_HOSTBYNAME:
- 			WS_do_async_gethost(pwsi,flag);
-		     case WSMSG_ASYNC_PROTOBYNUM:
-		     case WSMSG_ASYNC_PROTOBYNAME:
-			WS_do_async_getproto(pwsi,flag);
-		     case WSMSG_ASYNC_SERVBYPORT:
-		     case WSMSG_ASYNC_SERVBYNAME:
-			WS_do_async_getserv(pwsi,flag);
-		   }
-		   _exit(0); /* skip atexit()'ed cleanup */
-                 }
-      }
-      WS_FREE(async_ctl.ws_aop);
-      pwsi->err = wsaErrno();
-  } else pwsi->err = WSAEWOULDBLOCK;
-  return 0;
+    dprintf_winsock(stddeb, "WS_GetHostByAddr32(%08x): ptr %8x, len %d, type %d\n",
+                            (unsigned)pwsi, (unsigned) addr, len, type);
+    if( pwsi )
+    {
+	struct hostent* host = gethostbyaddr( addr, len, type );
+	if( host ) 
+	    return host;
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return NULL;
 }
 
-HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
+/***********************************************************************
+ *		gethostbyname()		(WINSOCK.52) 
+ *
+ *
+struct WIN_hostent *
+ */
+SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetHostByName16(%08x): %s\n",
+                          (unsigned)pwsi, (name)?name:"NULL");
+    if( pwsi )
+    {
+	struct hostent*     host;
+	if( (host = gethostbyname(name)) != NULL )
+	    if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else pwsi->err = WSAENOBUFS;
+	else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return (SEGPTR)NULL;
+}
+
+/***********************************************************************
+ *              gethostbyname()		(WSOCK32,52)
+ */
+struct hostent*  WINAPI WINSOCK_gethostbyname32(const char* name)
+{
+    LPWSINFO            pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetHostByName32(%08x): %s\n",
+                            (unsigned)pwsi, (name)?name:"NULL");
+    if( pwsi )
+    {
+	struct hostent* host = gethostbyname( name );
+	if( host )
+	    return host;
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return NULL;
+}
+
+/***********************************************************************
+ *		gethostname()		(WSOCK32.57)
+ */
+INT32 WINAPI WINSOCK_gethostname32(char *name, INT32 namelen)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
+			  (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
+    if( pwsi )
+    {
+	if (gethostname(name, namelen) == 0) return 0;
+	pwsi->err = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
+    }
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *              gethostname()		(WINSOCK.57)
+ */
+INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
+{
+    return (INT16)WINSOCK_gethostname32(name, namelen);
+}
+
+/***********************************************************************
+ *		getprotobyname()	(WINSOCK.53)
+ *
+ *
+struct WIN_protoent *
+ */
+SEGPTR WINAPI WINSOCK_getprotobyname16(char *name)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetProtoByName16(%08x): %s\n",
+                          (unsigned)pwsi, (name)?name:NULL_STRING);
+    if( pwsi )
+    {
+	struct protoent*     proto;
+	if( (proto = getprotobyname(name)) != NULL )
+	    if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else pwsi->err = WSAENOBUFS;
+	else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return (SEGPTR)NULL;
+}
+
+/***********************************************************************
+ *              getprotobyname()	(WSOCK32.53)
+ */
+struct protoent* WINAPI WINSOCK_getprotobyname32(char* name)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetProtoByName32(%08x): %s\n",
+                          (unsigned)pwsi, (name)?name:NULL_STRING);
+    if( pwsi )
+    {
+	struct protoent* proto;
+	if( (proto = getprotobyname(name)) != NULL )
+                return proto;
+        pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *		getprotobynumber()	(WINSOCK.54)
+ *
+ *
+struct WIN_protoent *
+ */
+SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetProtoByNumber16(%08x): %i\n", (unsigned)pwsi, number);
+
+    if( pwsi )
+    {
+	struct protoent*     proto;
+	if( (proto = getprotobynumber(number)) != NULL )
+	    if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else pwsi->err = WSAENOBUFS;
+	else pwsi->err = WSANO_DATA;
+    }
+    return (SEGPTR)NULL;
+}
+
+/***********************************************************************
+ *              getprotobynumber()	(WSOCK32.54)
+ */
+struct protoent* WINAPI WINSOCK_getprotobynumber32(INT32 number)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetProtoByNumber32(%08x): %i\n", (unsigned)pwsi, number);
+
+    if( pwsi )
+    {
+	struct protoent* proto;
+	if( (proto = getprotobynumber(number)) != NULL )
+	    return proto;
+	pwsi->err = WSANO_DATA;
+    }
+    return NULL;
+}
+
+/***********************************************************************
+ *		getservbyname()		(WINSOCK.55)
+ *
+ *
+struct WIN_servent *
+ */
+SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetServByName16(%08x): '%s', '%s'\n", 
+			  (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
+    if( pwsi )
+    {
+	struct servent*     serv;
+	if( (serv = getservbyname(name, proto)) != NULL )
+	    if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else pwsi->err = WSAENOBUFS;
+	else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return (SEGPTR)NULL;
+}
+
+/***********************************************************************
+ *              getservbyname()		(WSOCK32.55)
+ */
+struct servent* WINAPI WINSOCK_getservbyname32(const char *name, const char *proto)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetServByName32(%08x): '%s', '%s'\n",
+                          (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
+    if( pwsi )
+    {
+	struct servent* serv;
+	if( (serv = getservbyname(name, proto)) != NULL )
+	    return serv;
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return NULL;
+}
+
+/***********************************************************************
+ *		getservbyport()		(WINSOCK.56)
+ *
+ *
+struct WIN_servent *
+ */
+SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetServByPort16(%08x): %i, '%s'\n",
+                          (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
+    if( pwsi )
+    {
+	struct servent*     serv;
+	if( (serv = getservbyport(port, proto)) != NULL )
+	    if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+		return SEGPTR_GET(pwsi->buffer);
+	    else pwsi->err = WSAENOBUFS;
+	else pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return (SEGPTR)NULL;
+}
+
+/***********************************************************************
+ *              getservbyport()		(WSOCK32.56)
+ */
+struct servent* WINAPI WINSOCK_getservbyport32(INT32 port, const char *proto)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_GetServByPort32(%08x): %i, '%s'\n",
+                          (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
+    if( pwsi )
+    {
+	struct servent* serv;
+	if( (serv = getservbyport(port, proto)) != NULL )
+	    return serv;
+	pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+    }
+    return NULL;
+}
+
+
+/* ------------------------------------- Windows sockets extensions -- *
+ *								       *
+ * ------------------------------------------------------------------- */
+
+
+/***********************************************************************
+ *          Asynchronous DNS services
+ */
+
+/* winsock_dns.c */
+extern HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, INT16 type, LPCSTR init,
+				 INT16 len, LPCSTR proto, SEGPTR sbuf, INT16 buflen, UINT32 flag);
+
+/***********************************************************************
+ *       WSAAsyncGetHostByAddr()	(WINSOCK.102)
+ */
+HANDLE16 WINAPI WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
                                INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
@@ -1188,14 +1618,17 @@
                           (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
 
   if( pwsi ) 
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
-			    type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, type, addr, len,
+			    NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
   return 0;
 }
 
 
-HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
-                               SEGPTR sbuf, INT16 buflen)
+/***********************************************************************
+ *       WSAAsyncGetHostByName()	(WINSOCK.103)
+ */
+HANDLE16 WINAPI WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                      SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1203,14 +1636,17 @@
                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
 
   if( pwsi )
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
-                            0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+                            NULL, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
   return 0;
 }                     
 
 
-HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
-                                SEGPTR sbuf, INT16 buflen)
+/***********************************************************************
+ *       WSAAsyncGetProtoByName()	(WINSOCK.105)
+ */
+HANDLE16 WINAPI WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                       SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1218,14 +1654,17 @@
                           (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
 
   if( pwsi )
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
-                            0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+                            NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
   return 0;
 }
 
 
-HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
-                                  SEGPTR sbuf, INT16 buflen)
+/***********************************************************************
+ *       WSAAsyncGetProtoByNumber()	(WINSOCK.104)
+ */
+HANDLE16 WINAPI WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
+                                         SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1233,14 +1672,17 @@
                           (unsigned)pwsi, hWnd, uMsg, number );
 
   if( pwsi )
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
-                            number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, number, NULL, 0,
+                            NULL, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
   return 0;
 }
 
 
-HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
-                               LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+/***********************************************************************
+ *       WSAAsyncGetServByName()	(WINSOCK.107)
+ */
+HANDLE16 WINAPI WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                      LPCSTR proto, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1248,17 +1690,16 @@
                    (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
 
   if( pwsi )
-  { 
-    async_ctl.buffer = (char*)proto;
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
-                            0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
-  }
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, 0, name, 0,
+                            proto, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
   return 0;
 }
 
-
-HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
-			       LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+/***********************************************************************
+ *       WSAAsyncGetServByPort()	(WINSOCK.106)
+ */
+HANDLE16 WINAPI WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
+                                      LPCSTR proto, SEGPTR sbuf, INT16 buflen)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1266,170 +1707,315 @@
                            (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
 
   if( pwsi )
-    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
-                            port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
+      return __WSAsyncDBQuery(pwsi, hWnd, uMsg, port, proto, 0,
+                              NULL, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
   return 0;
 }
 
-INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
+/***********************************************************************
+ *       WSACancelAsyncRequest()	(WINSOCK.108)
+ */
+INT16 WINAPI WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
 {
+  INT16			retVal = SOCKET_ERROR;
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
   ws_async_op*		p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
 
   dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
 			   (unsigned)pwsi, hAsyncTaskHandle);
   if( pwsi )
-    if( WINSOCK_check_async_op(p_aop) )
-    {
-  	kill(p_aop->pid, SIGKILL); 
-	waitpid(p_aop->pid, NULL, 0); /* just in case */
-	close(p_aop->fd[0]);
-	WINSOCK_unlink_async_op(p_aop);
-	WS_FREE(p_aop);
-	return 0;
-    }
-    else pwsi->err = WSAEINVAL;
-  return SOCKET_ERROR;
-}
-
-/* ----- asynchronous select() */
-
-int cancel_async_select(ws_socket* pws)
-{
-  if( pws->p_aop )
   {
-    kill(pws->p_aop->pid, SIGKILL);
-    waitpid(pws->p_aop->pid, NULL, 0);
-    WS_FREE(pws->p_aop); 
-    pws->p_aop = NULL;
-    return 1;
-  }
-  return 0;
-}
-
-void _sigusr1_handler_parent(int sig)
-{
-  /* child process puts MTYPE_CLIENT data packet into the
-   * 'async_qid' message queue and signals us with SIGUSR1.
-   * This handler reads the queue and posts 'uMsg' notification
-   * message.
-   */
-
-  ipc_packet		ipack;
-
-  signal( SIGUSR1, _sigusr1_handler_parent);
-  while( msgrcv(async_qid, (struct msgbuf*)&ipack,
-          MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
-  {
-    if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
-    {
-      ws_socket*        pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
-      if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
+      SIGNAL_MaskAsyncEvents( TRUE );	/* block SIGIO */
+      if( WINSOCK_cancel_async_op(p_aop) )
       {
-	  pws->flags &= ~(ipack.lParam);
-#if 0
-          printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
-                  pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
-#endif
-	  PostMessage16(pws->p_aop->hWnd, pws->p_aop->uMsg, 
-                        (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
+	  WS_FREE(p_aop);
+	  pwsi->num_async_rq--;
+	  retVal = 0;
       }
-      else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
-    }
-    else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
+      else pwsi->err = WSAEINVAL;
+      SIGNAL_MaskAsyncEvents( FALSE );
   }
+  return retVal;
 }
 
-int notify_client( ws_socket* pws, unsigned flag )
+/***********************************************************************
+ *      WSAAsyncSelect()		(WINSOCK.101)
+ */
+
+static ws_select_op* __ws_select_list = NULL;
+
+BOOL32 WINSOCK_HandleIO( int* max_fd, int num_pending, fd_set io_set[3] )
 {
-  if( pws->p_aop && ((pws->p_aop->flags & flag) ||
-		     (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
-  {
-     async_ctl.ip.mtype = MTYPE_PARENT;
-     async_ctl.ip.lParam = flag;
-     while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
-                               MTYPE_PARENT_SIZE, 0) == -1 )
-     { 
-	if( errno == EINTR ) continue;
-	else
-	{
-	    perror("AsyncSelect(parent)"); 
-	    cancel_async_select(pws);
-	    pws->flags &= WS_FD_INTERNAL;
-	    return 0;
-	}
-     }
-     kill(pws->p_aop->pid, SIGUSR1);
-     return 1;
-  }
-  return 0;
-}
+    /* This function is called by the event dispatcher
+     * with io_set containing the result of select() */
 
-INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
-{
-    ws_async_op*        p_aop;
+    ws_select_op*	psop = __ws_select_list;
+    BOOL32		bPost = FALSE;
+    DWORD		dwEvent, dwErrBytes;
+    int			num_posted;
 
-    if( cancel_async_select(pws) )  /* delete old async handler if any */
-      pws->flags &= WS_FD_INTERNAL;
+    dprintf_winsock(stddeb,"WINSOCK_HandleIO: %i pending descriptors\n", num_pending );
 
-    if( lEvent == 0 ) return 0;
-
-    /* setup async handler - some data may be redundant */
-
-    WINSOCK_unblock_io(pws->fd, 1);
-    if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
+    for( num_posted = dwEvent = 0 ; psop; psop = psop->next )
     {
-      p_aop->hWnd = hWnd;
-      p_aop->uMsg = uMsg;
-      pws->p_aop = p_aop;
+	unsigned	flags = psop->pws->flags;
+	int		fd = psop->pws->fd;
+	int		r, w, e;
 
-      async_ctl.lEvent = p_aop->flags = lEvent;
-      async_ctl.ws_sock = pws;
-      async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
-      async_ctl.ip.lParam = 0;
+	w = 0;
+	if( (r = FD_ISSET( fd, &io_set[EVENT_IO_READ] )) ||
+	    (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] )) ||
+	    (e = FD_ISSET( fd, &io_set[EVENT_IO_EXCEPT] )) )
+	{
+	    /* This code removes WS_FD flags on one-shot events (WS_FD_CLOSE, 
+	     * WS_FD_CONNECT), otherwise it clears descriptors in the io_set.
+	     * Reenabling calls turn them back on.
+	     */
 
-      p_aop->pid = fork();
-      if( p_aop->pid != -1 )
-        if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
-	else pws->flags |= lEvent;
+	    dprintf_winsock(stddeb,"\tchecking psop = 0x%08x\n", (unsigned) psop );
 
-      signal( SIGUSR1, _sigusr1_handler_parent );
-      return 0;                                  /* Wine process */
+	    num_pending--;
+
+	    if( flags & WS_FD_ACCEPT )
+	    {
+		/* listening socket */
+
+		FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
+		if( r )
+		{
+		    FD_CLR( fd, &io_set[EVENT_IO_READ] ); /* reenabled by the next accept() */
+		    dwEvent = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
+		    bPost = TRUE;
+		} 
+		else continue;
+	    }
+	    else if( flags & WS_FD_CONNECT )
+	    {
+		/* connecting socket */
+
+		if( w || (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] )) )
+		{
+		    /* ready to write means that socket is connected */
+
+		    psop->pws->flags |= WS_FD_CONNECTED;
+		    psop->pws->flags &= ~(WS_FD_CONNECT | WS_FD_INACTIVE);
+		    dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
+
+		    if( flags & (WS_FD_READ | WS_FD_CLOSE))
+			FD_SET( fd, &io_set[EVENT_IO_READ] );
+		    if( flags & WS_FD_WRITE ) FD_SET( fd, &io_set[EVENT_IO_WRITE] );
+		    else FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
+		    bPost = TRUE;
+		}
+		else if( r )
+		{
+		    /* failure - do read() to get correct errno */
+
+		    if( read( fd, &dwErrBytes, sizeof(dwErrBytes) ) == -1 )
+		    {
+			dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
+			bPost = TRUE;
+		    }
+		}
+		/* otherwise bPost stays FALSE */
+	    }
+	    else 
+	    {
+		/* connected socket --
+		 * removed WS_FD_OOB code for now.
+		 */
+
+		if( flags & WS_FD_WRITE &&
+		   (w || (w = FD_ISSET( fd, &io_set[EVENT_IO_WRITE] ))) )
+		{
+		    /* this will be reenabled when send() or sendto() fail with
+		     * WSAEWOULDBLOCK */
+
+		    if( PostMessage16( psop->hWnd, psop->uMsg, (WPARAM16)WS_PTR2HANDLE(psop->pws), 
+			              (LPARAM)WSAMAKESELECTREPLY( WS_FD_WRITE, 0 ) ) )
+		    {
+			FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
+			num_posted++;
+		    }
+		}
+
+		if( r && (flags & (WS_FD_READ | WS_FD_CLOSE)) )
+		{
+		    int val = (flags & WS_FD_RAW);
+
+		     /* WS_FD_RAW is set by the WSAAsyncSelect() init */
+
+		    bPost = TRUE;
+		    if( !val && ioctl( fd, FIONREAD, (char*)&dwErrBytes) == -1 )
+		    {
+			/* weirdness */
+
+			dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
+		    }
+		    else if( val || dwErrBytes )
+		    {
+			/* got pending data, will be reenabled by recv() or recvfrom() */
+
+			FD_CLR( fd, &io_set[EVENT_IO_READ] );
+			dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
+		    }
+		    else
+		    {
+			/* 0 bytes to read - connection reset by peer? */
+
+			do
+			    val = read( fd, (char*)&dwErrBytes, sizeof(dwErrBytes));
+			while( errno == EINTR );
+			if( errno != EWOULDBLOCK )
+			{
+			    switch( val )
+			    {
+				case  0: errno = ENETDOWN;	/* soft reset, fall through */
+				case -1: 			/* hard reset */
+					 dwEvent = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
+					 break;
+
+				default: bPost = FALSE;
+					 continue;		/* FIXME: this is real bad */
+			    }
+			}
+			else { bPost = FALSE; continue; }	/* more weirdness */
+
+			/* this is it, this socket is closed */
+
+			psop->pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE | WS_FD_WRITE);
+			FD_CLR( fd, &io_set[EVENT_IO_READ] );
+			FD_CLR( fd, &io_set[EVENT_IO_WRITE] );
+
+			if( *max_fd == (fd + 1) ) (*max_fd)--;
+		    }
+		}
+	    }
+
+	    if( bPost )
+	    {
+		PostMessage16( psop->hWnd, psop->uMsg, 
+			      (WPARAM16)WS_PTR2HANDLE(psop->pws), (LPARAM)dwEvent );
+		bPost = FALSE;
+		num_posted++;
+	    }
+	}
+	if( num_pending <= 0 ) break;
     }
-    return SOCKET_ERROR;
+
+    dprintf_winsock(stddeb, "\tdone, %i posted events\n", num_posted );
+    return ( num_posted ) ? TRUE : FALSE;
 }
 
-INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+
+INT16 WINAPI WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
 {
-  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
-  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+    ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+    LPWSINFO      pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
+    dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
 			  (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
-  if( _check_ws(pwsi, pws) )
-    if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
-    else pwsi->err = WSAENOBUFS;
-  return SOCKET_ERROR; 
+    if( _check_ws(pwsi, pws) )
+    {
+	ws_select_op* psop;
+
+	if( (psop = pws->psop) )
+	{
+	    /* delete previous control struct */
+
+	    if( psop == __ws_select_list )
+		__ws_select_list = psop->next;
+	    else
+		psop->prev->next = psop->next; 
+	    if( psop->next ) psop->next->prev = psop->prev;
+
+	    if( pws->flags & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
+		EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
+	    if( pws->flags & (WS_FD_CONNECT | WS_FD_WRITE) )
+		EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
+
+	    dprintf_winsock(stddeb,"\tremoving psop = 0x%08x\n", (unsigned) psop );
+
+	    WS_FREE( pws->psop );
+	    pws->flags &= ~(WS_FD_RAW | WS_FD_ACCEPT | WS_FD_CONNECT | 
+			    WS_FD_READ | WS_FD_WRITE | WS_FD_CLOSE);
+	    pws->psop = NULL;
+	}
+
+	if( lEvent )
+	{
+	    psop = (ws_select_op*)WS_ALLOC(sizeof(ws_select_op));
+	    if( psop )
+	    {
+		int sock_type, bytes = sizeof(int);
+
+		WINSOCK_unblock_io( pws->fd, TRUE );
+
+		psop->prev = NULL;
+		psop->next = __ws_select_list;
+		if( __ws_select_list )
+		    __ws_select_list->prev = psop;
+		__ws_select_list = psop;
+		
+		psop->pws = pws;
+		psop->hWnd = hWnd;
+		psop->uMsg = uMsg;
+
+		pws->psop = psop;
+		pws->flags |= (0x0000FFFF &lEvent);
+		getsockopt(pws->fd, SOL_SOCKET, SO_TYPE, &sock_type, &bytes);
+		if( sock_type == SOCK_RAW ) pws->flags |= WS_FD_RAW;
+
+		if( lEvent & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
+		    EVENT_AddIO( pws->fd, EVENT_IO_READ );
+		if( lEvent & (WS_FD_CONNECT | WS_FD_WRITE) )
+		    EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
+
+		/* TODO: handle WS_FD_ACCEPT right away if the socket is readable */
+
+		dprintf_winsock(stddeb,"\tcreating psop = 0x%08x\n", (unsigned)psop );
+
+		return 0; /* success */
+	    }
+	    else pwsi->err = WSAENOBUFS;
+	} 
+	else return 0;
+    } 
+    else if( pwsi ) pwsi->err = WSAEINVAL;
+    return SOCKET_ERROR; 
 }
 
-/* ----- miscellaneous */
 
-INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
+/***********************************************************************
+ *	__WSAFDIsSet()			(WINSOCK.151)
+ */
+INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set *set)
 {
   int i = set->fd_count;
   
-  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
+  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n", s,(unsigned long)set);
     
   while (i--)
-      if (set->fd_array[i] == fd) return 1;
+      if (set->fd_array[i] == s) return 1;
   return 0;
 }                                                            
 
-BOOL16 WSAIsBlocking(void)
+/***********************************************************************
+ *      __WSAFDIsSet()			(WSOCK32.151)
+ */
+INT32 WINAPI __WSAFDIsSet32(SOCKET32 s, ws_fd_set *set)
+{
+    return __WSAFDIsSet16( (SOCKET16)s, set );
+}
+
+/***********************************************************************
+ *      WSAIsBlocking()			(WINSOCK.114)(WSOCK32.114)
+ */
+BOOL32 WINAPI WSAIsBlocking(void)
 {
   /* By default WinSock should set all its sockets to non-blocking mode
    * and poll in PeekMessage loop when processing "blocking" ones. This 
-   * function * is supposed to tell if program is in this loop. Our 
+   * function is supposed to tell if program is in this loop. Our 
    * blocking calls are truly blocking so we always return FALSE.
    *
    * Note: It is allowed to call this function without prior WSAStartup().
@@ -1439,7 +2025,10 @@
   return FALSE;
 }
 
-INT16 WSACancelBlockingCall(void)
+/***********************************************************************
+ *      WSACancelBlockingCall()		(WINSOCK.113)(WSOCK32.113)
+ */
+INT32 WINAPI WSACancelBlockingCall(void)
 {
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
@@ -1449,45 +2038,82 @@
   return SOCKET_ERROR;
 }
 
-FARPROC16 WSASetBlockingHook16(FARPROC16 lpBlockFunc)
+
+/***********************************************************************
+ *      WSASetBlockingHook16()		(WINSOCK.109)
+ */
+FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
 {
   FARPROC16		prev;
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
   dprintf_winsock(stddeb, "WS_SetBlockingHook16(%08x): hook %08x\n", 
 			  (unsigned)pwsi, (unsigned) lpBlockFunc);
-
   if( pwsi ) { 
-      prev = pwsi->blocking_hook; 
-      pwsi->blocking_hook = lpBlockFunc; 
+      prev = (FARPROC16)pwsi->blocking_hook; 
+      pwsi->blocking_hook = (DWORD)lpBlockFunc; 
+      pwsi->flags &= ~WSI_BLOCKINGHOOK32;
       return prev; 
   }
   return 0;
 }
 
-FARPROC32 WSASetBlockingHook32(FARPROC32 lpBlockFunc)
-{
-  fprintf( stderr, "WSASetBlockingHook32(%p): empty stub\n", lpBlockFunc );
-  return NULL;
-}
 
-INT16 WSAUnhookBlockingHook16(void)
+/***********************************************************************
+ *      WSASetBlockingHook32()
+ */
+FARPROC32 WINAPI WSASetBlockingHook32(FARPROC32 lpBlockFunc)
 {
+  FARPROC32             prev;
   LPWSINFO              pwsi = wsi_find(GetCurrentTask());
 
-  dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
-  if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
-  return SOCKET_ERROR;
-}
-
-INT32 WSAUnhookBlockingHook32(void)
-{
-  fprintf( stderr, "WSAUnhookBlockingHook32(): empty stub\n");
+  dprintf_winsock(stddeb, "WS_SetBlockingHook32(%08x): hook %08x\n",
+                          (unsigned)pwsi, (unsigned) lpBlockFunc);
+  if( pwsi ) {
+      prev = (FARPROC32)pwsi->blocking_hook;
+      pwsi->blocking_hook = (DWORD)lpBlockFunc;
+      pwsi->flags |= WSI_BLOCKINGHOOK32;
+      return prev;
+  }
   return NULL;
 }
 
-VOID
-WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) 
+
+/***********************************************************************
+ *      WSAUnhookBlockingHook16()	(WINSOCK.110)
+ */
+INT16 WINAPI WSAUnhookBlockingHook16(void)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_UnhookBlockingHook16(%08x)\n", (unsigned)pwsi);
+    if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
+    return SOCKET_ERROR;
+}
+
+
+/***********************************************************************
+ *      WSAUnhookBlockingHook32()
+ */
+INT32 WINAPI WSAUnhookBlockingHook32(void)
+{
+    LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+    dprintf_winsock(stddeb, "WS_UnhookBlockingHook32(%08x)\n", (unsigned)pwsi);
+    if( pwsi )
+    {
+	pwsi->blocking_hook = 0;
+	pwsi->flags &= ~WSI_BLOCKINGHOOK32;
+	return 0;
+    }
+    return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ *      WsControl()
+ */
+VOID WINAPI WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,
+                      LPDWORD x5,LPDWORD x6) 
 {
 	fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
 		x1,x2,x3,x4,x5,x6
@@ -1548,8 +2174,8 @@
 {
    /* Duplicate hostent structure and flatten data (with its pointers)
     * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
-    * relative to 0 depending on "flag" value. Return data size (also 
-    * in the pwsi->buflen).
+    * relative to pwsi->buffer depending on "flag" value. Returns size
+    * of the data copied (also in the pwsi->buflen).
     */
 
    int size = hostent_size(p_he);
@@ -1561,14 +2187,14 @@
      p = pwsi->buffer;
      p_base = (flag & WS_DUP_OFFSET) ? NULL
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
-     p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
+     p += (flag & WS_DUP_NATIVE) ? sizeof(struct hostent) : sizeof(struct ws_hostent);
      p_name = p;
      strcpy(p, p_he->h_name); p += strlen(p) + 1;
      p_aliases = p;
      p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
      p_addr = p;
      list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
-     if( !(flag & WS_DUP_SEGPTR) )
+     if( flag & WS_DUP_NATIVE )
      { struct hostent* p_to = (struct hostent*)pwsi->buffer;
        p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
        p_to->h_name = p_base + (p_name - pwsi->buffer);
@@ -1587,22 +2213,6 @@
    return size;
 }
 
-void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
-{
-   /* add 'base' to ws_hostent pointers to convert them from offsets */ 
-
-   int i;
-   unsigned*	p_aliases,*p_addr;
-
-   p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases); 
-   p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
-   ((unsigned)(p_wshe->h_name)) += (unsigned)base;
-   ((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
-   ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
-   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
-   for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
-}
-
 /* ----- protoent */
 
 static int protoent_size(struct protoent* p_pe)
@@ -1626,12 +2236,12 @@
      p = pwsi->buffer; 
      p_base = (flag & WS_DUP_OFFSET) ? NULL
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
-     p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
+     p += (flag & WS_DUP_NATIVE)? sizeof(struct protoent) : sizeof(struct ws_protoent);
      p_name = p;
      strcpy(p, p_pe->p_name); p += strlen(p) + 1;
      p_aliases = p;
      list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
-     if( !(flag & WS_DUP_NATIVE) )
+     if( flag & WS_DUP_NATIVE )
      { struct protoent* p_to = (struct protoent*)pwsi->buffer;
        p_to->p_proto = p_pe->p_proto;
        p_to->p_name = p_base + (p_name - pwsi->buffer); 
@@ -1646,15 +2256,6 @@
    return size;
 }
 
-void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
-{
-   int i;
-   unsigned*       p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases); 
-   ((unsigned)(p_wspe->p_name)) += (unsigned)base;
-   ((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
-   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
-}
-
 /* ----- servent */
 
 static int servent_size(struct servent* p_se)
@@ -1678,7 +2279,7 @@
      p = pwsi->buffer;
      p_base = (flag & WS_DUP_OFFSET) ? NULL 
 				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
-     p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
+     p += (flag & WS_DUP_NATIVE)? sizeof(struct servent) : sizeof(struct ws_servent);
      p_name = p;
      strcpy(p, p_se->s_name); p += strlen(p) + 1;
      p_proto = p;
@@ -1686,7 +2287,7 @@
      p_aliases = p;
      list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
 
-     if( !(flag & WS_DUP_SEGPTR) )
+     if( flag & WS_DUP_NATIVE )
      { struct servent* p_to = (struct servent*)pwsi->buffer;
        p_to->s_port = p_se->s_port;
        p_to->s_name = p_base + (p_name - pwsi->buffer); 
@@ -1703,16 +2304,6 @@
    return size;
 }
 
-void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
-{
-   int i;
-   unsigned*       p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
-   ((unsigned)(p_wsse->s_name)) += (unsigned)base;
-   ((p_wsse->s_proto)) += (unsigned)base;
-   ((p_wsse->s_aliases)) += (unsigned)base;
-   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
-}
-
 /* ----------------------------------- error handling */
 
 UINT16 wsaErrno(void)