Release 961201

Sat Nov 30 19:21:17 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [configure]
	Re-generated with autoconf 2.11. Let me know if you have
	problems.

	* [controls/listbox.c] [controls/oldlbox.c]
	Listboxes rewritten from scratch. Moved old code still used by
	comboboxes to oldlbox.c

	* [misc/registry.c]
	Use temporary file when saving registry.

	* [windows/dialog.c]
	Implemented Win32 version of DlgDirList() and DlgDirListComboBox().

	* [windows/winproc.c]
	Added translation for listbox Win32 messages.

Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [controls/widgets.c] [controls/button.c]
	Fixed some incompatibilities with CTL3D DLL.

	* [windows/dialog.c]
	Made dialog windows fit into the desktop.

	* [misc/winsock.c] [misc/winsock_async.c]
	New Winsock engine.

	* [windows/message.c]
	GetMessage() fixes.

	* [windows/queue.c] [windows/hook.c] [windows/win.c]
	SetMessageQueue() fixes.

Fri Nov 29 10:25:12 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [objects/text.c]
	DrawText16(): Fixed return value.

Tue Nov 26 14:47:09 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/profile.c] [*/*]
	Added Win32 profile functions, updated to new naming standard.

	* [objects/font.c] [if1632/thunk.c] [include/windows.h]
	Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
	structures.

	* [misc/ole2nls.c] [if1632/thunk.c]
	Added EnumSystemLocales() (winhelp.exe).

	* [misc/registry.c]
	Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no

	* [win32/file.c]
	Partially fixed CreateFileMapping(), added UnmapViewOfFile().

Sat Nov 23 23:36:05 1996  Ronan Waide  <waider@waider.ie>

	* [misc/shell.c]
	Fixed some FIXMEs relating to ShellExec() and FindExecutable().

	* [misc/main.c]
	Implemented a few more of the SystemParametersInfo() cases.

Tue Nov 19 01:24:34 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [include/keyboard.h]
	New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).

	* [include/windows.h]
	New [VK_A, VK_Z] and [VK_0, VK9] macros.

	* [misc/keyboard.c]
	Fixes in KeyTable and ToAscii.

	* [objects/font.c]
	FONT_init : Give default value for MSWIN "system" font.
	FONT_MatchFont : Do not try every size of a font family if the
	family does not exist.

	* [windows/event.c]
	lastEventChar hack removed.
	KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
	and QueueKeyStateTable (maintained in message.c).
	EVENT_key : Corrections to the extended bit setting.

	* [windows/message.c] [windows/keyboard.c]
	Implementation of a new QueueKeyStateTable : table of key states
	valid when messages are retrieved by GetMessage or PeekMessage,
	and valid for TranslateMessage.
	TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
	and ToAscii.
	
Mon Nov 18 16:59:01 1996  Robert Pouliot <krynos@clic.net>

	* [graphics/Makefile.in] [graphics/wing.c]
	  [if1632/wing.spec]
	Some functions for WinG support, mostly empty stubs.

	* [misc/crtdll.c] [if1632/crtdll.spec]
	Many functions added to CRTDLL, mostly calls to Unix C library.
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 32b5cc2..e21b133 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -38,7 +38,8 @@
 	user.c \
 	ver.c \
 	w32sys.c \
-	winsocket.c \
+	winsock.c \
+	winsock_async.c \
 	wsprintf.c \
 	xmalloc.c
 
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 80aa834..fddf5a9 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -166,22 +166,14 @@
  */
 static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath)
 {
-    BOOL32 ret = FALSE;
     int len;
-    char *str = SEGPTR_ALLOC(512);
-    if (!str) return TRUE;
+    char str[512];
 
     lstrcpyn32A( str, newPath, 512 );
     len = strlen(str);
-    GetDlgItemText32A( hWnd, edt1, str + len, 512 - len );
-    if (DlgDirList(hWnd, SEGPTR_GET(str), lst1, 0, 0x0000))
-    {
-        strcpy( str, "*.*" );
-        DlgDirList(hWnd, SEGPTR_GET(str), lst2, stc1, 0x8010 );
-        ret = TRUE;
-    }
-    SEGPTR_FREE(str);
-    return ret;
+    GetDlgItemText32A( hWnd, edt1, str + len, sizeof(str) - len );
+    if (!DlgDirList32A( hWnd, str, lst1, 0, 0x0000 )) return FALSE;
+    return DlgDirList32A( hWnd, "*.*", lst2, stc1, 0x8010 );
 }
 
 /***********************************************************************
@@ -388,10 +380,7 @@
   			lpofn->nFilterIndex, tmpstr);
   SetDlgItemText32A( hWnd, edt1, tmpstr );
   /* get drive list */
-  pstr = SEGPTR_ALLOC(1);
-  *pstr = 0;
-  DlgDirListComboBox16(hWnd, SEGPTR_GET(pstr), cmb2, 0, 0xC000);
-  SEGPTR_FREE(pstr);
+  DlgDirListComboBox32A(hWnd, "", cmb2, 0, 0xC000);
   /* read initial directory */
   if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) 
     {
diff --git a/misc/crtdll.c b/misc/crtdll.c
index e7a8be6..66b0549 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -616,6 +616,22 @@
 }
 
 /*********************************************************************
+ *                  calloc        (CRTDLL.350)
+ */
+VOID* CRTDLL_calloc(DWORD size, DWORD count)
+{
+    return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
+}
+
+/*********************************************************************
+ *                  realloc        (CRTDLL.447)
+ */
+VOID* CRTDLL_realloc( VOID *ptr, DWORD size )
+{
+    return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
+}
+
+/*********************************************************************
  *                  free          (CRTDLL.427)
  */
 VOID CRTDLL_free(LPVOID ptr)
diff --git a/misc/driver.c b/misc/driver.c
index e09113b..c0a23b0 100644
--- a/misc/driver.c
+++ b/misc/driver.c
@@ -21,7 +21,7 @@
     char  str[256];
     LPSTR ptr;
 
-    if (GetPrivateProfileString( "drivers", NULL, "", str, sizeof(str),
+    if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str),
 				 "SYSTEM.INI" ) < 2)
     {
     	fprintf( stderr,
@@ -84,7 +84,7 @@
 		    lpDriverName, lpSectionName, lParam );
 
     if (lpSectionName == NULL) lpSectionName = "drivers";
-    GetPrivateProfileString( lpSectionName, lpDriverName, "", DrvName,
+    GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName,
 			     sizeof(DrvName), "SYSTEM.INI" );
     dprintf_driver( stddeb,"OpenDriver // DrvName='%s'\n", DrvName );
     if (lstrlen32A(DrvName) < 1) return 0;
diff --git a/misc/keyboard.c b/misc/keyboard.c
index 750a645..cf0cbbe 100644
--- a/misc/keyboard.c
+++ b/misc/keyboard.c
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <ctype.h>
 #include "windows.h"
+#include "keyboard.h"
 #include "stddebug.h"
 /* #define DEBUG_KEYBOARD */
 #include "debug.h"
@@ -22,105 +23,110 @@
 
 static const struct KeyTableEntry KeyTable[] =
 {
-	{ 0x3, 0x3, 0x0, "" },
-	{ 0x8, 0x8, 0xe, "Backspace" },
-	{ 0x9, 0x9, 0xf, "Tab" },
-	{ 0xc, 0x0, 0x4c, "Num 5" },
-	{ 0xd, 0xd, 0x1c, "Enter" },
-	{ 0x10, 0x0, 0x2a, "Shift" },
-	{ 0x11, 0x0, 0x1d, "Ctrl" },
-	{ 0x12, 0x0, 0x38, "Alt" },
-	{ 0x14, 0x0, 0x3a, "Caps Lock" },
-	{ 0x1b, 0x1b, 0x1, "Esc" },
-	{ 0x20, 0x20, 0x39, "Space" },
-	{ 0x21, 0x0, 0x49, "Num 9" },
-	{ 0x22, 0x0, 0x51, "Num 3" },
-	{ 0x23, 0x0, 0x4f, "Num 1" },
-	{ 0x24, 0x0, 0x47, "Num 7" },
-	{ 0x25, 0x0, 0x4b, "Num 4" },
-	{ 0x26, 0x0, 0x48, "Num 8" },
-	{ 0x27, 0x0, 0x4d, "Num 6" },
-	{ 0x28, 0x0, 0x50, "Num 2" },
-	{ 0x2d, 0x0, 0x52, "Num 0" },
-	{ 0x2e, 0x0, 0x53, "Num Del" },
-	{ 0x30, 0x30, 0xb, "0" },
-	{ 0x31, 0x31, 0x2, "1" },
-	{ 0x32, 0x32, 0x3, "2" },
-	{ 0x33, 0x33, 0x4, "3" },
-	{ 0x34, 0x34, 0x5, "4" },
-	{ 0x35, 0x35, 0x6, "5" },
-	{ 0x36, 0x36, 0x7, "6" },
-	{ 0x37, 0x37, 0x8, "7" },
-	{ 0x38, 0x38, 0x9, "8" },
-	{ 0x39, 0x39, 0xa, "9" },
-	{ 0x41, 0x41, 0x1e, "A" },
-	{ 0x42, 0x42, 0x30, "B" },
-	{ 0x43, 0x43, 0x2e, "C" },
-	{ 0x44, 0x44, 0x20, "D" },
-	{ 0x45, 0x45, 0x12, "E" },
-	{ 0x46, 0x46, 0x21, "F" },
-	{ 0x47, 0x47, 0x22, "G" },
-	{ 0x48, 0x48, 0x23, "H" },
-	{ 0x49, 0x49, 0x17, "I" },
-	{ 0x4a, 0x4a, 0x24, "J" },
-	{ 0x4b, 0x4b, 0x25, "K" },
-	{ 0x4c, 0x4c, 0x26, "L" },
-	{ 0x4d, 0x4d, 0x32, "M" },
-	{ 0x4e, 0x4e, 0x31, "N" },
-	{ 0x4f, 0x4f, 0x18, "O" },
-	{ 0x50, 0x50, 0x19, "P" },
-	{ 0x51, 0x51, 0x10, "Q" },
-	{ 0x52, 0x52, 0x13, "R" },
-	{ 0x53, 0x53, 0x1f, "S" },
-	{ 0x54, 0x54, 0x14, "T" },
-	{ 0x55, 0x55, 0x16, "U" },
-	{ 0x56, 0x56, 0x2f, "V" },
-	{ 0x57, 0x57, 0x11, "W" },
-	{ 0x58, 0x58, 0x2d, "X" },
-	{ 0x59, 0x59, 0x15, "Y" },
-	{ 0x5a, 0x5a, 0x2c, "Z" },
-	{ 0x60, 0x0, 0x52, "Num 0" },
-	{ 0x61, 0x0, 0x4f, "Num 1" },
-	{ 0x62, 0x0, 0x50, "Num 2" },
-	{ 0x63, 0x0, 0x51, "Num 3" },
-	{ 0x64, 0x0, 0x4b, "Num 4" },
-	{ 0x65, 0x0, 0x4c, "Num 5" },
-	{ 0x66, 0x0, 0x4d, "Num 6" },
-	{ 0x67, 0x0, 0x47, "Num 7" },
-	{ 0x68, 0x0, 0x48, "Num 8" },
-	{ 0x69, 0x0, 0x49, "Num 9" },
-	{ 0x6a, 0x2a, 0x37, "Num *" },
-	{ 0x6b, 0x2b, 0x4e, "Num +" },
-	{ 0x6c, 0x0, 0x0, "" },
-	{ 0x6d, 0x2d, 0x4a, "Num -" },
-	{ 0x6e, 0x2e, 0x53, "Num Del" },
-	{ 0x6f, 0x2f, 0x0, "" },
-	{ 0x70, 0x0, 0x3b, "F1" },
-	{ 0x71, 0x0, 0x3c, "F2" },
-	{ 0x72, 0x0, 0x3d, "F3" },
-	{ 0x73, 0x0, 0x3e, "F4" },
-	{ 0x74, 0x0, 0x3f, "F5" },
-	{ 0x75, 0x0, 0x40, "F6" },
-	{ 0x76, 0x0, 0x41, "F7" },
-	{ 0x77, 0x0, 0x42, "F8" },
-	{ 0x78, 0x0, 0x43, "F9" },
-	{ 0x79, 0x0, 0x44, "F10" },
-	{ 0x7a, 0x0, 0x57, "F11" },
-	{ 0x7b, 0x0, 0x58, "F12" },
-	{ 0x90, 0x0, 0x45, "Pause" },
-	{ 0x91, 0x0, 0x46, "Scroll Lock" },
-	{ 0xba, 0x3b, 0x27, ";" },
-	{ 0xbb, 0x3d, 0xd, "=" },
-	{ 0xbc, 0x2c, 0x33, "," },
-	{ 0xbd, 0x2d, 0xc, "-" },
-	{ 0xbe, 0x2e, 0x34, "." },
-	{ 0xbf, 0x2f, 0x35, "/" },
-	{ 0xc0, 0x60, 0x29, "`" },
-	{ 0xdb, 0x5b, 0x1a, "[" },
-	{ 0xdc, 0x5c, 0x2b, "\\" },
-	{ 0xdd, 0x5d, 0x1b, "]" },
-	{ 0xde, 0x27, 0x28, "\'" },
-	{ 0xe2, 0x5c, 0x56, "\\" },
+	{ VK_CANCEL,	0x3,	0,	"" },
+	{ VK_BACK,	0x8,	0xe,	"Backspace" },
+	{ VK_TAB,	0x9,	0xf,	"Tab" },
+	{ VK_CLEAR,	0,	0x4c,	"Clear" },
+	{ VK_RETURN,	0xd,	0x1c,	"Enter" },
+	{ VK_SHIFT,	0,	0x2a,	"Shift" },
+	{ VK_CONTROL,	0,	0x1d,	"Ctrl" },
+	{ VK_MENU,	0,	0x38,	"Alt" },
+	{ VK_CAPITAL,	0,	0x3a,	"Caps Lock" },
+	{ VK_ESCAPE,	0x1b,	0x1,	"Esc" },
+	{ VK_SPACE,	0x20,	0x39,	"Space" },
+	{ VK_PRIOR,	0,	0x49,	"Page Up" },
+	{ VK_NEXT,	0,	0x51,	"Page Down" },
+	{ VK_END,	0,	0x4f,	"End" },
+	{ VK_HOME,	0,	0x47,	"Home" },
+	{ VK_LEFT,	0,	0x4b,	"Left Arrow" },
+	{ VK_UP,	0,	0x48,	"Up Arrow" },
+	{ VK_RIGHT,	0,	0x4d,	"Right Arrow" },
+	{ VK_DOWN,	0,	0x50,	"Down Arrow" },
+	{ VK_INSERT,	0,	0x52,	"Ins" },
+	{ VK_DELETE,	0,	0x53,	"Del" },
+	{ VK_0,		0x30,	0xb,	"0" },
+	{ VK_1,		0x31,	0x2,	"1" },
+	{ VK_2,		0x32,	0x3,	"2" },
+	{ VK_3,		0x33,	0x4,	"3" },
+	{ VK_4,		0x34,	0x5,	"4" },
+	{ VK_5,		0x35,	0x6,	"5" },
+	{ VK_6,		0x36,	0x7,	"6" },
+	{ VK_7,		0x37,	0x8,	"7" },
+	{ VK_8,		0x38,	0x9,	"8" },
+	{ VK_9,		0x39,	0xa,	"9" },
+	{ VK_A,		0x41,	0x1e,	"A" },
+	{ VK_B,		0x42,	0x30,	"B" },
+	{ VK_C,		0x43,	0x2e,	"C" },
+	{ VK_D,		0x44,	0x20,	"D" },
+	{ VK_E,		0x45,	0x12,	"E" },
+	{ VK_F,		0x46,	0x21,	"F" },
+	{ VK_G,		0x47,	0x22,	"G" },
+	{ VK_H,		0x48,	0x23,	"H" },
+	{ VK_I,		0x49,	0x17,	"I" },
+	{ VK_J,		0x4a,	0x24,	"J" },
+	{ VK_K,		0x4b,	0x25,	"K" },
+	{ VK_L,		0x4c,	0x26,	"L" },
+	{ VK_M,		0x4d,	0x32,	"M" },
+	{ VK_N,		0x4e,	0x31,	"N" },
+	{ VK_O,		0x4f,	0x18,	"O" },
+	{ VK_P,		0x50,	0x19,	"P" },
+	{ VK_Q,		0x51,	0x10,	"Q" },
+	{ VK_R,		0x52,	0x13,	"R" },
+	{ VK_S,		0x53,	0x1f,	"S" },
+	{ VK_T,		0x54,	0x14,	"T" },
+	{ VK_U,		0x55,	0x16,	"U" },
+	{ VK_V,		0x56,	0x2f,	"V" },
+	{ VK_W,		0x57,	0x11,	"W" },
+	{ VK_X,		0x58,	0x2d,	"X" },
+	{ VK_Y,		0x59,	0x15,	"Y" },
+	{ VK_Z,		0x5a,	0x2c,	"Z" },
+	{ VK_NUMPAD0,	0,	0x52,	"Num 0" },
+	{ VK_NUMPAD1,	0,	0x4f,	"Num 1" },
+	{ VK_NUMPAD2,	0,	0x50,	"Num 2" },
+	{ VK_NUMPAD3,	0,	0x51,	"Num 3" },
+	{ VK_NUMPAD4,	0,	0x4b,	"Num 4" },
+	{ VK_NUMPAD5,	0,	0x4c,	"Num 5" },
+	{ VK_NUMPAD6,	0,	0x4d,	"Num 6" },
+	{ VK_NUMPAD7,	0,	0x47,	"Num 7" },
+	{ VK_NUMPAD8,	0,	0x48,	"Num 8" },
+	{ VK_NUMPAD9,	0,	0x49,	"Num 9" },
+	{ VK_MULTIPLY,	0x2a,	0x37,	"Num *" },
+	{ VK_ADD,	0x2b,	0x4e,	"Num +" },
+	{ VK_SEPARATOR,	0,	0,	"" },
+	{ VK_SUBTRACT,	0x2d,	0x4a,	"Num -" },
+	{ VK_DECIMAL,	0x2e,	0x53,	"Num Del" },
+	{ VK_DIVIDE,	0x2f,	0,	"Num /" },
+	{ VK_F1,	0,	0x3b,	"F1" },
+	{ VK_F2,	0,	0x3c,	"F2" },
+	{ VK_F3,	0,	0x3d,	"F3" },
+	{ VK_F4,	0,	0x3e,	"F4" },
+	{ VK_F5,	0,	0x3f,	"F5" },
+	{ VK_F6,	0,	0x40,	"F6" },
+	{ VK_F7,	0,	0x41,	"F7" },
+	{ VK_F8,	0,	0x42,	"F8" },
+	{ VK_F9,	0,	0x43,	"F9" },
+	{ VK_F10,	0,	0x44,	"F10" },
+	{ VK_F11,	0,	0x57,	"F11" },
+	{ VK_F12,	0,	0x58,	"F12" },
+	{ VK_NUMLOCK,	0,	0x45,	"Num Lock" },
+	{ VK_SCROLL,	0,	0x46,	"Scroll Lock" },
+	/* Allowable ranges for OEM-specific virtual-key codes */
+/*	-		    0xBA-0xC0		OEM specific */
+	{ 0xba,		0x3b,	0x27,	";" },
+	{ 0xbb,		0x3d,	0xd,	"=" },
+	{ 0xbc,		0x2c,	0x33,	"," },
+	{ 0xbd,		0x2d,	0xc,	"-" },
+	{ 0xbe,		0x2e,	0x34,	"." },
+	{ 0xbf,		0x2f,	0x35,	"/" },
+	{ 0xc0,		0x60,	0x29,	"`" },
+/*	-		    0xDB-0xE4		OEM specific */
+	{ 0xdb,		0x5b,	0x1a,	"[" },
+	{ 0xdc,		0x5c,	0x2b,	"\\" },
+	{ 0xdd,		0x5d,	0x1b,	"]" },
+	{ 0xde,		0x27,	0x28,	"'" },
+	{ 0xe2,		0x5c,	0x56,	"\\" },
+/*	-		    0xE6		OEM specific */
+/*	-		    0xE9-0xF5		OEM specific */
 };
 
 #define KeyTableSize	sizeof(KeyTable) / sizeof(struct KeyTableEntry)
@@ -128,34 +134,55 @@
 int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
 	LPVOID lpChar, WORD wFlags) 
 {
+	char shift = lpKeyState[VK_SHIFT] < 0;
 	int i;
 
-    	dprintf_keyboard(stddeb,"ToAscii (%d,%d)\n",wVirtKey, wScanCode);
+    	dprintf_keyboard(stddeb, "ToAscii (%x,%x) -> ", wVirtKey, wScanCode);
 
 	/* FIXME: codepage is broken */
 
-	for (i = 0 ; i != KeyTableSize ; i++) 
-		if (KeyTable[i].virtualkey == wVirtKey)  
-		 {
-		   dprintf_keyboard(stddeb,"\t\tchar = %s\n", KeyTable[i].name);
-		   if( isprint(KeyTable[i].ASCII) || isspace(KeyTable[i].ASCII) )
-		     {
-			*(BYTE*)lpChar = KeyTable[i].ASCII;
-			*(((BYTE*)lpChar) + 1) = 0;
-
-			if( isalpha( *(BYTE*)lpChar ) )
-			  if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
-			      (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
-			      *(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
-			  else
-			      *(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
-
-			return 1;
-		     }
-		 }
-
 	*(BYTE*)lpChar = 0;
-	return 0;
+	switch (wVirtKey)
+	  {
+#define vkcase2(k1,k2,val) case val : *(BYTE*)lpChar = shift ? k2 : k1; break;
+#define vkcase(k, val) vkcase2(val, k, val)
+	  WINE_VKEY_MAPPINGS
+#undef vkcase
+#undef vkcase2
+	  default :
+	    for (i = 0 ; ; i++) 
+	      {
+	      if (i == KeyTableSize)
+		{
+		  dprintf_keyboard(stddeb, "0\n");
+		  return 0;
+		}
+	      if (KeyTable[i].virtualkey == wVirtKey)  
+	        {
+		  if (!isprint(KeyTable[i].ASCII) && !isspace(KeyTable[i].ASCII))
+		    {
+		      dprintf_keyboard(stddeb, "0\n");
+		      return 0;
+		    }
+		  dprintf_keyboard(stddeb,"\"%s\" ", KeyTable[i].name);
+
+		  *(BYTE*)lpChar = KeyTable[i].ASCII;
+		  *(((BYTE*)lpChar) + 1) = 0;
+
+		  if (isalpha(*(BYTE*)lpChar))
+		    if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
+			(!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
+			*(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
+		    else
+			*(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
+		  break;
+	        }
+	     }
+	  }
+	if (lpKeyState[VK_CONTROL] < 0)
+	  *(BYTE*)lpChar = *(BYTE*)lpChar & 0x1f;
+	dprintf_keyboard(stddeb, "1 (%x)\n", *(BYTE*)lpChar);
+	return 1;
 }
 
 DWORD OemKeyScan(WORD wOemChar)
@@ -166,7 +193,16 @@
 }
 
 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
- * for the current keyboard. */
+ * for the current keyboard.
+ * FIXME high-order byte should yield :
+ *	0	Unshifted
+ *	1	Shift
+ *	2	Ctrl
+ *	3-5	Shift-key combinations that are not used for characters
+ *	6	Ctrl-Alt
+ *	7	Ctrl-Alt-Shift
+ *	I.e. :	Shift = 1, Ctrl = 2, Alt = 4.
+ */
 
 WORD VkKeyScan(WORD cChar)
 {
@@ -208,26 +244,28 @@
 	int i;
 	
 	switch(wMapType) {
-		case 0:
+		case 0:	/* vkey-code to scan-code */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].virtualkey == wCode) 
 					return KeyTable[i].scancode;
 			return 0;
 
-		case 1:
+		case 1: /* scan-code to vkey-code */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].scancode == wCode) 
 					return KeyTable[i].virtualkey;
 			return 0;
 
-		case 2:
+		case 2: /* vkey-code to unshifted ANSI code */
+			/* FIXME : what does unshifted mean ? 'a' or 'A' ? */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].virtualkey == wCode) 
 					return KeyTable[i].ASCII;
 			return 0;
 
-		default: 
-			fprintf(stderr, "MapVirtualKey: unknown wMapType!\n");
+		default: /* reserved */
+			fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
+				wMapType);
 			return 0;	
 	}
 	return 0;
