Index: trunk/src/wsock32/asyncapi.cpp
===================================================================
--- trunk/src/wsock32/asyncapi.cpp	(revision 3203)
+++ 	(revision )
@@ -1,388 +1,0 @@
-/* $Id: asyncapi.cpp,v 1.1 2000-03-22 18:46:14 sandervl Exp $ */
-
-/*
- *
- * Win32 SOCK32 for OS/2 (Async apis)
- *
- * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
- *
- * Based on Wine code: (dlls\winsock\async.c)
- * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
- * (C) 1999 Marcus Meissner
- *
- * Project Odin Software License can be found in LICENSE.TXT
- *
- */
-#define INCL_BASE
-#include <os2wrap.h>
-#include <stdio.h>
-#include <string.h>
-#include <odin.h>
-#include <odinwrap.h>
-#include <os2sel.h>
-#include <misc.h>
-#include <win32api.h>
-#include "wsock32.h"
-#include "asyncthread.h"
-#include "wsastruct.h"
-
-#define DBG_LOCALLOG	DBG_async
-#include "dbglocal.h"
-
-ODINDEBUGCHANNEL(WSOCK32-ASYNC)
-
-//******************************************************************************
-//******************************************************************************
-void ASYNCCNV WSAsyncThreadProc(void *pparm)
-{
- PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
- LPARAM           lParam;
- int              size = 0;
- int              fail = NO_ERROR;
- 
-   if(!pThreadParm->fCancelled)
-   {
-	switch(pThreadParm->request)
-	{
-	case ASYNC_GETHOSTBYNAME:
-	case ASYNC_GETHOSTBYADDR:
-	{
-	  struct hostent  *ret;
-
-		if(pThreadParm->request == ASYNC_GETHOSTBYNAME) {
-	      		ret = gethostbyname(pThreadParm->u.gethostbyname.name);
-
-   			free(pThreadParm->u.gethostbyname.name);
-			pThreadParm->u.gethostbyname.name = 0;
-		}
-		else {
-			ret = gethostbyaddr(pThreadParm->u.gethostbyaddr.addr, 
-                                            pThreadParm->u.gethostbyaddr.len,
-                                            pThreadParm->u.gethostbyaddr.type);
-
-   			free(pThreadParm->u.gethostbyaddr.addr);
-			pThreadParm->u.gethostbyaddr.addr = 0;
-		}
-	      	if (ret != NULL) {
-			size = WS_copy_he((struct ws_hostent *)pThreadParm->buf,
-	                                  pThreadParm->buf,
-	                                  pThreadParm->buflen,
-	                                  ret);
-			if(size < 0) {
-	            		fail = WSAENOBUFS;
-				size = -size;
-	         	}
-	      	}
-	      	else  	fail = WSANO_DATA;
-		break;
-	}
-
-	case ASYNC_GETPROTOBYNAME:
-	case ASYNC_GETPROTOBYNUMBER:
-	{
-	  struct protoent *ret;
-
-		if(pThreadParm->request == ASYNC_GETPROTOBYNAME) {
-	      		ret = getprotobyname(pThreadParm->u.getprotobyname.name);
-
-			free(pThreadParm->u.getprotobyname.name);
-			pThreadParm->u.getprotobyname.name = 0;
-		}
-      		else	ret = getprotobynumber(pThreadParm->u.getprotobynumber.number);
-
-	      	if (ret != NULL) {
-			size = WS_copy_pe((struct ws_protoent *)pThreadParm->buf,
-	                                  pThreadParm->buf,
-	                                  pThreadParm->buflen,
-	                                  ret);
-			if(size < 0) {
-	            		fail = WSAENOBUFS;
-				size = -size;
-	         	}
-	      	}
-	      	else  	fail = WSANO_DATA;
-
-		break;
-	}
-
-	case ASYNC_GETSERVBYNAME:
-	case ASYNC_GETSERVBYPORT:
-	{
-	  struct servent  *ret;
-
-		if(pThreadParm->request == ASYNC_GETSERVBYNAME) {
-	      		ret = getservbyname(pThreadParm->u.getservbyname.name, pThreadParm->u.getservbyname.proto);
-
-   			free(pThreadParm->u.getservbyname.name);
-			pThreadParm->u.getservbyname.name = 0;
-
-	   		if(pThreadParm->u.getservbyname.proto) {
-				free(pThreadParm->u.getservbyname.proto);
-				pThreadParm->u.getservbyname.proto = 0;
-   			}
-
-		}
-		else {
-			ret = getservbyport(pThreadParm->u.getservbyport.port, pThreadParm->u.getservbyport.proto);
-	   		if(pThreadParm->u.getservbyport.proto) {
-				free(pThreadParm->u.getservbyport.proto);
-				pThreadParm->u.getservbyport.proto = 0;
-   			}
-		}
-
-	      	if (ret != NULL) {
-			size = WS_copy_se((struct ws_servent *)pThreadParm->buf,
-	                                  pThreadParm->buf,
-	                                  pThreadParm->buflen,
-        	                          ret);
-			if(size < 0) {
-	            		fail = WSAENOBUFS;
-				size = -size;
-	         	}
-	      	}
-	      	else  	fail = WSANO_DATA;
-		break;
-	}
-	}
-   }
-   lParam = (fail << 16) | size;
-
-   if(!pThreadParm->fCancelled) {
-  	PostMessageA(pThreadParm->hwnd, pThreadParm->msg, 
-                     (WPARAM)pThreadParm->hAsyncTaskHandle, lParam);
-   }
-   RemoveFromQueue(pThreadParm); 
-}
-//******************************************************************************
-//******************************************************************************
-LHANDLE WSAAsyncRequest(AsyncRequestType requesttype, HWND hwnd, int msg, char *buf, 
-                        int buflen, PVOID param1, PVOID param2, PVOID param3,
-                        PVOID param4)
-{
-  PASYNCTHREADPARM pThreadParm;
-  LHANDLE          hHost = 0;
-  LPSTR            tempname;
-  LPSTR            tempproto;
-  LPSTR            tempaddr;
-
-   if(!fWSAInitialized)
-   {
-      	WSASetLastError(WSANOTINITIALISED);
-   }
-   else
-   if(WSAIsBlocking())
-   {
-        WSASetLastError(WSAEINPROGRESS);      	// blocking call in progress
-   }
-   else
-   if(!IsWindow(hwnd))
-   {
-        WSASetLastError(WSAEINVAL);           	// invalid parameter
-   }
-   else
-   if(buf == NULL || buflen == 0) {
-        WSASetLastError(WSAENOBUFS);         	// invalid parameter
-   }
-   else
-   {
-	pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
-	if(pThreadParm == NULL) {
-		dprintf(("WSAAsyncRequest: malloc failure!"));
-		DebugInt3();
-		WSASetLastError(WSAEFAULT);
-		return 0;
-	}
-	pThreadParm->request= requesttype;
-        pThreadParm->hwnd   = hwnd;
-        pThreadParm->msg    = msg;
-        pThreadParm->buf    = buf;
-        pThreadParm->buflen = buflen;
-
-	switch(requesttype) {
-	case ASYNC_GETHOSTBYNAME:
-		tempname = (LPSTR)malloc(strlen((char *)param1)+1);
-        	if(tempname == NULL)
-		{
-			dprintf(("WSAAsyncGetHostByName: malloc failure!"));
-			DebugInt3();
-			WSASetLastError(WSAEFAULT);
-			return 0;
-		}
-		pThreadParm->u.gethostbyname.name   = tempname;
-		strcpy(pThreadParm->u.gethostbyname.name, (char *)param1);
-		break;
-
-	case ASYNC_GETHOSTBYADDR:
-		tempaddr = (LPSTR)malloc(strlen((char *)param1)+1);
-	        if(tempaddr == NULL)
-		{
-			dprintf(("WSAAsyncGetHostByAddr: malloc failure!"));
-			DebugInt3();
-			WSASetLastError(WSAEFAULT);
-			return 0;
-		}
-
-        	pThreadParm->u.gethostbyaddr.len  = (int)param2;
-	        pThreadParm->u.gethostbyaddr.type = (int)param3;
-		pThreadParm->u.gethostbyaddr.addr = tempaddr;
-		strcpy(pThreadParm->u.gethostbyaddr.addr, (char *)param1);
-		break;
-
-	case ASYNC_GETPROTOBYNAME:
-		tempname = (LPSTR)malloc(strlen((char *)param1)+1);
-	        if(tempname == NULL)
-		{
-			dprintf(("WSAAsyncGetProtoByName: malloc failure!"));
-			DebugInt3();
-			WSASetLastError(WSAEFAULT);
-			return 0;
-		}
-		pThreadParm->u.getprotobyname.name = tempname;
-		strcpy(pThreadParm->u.getprotobyname.name, (char *)param1);
-		break;
-
-	case ASYNC_GETPROTOBYNUMBER:
-		pThreadParm->u.getprotobynumber.number = (int)param1;
-		break;
-
-	case ASYNC_GETSERVBYNAME:
-		tempname    = (LPSTR)malloc(strlen((char *)param1)+1);
-		tempproto   = NULL;
-		if(param2) {
-			tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
-		}
-	        if(tempname == NULL || (param2 && !tempproto))
-		{
-			dprintf(("WSAAsyncGetServByName: malloc failure!"));
-			DebugInt3();
-			WSASetLastError(WSAEFAULT);
-			return 0;
-		}
-		pThreadParm->u.getservbyname.name   = tempname;
-		strcpy(pThreadParm->u.getservbyname.name, (char *)param1);
-		pThreadParm->u.getservbyname.proto   = tempproto;
-		if(param2)
-			strcpy(pThreadParm->u.getservbyname.proto, (char *)param2);
-		break;
-
-	case ASYNC_GETSERVBYPORT:
-		if(param2) {
-			tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
-		}
-	        if(param2 && !tempproto)
-		{
-			dprintf(("WSAAsyncGetServByPort: malloc failure!"));
-			DebugInt3();
-			WSASetLastError(WSAEFAULT);
-			return 0;
-		}
-		pThreadParm->u.getservbyport.port   = (int)param1;
-		pThreadParm->u.getservbyport.proto  = tempproto;
-		if(param2)
-			strcpy(pThreadParm->u.getservbyport.proto, (char *)param2);
-		break;
-	}
-   	return (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
-   }
-   return 0;
-}                      
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION5(LHANDLE,WSAAsyncGetHostByName,
-              HWND,hWnd,
-              u_int,wMsg,
-              const char *,name,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetHostByName %s", name));
-
-   return WSAAsyncRequest(ASYNC_GETHOSTBYNAME, hWnd, wMsg, buf, buflen, 
-                          (PVOID)name, 0, 0, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION7(LHANDLE,WSAAsyncGetHostByAddr,
-              HWND,hWnd,
-              u_int,wMsg,
-              const char *,addr,
-              int,len,
-              int,type,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetHostByAddr %s", addr));
-
-   return WSAAsyncRequest(ASYNC_GETHOSTBYADDR, hWnd, wMsg, buf, buflen, 
-                          (PVOID)addr, (PVOID)len, (PVOID)type, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByName,
-              HWND,hWnd,
-              u_int,wMsg,
-              const char *,name,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetProtoByName %s", name));
-
-   return WSAAsyncRequest(ASYNC_GETPROTOBYNAME, hWnd, wMsg, buf, buflen, 
-                          (PVOID)name, 0, 0, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByNumber,
-              HWND,hWnd,
-              u_int,wMsg,
-              int,number,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetProtoByNumber %d", number));
-
-   return WSAAsyncRequest(ASYNC_GETPROTOBYNUMBER, hWnd, wMsg, buf, buflen, 
-                          (PVOID)number, 0, 0, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION6(LHANDLE,WSAAsyncGetServByName,
-              HWND,hWnd,
-              u_int,wMsg,
-              const char *,name,
-              const char *,proto,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetServByName %s", name));
-
-   return WSAAsyncRequest(ASYNC_GETSERVBYNAME, hWnd, wMsg, buf, buflen, 
-                          (PVOID)name, (PVOID)proto, 0, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION6(LHANDLE,WSAAsyncGetServByPort,
-              HWND,hWnd,
-              u_int,wMsg,
-              int,port,
-              const char *,proto,
-              char *,buf,
-              int,buflen)
-{
-   dprintf(("WSAAsyncGetServByPort %d %s", port, proto));
-
-   return WSAAsyncRequest(ASYNC_GETSERVBYPORT, hWnd, wMsg, buf, buflen, 
-                          (PVOID)port, (PVOID)proto, 0, 0);
-}
-//******************************************************************************
-//******************************************************************************
-ODINFUNCTION4(int,WSAAsyncSelect,
-              SOCKET,s,
-              HWND,hWnd,
-              u_int,wMsg,
-              long,lEvent)
-{
-  return SOCKET_ERROR;
-}
-//******************************************************************************
-//******************************************************************************
Index: trunk/src/wsock32/new/asyncapi.cpp
===================================================================
--- trunk/src/wsock32/new/asyncapi.cpp	(revision 3203)
+++ trunk/src/wsock32/new/asyncapi.cpp	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: asyncapi.cpp,v 1.1 2000-03-22 20:01:04 sandervl Exp $ */
+/* $Id: asyncapi.cpp,v 1.2 2000-03-23 19:21:53 sandervl Exp $ */
 
 /*
@@ -7,5 +7,5 @@
  * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
  *
- * Based on Wine code: (dlls\winsock\async.c)
+ * Parts based on Wine code: (dlls\winsock\async.c)
  * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
  * (C) 1999 Marcus Meissner
@@ -17,4 +17,5 @@
 #include <os2wrap.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <odin.h>
@@ -152,5 +153,4 @@
                      (WPARAM)pThreadParm->hAsyncTaskHandle, lParam);
    }
-   RemoveFromQueue(pThreadParm); 
 }
 //******************************************************************************
@@ -161,8 +161,8 @@
 {
   PASYNCTHREADPARM pThreadParm;
-  LHANDLE          hHost = 0;
-  LPSTR            tempname;
-  LPSTR            tempproto;
-  LPSTR            tempaddr;
+  LHANDLE          hAsyncRequest = 0;
+  LPSTR            tempname  = 0;
+  LPSTR            tempproto = 0;
+  LPSTR            tempaddr  = 0;
 
    if(!fWSAInitialized)
@@ -193,4 +193,5 @@
 		return 0;
 	}
+	memset(pThreadParm, 0, sizeof(*pThreadParm));
 	pThreadParm->request= requesttype;
         pThreadParm->hwnd   = hwnd;
@@ -283,5 +284,17 @@
 		break;
 	}
-   	return (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
+   	hAsyncRequest = (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
+	if(hAsyncRequest == 0) {
+		free(pThreadParm);
+		if(tempname)	free(tempname);
+		if(tempaddr)	free(tempaddr);
+		if(tempproto)	free(tempproto);
+
+		dprintf(("WSAAsyncRequest: QueueAsyncJob failure!"));
+		DebugInt3();
+		WSASetLastError(WSAEFAULT);
+	 	return 0;
+	}
+	return hAsyncRequest;
    }
    return 0;
@@ -377,4 +390,165 @@
 //******************************************************************************
 //******************************************************************************
+void AsyncNotifyEvent(PASYNCTHREADPARM pThreadParm, ULONG event, ULONG socket_error)
+{
+   pThreadParm->u.asyncselect.lEventsPending &= ~event;
+
+   event = WSAMAKESELECTREPLY(event, socket_error);
+
+   PostMessageA(pThreadParm->hwnd, pThreadParm->msg, (WPARAM)pThreadParm->u.asyncselect.s, 
+               (LPARAM)event);
+}
+//******************************************************************************
+#define  nr(i) 		((i != -1) ? 1 : 0)
+#define  ready(i)       ((i != -1) && (sockets[i] != -1))
+//******************************************************************************
+void ASYNCCNV WSAsyncSelectThreadProc(void *pparm)
+{
+ PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
+ SOCKET           sockets[3];
+ SOCKET           s = pThreadParm->u.asyncselect.s;
+ int       	  noread, nowrite, noexcept, state, sockoptlen, sockoptval;
+ int              tmp, i, lEventsPending, ret, bytesread;
+  
+   while(TRUE)
+   {
+asyncloopstart:
+	i         = 0;
+	noread    = nowrite = noexcept = -1;
+
+	//break if user cancelled request
+      	if(pThreadParm->u.asyncselect.lEvents == 0) {
+		break;
+      	}
+
+        lEventsPending = pThreadParm->u.asyncselect.lEventsPending;
+      	//block if no events are pending
+      	if(lEventsPending == 0)
+      	{
+		//wait for events to be enabled
+		pThreadParm->u.asyncselect.asyncSem->wait();
+		//reset event semaphore
+		pThreadParm->u.asyncselect.asyncSem->reset();
+         	continue;
+      	}
+
+	if(lEventsPending & (FD_READ | FD_CLOSE | FD_ACCEPT)) {
+		noread = i++;
+		sockets[noread] = s;
+	}
+	if(lEventsPending & (FD_WRITE | FD_CONNECT)) {
+		nowrite = i++;
+		sockets[nowrite] = s;
+	}
+	if(lEventsPending & FD_OOB) {
+		noexcept = i++;
+		sockets[noexcept] = s;
+	}
+
+        dprintf(("WSAsyncSelectThreadProc %x wrs=%d, rds=%d, oos =%d, pending = %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending));
+
+	ret = select((int *)sockets, nr(noread), nr(nowrite), nr(noexcept), -1);
+	if(ret == SOCKET_ERROR) {
+		int selecterr = sock_errno();
+		switch(selecterr) 
+		{
+		case SOCEINTR:
+			goto asyncloopstart;	//so_cancel was called
+
+		case SOCECONNRESET:
+		case SOCEPIPE:
+       			if(lEventsPending & FD_CLOSE)
+       				AsyncNotifyEvent(pThreadParm, FD_CLOSE, WSAECONNRESET);
+
+			//remote connection broken (so can't receive data anymore)
+                        //but can still send
+       			pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
+			goto asyncloopstart; 
+
+		case SOCEINVAL:
+       			if(lEventsPending & FD_CLOSE)
+       				AsyncNotifyEvent(pThreadParm, FD_CLOSE, selecterr);
+      			break;
+		default:
+			dprintf(("WSAsyncSelectThreadProc: select SOCKET_ERROR %x", selecterr));
+			break; //something bad happened
+		}
+		break;
+	}
+
+      	if(ready(nowrite))
+ 	{
+        	state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
+
+         	if(lEventsPending & FD_CONNECT) {
+	    		if(state & SS_ISCONNECTED) {
+				AsyncNotifyEvent(pThreadParm, FD_CONNECT, NO_ERROR);
+	    		}
+            		else {
+            			sockoptlen = sizeof(int);
+
+            			ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
+                	        		 (char *) &sockoptval, &sockoptlen);
+				if(sockoptval == (WSAECONNREFUSED-WSABASEERR)) {
+					AsyncNotifyEvent(pThreadParm, FD_CONNECT, WSAECONNREFUSED);
+				}
+            		}  
+        	}
+		else
+		if(!(state & SS_CANTSENDMORE) && (lEventsPending & FD_WRITE)) {
+			AsyncNotifyEvent(pThreadParm, FD_WRITE, NO_ERROR);
+		}
+        }
+
+      	if(ready(noread))
+      	{
+         	state = ioctl(s, FIONREAD, (CHAR *) &bytesread, sizeof(bytesread));
+         	if(state == SOCKET_ERROR) {
+            		if(lEventsPending & FD_CLOSE) 
+			{
+				AsyncNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
+				//remote connection broken (so can't receive data anymore)
+                        	//but can still send
+       				pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
+				continue;
+			}
+			else {
+				dprintf(("WSAsyncSelectThreadProc: ioctl SOCKET_ERROR!"));
+				break; //todo: correct???
+			}
+		}
+         	if(lEventsPending & FD_ACCEPT) 
+ 		{
+            		sockoptlen = sizeof(sockoptlen);
+
+            		ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS,
+                                         (char *) &sockoptval, &sockoptlen);
+		        if(ret == SOCKET_ERROR) {
+				dprintf(("WSAsyncSelectThreadProc: getsockopt SOCKET_ERROR!"));
+               			break;
+			}
+			if((sockoptval & SO_ACCEPTCONN) == SO_ACCEPTCONN) {
+				AsyncNotifyEvent(pThreadParm, FD_ACCEPT, NO_ERROR);
+			}
+		}
+		if((lEventsPending & FD_READ) && bytesread > 0) {
+			AsyncNotifyEvent(pThreadParm, FD_READ, NO_ERROR);
+		}
+	}
+      	if(ready(noexcept))
+      	{
+		if(lEventsPending & FD_OOB) {
+         		AsyncNotifyEvent(pThreadParm, FD_OOB, NO_ERROR);
+		}
+      	}
+	if((pThreadParm->u.asyncselect.lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT)) == 
+            (lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT))) {
+		DosSleep(10);
+	}
+   }
+   delete pThreadParm->u.asyncselect.asyncSem;
+}
+//******************************************************************************
+//******************************************************************************
 ODINFUNCTION4(int,WSAAsyncSelect,
               SOCKET,s,
@@ -383,6 +557,68 @@
               long,lEvent)
 {
-  return SOCKET_ERROR;
-}
-//******************************************************************************
-//******************************************************************************
+  PASYNCTHREADPARM pThreadParm;
+  int              nonblock = 1;
+  int              ret;
+
+   if(!fWSAInitialized)
+   {
+      	WSASetLastError(WSANOTINITIALISED);
+	return SOCKET_ERROR;
+   }
+   else
+   if(WSAIsBlocking())
+   {
+        WSASetLastError(WSAEINPROGRESS);      	// blocking call in progress
+	return SOCKET_ERROR;
+   }
+   else
+   if(hWnd && !IsWindow(hWnd))
+   {
+        WSASetLastError(WSAEINVAL);           	// invalid parameter
+	return SOCKET_ERROR;
+   }
+   //Set socket to non-blocking mode
+   ret = ioctl(s, FIONBIO, (char *) &nonblock, sizeof(nonblock));
+   if(ret == SOCKET_ERROR) {
+ 	WSASetLastError(wsaErrno());
+	return SOCKET_ERROR;
+   }
+   if(FindAndSetAsyncEvent(s, hWnd, wMsg, lEvent) == TRUE) {
+	//found and changed active async event
+	WSASetLastError(NO_ERROR);
+	return NO_ERROR;
+   }
+   pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
+   if(pThreadParm == NULL) {
+	dprintf(("WSAAsyncSelect: malloc failure!"));
+	DebugInt3();
+	WSASetLastError(WSAEFAULT);
+ 	return SOCKET_ERROR;
+   }
+   memset(pThreadParm, 0, sizeof(*pThreadParm));
+   pThreadParm->request= ASYNC_SELECT;
+   pThreadParm->hwnd   = hWnd;
+   pThreadParm->msg    = wMsg;
+   pThreadParm->u.asyncselect.lEvents        = lEvent;
+   pThreadParm->u.asyncselect.lEventsPending = lEvent;
+   pThreadParm->u.asyncselect.s              = s;
+   pThreadParm->u.asyncselect.asyncSem       = new VSemaphore;
+   if(pThreadParm->u.asyncselect.asyncSem == NULL) {
+	dprintf(("WSAAsyncSelect: VSemaphore alloc failure!"));
+	DebugInt3();
+	WSASetLastError(WSAEFAULT);
+ 	return SOCKET_ERROR;
+   }
+   if(QueueAsyncJob(WSAsyncSelectThreadProc, pThreadParm) == 0) {
+	delete pThreadParm->u.asyncselect.asyncSem;
+	free(pThreadParm);
+	dprintf(("WSAAsyncSelect: QueueAsyncJob failure!"));
+	DebugInt3();
+	WSASetLastError(WSAEFAULT);
+ 	return SOCKET_ERROR;
+   }
+   WSASetLastError(NO_ERROR);
+   return NO_ERROR;
+}
+//******************************************************************************
+//******************************************************************************
Index: trunk/src/wsock32/new/asyncthread.cpp
===================================================================
--- trunk/src/wsock32/new/asyncthread.cpp	(revision 3203)
+++ trunk/src/wsock32/new/asyncthread.cpp	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: asyncthread.cpp,v 1.1 2000-03-22 20:01:04 sandervl Exp $ */
+/* $Id: asyncthread.cpp,v 1.2 2000-03-23 19:21:53 sandervl Exp $ */
 
 /*
@@ -6,12 +6,13 @@
  * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
  *
- * 
- * Not everything is thread safe 
+ * TODO: Not everything is 100% thread safe  (i.e. async parameter updates)
  *
  * Project Odin Software License can be found in LICENSE.TXT
+ *
  */
 #define INCL_BASE
 #include <os2wrap.h>
 #include <os2sel.h>
+#include <stdlib.h>
 #include <wprocess.h>
 #include <win32api.h>
@@ -35,5 +36,11 @@
   pThreadParm->asyncProc((PVOID)arg);
 
-  WSASetBlocking(TRUE, pThreadParm->hThread);
+//only for blocking hooks (currently not implemented
+////  if(pThreadParm->request == ASYNC_BLOCKHOOK)
+////	WSASetBlocking(FALSE, pThreadParm->hThread);
+
+  pThreadParm->fActive = FALSE;
+  RemoveFromQueue(pThreadParm); 
+  free((PVOID)pThreadParm);
 
   DosExit(EXIT_THREAD, 0);
@@ -41,5 +48,5 @@
 //******************************************************************************
 //******************************************************************************
-ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm)
+ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm, BOOL fSetBlocking)
 {
  APIRET rc;
@@ -55,5 +62,5 @@
    AddToQueue(pThreadParm);
 
-   WSASetBlocking(TRUE);
+   if(fSetBlocking) WSASetBlocking(TRUE);
 
    rc = DosCreateThread(&tid, AsyncThread, (ULONG)pThreadParm, CREATE_READY, 16384);
@@ -61,5 +68,5 @@
    {
    	dprintf(("QueueAsyncJob: DosCreateThread failed with error %x", rc));
-   	WSASetBlocking(FALSE);
+   	if(fSetBlocking) WSASetBlocking(FALSE);
 	RemoveFromQueue(pThreadParm);
    	WSASetLastError(WSAEFAULT);
@@ -83,21 +90,21 @@
 void RemoveFromQueue(PASYNCTHREADPARM pThreadParm)
 {
- PASYNCTHREADPARM parm;
-
-   asyncThreadMutex.enter();
-   parm = threadList;
-
-   if(parm == pThreadParm) {
+ PASYNCTHREADPARM pThreadInfo;
+
+   asyncThreadMutex.enter();
+   pThreadInfo = threadList;
+
+   if(pThreadInfo == pThreadParm) {
 	threadList = pThreadParm->next;
    }
    else {
-	while(parm->next) {
-		if(parm->next == pThreadParm) {
-			parm->next = pThreadParm->next;
+	while(pThreadInfo->next) {
+		if(pThreadInfo->next == pThreadParm) {
+			pThreadInfo->next = pThreadParm->next;
 			break;
 		}
-		parm = parm->next;
-	}
-	if(parm == NULL) {
+		pThreadInfo = pThreadInfo->next;
+	}
+	if(pThreadInfo == NULL) {
 		dprintf(("RemoveFromQueue: parm %x not found!!", pThreadParm));
 		DebugInt3();
@@ -111,18 +118,18 @@
 int WIN32API WSACancelAsyncRequest(LHANDLE hAsyncTaskHandle)
 {
- PASYNCTHREADPARM parm;
+ PASYNCTHREADPARM pThreadInfo;
  BOOL             found = FALSE;
 
    dprintf(("WSACancelAsyncRequest: cancel task %x", hAsyncTaskHandle));
    asyncThreadMutex.enter();
-   parm = threadList;
-
-   while(parm) {
-	if(parm->hAsyncTaskHandle == hAsyncTaskHandle) {
-		parm->fCancelled = TRUE;
+   pThreadInfo = threadList;
+
+   while(pThreadInfo) {
+	if(pThreadInfo->hAsyncTaskHandle == hAsyncTaskHandle) {
+		pThreadInfo->fCancelled = TRUE;
 		found = TRUE;
 		break;
 	}
-	parm = parm->next;
+	pThreadInfo = pThreadInfo->next;
    }
    asyncThreadMutex.leave();
@@ -134,7 +141,86 @@
 }
 //******************************************************************************
+//Only to cancel blocking hooks
+//******************************************************************************
+int WIN32API WSACancelBlockingCall()
+{
+ HANDLE hThread = GetCurrentThread();
+
+   dprintf(("WSACancelBlockingCall"));
+#if 0
+   asyncThreadMutex.enter();
+   pThreadInfo = threadList;
+
+   while(pThreadInfo) {
+	if(pThreadInfo->hThread == hThread) {
+		pThreadInfo->fCancelled = TRUE;
+
+		if(pThreadInfo->request == ASYNC_BLOCKHOOK) {
+            		ret = so_cancel(pThreadInfo->blockedsocket);
+		}
+
+		found = TRUE;
+		break;
+	}
+	pThreadInfo = pThreadInfo->next;
+   }
+   asyncThreadMutex.leave();
+#endif
+   return SOCKET_ERROR;
+}
+//******************************************************************************
+//Assumes caller owns async thread mutex!
+//******************************************************************************
+static PASYNCTHREADPARM FindAsyncEvent(SOCKET s)
+{
+ PASYNCTHREADPARM pThreadInfo;
+
+   pThreadInfo = threadList;
+   while(pThreadInfo) {
+	if(pThreadInfo->u.asyncselect.s == s) {
+		return pThreadInfo;
+	}
+	pThreadInfo = pThreadInfo->next;
+   }
+   return NULL;
+}
+//******************************************************************************
+//******************************************************************************
+BOOL FindAndSetAsyncEvent(SOCKET s, HWND hwnd, int msg, ULONG lEvent)
+{
+ PASYNCTHREADPARM pThreadInfo;
+ 
+   asyncThreadMutex.enter();
+   pThreadInfo = FindAsyncEvent(s);
+   if(pThreadInfo) {
+	pThreadInfo->u.asyncselect.lEvents = lEvent;
+	pThreadInfo->hwnd                  = hwnd;
+	pThreadInfo->msg                   = msg;
+	//cancel pending select in async select thread (if any)
+	so_cancel(s);
+
+	//unblock async thread if it was waiting
+	pThreadInfo->u.asyncselect.asyncSem->post();
+   }
+   asyncThreadMutex.leave();
+   return(pThreadInfo != NULL);
+}
+//******************************************************************************
 //******************************************************************************
 void EnableAsyncEvent(SOCKET s, ULONG flags)
 {
+ PASYNCTHREADPARM pThreadInfo;
+
+   asyncThreadMutex.enter();
+   pThreadInfo = FindAsyncEvent(s);
+   if(pThreadInfo) {
+	pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
+	//cancel pending select in async select thread (if any)
+	so_cancel(s);
+
+	//unblock async thread if it was waiting
+	pThreadInfo->u.asyncselect.asyncSem->post();
+   }
+   asyncThreadMutex.leave();
 }
 //******************************************************************************
@@ -142,6 +228,16 @@
 BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
 {
-   return FALSE;
-}
-//******************************************************************************
-//******************************************************************************
+ PASYNCTHREADPARM pThreadInfo;
+
+   asyncThreadMutex.enter();
+   pThreadInfo = FindAsyncEvent(s);
+   if(pThreadInfo) {
+	*pHwnd   = pThreadInfo->hwnd;
+	*pMsg    = pThreadInfo->msg;
+	*plEvent = pThreadInfo->u.asyncselect.lEvents;
+   }
+   asyncThreadMutex.leave();
+   return(pThreadInfo != NULL);
+}
+//******************************************************************************
+//******************************************************************************
Index: trunk/src/wsock32/new/asyncthread.h
===================================================================
--- trunk/src/wsock32/new/asyncthread.h	(revision 3203)
+++ trunk/src/wsock32/new/asyncthread.h	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: asyncthread.h,v 1.1 2000-03-22 20:01:04 sandervl Exp $ */
+/* $Id: asyncthread.h,v 1.2 2000-03-23 19:21:54 sandervl Exp $ */
 
 /*
@@ -12,4 +12,5 @@
 
 #include <vmutex.h>
+#include <vsemaphore.h>
 
 #define	ASYNCCNV	_Optlink
@@ -23,5 +24,6 @@
   ASYNC_GETPROTOBYNUMBER,
   ASYNC_GETSERVBYNAME,
-  ASYNC_GETSERVBYPORT
+  ASYNC_GETSERVBYPORT,
+  ASYNC_SELECT
 } ;
 
@@ -62,13 +64,20 @@
 			LPSTR   proto;
 		} getservbyport;
+		struct {
+			VSemaphore *asyncSem;
+			DWORD       lEvents;
+                        DWORD       lEventsPending;
+			SOCKET      s;
+		} asyncselect;
         } u;
         _ASYNCTHREADPARM *next;
 } ASYNCTHREADPARM, *PASYNCTHREADPARM;
 
-ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm);
+ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm, BOOL fSetBlocking = FALSE);
 void  RemoveFromQueue(PASYNCTHREADPARM pThreadParm);
 
 void  EnableAsyncEvent(SOCKET s, ULONG flags);
 BOOL  QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent);
+BOOL  FindAndSetAsyncEvent(SOCKET s, HWND hwnd, int msg, ULONG lEvent);
 
 #endif  //__ASYNCTHREAD_H__
Index: trunk/src/wsock32/new/wsa.cpp
===================================================================
--- trunk/src/wsock32/new/wsa.cpp	(revision 3203)
+++ trunk/src/wsock32/new/wsa.cpp	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: wsa.cpp,v 1.1 2000-03-22 20:01:07 sandervl Exp $ */
+/* $Id: wsa.cpp,v 1.2 2000-03-23 19:21:54 sandervl Exp $ */
 
 /*
@@ -32,4 +32,9 @@
 ODINDEBUGCHANNEL(WSOCK32-WSA)
 
+#ifndef winsockcleanupsockets
+// Exported by SO32DLL.  Used to close all open sockets.
+void _System winsockcleanupsockets(void);
+#endif
+
 static void WSASetBlocking(BOOL fBlock);
 
@@ -53,11 +58,15 @@
     if (!lpWSAData) return WSAEINVAL;
 
-    pwsi = WINSOCK_GetIData();
-    if( pwsi == NULL )
+    if(fWSAInitialized == FALSE) 
     {
         WINSOCK_CreateIData();
         pwsi = WINSOCK_GetIData();
-	if (!pwsi) return WSASYSNOTREADY;
-    }
+
+    	sock_init();
+    }
+    else pwsi = WINSOCK_GetIData();
+
+    if (!pwsi) return WSASYSNOTREADY;
+
     pwsi->num_startup++;
     fWSAInitialized = TRUE;
@@ -75,4 +84,6 @@
     if( pwsi ) {
 	if( --pwsi->num_startup > 0 ) return 0;
+
+        winsockcleanupsockets();
 
 	fWSAInitialized = FALSE;
@@ -103,13 +114,4 @@
 //TODO: Implement this
 //******************************************************************************
-ODINFUNCTION0(int,WSACancelBlockingCall)
-{
-  LPWSINFO pwsi = WINSOCK_GetIData();
-
-  if( pwsi ) return 0;
-  return SOCKET_ERROR;
-}
-//******************************************************************************
-//******************************************************************************
 ODINFUNCTION0(int,WSAUnhookBlockingHook)
 {
@@ -126,5 +128,5 @@
 //******************************************************************************
 //******************************************************************************
-ODINFUNCTION0(BOOL,WSAIsBlocking)
+BOOL WIN32API WSAIsBlocking()
 {
     LPWSINFO pwsi = WINSOCK_GetIData();
Index: trunk/src/wsock32/new/wsock32.cpp
===================================================================
--- trunk/src/wsock32/new/wsock32.cpp	(revision 3203)
+++ trunk/src/wsock32/new/wsock32.cpp	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: wsock32.cpp,v 1.16 2000-03-22 20:01:08 sandervl Exp $ */
+/* $Id: wsock32.cpp,v 1.17 2000-03-23 19:21:54 sandervl Exp $ */
 
 /*
@@ -94,5 +94,5 @@
 	goto tryagain;
     }
-    else {
+    if(iData == NULL) {
 	dprintf(("WINSOCK_GetIData: couldn't find struct for thread %x", tid));
 	DebugInt3();// should never happen!!!!!!!
@@ -145,14 +145,16 @@
 //******************************************************************************
 //******************************************************************************
-ODINPROCEDURE1(WSASetLastError,
-               int,iError)
+void WIN32API WSASetLastError(int iError)
 {
   // according to the docs, WSASetLastError() is just a call-through
   // to SetLastError()
+  if(iError) {
+	dprintf(("WSASetLastError %x", iError));
+  }
   SetLastError(iError);
 }
 //******************************************************************************
 //******************************************************************************
-ODINFUNCTION0(int,WSAGetLastError)
+int WIN32API WSAGetLastError()
 {
   return GetLastError();
@@ -232,5 +234,5 @@
 
    //Close WSAAsyncSelect thread if one was created for this socket
-   EnableAsyncEvent(s, 0L);
+   WSAAsyncSelect(s, 0, 0, 0);
    
    if(ret == SOCKET_ERROR) {
@@ -291,4 +293,7 @@
       	return SOCKET_ERROR;
    } 
+   // clear high word (not used in OS/2's tcpip stack)
+   cmd = LOUSHORT(cmd);
+
    if(cmd != FIONBIO && cmd != FIONREAD && cmd != SIOCATMARK) {
         WSASetLastError(WSAEINVAL);
@@ -317,6 +322,5 @@
 	}
    }
-   // clear high word (not used in OS/2's tcpip stack)
-   ret = ioctl(s, LOUSHORT(cmd), (char *)argp, sizeof(int));
+   ret = ioctl(s, cmd, (char *)argp, sizeof(int));
 
    // Map EOPNOTSUPP to EINVAL
@@ -878,4 +882,5 @@
 		break;
 	default: 
+		dprintf(("setsockopt: unknown option %x", optname));
             	WSASetLastError(WSAENOPROTOOPT);
             	return SOCKET_ERROR;
@@ -892,4 +897,5 @@
         } 
 	else {
+		dprintf(("setsockopt: unknown option %x", optname));
        		WSASetLastError(WSAENOPROTOOPT);
       		return SOCKET_ERROR;
@@ -974,4 +980,5 @@
 		break;
 	default: 
+		dprintf(("getsockopt: unknown option %x", optname));
             	WSASetLastError(WSAENOPROTOOPT);
             	return SOCKET_ERROR;
@@ -988,4 +995,5 @@
         } 
 	else {
+		dprintf(("getsockopt: unknown option %x", optname));
        		WSASetLastError(WSAENOPROTOOPT);
       		return SOCKET_ERROR;
Index: trunk/src/wsock32/new/wsock32.h
===================================================================
--- trunk/src/wsock32/new/wsock32.h	(revision 3203)
+++ trunk/src/wsock32/new/wsock32.h	(revision 3205)
@@ -1,3 +1,3 @@
-/* $Id: wsock32.h,v 1.4 2000-03-22 20:01:09 sandervl Exp $ */
+/* $Id: wsock32.h,v 1.5 2000-03-23 19:21:55 sandervl Exp $ */
 
 /* WSOCK32.H--definitions & conversions for Odin's wsock32.dll.
@@ -24,4 +24,6 @@
 #include <sys\time.h>
 
+#include <odinwrap.h>
+
 /*
  * Socket state bits.
@@ -45,4 +47,6 @@
 //socketopt options
 #define SO_DONTLINGER   (u_int)(~SO_LINGER)
+
+#define WSAMAKESELECTREPLY(event,error)     MAKELONG(event,error)
 
 // WSAAsyncSelect flags
@@ -216,6 +220,6 @@
 void WIN32API WSASetLastError(int iError);
 int  WIN32API WSAGetLastError(void);
+int  WIN32API WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent);
 BOOL WIN32API WSAIsBlocking(void);
-int  WIN32API WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent);
 
 extern BOOL fWSAInitialized;
Index: trunk/src/wsock32/new/wsock32exp.def
===================================================================
--- trunk/src/wsock32/new/wsock32exp.def	(revision 3203)
+++ 	(revision )
@@ -1,55 +1,0 @@
-;Internal export definition file - autogenerated by ImpDef.
-LIBRARY WSOCK32 INITINSTANCE
-EXPORTS
-    _accept@12                                @1
-    _bind@12                                  @2
-    _closesocket@4                            @3
-    _connect@12                               @4
-    _getpeername@12                           @5
-    _getsockname@12                           @6
-    _getsockopt@20                            @7
-    _htonl@4                                  @8
-    _htons@4                                  @9
-    _inet_addr@4                              @10
-    _inet_ntoa@4                              @11
-    _ioctlsocket@12                           @12
-    _listen@8                                 @13
-    _ntohl@4                                  @14
-    _ntohs@4                                  @15
-    _recv@16                                  @16
-    _recvfrom@24                              @17
-    _select@20                                @18
-    _send@16                                  @19
-    _sendto@24                                @20
-    _setsockopt@20                            @21
-    _shutdown@8                               @22
-    _socket@12                                @23
-    _gethostbyaddr@12                         @51
-    _gethostbyname@4                          @52
-    _getprotobyname@4                         @53
-    _getprotobynumber@4                       @54
-    _getservbyname@8                          @55
-    _getservbyport@8                          @56
-    _gethostname@8                            @57
-    _WSAAsyncSelect@16                        @101
-    _WSAAsyncGetHostByAddr@28                 @102
-    _WSAAsyncGetHostByName@20                 @103
-    _WSAAsyncGetProtoByNumber@20              @104
-    _WSAAsyncGetProtoByName@20                @105
-    _WSAAsyncGetServByPort@24                 @106
-    _WSAAsyncGetServByName@24                 @107
-    _WSACancelAsyncRequest@4                  @108
-    _WSASetBlockingHook@4                     @109
-    _WSAUnhookBlockingHook@0                  @110
-    _WSAGetLastError@0                        @111
-    _WSASetLastError@4                        @112
-    _WSACancelBlockingCall@0                  @113
-    _WSAIsBlocking@0                          @114
-    _WSAStartup@8                             @115
-    _WSACleanup@0                             @116
-    ___WSAFDIsSet@8                           @151
-    _rcmd@24                                  @1102
-    _rexec@24                                 @1103
-    _WSARecvEx@16                             @1107
-    _s_perror@8                               @1108
-    _OS2gethostname@8                         @2000