diff --git a/misc/main.c b/misc/main.c
index b9113a7..f8597ec 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -804,7 +804,8 @@
     fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
     break;
   }
-
+  if( getVersionEx.dwPlatformId == VER_PLATFORM_WIN32_NT )
+      result |= 0x4000; /* undocumented WF_WINNT */
   return result;
 }
 
@@ -1076,18 +1077,21 @@
 			break;
 
 		case SPI_GETFASTTASKSWITCH:
-			*(BOOL *) lpvParam = FALSE;
-			/* FIXME GetProfileInt( "windows", "CoolSwitch", 1 ) */
+		    if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 )
+			  *(BOOL *) lpvParam = TRUE;
+			else
+			  *(BOOL *) lpvParam = FALSE;
 			break;
 
 		case SPI_GETGRIDGRANULARITY:
-			*(INT *) lpvParam = 1;
-		/* FIXME GetProfileInt( "desktop", "GridGranularity", 1 ) */
-			break;
+                    *(INT *) lpvParam = GetProfileInt32A( "desktop", 
+                                                          "GridGranularity",
+                                                          1 );
+                    break;
 
 		case SPI_GETICONTITLEWRAP:
 			*(BOOL *) lpvParam = FALSE;
-			/* FIXME GetProfileInt( "desktop", "?", True ) */
+			/* FIXME GetProfileInt32A( "desktop", "?", True ) */
 			break;
 
 		case SPI_GETKEYBOARDDELAY:
@@ -1105,9 +1109,11 @@
 			break;
 
 		case SPI_GETSCREENSAVEACTIVE:
-			/* FIXME GetProfileInt( "windows", "ScreenSaveActive", 1 ); */
-			*(BOOL *) lpvParam = FALSE;
-			break;
+                    if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 )
+                        *(BOOL *) lpvParam = TRUE;
+                    else
+                        *(BOOL *) lpvParam = FALSE;
+                    break;
 
 		case SPI_GETSCREENSAVETIMEOUT:
 			/* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
@@ -1116,18 +1122,20 @@
 			break;
 
 		case SPI_ICONHORIZONTALSPACING:
+                    /* FIXME Get/SetProfileInt */
 			if (lpvParam == NULL)
-				fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
-			else
-				*(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
+                            /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ;
+                        else
+                            *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
 			break;
 
 		case SPI_ICONVERTICALSPACING:
-			if (lpvParam == NULL)
-				fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
-			else
-				*(INT *) lpvParam = GetSystemMetrics( SM_CYICONSPACING );
-			break;
+                    /* FIXME Get/SetProfileInt */
+                    if (lpvParam == NULL)
+                        /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ;
+		    else
+                        *(INT *) lpvParam = GetSystemMetrics(SM_CYICONSPACING);
+                    break;
 
 		case SPI_SETBEEP:
 			if (uParam == TRUE)
@@ -1147,7 +1155,7 @@
 
 		case SPI_SETSCREENSAVETIMEOUT:
 			XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
-						DefaultExposures);
+							DefaultExposures);
 			break;
 
 		case SPI_SETDESKWALLPAPER:
@@ -1156,7 +1164,7 @@
 
 		case SPI_SETDESKPATTERN:
 			if ((INT) uParam == -1) {
-				GetProfileString("Desktop", "Pattern", 
+				GetProfileString32A("Desktop", "Pattern", 
 						"170 85 170 85 170 85 170 85", 
 						buffer, sizeof(buffer) );
 				return (DESKTOP_SetPattern((LPSTR) buffer));
@@ -1166,19 +1174,20 @@
 
 	        case SPI_GETICONTITLELOGFONT: 
 	        {
-		    /* FIXME GetProfileString( "?", "?", "?" ) */
-		  LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
-		  lpLogFont->lfHeight = 10;
-		  lpLogFont->lfWidth = 0;
-		  lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
-		  lpLogFont->lfWeight = FW_NORMAL;
-		  lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
-		  lpLogFont->lfCharSet = ANSI_CHARSET;
-		  lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
-		  lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
-		  lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
-		  break;
-		}
+			  /* FIXME GetProfileString32A( "?", "?", "?" ) */
+			  LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
+			  lpLogFont->lfHeight = 10;
+			  lpLogFont->lfWidth = 0;
+			  lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
+			  lpLogFont->lfWeight = FW_NORMAL;
+			  lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
+			  lpLogFont->lfCharSet = ANSI_CHARSET;
+			  lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+			  lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+			  lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
+			  break;
+			}
+
 		case SPI_LANGDRIVER:
 		case SPI_SETBORDER:
 		case SPI_SETDOUBLECLKHEIGHT:
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index 66a7a74..8669f50 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -4,16 +4,126 @@
  *	Copyright 1995	Martin von Loewis
  */
 
-/*	At the moment, these are only empty stubs.
- */
-
 #include <string.h>
+#include <malloc.h>
 #include "windows.h"
 #include "ole.h"
 #include "options.h"
 #include "winnls.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "string32.h"
+
+/* Locale name to id map. used by EnumSystemLocales, GetLocalInfoA 
+ * MUST contain all #defines from winnls.h
+ * last entry has NULL name, 0 id.
+ */ 
+#define LOCALE_ENTRY(x)	{#x,LOCALE_##x}
+static struct tagLOCALE_NAME2ID {
+	char	*name;
+	DWORD	id;
+} locale_name2id[]= {
+	LOCALE_ENTRY(ILANGUAGE),
+	LOCALE_ENTRY(SLANGUAGE),
+	LOCALE_ENTRY(SENGLANGUAGE),
+	LOCALE_ENTRY(SABBREVLANGNAME),
+	LOCALE_ENTRY(SNATIVELANGNAME),
+	LOCALE_ENTRY(ICOUNTRY),
+	LOCALE_ENTRY(SCOUNTRY),
+	LOCALE_ENTRY(SENGCOUNTRY),
+	LOCALE_ENTRY(SABBREVCTRYNAME),
+	LOCALE_ENTRY(SNATIVECTRYNAME),
+	LOCALE_ENTRY(IDEFAULTLANGUAGE),
+	LOCALE_ENTRY(IDEFAULTCOUNTRY),
+	LOCALE_ENTRY(IDEFAULTCODEPAGE),
+	LOCALE_ENTRY(IDEFAULTANSICODEPAGE),
+	LOCALE_ENTRY(SLIST),
+	LOCALE_ENTRY(IMEASURE),
+	LOCALE_ENTRY(SDECIMAL),
+	LOCALE_ENTRY(STHOUSAND),
+	LOCALE_ENTRY(SGROUPING),
+	LOCALE_ENTRY(IDIGITS),
+	LOCALE_ENTRY(ILZERO),
+	LOCALE_ENTRY(INEGNUMBER),
+	LOCALE_ENTRY(SNATIVEDIGITS),
+	LOCALE_ENTRY(SCURRENCY),
+	LOCALE_ENTRY(SINTLSYMBOL),
+	LOCALE_ENTRY(SMONDECIMALSEP),
+	LOCALE_ENTRY(SMONTHOUSANDSEP),
+	LOCALE_ENTRY(SMONGROUPING),
+	LOCALE_ENTRY(ICURRDIGITS),
+	LOCALE_ENTRY(IINTLCURRDIGITS),
+	LOCALE_ENTRY(ICURRENCY),
+	LOCALE_ENTRY(INEGCURR),
+	LOCALE_ENTRY(SDATE),
+	LOCALE_ENTRY(STIME),
+	LOCALE_ENTRY(SSHORTDATE),
+	LOCALE_ENTRY(SLONGDATE),
+	LOCALE_ENTRY(STIMEFORMAT),
+	LOCALE_ENTRY(IDATE),
+	LOCALE_ENTRY(ILDATE),
+	LOCALE_ENTRY(ITIME),
+	LOCALE_ENTRY(ITIMEMARKPOSN),
+	LOCALE_ENTRY(ICENTURY),
+	LOCALE_ENTRY(ITLZERO),
+	LOCALE_ENTRY(IDAYLZERO),
+	LOCALE_ENTRY(IMONLZERO),
+	LOCALE_ENTRY(S1159),
+	LOCALE_ENTRY(S2359),
+	LOCALE_ENTRY(ICALENDARTYPE),
+	LOCALE_ENTRY(IOPTIONALCALENDAR),
+	LOCALE_ENTRY(IFIRSTDAYOFWEEK),
+	LOCALE_ENTRY(IFIRSTWEEKOFYEAR),
+	LOCALE_ENTRY(SDAYNAME1),
+	LOCALE_ENTRY(SDAYNAME2),
+	LOCALE_ENTRY(SDAYNAME3),
+	LOCALE_ENTRY(SDAYNAME4),
+	LOCALE_ENTRY(SDAYNAME5),
+	LOCALE_ENTRY(SDAYNAME6),
+	LOCALE_ENTRY(SDAYNAME7),
+	LOCALE_ENTRY(SABBREVDAYNAME1),
+	LOCALE_ENTRY(SABBREVDAYNAME2),
+	LOCALE_ENTRY(SABBREVDAYNAME3),
+	LOCALE_ENTRY(SABBREVDAYNAME4),
+	LOCALE_ENTRY(SABBREVDAYNAME5),
+	LOCALE_ENTRY(SABBREVDAYNAME6),
+	LOCALE_ENTRY(SABBREVDAYNAME7),
+	LOCALE_ENTRY(SMONTHNAME1),
+	LOCALE_ENTRY(SMONTHNAME2),
+	LOCALE_ENTRY(SMONTHNAME3),
+	LOCALE_ENTRY(SMONTHNAME4),
+	LOCALE_ENTRY(SMONTHNAME5),
+	LOCALE_ENTRY(SMONTHNAME6),
+	LOCALE_ENTRY(SMONTHNAME7),
+	LOCALE_ENTRY(SMONTHNAME8),
+	LOCALE_ENTRY(SMONTHNAME9),
+	LOCALE_ENTRY(SMONTHNAME10),
+	LOCALE_ENTRY(SMONTHNAME11),
+	LOCALE_ENTRY(SMONTHNAME12),
+	LOCALE_ENTRY(SMONTHNAME13),
+	LOCALE_ENTRY(SABBREVMONTHNAME1),
+	LOCALE_ENTRY(SABBREVMONTHNAME2),
+	LOCALE_ENTRY(SABBREVMONTHNAME3),
+	LOCALE_ENTRY(SABBREVMONTHNAME4),
+	LOCALE_ENTRY(SABBREVMONTHNAME5),
+	LOCALE_ENTRY(SABBREVMONTHNAME6),
+	LOCALE_ENTRY(SABBREVMONTHNAME7),
+	LOCALE_ENTRY(SABBREVMONTHNAME8),
+	LOCALE_ENTRY(SABBREVMONTHNAME9),
+	LOCALE_ENTRY(SABBREVMONTHNAME10),
+	LOCALE_ENTRY(SABBREVMONTHNAME11),
+	LOCALE_ENTRY(SABBREVMONTHNAME12),
+	LOCALE_ENTRY(SABBREVMONTHNAME13),
+	LOCALE_ENTRY(SPOSITIVESIGN),
+	LOCALE_ENTRY(SNEGATIVESIGN),
+	LOCALE_ENTRY(IPOSSIGNPOSN),
+	LOCALE_ENTRY(INEGSIGNPOSN),
+	LOCALE_ENTRY(IPOSSYMPRECEDES),
+	LOCALE_ENTRY(IPOSSEPBYSPACE),
+	LOCALE_ENTRY(INEGSYMPRECEDES),
+	LOCALE_ENTRY(INEGSEPBYSPACE),
+	{NULL,0},
+};
 
 /***********************************************************************
  *           GetUserDefaultLCID       (OLE2NLS.1)
@@ -86,137 +196,39 @@
  */
 int GetLocaleInfoA(DWORD lcid,DWORD LCType,LPSTR buf,WORD len)
 {
-	char *retString;
-    int retLen;
-    dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
+	char	*retString;
+	int	found,i;
+
+	dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
 			lcid,LCType,buf,len);
-#if 0
-	/* Wine is supporting only the default locale */
-	if(lcid!=GetUserDefaultLCID())
-	{
-		dprintf_ole(stdnimp,"GetLocaleInfoA: Unknown locale\n");
-		return 0;
-	}
-#endif
 	/* As an option, we could obtain the value from win.ini.
 	   This would not match the Wine compile-time option.
 	   Also, not all identifiers are available from win.ini */
 	retString=0;
-	retLen=0;
 	/* If we are through all of this, retLen should not be zero anymore.
 	   If it is, the value is not supported */
-#define LOCVAL(type,value)	if(type==LCType)			\
-								{retLen=strlen(value)+1;\
-								 retString=value;       \
-								}
-#define UNSUPPORTED(type)   if(type==lcid)retString=#type;
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		if (LCType == locale_name2id[i].id) {
+			retString = locale_name2id[i].name;
+			break;
+		}
+		i++;
+	}
+	if (!retString) {
+		fprintf(stderr,"Unkown LC type %lX\n",LCType);
+		return 0;
+	}
 
-/* I really wish I would know a better way to do this */
-UNSUPPORTED(LOCALE_ILANGUAGE)
-UNSUPPORTED(LOCALE_SLANGUAGE)
-UNSUPPORTED(LOCALE_SENGLANGUAGE)
-UNSUPPORTED(LOCALE_SABBREVLANGNAME)
-UNSUPPORTED(LOCALE_SNATIVELANGNAME)
-UNSUPPORTED(LOCALE_ICOUNTRY)
-UNSUPPORTED(LOCALE_SCOUNTRY)
-UNSUPPORTED(LOCALE_SENGCOUNTRY)
-UNSUPPORTED(LOCALE_SABBREVCTRYNAME)
-UNSUPPORTED(LOCALE_SNATIVECTRYNAME)
-UNSUPPORTED(LOCALE_IDEFAULTLANGUAGE)
-UNSUPPORTED(LOCALE_IDEFAULTCOUNTRY)
-UNSUPPORTED(LOCALE_IDEFAULTCODEPAGE)
-UNSUPPORTED(LOCALE_IDEFAULTANSICODEPAGE)
-UNSUPPORTED(LOCALE_SLIST)
-UNSUPPORTED(LOCALE_IMEASURE)
-UNSUPPORTED(LOCALE_SDECIMAL)
-UNSUPPORTED(LOCALE_STHOUSAND)
-UNSUPPORTED(LOCALE_SGROUPING)
-UNSUPPORTED(LOCALE_IDIGITS)
-UNSUPPORTED(LOCALE_ILZERO)
-UNSUPPORTED(LOCALE_INEGNUMBER)
-UNSUPPORTED(LOCALE_SNATIVEDIGITS)
-UNSUPPORTED(LOCALE_SCURRENCY)
-UNSUPPORTED(LOCALE_SINTLSYMBOL)
-UNSUPPORTED(LOCALE_SMONDECIMALSEP)
-UNSUPPORTED(LOCALE_SMONTHOUSANDSEP)
-UNSUPPORTED(LOCALE_SMONGROUPING)
-UNSUPPORTED(LOCALE_ICURRDIGITS)
-UNSUPPORTED(LOCALE_IINTLCURRDIGITS)
-UNSUPPORTED(LOCALE_ICURRENCY)
-UNSUPPORTED(LOCALE_INEGCURR)
-UNSUPPORTED(LOCALE_SDATE)
-UNSUPPORTED(LOCALE_STIME)
-UNSUPPORTED(LOCALE_SSHORTDATE)
-UNSUPPORTED(LOCALE_SLONGDATE)
-UNSUPPORTED(LOCALE_STIMEFORMAT)
-UNSUPPORTED(LOCALE_IDATE)
-UNSUPPORTED(LOCALE_ILDATE)
-UNSUPPORTED(LOCALE_ITIME)
-UNSUPPORTED(LOCALE_ITIMEMARKPOSN)
-UNSUPPORTED(LOCALE_ICENTURY)
-UNSUPPORTED(LOCALE_ITLZERO)
-UNSUPPORTED(LOCALE_IDAYLZERO)
-UNSUPPORTED(LOCALE_IMONLZERO)
-UNSUPPORTED(LOCALE_S1159)
-UNSUPPORTED(LOCALE_S2359)
-UNSUPPORTED(LOCALE_ICALENDARTYPE)
-UNSUPPORTED(LOCALE_IOPTIONALCALENDAR)
-UNSUPPORTED(LOCALE_IFIRSTDAYOFWEEK)
-UNSUPPORTED(LOCALE_IFIRSTWEEKOFYEAR)
-UNSUPPORTED(LOCALE_SDAYNAME1)
-UNSUPPORTED(LOCALE_SDAYNAME2)
-UNSUPPORTED(LOCALE_SDAYNAME3)
-UNSUPPORTED(LOCALE_SDAYNAME4)
-UNSUPPORTED(LOCALE_SDAYNAME5)
-UNSUPPORTED(LOCALE_SDAYNAME6)
-UNSUPPORTED(LOCALE_SDAYNAME7)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME1)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME2)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME3)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME4)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME5)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME6)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME1)
-UNSUPPORTED(LOCALE_SMONTHNAME2)
-UNSUPPORTED(LOCALE_SMONTHNAME3)
-UNSUPPORTED(LOCALE_SMONTHNAME4)
-UNSUPPORTED(LOCALE_SMONTHNAME5)
-UNSUPPORTED(LOCALE_SMONTHNAME6)
-UNSUPPORTED(LOCALE_SMONTHNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME8)
-UNSUPPORTED(LOCALE_SMONTHNAME9)
-UNSUPPORTED(LOCALE_SMONTHNAME10)
-UNSUPPORTED(LOCALE_SMONTHNAME11)
-UNSUPPORTED(LOCALE_SMONTHNAME12)
-UNSUPPORTED(LOCALE_SMONTHNAME13)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME1)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME2)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME3)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME4)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME5)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME6)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME7)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME8)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME9)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME10)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME11)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME12)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME13)
-UNSUPPORTED(LOCALE_SPOSITIVESIGN)
-UNSUPPORTED(LOCALE_SNEGATIVESIGN)
-UNSUPPORTED(LOCALE_IPOSSIGNPOSN)
-UNSUPPORTED(LOCALE_INEGSIGNPOSN)
-UNSUPPORTED(LOCALE_IPOSSYMPRECEDES)
-UNSUPPORTED(LOCALE_IPOSSEPBYSPACE)
-UNSUPPORTED(LOCALE_INEGSYMPRECEDES)
-UNSUPPORTED(LOCALE_INEGSEPBYSPACE)
+#define LOCVAL(type,value) case type:retString=value;break;
 
 /* Now, the language specific definitions. They don't have to be
    complete */
+    found=1;
     switch(Options.language)
     {
     case LANG_De:
+    	switch (LCType) {
 /* This definitions apply to Germany only. Users in Austria 
    or Switzerland might want to modify them */
 LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -339,9 +351,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(De) */
 
     case LANG_Da:
+    	switch (LCType) {
 /* LOCVAL(LOCALE_ILANGUAGE,"9") */
 LOCVAL(LOCALE_SLANGUAGE,"Dansk")
 LOCVAL(LOCALE_SENGLANGUAGE,"Danish")
@@ -441,9 +456,12 @@
 /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
 /* LOCVAL(LOCALE_INEGSYMPRECEDES) */
 /* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+	default: found=0;break;
+	}
     break; /* LANG(Da) */
 
     case LANG_En:
+    	switch (LCType) {
 /* This definitions apply to Germany only. Users in Austria 
    or Switzerland might want to modify them */
 LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -566,9 +584,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(En) */
 
     case LANG_Eo:
+    	switch (LCType) {
 /* LOCVAL(LOCALE_ILANGUAGE,"9") ISO numerical ID for language TODO */
 LOCVAL(LOCALE_SLANGUAGE,"Esperanto")
 LOCVAL(LOCALE_SENGLANGUAGE,"Esperanto")
@@ -668,9 +689,12 @@
 /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
 /* LOCVAL(LOCALE_INEGSYMPRECEDES) */
 /* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+	default: found=0;break;
+	}
     break;  /* LANG(Eo) */
 
     case LANG_Fi:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE,"11")
 LOCVAL(LOCALE_SLANGUAGE,"Suomi")
 LOCVAL(LOCALE_SENGLANGUAGE,"Finnish")
@@ -791,9 +815,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(Fi) */
 
     case LANG_It:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE,"9")
 LOCVAL(LOCALE_SLANGUAGE,"Italiano")
 LOCVAL(LOCALE_SENGLANGUAGE,"Italian")
@@ -914,9 +941,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(It) */
 
     case 0x0409:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE, "0409")
 LOCVAL(LOCALE_SLANGUAGE, "English (United States)")
 LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1016,9 +1046,12 @@
 LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
 LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
 LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+	default: found=0;break;
+	}
     break; /* LANG(0x0409) (U.S. English) */
 
     case 0x0809:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE, "0809")
 LOCVAL(LOCALE_SLANGUAGE, "English (United Kingdom)")
 LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1118,25 +1151,24 @@
 LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
 LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
 LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+	default: found=0;break;
+	}
     break; /* LANG(0x0809) (U.K. English) */
 
 /*Insert other languages here*/
 
     default:
+    	found=0;
 	break;
     }  /* switch */
 
-	if(!retLen)
-	{
-		if(!retString)fprintf(stderr,"Unkown LC type %lX\n",LCType);
-		else fprintf(stderr,"'%s' not supported for your language.\n",
+	if(!found) {
+		fprintf(stderr,"'%s' not supported for your language.\n",
 			retString);
 		return 0;
 	}
-
-	if(retLen>len)retLen=len;
 	lstrcpyn32A(buf,retString,len);
-	return retLen;
+	return strlen(retString)+1;
 }
 
 /***********************************************************************
@@ -1230,7 +1262,57 @@
 	return TRUE;
 }
 
-BOOL IsValidLocale(DWORD lcid,DWORD flags) {
-	fprintf(stdnimp,"IsValidLocale(%ld,%ld)\n",lcid,flags);
+/***********************************************************************
+ *           IsValidLocale       (KERNEL32.361)
+ */
+BOOL32 IsValidLocale(DWORD lcid,DWORD flags) {
+	int	i;
+
+	i=0;
+	while (locale_name2id[i].name!=NULL)
+		if (locale_name2id[i].id == lcid)
+			return TRUE;
+	return FALSE;
+}
+
+/***********************************************************************
+ *              EnumSystemLocales32W                (KERNEL32.93)
+ */
+BOOL32
+EnumSystemLocales32W(LOCALE_ENUMPROC32W lpfnLocaleEnum,DWORD flags) {
+	WCHAR	*cp;
+	int	i;
+	BOOL32	ret;
+
+	dprintf_win32(stddeb,"EnumSystemLocales32W(%p,%08lx)\n",
+		lpfnLocaleEnum,flags
+	);
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		cp=(LPWSTR)STRING32_DupAnsiToUni(locale_name2id[i].name);
+		ret=lpfnLocaleEnum(cp);
+		free(cp);
+		if (!ret) break;
+		i++;
+	}
+	return TRUE;
+}
+
+/***********************************************************************
+ *              EnumSystemLocales32A                (KERNEL32.92)
+ */
+BOOL32
+EnumSystemLocales32A(LOCALE_ENUMPROC32A lpfnLocaleEnum,DWORD flags) {
+	int	i;
+
+	dprintf_win32(stddeb,"EnumSystemLocales32A(%p,%08lx)\n",
+		lpfnLocaleEnum,flags
+	);
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		if (!lpfnLocaleEnum(locale_name2id[i].name))
+			break;
+		i++;
+	}
 	return TRUE;
 }
diff --git a/misc/registry.c b/misc/registry.c
index cdd6751..90c001a 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -450,7 +450,7 @@
 	return _savesubkey(F,lpkey->nextsub,0,all);
 }
 
-static void
+static BOOL32
 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
 	FILE	*F;
 
@@ -459,15 +459,16 @@
 		fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
 			fn,strerror(errno)
 		);
-		return;
+		return FALSE;
 	}
 	if (!_savesubreg(F,lpkey,all)) {
 		fclose(F);
 		unlink(fn);
 		fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
-		return;
+		return FALSE;
 	}
 	fclose(F);
+        return TRUE;
 }
 
 void
@@ -500,19 +501,22 @@
 	if (lstrcmpi32A(buf,"yes"))
 		all=1;
 	pwd=getpwuid(getuid());
-	if (pwd!=NULL && pwd->pw_dir!=NULL) {
-		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
+	if (pwd!=NULL && pwd->pw_dir!=NULL)
+        {
+                char *tmp = tmpnam(NULL);
+		fn=(char*)xmalloc( strlen(pwd->pw_dir) + strlen(WINE_PREFIX) +
+                                   strlen(SAVE_CURRENT_USER) + 2 );
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX);
 		/* create the directory. don't care about errorcodes. */
 		mkdir(fn,0755); /* drwxr-xr-x */
 		strcat(fn,"/"SAVE_CURRENT_USER);
-		_savereg(key_current_user,fn,all);
+		if (_savereg(key_current_user,tmp,all)) rename(tmp,fn);
 		free(fn);
 		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
-		_savereg(key_local_machine,fn,all);
+		if (_savereg(key_local_machine,tmp,all)) rename(tmp,fn);
 		free(fn);
 	} else
 		fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
@@ -1315,6 +1319,216 @@
 	free(keys);
 }
 
+/* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
+
+/*
+    reghack - windows 3.11 registry data format demo program.
+
+    The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
+    a combined hash table and tree description, and finally a text table.
+
+    The header is obvious from the struct header. The taboff1 and taboff2
+    fields are always 0x20, and their usage is unknown.
+
+    The 8-byte entry table has various entry types.
+
+    tabent[0] is a root index. The second word has the index of the root of
+            the directory.
+    tabent[1..hashsize] is a hash table. The first word in the hash entry is
+            the index of the key/value that has that hash. Data with the same
+            hash value are on a circular list. The other three words in the
+            hash entry are always zero.
+    tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
+            entry: dirent and keyent/valent. They are identified by context.
+    tabent[freeidx] is the first free entry. The first word in a free entry
+            is the index of the next free entry. The last has 0 as a link.
+            The other three words in the free list are probably irrelevant.
+
+    Entries in text table are preceeded by a word at offset-2. This word
+    has the value (2*index)+1, where index is the referring keyent/valent
+    entry in the table. I have no suggestion for the 2* and the +1.
+    Following the word, there are N bytes of data, as per the keyent/valent
+    entry length. The offset of the keyent/valent entry is from the start
+    of the text table to the first data byte.
+
+    This information is not available from Microsoft. The data format is
+    deduced from the reg.dat file by me. Mistakes may
+    have been made. I claim no rights and give no guarantees for this program.
+
+    Tor Sjøwall, tor@sn.no
+*/
+
+/* reg.dat header format */
+struct _w31_header {
+	char		cookie[8];	/* 'SHCC3.10' */
+	unsigned long	taboff1;	/* offset of hash table (??) = 0x20 */
+	unsigned long	taboff2;	/* offset of index table (??) = 0x20 */
+	unsigned long	tabcnt;		/* number of entries in index table */
+	unsigned long	textoff;	/* offset of text part */
+	unsigned long	textsize;	/* byte size of text part */
+	unsigned short	hashsize;	/* hash size */
+	unsigned short	freeidx;	/* free index */
+};
+
+/* generic format of table entries */
+struct _w31_tabent {
+	unsigned short w0, w1, w2, w3;
+};
+
+/* directory tabent: */
+struct _w31_dirent {
+	unsigned short	sibling_idx;	/* table index of sibling dirent */
+	unsigned short	child_idx;	/* table index of child dirent */
+	unsigned short	key_idx;	/* table index of key keyent */
+	unsigned short	value_idx;	/* table index of value valent */
+};
+
+/* key tabent: */
+struct _w31_keyent {
+	unsigned short	hash_idx;	/* hash chain index for string */
+	unsigned short	refcnt;		/* reference count */
+	unsigned short	length;		/* length of string */
+	unsigned short	string_off;	/* offset of string in text table */
+};
+
+/* value tabent: */
+struct _w31_valent {
+	unsigned short	hash_idx;	/* hash chain index for string */
+	unsigned short	refcnt;		/* reference count */
+	unsigned short	length;		/* length of string */
+	unsigned short	string_off;	/* offset of string in text table */
+};
+
+/* recursive helper function to display a directory tree */
+void
+__w31_dumptree(	unsigned short idx,
+		unsigned char *txt,
+		struct _w31_tabent *tab,
+		struct _w31_header *head,
+		LPKEYSTRUCT	lpkey,
+		time_t		lastmodified,
+		int		level
+) {
+	struct _w31_dirent	*dir;
+	struct _w31_keyent	*key;
+	struct _w31_valent	*val;
+	LPKEYSTRUCT		xlpkey;
+	LPWSTR			name,value;
+	static char		tail[400];
+
+	while (idx!=0) {
+		dir=(struct _w31_dirent*)&tab[idx];
+
+		if (dir->key_idx) {
+			key = (struct _w31_keyent*)&tab[dir->key_idx];
+
+			memcpy(tail,&txt[key->string_off],key->length);
+			tail[key->length]='\0';
+			/* all toplevel entries AND the entries in the 
+			 * toplevel subdirectory belong to \SOFTWARE\Classes
+			 */
+			if (!level && !lstrcmp32A(tail,".classes")) {
+				__w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
+				idx=dir->sibling_idx;
+				continue;
+			}
+			name=STRING32_DupAnsiToUni(tail);
+
+			xlpkey=_find_or_add_key(lpkey,name);
+
+			/* only add if leaf node or valued node */
+			if (dir->value_idx!=0||dir->child_idx==0) {
+				if (dir->value_idx) {
+					val=(struct _w31_valent*)&tab[dir->value_idx];
+					memcpy(tail,&txt[val->string_off],val->length);
+					tail[val->length]='\0';
+					value=STRING32_DupAnsiToUni(tail);
+					_find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlen32W(value)*2+2,lastmodified);
+				}
+			}
+		} else {
+			dprintf_reg(stddeb,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx);
+		}
+		__w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
+		idx=dir->sibling_idx;
+	}
+}
+
+void
+_w31_loadreg() {
+	HFILE			hf;
+	struct _w31_header	head;
+	struct _w31_tabent	*tab;
+	unsigned char		*txt;
+	int			len;
+	OFSTRUCT		ofs;
+	BY_HANDLE_FILE_INFORMATION hfinfo;
+	time_t			lastmodified;
+	HKEY			hkey;
+	LPKEYSTRUCT		lpkey;
+
+	hf = OpenFile("reg.dat",&ofs,OF_READ);
+	if (hf==HFILE_ERROR)
+		return;
+
+	/* read & dump header */
+	if (sizeof(head)!=_lread32(hf,&head,sizeof(head))) {
+		dprintf_reg(stddeb,"_w31_loadreg:reg.dat is too short.\n");
+		_lclose(hf);
+		return;
+	}
+	if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
+		dprintf_reg(stddeb,"_w31_loadreg:reg.dat has bad signature.\n");
+		_lclose(hf);
+		return;
+	}
+
+	len = head.tabcnt * sizeof(struct _w31_tabent);
+	/* read and dump index table */
+	tab = xmalloc(len);
+	if (len!=_lread32(hf,tab,len)) {
+		dprintf_reg(stderr,"_w31_loadreg:couldn't read %d bytes.\n",len); 
+		free(tab);
+		_lclose(hf);
+		return;
+	}
+
+	/* read text */
+	txt = xmalloc(head.textsize);
+	if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
+		dprintf_reg(stderr,"_w31_loadreg:couldn't seek to textblock.\n"); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+	if (head.textsize!=_lread32(hf,txt,head.textsize)) {
+		dprintf_reg(stderr,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len,head.textsize); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+
+	if (!GetFileInformationByHandle(hf,&hfinfo)) {
+		dprintf_reg(stderr,"_w31_loadreg:GetFileInformationByHandle failed?.\n"); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+	lastmodified	= DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime));
+
+	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
+		return;
+	lpkey = lookup_hkey(hkey);
+	__w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
+	free(tab);
+	free(txt);
+	_lclose(hf);
+	return;
+}
+
 void
 SHELL_LoadRegistry() {
 	char	*fn;
@@ -1326,13 +1540,13 @@
 	if (key_classes_root==NULL)
 		SHELL_Init();
 
+	/* Load windows 3.1 entries */
+	_w31_loadreg();
 	/* Load windows 95 entries */
 	_w95_loadreg("C:\\system.1st",	key_local_machine);
 	_w95_loadreg("system.dat",	key_local_machine);
 	_w95_loadreg("user.dat",	key_users);
 
-	/* FIXME: win3.1 reg.dat loader still missing */
-
 	/* the global user default is loaded under HKEY_USERS\\.Default */
 	RegCreateKey16(HKEY_USERS,".Default",&hkey);
 	lpkey = lookup_hkey(hkey);
diff --git a/misc/shell.c b/misc/shell.c
index 3a96897..2f9cc8b 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -195,29 +195,34 @@
     /* extensions; however, it'd make sense to check the programs */
     /* section first, so that's what happens here. */
 
-    /* See if it's a program */
-    GetProfileString("windows", "programs", "exe pif bat com",
-		      buffer, sizeof(buffer)); /* FIXME check return code! */
+    /* See if it's a program - if GetProfileString fails, we skip this
+     * section. Actually, if GetProfileString fails, we've probably
+     * got a lot more to worry about than running a program... */
+    if ( GetProfileString32A("windows", "programs", "exe pif bat com",
+						  buffer, sizeof(buffer)) > 0 )
+	  {
+		for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
 
-    for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
+		tok = strtok(buffer, " \t"); /* ? */
+		while( tok!= NULL)
+		  {
+			if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
+			  {
+				strcpy(lpResult, xlpFile);
+				/* Need to perhaps check that the file has a path
+				 * attached */
+				dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
+							 lpResult);
+	    return 33;
 
-    tok = strtok(buffer, " \t"); /* ? */
-    while( tok!= NULL)
-    {
-	if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
-	{
-	    strcpy(lpResult, xlpFile); /* Need to perhaps check that */
-				      /* the file has a path attached */
-	    dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
-			 lpResult);
-	    return 33; /* Greater than 32 to indicate success FIXME */
-		       /* According to the docs, I should be returning */
-		       /* a handle for the executable. Does this mean */
-		       /* I'm supposed to open the executable file or */
-		       /* something? More RTFM, I guess... */
-	}
-	tok=strtok(NULL, " \t");
-    }
+		/* Greater than 32 to indicate success FIXME According to the
+		 * docs, I should be returning a handle for the
+		 * executable. Does this mean I'm supposed to open the
+		 * executable file or something? More RTFM, I guess... */
+			  }
+			tok=strtok(NULL, " \t");
+		  }
+	  }
 
     /* Check registry */
     if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
@@ -249,32 +254,34 @@
 		    strcat( lpResult, &tok[2] );
 		}
 	    }
-	    retval=33;
+	    retval=33; /* FIXME see above */
 	}
     }
     else /* Check win.ini */
     {
 	/* Toss the leading dot */
 	extension++;
-	GetProfileString( "extensions", extension, "", command,
-			 sizeof(command));
-	if (strlen(command)!=0)
-	{
-	    strcpy( lpResult, command );
-	    tok=strstr( lpResult, "^" ); /* should be ^.extension? */
-	    if (tok != NULL)
-	    {
-		tok[0]='\0';
-		strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
-		tok=strstr( command, "^" ); /* see above */
-		if ((tok != NULL) && (strlen(tok)>5))
-		{
-		    strcat( lpResult, &tok[5]);
-		}
-	    }
-	    retval=33;
+	if ( GetProfileString32A( "extensions", extension, "", command,
+                                  sizeof(command)) > 0)
+	  {
+		if (strlen(command)!=0)
+		  {
+			strcpy( lpResult, command );
+			tok=strstr( lpResult, "^" ); /* should be ^.extension? */
+			if (tok != NULL)
+			  {
+				tok[0]='\0';
+				strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
+				tok=strstr( command, "^" ); /* see above */
+				if ((tok != NULL) && (strlen(tok)>5))
+				  {
+					strcat( lpResult, &tok[5]);
+				  }
+			  }
+			retval=33; /* FIXME - see above */
+		  }
+	  }
 	}
-    }
 
     dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
     return retval;
@@ -804,7 +811,7 @@
  */
 int RegisterShellHook(void *ptr) 
 {
-	fprintf(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
+	fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr);
 	return 0;
 }
 
diff --git a/misc/spy.c b/misc/spy.c
index 57ce9d9..1b00d39 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -296,7 +296,8 @@
     "LB_SETITEMHEIGHT32",       /* 0x01a0 */
     "LB_GETITEMHEIGHT32",       /* 0x01a1 */
     "LB_FINDSTRINGEXACT32",     /* 0x01a2 */
-    NULL, NULL,
+    "LB_CARETON32",             /* 0x01a3 */
+    "LB_CARETOFF32",            /* 0x01a4 */
     "LB_SETLOCALE32",           /* 0x01a5 */
     "LB_GETLOCALE32",           /* 0x01a6 */
     "LB_SETCOUNT32",            /* 0x01a7 */
diff --git a/misc/user.c b/misc/user.c
index 3516a78..68a91a5 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -101,7 +101,7 @@
     int queueSize;
 
       /* Create task message queue */
-    queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
+    queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
     if (!SetMessageQueue( queueSize )) return 0;
 
     return 1;
@@ -112,8 +112,7 @@
  */
 void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue )
 {
-    /* FIXME: flush send messages (which are not implemented yet),
-     *        empty clipboard if needed, maybe destroy menus (Windows
+    /* FIXME: empty clipboard if needed, maybe destroy menus (Windows
      *	      only complains about them but does nothing);
      */
 
@@ -126,18 +125,13 @@
     /* Patch resident popup menu window */
     MENU_SwitchTPWndTo(0);
 
-    /* Nuke timers */
-
     TIMER_RemoveQueueTimers( hQueue );
 
+    QUEUE_FlushMessages( hQueue );
     HOOK_FreeQueueHooks( hQueue );
 
     QUEUE_SetDoomedQueue( hQueue );
-
-    /* Nuke orphaned windows */
-
-    WIN_DestroyQueueWindows( desktop->child, hQueue );
-
+    WIN_ResetQueueWindows( desktop->child, hQueue, (HQUEUE16)0);
     QUEUE_SetDoomedQueue( 0 );
 
     /* Free the message queue */
diff --git a/misc/winsock.c b/misc/winsock.c
new file mode 100644
index 0000000..cb22484
--- /dev/null
+++ b/misc/winsock.c
@@ -0,0 +1,1713 @@
+/*
+ * 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.
+ */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/ioctl.h>
+#if defined(__svr4__)
+#include <sys/filio.h>
+#include <sys/ioccom.h>
+#endif
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "windows.h"
+#include "winnt.h"
+#include "heap.h"
+#include "ldt.h"
+#include "winsock.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define dump_sockaddr(a) \
+        fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
+                        ((struct sockaddr_in *)a)->sin_family, \
+                        inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
+                        ntohs(((struct sockaddr_in *)a)->sin_port))
+
+extern void SIGNAL_MaskAsyncEvents( BOOL32 );
+
+#pragma pack(4)
+
+/* ----------------------------------- 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;
+static LPWSINFO         _wsi_list = NULL;
+
+#define WS_ALLOC(size) \
+	HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
+#define WS_FREE(ptr) \
+	HeapFree(_WSHeap, 0, (ptr) )
+
+#define WS_PTR2HANDLE(ptr) \
+        ((short)((int)(ptr) - (int)_ws_stub))
+#define WS_HANDLE2PTR(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[] =
+       { 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 };
+static int           _px_sock_ops[] =
+       { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
+         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);
+
+static int delete_async_op(ws_socket*);
+
+static void convert_sockopt(INT16 *level, INT16 *optname)
+{
+  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];
+        else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
+        break;
+     case WS_IPPROTO_TCP:
+        *optname = IPPROTO_TCP;
+  }
+}
+
+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; } 
+}
+
+static LPWSINFO wsi_find(HTASK16 hTask)
+{ LPWSINFO pwsi = _wsi_list;
+  while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
+  return pwsi; 
+}
+
+static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
+{
+  if( pwsi->last_free >= 0 )
+  {
+    int i = pwsi->last_free;
+
+    pwsi->last_free = pwsi->sock[i].flags;
+    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); 
+      }
+    }
+  }
+}
+
+static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws)
+{
+  if( ws )
+  {
+    int	        i, j, count = ws->fd_count;
+    ws_socket*  pws;
+    for( i = 0, j = 0; i < count; i++ )
+    {
+      pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+      if( _check_ws(pwsi, pws) ) 
+        if( FD_ISSET(pws->fd, fds) )
+        { 
+	  ws->fd_array[j++] = ws->fd_array[i];
+          continue; 
+        }
+      ws->fd_count--;
+    }
+  }
+}
+
+/* ----------------------------------- API ----- 
+ *
+ * Init / cleanup / error checking.
+ */
+
+INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
+{
+  WSADATA WINSOCK_data = { 0x0101, 0x0101,
+                          "WINE Sockets 1.1",
+                        #ifdef linux
+                                "Linux/i386",
+                        #elif defined(__NetBSD__)
+                                "NetBSD/i386",
+                        #elif defined(sunos)
+                                "SunOS",
+                        #elif defined(__FreeBSD__)
+                                "FreeBSD",
+                        #else
+                                "Unknown",
+                        #endif
+			   WS_MAX_SOCKETS_PER_THREAD,
+			   WS_MAX_UDP_DATAGRAM, NULL };
+  HTASK16               tid = GetCurrentTask();
+  LPWSINFO              pwsi;
+
+  dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
+
+  if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
+      HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
+
+  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))) )
+    {
+      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++;
+
+  /* return winsock information */
+  memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
+
+  dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
+  return(0);
+}
+
+INT16 WSACleanup(void)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  /* FIXME: do global cleanup if no current task */
+
+  dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
+  if( pwsi )
+  {
+      int	i, j, n;
+
+      if( pwsi->num_startup-- ) return 0;
+
+      SIGNAL_MaskAsyncEvents( TRUE );
+      WINSOCK_cancel_async_op(GetCurrentTask());
+      SIGNAL_MaskAsyncEvents( FALSE );
+
+      wsi_unlink(pwsi);
+      if( _wsi_list == NULL && async_qid != -1 )
+        if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
+        { 
+          fprintf(stderr,"failed to delete WS message queue.\n");
+        } else async_qid = -1;
+
+      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 );
+
+      for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
+	if( pwsi->sock[i].fd != -1 )
+	{ 
+	  n += delete_async_op(&pwsi->sock[i]);
+          close(pwsi->sock[i].fd); j++; 
+        }
+      if( j ) 
+	  dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
+
+      if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
+      WS_FREE(pwsi);
+      return 0;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WSAGetLastError(void)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+  INT16		ret;
+
+  dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
+
+  ret = (pwsi) ? pwsi->errno : WSANOTINITIALISED;
+
+  dprintf_winsock(stddeb, " = %i\n", (int)ret);
+  return ret;
+}
+
+void WSASetLastError(INT16 iError)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
+
+  if( pwsi ) pwsi->errno = iError;
+}
+
+int _check_ws(LPWSINFO pwsi, ws_socket* pws)
+{
+  if( pwsi )
+    if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->errno = WSAEINPROGRESS;
+    else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
+    else pwsi->errno = 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);
+}
+
+/* ----- socket operations */
+
+SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
+{
+  ws_socket*	pws  = (ws_socket*)WS_HANDLE2PTR(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;
+
+     /* 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);
+     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); 
+	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->errno = WSAENOBUFS;
+     } 
+     else pwsi->errno = wsaErrno();
+
+     pwsi->flags &= ~WSI_BLOCKINGCALL;
+  }
+  return INVALID_SOCKET;
+}
+
+INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 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);
+#endif
+
+  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;
+	     dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
+	     errno = loc_errno;
+	     switch(errno)
+	     {
+		case EBADF: pwsi->errno = WSAENOTSOCK; break;
+		case EADDRNOTAVAIL: pwsi->errno = WSAEINVAL; break;
+		default: pwsi->errno = wsaErrno();
+	     }
+	  }
+	  else return 0;
+       else pwsi->errno = WSAEAFNOSUPPORT;
+    else pwsi->errno = WSAEFAULT;
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_closesocket(SOCKET16 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;
+
+    delete_async_op(pws);
+    pws->p_aop = NULL; pws->fd = -1;
+    pws->flags = (unsigned)pwsi->last_free;
+    pwsi->last_free = pws - &pwsi->sock[0];
+    if (close(fd) < 0) pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+    else return 0;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", 
+			   (unsigned)pwsi, s, (int) name, namelen);
+#if 0
+  dump_sockaddr(name);
+#endif
+
+  if( _check_ws(pwsi, pws) )
+  {
+    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); 
+        return 0; 
+    }
+    pwsi->errno = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *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 0
+	dump_sockaddr(name);
+#endif
+       *namelen = (INT16)namelen32; 
+        return 0; 
+    }
+    pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+{
+  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", 
+			  (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; 
+    }
+    pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockopt(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, "WSA_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->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+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)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+  char*		s = inet_ntoa(in);
+
+  if( pwsi )
+  {
+    if( s == NULL ) { pwsi->errno = wsaErrno(); return NULL; }
+    if( _check_buffer( pwsi, 32 ) )
+    { 
+      strncpy(pwsi->buffer, s, 32 );
+      return SEGPTR_GET(pwsi->buffer); 
+    }
+    pwsi->errno = WSAENOBUFS;
+  }
+  return (SEGPTR)NULL;
+}
+
+INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", 
+			  (unsigned)pwsi, s, cmd, (unsigned) argp);
+  if( _check_ws(pwsi, pws) )
+  {
+    long 	newcmd  = cmd;
+
+    switch( cmd )
+    {
+	case WS_FIONREAD:   newcmd=FIONREAD; break;
+	case WS_FIONBIO:    newcmd=FIONBIO;  
+			    if( pws->p_aop && *argp == 0 ) 
+			    { 
+				pwsi->errno = WSAEINVAL; 
+				return SOCKET_ERROR; 
+			    }
+			    break;
+	case WS_SIOCATMARK: newcmd=SIOCATMARK; break;
+	case WS_IOW('f',125,u_long): 
+			  fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
+			  pwsi->errno = WSAEINVAL; return SOCKET_ERROR;
+	default:	  fprintf(stderr,"Warning: Unknown WS_IOCTL cmd (%08x)\n", cmd);
+    }
+    if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
+    pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); 
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_listen(SOCKET16 s, INT16 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) )
+  {
+    if( !pws->p_aop )
+    {
+      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 (listen(pws->fd, backlog) == 0) return 0;
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+  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->errno = wsaErrno();
+  }
+  dprintf_winsock(stddeb, " -> ERROR\n");
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, 
+		struct sockaddr *from, INT16 *fromlen16)
+{
+  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",
+                          (unsigned)pwsi, s, (unsigned)buf, len, flags);
+  if( _check_ws(pwsi, pws) )
+  {
+    int length, fromlen32 = *fromlen16;
+    if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0) 
+    {   
+      *fromlen16 = fromlen32; 
+       notify_client(pws, WS_FD_READ);
+       return (INT16)length;
+    }
+    pwsi->errno = wsaErrno();
+  }
+  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)
+{
+  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);
+
+  if( pwsi )
+  {
+     int         highfd = 0;
+     fd_set      readfds, writefds, exceptfds;
+
+     fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
+     fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
+     fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
+
+     if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
+     {
+	  if( highfd )
+	  {
+	    fd_set_update(pwsi, &readfds, ws_readfds);
+	    fd_set_update(pwsi, &writefds, ws_writefds);
+ 	    fd_set_update(pwsi, &exceptfds, ws_exceptfds);
+	  }
+	  return highfd; 
+     }
+     pwsi->errno = wsaErrno();
+  } 
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 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;
+	pwsi->errno = wsaErrno();
+    }
+    notify_client(pws, WS_FD_WRITE);
+    return (INT16)length;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+		     struct sockaddr *to, INT16 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) )
+  {
+    int		length;
+
+    if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
+    {
+	length = SOCKET_ERROR;
+        pwsi->errno = 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);
+    if( optname == SO_LINGER )
+    {
+	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->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
+{
+  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;
+    delete_async_op(pws);
+
+    if (shutdown(pws->fd, how) == 0) return 0;
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", 
+			  (unsigned)pwsi, af, type, protocol);
+
+  if( pwsi )
+  {
+    int		sock;
+
+    /* check the socket family */
+    switch(af) 
+    {
+	case AF_INET:
+	case AF_UNSPEC: break;
+	default:        pwsi->errno = WSAEAFNOSUPPORT; return INVALID_SOCKET;
+    }
+
+    /* check the socket type */
+    switch(type) 
+    {
+	case SOCK_STREAM:
+	case SOCK_DGRAM:
+	case SOCK_RAW: break;
+	default:       pwsi->errno = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
+    }
+
+    /* check the protocol type */
+    if ( protocol < 0 )  /* don't support negative values */
+    { pwsi->errno = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
+
+    if ( af == AF_UNSPEC)  /* did they not specify the address family? */
+        switch(protocol) 
+	{
+          case IPPROTO_TCP:
+             if (type == SOCK_STREAM) { af = AF_INET; break; }
+          case IPPROTO_UDP:
+             if (type == SOCK_DGRAM)  { af = AF_INET; break; }
+          default: pwsi->errno = WSAEPROTOTYPE; return INVALID_SOCKET;
+        }
+
+    if ((sock = socket(af, type, protocol)) >= 0) 
+    {
+        ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
+
+/*	printf("created %04x (%i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
+ */
+        if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
+        else pwsi->errno = WSAENOBUFS;
+    }
+
+    if (errno == EPERM) /* raw socket denied */
+    {
+        fprintf(stderr, "WS_SOCKET: not enough privileges\n");
+        pwsi->errno = WSAESOCKTNOSUPPORT;
+    } pwsi->errno = wsaErrno();
+  }
+ 
+  dprintf_winsock(stddeb, "\t\tfailed!\n");
+  return INVALID_SOCKET;
+}
+    
+
+/* ----- database functions 
+ *
+ * Note that ws_...ent structures we return have SEGPTR pointers inside them.
+ */
+
+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", 
+			  (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->errno = WSAENOBUFS;
+    else pwsi->errno = (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->errno = WSAENOBUFS;
+    else pwsi->errno = (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->errno = (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->errno = WSAENOBUFS;
+    else pwsi->errno = (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->errno = WSAENOBUFS;
+    else pwsi->errno = 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->errno = WSAENOBUFS;
+    else pwsi->errno = (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->errno = WSAENOBUFS;
+    else pwsi->errno = (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( LOWORD(lLength) <= p_aop->buflen )
+    {
+      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;
+      }
+    }
+    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
+
+  PostMessage(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
+  return AOP_CONTROL_REMOVE;
+}
+
+
+static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
+				 INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
+{
+  /* queue 'flag' request and fork off its handler */
+
+  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.ws_aop->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);
+		   }
+                 }
+      }
+      WS_FREE(async_ctl.ws_aop);
+      pwsi->errno = wsaErrno();
+  } else pwsi->errno = WSAEWOULDBLOCK;
+  return 0;
+}
+
+HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
+                               INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
+                          (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
+
+  if( pwsi ) 
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
+			    type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                               SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
+                          (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 0;
+}                     
+
+
+HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
+                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+                            0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
+                                  SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
+                          (unsigned)pwsi, hWnd, uMsg, number );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
+                            number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                               LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
+                   (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 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
+			       LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
+                           (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 0;
+}
+
+INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
+{
+  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);
+	close(p_aop->fd[0]);
+	WINSOCK_unlink_async_op(p_aop);
+	WS_FREE(p_aop);
+	return 0;
+    }
+    else pwsi->errno = WSAEINVAL;
+  return SOCKET_ERROR;
+}
+
+/* ----- asynchronous select() */
+
+int delete_async_op(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); return 1;
+    pws->flags &= WS_FD_INTERNAL;
+  }
+  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 )
+      {
+	  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
+	  PostMessage(pws->p_aop->hWnd, pws->p_aop->uMsg, 
+		     (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
+      }
+      else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
+    }
+    else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
+  }
+}
+
+int notify_client( ws_socket* pws, unsigned flag )
+{
+  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)"); 
+	    delete_async_op(pws);
+	    pws->flags &= WS_FD_INTERNAL;
+	    return 0;
+	}
+     }
+     kill(pws->p_aop->pid, SIGUSR1);
+     return 1;
+  }
+  return 0;
+}
+
+INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+    ws_async_op*        p_aop;
+
+    if( delete_async_op(pws) )  /* delete old async handler if any */
+    {
+      pws->p_aop = NULL;
+      pws->flags &= WS_FD_INTERNAL;
+    }
+    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))) )
+    {
+      p_aop->hWnd = hWnd;
+      p_aop->uMsg = uMsg;
+      pws->p_aop = p_aop;
+
+      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;
+
+      p_aop->pid = fork();
+      if( p_aop->pid != -1 )
+        if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
+	else pws->flags |= lEvent;
+
+      signal( SIGUSR1, _sigusr1_handler_parent );
+      return 0;                                  /* Wine process */
+    }
+    return SOCKET_ERROR;
+}
+
+INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+  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",
+			  (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->errno = WSAENOBUFS;
+  return SOCKET_ERROR; 
+}
+
+/* ----- miscellaneous */
+
+INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
+{
+  int i = set->fd_count;
+  
+  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
+    
+  while (i--)
+      if (set->fd_array[i] == fd) return 1;
+  return 0;
+}                                                            
+
+BOOL16 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 
+   * blocking calls are truly blocking so we always return FALSE.
+   *
+   * Note: It is allowed to call this function without prior WSAStartup().
+   */
+
+  dprintf_winsock(stddeb, "WS_IsBlocking()\n");
+  return FALSE;
+}
+
+INT16 WSACancelBlockingCall(void)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
+
+  if( pwsi ) return 0;
+  return SOCKET_ERROR;
+}
+
+FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
+{
+  FARPROC16		prev;
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n", 
+			  (unsigned)pwsi, (unsigned) lpBlockFunc);
+
+  if( pwsi ) { 
+      prev = pwsi->blocking_hook; 
+      pwsi->blocking_hook = lpBlockFunc; 
+      return prev; 
+  }
+  return 0;
+}
+
+INT16 WSAUnhookBlockingHook(void)
+{
+  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;
+}
+
+VOID
+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
+	);
+	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
+		x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
+	);
+	return;
+}
+/* ----------------------------------- end of API stuff */
+
+
+
+/* ----------------------------------- helper functions */
+
+static int list_size(char** l, int item_size)
+{
+  int i,j = 0;
+  if(l)
+  { for(i=0;l[i];i++) 
+	j += (item_size) ? item_size : strlen(l[i]) + 1;
+    j += (i + 1) * sizeof(char*); }
+  return j;
+}
+
+static int list_dup(char** l_src, char* ref, char* base, int item_size)
+{ 
+   /* base is either either equal to ref or 0 or SEGPTR */
+
+   char*		p = ref;
+   char**		l_to = (char**)ref;
+   int			i,j,k;
+
+   for(j=0;l_src[j];j++) ;
+   p += (j + 1) * sizeof(char*);
+   for(i=0;i<j;i++)
+   { l_to[i] = base + (p - ref);
+     k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
+     memcpy(p, l_src[i], k); p += k; }
+   l_to[i] = NULL;
+   return (p - ref);
+}
+
+/* ----- hostent */
+
+static int hostent_size(struct hostent* p_he)
+{
+  int size = 0;
+  if( p_he )
+  { size  = sizeof(struct hostent); 
+    size += strlen(p_he->h_name) + 1;
+    size += list_size(p_he->h_aliases, 0);  
+    size += list_size(p_he->h_addr_list, p_he->h_length ); }
+  return size;
+}
+
+int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
+{
+   /* 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).
+    */
+
+   int size = hostent_size(p_he);
+   if( size )
+   {
+     char*           p_name,*p_aliases,*p_addr,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     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_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) )
+     { 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);
+       p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
+       p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
+     else
+     { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
+       p_to->h_addrtype = (INT16)p_he->h_addrtype; 
+       p_to->h_length = (INT16)p_he->h_length;
+       p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+       p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
+       p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
+       return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
+   }
+   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)
+{
+  int size = 0;
+  if( p_pe )
+  { size  = sizeof(struct protoent);
+    size += strlen(p_pe->p_name) + 1;
+    size += list_size(p_pe->p_aliases, 0); }
+  return size;
+}
+
+int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
+{
+   int size = protoent_size(p_pe);
+   if( size )
+   {
+     char*            p_name,*p_aliases,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     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_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) )
+     { 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); 
+       p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+     else
+     { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
+       p_to->p_proto = (INT16)p_pe->p_proto;
+       p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
+       p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
+       return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
+   }
+   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)
+{
+  int size = 0;
+  if( p_se )
+  { size += sizeof(struct servent);
+    size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
+    size += list_size(p_se->s_aliases, 0); }
+  return size;
+}
+
+int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
+{
+   int size = servent_size(p_se);
+   if( size )
+   {
+     char*           p_name,*p_aliases,*p_proto,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     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_name = p;
+     strcpy(p, p_se->s_name); p += strlen(p) + 1;
+     p_proto = p;
+     strcpy(p, p_se->s_proto); p += strlen(p) + 1;
+     p_aliases = p;
+     list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
+
+     if( !(flag & WS_DUP_SEGPTR) )
+     { 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); 
+       p_to->s_proto = p_base + (p_proto - pwsi->buffer);
+       p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+     else
+     { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
+       p_to->s_port = (INT16)p_se->s_port;
+       p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+       p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
+       p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
+       return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
+   }
+   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)
+{
+    int	loc_errno = errno; 
+#if defined(__FreeBSD__)
+       dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
+                			 errno, sys_errlist[errno]);
+#else
+       dprintf_winsock(stderr, "winsock: errno %d\n", errno);
+#endif
+
+    switch(loc_errno)
+    {
+	case EINTR:		return WSAEINTR;
+	case EBADF:		return WSAEBADF;
+	case EACCES:		return WSAEACCES;
+	case EFAULT:		return WSAEFAULT;
+	case EINVAL:		return WSAEINVAL;
+	case EMFILE:		return WSAEMFILE;
+	case EWOULDBLOCK:	return WSAEWOULDBLOCK;
+	case EINPROGRESS:	return WSAEINPROGRESS;
+	case EALREADY:		return WSAEALREADY;
+	case ENOTSOCK:		return WSAENOTSOCK;
+	case EDESTADDRREQ:	return WSAEDESTADDRREQ;
+	case EMSGSIZE:		return WSAEMSGSIZE;
+	case EPROTOTYPE:	return WSAEPROTOTYPE;
+	case ENOPROTOOPT:	return WSAENOPROTOOPT;
+	case EPROTONOSUPPORT:	return WSAEPROTONOSUPPORT;
+	case ESOCKTNOSUPPORT:	return WSAESOCKTNOSUPPORT;
+	case EOPNOTSUPP:	return WSAEOPNOTSUPP;
+	case EPFNOSUPPORT:	return WSAEPFNOSUPPORT;
+	case EAFNOSUPPORT:	return WSAEAFNOSUPPORT;
+	case EADDRINUSE:	return WSAEADDRINUSE;
+	case EADDRNOTAVAIL:	return WSAEADDRNOTAVAIL;
+	case ENETDOWN:		return WSAENETDOWN;
+	case ENETUNREACH:	return WSAENETUNREACH;
+	case ENETRESET:		return WSAENETRESET;
+	case ECONNABORTED:	return WSAECONNABORTED;
+	case ECONNRESET:	return WSAECONNRESET;
+	case ENOBUFS:		return WSAENOBUFS;
+	case EISCONN:		return WSAEISCONN;
+	case ENOTCONN:		return WSAENOTCONN;
+	case ESHUTDOWN:		return WSAESHUTDOWN;
+	case ETOOMANYREFS:	return WSAETOOMANYREFS;
+	case ETIMEDOUT:		return WSAETIMEDOUT;
+	case ECONNREFUSED:	return WSAECONNREFUSED;
+	case ELOOP:		return WSAELOOP;
+	case ENAMETOOLONG:	return WSAENAMETOOLONG;
+	case EHOSTDOWN:		return WSAEHOSTDOWN;
+	case EHOSTUNREACH:	return WSAEHOSTUNREACH;
+	case ENOTEMPTY:		return WSAENOTEMPTY;
+#ifdef EPROCLIM
+	case EPROCLIM:		return WSAEPROCLIM;
+#endif
+#ifdef EUSERS
+	case EUSERS:		return WSAEUSERS;
+#endif
+#ifdef EDQUOT
+	case EDQUOT:		return WSAEDQUOT;
+#endif
+	case ESTALE:		return WSAESTALE;
+	case EREMOTE:		return WSAEREMOTE;
+
+       /* just in case we ever get here and there are no problems */
+	case 0:			return 0;
+        default:
+		fprintf(stderr, "winsock: unknown errno %d!\n", errno);
+		return WSAEOPNOTSUPP;
+    }
+}
+
+UINT16 wsaHerrno(void)
+{
+    int		loc_errno = h_errno;
+
+#if defined(__FreeBSD__)
+    dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
+               	    h_errno, sys_errlist[h_errno]);
+#else
+    dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
+#ifndef sun
+    if( debugging_winsock )  herror("wine: winsock: wsaherrno");
+#endif
+#endif
+
+    switch(loc_errno)
+    {
+	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
+	case TRY_AGAIN:		return WSATRY_AGAIN;
+	case NO_RECOVERY:	return WSANO_RECOVERY;
+	case NO_DATA:		return WSANO_DATA; 
+
+	case 0:			return 0;
+        default:
+		fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
+		return WSAEOPNOTSUPP;
+    }
+}
+
+
diff --git a/misc/winsock_async.c b/misc/winsock_async.c
new file mode 100644
index 0000000..6596b5f
--- /dev/null
+++ b/misc/winsock_async.c
@@ -0,0 +1,486 @@
+/*
+ * asynchronous winsock services
+ * 
+ * (C) 1996 Alex Korobka.
+ *
+ * FIXME: telftp16 (ftp part) stalls on AsyncSelect with FD_ACCEPT.
+ */
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "windows.h"
+#include "winsock.h"
+#include "debug.h"
+
+#define __WS_ASYNC_DEBUG	0
+
+static int		_async_io_max_fd = 0;
+static fd_set		__async_io_fdset;
+static ws_async_op*	__async_op_list = NULL;
+
+extern ws_async_ctl	async_ctl;
+extern int		async_qid;
+
+fd_set		 fd_read, fd_write, fd_excp;
+
+/* ----------------------------------- async/non-blocking I/O */
+
+int WINSOCK_async_io(int fd, int async)
+{
+    int fd_flags;
+
+    fcntl(fd, F_SETOWN, getpid());
+
+    fd_flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, (async)? fd_flags | FASYNC
+                                  : fd_flags & ~FASYNC ) != -1) return 0;
+    return -1;
+}
+
+int WINSOCK_unblock_io(int fd, int noblock)
+{
+    int fd_flags;
+
+    fd_flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, (noblock)? fd_flags |  O_NONBLOCK
+                                    : fd_flags & ~O_NONBLOCK ) != -1) return 0;
+    return -1;
+}
+
+int WINSOCK_check_async_op(ws_async_op* p_aop)
+{
+  ws_async_op*   p = __async_op_list;
+  while( p ) if( p == p_aop ) return 1;
+	     else p = p->next;
+  return 0;
+}
+
+void WINSOCK_cancel_async_op(HTASK16 hTask)
+{
+  ws_async_op*   p = __async_op_list;
+  while( p ) 
+     if(hTask == GetWindowTask16(p->hWnd)) 
+        p->flags = 0;
+}
+
+void WINSOCK_link_async_op(ws_async_op* p_aop)
+{
+  if( __async_op_list ) __async_op_list->prev = p_aop;
+  else FD_ZERO(&__async_io_fdset);
+
+  p_aop->next = __async_op_list; 
+  p_aop->prev = NULL;
+  __async_op_list = p_aop;
+
+  FD_SET(p_aop->fd[0], &__async_io_fdset);
+  if( p_aop->fd[0] > _async_io_max_fd ) 
+		     _async_io_max_fd = p_aop->fd[0];
+}
+
+void WINSOCK_unlink_async_op(ws_async_op* p_aop)
+{
+  if( p_aop == __async_op_list ) __async_op_list = p_aop->next;
+  else
+  { p_aop->prev->next = p_aop->next;
+    if( p_aop->next ) p_aop->next->prev = p_aop->prev; }
+  FD_CLR(p_aop->fd[0], &__async_io_fdset); 
+  if( p_aop->fd[0] == _async_io_max_fd )
+		      _async_io_max_fd--;
+}
+
+/* ----------------------------------- SIGIO handler -
+ *
+ * link_async_op/unlink_async_op allow to install generic
+ * async IO handlers (provided that aop_control function is defined).
+ *
+ * Note: AsyncGetXbyY expilicitly raise it.
+ */
+
+void WINSOCK_sigio(int signal)
+{
+ struct timeval         timeout;
+ fd_set                 check_set;
+ ws_async_op*		p_aop;
+
+ check_set = __async_io_fdset;
+ bzero(&timeout,sizeof(timeout));
+
+ while( select(_async_io_max_fd + 1,
+              &check_set, NULL, NULL, &timeout) > 0)
+ {
+   for( p_aop = __async_op_list;
+	p_aop ; p_aop = p_aop->next )
+      if( FD_ISSET(p_aop->fd[0], &check_set) )
+          if( p_aop->aop_control(p_aop, AOP_IO) == AOP_CONTROL_REMOVE )
+	  {
+	      if( p_aop->pid ) 
+	      { 
+		kill(p_aop->pid, SIGKILL);
+		waitpid(p_aop->pid, NULL, 0);  
+	      }
+	      WINSOCK_unlink_async_op( p_aop );
+	  }
+   check_set = __async_io_fdset;
+  }
+}
+
+/* ----------------------------------- child process IPC */
+
+static void _sigusr1_handler_child(int sig)
+{
+   /* read message queue to decide which
+    * async_ctl parameters to update 
+    *
+    * Note: we don't want to have SA_RESTART on this signal
+    * handler, otherwise select() won't notice changed fd sets.
+    */
+
+   signal( SIGUSR1, _sigusr1_handler_child );
+   while( msgrcv(async_qid, (struct msgbuf*)&async_ctl.ip,
+          MTYPE_PARENT_SIZE, MTYPE_PARENT, IPC_NOWAIT) != -1 )
+   {
+       /* only ip.lParam is updated */
+#if __WS_ASYNC_DEBUG
+       printf("handler - event %08x\n", async_ctl.ip.lParam );
+#endif
+
+       switch( async_ctl.ip.lParam )
+       {
+	  /* These are events we are notified of.
+	   */
+
+          case   WS_FD_CONNECTED: async_ctl.lEvent &= ~WS_FD_CONNECT;
+				  FD_SET(async_ctl.ws_sock->fd, &fd_read);
+				  FD_SET(async_ctl.ws_sock->fd, &fd_write);
+			  	  break;
+
+          case   WS_FD_ACCEPT:  async_ctl.ws_sock->flags |= WS_FD_ACCEPT;
+				FD_SET(async_ctl.ws_sock->fd, &fd_read);
+                                FD_SET(async_ctl.ws_sock->fd, &fd_write);
+                                break;
+          case   WS_FD_OOB:     async_ctl.lEvent |= WS_FD_OOB;
+				FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+                                break;
+          case   WS_FD_READ:    async_ctl.lEvent |= WS_FD_READ;
+				FD_SET(async_ctl.ws_sock->fd, &fd_read);
+                                break;
+          case   WS_FD_WRITE:   async_ctl.lEvent |= WS_FD_WRITE;
+				FD_SET(async_ctl.ws_sock->fd, &fd_write);
+                                break;
+          default:
+       }
+   }
+}
+
+static int notify_parent( unsigned flag )
+{
+  if( flag & WSMSG_ASYNC_SELECT )
+  {
+     async_ctl.ip.mtype = MTYPE_CLIENT;
+     while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
+                               MTYPE_CLIENT_SIZE, 0) == -1 )
+     {
+       if( errno == EINTR ) continue;
+       else if( errno == EIDRM ) _exit(0);
+       else 
+       { 
+	 perror("AsyncSelect(child)"); 
+	 return 0; 
+       }
+     }
+     kill(getppid(), SIGUSR1); 
+
+#if __WS_ASYNC_DEBUG
+  printf("handler - notify [%08x]\n", async_ctl.ip.lParam);
+#endif
+  }
+  else /* use half-duplex pipe to handle variable length packets */
+  {
+     write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+     write(async_ctl.ws_aop->fd[1], async_ctl.buffer, async_ctl.lLength );
+     kill(getppid(), SIGIO);    /* simulate async I/O */
+#if __WS_ASYNC_DEBUG
+  printf("handler - notify aop [%d, buf %d]\n", async_ctl.lLength, async_ctl.ws_aop->buflen);
+#endif
+     pause();
+  }
+  return 1;
+}
+
+/* ----------------------------------- async select */
+
+static void setup_fd_sets()
+{
+   FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_excp);
+
+   if( async_ctl.lEvent & WS_FD_OOB) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+   if( async_ctl.lEvent & (WS_FD_ACCEPT | WS_FD_READ |
+			   WS_FD_CONNECT | WS_FD_CLOSE) ) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_read);
+   if( async_ctl.lEvent & (WS_FD_WRITE | WS_FD_CONNECT) ) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_write);
+}
+
+static void setup_sig_sets(sigset_t* sig_block)
+{
+   sigemptyset(sig_block);
+   sigaddset(sig_block, SIGUSR1);
+   sigprocmask( SIG_BLOCK, sig_block, NULL);
+   signal( SIGUSR1, _sigusr1_handler_child );
+}
+
+void WINSOCK_do_async_select()
+{
+  sigset_t    sig_block;
+  int	      bytes;
+
+  setup_sig_sets(&sig_block);
+  setup_fd_sets();
+
+  while(1)
+  {
+    int		val;
+
+    sigprocmask( SIG_UNBLOCK, &sig_block, NULL); 
+
+#if __WS_ASYNC_DEBUG
+    printf("select(2)[%i,%i,%i]... ", 
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_read),
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_write),
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_excp));
+#endif
+    if( (val = select(async_ctl.ws_sock->fd + 1, 
+		     &fd_read, &fd_write, &fd_excp, NULL)) == -1 )
+      if( errno == EINTR ) continue;
+#if __WS_ASYNC_DEBUG
+    printf("got %i events\n", val);
+#endif
+
+#if __WS_ASYNC_DEBUG
+    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	printf("handler - read is READY! [%08x]\n", async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE));
+#endif
+
+    sigprocmask( SIG_BLOCK, &sig_block, NULL);
+    async_ctl.ip.lParam = 0;
+    if( async_ctl.ws_sock->flags & WS_FD_ACCEPT )
+    {
+	/* listening socket */
+	
+	FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+	FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+	async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
+        notify_parent( WSMSG_ASYNC_SELECT );
+	continue;
+    }
+    else /* I/O socket */
+    {
+	if( async_ctl.lEvent & WS_FD_CONNECT )
+	{
+	  if( FD_ISSET(async_ctl.ws_sock->fd, &fd_write) ) 
+	  {
+	      /* success - reinit fd sets to start I/O */
+
+	      if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE))
+		   FD_SET(async_ctl.ws_sock->fd, &fd_read);
+	      else FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+	      if( async_ctl.lEvent & WS_FD_WRITE )
+		   FD_SET(async_ctl.ws_sock->fd, &fd_write);
+	      else FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+	      async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
+	      async_ctl.lEvent &= ~WS_FD_CONNECT; /* one-shot */
+	  }
+	  else if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	  {
+              /* failure - do read() to get correct errno */
+
+              if( read(async_ctl.ws_sock->fd, &bytes, 4) == -1 )
+                  async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
+              else continue;
+	  } else continue; /* OOB?? */
+
+          notify_parent( WSMSG_ASYNC_SELECT );
+	}
+	else /* connected socket */
+	{
+
+	  if( async_ctl.lEvent & WS_FD_OOB )
+	    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_excp) )
+	    {
+	      async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_OOB, 0 );
+	      async_ctl.lEvent &= ~WS_FD_OOB;
+	      FD_CLR(async_ctl.ws_sock->fd, &fd_excp);
+	      notify_parent( WSMSG_ASYNC_SELECT );
+	    }
+	    else FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+
+          if( async_ctl.lEvent & WS_FD_WRITE )
+            if( FD_ISSET( async_ctl.ws_sock->fd, &fd_write ) )
+            {
+              async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_WRITE, 0 );
+              async_ctl.lEvent &= ~WS_FD_WRITE;
+              FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+              notify_parent( WSMSG_ASYNC_SELECT );
+            }
+            else FD_SET(async_ctl.ws_sock->fd, &fd_write);
+
+	  if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE) )
+	    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	    {
+	      if( ioctl( async_ctl.ws_sock->fd, FIONREAD, (char*)&bytes) != -1 )
+	      {
+	        if( bytes )	/* got data */
+	        {
+#if __WS_ASYNC_DEBUG
+		  printf("\t%i bytes pending\n", bytes );
+#endif
+		  if( async_ctl.lEvent & WS_FD_READ )
+		  {
+		     async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
+		     async_ctl.lEvent &= ~WS_FD_READ;
+		     if( !(async_ctl.lEvent & WS_FD_CLOSE) ) 
+			   FD_CLR( async_ctl.ws_sock->fd, &fd_read );
+		  }
+		  else if( !(async_ctl.lEvent & (WS_FD_WRITE | WS_FD_OOB)) ) 
+		       {
+			  sigprocmask( SIG_UNBLOCK, &sig_block, NULL);
+			  pause();
+			  sigprocmask( SIG_BLOCK, &sig_block, NULL);
+		       }
+		       else continue;
+	        }
+	        else		/* 0 bytes to read */
+	        {
+		  val = read( async_ctl.ws_sock->fd, (char*)&bytes, 4);
+	          if( errno == EWOULDBLOCK || errno == EINTR ) 
+		  { 
+#if __WS_ASYNC_DEBUG
+		    printf("\twould block..\n");
+#endif
+		    continue;
+		  }
+		  switch( val )
+		  {
+		    case  0: errno = ENETDOWN;	/* ENETDOWN */
+		    case -1: 			/* ECONNRESET */
+			     async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
+			     break;
+		    default: continue;
+		  }
+		  async_ctl.lEvent &= ~(WS_FD_CLOSE | WS_FD_READ); /* one-shot */
+		  FD_ZERO(&fd_read); FD_ZERO(&fd_write); 
+	        }
+	      }
+	      else async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
+
+	      notify_parent( WSMSG_ASYNC_SELECT );
+	  }
+	  else FD_SET(async_ctl.ws_sock->fd, &fd_read);
+
+	} /* connected socket */
+    } /* I/O socket */
+  } /* while */
+}
+
+
+/* ----------------------------------- getXbyY requests */
+
+static void _async_fail()
+{
+     async_ctl.lLength =
+        (h_errno < 0) ? (unsigned)WSAMAKEASYNCREPLY( 0, wsaErrno() )
+                      : (unsigned)WSAMAKEASYNCREPLY( 0, wsaHerrno() );
+     write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+     kill(getppid(), SIGIO);    /* simulate async I/O */
+     pause();
+}
+
+void dump_ws_hostent_offset(struct ws_hostent* wshe)
+{
+  int		i;
+  char*		base = (char*)wshe;
+  unsigned*	ptr;
+
+  printf("h_name = %08x\t[%s]\n", (unsigned)wshe->h_name, base + (unsigned)wshe->h_name);
+  printf("h_aliases = %08x\t[%08x]\n", (unsigned)wshe->h_aliases, 
+				       (unsigned)(base + (unsigned)wshe->h_aliases));
+  ptr = (unsigned*)(base + (unsigned)wshe->h_aliases);
+  for(i = 0; ptr[i]; i++ )
+  {
+	printf("%i - %08x ", i + 1, ptr[i]);
+	printf(" [%s]\n", ((char*)base) + ptr[i]);
+  }
+  printf("h_length = %i\n", wshe->h_length);
+}
+
+void WS_do_async_gethost(LPWSINFO pwsi, unsigned flag )
+{  
+  int			size = 0;
+  struct hostent* 	p_he;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_he = (flag & WSMSG_ASYNC_HOSTBYNAME)
+	 ? gethostbyname(async_ctl.ws_aop->init)
+	 : gethostbyaddr(async_ctl.ws_aop->init,
+		 	 async_ctl.lLength, async_ctl.lEvent);
+  if( p_he ) size = WS_dup_he(pwsi, p_he, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  }
+  else _async_fail();
+  _exit(0);
+}
+
+void WS_do_async_getproto(LPWSINFO pwsi, unsigned flag )
+{
+  int			size = 0;
+  struct protoent*	p_pe;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_pe = (flag & WSMSG_ASYNC_PROTOBYNAME)
+	 ? getprotobyname(async_ctl.ws_aop->init)
+	 : getprotobynumber(async_ctl.lEvent);
+  if( p_pe ) size = WS_dup_pe(pwsi, p_pe, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  } 
+  else _async_fail();
+  _exit(0);
+}
+
+void WS_do_async_getserv(LPWSINFO pwsi, unsigned flag )
+{
+  int			size = 0;
+  struct servent* 	p_se;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_se = (flag & WSMSG_ASYNC_SERVBYNAME)
+	 ? getservbyname(async_ctl.ws_aop->init, async_ctl.buffer)
+	 : getservbyport(async_ctl.lEvent, async_ctl.ws_aop->init);
+  if( p_se ) size = WS_dup_se(pwsi, p_se, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  }
+  else _async_fail();
+  _exit(0);
+}
+
diff --git a/misc/winsocket.c b/misc/winsocket.c
deleted file mode 100644
index 1507a5e..0000000
--- a/misc/winsocket.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * based on Windows Sockets 1.1 specs
- * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
- * 
- * (C) 1993,1994 John Brezak, Erik Bos.
- */
- 
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/ioctl.h>
-#if defined(__svr4__)
-#include <sys/filio.h>
-#include <sys/ioccom.h>
-#endif
-#include <sys/msg.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#include "winsock.h"
-#include "global.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#ifdef _SCO_DS
-#define _IOR _IOSR
-#define _IOW _IOSW
-#endif
-
-static WORD wsa_errno;
-static int wsa_initted;
-static key_t wine_key = 0;
-static FARPROC16 BlockFunction;
-static fd_set fd_in_use;
-
-extern int h_errno;
-
-struct ipc_packet {
-	long	mtype;
-	HANDLE16 handle;
-	HWND	hWnd;
-	WORD	wMsg;
-	LONG	lParam;
-};
-
-#ifndef WINELIB
-#pragma pack(1)
-#endif
-
-#define WINSOCK_MAX_SOCKETS	256
-#define WINSOCK_MAX_UDPDG	1024
-
-/* we are out by two with the following, is it due to byte alignment?
- * #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long)) 
- */
-#define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long) - 2)
-/*#define MTYPE 0xb0b0eb05*/
-#define MTYPE 0x30b0eb05
-
-/* These structures are Win16 only */
-
-struct WIN_hostent  {
-	SEGPTR	h_name WINE_PACKED;		/* official name of host */
-	SEGPTR	h_aliases WINE_PACKED;	/* alias list */
-	INT	h_addrtype WINE_PACKED;		/* host address type */
-	INT	h_length WINE_PACKED;		/* length of address */
-	char	**h_addr_list WINE_PACKED;	/* list of addresses from name server */
-	char	*names[2];
-	char    hostname[200];
-};
-
-struct	WIN_protoent {
-	SEGPTR	p_name WINE_PACKED;		/* official protocol name */
-	SEGPTR	p_aliases WINE_PACKED;	/* alias list */
-	INT	p_proto WINE_PACKED;		/* protocol # */
-};
-
-struct	WIN_servent {
-	SEGPTR	s_name WINE_PACKED;		/* official service name */
-	SEGPTR	s_aliases WINE_PACKED;	/* alias list */
-	INT	s_port WINE_PACKED;		/* port # */
-	SEGPTR	s_proto WINE_PACKED;		/* protocol to use */
-};
-
-typedef struct WinSock_fd_set {
-	u_short fd_count;               /* how many are SET? */
-	SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
-} WinSock_fd_set;
-                
-struct WinSockHeap {
-	char	ntoa_buffer[32];
-
-	struct	WIN_hostent hostent_addr;
-	struct	WIN_hostent hostent_name;
-	struct	WIN_protoent protoent_name;
-	struct	WIN_protoent protoent_number;
-	struct	WIN_servent servent_name;
-	struct	WIN_servent servent_port;
-
-	struct	WIN_hostent WSAhostent_addr;
-	struct	WIN_hostent WSAhostent_name;
-	struct	WIN_protoent WSAprotoent_name;
-	struct	WIN_protoent WSAprotoent_number;	
-	struct	WIN_servent WSAservent_name;
-	struct	WIN_servent WSAservent_port;
-	/* 8K scratch buffer for aliases and friends are hopefully enough */
-	char scratch[8192];
-};
-static struct WinSockHeap *Heap;
-static HGLOBAL16 HeapHandle;
-#ifndef WINELIB32
-static int ScratchPtr;
-#endif
-
-#ifndef WINELIB
-#define GET_SEG_PTR(x)	MAKELONG((int)((char*)(x)-(char*)Heap),	\
-							GlobalHandleToSel(HeapHandle))
-#else
-#define GET_SEG_PTR(x)	((SEGPTR)x)
-#endif
-
-#ifndef WINELIB
-#pragma pack(4)
-#endif
-
-#define dump_sockaddr(a) \
-	fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
-			((struct sockaddr_in *)a)->sin_family, \
-			inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
-			ntohs(((struct sockaddr_in *)a)->sin_port))
-
-#ifndef WINELIB32
-static void ResetScratch()
-{
-	ScratchPtr=0;
-}
-
-static void *scratch_alloc(int size)
-{
-	char *ret;
-	if(ScratchPtr+size > sizeof(Heap->scratch))
-		return 0;
-	ret = Heap->scratch + ScratchPtr;
-	ScratchPtr += size;
-	return ret;
-}
-
-static SEGPTR scratch_strdup(char * s)
-{
-	char *ret=scratch_alloc(strlen(s)+1);
-	strcpy(ret,s);
-	return GET_SEG_PTR(ret);
-}
-#endif
-
-static WORD wsaerrno(void)
-{
-#ifdef DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
-                fprintf(stderr, "winsock: errno %d, (%s).\n", 
-                			errno, sys_errlist[errno]);
-#else
-                fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#else
-                fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#endif
-
-        switch(errno)
-        {
-	case EINTR:		return WSAEINTR;
-	case EBADF:		return WSAEBADF;
-	case EACCES:		return WSAEACCES;
-	case EFAULT:		return WSAEFAULT;
-	case EINVAL:		return WSAEINVAL;
-	case EMFILE:		return WSAEMFILE;
-	case EWOULDBLOCK:	return WSAEWOULDBLOCK;
-	case EINPROGRESS:	return WSAEINPROGRESS;
-	case EALREADY:		return WSAEALREADY;
-	case ENOTSOCK:		return WSAENOTSOCK;
-	case EDESTADDRREQ:	return WSAEDESTADDRREQ;
-	case EMSGSIZE:		return WSAEMSGSIZE;
-	case EPROTOTYPE:	return WSAEPROTOTYPE;
-	case ENOPROTOOPT:	return WSAENOPROTOOPT;
-	case EPROTONOSUPPORT:	return WSAEPROTONOSUPPORT;
-	case ESOCKTNOSUPPORT:	return WSAESOCKTNOSUPPORT;
-	case EOPNOTSUPP:	return WSAEOPNOTSUPP;
-	case EPFNOSUPPORT:	return WSAEPFNOSUPPORT;
-	case EAFNOSUPPORT:	return WSAEAFNOSUPPORT;
-	case EADDRINUSE:	return WSAEADDRINUSE;
-	case EADDRNOTAVAIL:	return WSAEADDRNOTAVAIL;
-	case ENETDOWN:		return WSAENETDOWN;
-	case ENETUNREACH:	return WSAENETUNREACH;
-	case ENETRESET:		return WSAENETRESET;
-	case ECONNABORTED:	return WSAECONNABORTED;
-	case ECONNRESET:	return WSAECONNRESET;
-	case ENOBUFS:		return WSAENOBUFS;
-	case EISCONN:		return WSAEISCONN;
-	case ENOTCONN:		return WSAENOTCONN;
-	case ESHUTDOWN:		return WSAESHUTDOWN;
-	case ETOOMANYREFS:	return WSAETOOMANYREFS;
-	case ETIMEDOUT:		return WSAETIMEDOUT;
-	case ECONNREFUSED:	return WSAECONNREFUSED;
-	case ELOOP:		return WSAELOOP;
-	case ENAMETOOLONG:	return WSAENAMETOOLONG;
-	case EHOSTDOWN:		return WSAEHOSTDOWN;
-	case EHOSTUNREACH:	return WSAEHOSTUNREACH;
-	case ENOTEMPTY:		return WSAENOTEMPTY;
-#ifdef EPROCLIM
-	case EPROCLIM:		return WSAEPROCLIM;
-#endif
-#ifdef EUSERS
-	case EUSERS:		return WSAEUSERS;
-#endif
-#ifdef EDQUOT
-	case EDQUOT:		return WSAEDQUOT;
-#endif
-	case ESTALE:		return WSAESTALE;
-	case EREMOTE:		return WSAEREMOTE;
-/* just in case we ever get here and there are no problems */
-	case 0:			return 0;
-
-        default:
-		fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
-		return WSAEOPNOTSUPP;
-	}
-}
-
-static void errno_to_wsaerrno(void)
-{
-	wsa_errno = wsaerrno();
-}
-
-
-static WORD wsaherrno(void)
-{
-#if DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
-                fprintf(stderr, "winsock: h_errno %d, (%s).\n", 
-                			h_errno, sys_errlist[h_errno]);
-#else
-                fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
-		herror("wine: winsock: wsaherrno");
-#endif
-#else
-                fprintf(stderr, "winsock: h_errno %d\n", h_errno);
-#endif
-#endif
-
-        switch(h_errno)
-        {
-	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
-	case TRY_AGAIN:		return WSATRY_AGAIN;
-	case NO_RECOVERY:	return WSANO_RECOVERY;
-	case NO_DATA:		return WSANO_DATA; 
-/* just in case we ever get here and there are no problems */
-	case 0:			return 0;
-
-
-        default:
-		fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
-		return WSAEOPNOTSUPP;
-	}
-}
-
-
-static void herrno_to_wsaerrno(void)
-{
-	wsa_errno = wsaherrno();
-}
-
-
-static void convert_sockopt(INT *level, INT *optname)
-{
-/* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
-
-	switch (*level) {
-		case -1: 
-			*level = SOL_SOCKET;
-			switch (*optname) {
-			case 0x01:	*optname = SO_DEBUG;
-					break;
-			case 0x04:	*optname = SO_REUSEADDR;
-					break;
-			case 0x08:	*optname = SO_KEEPALIVE;
-					break;
-			case 0x10:	*optname = SO_DONTROUTE;
-					break;
-			case 0x20:	*optname = SO_BROADCAST;
-					break;
-			case 0x80:	*optname = SO_LINGER;
-					break;
-			case 0x100:	*optname = SO_OOBINLINE;
-					break;
-			case 0x1001:	*optname = SO_SNDBUF;
-					break;
-			case 0x1002:	*optname = SO_RCVBUF;
-					break;
-			case 0x1007:	*optname = SO_ERROR;
-					break;
-			case 0x1008:	*optname = SO_TYPE;
-					break;
-			default: 
-					fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
-					break;
-			}
-			break;
-		case 6:	*optname = IPPROTO_TCP;
-	}
-}
-
-#ifndef WINELIB
-static SEGPTR copy_stringlist(char **list)
-{
-	SEGPTR *s_list;
-	int i;
-	for(i=0;list[i];i++)
-		;
-	s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
-	for(i=0;list[i];i++)
-	{
-		void *copy = scratch_alloc(strlen(list[i])+1);
-		strcpy(copy,list[i]);
-		s_list[i]=GET_SEG_PTR(copy);
-	}
-	s_list[i]=0;
-	return GET_SEG_PTR(s_list);
-}
-	
-
-static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
-{
-	SEGPTR *addr_list;
-	int i;
-	ResetScratch();
-	strcpy(heapent->hostname,host->h_name);
-	heapent->h_name = GET_SEG_PTR(heapent->hostname);
-	/* Convert aliases. Have to create array with FAR pointers */
-	if(!host->h_aliases)
-		heapent->h_aliases = 0;
-	else
-		heapent->h_aliases = copy_stringlist(host->h_aliases);
-
-	heapent->h_addrtype = host->h_addrtype;
-	heapent->h_length = host->h_length;
-	for(i=0;host->h_addr_list[i];i++)
-		;
-	addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
-	heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
-	for(i=0;host->h_addr_list[i];i++)
-	{
-		void *addr=scratch_alloc(host->h_length);
-		memcpy(addr,host->h_addr_list[i],host->h_length);
-		addr_list[i]=GET_SEG_PTR(addr);
-	}
-	addr_list[i]=0;
-}
-
-static void CONVERT_PROTOENT(struct WIN_protoent *heapent, 
-	struct protoent *proto)
-{
-	ResetScratch();
-	heapent->p_name= scratch_strdup(proto->p_name);
-	heapent->p_aliases=proto->p_aliases ? 
-			copy_stringlist(proto->p_aliases) : 0;
-	heapent->p_proto = proto->p_proto;
-}
-
-static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
-{
-	ResetScratch();
-	heapent->s_name = scratch_strdup(serv->s_name);
-	heapent->s_aliases = serv->s_aliases ?
-			copy_stringlist(serv->s_aliases) : 0;
-	heapent->s_port = serv->s_port;
-	heapent->s_proto = scratch_strdup(serv->s_proto);
-}
-#else
-#define CONVERT_HOSTENT(a,b)	memcpy(a, &b, sizeof(a))
-#define CONVERT_PROTOENT(a,b)	memcpy(a, &b, sizeof(a))
-#define CONVERT_SERVENT(a,b)	memcpy(a, &b, sizeof(a))
-#endif
-
-SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
-{
-	int sock;
-
-	dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return INVALID_SOCKET;
-	}
-
-	if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
-        	errno_to_wsaerrno();
-        	return INVALID_SOCKET;
-	}
-	return sock;
-}
-
-INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
-{
-
-	dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (namelen < sizeof(*name)) {
-		WSASetLastError(WSAEFAULT);
-		return SOCKET_ERROR;
-	}
-
-	/* check the socket family */
-	if ( ((struct sockaddr_in *)name)->sin_family != AF_INET ) {
-		WSASetLastError(WSAEAFNOSUPPORT);
-		return SOCKET_ERROR;
-	}
-
-	if (bind(s, name, namelen) < 0) {
-		switch(errno) {
-		case EBADF:
-			WSASetLastError(WSAENOTSOCK);
-			break;
-		case EADDRNOTAVAIL:
-			WSASetLastError(WSAEINVAL);
-			break;
-		default:
-			errno_to_wsaerrno();
-			break;
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_closesocket(SOCKET s)
-{
-	dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	FD_CLR(s, &fd_in_use);
-
-	if (close(s) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
-{
-	dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (connect(s, name, namelen) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
-{
-	dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (getpeername(s, name, (int *) namelen) < 0) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
-{
-	dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (getsockname(s, name, (int *) namelen) < 0) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT
-WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
-{
-	dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	convert_sockopt(&level, &optname);
-
-	if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-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) );
-}
-
-char *WINSOCK_inet_ntoa(struct in_addr in)
-{
-	char *s;
-
-/*	dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
-
-	if ((s = inet_ntoa(in)) == NULL) {
-        	errno_to_wsaerrno();
-        	return NULL;
-	}
-
-	strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
-
-	return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
-}
-
-INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
-{
-	long newcmd;
-	u_long *newargp;
-	char *ctlname;
-	dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	/* Why can't they all use the same ioctl numbers */
-	newcmd=cmd;
-	newargp=argp;
-	ctlname=0;
-	if(cmd == _IOR('f',127,u_long))
-	{
-		ctlname="FIONREAD";
-		newcmd=FIONREAD;
-	}else 
-	if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
-	{
-		ctlname="FIONBIO";
-		newcmd=FIONBIO;
-	}else
-	if(cmd == _IOW('f',125,u_long))
-	{
-		ctlname="FIOASYNC";
-		newcmd=FIOASYNC;
-	}
-
-	if(!ctlname)
-		fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
-	else
-		dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
-	
-
-	if (ioctl(s, newcmd, newargp) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_listen(SOCKET s, INT backlog)
-{
-	dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (listen(s, backlog) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-u_long WINSOCK_ntohl(u_long netlong)
-{
-	return( ntohl(netlong) );
-}
-
-u_short WINSOCK_ntohs(u_short netshort)
-{
-	return( ntohs(netshort) );
-}
-
-INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = recv(s, buf, len, flags)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
-		struct sockaddr *from, int *fromlen)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_select(INT nfds, WinSock_fd_set *ws_readfds,
-	WinSock_fd_set *ws_writefds, WinSock_fd_set *ws_exceptfds,
-	struct timeval *timeout)
-{
-	int ret;
-	int i;
-	int count;
-	int highfd;
-	fd_set readfds,writefds,exceptfds;
-	FD_ZERO(&readfds);
-	FD_ZERO(&writefds);
-	FD_ZERO(&exceptfds);
-	
-	dprintf_winsock(stddeb, "WSA_select called: nfds %d (ignored), ptr %8lx, ptr %8lx, ptr %8lx\n", nfds, (unsigned long) ws_readfds, (unsigned long) ws_writefds, (unsigned long) ws_exceptfds);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		dprintf_winsock(stddeb, "WSA_select: returning error WSANOTINITIALISED\n");
-		return SOCKET_ERROR;
-	}
-	
-/* In some sort of attempt to be BSD-compatible, MS-Winsock accepts and
-   discards the nfds parameter.  However, the format of windoze's fd_sets
-   is totally different from the BSD standard.  So much for compatibility.
-   Hence, we must convert the winsock array-of-ints fd_set to the UNIX
-   bitmapped format. */
-
-	if(ws_readfds!=NULL) {
-		dprintf_winsock(stddeb, "readfds: (%d) ",ws_readfds->fd_count);
-		for(i=0;i<(ws_readfds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_readfds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_readfds)[2]))[i], &readfds);*/
-			FD_SET(ws_readfds->fd_array[i], &readfds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "readfds: (null)\n");
-	}
-	if(ws_writefds!=NULL) {
-		dprintf_winsock(stddeb, "writefds: (%d) ",ws_writefds->fd_count);
-		for(i=0;i<(ws_writefds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_writefds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_writefds)[2]))[i], &writefds);*/
-			FD_SET(ws_writefds->fd_array[i], &writefds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "writefds: (null)\n");
-	}
-	if(ws_exceptfds!=NULL) {
-		dprintf_winsock(stddeb, "exceptfds: (%d) ",ws_exceptfds->fd_count);
-		for(i=0;i<(ws_exceptfds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_exceptfds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_exceptfds)[2]))[i], &exceptfds);*/
-			FD_SET(ws_exceptfds->fd_array[i], &exceptfds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "exceptfds: (null)\n");
-	}
-	
-	/* Make the select() call */
-	dprintf_winsock(stddeb, "WSA_select: calling select()\n");
-	highfd=256; /* We should count them, but this works */
-	ret=select(highfd, &readfds, &writefds, &exceptfds, timeout);
-	dprintf_winsock(stddeb, "WSA_select: select() returned %d\n",ret);
-	if(ret<0) {
-		errno_to_wsaerrno();
-		dprintf_winsock(stddeb, "WSA_select returning: Error %d\n",SOCKET_ERROR);
-		return SOCKET_ERROR;
-	}
-	
-	/* update the winsock fd sets */
-	if(ws_readfds!=NULL) {
-		dprintf_winsock(stddeb, "readfds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&readfds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_readfds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_readfds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "readfds: (null)\n");
-	}
-	if(ws_writefds!=NULL) {
-		dprintf_winsock(stddeb, "writefds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&writefds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_writefds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_writefds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "writefds: (null)\n");
-	}
-	if(ws_exceptfds!=NULL) {
-		dprintf_winsock(stddeb, "exceptfds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&exceptfds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_exceptfds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_exceptfds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "exceptfds: (null)\n");
-	}
-	
-	dprintf_winsock(stddeb, "WSA_select returning: %d\n",ret);
-	return(ret);	
-}
-
-INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = send(s, buf, len, flags)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
-		struct sockaddr *to, INT tolen)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval, 
-			INT optlen)
-{
-	dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
-	convert_sockopt(&level, &optname);
-	
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (setsockopt(s, level, optname, optval, optlen) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}                                         
-
-INT WINSOCK_shutdown(SOCKET s, INT how)
-{
-	dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (shutdown(s, how) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
-{
-    int sock;
-
-    dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return INVALID_SOCKET;
-	}
-
-    /* check the socket family */
-    switch(af) {
-    case AF_INET:
-    case AF_UNSPEC:
-        break;
-    default:
-        WSASetLastError(WSAEAFNOSUPPORT);
-        return INVALID_SOCKET;
-        break;
-    }
-
-    /* check the socket type */
-    switch(type) {
-    case SOCK_STREAM:
-    case SOCK_DGRAM:
-    case SOCK_RAW:
-        break;
-    default:
-        WSASetLastError(WSAESOCKTNOSUPPORT);
-        return INVALID_SOCKET;
-        break;
-    }
-
-    /* check the protocol type */
-    if ( protocol < 0 ) { /* don't support negative values */
-        WSASetLastError(WSAEPROTONOSUPPORT);
-        return INVALID_SOCKET;
-    }
-
-    if ( af == AF_UNSPEC) { /* did they not specify the address family? */
-        switch(protocol) {
-        case IPPROTO_TCP:
-             if (type == SOCK_STREAM) {
-                 af = AF_INET;
-                 break;
-             }
-        case IPPROTO_UDP:
-             if (type == SOCK_DGRAM) {
-                 af = AF_INET;
-                 break;
-             }
-        default:
-             WSASetLastError(WSAEPROTOTYPE);
-             return INVALID_SOCKET;
-             break;
-        }
-    }
-
-    if ((sock = socket(af, type, protocol)) < 0) {
-        if (errno == EPERM) {
-            /* non super-user wants a raw socket */
-            fprintf(stderr, "WSA_socket: not enough privileges\n");
-            WSASetLastError(WSAESOCKTNOSUPPORT);
-        } else
-            errno_to_wsaerrno();
-        dprintf_winsock(stddeb, "WSA_socket: failed !\n");
-        return INVALID_SOCKET;
-    }
-    
-    if (sock > WINSOCK_MAX_SOCKETS) {
-	/* we only support socket numbers up to WINSOCK_MAX_SOCKETS.
-	 * The return value indicates no more descriptors are available
-	 */
-        WSASetLastError(WSAEMFILE);
-	return INVALID_SOCKET;
-    }
-
-    FD_SET(sock, &fd_in_use);
-
-    dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
-    return sock;
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
-{
-	struct hostent *host;
-
-	dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	if ((host = gethostbyaddr(addr, len, type)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_HOSTENT(&Heap->hostent_addr, host);
-
-	return GET_SEG_PTR(&Heap->hostent_addr);
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyname(const char *name)
-{
-	struct hostent *host;
-
-	dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	if ((host = gethostbyname(name)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_HOSTENT(&Heap->hostent_name, host);
-
-	return GET_SEG_PTR(&Heap->hostent_name);
-}
-
-INT WINSOCK_gethostname(char *name, INT namelen)
-{
-	dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return SOCKET_ERROR;
-	}
-
-	if (gethostname(name, namelen) < 0) {
-		if (errno == EINVAL)
-			WSASetLastError(WSAEFAULT);
-		else
-			errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}          
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobyname(char *name)
-{
-	struct protoent *proto;
-
-	dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((proto = getprotobyname(name)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_PROTOENT(&Heap->protoent_name, proto);
-
-	return GET_SEG_PTR(&Heap->protoent_name);
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobynumber(INT number)
-{
-	struct protoent *proto;
-
-	dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((proto = getprotobynumber(number)) == NULL) {
-#if 0
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-#endif
-		WSASetLastError(WSANO_DATA);
-        	return NULL;
-	}
-	CONVERT_PROTOENT(&Heap->protoent_number, proto);
-
-	return GET_SEG_PTR(&Heap->protoent_number);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
-{
-	struct servent *service;
-
-	if (proto == NULL)
-		proto = "tcp";
-
-	dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((service = getservbyname(name, proto)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_SERVENT(&Heap->servent_name, service);
-
-	return GET_SEG_PTR(&Heap->servent_name);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
-{
-	struct servent *service;
-
-	dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((service = getservbyport(port, proto)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_SERVENT(&Heap->servent_port, service);
-
-	return GET_SEG_PTR(&Heap->servent_port);
-}
-
-/******************** winsock specific functions ************************
- *
- */
-static HANDLE16 new_handle = 1;
-
-static HANDLE16 AllocWSAHandle(void)
-{
-	return new_handle++;
-}
-
-static void recv_message(int sig)
-{
-	static struct ipc_packet message;
-	int message_is_valid = 0;
-	BOOL result;
-
-	message.mtype = MTYPE;
-
-	signal(SIGUSR1, recv_message);
-	while (1) {
-
-		if (!message_is_valid) {
-			if (msgrcv(wine_key, (struct msgbuf*)&(message), 
-				   IPC_PACKET_SIZE, 0 /*MTYPE*/, IPC_NOWAIT) == -1) {
-				perror("wine: winsock: msgrcv");
-				break;
-			}
-		}
-
-		result = PostMessage(message.hWnd, message.wMsg,
-				     (WPARAM16)message.handle, message.lParam);
-		if (result != FALSE) {
-			message_is_valid = 1;
-			break;
-		}
-		else
-			message_is_valid = 0;
-		
-	}
-		
-    if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
-	perror("wine: winsock: msgget"); 
-}
-
-
-static void send_message( HWND hWnd, u_int wMsg, HANDLE16 handle, long lParam)
-{
-	struct ipc_packet message;
-	
-	message.mtype = MTYPE;
-	message.handle = handle;
-	message.hWnd = hWnd;
-	message.wMsg = wMsg;
-	message.lParam = lParam;
-
-	if (msgsnd(wine_key, (struct msgbuf*)&(message),  
-		   IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
-		perror("wine: winsock: msgsnd");
-
-	kill(getppid(), SIGUSR1);
-}
-
-
-HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr,
-                             INT len, INT type, LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct hostent *host;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((host = gethostbyaddr(addr, len, type)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, host, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                             LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct hostent *host;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((host = gethostbyname(name)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, host, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}                     
-
-
-HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                              LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct protoent *proto;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((proto = getprotobyname(name)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, proto, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, 
-                                LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct protoent *proto;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((proto = getprotobynumber(number)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, proto, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                             LPCSTR proto, LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct servent *service;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((service = getservbyname(name, proto)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, service, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, LPCSTR proto,
-                             LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct servent *service;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((service = getservbyport(port, proto)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, service, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
-{
-    long event;
-    fd_set read_fds, write_fds, except_fds;
-    int errors = 0;
-    int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-    dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %04x, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
-
-    /* remove outstanding asyncselect() processes */
-    /* kill */
-
-    if (wMsg == 0 && lEvent == 0) 
-        return 0;
-
-    newpid = fork();
-    if (newpid) {
-        dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-        return 0;
-    } else {
-        while (1) {
-            FD_ZERO(&read_fds);
-            FD_ZERO(&write_fds);
-            FD_ZERO(&except_fds);
-
-            if (lEvent & FD_READ)
-                FD_SET(s, &read_fds);
-            if (lEvent & FD_WRITE)
-                FD_SET(s, &write_fds);
-
-            fcntl(s, F_SETFL, O_NONBLOCK);
-            if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) {
-                errors = wsaerrno();
-            }
-
-            event = 0;
-            if (FD_ISSET(s, &read_fds))
-                event |= FD_READ;
-            if (FD_ISSET(s, &write_fds))
-                event |= FD_WRITE;
-            send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
-        }
-    }
-}
-
-INT WSAFDIsSet(SOCKET fd, WinSock_fd_set *set)
-{
-  int i = set->fd_count;
-  
-  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
-    
-  while (i--)
-    {
-      if (set->fd_array[i] == fd)
-        {
-          dprintf_winsock(stddeb, "__WSAFDIsSet returning 1\n");
-          return 1;
-        }
-    }
-  dprintf_winsock(stddeb, "__WSAFDIsSet returning 0\n");
-  return 0;
-}                                                            
-
-INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
-{
-	dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %04x\n", hAsyncTaskHandle);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	return 0;
-}
-
-INT WSACancelBlockingCall(void)
-{
-	dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	return 0;
-}
-          
-INT WSAGetLastError(void)
-{
-	dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
-
-	return wsa_errno;
-}
-
-void WSASetLastError(INT iError)
-{
-	dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
-
-	/* technically, we should make sure that WINESockets 
-	* has been started up correctly. But since this function
-	* is also used internally, it makes no sense.
-	*
-	*if (!wsa_initted) { 
-	*	WSASetLastError(WSANOTINITIALISED);
-	*	return SOCKET_ERROR;
-	*}
-	*/
-
-	wsa_errno = iError;
-}
-
-BOOL WSAIsBlocking(void)
-{
-	dprintf_winsock(stddeb, "WSA_IsBlocking\n");
-
-	return 0;
-}
-
-FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
-{
-	dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	BlockFunction = lpBlockFunc;
-
-	return (FARPROC16) lpBlockFunc;
-}
-
-INT WSAUnhookBlockingHook(void)
-{
-	dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	BlockFunction = NULL;
-
-	return 0;
-}
-
-#ifdef 0
-WSADATA WINSOCK_data = {
-        0x0101,
-        0x0101,
-        "WINE Sockets",
-#ifdef linux
-        "LINUX/i386",
-#elif defined(__NetBSD__)
-        "NetBSD/i386",
-#elif defined(sunos)
-	"SunOS",
-#elif defined(__FreeBSD__)
-	"FreeBSD",
-#else
-	"Unknown",
-#endif
-        WINSOCK_MAX_SOCKETS,
-	WINSOCK_MAX_UDPDG,
-        NULL
-};
-#endif
-
-INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
-{
-
-	WSADATA WINSOCK_data = {
-        			0x0101,
-        			0x0101,
-        			"WINE Sockets",
-			#ifdef linux
-        			"Linux/i386",
-			#elif defined(__NetBSD__)
-        			"NetBSD/i386",
-			#elif defined(sunos)
-				"SunOS",
-			#elif defined(__FreeBSD__)
-				"FreeBSD",
-			#else
-				"Unknown",
-			#endif
-        			WINSOCK_MAX_SOCKETS,
-				WINSOCK_MAX_UDPDG,
-				NULL
-				};
-
-    dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
-
-    if (LOBYTE(wVersionRequested) < 1 ||
-        (LOBYTE(wVersionRequested) == 1 &&
-         HIBYTE(wVersionRequested) < 1))
-	return WSAVERNOTSUPPORTED;
-
-    if (!lpWSAData)
-        return WSAEINVAL;
-
-	/* alloc winsock heap */
-
-    if ((HeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
-	return WSASYSNOTREADY;
-
-    Heap = (struct WinSockHeap *) GlobalLock16(HeapHandle);
-
-    /* return winsock information */
-    memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data)); 
-
-    /* ipc stuff */
-
-    if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
-	perror("wine: winsock: msgget"); 
-
-    signal(SIGUSR1, recv_message);
-
-    /* clear */
-    
-    FD_ZERO(&fd_in_use);
-
-    /* increment our usage count */
-    wsa_initted++;
-    dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
-    return(0);
-}
-
-INT WSACleanup(void)
-{
-	int fd;
-
-	dprintf_winsock(stddeb, "WSACleanup (%d)\n",getpid());
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	/* decrement usage count */
-	wsa_initted--;
-
-	if (wsa_initted == 0) {
-		if (wine_key)
-			if (msgctl(wine_key, IPC_RMID, NULL) == -1)
-				perror("wine: winsock: msgctl");
-
-		for (fd = 0; fd != FD_SETSIZE; fd++)
-			if (FD_ISSET(fd, &fd_in_use))
-				close(fd);
-
-	}
-	return 0;
-}
-
-VOID
-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
-	);
-	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
-		x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
-	);
-	return;
-}