diff --git a/ANNOUNCE b/ANNOUNCE
index 8b5e5191df94373c05610b85909bf256fb88ec97..f1033c99228d067964bc6e46ae6610bb62768b40 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,17 +1,17 @@
-This is release 950319 of Wine the MS Windows emulator.  This is still a
+This is release 950403 of Wine the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work.
 
 Patches should be submitted to "wine-new@amscons.com".  Please don't forget
 to include a ChangeLog entry.  I'll make a new release every other Sunday.
 
-WHAT'S NEW with Wine-950319: (see ChangeLog for details)
-	- New memory management scheme. This will probably cause many
-	  new problems, please report them. I'm particularly interested
-	  to hear how it works for the *BSD people.
-	- Many fixes in file and directory handling.
-	- Handling of additive fixup records.
-	- Lots of bug fixes
+WHAT'S NEW with Wine-950403: (see ChangeLog for details)
+	- Compiled callbacks for better performance.
+	- Many listbox fixes.
+	- Many edit control fixes.
+	- 16-bit entry points for built-in window procedures to make
+	  Borland programs happy.
+	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
 
@@ -19,10 +19,10 @@ Because of lags created by using mirror, this message may reach you before
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950319.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950319.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950319.tar.gz
-    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950319.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950403.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950403.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950403.tar.gz
+    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950403.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 1f66b98a3a3a7cd8798977c71ebff7a904785911..dae439c7adb057d6923d103fe670aeda19972d16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,109 @@
+----------------------------------------------------------------------
+Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
+
+	* [Configure] [if1632/Imakefile]
+	Removed new build and short names options.
+
+	* [if1632/*.c] [tools/build.c]
+	Implemented compiled call-back functions for better performance;
+	all the relay code is now done in assembly code generated by the
+	build program.
+	Relay code is no longer dependent on being loaded below 64K.
+
+	* [loader/resource.c]
+	Fixed memory leak in LoadString(). A fix will also be needed for
+	other resources.
+
+	* [memory/global.c]
+	Implemented global heap arenas, so we can store informations about
+	global blocks, like lock counts or owner handle.
+	Implemented FarGetOwner() and FarSetOwner().
+	Implemented global heap TOOLHELP functions.
+
+	* [memory/selector.c]
+	Bug fix: it was not possible to re-use a free selector.
+
+Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)
+
+	*  [controls/listbox.c]
+	Major work on listbox code
+         - Many bugs fixed (still many bugs)
+         - More messages supported
+         - Code simplified
+
+Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)
+
+	* [controls/edit.c]
+	Lots of bug fixes related to diappearing text, lost carets,
+	highlighting, segmentation faults, occurance of random
+	characters, insertion of characters over selection, misplaced
+	caret location, display corruption, end of line behavior, etc.
+
+	* [controls/widgets.c]
+	EDIT class doesn't want to use CS_PARENTDC flag.
+
+Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [loader/selector.c]
+	  FixupFunctionPrologs() should also handle multiple data modules.
+	  (this bug only became visible because MakeProcInstance() was fixed
+	  in 950319)
+	
+	* [misc/dosfs.c]
+	  Simplified DOS_SimplifyPath.
+	  Small fix to DOS_opendir to reuse an entry if an open directory
+	  is opened again, to prevent "too many open directories" messages.
+
+Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>
+
+	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
+	CoDisconnectObject: new stub function
+
+	* [include/msdos.h]
+	fix DOSVERSION
+
+	* [loader/ne_image.c]
+	NE_FixupSegment: Be more generous on additive fixups
+
+	* [if1632/user.spec][misc/network.c]
+	Add more WNet* stubs
+
+Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+        * [controls/listbox.c]
+	  DlgDirList(): send segptr instead of linear pointer 
+	  in message to static control
+	* [controls/menu.c]
+	  Tried to implement ownerdrawn menuitems. Doesn't work.
+	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
+	  Provide a stub for GetRasterizerCaps()
+	* [loader/selector.c]
+	  Pass end address instead of length to LocalInit() in 
+	  CreateSelectors()
+	* [memory/local.c]
+	  LocalInit(): If there's already a local heap in the segment, do
+	  nothing and return TRUE
+	* [objects/linedda.c]
+	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
+	  now.
+	* [windows/cursor.c]
+	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
+	  more work still.
+
+Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
+	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
+	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
+	  [windows/nonclient.c] [misc/message.c]
+	  Added a new builtin DLL that provides 16 bit entry points for all
+	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
+	  again.
+	* [misc/shell.c]
+	  RegOpenKey()/RegCreateKey() bugs fixed.
+        * [loader/ne_image.c]
+	  Skipping the initialization of a DLL when CS == 0 was broken.
+
 ----------------------------------------------------------------------
 Sun Mar 19 16:30:20 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
 
diff --git a/Configure b/Configure
index b1b4a6d62f18a60364428adee980466821746bcb..892e481a8badffef85da45432de92a582161ab6d 100644
--- a/Configure
+++ b/Configure
@@ -6,9 +6,7 @@
 : ${PAGER:=more}
 
 WINELIB=''
-SHORTNAMES=''
 LANGUAGE=not_matching
-NEWBUILD=''
 ALLDEFINES=''
 
 # Ask question 'str' and set 'var' to reply (defaulting to 'def' on CR)
@@ -28,6 +26,7 @@ prompt ()
 	fi
 }
 
+echo
 echo Read the RELEASE-NOTES for an explanation of the various flags
 echo
 
@@ -39,15 +38,6 @@ then
 	ALLDEFINES="$ALLDEFINES -DWINELIB"
 fi
 
-echo
-echo -n 'Short filenames (Y/N) [N]? '
-read input
-if [ "$input" = 'y' -o "$input" = 'Y' ]
-then
-	SHORTNAMES='#define ShortNames -DSHORTNAMES'
-	ALLDEFINES="$ALLDEFINES -DSHORTNAMES"
-fi
-
 LANGS=`echo En rc/sysres_*.rc | sed -e 's/rc\/sysres_//g' -e 's/\.rc//g' -e 's/ /\//g;'`
 while	expr "$LANGS" : ".*$LANGUAGE" = 0 > /dev/null
 do
@@ -68,18 +58,6 @@ else
        MALLOC_DEBUGGING=''
 fi
 
-if [ "`(domainname)`" = 'amscons.com' ]
-then
-	echo
-	echo -n 'New build program (Y/N) [N]? '
-	read input
-	if [ "$input" = 'y' -o "$input" = 'Y' ]
-	then
-		NEWBUILD='#define NewBuild -DNEWBUILD'
-		ALLDEFINES="$ALLDEFINES -DNEWBUILD"
-	fi
-fi
-
 prompt "Global configfile name" WINE_CONFIGFILE /usr/local/etc/wine.conf
 
 if [ -r $WINE_CONFIGFILE ]
@@ -197,8 +175,6 @@ fi
 cat > autoconf.h << EOF
 /* autoconf.h generated automatically.  Run Configure. */
 $WINELIB
-$SHORTNAMES
-$NEWBUILD
 $MALLOC_DEBUGGING
 #define WINE_INI_GLOBAL "$WINE_CONFIGFILE"
 #define AutoDefines $ALLDEFINES
diff --git a/Imakefile b/Imakefile
index 8405d0a350a56ca67dd66c962f55c247b79d4018..33ee8876824a66eee0b6e7160fb20b37f00fb535 100644
--- a/Imakefile
+++ b/Imakefile
@@ -58,13 +58,9 @@ COMMONOBJS = \
 	rc/rc.o \
 	windows/windows.o
 
-/*
- * WARNING: if1632.o must be the first object file because its code must be
- *          linked at the lowest possible addresses.
- */
 EMUOBJS = \
-	if1632/if1632.o \
 	debugger/debugger.o \
+	if1632/if1632.o \
 	memory/memory.o \
 	miscemu/miscemu.o
 
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 8d53b913a311f1aa26579fc3c269abb36f895fc2..85028b1035c75dd45f5587c1a4ec94f8230d12a5 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -15,9 +15,6 @@ sure to analyze the problem before you report it to the newsgroup.
 Emulator/Library: You need an emulator when you want to run MS-Win
 binaries. You need a library when you want to compile the source code
 of a Windows program.
-Short filenames: Some file systems are limited to 11 characters per
-file name. Files generated in if1632 will get gracefully translated
-names.
 Language: Wine can present the system menu in multiple languages. Select
 one of English, German, or Norwegian here.
 Malloc debugging: When enabled, the mtrace and mcheck GNU libc functions
diff --git a/Wine.tmpl b/Wine.tmpl
index e1f7e0b6287949c18e4a74611607b543538ab588..1cc33203f2d0937d609cde3eaf0d5e94c3f01a0a 100644
--- a/Wine.tmpl
+++ b/Wine.tmpl
@@ -1,38 +1,7 @@
-XCOMM $Id$
-
 INCLUDES = -I$(TOP)/include -I$(TOP)
 
 XCOMM Imake rules go here
 
-XCOMM First, dll description to files etc
-#ifndef MakeDllFromSpec
-#ifndef NewBuild
-#ifndef ShortNames
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/build  @@\
-	$(TOP)/tools/build name.spec					@@\
-
-#else /* ShortNames */
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/build   @@\
-	$(TOP)/tools/build name.spec					@@\
-
-#endif /* ShortNames */
-#else /* NewBuild */
-#ifndef ShortNames
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(rly_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/newbuild  @@\
-	$(TOP)/tools/newbuild name.spec					@@\
-
-#else /* ShortNames */
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(rly_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/newbuild   @@\
-	$(TOP)/tools/newbuild name.spec					@@\
-
-#endif /* ShortNames */
-#endif /* NewBuild */
-#endif /* MakeDllFromSpec */
-
 /*
  * WineRelocatableTarget - generate rules to produce a relocatable object
  * file instead of a library.  
diff --git a/controls/edit.c b/controls/edit.c
index 5a42a133d57e822314d6b564dad63353c14ec0f8..2109aa3a56481df0dfcd338c1d62a09b32350acf 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -4,6 +4,7 @@
  * Copyright  David W. Metcalfe, 1994
  *
  * Release 3, July 1994
+ * April 1995 bug fixes (William Magro)
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
 */
@@ -65,6 +66,7 @@ typedef struct
     int DeletedCurrCol;      /* starting col from which text was deleted */
     int NumTabStops;         /* number of tab stops in buffer hTabStops */
     HANDLE hTabStops;        /* handle of tab stops buffer */
+    BOOL HaveFocus;          /* TRUE if this edit has the focus */
 } EDITSTATE;
 
 
@@ -147,7 +149,7 @@ void EDIT_DeleteSel(HWND hwnd);
 void EDIT_ClearSel(HWND hwnd);
 int EDIT_TextLineNumber(HWND hwnd, char *lp);
 void EDIT_SetAnchor(HWND hwnd, int row, int col);
-void EDIT_ExtendSel(HWND hwnd, int x, int y);
+void EDIT_ExtendSel(HWND hwnd, INT x, INT y);
 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
 void EDIT_StopMarking(HWND hwnd);
 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
@@ -380,29 +382,32 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	break;
 
     case WM_KILLFOCUS:
+	es->HaveFocus = FALSE;
 	DestroyCaret();
+	if (SelMarked(es)) EDIT_ClearSel(hwnd);
 	NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
 	break;
 
     case WM_LBUTTONDOWN:
 	HideCaret(hwnd);
 	SetFocus(hwnd);
+	SetCapture(hwnd);
 	EDIT_LButtonDownMsg(hwnd, wParam, lParam);
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
 	ShowCaret(hwnd);
 	break;
 
     case WM_LBUTTONUP:
+	if (GetCapture() != hwnd) break;
+	ReleaseCapture();
 	ButtonDown = FALSE;
 	if (TextMarking)
 	    EDIT_StopMarking(hwnd);
 	break;
 
     case WM_MOUSEMOVE:
-	HideCaret(hwnd);
-	EDIT_MouseMoveMsg(hwnd, wParam, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
+	if (es->HaveFocus)
+	    EDIT_MouseMoveMsg(hwnd, wParam, lParam);
 	break;
 
     case WM_MOVE:
@@ -422,6 +427,7 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam)
 	break;
 
     case WM_SETFOCUS:
+	es->HaveFocus = TRUE;
 	CreateCaret(hwnd, 0, 2, es->txtht);
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
 	ShowCaret(hwnd);
@@ -506,6 +512,8 @@ long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
         es->wlines = 0;
         es->textwidth = 0;
 	EDIT_ClearTextPointers(hwnd);
+	if(IsMultiLine()) strcpy(text, "\r\n");
+	EDIT_BuildTextPointers(hwnd);
     }
     else
     {
@@ -516,14 +524,18 @@ long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
 	    es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
 	    text = EDIT_HeapAddr(hwnd, es->hText);
 	    strcpy(text, windowName);
+	    if(IsMultiLine()) strcat(text, "\r\n");
+	    es->textlen += 2;
 	    *(text + es->textlen) = '\0';
 	}
 	else
 	{
-	    es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 2);
+	    es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 4);
 	    text = EDIT_HeapAddr(hwnd, es->hText);
 	    strcpy(text, windowName);
-	    es->textlen = strlen(windowName) + 1;
+	    if(IsMultiLine()) strcat(text, "\r\n");
+	    es->textlen = strlen(windowName) + 3;
+	    *(text + es->textlen) = '\0';
 	}
 	*(text + es->textlen + 1) = '\0';
 	EDIT_BuildTextPointers(hwnd);
@@ -727,7 +739,7 @@ void EDIT_PaintMsg(HWND hwnd)
 
     for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
     {
-	if (y < es->wlines - es->wtop)
+	if (y < (IsMultiLine() ? es->wlines : 1) - es->wtop)
 	    EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
     }
 
@@ -885,17 +897,23 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
     lnlen1 = lnlen;
 
     /* build the line to display */
-    if (lnlen < es->wleft)
+    if (lnlen < (es->wleft + rc.left))
+    {
 	lnlen = 0;
+        return;
+    }
     else
+    {
 	off += es->wleft;
+	lnlen -= off;
+    }
 
     if (lnlen > rc.left)
     {
 	off += rc.left;
 	lnlen = lnlen1 - off;
-	len = min(lnlen, rc.right - rc.left);
     }
+    len = min(lnlen, rc.right - rc.left);
 
     if (SelMarked(es))
     {
@@ -1141,7 +1159,7 @@ HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
     str = (char *)EDIT_HeapAddr(hwnd, hStr);
     for (i = ch1, j = 0; i < ch; i++, j++)
 	str[j] = lp[i];
-    str[++j] = '\0';
+    str[j] = '\0';
     dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
     return hStr;
 }
@@ -1193,7 +1211,7 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
     char *text = EDIT_HeapAddr(hwnd, es->hText);
-    char *currchar = CurrChar;
+    char *currchar;
     RECT rc;
     BOOL FullPaint = FALSE;
 
@@ -1203,6 +1221,9 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
     if (SelMarked(es))
 	EDIT_DeleteSel(hwnd);
 
+    /* currchar must be assigned after deleting the selection */
+    currchar = CurrChar;
+
     /* test for typing at end of maximum buffer size */
     if (currchar == text + es->MaxTextLen)
     {
@@ -1271,7 +1292,6 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
     else
 	es->textwidth = max(es->textwidth,
 			    EDIT_StrLength(hwnd, text, strlen(text), 0));
-    EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
 
     if (ch == '\n')
     {
@@ -1306,6 +1326,7 @@ void EDIT_KeyTyped(HWND hwnd, short ch)
     }
     es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
     es->CurrCol++;
+    EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
     SetCaretPos(es->WndCol, es->WndRow * es->txtht);
     ShowCaret(hwnd);
     NOTIFY_PARENT(hwnd, EN_CHANGE);
@@ -1382,8 +1403,11 @@ void EDIT_Forward(HWND hwnd)
 
     if (*CurrChar == '\r')
     {
-	EDIT_Home(hwnd);
-	EDIT_Downward(hwnd);
+        if (es->CurrLine < (es->wlines - 1))
+        {
+	    EDIT_Home(hwnd);
+	    EDIT_Downward(hwnd);
+        }
     }
     else
     {
@@ -1549,7 +1573,7 @@ void EDIT_StickEnd(HWND hwnd)
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
     int len = EDIT_LineLength(hwnd, es->CurrLine);
     char *cp = EDIT_TextLine(hwnd, es->CurrLine);
-    char currpel;
+    int currpel;
 
     es->CurrCol = min(len, es->CurrCol);
     es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
@@ -2150,22 +2174,22 @@ void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
 	EDIT_ClearSel(hwnd);
 
     es->WndRow = HIWORD(lParam) / es->txtht;
-    if (es->WndRow > es->wlines - es->wtop - 1)
+    if (!IsMultiLine())
+        es->WndRow = 0;
+    else if (es->WndRow > es->wlines - es->wtop - 1)
     {
-	if (es->wlines)
-	    es->WndRow = es->wlines - es->wtop - 1;
-	else
-	    es->WndRow = 0;
+        es->WndRow = es->wlines - es->wtop - 1;
 	end = TRUE;
     }
     es->CurrLine = es->wtop + es->WndRow;
 
     cp = EDIT_TextLine(hwnd, es->CurrLine);
     len = EDIT_LineLength(hwnd, es->CurrLine);
-    es->WndCol = LOWORD(lParam);
-    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
-	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
+    es->WndCol = LOWORD(lParam) + es->wleft;
+    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) || end)
+	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
+    es->WndCol -= es->wleft;
 
     ButtonDown = TRUE;
     ButtonRow = es->CurrLine;
@@ -2179,9 +2203,14 @@ void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam)
 
 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
 {
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = 
+	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
+
     if (wParam != MK_LBUTTON)
 	return;
 
+    HideCaret(hwnd);
     if (ButtonDown)
     {
 	EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
@@ -2190,7 +2219,11 @@ void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
     }
 
     if (TextMarking)
+    {
 	EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
+        SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+    }
+    ShowCaret(hwnd);
 }
 
 
@@ -2297,7 +2330,7 @@ void EDIT_ClearText(HWND hwnd)
 
 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
 {
-    int so, eo;
+    INT so, eo;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2313,7 +2346,7 @@ void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
 
     if (so == eo)       /* if so == eo, set caret only */
     {
-	EDIT_GetLineCol(hwnd, so, &(es->CurrLine), &(es->CurrCol));
+	EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol));
 	es->WndRow = es->CurrLine - es->wtop;
 
 	if (!wParam)
@@ -2340,11 +2373,16 @@ void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
     }
     else                /* otherwise set selection */
     {
-	if (so > eo)
-	    swap(&so, &eo);
+	if (eo >= 0 && so > eo)	  /* eo == -1 flag to extend to end of text */
+        {
+            INT tmp;
+            tmp = so;
+            so = eo;
+            eo = tmp;
+        }
 
-	EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
-	EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
+	EDIT_GetLineCol(hwnd, (int) so, &(es->SelBegLine), &(es->SelBegCol));
+	EDIT_GetLineCol(hwnd, (int) eo, &(es->SelEndLine), &(es->SelEndCol));
 	es->CurrLine = es->SelEndLine;
 	es->CurrCol = es->SelEndCol;
 	es->WndRow = es->SelEndLine - es->wtop;
@@ -2407,7 +2445,7 @@ void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
 	return;
     }
 
-    if (off > strlen(text)) off = strlen(text);
+    if (off < 0 || off > strlen(text)) off = strlen(text);
     cp1 = text;
     for (lineno = 0; lineno < es->wlines; lineno++)
     {
@@ -2536,8 +2574,10 @@ void EDIT_SetAnchor(HWND hwnd, int row, int col)
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
 
     if (SelMarked(es))
+    {
 	sel = TRUE;
-    EDIT_ClearSel(hwnd);
+        EDIT_ClearSel(hwnd);
+    }
     es->SelBegLine = es->SelEndLine = row;
     es->SelBegCol = es->SelEndCol = col;
     if (sel)
@@ -2554,12 +2594,11 @@ void EDIT_SetAnchor(HWND hwnd, int row, int col)
  *  Extend selection to the given screen co-ordinates.
  */
 
-void EDIT_ExtendSel(HWND hwnd, int x, int y)
+void EDIT_ExtendSel(HWND hwnd, INT x, INT y)
 {
     int bbl, bel, bbc, bec;
     char *cp;
     int len, line;
-    BOOL end = FALSE;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2568,28 +2607,31 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y)
 
     bbl = es->SelEndLine;
     bbc = es->SelEndCol;
-    line = es->wtop + y / es->txtht;
-    if (line > es->wlines)
-	line = es->wlines;
+    y = max(y,0);
+    if (IsMultiLine())
+    {
+        if ((line = es->wtop + y / es->txtht) >= es->wlines)
+	    line = es->wlines - 1;
+    }
+    else
+        line = 0;
+        
     cp = EDIT_TextLine(hwnd, line);
     len = EDIT_LineLength(hwnd, line);
 
     es->WndRow = y / es->txtht;
-    if (es->WndRow > es->wlines - es->wtop - 1)
-    {
-	if (es->wlines)
-	    es->WndRow = es->wlines - es->wtop - 1;
-	else
+    if (!IsMultiLine())
 	    es->WndRow = 0;
-	end = TRUE;
-    }
+    else if (es->WndRow > es->wlines - es->wtop - 1)
+	    es->WndRow = es->wlines - es->wtop - 1;
     es->CurrLine = es->wtop + es->WndRow;
     es->SelEndLine = es->CurrLine;
 
-    es->WndCol = x;
-    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
-	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
+    es->WndCol = es->wleft + max(x,0);
+    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0))
+	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
+    es->WndCol -= es->wleft;
     es->SelEndCol = es->CurrCol;
 
     bel = es->SelEndLine;
@@ -2631,12 +2673,10 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y)
 
 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
 {
-    RECT rc;
+    RECT rc, rcInvert;
     int scol, ecol;
     char *cp;
     HDC hdc;
-    HBRUSH hbrush, holdbrush;
-    int olddm;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2660,20 +2700,19 @@ void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
      * lines.  I have kludged this by adding on two pixels to ecol and
      * to the line height in the call to Rectangle.
      */
-    scol = EDIT_StrLength(hwnd, cp, start, 0);
+    scol = EDIT_StrLength(hwnd, cp, start, 0) - es->wleft;
     if (scol > rc.right) return;
     if (scol < rc.left) scol = rc.left;
-    ecol = EDIT_StrLength(hwnd, cp, end, 0) + 2;   /* ??? */
+    ecol = EDIT_StrLength(hwnd, cp, end, 0) - es->wleft;
     if (ecol < rc.left) return;
     if (ecol > rc.right) ecol = rc.right;
 
     hdc = GetDC(hwnd);
-    hbrush = GetStockObject(BLACK_BRUSH);
-    holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
-    olddm = SetROP2(hdc, R2_XORPEN);
-    Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht + 2);
-    SetROP2(hdc, olddm);
-    SelectObject(hdc, (HANDLE)holdbrush);
+    rcInvert.left = scol;
+    rcInvert.top = y * es->txtht;
+    rcInvert.right = ecol;
+    rcInvert.bottom = (y + 1) * es->txtht;
+    InvertRect(hdc, (LPRECT) &rcInvert);
     ReleaseDC(hwnd, hdc);
 }
 
@@ -2931,7 +2970,10 @@ void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
 
-    es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
+    if (!es->hDeletedText)
+        es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len );
+    else 
+        es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
     if (!es->hDeletedText) return;
     text = (char *)GlobalLock(es->hDeletedText);
     memcpy(text, deltext, len);
diff --git a/controls/listbox.c b/controls/listbox.c
index ebfab3aa566dfc1b6612b7e951c03775900c51e4..58d204c762b1f7b1ecd9b27889a5061d965cc74d 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -2,6 +2,7 @@
  * Interface code to listbox widgets
  *
  * Copyright  Martin Ayotte, 1993
+ * Copyright  Constantine Sapuntzakis, 1995
  *
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 */
@@ -23,11 +24,11 @@ static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
 #define GMEM_ZEROINIT 0x0040
 
-
+LPLISTSTRUCT ListBoxGetItem (HWND hwnd, UINT uIndex);
+int ListBoxScrolltoFocus(HWND hwnd);
 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
-void StdDrawListBox(HWND hwnd);
-void OwnerDrawListBox(HWND hwnd);
+void RepaintListBox(HWND hwnd);
 int ListBoxFindMouse(HWND hwnd, int X, int Y);
 int CreateListBoxStruct(HWND hwnd);
 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
@@ -50,10 +51,13 @@ int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
 int ListMaxFirstVisible(LPHEADLIST lphl);
 void ListBoxSendNotification(HWND hwnd, WORD code);
 
-#define HasStrings(wndPtr) ( \
-  ( ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) && \
-    ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE) ) || \
-  ((wndPtr->dwStyle & LBS_HASSTRINGS) == LBS_HASSTRINGS) )
+#define OWNER_DRAWN(wndPtr) \
+  ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) ||  \
+   (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE))
+
+#define HasStrings(wndPtr) (  \
+  (! OWNER_DRAWN (wndPtr)) || \
+  (wndPtr->dwStyle & LBS_HASSTRINGS))
 
 #if 0
 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
@@ -68,724 +72,1436 @@ void ListBoxSendNotification(HWND hwnd, WORD code);
 
 #define LIST_HEAP_SIZE 0x10000
 
+/* Design notes go here */
+
+LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+
+
+typedef struct {
+  WORD   message;
+  LONG  (*handler)(HWND, WORD, WPARAM, LPARAM);
+} msg_tbl;
+
+static msg_tbl methods[] = {
+  {WM_CREATE, LBCreate},
+  {WM_DESTROY, LBDestroy},
+  {WM_GETDLGCODE, LBGetDlgCode},
+  {WM_VSCROLL, LBVScroll},
+  {WM_HSCROLL, LBHScroll},
+  {WM_LBUTTONDOWN, LBLButtonDown},
+  {WM_LBUTTONUP, LBLButtonUp},
+  {WM_RBUTTONUP, LBRButtonUp},
+  {WM_LBUTTONDBLCLK, LBRButtonUp},
+  {WM_MOUSEMOVE, LBMouseMove},
+  {WM_KEYDOWN, LBKeyDown},
+  {WM_SETFONT, LBSetFont},
+  {WM_SETREDRAW, LBSetRedraw},
+  {WM_PAINT, LBPaint},
+  {WM_SETFOCUS, LBSetFocus},
+  {WM_KILLFOCUS, LBKillFocus},
+  {LB_RESETCONTENT, LBResetContent},
+  {LB_DIR, LBDir},
+  {LB_ADDSTRING, LBAddString},
+  {LB_INSERTSTRING, LBInsertString},
+  {LB_DELETESTRING, LBDeleteString},
+  {LB_FINDSTRING, LBFindString},
+  {LB_GETCARETINDEX, LBGetCaretIndex},
+  {LB_GETCOUNT, LBGetCount},
+  {LB_GETCURSEL, LBGetCurSel},
+  {LB_GETHORIZONTALEXTENT, LBGetHorizontalExtent},
+  {LB_GETITEMDATA, LBGetItemData},
+  {LB_GETITEMHEIGHT, LBGetItemHeight},
+  {LB_GETITEMRECT, LBGetItemRect},
+  {LB_GETSEL, LBGetSel},
+  {LB_GETSELCOUNT, LBGetSelCount},
+  {LB_GETSELITEMS, LBGetSelItems},
+  {LB_GETTEXT, LBGetText},
+  {LB_GETTEXTLEN, LBGetTextLen},
+  {LB_GETTOPINDEX, LBGetTopIndex},
+  {LB_SELECTSTRING, LBSelectString},
+  {LB_SELITEMRANGE, LBSelItemRange},
+  {LB_SETCARETINDEX, LBSetCaretIndex},
+  {LB_SETCOLUMNWIDTH, LBSetColumnWidth},
+  {LB_SETHORIZONTALEXTENT, LBSetHorizontalExtent},
+  {LB_SETITEMDATA, LBSetItemData},
+  {LB_SETTABSTOPS, LBSetTabStops},
+  {LB_SETCURSEL, LBSetCurSel},
+  {LB_SETSEL, LBSetSel},
+  {LB_SETTOPINDEX, LBSetTopIndex},
+  {LB_SETITEMHEIGHT, LBSetItemHeight}
+};
+
 /***********************************************************************
- *           ListBoxWndProc 
+ *           LBCreate
  */
-LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
-{    
-	WND  *wndPtr;
-	LPHEADLIST  lphl;
-	HWND	hWndCtl;
-	WORD	wRet;
-	LONG	lRet;
-	RECT	rect;
-	int		y;
-	CREATESTRUCT *createStruct;
-	static RECT rectsel;
-    switch(message) {
-	case WM_CREATE:
-		CreateListBoxStruct(hwnd);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
-		if (lphl == NULL) return 0;
-		createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
-		if (HIWORD(createStruct->lpCreateParams) != 0)
-			lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
-		else
-			lphl->hWndLogicParent = GetParent(hwnd);
-		lphl->hFont = GetStockObject(SYSTEM_FONT);
-		lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
-                SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
-                SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
-			}
-		return 0;
-	case WM_DESTROY:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		ListBoxResetContent(hwnd);
-		/* XXX need to free lphl->Heap */
-		free(lphl);
-		*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
-		dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
-		return 0;
-
-	case WM_VSCROLL:
-		dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
-				wParam, lParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return 0;
-		y = lphl->FirstVisible;
-		switch(wParam) {
-			case SB_LINEUP:
-				if (lphl->FirstVisible > 1)	
-					lphl->FirstVisible--;
-				break;
-			case SB_LINEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
-					lphl->FirstVisible++;
-				break;
-			case SB_PAGEUP:
-				if (lphl->FirstVisible > 1)  
-					lphl->FirstVisible -= lphl->ItemsVisible;
-				break;
-			case SB_PAGEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))  
-					lphl->FirstVisible += lphl->ItemsVisible;
-				break;
-			case SB_THUMBTRACK:
-				lphl->FirstVisible = LOWORD(lParam);
-				break;
-			}
-		if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
-		if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-			lphl->FirstVisible = ListMaxFirstVisible(lphl);
-		if (y != lphl->FirstVisible) {
-			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-			InvalidateRect(hwnd, NULL, TRUE);
-			UpdateWindow(hwnd);
-			}
-		return 0;
-	
-	case WM_HSCROLL:
-		dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
-				wParam, lParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return 0;
-		y = lphl->FirstVisible;
-		switch(wParam) {
-			case SB_LINEUP:
-				if (lphl->FirstVisible > 1)
-					lphl->FirstVisible -= lphl->ItemsPerColumn;
-				break;
-			case SB_LINEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
-					lphl->FirstVisible += lphl->ItemsPerColumn;
-				break;
-			case SB_PAGEUP:
-				if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
-					lphl->FirstVisible -= lphl->ItemsVisible /
-					lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-				break;
-			case SB_PAGEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
-							lphl->ItemsPerColumn != 0)  
-					lphl->FirstVisible += lphl->ItemsVisible /
-					lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-				break;
-			case SB_THUMBTRACK:
-				lphl->FirstVisible = lphl->ItemsPerColumn * 
-								(LOWORD(lParam) - 1) + 1;
-				break;
-			}
-		if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
-		if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-			lphl->FirstVisible = ListMaxFirstVisible(lphl);
-		if (lphl->ItemsPerColumn != 0) {
-			lphl->FirstVisible = lphl->FirstVisible /
-				lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
-			if (y != lphl->FirstVisible) {
-				SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
-				lphl->ItemsPerColumn + 1, TRUE);
-				InvalidateRect(hwnd, NULL, TRUE);
-				UpdateWindow(hwnd);
-				}
-			}
-		return 0;
-	
-	case WM_LBUTTONDOWN:
-		SetFocus(hwnd);
-		SetCapture(hwnd);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		lphl->PrevFocused = lphl->ItemFocused;
-	        y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-		if (y==-1)
-		    return 0;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		    lphl->ItemFocused = y;
-		    wRet = ListBoxGetSel(hwnd, y);
-		    ListBoxSetSel(hwnd, y, !wRet);
-		    }
-		else
-		    ListBoxSetCurSel(hwnd, y);
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL)
-		  ListBoxSendNotification( hwnd, LBN_SELCHANGE );
-		ListBoxGetItemRect(hwnd, y, &rectsel);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return 0;
-	case WM_LBUTTONUP:
-		ReleaseCapture();
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if (lphl->PrevFocused != lphl->ItemFocused)
-		  ListBoxSendNotification( hwnd, LBN_SELCHANGE );
-		return 0;
-	case WM_RBUTTONUP:
-	case WM_LBUTTONDBLCLK:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
-										MAKELONG(hwnd, LBN_DBLCLK));
-		return 0;
-	case WM_MOUSEMOVE:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if ((wParam & MK_LBUTTON) != 0) {
-			y = HIWORD(lParam);
-			if (y < 4) {
-				if (lphl->FirstVisible > 1) {
-					lphl->FirstVisible--;
-					SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					break;
-					}
-				}
-			GetClientRect(hwnd, &rect);
-			if (y > (rect.bottom - 4)) {
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
-					lphl->FirstVisible++;
-					SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					break;
-					}
-				}
-			if ((y > 0) && (y < (rect.bottom - 4))) {
-				if ((y < rectsel.top) || (y > rectsel.bottom)) {
-					wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-					if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-						lphl->ItemFocused = wRet;
-						ListBoxSendNotification(hwnd, LBN_SELCHANGE);
-						}
-					else
-						ListBoxSetCurSel(hwnd, wRet);
-					ListBoxGetItemRect(hwnd, wRet, &rectsel);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					}
-				}
-			}
-		break;
-	case WM_KEYDOWN:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		switch(wParam) {
-			case VK_TAB:
-				hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
-					hwnd, !(GetKeyState(VK_SHIFT) < 0));
-				SetFocus(hWndCtl);
-				if(debugging_listbox){
-				if ((GetKeyState(VK_SHIFT) < 0))
-					dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
-				else
-					dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
-				}
-				break;
-			case VK_HOME:
-				lphl->ItemFocused = 0;
-				break;
-			case VK_END:
-				lphl->ItemFocused = lphl->ItemsCount - 1;
-				break;
-			case VK_LEFT:
-				if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-					lphl->ItemFocused -= lphl->ItemsPerColumn;
-					}
-				break;
-			case VK_UP:
-				lphl->ItemFocused--;
-				break;
-			case VK_RIGHT:
-				if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-					lphl->ItemFocused += lphl->ItemsPerColumn;
-					}
-				break;
-			case VK_DOWN:
-				lphl->ItemFocused++;
-				break;
-			case VK_PRIOR:
-				lphl->ItemFocused -= lphl->ItemsVisible;
-				break;
-			case VK_NEXT:
-				lphl->ItemFocused += lphl->ItemsVisible;
-				break;
-			case VK_SPACE:
-				wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
-				ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
-				break;
-			default:
-				ListBoxFindNextMatch(hwnd, wParam);
-				return 0;
-			}
-		if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
-		if (lphl->ItemFocused >= lphl->ItemsCount)
-			lphl->ItemFocused = lphl->ItemsCount - 1;
-		lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible * 
-											lphl->ItemsVisible + 1;
-		if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
-			ListBoxSetCurSel(hwnd, lphl->ItemFocused);
-			ListBoxSendNotification(hwnd, LBN_SELCHANGE);
-			}
-                SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
-	case WM_SETFONT:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if (wParam == 0)
-			lphl->hFont = GetStockObject(SYSTEM_FONT);
-		else
-			lphl->hFont = wParam;
-		if (wParam == 0) break;
-		break;
-	case WM_SETREDRAW:
-		dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		lphl->bRedrawFlag = wParam;
-		break;
-	case WM_PAINT:
-		wndPtr = WIN_FindWndPtr(hwnd);
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
-			OwnerDrawListBox(hwnd);
-			break;
-			}
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
-			OwnerDrawListBox(hwnd);
-			break;
-			}
-		StdDrawListBox(hwnd);
-		break;
-	case WM_SETFOCUS:
-		dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		break;
-	case WM_KILLFOCUS:
-		dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
+LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-    case LB_RESETCONTENT:
-		dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
-		ListBoxResetContent(hwnd);
-		return 0;
-    case LB_DIR:
-		dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
-		wRet = ListBoxDirectory(hwnd, wParam,
-                                        (LPSTR)PTR_SEG_TO_LIN(lParam));
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_ADDSTRING:
-		wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_GETTEXT:
-		dprintf_listbox(stddeb, "LB_GETTEXT  wParam=%d\n",wParam);
-		wRet = ListBoxGetText(hwnd, wParam,
-                                      (LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
-                return wRet;
-	case LB_INSERTSTRING:
-		wRet = ListBoxInsertString(hwnd, wParam,
-                                           (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_DELETESTRING:
-		wRet = ListBoxDeleteString(hwnd, wParam);
-		return wRet;
-	case LB_FINDSTRING:
-		wRet = ListBoxFindString(hwnd, wParam,
-                                         (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_GETCARETINDEX:
-		return wRet;
-	case LB_GETCOUNT:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		return lphl->ItemsCount;
-	case LB_GETCURSEL:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n", 
-				lphl->ItemFocused);
-		return lphl->ItemFocused;
-	case LB_GETHORIZONTALEXTENT:
-		return wRet;
-	case LB_GETITEMDATA:
-		dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
-		lRet = ListBoxGetText(hwnd, wParam,
-                                      (LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
-		return lRet;
-	case LB_GETITEMHEIGHT:
-                ListBoxGetItemRect(hwnd, wParam, &rect);
-                return (rect.bottom - rect.top);
-	case LB_GETITEMRECT:
-                ListBoxGetItemRect(hwnd,wParam,(LPRECT)PTR_SEG_TO_LIN(lParam));
-                return 0;
-	case LB_GETSEL:
-		wRet = ListBoxGetSel(hwnd, wParam);
-		return wRet;
-	case LB_GETSELCOUNT:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		return lphl->SelCount;
-	case LB_GETSELITEMS:
-		return wRet;
-	case LB_GETTEXTLEN:
-		return wRet;
-	case LB_GETTOPINDEX:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		return lphl->FirstVisible;
-	case LB_SELECTSTRING:
-		return wRet;
-	case LB_SELITEMRANGE:
-		return wRet;
-	case LB_SETCARETINDEX:
-		return wRet;
-	case LB_SETCOLUMNWIDTH:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		lphl->ColumnsWidth = wParam;
-		break;
-	case LB_SETHORIZONTALEXTENT:
-		return wRet;
-	case LB_SETITEMDATA:
-		dprintf_listbox(stddeb, "LB_SETITEMDATA  wParam=%x  lParam=%lx\n", wParam, lParam);
-		wRet = ListBoxSetItemData(hwnd, wParam, lParam);
-		return wRet;
-	case LB_SETTABSTOPS:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		lphl->FirstVisible = wParam;
-		return 0;
-	case LB_SETCURSEL:
-		dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", 
-				wParam);
-		wRet = ListBoxSetCurSel(hwnd, wParam);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_SETSEL:
-		dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
-		wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_SETTOPINDEX:
-		dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
-				wParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		lphl->FirstVisible = wParam;
-                SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
-	case LB_SETITEMHEIGHT:
-		dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
-		wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
-		return wRet;
+{
+  LPHEADLIST  lphl;
+  CREATESTRUCT *createStruct;
+  WND          *wndPtr;
 
-	default:
-		return DefWindowProc( hwnd, message, wParam, lParam );
-    }
-return 0;
+  CreateListBoxStruct(hwnd);
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
+
+  if (lphl == NULL) return 0;
+
+  createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
+
+  if (HIWORD(createStruct->lpCreateParams) != 0)
+    lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
+  else
+    lphl->hWndLogicParent = GetParent(hwnd);
+
+  lphl->hFont = GetStockObject(SYSTEM_FONT);
+  lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+  SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
+
+  return 0;
 }
 
+int CreateListBoxStruct(HWND hwnd)
 
-LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
 {
-    WND  *Ptr;
-    LPHEADLIST lphl;
-    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
-    lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
-    return lphl;
+  WND  *wndPtr;
+  LPHEADLIST lphl;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
+  *((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;
+
+  lphl->lpFirst        = NULL;
+  lphl->ItemsCount     = 0;
+  lphl->ItemsVisible   = 0;
+  lphl->FirstVisible   = 1;
+  lphl->ColumnsVisible = 1;
+  lphl->ItemsPerColumn = 0;
+  lphl->StdItemHeight  = 15;
+  lphl->ItemFocused    = -1;
+  lphl->PrevFocused    = -1;
+  lphl->DrawCtlType    = ODT_LISTBOX;
+  lphl->bRedrawFlag    = TRUE;
+  lphl->iNumStops      = 0;
+  lphl->TabStops       = NULL;
+
+  if (OWNER_DRAWN(wndPtr)) 
+    lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
+  else
+    lphl->hDrawItemStruct = 0;
+
+#if 0
+  HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
+  HeapBase = GlobalLock(HeapHandle);
+  HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
+#endif
+  return TRUE;
 }
 
 
-LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
+/***********************************************************************
+ *           LBDestroy
+ */
+LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
 {
-    WND  *wndPtr;
-    LPHEADLIST lphl;
-    wndPtr = WIN_FindWndPtr(hwnd);
-    lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
-    return lphl;
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return 0;
+  ListBoxResetContent(hwnd);
+
+  if (lphl->hDrawItemStruct)
+    USER_HEAP_FREE(lphl->hDrawItemStruct);
+
+  /* XXX need to free lphl->Heap */
+  free(lphl);
+  *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
+  dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
+  return 0;
 }
 
+/* get the maximum value of lphl->FirstVisible */
+int ListMaxFirstVisible(LPHEADLIST lphl)
+{
+    int m = lphl->ItemsCount-lphl->ItemsVisible+1;
+    return (m < 1) ? 1 : m;
+}
+
+
+/***********************************************************************
+ *           LBVScroll
+ */
+LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-void StdDrawListBox(HWND hwnd)
 {
-	WND 	*wndPtr;
-	LPHEADLIST  lphl;
-	LPLISTSTRUCT lpls;
-	PAINTSTRUCT ps;
-	HBRUSH 	hBrush;
-	int 	OldBkMode;
-	DWORD 	dwOldTextColor;
-	HDC 	hdc;
-	RECT 	rect;
-	int     i, h, h2, maxwidth, ipc;
-	h = 0;
-	hdc = BeginPaint( hwnd, &ps );
-	if (!IsWindowVisible(hwnd)) {
-		EndPaint( hwnd, &ps );
-		return;
-		}
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-	if (lphl == NULL) goto EndOfPaint;
-	if (!lphl->bRedrawFlag) goto EndOfPaint;
-	SelectObject(hdc, lphl->hFont);
-	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
-		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
-	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	GetClientRect(hwnd, &rect);
-	FillRect(hdc, &rect, hBrush);
-	maxwidth = rect.right;
-	rect.right = lphl->ColumnsWidth;
-	if (lphl->ItemsCount == 0) goto EndOfPaint;
-	lpls = lphl->lpFirst;
-	if (lpls == NULL) goto EndOfPaint;
-	lphl->ItemsVisible = 0;
-	lphl->ItemsPerColumn = ipc = 0;
-	for(i = 1; i <= lphl->ItemsCount; i++) {
-	    if (i >= lphl->FirstVisible) {
-	        if (lpls == NULL) break;
-		if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
-		    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-			lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
-			ipc = 0;
-			h = 0;
-			rect.left += lphl->ColumnsWidth;
-			rect.right += lphl->ColumnsWidth;
-			if (rect.left > maxwidth) break;
-			}
-		    else 
-			break;
-		    }
-		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-		lpls->dis.rcItem.top = h;
-		lpls->dis.rcItem.bottom = h + h2;
-		lpls->dis.rcItem.left = rect.left;
-		lpls->dis.rcItem.right = rect.right;
-		OldBkMode = SetBkMode(hdc, TRANSPARENT);
-		if (lpls->dis.itemState != 0) {
-			dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
-		    FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
-		    }
-		TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->itemText, 
-			strlen((char *)lpls->itemText));
-		if (lpls->dis.itemState != 0) {
-			SetTextColor(hdc, dwOldTextColor);
-		    }
-		SetBkMode(hdc, OldBkMode);
-		if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
-		    DrawFocusRect(hdc, &lpls->dis.rcItem);
-		    }
-		h += h2;
-		lphl->ItemsVisible++;
-		ipc++;
-		}
-	    if (lpls->lpNext == NULL) goto EndOfPaint;
-	    lpls = (LPLISTSTRUCT)lpls->lpNext;
-	}
-EndOfPaint:
-    EndPaint( hwnd, &ps );
+  LPHEADLIST lphl;
+  int  y;
+
+  dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
+		  wParam, lParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return 0;
+  y = lphl->FirstVisible;
+
+  switch(wParam) {
+  case SB_LINEUP:
+    if (lphl->FirstVisible > 1)	
+      lphl->FirstVisible--;
+    break;
+
+  case SB_LINEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
+      lphl->FirstVisible++;
+    break;
+
+  case SB_PAGEUP:
+    if (lphl->FirstVisible > 1)  
+      lphl->FirstVisible -= lphl->ItemsVisible;
+    break;
+
+  case SB_PAGEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))  
+      lphl->FirstVisible += lphl->ItemsVisible;
+    break;
+
+  case SB_THUMBTRACK:
+    lphl->FirstVisible = LOWORD(lParam);
+    break;
+  }
+
+  if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if (y != lphl->FirstVisible) {
+    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+  return 0;
 }
 
+/***********************************************************************
+ *           LBHScroll
+ */
+LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  int        y;
+
+  dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
+		  wParam, lParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return 0;
+  y = lphl->FirstVisible;
+  switch(wParam) {
+  case SB_LINEUP:
+    if (lphl->FirstVisible > 1)
+      lphl->FirstVisible -= lphl->ItemsPerColumn;
+    break;
+  case SB_LINEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
+      lphl->FirstVisible += lphl->ItemsPerColumn;
+    break;
+  case SB_PAGEUP:
+    if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
+      lphl->FirstVisible -= lphl->ItemsVisible /
+	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+    break;
+  case SB_PAGEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
+	lphl->ItemsPerColumn != 0)  
+      lphl->FirstVisible += lphl->ItemsVisible /
+	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+    break;
+  case SB_THUMBTRACK:
+    lphl->FirstVisible = lphl->ItemsPerColumn * 
+      (LOWORD(lParam) - 1) + 1;
+    break;
+  } 
+  if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if (lphl->ItemsPerColumn != 0) {
+    lphl->FirstVisible = lphl->FirstVisible /
+      lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
+    if (y != lphl->FirstVisible) {
+      SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
+		   lphl->ItemsPerColumn + 1, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+      UpdateWindow(hwnd);
+    }
+  }
+  return 0;
+}
 
+/***********************************************************************
+ *           LBLButtonDown
+ */
+LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-void OwnerDrawListBox(HWND hwnd)
 {
-	WND 	*wndPtr,*ParentWndPtr;
-	LPHEADLIST  lphl;
-	LPLISTSTRUCT lpls;
-	PAINTSTRUCT ps;
-	HBRUSH 	hBrush;
-	DWORD   itemData;
-	HDC 	hdc;
-	RECT 	rect;
-	int     i, h, h2, maxwidth;
-        HANDLE hDrawItemStruct;
-	h = 0;
-	hdc = BeginPaint(hwnd, &ps);
-	if (!IsWindowVisible(hwnd)) {
-		EndPaint( hwnd, &ps );
-		return;
-		}
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-	if (lphl == NULL) goto EndOfPaint;
-	if (!lphl->bRedrawFlag) goto EndOfPaint;
-	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
-		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
-	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	GetClientRect(hwnd, &rect);
-	FillRect(hdc, &rect, hBrush);
-	maxwidth = rect.right;
-	rect.right = lphl->ColumnsWidth;
-	if (lphl->ItemsCount == 0) goto EndOfPaint;
-	lpls = lphl->lpFirst;
-	if (lpls == NULL) goto EndOfPaint;
-	lphl->ItemsVisible = 0;
-        hDrawItemStruct = USER_HEAP_ALLOC( sizeof(DRAWITEMSTRUCT) );
-	for (i = 1; i <= lphl->ItemsCount; i++) {
-	    if (i >= lphl->FirstVisible) {
-		lpls->dis.hDC = hdc;
-		lpls->dis.hwndItem = hwnd;
-		lpls->dis.CtlType = ODT_LISTBOX;
-		lpls->dis.itemID = i - 1;
-		if ((!lpls->dis.CtlID) && (lphl->hWndLogicParent)) {
-			ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
-			lpls->dis.CtlID = ParentWndPtr->wIDmenu;
-			}
-		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-		lpls->dis.rcItem.top = h;
-		lpls->dis.rcItem.bottom = h + h2;
-		lpls->dis.rcItem.left = rect.left;
-		lpls->dis.rcItem.right = rect.right;
-		lpls->dis.itemAction = ODA_DRAWENTIRE;
-/*		if (lpls->dis.itemState != 0) {
-		    lpls->dis.itemAction |= ODA_SELECT;
-		    }
-		if (lphl->ItemFocused == i - 1) {
-		    lpls->dis.itemAction |= ODA_FOCUS;
-		    }*/
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n", 
-			i-1, lpls->dis.rcItem.left, lpls->dis.rcItem.top, 
-			lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM &dis=%lX CtlID=%u !\n", 
-			(LONG)&lpls->dis, lpls->dis.CtlID);
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM %08lX!\n",lpls->dis.itemData);
-		if (HasStrings(wndPtr))
-		  dprintf_listbox(stddeb,"  '%s'\n",lpls->itemText);
-		if (HasStrings(wndPtr)) {
-			itemData = lpls->dis.itemData;
-			lpls->dis.itemData = (DWORD)lpls->itemText;
-			}
-                memcpy( USER_HEAP_LIN_ADDR(hDrawItemStruct), &lpls->dis,
-                        sizeof(DRAWITEMSTRUCT) );
-		SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, 
-                            i-1, (LPARAM)USER_HEAP_SEG_ADDR(hDrawItemStruct));
-		if (HasStrings(wndPtr))
-			lpls->dis.itemData = itemData;
-
-/*		if (lpls->dis.itemState != 0) {
-  		    InvertRect(hdc, &lpls->dis.rcItem);  
-		    }  */
-		h += h2;
-		lphl->ItemsVisible++;
-		/* if (h > rect.bottom) goto EndOfPaint;*/
-		}
-	    if (lpls->lpNext == NULL) break;
-	    lpls = (LPLISTSTRUCT)lpls->lpNext;
-	}
-        USER_HEAP_FREE( hDrawItemStruct );
-EndOfPaint:
-        EndPaint( hwnd, &ps );
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+  WORD       wRet;
+  int        y;
+  RECT       rectsel;
+
+  SetFocus(hwnd);
+  SetCapture(hwnd);
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+
+  lphl->PrevFocused = lphl->ItemFocused;
+
+  y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+  if (y==-1)
+    return 0;
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL) {
+    lphl->ItemFocused = y;
+    wRet = ListBoxGetSel(hwnd, y);
+    ListBoxSetSel(hwnd, y, !wRet);
+  }
+  else
+    ListBoxSetCurSel(hwnd, y);
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL)
+    ListBoxSendNotification( hwnd, LBN_SELCHANGE );
+
+  ListBoxGetItemRect(hwnd, y, &rectsel);
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
 }
 
+/***********************************************************************
+ *           LBLButtonUp
+ */
+LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND        *wndPtr;
 
+  ReleaseCapture();
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  if (lphl->PrevFocused != lphl->ItemFocused)
+    ListBoxSendNotification( hwnd, LBN_SELCHANGE );
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBRButtonUp
+ */
+LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-int ListBoxFindMouse(HWND hwnd, int X, int Y)
 {
-    WND 		*wndPtr;
-    LPHEADLIST 		lphl;
-    LPLISTSTRUCT	lpls;
-    RECT 		rect;
-    int                 i, h, h2, w, w2;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (lphl->ItemsCount == 0) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+  
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
+		MAKELONG(hwnd, LBN_DBLCLK));
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBMouseMove
+ */
+LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+  int  y;
+  WORD        wRet;
+  RECT        rect, rectsel;   /* XXX Broken */
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  if ((wParam & MK_LBUTTON) != 0) {
+    y = HIWORD(lParam);
+    if (y < 4) {
+      if (lphl->FirstVisible > 1) {
+	lphl->FirstVisible--;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return 0;
+      }
+    }
     GetClientRect(hwnd, &rect);
-    h = w2 = 0;
-    w = lphl->ColumnsWidth;
-    for(i = 1; i <= lphl->ItemsCount; i++) {
-	if (i >= lphl->FirstVisible) {
-	    h2 = h;
-	    h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-	    if ((Y > h2) && (Y < h) &&
-		(X > w2) && (X < w)) return(i - 1);
-	    if (h > rect.bottom) {
-		if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
-		h = 0;
-		w2 = w;
-		w += lphl->ColumnsWidth;
-		if (w2 > rect.right) return LB_ERR;
-		}
-	    }
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
+    if (y > (rect.bottom - 4)) {
+      if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
+	lphl->FirstVisible++;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return 0;
+      }
+    }
+    if ((y > 0) && (y < (rect.bottom - 4))) {
+      if ((y < rectsel.top) || (y > rectsel.bottom)) {
+	wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	  lphl->ItemFocused = wRet;
+	  ListBoxSendNotification(hwnd, LBN_SELCHANGE);
 	}
-    return(LB_ERR);
+	else
+	  ListBoxSetCurSel(hwnd, wRet);
+	ListBoxGetItemRect(hwnd, wRet, &rectsel);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+      }
+    }
+  }
+
+  return 0;
 }
 
+/***********************************************************************
+ *           LBKeyDown
+ */
+LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+  HWND        hWndCtl;
+  WORD        wRet;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  switch(wParam) {
+  case VK_TAB:
+    hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
+				hwnd, !(GetKeyState(VK_SHIFT) < 0));
+    SetFocus(hWndCtl);
+    if(debugging_listbox){
+      if ((GetKeyState(VK_SHIFT) < 0))
+	dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
+      else
+	dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
+    }
+    break;
+  case VK_HOME:
+    lphl->ItemFocused = 0;
+    break;
+  case VK_END:
+    lphl->ItemFocused = lphl->ItemsCount - 1;
+    break;
+  case VK_LEFT:
+    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+      lphl->ItemFocused -= lphl->ItemsPerColumn;
+    }
+    break;
+  case VK_UP:
+    lphl->ItemFocused--;
+    break;
+  case VK_RIGHT:
+    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+      lphl->ItemFocused += lphl->ItemsPerColumn;
+    }
+    break;
+  case VK_DOWN:
+    lphl->ItemFocused++;
+    break;
+  case VK_PRIOR:
+    lphl->ItemFocused -= lphl->ItemsVisible;
+    break;
+  case VK_NEXT:
+    lphl->ItemFocused += lphl->ItemsVisible;
+    break;
+  case VK_SPACE:
+    wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
+    ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
+    break;
+  default:
+    ListBoxFindNextMatch(hwnd, wParam);
+    return 0;
+  }
+
+  if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
+  if (lphl->ItemFocused >= lphl->ItemsCount)
+    lphl->ItemFocused = lphl->ItemsCount - 1;
 
+  if (lphl->ItemsVisible != 0)
+    lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible * 
+      lphl->ItemsVisible + 1;
+
+  if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
+    ListBoxSetCurSel(hwnd, lphl->ItemFocused);
+    ListBoxSendNotification(hwnd, LBN_SELCHANGE);
+  }
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetRedraw
+ */
+LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-int CreateListBoxStruct(HWND hwnd)
 {
-	WND  *wndPtr;
-	LPHEADLIST lphl;
-	wndPtr = WIN_FindWndPtr(hwnd);
-	lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
-	lphl->lpFirst = NULL;
-	*((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;     /* HEAD of List */
-	lphl->ItemsCount = 0;
-	lphl->ItemsVisible = 0;
-	lphl->FirstVisible = 1;
-	lphl->ColumnsVisible = 1;
-	lphl->ItemsPerColumn = 0;
-	lphl->StdItemHeight = 15;
-	lphl->ItemFocused = 0;
-	lphl->PrevFocused = 0;
-	lphl->SelCount = 0;
-	lphl->DrawCtlType = ODT_LISTBOX;
-	lphl->bRedrawFlag = TRUE;
-#if 0
-	HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
-	HeapBase = GlobalLock(HeapHandle);
-	HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
-#endif
-	return TRUE;
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  lphl->bRedrawFlag = wParam;
+
+  return 0;
 }
 
+/***********************************************************************
+ *           LBSetFont
+ */
+
+LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)  
 {
-	MEASUREITEMSTRUCT 	*lpmeasure;
-	HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
-	lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
-	if (lpmeasure == NULL) {
-		fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
-		return;
-		}
-	lpmeasure->CtlType = ODT_LISTBOX;
-	lpmeasure->CtlID = wndPtr->wIDmenu;
-	lpmeasure->itemID = lpls->dis.itemID;
-	lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
-	lpmeasure->itemHeight = 0;
-	if (HasStrings(wndPtr))
-		lpmeasure->itemData = (DWORD)lpls->itemText;
-	else
-		lpmeasure->itemData = lpls->dis.itemData;
-	SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
-                    0, USER_HEAP_SEG_ADDR(hTemp));
-	lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
-	lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
-	USER_HEAP_FREE(hTemp);			
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+
+  if (wParam == 0)
+    lphl->hFont = GetStockObject(SYSTEM_FONT);
+  else
+    lphl->hFont = wParam;
+
+  return 0;
 }
 
+/***********************************************************************
+ *           LBPaint
+ */
+LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-int ListBoxAddString(HWND hwnd, LPSTR newstr)
 {
-    LPHEADLIST	lphl;
-    UINT	pos = (UINT) -1;
-    WND		*wndPtr;
-    
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
+  RepaintListBox(hwnd);
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetFocus
+ */
+LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND       *wndPtr;
+
+  dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBKillFocus
+ */
+LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  
+  return 0;
+}
+
+/***********************************************************************
+ *           LBResetContent
+ */
+LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
+  ListBoxResetContent(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBDir
+ */
+LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD   wRet;
+  dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
+
+  wRet = ListBoxDirectory(hwnd, wParam,
+			  (LPSTR)PTR_SEG_TO_LIN(lParam));
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBAddString
+ */
+LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD  wRet;
+  WND  *wndPtr;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (HasStrings(wndPtr))
+    wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
+  else
+    wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBGetText
+ */
+LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LONG   wRet;
+
+  dprintf_listbox(stddeb, "LB_GETTEXT  wParam=%d\n",wParam);
+  wRet = ListBoxGetText(hwnd, wParam,
+			(LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBInsertString
+ */
+LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD  wRet;
+  WND  *wndPtr;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (HasStrings(wndPtr))
+    wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
+  else
+    wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBDeleteString
+ */    
+LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxDeleteString(hwnd, wParam); 
+}
+
+/***********************************************************************
+ *           LBFindString
+ */
+LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxFindString(hwnd, wParam,
+			   (LPSTR)PTR_SEG_TO_LIN(lParam));
+}
+
+/***********************************************************************
+ *           LBGetCaretIndex
+ */
+LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+
+  return lphl->ItemFocused;
+}
+
+/***********************************************************************
+ *           LBGetCount
+ */
+LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  return lphl->ItemsCount;
+}
+
+/***********************************************************************
+ *           LBGetCurSel
+ */
+LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n", 
+		  lphl->ItemFocused);
+  return lphl->ItemFocused;
+}
+
+/***********************************************************************
+ *           LBGetHorizontalExtent
+ */
+LONG LBGetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{    
+  return 0;
+}
+
+/***********************************************************************
+ *           LBGetItemData
+ */
+LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+    dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
+    return ListBoxGetText(hwnd, wParam,
+			  (LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
+}
+
+/***********************************************************************
+ *           LBGetItemHeight
+ */
+LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  RECT   rect;
+
+  ListBoxGetItemRect(hwnd, wParam, &rect);
+  return (rect.bottom - rect.top);
+}
+
+/***********************************************************************
+ *           LBGetItemRect
+ */
+LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxGetItemRect (hwnd, wParam, PTR_SEG_TO_LIN(lParam));
+}
+
+/***********************************************************************
+ *           LBGetSel
+ */
+LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxGetSel (hwnd, wParam);
+}
+
+/***********************************************************************
+ *           LBGetSelCount
+ */
+LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  int          cnt = 0;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+
+  while (lpls != NULL) {
+    if (lpls->dis.itemState > 0) cnt++;
+
+    lpls = lpls->lpNext;
+  }
+
+  return cnt;
+}
+
+/***********************************************************************
+ *           LBGetSelItems
+ */
+LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  int          cnt, idx;
+  WND         *wndPtr;
+  int         *lpItems = PTR_SEG_TO_LIN(lParam);
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  if (wParam == 0) return 0;
+
+  lpls = lphl->lpFirst;
+  cnt = 0; idx = 0;
+
+  while (lpls != NULL) {
+    if (lpls->dis.itemState > 0) lpItems[cnt++] = idx;
+
+    if (cnt == wParam) break;
+    idx++;
+    lpls = lpls->lpNext;
+  }
+
+  return cnt;
+}
+
+/***********************************************************************
+ *           LBGetTextLen
+ */
+LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+  int          cnt = 0;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!HasStrings(wndPtr)) return LB_ERR;
+
+  if (wParam >= lphl->ItemsCount) return LB_ERR;
+    
+  lpls = lphl->lpFirst;
+
+  while (cnt++ < wParam) lpls = lpls->lpNext;
+  
+  return strlen(lpls->itemText);
+}
+
+/***********************************************************************
+ *           LBGetDlgCode
+ */
+LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return DLGC_WANTALLKEYS;
+}
+
+/***********************************************************************
+ *           LBGetTopIndex
+ */
+LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+
+  return (lphl->FirstVisible - 1);
+}
+
+
+/***********************************************************************
+ *           LBSelectString
+ */
+LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WND  *wndPtr;
+  WORD  wRet;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  wRet = ListBoxFindString(hwnd, wParam,
+			   (LPSTR)PTR_SEG_TO_LIN(lParam));
+
+  /* XXX add functionality here */
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSelItemRange
+ */
+LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+  WORD         cnt;
+  WORD         first = LOWORD(lParam);
+  WORD         last = HIWORD(lParam);
+  BOOL         select = wParam;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  if (first >= lphl->ItemsCount ||
+      last >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  cnt = 0;
+
+  while (lpls != NULL) {
+    if (cnt++ >= first)
+      lpls->dis.itemState = select ? ODS_SELECTED : 0;
+
+    if (cnt > last)
+      break;
+
+    lpls = lpls->lpNext;
+  }
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetCaretIndex
+ */
+LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  WND         *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
+  if (wParam >= lphl->ItemsCount) return LB_ERR;
+
+  lphl->ItemFocused = wParam;
+  ListBoxScrolltoFocus (hwnd);
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetColumnWidth
+ */
+LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+  lphl->ColumnsWidth = wParam;
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetHorizontalExtent
+ */
+LONG LBSetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetItemData
+ */
+LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb, "LB_SETITEMDATA  wParam=%x  lParam=%lx\n", wParam, lParam);
+  return ListBoxSetItemData(hwnd, wParam, lParam);
+}
+
+/***********************************************************************
+ *           LBSetTabStops
+ */
+LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+
+  if (lphl->TabStops != NULL) {
+    lphl->iNumStops = 0;
+    free (lphl->TabStops);
+  }
+
+  lphl->TabStops = malloc (wParam * sizeof (short));
+  if (lphl->TabStops) {
+    lphl->iNumStops = wParam;
+    memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/***********************************************************************
+ *           LBSetCurSel
+ */
+LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WORD  wRet;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR; 
+
+  dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", 
+		  wParam);
+
+  wRet = ListBoxSetCurSel(hwnd, wParam);
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBSetSel
+ */
+LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD wRet;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
+
+  wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBSetTopIndex
+ */
+LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
+		  wParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  lphl->FirstVisible = wParam;
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetItemHeight
+ */
+LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam)
+
+{
+  WORD  wRet;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
+  wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
+  return wRet;
+}
+
+
+/***********************************************************************
+ *           ListBoxWndProc 
+ */
+
+LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{ 
+  int idx = 0;
+  int table_size = sizeof (methods) / sizeof (msg_tbl);
+
+  while (idx < table_size) {
+    if (message == methods[idx].message) {
+      return (*(methods[idx].handler))(hwnd, message, wParam, lParam);
+    }
+    idx++;
+  }
+  
+  return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+
+LPLISTSTRUCT ListBoxGetItem(HWND hwnd, UINT uIndex)
+
+{
+  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+  LPLISTSTRUCT lpls;
+  UINT         Count = 0;
+
+  if (uIndex >= lphl->ItemsCount) return NULL;
+
+  lpls = lphl->lpFirst;
+
+  while (Count++ < uIndex) lpls = lpls->lpNext;
+
+  return lpls;
+}
+
+ 
+LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
+{
+    WND  *Ptr;
+    LPHEADLIST lphl;
+    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
+    lphl = *((LPHEADLIST *)&Ptr->wExtra[1]);
+    return lphl;
+}
+
+
+LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
+{
+    WND  *wndPtr;
+    LPHEADLIST lphl;
+    wndPtr = WIN_FindWndPtr(hwnd);
+    lphl = *((LPHEADLIST *)&wndPtr->wExtra[1]);
+    return lphl;
+}
+
+
+void ListBoxDrawItem (HWND hwnd, HDC hdc, LPLISTSTRUCT lpls,
+		      WORD itemAction, WORD itemState)
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (OWNER_DRAWN(wndPtr)) {
+    DRAWITEMSTRUCT   *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
+
+    memcpy (dis, &lpls->dis, sizeof(DRAWITEMSTRUCT));
+
+    dis->CtlType  = ODT_LISTBOX;
+    dis->hDC      = hdc;
+
+    if ((!dis->CtlID) && lphl->hWndLogicParent) {
+      WND   *ParentWndPtr;
+
+      ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
+      dis->CtlID   = ParentWndPtr->wIDmenu;
+    }
+
+    if (HasStrings(wndPtr)) dis->itemData = (DWORD)lpls->itemText;
+   
+    dis->itemAction = itemAction;
+    dis->itemState  = itemState;
+
+    SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, 
+		0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
+  }
+  else {
+
+    if (itemAction == ODA_DRAWENTIRE ||
+	itemAction == ODA_SELECT) {
+      int 	OldBkMode;
+      DWORD 	dwOldTextColor;
+
+      OldBkMode = SetBkMode(hdc, TRANSPARENT);
+
+      if (itemState != 0) {
+	dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
+	FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
+      }
+
+      if (wndPtr->dwStyle & LBS_USETABSTOPS)
+	TabbedTextOut(hdc, lpls->dis.rcItem.left + 5, 
+		      lpls->dis.rcItem.top + 2, 
+		      (char *)lpls->itemText, 
+		      strlen((char *)lpls->itemText), lphl->iNumStops,
+		      lphl->TabStops, 0);
+      else
+	TextOut(hdc, lpls->dis.rcItem.left + 5, lpls->dis.rcItem.top + 2, 
+		(char *)lpls->itemText, strlen((char *)lpls->itemText));
+
+      if (itemState != 0) {
+	SetTextColor(hdc, dwOldTextColor);
+      }
+      
+      SetBkMode(hdc, OldBkMode);
+    } else DrawFocusRect(hdc, &lpls->dis.rcItem);
+  }
+
+  return;
+}
+
+void RepaintListBox(HWND hwnd)
+
+{
+  WND 	*wndPtr;
+  LPHEADLIST  lphl;
+  LPLISTSTRUCT lpls;
+  PAINTSTRUCT ps;
+  HBRUSH 	hBrush;
+
+  HDC 	hdc;
+  RECT 	rect;
+  int   i, top, height, maxwidth, ipc;
+
+  top = 0;
+
+  hdc = BeginPaint( hwnd, &ps );
+
+  if (!IsWindowVisible(hwnd)) {
+    EndPaint( hwnd, &ps );
+    return;
+  }
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) goto EndOfPaint;
+  if (!lphl->bRedrawFlag) goto EndOfPaint;
+
+  SelectObject(hdc, lphl->hFont);
+
+  hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
+		       MAKELONG(hwnd, CTLCOLOR_LISTBOX));
+
+  if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
+
+  GetClientRect(hwnd, &rect);
+  FillRect(hdc, &rect, hBrush);
+
+  maxwidth = rect.right;
+  rect.right = lphl->ColumnsWidth;
+
+  if (lphl->ItemsCount == 0) goto EndOfPaint;
+
+  lpls = lphl->lpFirst;
+
+  lphl->ItemsVisible = 0;
+  lphl->ItemsPerColumn = ipc = 0;
+
+  for(i = 0; i < lphl->ItemsCount; i++) {
+    if (lpls == NULL) goto EndOfPaint;
+
+    if (i >= lphl->FirstVisible - 1) {
+      height = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
+
+      if (top > rect.bottom) {
+	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+	  lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
+	  ipc = 0;
+	  top = 0;
+	  rect.left += lphl->ColumnsWidth;
+	  rect.right += lphl->ColumnsWidth;
+	  if (rect.left > maxwidth) break;
+	}
+	else 
+	  break;
+      }
+
+      lpls->dis.rcItem.top    = top;
+      lpls->dis.rcItem.bottom = top + height;
+      lpls->dis.rcItem.left   = rect.left;
+      lpls->dis.rcItem.right  = rect.right;
+
+      if (OWNER_DRAWN(wndPtr)) {
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, 0);
+	if (lpls->dis.itemState)
+	  ListBoxDrawItem (hwnd, hdc, lpls, ODA_SELECT, ODS_SELECTED);
+      }
+      else 
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, lpls->dis.itemState);
+
+      if ((lphl->ItemFocused == i) && GetFocus() == hwnd)
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_FOCUS, ODS_FOCUS);
+
+      top += height;
+      lphl->ItemsVisible++;
+      ipc++;
+    }
+
+    lpls = lpls->lpNext;
+  }
+ EndOfPaint:
+  EndPaint( hwnd, &ps );
+}
+
+int ListBoxFindMouse(HWND hwnd, int X, int Y)
+
+{
+  WND 		*wndPtr;
+  LPHEADLIST 		lphl;
+  LPLISTSTRUCT	lpls;
+  RECT 		rect;
+  int                 i, h, h2, w, w2;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return LB_ERR;
+  if (lphl->ItemsCount == 0) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+  GetClientRect(hwnd, &rect);
+  h = w2 = 0;
+  w = lphl->ColumnsWidth;
+
+  for(i = 1; i <= lphl->ItemsCount; i++) {
+    if (i >= lphl->FirstVisible) {
+      h2 = h;
+      h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
+      if ((Y > h2) && (Y < h) &&
+	  (X > w2) && (X < w)) return(i - 1);
+      if (h > rect.bottom) {
+	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
+	h = 0;
+	w2 = w;
+	w += lphl->ColumnsWidth;
+	if (w2 > rect.right) return LB_ERR;
+      }
+    }
+    if (lpls->lpNext == NULL) return LB_ERR;
+    lpls = (LPLISTSTRUCT)lpls->lpNext;
+  }
+  return(LB_ERR);
+}
+
+void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)  
+
+{
+  MEASUREITEMSTRUCT 	*lpmeasure;
+
+  HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
+
+  lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
+
+  if (lpmeasure == NULL) {
+    fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
+    return;
+  }
+ 
+  lpmeasure->CtlType    = ODT_LISTBOX;
+  lpmeasure->CtlID      = wndPtr->wIDmenu;
+  lpmeasure->itemID     = lpls->dis.itemID;
+  lpmeasure->itemWidth  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
+  lpmeasure->itemHeight = 0;
+
+  if (HasStrings(wndPtr))
+    lpmeasure->itemData = (DWORD)lpls->itemText;
+  else
+    lpmeasure->itemData = lpls->dis.itemData;
+
+  SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
+	      0, USER_HEAP_SEG_ADDR(hTemp));
+
+  if (wndPtr->dwStyle & LBS_OWNERDRAWFIXED) {
+    lphl->StdItemHeight = lpmeasure->itemHeight;
+  }
+
+  lpls->dis.rcItem.right  = lpls->dis.rcItem.left + lpmeasure->itemWidth;
+  lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
+  USER_HEAP_FREE(hTemp);			
+}
+
+
+int ListBoxAddString(HWND hwnd, LPSTR newstr)
+{
+    LPHEADLIST	lphl;
+    UINT	pos = (UINT) -1;
+    WND		*wndPtr;
+    
+    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+    if (lphl == NULL) return LB_ERR;
+
     if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
 	LPLISTSTRUCT lpls = lphl->lpFirst;
 	for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
@@ -796,193 +1512,230 @@ int ListBoxAddString(HWND hwnd, LPSTR newstr)
 }
 
 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT *lppls, lplsnew;
-    HANDLE 	hItem;
-    HANDLE 	hStr;
-    LPSTR	str;
-    UINT	Count;
+  WND  	       *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT *lppls, lplsnew;
+  HANDLE 	hItem;
+  HANDLE 	hStr;
+  LPSTR	str;
+  UINT	Count;
     
-    dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n", 
-		    hwnd, uIndex, newstr);
+  dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n", 
+		  hwnd, uIndex, newstr);
     
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
     
-    if (uIndex == (UINT)-1)
-	uIndex = lphl->ItemsCount;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
+  if (uIndex == (UINT)-1)
+    uIndex = lphl->ItemsCount;
+
+  if (uIndex > lphl->ItemsCount) return LB_ERR;
+
+  lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
     
-    for(Count = 0; Count < uIndex; Count++) {
-	if (*lppls == NULL) return LB_ERR;
-	lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
-        }
+  for(Count = 0; Count < uIndex; Count++) {
+    if (*lppls == NULL) return LB_ERR;
+    lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
+  }
     
-	hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
-	lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
-    if (lplsnew == NULL) {
-		printf("ListBoxInsertString() // Bad allocation of new item !\n");
-		return LB_ERRSPACE;
-		}
-	ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
-	lplsnew->hMem = hItem;
-	lplsnew->lpNext = *lppls;
-	*lppls = lplsnew;
-	lphl->ItemsCount++;
-	hStr = 0;
-
-	if (HasStrings(wndPtr)) {
-		hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
-		str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
-		if (str == NULL) return LB_ERRSPACE;
-		strcpy(str, newstr);
-		newstr = str;
-		lplsnew->itemText = str;
-		dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
-		}
-	else {
-		lplsnew->itemText = NULL;
-		lplsnew->dis.itemData = (DWORD)newstr;
-		}
-	lplsnew->dis.itemID = lphl->ItemsCount;
-	lplsnew->hData = hStr;
-	if (((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) ||
-		((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED))
-		ListBoxAskMeasure(wndPtr, lphl, lplsnew);
-        SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), 
-                       (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
-	if (lphl->ItemsPerColumn != 0)
-		SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
-			lphl->ItemsPerColumn + 1,
-			(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
-	if ((lphl->FirstVisible <= uIndex) &&
-		((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		}
-        dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
-	return uIndex;
+  hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
+  lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
+
+  if (lplsnew == NULL) {
+    printf("ListBoxInsertString() // Bad allocation of new item !\n");
+    return LB_ERRSPACE;
+  }
+
+  ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
+  lplsnew->hMem = hItem;
+  lplsnew->lpNext = *lppls;
+  *lppls = lplsnew;
+  lphl->ItemsCount++;
+  hStr = 0;
+
+  if (HasStrings(wndPtr)) {
+    hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
+    str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
+    if (str == NULL) return LB_ERRSPACE;
+    strcpy(str, newstr);
+    newstr = str;
+    lplsnew->itemText = str;
+    dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
+  }
+  else {
+    lplsnew->itemText = NULL;
+    lplsnew->dis.itemData = (DWORD)newstr;
+  }
+
+  lplsnew->dis.itemID = lphl->ItemsCount;
+  lplsnew->hData = hStr;
+ 
+  if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) && (lphl->ItemsCount == 1)) {
+    ListBoxAskMeasure(wndPtr, lphl, lplsnew);
+  }
+
+  if (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)
+    ListBoxAskMeasure(wndPtr, lphl, lplsnew);   
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), 
+		 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
+
+  if (lphl->ItemsPerColumn != 0)
+    SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+		   lphl->ItemsPerColumn + 1,
+		   (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
+
+  if ((lphl->FirstVisible <= uIndex) &&
+      ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+
+  dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
+  return uIndex;
 }
 
 
 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    if ((!OutStr)&&(!bItemData))
-	fprintf(stderr, "ListBoxGetText // OutStr==NULL\n"); 
-    if (!bItemData)   	*OutStr=0;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    for(Count = 0; Count < uIndex; Count++) {
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    if (bItemData)
-	return lpls->dis.itemData;
-    if (!(HasStrings(wndPtr)) )
-      {
-	*((long *)OutStr) = lpls->dis.itemData;
-	return 4;
-      }
+  WND  	*wndPtr;
+  LPLISTSTRUCT lpls;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (!OutStr && !bItemData) {
+    dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
+    return 0;
+  }
+
+  if (!bItemData) *OutStr=0;
+
+  if ((lpls = ListBoxGetItem (hwnd, uIndex)) == NULL) 
+    return 0;
+
+  if (bItemData)
+    return lpls->dis.itemData;
+
+  if (!HasStrings(wndPtr)) {
+    *((long *)OutStr) = lpls->dis.itemData;
+    return 4;
+  }
 	
-    strcpy(OutStr, lpls->itemText);
-    return strlen(OutStr);
+  strcpy(OutStr, lpls->itemText);
+  return strlen(OutStr);
 }
 
 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
+
 {
-    WND         *wndPtr;
-    LPHEADLIST  lphl;
-    LPLISTSTRUCT lpls;
-    UINT        Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    for(Count = 0; Count < uIndex; Count++) {
-        if (lpls->lpNext == NULL) return LB_ERR;
-        lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    lpls->dis.itemData = ItemData;
-    return 1;
+  LPLISTSTRUCT lpls;
+
+  if ((lpls = ListBoxGetItem(hwnd, uIndex)) == NULL)
+    return 0;
+
+  lpls->dis.itemData = ItemData;
+  return 1;
 }
 
 
 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    if( uIndex == 0 )
-      lphl->lpFirst = lpls->lpNext;
-    else {
-      for(Count = 0; Count < uIndex; Count++) {
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-      }
-      lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
+  WND  	*wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls, lpls2;
+  UINT	Count;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (uIndex >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+
+  if( uIndex == 0 )
+    lphl->lpFirst = lpls->lpNext;
+  else {
+    for(Count = 0; Count < uIndex; Count++) {
+      if (lpls->lpNext == NULL) return LB_ERR;
+
+      lpls2 = lpls;
+      lpls = (LPLISTSTRUCT)lpls->lpNext;
     }
-    lphl->ItemsCount--;
-    if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
-    if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
-    SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
-    if (lphl->ItemsPerColumn != 0)
-	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
-	    lphl->ItemsPerColumn + 1, TRUE);
-    if ((lphl->FirstVisible <= uIndex) &&
-        ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
-        }
-    return lphl->ItemsCount;
+    lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
+  }
+
+  lphl->ItemsCount--;
+
+  if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
+  if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+  if (lphl->ItemsPerColumn != 0)
+    SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+		   lphl->ItemsPerColumn + 1, TRUE);
+
+  if ((lphl->FirstVisible <= uIndex) &&
+      ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+
+  return lphl->ItemsCount;
 }
 
 
 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
 {
-    WND          *wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (nFirst > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    Count = 0;
-    while(lpls != NULL) {
-      if (HasStrings(wndPtr))
-	{
-	  if (strcmp(lpls->itemText, MatchStr) == 0) return Count;
-	}
-      else
-	{
-	  if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
-	}
-      lpls = (LPLISTSTRUCT)lpls->lpNext;
-      Count++;
+  WND          *wndPtr;
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  UINT	       Count;
+  UINT         First = nFirst + 1;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return LB_ERR;
+
+  if (First > lphl->ItemsCount) return LB_ERR;
+ 
+  lpls = ListBoxGetItem(hwnd, First);
+  Count = 0;
+  while(lpls != NULL) {
+    if (HasStrings(wndPtr)) {
+      if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
+    } else if (wndPtr->dwStyle & LBS_SORT) {
+      /* XXX Do a compare item */
+    }
+    else
+      if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
+
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  /* Start over at top */
+  Count = 0;
+  lpls = lphl->lpFirst;
+
+  while (Count < First) {
+    if (HasStrings(wndPtr)) {
+      if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
+    } else if (wndPtr->dwStyle & LBS_SORT) {
+      /* XXX Do a compare item */
     }
-    return LB_ERR;
+    else
+      if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
+
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  return LB_ERR;
 }
 
 
@@ -990,112 +1743,123 @@ int ListBoxResetContent(HWND hwnd)
 {
     WND  *wndPtr;
     LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
+    LPLISTSTRUCT lpls;
     UINT	i;
+
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
+
+    if (lphl->ItemsCount == 0) return 0;
+
     lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
+
     dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
 	lphl->ItemsCount);
-    for(i = 0; i <= lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i != 0) {
-	    dprintf_listbox(stddeb,"ResetContent #%u\n", i);
-	    if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
-		LIST_HEAP_FREE(lphl, lpls2->hData);
-	    if (lpls2->hMem != 0) LIST_HEAP_FREE(lphl, lpls2->hMem);
-	    }  
-	if (lpls == NULL)  break;
+
+    for(i = 0; i < lphl->ItemsCount; i++) {
+      LPLISTSTRUCT lpls2;
+
+      if (lpls == NULL) return LB_ERR;
+
+      lpls2 = lpls->lpNext;
+
+      if (i != 0) {
+	dprintf_listbox(stddeb,"ResetContent #%u\n", i);
+	if (lpls->hData != 0 && lpls->hData != lpls->hMem)
+	  LIST_HEAP_FREE(lphl, lpls->hData);
+
+	if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
+      }  
+
+      lpls = lpls2;
     }
-    lphl->lpFirst = NULL;
+
+    lphl->lpFirst      = NULL;
     lphl->FirstVisible = 1;
-    lphl->ItemsCount = 0;
-    lphl->ItemFocused = -1;
-    lphl->PrevFocused = -1;
+    lphl->ItemsCount   = 0;
+    lphl->ItemFocused  = -1;
+    lphl->PrevFocused  = -1;
+
     SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+
     if (lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, TRUE);
+
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
+
     return TRUE;
 }
 
 
 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
+
 {
-    WND  *wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if( (wIndex != (WORD)(-1)) && (wIndex > lphl->ItemsCount) )
-      return LB_ERR;
-    lphl->ItemFocused = LB_ERR; 
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex)
-	    lpls2->dis.itemState = 1;
-	else 
-	    if (lpls2->dis.itemState != 0)
-	        lpls2->dis.itemState = 0;
-	if (lpls == NULL)  break;
-    }
+  WND  *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL) return 0;
+
+  if (lphl->ItemFocused != -1) {
+    lpls = ListBoxGetItem(hwnd, lphl->ItemFocused);
+    lpls->dis.itemState = 0;
+  }
+
+  if (wIndex != (UINT)-1) {
     lphl->ItemFocused = wIndex;
-    return wIndex;
-}
+    lpls = ListBoxGetItem(hwnd, wIndex);
+    lpls->dis.itemState = ODS_SELECTED | ODS_FOCUS;
 
+    return 0;
+  }
 
+  return LB_ERR;
+}
 
 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
+
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
+
+  if (wIndex == (UINT)-1) {
     lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if ((i == wIndex) || (wIndex == (WORD)-1)) {
-	    lpls2->dis.itemState = state;
-	    break;
-	    }  
-	if (lpls == NULL)  break;
+
+    while (lpls != NULL) {
+      lpls->dis.itemState = state;
+      lpls = lpls->lpNext;
     }
-    return LB_ERR;
+
+    return 0;
+  }
+
+  if (wIndex >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = ListBoxGetItem(hwnd, wIndex);
+  lpls->dis.itemState = state;
+
+  return 0;
 }
 
 
 int ListBoxGetSel(HWND hwnd, WORD wIndex)
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    return lpls2->dis.itemState;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
+  LPLISTSTRUCT lpls;
+
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+
+  return lpls->dis.itemState;
 }
 
 
@@ -1184,145 +1948,136 @@ int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
 
 
 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
+
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    *(lprect) = lpls2->dis.rcItem;
-	    break;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
-}
+  LPLISTSTRUCT lpls;
 
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+
+  *(lprect) = lpls->dis.rcItem;
+
+  return 0;
+}
 
 
 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
+
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    break;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
-}
+  LPHEADLIST    lphl;
+  WND          *wndPtr;
+  LPLISTSTRUCT  lpls;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
 
+  if (!(wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)) {
+    lphl->StdItemHeight = (short)height;
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
 
+    return 0;
+  }
 
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+  
+  lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + (short)height;
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
 
+  return 0;
+}
 
 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr, 
 	LPHEADLIST lphl, LPLISTSTRUCT lpls)
+
 {
-    RECT	rect;
-	if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
-		fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
-		return FALSE;
-		}
-    GetClientRect(hwnd, &rect);
-    SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
-    lpls->dis.CtlType = lphl->DrawCtlType;
-    lpls->dis.CtlID = wndPtr->wIDmenu;
-    lpls->dis.itemID = 0;
-    lpls->dis.itemAction = 0;
-    lpls->dis.itemState = 0;
-    lpls->dis.hwndItem = hwnd;
-    lpls->dis.hDC = 0;
-    lpls->dis.itemData = 0;
-	return TRUE;
+  RECT	rect;
+
+  if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
+    fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
+    return FALSE;
+  }
+
+  GetClientRect(hwnd, &rect);
+  SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
+
+  lpls->dis.CtlType    = lphl->DrawCtlType;
+  lpls->dis.CtlID      = wndPtr->wIDmenu;
+  lpls->dis.itemID     = 0;
+  lpls->dis.itemAction = 0;
+  lpls->dis.itemState  = 0;
+  lpls->dis.hwndItem   = hwnd;
+  lpls->dis.hDC        = 0;
+  lpls->dis.itemData   = 0;
+
+  return TRUE;
 }
 
 
 
 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (wChar < ' ') return LB_ERR;
-    if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
-	    ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
-	if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) { 
-	    return LB_ERR;
-	    }
+  WND  	        *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT  lpls;
+  UINT	        Count;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+  if (wChar < ' ') return LB_ERR;
+
+  if (!HasStrings(wndPtr)) return LB_ERR;
+
+  Count = 0;
+  while(lpls != NULL) {
+    if (Count > lphl->ItemFocused) {
+      if (*(lpls->itemText) == (char)wChar) {
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	  lphl->ItemFocused = Count;
+	  ListBoxScrolltoFocus(hwnd);
 	}
-    Count = 0;
-    while(lpls != NULL) {
-        if (Count > lphl->ItemFocused) {
-	    if (*(lpls->itemText) == (char)wChar) {
-		lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
-		if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		    lphl->ItemFocused = Count;
-		    }
-		else {
-		    ListBoxSetCurSel(hwnd, Count);
-		    }
-		SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	        InvalidateRect(hwnd, NULL, TRUE);
-	        UpdateWindow(hwnd);
-	        return Count;
-	        }
-	    }
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	Count++;
+	else {
+	  ListBoxSetCurSel(hwnd, Count);
 	}
-    Count = 0;
-    lpls = lphl->lpFirst;
-    while(lpls != NULL) {
-	if (*(lpls->itemText) == (char)wChar) {
-	    if (Count == lphl->ItemFocused)    return LB_ERR;
-	    lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
-	    if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-	    if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		lphl->ItemFocused = Count;
-		}
-	    else {
-		ListBoxSetCurSel(hwnd, Count);
-		}
-	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    return Count;
-	    }
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	Count++;
-        }
-    return LB_ERR;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return Count;
+      }
+    }
+    lpls = (LPLISTSTRUCT)lpls->lpNext;
+    Count++;
+  }
+  Count = 0;
+  lpls = lphl->lpFirst;
+  while(lpls != NULL) {
+    if (*(lpls->itemText) == (char)wChar) {
+      if (Count == lphl->ItemFocused)    return LB_ERR;
+
+      if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	lphl->ItemFocused = Count;
+	ListBoxScrolltoFocus(hwnd);
+      }
+      else {
+	ListBoxSetCurSel(hwnd, Count);
+      }
+      SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+      UpdateWindow(hwnd);
+      return Count;
+    }
+    lpls = lpls->lpNext;
+    Count++;
+  }
+  return LB_ERR;
 }
 
 
 /************************************************************************
- * 					DlgDirSelect			[USER.99]
+ * 		      	DlgDirSelect			[USER.99]
  */
 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
 {
@@ -1364,53 +2119,85 @@ BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
 
 
 /************************************************************************
- * 					DlgDirList				[USER.100]
+ * 			   DlgDirList				[USER.100]
  */
 int DlgDirList(HWND hDlg, LPSTR lpPathSpec, 
 	int nIDLBox, int nIDStat, WORD wType)
 {
-	HWND	hWnd;
-	int ret;
-	dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
-			hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
-	if (nIDLBox)
-	  hWnd = GetDlgItem(hDlg, nIDLBox);
-	else
-	  hWnd = 0;
-	if (hWnd)
-	  ListBoxResetContent(hWnd);
-	if (hWnd)
-	  ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
-	else
-	  ret=0;
-	if (nIDStat)
-	  {
-	    int drive;
-	    char temp[255];
-	    drive = DOS_GetDefaultDrive();
-	    strcpy( temp+3, DOS_GetCurrentDir(drive) );
-	    if( temp[3] == '\\' ) {
-	      temp[1] = 'A'+drive;
-	      temp[2] = ':';
-	      SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0, (LONG)(temp+1));
-	    }
-	    else {
-	      temp[0] = 'A'+drive;
-	      temp[1] = ':';
-	      temp[2] = '\\';
-	      SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0, (LONG) temp );
-	    }
-	  } 
-	return ret;
+  HWND	hWnd;
+  int ret;
+  dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
+		  hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
+  if (nIDLBox)
+    hWnd = GetDlgItem(hDlg, nIDLBox);
+  else
+    hWnd = 0;
+  if (hWnd)
+    ListBoxResetContent(hWnd);
+  if (hWnd)
+    ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
+  else
+    ret=0;
+  if (nIDStat)
+    {
+      int drive;
+      HANDLE hTemp;
+      char *temp;
+      drive = DOS_GetDefaultDrive();
+      hTemp = USER_HEAP_ALLOC( 256 );
+      temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
+      strcpy( temp+3, DOS_GetCurrentDir(drive) );
+      if( temp[3] == '\\' ) {
+	temp[1] = 'A'+drive;
+	temp[2] = ':';
+	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
+                            USER_HEAP_SEG_ADDR(hTemp) + 1 );
+      }
+      else {
+	temp[0] = 'A'+drive;
+	temp[1] = ':';
+	temp[2] = '\\';
+	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
+                            USER_HEAP_SEG_ADDR(hTemp) );
+      }
+      USER_HEAP_FREE( hTemp );
+    } 
+  return ret;
 }
 
-/* get the maximum value of lphl->FirstVisible */
-int ListMaxFirstVisible(LPHEADLIST lphl)
+
+/* Returns: 0 if nothing needs to be changed */
+/*          1 if FirstVisible changed */
+
+int ListBoxScrolltoFocus(HWND hwnd)
+
 {
-    int m = lphl->ItemsCount-lphl->ItemsVisible+1;
-    return (m < 1) ? 1 : m;
-}
+  WND  *wndPtr;
+  LPHEADLIST  lphl;
+  short       end;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl->ItemsCount == 0) return 0;
+  if (lphl->ItemFocused == -1) return 0;
+
+  end = lphl->FirstVisible + lphl->ItemsVisible - 2;
 
+  if (lphl->ItemFocused < lphl->FirstVisible - 1) {
+    lphl->FirstVisible = lphl->ItemFocused + 1;
+  }
+  else if (lphl->ItemFocused > end) {
+    UINT maxFirstVisible = ListMaxFirstVisible(lphl);
+
+    lphl->FirstVisible = lphl->ItemFocused;
+
+    if (lphl->FirstVisible > maxFirstVisible) {
+      lphl->FirstVisible = maxFirstVisible;
+    }
+  } else return 0;
+
+  return 1;
+}
 
 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
    has the LBS_NOTIFY style */
@@ -1419,7 +2206,8 @@ void ListBoxSendNotification(HWND hwnd, WORD code)
   WND  *wndPtr;
   LPHEADLIST  lphl;
   lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-  if( wndPtr && ( (wndPtr->dwStyle && LBS_NOTIFY) != 0) )
+
+  if (wndPtr && (wndPtr->dwStyle & LBS_NOTIFY))
     SendMessage(lphl->hWndLogicParent, WM_COMMAND,
 		wndPtr->wIDmenu, MAKELONG(hwnd, code));
-} 
+}
diff --git a/controls/menu.c b/controls/menu.c
index ac118e902e1254c4eee6f80b49f627f113e555ef..2b20dbeaa7a64d04c0d82154c9321c6f15a0fd49 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -246,6 +246,27 @@ static void MENU_CalcItemSize( HDC hdc, LPMENUITEM lpitem, HWND hwndOwner,
 
     SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
     lpitem->xTab = 0;
+    if (lpitem->item_flags & MF_OWNERDRAW)  {
+      static HANDLE mistrh = 0;
+      static SEGPTR mistrsegp = 0;
+      static LPMEASUREITEMSTRUCT mistruct=NULL;
+      if (mistruct == NULL)  {
+	mistrh = GlobalAlloc(0,sizeof(MEASUREITEMSTRUCT));
+	mistrsegp = WIN16_GlobalLock(mistrh);
+	mistruct = PTR_SEG_TO_LIN(mistrsegp);
+      }
+      mistruct->CtlType = ODT_MENU;
+      mistruct->itemID = lpitem->item_id;
+      mistruct->itemData = (long int)lpitem->item_text;
+      mistruct->itemHeight = 16;
+      mistruct->itemWidth = 30;
+      SendMessage(hwndOwner,WM_MEASUREITEM,0,mistrsegp);
+      lpitem->rect.bottom += mistruct->itemHeight;
+      lpitem->rect.right += mistruct->itemWidth;
+      dprintf_menu(stddeb,"DrawMenuItem: MeasureItem %04x %d:%d!\n",
+		   lpitem->item_id,mistruct->itemWidth, mistruct->itemHeight);
+      return;
+    } 
 
     if (lpitem->item_flags & MF_SEPARATOR)
     {
@@ -422,11 +443,35 @@ static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect, LPPOPUPMENU lppop,
  *
  * Draw a single menu item.
  */
-static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem,
+static void MENU_DrawMenuItem( HWND hwnd, HDC hdc, LPMENUITEM lpitem,
 			       WORD height, BOOL menuBar )
 {
     RECT rect;
 
+    if (lpitem->item_flags & MF_OWNERDRAW)  {
+      static HANDLE distrh = 0;
+      static SEGPTR distrsegp = 0;
+      static LPDRAWITEMSTRUCT distruct=NULL;
+      if (distruct == NULL)  {
+	distrh = GlobalAlloc(0,sizeof(DRAWITEMSTRUCT));
+	distrsegp = WIN16_GlobalLock(distrh);
+	distruct = PTR_SEG_TO_LIN(distrsegp);
+      }
+      dprintf_menu(stddeb,"DrawMenuItem: Ownerdraw!\n");
+      distruct->CtlType = ODT_MENU;
+      distruct->itemID = lpitem->item_id;
+      distruct->itemData = (long int)lpitem->item_text;
+      distruct->itemState = 0;
+      if (lpitem->item_flags & MF_CHECKED) distruct->itemState |= ODS_CHECKED;
+      if (lpitem->item_flags & MF_GRAYED) distruct->itemState |= ODS_GRAYED;
+      if (lpitem->item_flags & MF_HILITE) distruct->itemState |= ODS_SELECTED;
+      distruct->itemAction = ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS;
+      distruct->hwndItem = hwnd;
+      distruct->hDC = hdc;
+      distruct->rcItem = lpitem->rect;
+      SendMessage(hwnd,WM_DRAWITEM,0,distrsegp);
+      return;
+    }
     if (menuBar && (lpitem->item_flags & MF_SEPARATOR)) return;
     rect = lpitem->rect;
 
@@ -566,7 +611,7 @@ static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu )
     if (!menu || !menu->nItems) return;
     item = (MENUITEM *) USER_HEAP_LIN_ADDR( menu->hItems );
     for (i = menu->nItems; i > 0; i--, item++)
-	MENU_DrawMenuItem( hdc, item, menu->Height, FALSE );
+	MENU_DrawMenuItem( hwnd, hdc, item, menu->Height, FALSE );
 }
 
 
@@ -599,7 +644,7 @@ WORD MENU_DrawMenuBar(HDC hDC, LPRECT lprect, HWND hwnd, BOOL suppress_draw)
     lpitem = (MENUITEM *) USER_HEAP_LIN_ADDR( lppop->hItems );
     for (i = 0; i < lppop->nItems; i++, lpitem++)
     {
-	MENU_DrawMenuItem( hDC, lpitem, lppop->Height, TRUE );
+	MENU_DrawMenuItem( hwnd, hDC, lpitem, lppop->Height, TRUE );
     }
     return lppop->Height;
 } 
@@ -677,7 +722,7 @@ static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
 	else
 	{
 	    items[lppop->FocusedItem].item_flags &=~(MF_HILITE|MF_MOUSESELECT);
-	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+	    MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
 			       !(lppop->wFlags & MF_POPUP) );
 	}
     }
@@ -691,7 +736,7 @@ static void MENU_SelectItem( HMENU hmenu, WORD wIndex )
 	else
 	{
 	    items[lppop->FocusedItem].item_flags |= MF_HILITE;
-	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+	    MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
 			       !(lppop->wFlags & MF_POPUP) );
 	    SendMessage(lppop->hWnd, WM_MENUSELECT,
 			items[lppop->FocusedItem].item_id, 
diff --git a/controls/widgets.c b/controls/widgets.c
index 20e22dcc5150740a60f5cdfed2c439303b3ba0d1..a2f17a9b8be7d20a068f2fe7fb82861a97466ded 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -14,37 +14,31 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include "mdi.h"
 #include "gdi.h"
 #include "user.h"
-
-LONG ListBoxWndProc  ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG ComboBoxWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG EditWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG PopupMenuWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG DesktopWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG MDIClientWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+#include "selectors.h"
 
 
 static WNDCLASS WIDGETS_BuiltinClasses[] =
 {
-    { CS_GLOBALCLASS | CS_PARENTDC, ButtonWndProc, 0, sizeof(BUTTONINFO), 
-      0, 0, 0, 0, NULL, "BUTTON" },
-    { CS_GLOBALCLASS | CS_PARENTDC, StaticWndProc, 0, sizeof(STATICINFO),
-      0, 0, 0, 0, NULL, "STATIC" },
-    { CS_GLOBALCLASS | CS_PARENTDC, ScrollBarWndProc, 0, sizeof(SCROLLINFO),
-      0, 0, 0, 0, NULL, "SCROLLBAR" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, ListBoxWndProc, 0, 8,
-      0, 0, 0, 0, NULL, "LISTBOX" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, ComboBoxWndProc, 0, 8,
-      0, 0, 0, 0, NULL, "COMBOBOX" },
-    { CS_GLOBALCLASS | CS_PARENTDC, EditWndProc, 0, sizeof(WORD), 
-      0, 0, 0, 0, NULL, "EDIT" },
-    { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc, 0, 8,
-      0, 0, 0, 0, NULL, POPUPMENU_CLASS_NAME },
-    { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
-      0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
-    { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProc, 0, DLGWINDOWEXTRA,
-      0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
-    { CS_GLOBALCLASS, MDIClientWndProc, 0, sizeof(MDICLIENTINFO),
-      0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ButtonWndProc", 0,
+      sizeof(BUTTONINFO), 0, 0, 0, 0, NULL, "BUTTON" },
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"StaticWndProc", 0,
+      sizeof(STATICINFO), 0, 0, 0, 0, NULL, "STATIC" },
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ScrollBarWndProc", 0,
+      sizeof(SCROLLINFO), 0, 0, 0, 0, NULL, "SCROLLBAR" },
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ListBoxWndProc", 0,
+      8, 0, 0, 0, 0, NULL, "LISTBOX" },
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ComboBoxWndProc", 0,
+      8, 0, 0, 0, 0, NULL, "COMBOBOX" },
+    { CS_GLOBALCLASS, (WNDPROC)"EditWndProc", 0,
+      sizeof(WORD), 0, 0, 0, 0, NULL, "EDIT" },
+    { CS_GLOBALCLASS | CS_SAVEBITS, (WNDPROC)"PopupMenuWndProc", 0,
+      8, 0, 0, 0, 0, NULL, POPUPMENU_CLASS_NAME },
+    { CS_GLOBALCLASS, (WNDPROC)"DesktopWndProc", 0,
+      sizeof(DESKTOPINFO), 0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
+    { CS_GLOBALCLASS | CS_SAVEBITS, (WNDPROC)"DefDlgProc", 0,
+      DLGWINDOWEXTRA, 0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
+    { CS_GLOBALCLASS, (WNDPROC)"MDIClientWndProc", 0,
+      sizeof(MDICLIENTINFO), 0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
 };
 
 #define NB_BUILTIN_CLASSES \
@@ -70,6 +64,7 @@ BOOL WIDGETS_Init(void)
         strcpy( name, class->lpszClassName );
         class->lpszClassName = (LPSTR)USER_HEAP_SEG_ADDR( hName );
 	class->hCursor = LoadCursor( 0, IDC_ARROW );
+        class->lpfnWndProc = GetWndProcEntry16( (char *)class->lpfnWndProc );
 	if (!RegisterClass( class )) return FALSE;
     }
     USER_HEAP_FREE( hName );
diff --git a/debugger/info.c b/debugger/info.c
index 950624077d16ae40045c314f851876f8c2b40aa0..8b1604ffbd8d6c828cf1df08f121fbe0d828924a 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -277,11 +277,12 @@ void dbg_bt(){
   while((cs & 3) == 3) {
     /* See if in 32 bit mode or not.  Assume GDT means 32 bit. */
     if ((cs & 7) != 7) {
-      void CallTo32();
+      extern int main();
       fprintf(stderr,"%d ",frameno++);
       print_address(frame->u.win32.saved_ip,stderr,32);
       fprintf( stderr, "\n" );
-      if(frame->u.win32.saved_ip<((unsigned long)CallTo32+1000))break;
+      if (frame->u.win32.saved_ip >= ((unsigned long)main) &&
+          frame->u.win32.saved_ip <= ((unsigned long)main+1000)) break;
       frame = (struct frame *) frame->u.win32.saved_bp;
     } else {
       if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
diff --git a/if1632/Imakefile b/if1632/Imakefile
index 85ef1ea08b166b9cb51b47d98149c4c0e8282e81..99e872bdac6075a2feb1dc1882a76d86757dbc9c 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -9,40 +9,45 @@ SRCS = \
 
 #ifdef WINELIB
 CALLOBJS =
-DLLOBJS =
+DLLS =
 #else
-CALLOBJS = call.o
-DLLOBJS = \
-	dll_commdlg.o \
-	dll_compobj.o \
-	dll_gdi.o \
-	dll_kernel.o \
-	dll_keyboard.o \
-	dll_mmsystem.o \
-	dll_mouse.o \
-	dll_ole2.o \
-	dll_ole2conv.o \
-	dll_ole2disp.o \
-	dll_ole2nls.o \
-	dll_ole2prox.o \
-	dll_olecli.o \
-	dll_olesvr.o \
-	dll_shell.o \
-	dll_sound.o \
-	dll_storage.o \
-	dll_stress.o \
-	dll_system.o \
-	dll_toolhelp.o \
-	dll_user.o \
-	dll_win87em.o \
-	dll_winsock.o
+CALLOBJS = \
+	call16.o \
+	call32.o
+DLLS = \
+	commdlg \
+	compobj \
+	gdi \
+	kernel \
+	keyboard \
+	mmsystem \
+	mouse \
+	ole2 \
+	ole2conv \
+	ole2disp \
+	ole2nls \
+	ole2prox \
+	olecli \
+	olesvr \
+	shell \
+	sound \
+	storage \
+	stress \
+	system \
+	toolhelp \
+	user \
+	win87em \
+	winprocs \
+	winsock
 #endif
 
-#ifndef NewBuild
-OBJS = $(CALLOBJS) $(DLLOBJS) $(SRCS:.c=.o) $(DLLOBJS:.o=_tab.o)
-#else
-OBJS = $(CALLOBJS) $(DLLOBJS) $(SRCS:.c=.o) $(DLLOBJS:.o=_tab.o) $(DLLOBJS:dll_.rly_)
-#endif
+OBJS = $(DLLS:%=dll_%.o) $(CALLOBJS) $(SRCS:.c=.o) $(DLLS:%=tab_%.o)
+
+BUILD = $(TOP)/tools/build
+
+#define MakeDllFromSpec(name)					@@\
+Concat(dll_,name.S) Concat(tab_,name.c): name.spec $(BUILD)	@@\
+	$(BUILD) -spec name.spec				@@\
 
 /*
  * If you add a new spec file, copy one of these lines
@@ -69,23 +74,25 @@ MakeDllFromSpec(system)
 MakeDllFromSpec(toolhelp)
 MakeDllFromSpec(user)
 MakeDllFromSpec(win87em)
+MakeDllFromSpec(winprocs)
 MakeDllFromSpec(winsock)
 
 WineRelocatableTarget($(MODULE),,$(OBJS))
 DependTarget()
 
 #ifndef WINELIB
-pop.h: $(TOP)/tools/build
-	$(TOP)/tools/build -p
 
-call.o: call.S pop.h
-	$(CC) -I. -c -o call.o call.S
-#endif
+call32.S: $(BUILD) $(DLLS:%=dll_%.S)
+	$(BUILD) -call32 `cat $(DLLS:%=dll_%.S) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
+
+call16.S: $(BUILD) $(TOP)/include/callback.h
+	$(BUILD) -call16 `cat $(TOP)/include/callback.h | grep "extern.*CallTo16_" | sed 's/.*CallTo16_\(.*\)(.*/\1/' | sort | uniq` > call16.S
+
+#endif  /* WINELIB */
 
 includes::
-	touch pop.h
 
 install::
 
 clean::
-	$(RM) dll* dtb* pop.h call.s
+	$(RM) dll_* tab_* call32.S call16.S
diff --git a/if1632/call.S b/if1632/call.S
deleted file mode 100644
index e6ab7b3eb0ca2e0734ecba26292d7851f593b9a2..0000000000000000000000000000000000000000
--- a/if1632/call.S
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright  Robert J. Amstadt, 1993
- */
-#ifdef linux
-#define UDATASEL 0x2b
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UDATASEL 0x27
-#endif
-#ifdef __ELF__
-#define A(addr) addr
-#else
-#define A(addr) _##addr
-#endif
-	.data
-jump_target:
-return_value:
-	.long	0
-
-/**********************************************************************
- *	Places to keep info about the current 32-bit stack frame.
- */
-	.globl	A( IF1632_Saved32_esp), A(IF1632_Saved32_ebp), A(IF1632_Saved32_ss)
-A(IF1632_Saved32_esp:)
-	.long	0
-A(IF1632_Saved32_ebp:)
-	.long	0
-A(IF1632_Saved32_ss:)
-	.word	0
-#ifdef __ELF__
-A(IF1632_ELF_KLUDGE:)
-	.long	0
-	.word	0x0f
-#endif
-
-/**********************************************************************
- *	Places to keep info about the current 16-bit stack frame.
- */
-	.globl A(IF1632_Saved16_sp),A(IF1632_Saved16_bp),A(IF1632_Saved16_ss)
-A(IF1632_Saved16_sp:)
-	.word	0
-A(IF1632_Saved16_bp:)
-	.word	0
-A(IF1632_Saved16_ss:)
-	.word	0
-
-nbytes:
-	.word	0
-selector:
-	.word	0
-offset:
-	.word	0
-
-	.text
-
-/**********************************************************************
- *	int CallToInit16(unsigned long csip, unsigned long sssp,
- *		     unsigned short ds)
- *
- *	Stack:	 	0	ebp
- *		 	4	eip
- *		 	8	target ip
- *			10	target cs
- *			12	target sp
- *			14	target ss
- *			16	target ds
- */
-	.align	4
-	.globl A(CallToInit16)
-A(CallToInit16:)
-	pushl	%ebp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save our registers
-	 */
-	pushal
-	pushl	A(IF1632_Saved32_esp)
-	pushl	A(IF1632_Saved32_ebp)
-	pushw	A(IF1632_Saved32_ss)
-
-#ifdef __ELF__
-	/* change to the other code segment */
-	movw	$0x0f, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L4, %eax
-	andl	$0x0000ffff, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L4:
-#endif
-	/*
-	 * Get target address.
-	 */
-	movl	8(%ebp),%eax
-	movl	%eax,jump_target
-	lea	jump_target,%edx
-
-	/*
-	 * Put stack registers where we can get them after stack switch.
-	 */
-	movw	%ss,A(IF1632_Saved32_ss)
-	movl	%esp,A(IF1632_Saved32_esp)
-	movl	%ebp,A(IF1632_Saved32_ebp)
-
-	/*
-	 * Load initial registers
-	 */
-	movw	A(WIN_StackSize),%bx
-	movw	A(WIN_HeapSize),%cx
-	movl	$0,%esi
-	xorl	%eax,%eax
-	movw	A(PSPSelector),%ax
-	movw	%ax,%es
-	movw	16(%ebp),%ax
-	movw	%ax,%ds
-	movl	%eax,%edi
-	xorl	%eax,%eax
-	movw	12(%ebp),%ax
-	movl	%eax,%esp
-	movw	14(%ebp),%ax
-	movw	%ax,%ss
-	movl	%esp,%eax
-	movl	%eax,%ebp
-	movw	$UDATASEL,%ax
-	movw	%ax,%fs
-	movw	%ax,%gs
-	movw	%ds,%ax
-
-	/*
-	 * Call entry point
-	 */
-	.byte	0x66
-	lcall	%fs:(%edx)
-
-	/*
-	 * Restore old stack and segment registers.
-	 *
-	 * Two choices here:
-	 *	1. Trust that fs or gs hasn't changed.
-	 *	2. Rely on knowledge of Linux use of segments.
-	 *
-	 * I'll opt for choice 2 because who knows what programs we
-	 * going to run.  Linux should be fairly stable in terms of
-	 * GDT usage.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	movw	%ax,%fs
-	movw	%ax,%gs
-	popl	%eax
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	popw	A(IF1632_Saved32_ss)
-	popl	A(IF1632_Saved32_ebp)
-	popl	A(IF1632_Saved32_esp)
-	movl	%eax,return_value
-#ifdef __ELF__
-	/* change back  */
-	movw	$0x23, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L5, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L5:
-#endif
-	popal
-	movl	return_value,%eax
-	.align	2,0x90
-	leave
-	ret
-
-/**********************************************************************
- *	int CallTo16  (unsigned long csip, unsigned short ds)
- *      int CallTo16cx(unsigned long csip, unsigned long dscx);
- *
- *	Stack:	 	0	ebp
- *		 	4	eip
- *		 	8	target ip
- *			10	target cs
- *			12	target ds
- *			14      target cx  (only CallTo16cx)
- *                      16      target di
- */
-	.align	4
-	.globl A(CallTo16), A(CallTo16cx), A(CallToLibMain)
-A(CallToLibMain:)
-        pushl   %ebp
-        movl    %esp,%ebp
-        movw    16(%ebp),%di
-        movw    0,%si
-        movw    0,%es
-        jmp     L1
-A(CallTo16:)
-A(CallTo16cx:)
-	pushl	%ebp
-	movl	%esp,%ebp
-
-	/*
-	 * Get target address and new ds
-	 */
-L1:
-#ifdef __ELF__
-	/* change code segments */
-	movw	$0x0f, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L2, %eax
-	andl	$0x0000ffff, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L2:
-#endif
-	/* At this point we have changed segments. */
-	movl	8(%ebp),%eax
-	movl	%eax,jump_target
-	lea	jump_target,%edx
-	movw	12(%ebp),%ax
-	movw	14(%ebp),%cx
-
-	/*
-	 * Switch to 16-bit stack
-	 */
-	pushl	A(IF1632_Saved32_esp)
-	pushl	A(IF1632_Saved32_ebp)
-	pushw	A(IF1632_Saved32_ss)
-
-	movw	%ss,A(IF1632_Saved32_ss)
-	movl	%esp,A(IF1632_Saved32_esp)
-	movl	%ebp,A(IF1632_Saved32_ebp)
-
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	/*
-	 * Call entry point
-	 */
- 	movw	%ax,%ds
-	movw	%ax,%di
-	.byte	0x66
-	lcall	%fs:(%edx)
-
-	/*
-	 * Restore old stack and segment registers.
-	 *
-	 * Two choices here:
-	 *	1. Trust that fs or gs hasn't changed.
-	 *	2. Rely on knowledge of Linux use of segments.
-	 *
-	 * I'll opt for choice 2 because who knows what programs we
-	 * going to run.  Linux should be fairly stable in terms of
-	 * GDT usage.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	movw	%ax,%fs
-	movw	%ax,%gs
-	popl	%eax
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%esp,A(IF1632_Saved16_sp)
-	movw	%ebp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	popw	A(IF1632_Saved32_ss)
-	popl	A(IF1632_Saved32_ebp)
-	popl	A(IF1632_Saved32_esp)
-
-	movl	%eax,return_value
-	movw	return_value+2,%dx
-	/* switch segments */
-#ifdef __ELF__
-	movw	$0x23, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L3, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L3:
-	/* back in the regular segment set up. */
-	/* restore eax */
-	movl	return_value, %eax
-#endif
-	.align	2,0x90
-	leave
-	ret
-
-/**********************************************************************
- *	CallTo32()
- *
- *	This function is called as a relay point to the built function
- *	handler.  KERNEL, USER and GDI calls are dealt with by this
- *	handler.  Calls to these DLLs will be mapped to a call handler
- *	which will set EAX to a number indicating which DLL and which
- *	function within that DLL.
- *
- *	This function will pass to the function handler two arguments.
- *	The first argument will be the contents of EAX, the second
- *	argument will be a segment:offset pair that points to the
- *	16-bit stack.
- */
-	.align	4
-	.globl A(CallTo32)
-A(CallTo32:)
-	andl	$0x0000ffff,%esp
-	pushw	%bp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	pushw	%ds
-
-	/*
-	 * Restore segment registers.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	popl	%eax
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	pushw	A(IF1632_Saved16_sp)
-	pushw	A(IF1632_Saved16_bp)
-	pushw	A(IF1632_Saved16_ss)
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%sp,A(IF1632_Saved16_sp)
-	movw	%bp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
-	 * Call entry point
-	 */
-	pushl	%edx
-	pushw	A(IF1632_Saved16_ss)
-	pushw	A(IF1632_Saved16_sp)
-	pushl	%eax
-	call	A(DLLRelay)
-
-	popl	%edx
-	popl	%edx
-	popl	%edx
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	popw	%gs:nbytes
-	cmpw	$0,%gs:nbytes
-	je	noargs
-	popw	%gs:offset
-	popw	%gs:selector
-	addw	%gs:nbytes,%esp
-	pushw	%gs:selector
-	pushw	%gs:offset
-noargs:
-
-	/*
-	 * Last, but not least we need to move the high word from eax to dx
-	 */
-
-	pushl	%eax
-	popw	%dx
-	popw	%dx
-
-	.byte	0x66
-	lret
-
-/**********************************************************************
- *	CallTo32_16()
- *
- *	This function is same one as CallTo32() except that the high
- *	word of EAX won't be moved to DX.
- */
-	.align	4
-	.globl A(CallTo32_16)
-A(CallTo32_16:)
-	andl	$0x0000ffff,%esp
-	pushw	%bp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	pushw	%ds
-
-	/*
-	 * Restore segment registers.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	popl	%eax
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	pushw	A(IF1632_Saved16_sp)
-	pushw	A(IF1632_Saved16_bp)
-	pushw	A(IF1632_Saved16_ss)
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%esp,A(IF1632_Saved16_sp)
-	movw	%ebp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
-	 * Call entry point
-	 */
-	pushl	%edx
-	pushw	A(IF1632_Saved16_ss)
-	pushw	A(IF1632_Saved16_sp)
-	pushl	%eax
-	call	A(DLLRelay)
-
-	popl	%edx
-	popl	%edx
-	popl	%edx
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	popw	%gs:nbytes
-	cmpw	$0,%gs:nbytes
-	je	noargs2
-	popw	%gs:offset
-	popw	%gs:selector
-	addw	%gs:nbytes,%esp
-	pushw	%gs:selector
-	pushw	%gs:offset
-noargs2:
-	.byte	0x66
-	lret
-
-/**********************************************************************
- *	ReturnFromRegisterFunc()
- */
-	.globl A(ReturnFromRegisterFunc)
-A(ReturnFromRegisterFunc:)
-	/*
- 	 * Restore 16-bit stack
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * This leaves us with a stack that has number of arguments,
-	 * the return address, the saved registers, and the return 
-	 * address again.
-	 */
-	add	$6,%esp		/* argument count, return address */
-#include "pop.h"		/* restore context                */
-
-	/*
-	 * Return to original caller.
-	 */
-	.byte	0x66
-	lret
-
diff --git a/if1632/callback.c b/if1632/callback.c
index db210f2e6112f8885e6f434c96a1ee3430b1d6ac..a941b16045db27c0826e4af50304b5d3f374fd6a 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -7,18 +7,17 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
+#include <setjmp.h>
 #include "windows.h"
 #include "callback.h"
 #include "wine.h"
-#include <setjmp.h>
-#include "ldt.h"
+#include "global.h"
 #include "stackframe.h"
 #include "dlls.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "if1632.h"
 
-extern unsigned short IF1632_Saved32_ss;
 extern unsigned long  IF1632_Saved32_ebp;
 extern unsigned long  IF1632_Saved32_esp;
 
@@ -30,64 +29,6 @@ struct thunk_s
     unsigned char thunk[8];
 };
 
-#ifdef __ELF__
-#define FIRST_SELECTOR 2
-#define IS_16_BIT_ADDRESS(addr)  \
-    (((unsigned int)(addr) < 0x8000000) || ((unsigned int)(addr) >= 0x8400000))
-#else
-#define FIRST_SELECTOR	8
-#define IS_16_BIT_ADDRESS(addr)  \
-     ((unsigned int)(addr) >= (((FIRST_SELECTOR << __AHSHIFT) | 7) << 16))
-#endif
-
-/**********************************************************************
- *					PushOn16
- */
-static void
-PushOn16(int size, unsigned int value)
-{
-    char *p = PTR_SEG_OFF_TO_LIN( IF1632_Saved16_ss, IF1632_Saved16_sp );
-    if (size)
-    {
-	unsigned long *lp = (unsigned long *) p - 1;
-	
-	*lp = value;
-	IF1632_Saved16_sp -= 4;
-    }
-    else
-    {
-	unsigned short *sp = (unsigned short *) p - 1;
-	
-	*sp = value;
-	IF1632_Saved16_sp -= 2;
-    }
-}
-
-
-/**********************************************************************
- *					CallBack16
- */
-int
-CallBack16(void *func, int n_args, ...)
-{
-    va_list ap;
-    int i;
-    int arg_type, arg_value;
-    WORD ds = CURRENT_DS;
-
-    va_start(ap, n_args);
-
-    for (i = 0; i < n_args; i++)
-    {
-	arg_type = va_arg(ap, int);
-	arg_value = va_arg(ap, int);
-	PushOn16(arg_type, arg_value);
-    }
-
-    va_end(ap);
-
-    return CallTo16((unsigned int) func, ds );
-}
 
 /**********************************************************************
  *					MakeProcInstance
@@ -100,18 +41,8 @@ FARPROC MakeProcInstance( FARPROC func, WORD instance )
 
     if (!ThunkSelector)
     {
-        ldt_entry entry;
-
-          /* Allocate a segment for thunks */
-        ThunkSelector = AllocSelector( 0 );
-        entry.base           = (unsigned long) malloc( 0x10000 );
-        entry.limit          = 0xffff;
-        entry.seg_32bit      = 0;
-        entry.limit_in_pages = 0;
-        entry.type           = SEGMENT_CODE;
-        entry.read_only      = 0;
-        memset( (char *)entry.base, 0, 0x10000 );
-        LDT_SetEntry( SELECTOR_TO_ENTRY(ThunkSelector), &entry );
+        HGLOBAL handle = GLOBAL_Alloc( GMEM_ZEROINIT, 0x10000, 0, TRUE, FALSE);
+        ThunkSelector = GlobalHandleToSel(handle);
     }
 
     thunks = (char *)PTR_SEG_OFF_TO_LIN( ThunkSelector, 0 );
@@ -173,110 +104,9 @@ LONG CallWindowProc( WNDPROC func, HWND hwnd, WORD message,
 		     WORD wParam, LONG lParam )
 {
     SpyMessage(hwnd, message, wParam, lParam);
-
-    if (HIWORD((LONG)func) == WINE_CODE_SELECTOR) 
-    {
-	static struct dll_table_entry_s *user_tab = NULL;
-	void *address = (void *) ((LONG) func & 0xffff);
-
-	if (user_tab == NULL)
-	    user_tab = FindDLLTable("USER");
-
-	/* DefWindowProc */
-	if (((LONG)user_tab[107].address &0xffff) == (LONG) address)
-	    return DefWindowProc(hwnd, message, wParam, lParam);
-	
-	/* DefDlgProc */
-	else if (((LONG)user_tab[308].address &0xffff) == (LONG)address)
-	    return DefDlgProc(hwnd, message, wParam, lParam);
-	
-	/* DefMDIChildProc */
-	else if (((LONG)user_tab[447].address &0xffff) == (LONG)address)
-	    return DefMDIChildProc(hwnd, message, wParam, lParam);
-	
-	/* default */
-	else
-	{
-	    fprintf(stderr, "wine: Unknown wine callback %08x\n", 
-	    	(unsigned int) func);
-	    exit(1);
-	}
-    }
-    else if (IS_16_BIT_ADDRESS(func))
-    {	
-        WORD ds = CURRENT_DS;
-	dprintf_callback(stddeb, "CallWindowProc // 16bit func=%08x ds=%04x!\n", 
-		(unsigned int) func, ds );
-	PushOn16( CALLBACK_SIZE_WORD, hwnd );
-	PushOn16( CALLBACK_SIZE_WORD, message );
-	PushOn16( CALLBACK_SIZE_WORD, wParam );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	dprintf_callback(stddeb, "CallWindowProc // 32bit func=%08X !\n",
-		(unsigned int) func);
-	return (*func)(hwnd, message, wParam, lParam);
-    }
+    return CallWndProc( (FARPROC)func, hwnd, message, wParam, lParam );
 }
 
-/**********************************************************************
- *					CallLineDDAProc
- */
-void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam)
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, xPos );
-	PushOn16( CALLBACK_SIZE_WORD, yPos );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	(*func)(xPos, yPos, lParam);
-    }
-}
-
-/**********************************************************************
- *					CallHookProc
- */
-DWORD CallHookProc( HOOKPROC func, short code, WPARAM wParam, LPARAM lParam )
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, code );
-	PushOn16( CALLBACK_SIZE_WORD, wParam );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	return (*func)( code, wParam, lParam );
-    }
-}
-
-/**********************************************************************
- *					CallGrayStringProc
- */
-BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch )
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, hdc );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	PushOn16( CALLBACK_SIZE_WORD, cch );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	return (*func)( hdc, lParam, cch );
-    }
-}
 
 /* ------------------------------------------------------------------------ */
 /*
@@ -295,7 +125,7 @@ BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch )
 
 struct special_buffer {
 	jmp_buf buffer;
-	long 	regs [6];
+	long 	regs [5];
 	char 	stack_part [STACK_DEPTH_16];
 } *sb;
 
@@ -303,8 +133,6 @@ int Catch (LPCATCHBUF cbuf)
 {
 	WORD retval;
 	jmp_buf *tmp_jmp;
-	char *stack16 =  (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
-                                   IF1632_Saved16_sp);
 
 	sb = malloc (sizeof (struct special_buffer));
 	
@@ -313,8 +141,7 @@ int Catch (LPCATCHBUF cbuf)
 	sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
 	sb -> regs [3] = IF1632_Saved32_esp;
 	sb -> regs [4] = IF1632_Saved32_ebp;
-	sb -> regs [5] = IF1632_Saved32_ss & 0xffff;
-	memcpy (sb -> stack_part, stack16, STACK_DEPTH_16);
+	memcpy (sb -> stack_part, CURRENT_STACK16, STACK_DEPTH_16);
 	tmp_jmp = &sb -> buffer;
 	*((struct special_buffer **)cbuf) = sb;
 	
@@ -325,11 +152,8 @@ int Catch (LPCATCHBUF cbuf)
 		IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
 		IF1632_Saved32_esp = sb -> regs [3];
 		IF1632_Saved32_ebp = sb -> regs [4];
-		IF1632_Saved32_ss = sb -> regs [5] & 0xffff;
-		stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
-                                    IF1632_Saved16_sp);
 
-		memcpy (stack16, sb -> stack_part, STACK_DEPTH_16);
+		memcpy (CURRENT_STACK16, sb -> stack_part, STACK_DEPTH_16);
 		dprintf_catch (stddeb, "Been thrown here: %d, retval = %d\n", 
 			(int) sb, (int) retval);
 		free ((void *) sb);
diff --git a/if1632/compobj.spec b/if1632/compobj.spec
index a4b0993a28b1d0cebd14d055a5d0e305072d861b..06618a80a691bf71a747925d17b00962c1118e11 100644
--- a/if1632/compobj.spec
+++ b/if1632/compobj.spec
@@ -16,7 +16,7 @@ length	163
 #12 COFREEALLLIBRARIES
 #13 COCREATEINSTANCE
 #14 STRINGFROMIID
-#15 CODISCONNECTOBJECT
+15 pascal CoDisconnectObject(ptr long) CoDisconnectObject
 #16 CORELEASEMARSHALDATA
 #17 COFREEUNUSEDLIBRARIES
 #18 ISEQUALGUID
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index ea1197043ae3081af7e80735e7179a913baadbb4..4389097cc8d2f79c1e462efa8b28a056b7fa555c 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -212,7 +212,7 @@ length	490
 #310 pascal CREATESCALABLEFONTRESOURCE
 #311 pascal GETFONTDATA
 #312 pascal CONVERTOUTLINEFONTFILE
-#313 pascal GETRASTERIZERCAPS
+313 pascal16 GetRasterizerCaps(ptr word) GetRasterizerCaps
 #314 pascal ENGINEEXTTEXTOUT
 330 pascal16 EnumFontFamilies(word ptr segptr long) EnumFontFamilies
 #332 pascal GETKERNINGPAIRS
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index a9eec0580cb201672971853d988d67abd22347a6..bdaa2ef169bbfce5169dfc1bf4771d99714c90c3 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -207,10 +207,10 @@ length	415
 #318 FATALEXITHOOK
 #319 FLUSHCACHEDFILEHANDLE
 #320 ISTASK
-323 pascal IsRomModule() IsRomModule
+323 return IsRomModule 2 0
 #324 LOGERROR
 #325 LOGPARAMERROR
-#326 ISROMFILE
+326 return IsRomFile 2 0
 #327 K327
 #328 _DEBUGOUTPUT
 #329 K329
@@ -237,5 +237,5 @@ length	415
 #354 GETAPPCOMPATFLAGS
 #355 GETWINDEBUGINFO
 #356 SETWINDEBUGINFO
-#403 K403
-#404 K404
+403 pascal16 FarSetOwner(word word) FarSetOwner
+404 pascal16 FarGetOwner(word) FarGetOwner
diff --git a/if1632/olecli.spec b/if1632/olecli.spec
index ea211077980bba5dadc122ca35bbb98da59b1643..97c3ded4f8d4085f7de55952acaf02042cd478df 100644
--- a/if1632/olecli.spec
+++ b/if1632/olecli.spec
@@ -1,8 +1,6 @@
 name	olecli
 id	20
-length	43
-## 954 is too large for now
-##length	954
+length	954
 
 #1 WEP
 #2 OLEDELETE
diff --git a/if1632/relay.c b/if1632/relay.c
index e717b5af7d325616bb4aa130142c2eb60c714faa..c855e8192bd26dbb257ce9186050ab62df2b7443 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -23,16 +23,16 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #include "prototypes.h"
 #include "dlls.h"
 #include "options.h"
+#include "selectors.h"
 #include "stackframe.h"
+#include "wine.h"
 #include "stddebug.h"
 /* #define DEBUG_RELAY */
-/* #define DEBUG_STACK */
 #include "debug.h"
 
 #if 0
 /* Make make_debug think these were really used */
 dprintf_relay
-dprintf_stack
 #endif
 
 #ifdef WINELIB
@@ -43,256 +43,210 @@ dprintf_stack
 
 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
 {
-    { "KERNEL",  WineLibSkip(KERNEL_table), 	410, 1, 1 },
-    { "USER",    WineLibSkip(USER_table), 	540, 2, 1 },
-    { "GDI",     WineLibSkip(GDI_table), 	490, 3, 1 },
-    { "WIN87EM", WineLibSkip(WIN87EM_table),  10, 4, 1 },
-    { "SHELL",   WineLibSkip(SHELL_table),   103, 5, 1 },
-    { "SOUND",   WineLibSkip(SOUND_table),    20, 6, 1 },
-    { "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 7, 1 },
-    { "WINSOCK", WineLibSkip(WINSOCK_table), 155, 8, 1 },
-    { "STRESS",  WineLibSkip(STRESS_table),   15, 9, 1},
-    { "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,10, 1},
-    { "SYSTEM",  WineLibSkip(SYSTEM_table),   20 ,11, 1},
-    { "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 12, 1},
-    { "MOUSE",   WineLibSkip(MOUSE_table),     8, 13, 1},
-    { "COMMDLG", WineLibSkip(COMMDLG_table),  31, 14, 1},
-    { "OLE2",    WineLibSkip(OLE2_table),     31, 15, 1},
-    { "OLE2CONV",WineLibSkip(OLE2CONV_table), 31, 16, 1},
-    { "OLE2DISP",WineLibSkip(OLE2DISP_table), 31, 17, 1},
-    { "OLE2NLS", WineLibSkip(OLE2NLS_table),  31, 18, 1},
-    { "OLE2PROX",WineLibSkip(OLE2PROX_table), 31, 19, 1},
-    { "OLECLI",  WineLibSkip(OLECLI_table),   31, 20, 1},
-    { "OLESVR",  WineLibSkip(OLESVR_table),   31, 21, 1},
-    { "COMPOBJ", WineLibSkip(COMPOBJ_table),  31, 22, 1},
-    { "STORAGE", WineLibSkip(STORAGE_table),  31, 23, 1}
+    { "KERNEL",   WineLibSkip(&KERNEL_table), 1 },
+    { "USER",     WineLibSkip(&USER_table), 1 },
+    { "GDI",      WineLibSkip(&GDI_table), 1 },
+    { "WIN87EM",  WineLibSkip(&WIN87EM_table), 1 },
+    { "SHELL",    WineLibSkip(&SHELL_table), 1 },
+    { "SOUND",    WineLibSkip(&SOUND_table), 1 },
+    { "KEYBOARD", WineLibSkip(&KEYBOARD_table), 1 },
+    { "WINSOCK",  WineLibSkip(&WINSOCK_table), 1 },
+    { "STRESS",   WineLibSkip(&STRESS_table), 1 },
+    { "MMSYSTEM", WineLibSkip(&MMSYSTEM_table), 1 },
+    { "SYSTEM",   WineLibSkip(&SYSTEM_table), 1 },
+    { "TOOLHELP", WineLibSkip(&TOOLHELP_table), 1 },
+    { "MOUSE",    WineLibSkip(&MOUSE_table), 1 },
+    { "COMMDLG",  WineLibSkip(&COMMDLG_table), 1 },
+    { "OLE2",     WineLibSkip(&OLE2_table), 1 },
+    { "OLE2CONV", WineLibSkip(&OLE2CONV_table), 1 },
+    { "OLE2DISP", WineLibSkip(&OLE2DISP_table), 1 },
+    { "OLE2NLS",  WineLibSkip(&OLE2NLS_table), 1 },
+    { "OLE2PROX", WineLibSkip(&OLE2PROX_table), 1 },
+    { "OLECLI",   WineLibSkip(&OLECLI_table), 1 },
+    { "OLESVR",   WineLibSkip(&OLESVR_table), 1 },
+    { "COMPOBJ",  WineLibSkip(&COMPOBJ_table), 1 },
+    { "STORAGE",  WineLibSkip(&STORAGE_table), 1 },
+    { "WINPROCS", WineLibSkip(&WINPROCS_table), 1 },
 };
-/* don't forget to increase N_BUILTINS in dll.h if you add a dll */
-
-/* the argument conversion tables for each dll */
-struct dll_conversions {
-	unsigned short *dst_args;   /*  Offsets to arguments on stack */
-	unsigned char *src_types;   /* Argument types              */
-} dll_conversion_table[N_BUILTINS]= {
-  { KERNEL_offsets,   KERNEL_types },   /* KERNEL     */
-  { USER_offsets,     USER_types },     /* USER       */
-  { GDI_offsets,      GDI_types },      /* GDI        */
-  { WIN87EM_offsets,  WIN87EM_types },  /* WIN87EM    */
-  { SHELL_offsets,    SHELL_types },    /* SHELL      */
-  { SOUND_offsets,    SOUND_types },    /* SOUND      */
-  { KEYBOARD_offsets, KEYBOARD_types }, /* KEYBOARD   */
-  { WINSOCK_offsets,  WINSOCK_types },  /* WINSOCK    */
-  { STRESS_offsets,   STRESS_types },   /* STRESS,     */
-  { MMSYSTEM_offsets, MMSYSTEM_types }, /* MMSYSTEM   */
-  { SYSTEM_offsets,   SYSTEM_types },   /* SYSTEM     */
-  { TOOLHELP_offsets, TOOLHELP_types }, /* TOOLHELP   */
-  { MOUSE_offsets,    MOUSE_types },    /* MOUSE      */
-  { COMMDLG_offsets,  COMMDLG_types },  /* EMUCOMMDLG */
-  { OLE2_offsets,     OLE2_types },     /* OLE2       */
-  { OLE2CONV_offsets, OLE2CONV_types }, /* OLE2CONV   */
-  { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2DISP   */
-  { OLE2NLS_offsets,  OLE2NLS_types },  /* OLE2NLS    */
-  { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2PROX   */
-  { OLECLI_offsets,   OLECLI_types },   /* OLE2CLI    */
-  { OLESVR_offsets,   OLESVR_types },   /* OLE2CLI    */
-  { COMPOBJ_offsets,  COMPOBJ_types },  /* COMPOBJ    */
-  { STORAGE_offsets,  STORAGE_types }   /* STORAGE    */
-};
-
+/* don't forget to increase N_BUILTINS in dlls.h if you add a dll */
 
-#ifndef WINELIB
+  /* Saved 16-bit stack */
+WORD IF1632_Saved16_ss = 0;
+WORD IF1632_Saved16_sp = 0;
+WORD IF1632_Saved16_bp = 0;
 
-extern unsigned short IF1632_Saved16_sp;
-extern unsigned short IF1632_Saved16_bp;
-extern unsigned short IF1632_Saved16_ss;
+  /* Saved 32-bit stack */
+DWORD IF1632_Saved32_esp = 0;
+DWORD IF1632_Saved32_ebp = 0;
 
-void RelayDebug( unsigned int func_num )
+/***********************************************************************
+ *           RELAY_Init
+ */
+BOOL RELAY_Init(void)
 {
-    unsigned int dll_id, ordinal;
+    WORD codesel, datasel;
+    struct dll_table_s *table;
+    struct dll_table_entry_s *entry;
+    int i, j;
+
+      /* Allocate the code selector for CallTo16 routines */
+
+    extern void CALL16_Start(), CALL16_End();
+    extern void CALL16_Ret_word(), CALL16_Ret_long();
+    extern DWORD CALL16_RetAddr_word, CALL16_RetAddr_long;
+
+    codesel = SELECTOR_AllocBlock( (void *)CALL16_Start,
+                                   (int)CALL16_End - (int)CALL16_Start,
+                                   SEGMENT_CODE, TRUE, FALSE );
+    if (!codesel) return FALSE;
+
+      /* Patch the return addresses for CallTo16 routines */
 
-    if (debugging_relay)
+    CALL16_RetAddr_word = MAKELONG( (int)CALL16_Ret_word - (int)CALL16_Start,
+                                    codesel );
+    CALL16_RetAddr_long = MAKELONG( (int)CALL16_Ret_long - (int)CALL16_Start,
+                                    codesel );
+
+      /* Allocate the selectors for built-in dlls */
+
+    for (i = 0; i < N_BUILTINS; i++)
     {
-        dll_id  = ((func_num >> 16) & 0xffff) - 1;
-        ordinal = func_num & 0xffff;
-        printf( "Calling %s.%d\n",
-               dll_builtin_table[dll_id].dll_table[ordinal].export_name,
-               ordinal );
+        table = dll_builtin_table[i].table;
+        codesel = SELECTOR_AllocBlock( table->code_start,
+                                   (int)table->code_end-(int)table->code_start,
+                                   SEGMENT_CODE, TRUE, FALSE );
+        if (!codesel) return FALSE;
+        if (table->data_start != table->data_end)
+            datasel = SELECTOR_AllocBlock( table->data_start,
+                                   (int)table->data_end-(int)table->data_start,
+                                   SEGMENT_DATA, TRUE, FALSE );
+        else datasel = 0;
+        entry = table->dll_table;
+        for (j = 0; j < table->dll_table_length; j++, entry++)
+        {
+            if (entry->selector == 1)  /* code selector */
+                entry->selector = codesel;
+            else if (entry->selector == 2)  /* data selector */
+                entry->selector = datasel;
+            else entry->selector = 0;  /* constant selector */
+        }
     }
+
+    return TRUE;
 }
 
 
-/**********************************************************************
- *					DLLRelay
- *
- * We get a stack frame pointer to data that looks like this:
- *
- *   Hex Offset Contents
- *   ---------- -------
- *	+00	previous saved_16ss
- *	+02	previous saved_16ebp
- *	+06	previous saved_16esp
- *	+0A	16-bit es
- *	+0C	16-bit ds
- *	+0E	16-bit ebp
- *	+12	length of 16-bit arguments
- *	+14	16-bit ip
- *	+16	16-bit cs
- *	+18	arguments
- */
-int
-DLLRelay(unsigned int func_num, unsigned int seg_off)
+#ifndef WINELIB
+
+void RELAY_DebugCall32( char *args )
 {
-    struct dll_table_entry_s *dll_p;
-    STACK16FRAME *pStack16Frame;
-    unsigned int offset;
-    unsigned int dll_id;
-    unsigned int ordinal;
-    int arg_table[DLL_MAX_ARGS];
-    void *arg_ptr;
-    int (*func_ptr)();
+    STACK16FRAME *frame;
+    char *args16;
     int i;
-    int ret_val;
-    int conv_ref;
-    unsigned char *type_conv;
-    unsigned short *offset_conv;
-    STACK16FRAME stackFrameCopy;
-
-    /*
-     * Determine address of arguments.
-     */
-    pStack16Frame = (STACK16FRAME *) PTR_SEG_TO_LIN(seg_off);
-    arg_ptr = (void *)pStack16Frame->args;
-
-    /*
-     * Extract the DLL number and ordinal number.
-     */
-    dll_id  = ((func_num >> 16) & 0xffff) - 1;
-    ordinal = func_num & 0xffff;
-    dll_p   = &dll_builtin_table[dll_id].dll_table[ordinal];
-
-    dprintf_relay( stddeb, "Call %s (%s.%d), stack=%04x:%04x ret=%04x:%04x ds=%04x bp=%04x args=%d\n",
-                  dll_p->export_name,
-                  dll_builtin_table[dll_id].dll_name, ordinal,
-                  seg_off >> 16, seg_off & 0xffff,
-                  pStack16Frame->cs, pStack16Frame->ip,
-                  pStack16Frame->ds, pStack16Frame->bp,
-                  pStack16Frame->arg_length );
-
-    if(debugging_stack)
+
+    if (!debugging_relay) return;
+
+    frame = CURRENT_STACK16;
+    printf( "Call %s.%d: %s(",
+            dll_builtin_table[frame->dll_id-1].dll_name,
+            frame->ordinal_number,
+            dll_builtin_table[frame->dll_id-1].table->dll_table[frame->ordinal_number].export_name );
+    args16 = (char *)frame->args;
+    for (i = 0; i < strlen(args); i++)
     {
-        unsigned short *stack_p = (unsigned short *) pStack16Frame;
-        /* FIXME: Is there an end-of-stack-pointer somewhere ? */
-        int n = min(24, (0x10000 - (seg_off & 0xffff)) / sizeof(*stack_p));
-        for (i = 0; i < n; i++, stack_p++)
+        switch(args[i])
         {
-            printf("%04x ", *stack_p);
-            if ((i & 7) == 7)
-                printf("\n");
+        case 'w':
+        case 's':
+            args16 += 2;
+            break;
+        case 'l':
+        case 'p':
+            args16 += 4;
+            break;
         }
-        printf("\n");
     }
 
-    /*
-     * Make sure we have a handler defined for this call.
-     */
-    if (dll_p->handler == NULL)
+    while (*args)
     {
-	char buffer[100];
-	
-	sprintf(buffer, "No handler for routine %s.%d", 
-		dll_builtin_table[dll_id].dll_name, ordinal);
-	myerror(buffer);
-    }
-    func_ptr = dll_p->handler;
-
-    /*
-     * OK, special case.  If the handler is define as taking no arguments
-     * then pass the address of the arguments on the 16-bit stack to the
-     * handler.  It will just ignore the pointer if it really takes no
-     * arguments.  This allows us to write slightly faster library routines
-     * if we choose.
-     */
-    if (dll_p->n_args == 0)
-    {
-	ret_val = (*func_ptr)(arg_ptr);
-	dprintf_relay( stddeb, "Returning %08x from %s (%s.%d) ds=%04x\n",
-                       ret_val, dll_p->export_name,
-                       dll_builtin_table[dll_id].dll_name, ordinal,
-                       pStack16Frame->ds );
-	return ret_val;
+        switch(*args)
+        {
+        case 'w':
+        case 's':
+            args16 -= 2;
+            printf( "0x%04x", *(WORD *)args16 );
+            break;
+        case 'l':
+            args16 -= 4;
+            printf( "0x%08x", *(int *)args16 );
+            break;
+        case 'p':
+            args16 -= 4;
+            printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+            break;
+        }
+        args++;
+        if (*args) printf( "," );
     }
+    printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
+}
 
-    /*
-     * Getting this far means we need to convert the 16-bit argument stack.
-     */
-    conv_ref= dll_p->conv_reference;
-    type_conv= dll_conversion_table[dll_id].src_types + conv_ref;
-    offset_conv= dll_conversion_table[dll_id].dst_args + conv_ref;
-    for (i = 0; i < dll_p->n_args; i++,type_conv++,offset_conv++)
-    {
-	short *sp;
-	int *ip;
-	
-	offset = *offset_conv;
-
-	switch (*type_conv)
-	{
-	  case DLL_ARGTYPE_SIGNEDWORD:
-	    sp = (short *) ((char *) arg_ptr + offset);
-	    arg_table[i] = *sp;
-	    break;
-	    
-	  case DLL_ARGTYPE_WORD:
-	    sp = (short *) ((char *) arg_ptr + offset);
-	    arg_table[i] = (int) *sp & 0xffff;
-	    break;
-	    
-	  case DLL_ARGTYPE_LONG:
-	    ip = (int *) ((char *) arg_ptr + offset);
-	    arg_table[i] = *ip;
-	    break;
 
-	  case DLL_ARGTYPE_FARPTR:
-	    ip = (int *) ((char *) arg_ptr + offset);
-            arg_table[i] = (unsigned int) PTR_SEG_TO_LIN( *ip );
-	    break;
-	}
-    }
+void RELAY_DebugReturn( int short_ret, int ret_val )
+{
+    STACK16FRAME *frame;
 
-    if (debugging_relay)
-        memcpy( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) );
+    if (!debugging_relay) return;
 
-    /*
-     * Call the handler
-     */
-    ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2], 
-			  arg_table[3], arg_table[4], arg_table[5], 
-			  arg_table[6], arg_table[7], arg_table[8], 
-			  arg_table[9], arg_table[10], arg_table[11],
-			  arg_table[12], arg_table[13], arg_table[14], 
-			  arg_table[15]);
+    frame = CURRENT_STACK16;
+    printf( "Ret  %s.%d: %s() ",
+            dll_builtin_table[frame->dll_id-1].dll_name,
+            frame->ordinal_number,
+            dll_builtin_table[frame->dll_id-1].table->dll_table[frame->ordinal_number].export_name );
+    if (short_ret) printf( "retval=0x%04x\n", ret_val & 0xffff );
+    else printf( "retval=0x%08x\n", ret_val );
+}
 
-    if (debugging_relay)
-    {
-        if (memcmp( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) ))
-        {
-            printf( "**** 16-bit stack corrupted!\n" );
-        }
-	printf("Returning %08x from %s (%s.%d) ds=%04x\n",
-	       ret_val,
-	       dll_p->export_name,
-	       dll_builtin_table[dll_id].dll_name, ordinal,
-               pStack16Frame->ds );
-    }
 
-    return ret_val;
+void RELAY_Unimplemented(void)
+{
+    STACK16FRAME *frame = CURRENT_STACK16;
+
+    fprintf( stderr, "No handler for routine %s.%d\n",
+             dll_builtin_table[frame->dll_id-1].dll_name,
+             frame->ordinal_number );
+    exit(1);
 }
-#endif
+
+
+/***********************************************************************
+ *           RELAY_DebugCall16
+ *
+ * 'stack' points to the called function address on the 32-bit stack.
+ * Stack layout:
+ *  ...        ...
+ * (stack+12)  arg2
+ * (stack+8)   arg1
+ * (stack+4)   16-bit ds
+ * (stack)     func to call
+ */
+void RELAY_DebugCall16( int* stack, int nbargs )
+{
+    if (!debugging_relay) return;
+
+    printf( "CallTo16(func=%04x:%04x,ds=%04x",
+            HIWORD(stack[0]), LOWORD(stack[0]), LOWORD(stack[1]) );
+    stack += 2;
+    while (nbargs--) printf( ",0x%x", *stack++ );
+    printf( ")\n" );
+}
+
+#endif  /* WINELIB */
 
 /**********************************************************************
  *					FindDLLTable
  */
-struct  dll_table_entry_s *
+struct dll_table_s *
 FindDLLTable(char *dll_name)
 {
     int i;
@@ -300,11 +254,7 @@ FindDLLTable(char *dll_name)
     for (i = 0; i < N_BUILTINS; i++)
 	if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0
 	  && dll_builtin_table[i].dll_is_used)
-#ifdef WINELIB
-	    return dll_builtin_table[i].dll_number;
-#else
-	    return dll_builtin_table[i].dll_table;
-#endif
+	    return dll_builtin_table[i].table;
     return NULL;
 }
 
@@ -317,27 +267,19 @@ FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name)
     int i, limit;
 
     for (i = 0; i < N_BUILTINS; i++)
-	if (dll_table == dll_builtin_table[i].dll_table)
+	if (dll_table == dll_builtin_table[i].table->dll_table)
 	    break;
     
     if (i == N_BUILTINS)
 	return 0;
 
-    limit = dll_builtin_table[i].dll_table_length;
+    limit = dll_builtin_table[i].table->dll_table_length;
     for (i = 0; i < limit; i++)
 	if (strcasecmp(dll_table[i].export_name, func_name) == 0)
 	    return i;
     
     return 0;
 }
-/**********************************************************************
- *					ReturnArg
- */
-int
-ReturnArg(int arg)
-{
-    return arg;
-}
 
 #ifndef WINELIB
 #ifdef WINESTAT
@@ -351,13 +293,13 @@ void winestat(){
 	tused = 0;
 	timplemented = 0;
     for (i = 0; i < N_BUILTINS; i++) {
-	    table = dll_builtin_table[i].dll_table;
+	    table = dll_builtin_table[i].table->dll_table;
 	    used = 0;
 	    implemented = 0;
-	    for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
+	    for(j=0; j < dll_builtin_table[i].table->dll_table_length; j++) {
 		    if(table[j].used){
 			    used++;
-			    if (table[j].handler) implemented++;
+			    if (table[j].export_name[0]) implemented++;
 			    else 
 				    printf("%s.%d not implemented\n",
 					   dll_builtin_table[i].dll_name,
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 775ee81ad16bd8a12bd52cb4461cc55dc2d0a25e..a7d8243ead28906d4a226f8ad07c1c974dc19e13 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -3,11 +3,11 @@ id	12
 length	83
 
 50 pascal16 GlobalHandleToSel(word) GlobalHandleToSel
-# 51   1  0318  GLOBALFIRST exported, shared data
-# 52   1  0399  GLOBALNEXT exported, shared data
-# 53   1  02a2  GLOBALINFO exported, shared data
-# 54   1  0417  GLOBALENTRYHANDLE exported, shared data
-# 55   1  04a9  GLOBALENTRYMODULE exported, shared data
+51 pascal16 GlobalFirst(ptr word) GlobalFirst
+52 pascal16 GlobalNext(ptr word) GlobalNext
+53 pascal16 GlobalInfo(ptr) GlobalInfo
+54 pascal16 GlobalEntryHandle(ptr word) GlobalEntryHandle
+55 pascal16 GlobalEntryModule(ptr word word) GlobalEntryModule
 56 pascal16 LocalInfo(ptr word) LocalInfo
 57 pascal16 LocalFirst(ptr word) LocalFirst
 58 pascal16 LocalNext(ptr) LocalNext
@@ -24,7 +24,7 @@ length	83
 69 pascal16 ClassFirst(ptr) ClassFirst
 70 pascal16 ClassNext(ptr) ClassNext
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo
-#72 pascal16 MemManInfo(ptr) MemManInfo
+72 pascal16 MemManInfo(ptr) MemManInfo
 # 73   1  1b72  NOTIFYREGISTER exported, shared data
 # 74   1  1c29  NOTIFYUNREGISTER exported, shared data
 # 75   1  2060  INTERRUPTREGISTER exported, shared data
diff --git a/if1632/user.spec b/if1632/user.spec
index 73de7b650ded9bd9ef1e62a0b2608068f555e199..58a1a79e590166f40a80124c457fa4aae3d89eac 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -392,36 +392,36 @@ length	540
 482 pascal16 EnableScrollBar(word word word) EnableScrollBar
 483 pascal SystemParametersInfo(word word ptr word) SystemParametersInfo
 #484 __GP
-#499 WNETERRORTEXT
-#501 WNETOPENJOB
-#502 WNETCLOSEJOB
-#503 WNETABORTJOB
-#504 WNETHOLDJOB
-#505 WNETRELEASEJOB
-#506 WNETCANCELJOB
-#507 WNETSETJOBCOPIES
-#508 WNETWATCHQUEUE
-#509 WNETUNWATCHQUEUE
-#510 WNETLOCKQUEUEDATA
-#511 WNETUNLOCKQUEUEDATA
+499 pascal WNetErrorText(word ptr word) WNetErrorText
+501 pascal WNetOpenJob(ptr ptr word ptr)  WNetOpenJob
+502 pascal WNetCloseJob(word ptr ptr) WNetCloseJob
+503 pascal WNetAbortJob(ptr word) WNetAbortJob
+504 pascal WNetHoldJob(ptr word) WNetHoldJob
+505 pascal WNetReleaseJob(ptr word) WNetReleaseJob
+506 pascal WNetCancelJob(ptr word) WNetCancelJob
+507 pascal WNetSetJobCopies(ptr word word) WNetSetJobCopies
+508 pascal WNetWatchQueue(word ptr ptr word) WNetWatchQueue
+509 pascal WNetUnwatchQueue(word ptr ptr word) WNetUnwatchQueue
+510 pascal WNetLockQueueData(ptr ptr ptr) WNetLockQueueData
+511 pascal WNetUnlockQueueData(ptr) WNetUnlockQueueData
 512 pascal16 WNetGetConnection(ptr ptr ptr) WNetGetConnection
 513 pascal WNetGetCaps(word) WNetGetCaps
-#514 WNETDEVICEMODE
-#515 WNETBROWSEDIALOG
+514 pascal WNetDeviceMode(word) WNetDeviceMode
+515 pascal WNetBrowseDialog(word word ptr) WNetBrowseDialog
 516 pascal WNetGetUser(ptr ptr ptr) WNetGetUser
 517 pascal16 WNetAddConnection(ptr ptr ptr) WNetAddConnection
 518 pascal16 WNetCancelConnection(ptr word) WNetCancelConnection
-#519 WNETGETERROR
-#520 WNETGETERRORTEXT
+519 pascal WNetGetError(ptr) WNetGetError
+520 pascal WNetGetErrorText(word ptr ptr) WNetGetErrorText
 #521 WNETENABLE
 #522 WNETDISABLE
-#523 WNETRESTORECONNECTION
-#524 WNETWRITEJOB
-#525 WNETCONNECTDIALOG
-#526 WNETDISCONNECTDIALOG
-#527 WNETCONNECTIONDIALOG
-#528 WNETVIEWQUEUEDIALOG
-#529 WNETPROPERTYDIALOG
-#530 WNETGETDIRECTORYTYPE
-#531 WNETDIRECTORYNOTIFY
-#532 WNETGETPROPERTYTEXT
+523 pascal WNetRestoreConnection(word ptr) WNetRestoreConnection
+524 pascal WNetWriteJob(word ptr ptr) WNetWriteJob
+525 pascal WnetConnectDialog(word word) WNetConnectDialog
+526 pascal WNetDisconnectDialog(word word) WNetDisconnectDialog
+527 pascal WNetConnectionDialog(word word) WNetConnectionDialog
+528 pascal WNetViewQueueDialog(word ptr) WNetViewQueueDialog
+529 pascal WNetPropertyDialog(word word ptr word) WNetPropertyDialog
+530 pascal WNetGetDirectoryType(ptr ptr) WNetGetDirectoryType
+531 pascal WNetDirectoryNotify(word ptr word) WNetDirectoryNotify
+532 pascal WNetGetPropertyText(word word word ptr word) WNetGetPropertyText
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
new file mode 100644
index 0000000000000000000000000000000000000000..c27681700e9237d51ab5c417a75eb2ac01e590ce
--- /dev/null
+++ b/if1632/winprocs.spec
@@ -0,0 +1,27 @@
+name	winprocs
+id	24
+length	23
+
+1  pascal ButtonWndProc(word word word long) ButtonWndProc
+2  pascal StaticWndProc(word word word long) StaticWndProc
+3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
+4  pascal ListBoxWndProc(word word word long) ListBoxWndProc
+5  pascal ComboBoxWndProc(word word word long) ComboBoxWndProc
+6  pascal EditWndProc(word word word long) EditWndProc
+7  pascal PopupMenuWndProc(word word word long) PopupMenuWndProc
+8  pascal DesktopWndProc(word word word long) DesktopWndProc
+9  pascal DefDlgProc(word word word long) DefDlgProc
+10 pascal MDIClientWndProc(word word word long) MDIClientWndProc
+11 pascal DefWindowProc(word word word long) DefWindowProc
+12 pascal DefMDIChildProc(word word word long) DefMDIChildProc
+13 pascal SystemMessageBoxProc(word word word long) SystemMessageBoxProc
+14 pascal FileOpenDlgProc(word word word long) FileOpenDlgProc
+15 pascal FileSaveDlgProc(word word word long) FileSaveDlgProc
+16 pascal ColorDlgProc(word word word long) ColorDlgProc
+17 pascal FindTextDlgProc(word word word long) FindTextDlgProc
+18 pascal ReplaceTextDlgProc(word word word long) ReplaceTextDlgProc
+19 pascal PrintSetupDlgProc(word word word long) PrintSetupDlgProc
+20 pascal PrintDlgProc(word word word long) PrintDlgProc
+21 pascal AboutDlgProc(word word word long) AboutDlgProc
+22 pascal AboutWine_Proc(word word word long) AboutWine_Proc
+23 pascal16 CARET_Callback(word word word long) CARET_Callback
diff --git a/include/callback.h b/include/callback.h
index 18206c904d740886f5856ed4d944f8182f50e9f4..01a87d6a4d6272f3ddf495cf7ba201a2b8527623 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -1,21 +1,93 @@
-/* $Id$
- */
 /*
- * Copyright  Robert J. Amstadt, 1993
+ * 16-bit mode callback functions
+ *
+ * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef CALLBACK_H
-#define CALLBACK_H
+#ifndef WINE_CALLBACK_H
+#define WINE_CALLBACK_H
 
 #include <stdlib.h>
 #include <stdarg.h>
 
-#define CALLBACK_SIZE_WORD	0
-#define CALLBACK_SIZE_LONG	1
+#include "stackframe.h"
+
+#ifndef WINELIB
+
+/* List of the 16-bit callback functions. This list is used  */
+/* by the build program to generate the file if1632/call16.S */
+
+                               /* func     ds    parameters */
+extern WORD CallTo16_word_wl   ( FARPROC, WORD, WORD, LONG );
+extern WORD CallTo16_word_ll   ( FARPROC, WORD, LONG, LONG );
+extern WORD CallTo16_word_wwl  ( FARPROC, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_wlw  ( FARPROC, WORD, WORD, LONG, WORD );
+extern LONG CallTo16_long_wwl  ( FARPROC, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_llwl ( FARPROC, WORD, LONG, LONG, WORD, LONG );
+extern LONG CallTo16_long_wwwl ( FARPROC, WORD, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_wllwl( FARPROC, WORD, WORD, LONG, LONG, WORD, LONG );
+extern WORD CallTo16_word_wwlll( FARPROC, WORD, WORD, WORD, LONG, LONG, LONG );
+
+extern WORD CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD ax, WORD bx,
+                            WORD cx, WORD dx, WORD si, WORD di );
+
+#define CallEnumChildProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
+    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
+#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
+    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
+#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
+    CallTo16_word_wllwl(func, CURRENT_DS, hdc, lptable, lprecord, objs, lParam)
+#define CallEnumObjectsProc( func, lpobj, lParam ) \
+    CallTo16_word_ll( func, CURRENT_DS, lpobj, lParam )
+#define CallEnumPropProc( func, hwnd, lpstr, data ) \
+    CallTo16_word_wlw( func, CURRENT_DS, hwnd, lpstr, data )
+#define CallEnumTaskWndProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallEnumWindowsProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallLineDDAProc( func, xPos, yPos, lParam ) \
+    CallTo16_word_wwl( func, CURRENT_DS, xPos, yPos, lParam )
+#define CallGrayStringProc( func, hdc, lParam, cch ) \
+    CallTo16_word_wlw( func, CURRENT_DS, hdc, lParam, cch )
+#define CallHookProc( func, code, wParam, lParam ) \
+    CallTo16_long_wwl( func, CURRENT_DS, code, wParam, lParam )
+#define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
+    CallTo16_word_wwlll( func, CURRENT_DS, id, msg, dwUser, dw1, dw2 )
+#define CallWndProc( func, hwnd, msg, wParam, lParam ) \
+    CallTo16_long_wwwl( func, CURRENT_DS, hwnd, msg, wParam, lParam )
+
+#else  /* WINELIB */
+
+#define CallEnumChildProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
+    (*func)( lpfont, lpmetric, type, lParam )
+#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
+    (*func)( lpfont, lpmetric, type, lParam )
+#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
+    (*func)( hdc, lptable, lprecord, objs, lParam)
+#define CallEnumObjectsProc( func, lpobj, lParam ) \
+    (*func)( lpobj, lParam )
+#define CallEnumPropProc( func, hwnd, lpstr, data ) \
+    (*func)( hwnd, lpstr, data )
+#define CallEnumTaskWndProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallEnumWindowsProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallLineDDAProc( func, xPos, yPos, lParam ) \
+    (*func)( xPos, yPos, lParam )
+#define CallGrayStringProc( func, hdc, lParam, cch ) \
+    (*func)( hdc, lParam, cch )
+#define CallHookProc( func, code, wParam, lParam ) \
+    (*func)( code, wParam, lParam )
+#define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
+    (*func)( id, msg, dwUser, dw1, dw2 )
+#define CallWndProc( func, hwnd, msg, wParam, lParam ) \
+    (*func)( hwnd, msg, wParam, lParam )
 
-extern int CallTo16(unsigned int csip, unsigned short ds);
-extern int CallBack16(void *func, int n_args, ...);
+#endif  /* WINELIB */
 
-extern BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch);
 
-#endif /* CALLBACK_H */
+#endif /* WINE_CALLBACK_H */
diff --git a/include/compobj.h b/include/compobj.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9482dcdceeed4530596102c5a9028b40a2099bd
--- /dev/null
+++ b/include/compobj.h
@@ -0,0 +1,5 @@
+/*
+ *	compobj.h	-	Declarations for COMPOBJ
+ */
+
+typedef	LPVOID	LPUNKNOWN;
diff --git a/include/debug.h b/include/debug.h
index 34493c851120eb5b03c101e00be71d85049db4ba..24c4730366ce1fc0ddeaf12038eca36375a0197b 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -69,7 +69,6 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
-#undef DEBUG_STACK
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -145,7 +144,6 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
-#define DEBUG_STACK
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
@@ -475,11 +473,6 @@ short debug_msg_enabled[]={
 #else
     0,
 #endif
-#ifdef DEBUG_STACK
-    1,
-#else
-    0,
-#endif
 #ifdef DEBUG_STRESS
     1,
 #else
@@ -1352,21 +1345,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stack if(!debug_msg_enabled[63]) ; else fprintf
-#define debugging_stack debug_msg_enabled[63]
-#else
-#ifdef DEBUG_STACK
-#define dprintf_stack fprintf
-#define debugging_stack 1
-#else
-#define dprintf_stack while(0) fprintf
-#define debugging_stack 0
-#endif
-#endif
-
-#ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_stress debug_msg_enabled[64]
+#define dprintf_stress if(!debug_msg_enabled[63]) ; else fprintf
+#define debugging_stress debug_msg_enabled[63]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1378,8 +1358,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[65]
+#define dprintf_syscolor if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[64]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1391,8 +1371,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_task debug_msg_enabled[66]
+#define dprintf_task if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_task debug_msg_enabled[65]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1404,8 +1384,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_text debug_msg_enabled[67]
+#define dprintf_text if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_text debug_msg_enabled[66]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1417,8 +1397,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_timer debug_msg_enabled[68]
+#define dprintf_timer if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_timer debug_msg_enabled[67]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1430,8 +1410,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[69]
+#define dprintf_toolhelp if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1443,8 +1423,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_utility if(!debug_msg_enabled[70]) ; else fprintf
-#define debugging_utility debug_msg_enabled[70]
+#define dprintf_utility if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_utility debug_msg_enabled[69]
 #else
 #ifdef DEBUG_UTILITY
 #define dprintf_utility fprintf
@@ -1456,8 +1436,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[71]) ; else fprintf
-#define debugging_win debug_msg_enabled[71]
+#define dprintf_win if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_win debug_msg_enabled[70]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1469,8 +1449,8 @@ extern short debug_msg_enabled[];
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[72]
+#define dprintf_winsock if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[71]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1548,7 +1528,6 @@ static char *debug_msg_name[] = {
     "scroll",
     "selector",
     "selectors",
-    "stack",
     "stress",
     "syscolor",
     "task",
diff --git a/include/dlls.h b/include/dlls.h
index cdceae540f2028fc67f4c51d528d08730947bce9..10f2f08855f55352bec5dc54bebff87fb3b2e230 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -7,6 +7,8 @@
 #ifndef DLLS_H
 #define DLLS_H
 
+#include "wintypes.h"
+
 #define MAX_NAME_LENGTH		64
 
 typedef struct resource_name_table
@@ -54,119 +56,67 @@ extern struct  w_files *wine_files;
 #define DLL	0
 #define EXE	1
 
-#define DLL_ARGTYPE_SIGNEDWORD	0
-#define DLL_ARGTYPE_WORD	1
-#define DLL_ARGTYPE_LONG	2
-#define DLL_ARGTYPE_FARPTR	3
-#define DLL_MAX_ARGS		16
-
-#define DLL_HANDLERTYPE_PASCAL	16
-
 struct dll_table_entry_s
 {
     /*
      * Relocation data
      */
-    unsigned int selector;	/* Selector to access this entry point	  */
-    void *address;		/* Offset in segment of entry point	  */
+    WORD selector;  /* Selector of entry point */
+    WORD offset;    /* Offset in segment of entry point */
 
     /*
      * 16->32 bit interface data
      */
     char *export_name;
-    void *handler;		/* Address of function to process request */
-    char n_args;			/* Number of arguments passed to function */
-    short conv_reference ; /* reference to Argument conversion data  */
 #ifdef WINESTAT
     int used;			/* Number of times this function referenced */
 #endif
-    
 };
 
-struct dll_name_table_entry_s
+struct dll_table_s
 {
-    char *dll_name;
     struct dll_table_entry_s *dll_table;
     int dll_table_length;
     int dll_number;
+    void *code_start;  /* 32-bit address of DLL code */
+    void *code_end;
+    void *data_start;  /* 32-bit address of DLL data */
+    void *data_end;
+};
+
+struct dll_name_table_entry_s
+{
+    char *dll_name;
+    struct dll_table_s *table;
     int dll_is_used;   /* use MS provided if set to zero */
 };
 
-extern struct dll_table_entry_s KERNEL_table[];
-extern struct dll_table_entry_s USER_table[];
-extern struct dll_table_entry_s GDI_table[];
-extern struct dll_table_entry_s WIN87EM_table[];
-extern struct dll_table_entry_s MMSYSTEM_table[];
-extern struct dll_table_entry_s SHELL_table[];
-extern struct dll_table_entry_s SOUND_table[];
-extern struct dll_table_entry_s KEYBOARD_table[];
-extern struct dll_table_entry_s WINSOCK_table[];
-extern struct dll_table_entry_s STRESS_table[];
-extern struct dll_table_entry_s SYSTEM_table[];
-extern struct dll_table_entry_s TOOLHELP_table[];
-extern struct dll_table_entry_s MOUSE_table[];
-extern struct dll_table_entry_s COMMDLG_table[];
-extern struct dll_table_entry_s OLE2_table[];
-extern struct dll_table_entry_s OLE2CONV_table[];
-extern struct dll_table_entry_s OLE2DISP_table[];
-extern struct dll_table_entry_s OLE2NLS_table[];
-extern struct dll_table_entry_s OLE2PROX_table[];
-extern struct dll_table_entry_s OLECLI_table[];
-extern struct dll_table_entry_s OLESVR_table[];
-extern struct dll_table_entry_s COMPOBJ_table[];
-extern struct dll_table_entry_s STORAGE_table[];
-
-
-extern unsigned short KERNEL_offsets[];
-extern unsigned short USER_offsets[];
-extern unsigned short GDI_offsets[];
-extern unsigned short WIN87EM_offsets[];
-extern unsigned short MMSYSTEM_offsets[];
-extern unsigned short SHELL_offsets[];
-extern unsigned short SOUND_offsets[];
-extern unsigned short KEYBOARD_offsets[];
-extern unsigned short WINSOCK_offsets[];
-extern unsigned short STRESS_offsets[];
-extern unsigned short SYSTEM_offsets[];
-extern unsigned short TOOLHELP_offsets[];
-extern unsigned short MOUSE_offsets[];
-extern unsigned short COMMDLG_offsets[];
-extern unsigned short OLE2_offsets[];
-extern unsigned short OLE2CONV_offsets[];
-extern unsigned short OLE2DISP_offsets[];
-extern unsigned short OLE2NLS_offsets[];
-extern unsigned short OLE2PROX_offsets[];
-extern unsigned short OLECLI_offsets[];
-extern unsigned short OLESVR_offsets[];
-extern unsigned short COMPOBJ_offsets[];
-extern unsigned short STORAGE_offsets[];
-
-
-extern unsigned char KERNEL_types[];
-extern unsigned char USER_types[];
-extern unsigned char GDI_types[];
-extern unsigned char WIN87EM_types[];
-extern unsigned char MMSYSTEM_types[];
-extern unsigned char SHELL_types[];
-extern unsigned char SOUND_types[];
-extern unsigned char KEYBOARD_types[];
-extern unsigned char WINSOCK_types[];
-extern unsigned char STRESS_types[];
-extern unsigned char SYSTEM_types[];
-extern unsigned char TOOLHELP_types[];
-extern unsigned char MOUSE_types[];
-extern unsigned char COMMDLG_types[];
-extern unsigned char OLE2_types[];
-extern unsigned char OLE2CONV_types[];
-extern unsigned char OLE2DISP_types[];
-extern unsigned char OLE2NLS_types[];
-extern unsigned char OLE2PROX_types[];
-extern unsigned char OLECLI_types[];
-extern unsigned char OLESVR_types[];
-extern unsigned char COMPOBJ_types[];
-extern unsigned char STORAGE_types[];
-
-#define N_BUILTINS	23
+extern struct dll_table_s KERNEL_table;
+extern struct dll_table_s USER_table;
+extern struct dll_table_s GDI_table;
+extern struct dll_table_s WIN87EM_table;
+extern struct dll_table_s MMSYSTEM_table;
+extern struct dll_table_s SHELL_table;
+extern struct dll_table_s SOUND_table;
+extern struct dll_table_s KEYBOARD_table;
+extern struct dll_table_s WINSOCK_table;
+extern struct dll_table_s STRESS_table;
+extern struct dll_table_s SYSTEM_table;
+extern struct dll_table_s TOOLHELP_table;
+extern struct dll_table_s MOUSE_table;
+extern struct dll_table_s COMMDLG_table;
+extern struct dll_table_s OLE2_table;
+extern struct dll_table_s OLE2CONV_table;
+extern struct dll_table_s OLE2DISP_table;
+extern struct dll_table_s OLE2NLS_table;
+extern struct dll_table_s OLE2PROX_table;
+extern struct dll_table_s OLECLI_table;
+extern struct dll_table_s OLESVR_table;
+extern struct dll_table_s COMPOBJ_table;
+extern struct dll_table_s STORAGE_table;
+extern struct dll_table_s WINPROCS_table;
+
+#define N_BUILTINS	24
 
 #endif /* DLLS_H */
 
diff --git a/include/global.h b/include/global.h
new file mode 100644
index 0000000000000000000000000000000000000000..626890f8f17ab805775743e6df701fd621530d46
--- /dev/null
+++ b/include/global.h
@@ -0,0 +1,16 @@
+/*
+ * Global heap declarations
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#ifndef __WINE_GLOBAL_H
+#define __WINE_GLOBAL_H
+
+#include "wintypes.h"
+
+extern HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
+                             BOOL isCode, BOOL isReadOnly );
+extern WORD GlobalHandleToSel( HGLOBAL handle );
+
+#endif  /* __WINE_GLOBAL_H */
diff --git a/include/hook.h b/include/hook.h
index 303fdd8d56c28caf512135e9befa3670164c3f9b..bd918220bf639216ebb86d1dac58dd3680cd6b6f 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -9,6 +9,7 @@
 
 #include "windows.h"
 #include "ldt.h"
+#include "callback.h"
 
   /* Hook data (pointed to by a HHOOK) */
 typedef struct
@@ -34,9 +35,6 @@ typedef struct
 #define CALL_TASK_HOOK(id,code,wparam,lparam) \
     INTERNAL_CALL_HOOK(TASK_HOOK(id),code,wparam,lparam)
 
-extern DWORD CallHookProc( HOOKPROC func, short code,
-			   WPARAM wParam, LPARAM lParam );  /* callback.c */
-
 extern HHOOK systemHooks[];
 extern HHOOK taskHooks[];
 
diff --git a/include/if1632.h b/include/if1632.h
index 03621a628350175f540e4c3d6598e6d2fe1dd4ab..96726dd0e4415a809e1d98a9b6031988aa3caede 100644
--- a/include/if1632.h
+++ b/include/if1632.h
@@ -7,12 +7,11 @@ extern int CallToInit16(unsigned long csip, unsigned long sssp,
 			unsigned short ds);
 extern int CallTo16cx(unsigned long csip, unsigned long dscx);
 extern int CallToDllEntry(unsigned long csip, unsigned long dscx, unsigned short di);
-extern int CallBack16(void *func, int n_args, ...);
-extern void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam);
 extern void winestat(void);
-extern int DLLRelay(unsigned int func_num, unsigned int seg_off);
-extern struct dll_table_entry_s *FindDLLTable(char *dll_name);
+extern struct dll_table_s *FindDLLTable(char *dll_name);
 extern int FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name);
 extern int ReturnArg(int arg);
 
+extern BOOL RELAY_Init(void);
+
 #endif /* __WINE_IF1632_H */
diff --git a/include/listbox.h b/include/listbox.h
index c1b2278bc7effe3d1bd0e28451c96167bdec0be9..307a74e6070d23a70930993c4fc031db16e224ec 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -8,7 +8,7 @@ typedef struct tagLISTSTRUCT {
 	HANDLE		hMem;
 	HANDLE		hData;
 	char		*itemText;
-	void		*lpNext;
+	struct tagLISTSTRUCT *lpNext;
 } LISTSTRUCT;
 typedef LISTSTRUCT FAR* LPLISTSTRUCT;
 
@@ -21,15 +21,17 @@ typedef struct tagHEADLIST {
 	short	ItemsPerColumn;
 	short	ItemFocused;
 	short	PrevFocused;
-	short	SelCount;
 	short 	StdItemHeight;
 	short	ColumnsWidth;
 	short	DrawCtlType;
-	void	*lpFirst; 
+	void	*lpFirst;
 	DWORD	dwStyle;
 	HWND	hWndLogicParent;
 	HFONT	hFont;
 	BOOL	bRedrawFlag;
+	WORD    iNumStops;
+	LPINT   TabStops;
+	HANDLE  hDrawItemStruct;
 /*	MDESC	*Heap; */
 } HEADLIST;
 typedef HEADLIST FAR* LPHEADLIST;
diff --git a/include/local.h b/include/local.h
index eb813e93041f197997044b4ec13c36c56c68a73a..a676a137740d9114df97d147d949e53a1e435d86 100644
--- a/include/local.h
+++ b/include/local.h
@@ -4,8 +4,8 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef __WINE_HEAP_H
-#define __WINE_HEAP_H
+#ifndef __WINE_LOCAL_H
+#define __WINE_LOCAL_H
 
 #include "wintypes.h"
 
@@ -21,4 +21,4 @@ extern WORD LOCAL_Size( WORD ds, HLOCAL handle );
 extern WORD LOCAL_Flags( WORD ds, HLOCAL handle );
 extern WORD LOCAL_HeapSize( WORD ds );
 
-#endif  /* __WINE_HEAP_H */
+#endif  /* __WINE_LOCAL_H */
diff --git a/include/msdos.h b/include/msdos.h
index 35b8d92f48525c08dc8cccf6d561e66a9f20c235..7b2bda783157c74d2377dad7dc557878fd2e5b62 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -30,7 +30,7 @@ struct fcb {
 	BYTE dummy2[9];
 };
 
-#define DOSVERSION 0x0500;      /* Might as well pretend we're DOS 5.0 */
+#define DOSVERSION 0x0005;      /* Major version in low byte: DOS 5.00 */
 #define MAX_DOS_DRIVES	26
 
 extern WORD ExtendedError;
diff --git a/include/neexe.h b/include/neexe.h
index ad26cbec76219d3ba202efa7eeca8512e40a2c71..51e860def25c86b0769a5b7e5af9b6864b6cbcf4 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -12,18 +12,19 @@
  */
 struct mz_header_s
 {
-    u_char dont_care1[0x18];	/* MZ Header stuff			*/
-    u_char must_be_0x40;	/* 0x40 for non-MZ program		*/
-    u_char dont_care2[0x23];	/* More MZ header stuff			*/
-    u_short ne_offset;		/* Offset to extended header		*/
+    u_short mz_magic;         /* MZ Header signature */
+    u_char  dont_care[0x3a];  /* MZ Header stuff */
+    u_short ne_offset;        /* Offset to extended header */
 };
 
+#define MZ_SIGNATURE  ('M' | ('Z' << 8))
+
 /*
  * This is the Windows executable (NE) header.
  */
 struct ne_header_s
 {
-    char    header_type[2];	/* Must contain 'N' 'E'			*/
+    u_short ne_magic;           /* NE signature 'NE' */
     u_char  linker_version;	/* Linker version number		*/
     u_char  linker_revision;	/* Linker revision number		*/
     u_short entry_tab_offset;	/* Offset to entry table relative to NE */
@@ -57,6 +58,9 @@ struct ne_header_s
     u_short expect_version;	/* Expected Windows version number	*/
 };
 
+#define NE_SIGNATURE  ('N' | ('E' << 8))
+#define PE_SIGNATURE  ('P' | ('E' << 8))
+
 /*
  * NE Header FORMAT FLAGS
  */
diff --git a/include/registers.h b/include/registers.h
index ce06a0fed05accc650cdf2a3dae97600394dda11..0298c238d6d3fcf5c588e52431e9d11c2efabec0 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -5,6 +5,8 @@
 
 #ifndef PROCEMU
 
+#include "wine.h"
+
 #define EAX context->sc_eax
 #define EBX context->sc_ebx
 #define ECX context->sc_ecx
diff --git a/include/selectors.h b/include/selectors.h
index 55715b9c7f7ed67a5d99d0bc2377a0c164ae7f9e..13cb8365fb6deadb58c2115dd70e4c942a505167 100644
--- a/include/selectors.h
+++ b/include/selectors.h
@@ -20,12 +20,14 @@ extern WORD SELECTOR_ReallocBlock( WORD sel, void *base, DWORD size,
 
 extern WORD *CreateSelectors( struct w_files * wpnt );
 
-extern unsigned int GetEntryDLLName(char *dll_name, char *function, WORD *sel,
-					int *addr);
-extern unsigned int GetEntryDLLOrdinal(char *dll_name, int ordinal, WORD *sel,
-					int *addr);
-extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt, 
-					int ordinal);
+extern unsigned int GetEntryDLLName(char *dll_name, char *function,
+                                    WORD *sel, WORD *offset);
+extern unsigned int GetEntryDLLOrdinal(char *dll_name, int ordinal,
+                                       WORD *sel, WORD *offset);
+extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt,
+                                             int ordinal);
 extern void InitSelectors(void);
 
+extern WNDPROC GetWndProcEntry16( char *name );
+
 #endif /* __WINE_SELECTORS_H */
diff --git a/include/stackframe.h b/include/stackframe.h
index d029ec198d5c3413c5d51a9257176c12dcbb3033..3a1bf2de1f7624c8c3d8c6b7ea807fe2755a983b 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -10,19 +10,29 @@
 #include <windows.h>
 #include "ldt.h"
 
+#ifndef WINELIB
+#pragma pack(1)
+#endif
+
 typedef struct
 {
-    WORD    saved_ss;
+    WORD    saved_ss;                /* saved previous 16-bit stack */
     WORD    saved_bp;
     WORD    saved_sp;
-    WORD    ds;
-    WORD    bp;
-    WORD    arg_length;
-    WORD    ip;
+    WORD    ds;                      /* 16-bit ds */
+    DWORD   entry_point WINE_PACKED; /* entry point to call */
+    WORD    ordinal_number;          /* ordinal number of entry point */
+    WORD    dll_id;                  /* DLL id of entry point */
+    WORD    bp;                      /* 16-bit bp */
+    WORD    ip;                      /* return address */
     WORD    cs;
-    WORD    args[1];
+    WORD    args[1];                 /* arguments to API function */
 } STACK16FRAME;
 
+#ifndef WINELIB
+#pragma pack(4)
+#endif
+
 extern WORD IF1632_Saved16_ss;
 extern WORD IF1632_Saved16_sp;
 extern WORD IF1632_Saved16_bp;
diff --git a/include/stddebug.h b/include/stddebug.h
index 4abb78e8bfaa84cd19877d1425aa5e15170f3c4b..2b4114e940eaaaac667a84434f94f04ca6643151 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -139,7 +139,6 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
-#undef DEBUG_STACK
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -215,7 +214,6 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
-#define DEBUG_STACK
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 85ab7b30e974d624669bdff6f2459ec4cdaddc45..ba1a05a8afd932d3d2bafce5e7aaae95d5cc0c3c 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -10,8 +10,76 @@
 
 /* Global heap */
 
-WORD GlobalHandleToSel( HANDLE handle );
+typedef struct
+{
+    DWORD dwSize;
+    WORD  wcItems;
+    WORD  wcItemsFree;
+    WORD  wcItemsLRU;
+} GLOBALINFO;
 
+typedef struct
+{
+    DWORD   dwSize;
+    DWORD   dwAddress;
+    DWORD   dwBlockSize;
+    HGLOBAL hBlock;
+    WORD    wcLock;
+    WORD    wcPageLock;
+    WORD    wFlags;
+    BOOL    wHeapPresent;
+    HGLOBAL hOwner;
+    WORD    wType;
+    WORD    wData;
+    DWORD   dwNext;
+    DWORD   dwNextAlt;
+} GLOBALENTRY;
+
+  /* GlobalFirst()/GlobalNext() flags */
+#define GLOBAL_ALL      0
+#define GLOBAL_LRU      1
+#define GLOBAL_FREE     2
+
+  /* wType values */
+#define GT_UNKNOWN      0
+#define GT_DGROUP       1
+#define GT_DATA         2
+#define GT_CODE         3
+#define GT_TASK         4
+#define GT_RESOURCE     5
+#define GT_MODULE       6
+#define GT_FREE         7
+#define GT_INTERNAL     8
+#define GT_SENTINEL     9
+#define GT_BURGERMASTER 10
+
+/* wData values */
+#define GD_USERDEFINED      0
+#define GD_CURSORCOMPONENT  1
+#define GD_BITMAP           2
+#define GD_ICONCOMPONENT    3
+#define GD_MENU             4
+#define GD_DIALOG           5
+#define GD_STRING           6
+#define GD_FONTDIR          7
+#define GD_FONT             8
+#define GD_ACCELERATORS     9
+#define GD_RCDATA           10
+#define GD_ERRTABLE         11
+#define GD_CURSOR           12
+#define GD_ICON             14
+#define GD_NAMETABLE        15
+#define GD_MAX_RESOURCE     15
+
+/* wFlags values */
+#define GF_PDB_OWNER        0x0100      /* Low byte is KERNEL flags */
+
+BOOL GlobalInfo( GLOBALINFO *pInfo );
+BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags );
+BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags) ;
+BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem );
+BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg );
+WORD GlobalHandleToSel( HGLOBAL handle );
 
 /* Local heap */
 
diff --git a/include/windows.h b/include/windows.h
index 5ff1c252d6c88e24f26916ea201cd53458f6517b..2e639f931132765b6f68318e08cada6d3e0a710f 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -680,6 +680,17 @@ typedef struct tagTEXTMETRIC
 #define ETO_OPAQUE          0x02
 #define ETO_CLIPPED         0x04
 
+  /* Rasterizer status */
+typedef struct
+{
+    WORD nSize;
+    WORD wFlags;
+    WORD nLanguageID;
+} RASTERIZER_STATUS, *LPRASTERIZER_STATUS;
+
+#define TT_AVAILABLE        0x0001
+#define TT_ENABLED          0x0002
+
 typedef struct tagPALETTEENTRY
 {
 	BYTE peRed, peGreen, peBlue, peFlags;
@@ -2469,8 +2480,8 @@ Fa(LPSTR,AnsiLower,LPSTR,a)
 Fa(SEGPTR,AnsiNext,SEGPTR,a)
 Fa(LPSTR,AnsiUpper,LPSTR,a)
 Fa(LPSTR,GlobalLock,HGLOBAL,a)
-Fa(LPSTR,GlobalWire,HGLOBAL,a)
 Fa(LPSTR,LockResource,HANDLE,a)
+Fa(SEGPTR,GlobalWire,HGLOBAL,a)
 Fa(SEGPTR,WIN16_GlobalLock,HGLOBAL,a)
 Fa(UINT,GDIRealizePalette,HDC,a)
 Fa(UINT,RealizePalette,HDC,a)
diff --git a/include/wine.h b/include/wine.h
index bd426f378e785228d9756bc903a65368dba98c50..101f50e1df807cc36c31dadee41e0eb23b9b9dbf 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -1,8 +1,5 @@
 #ifndef  WINE_H
 #define  WINE_H
-#if 0
-#define __ELF__
-#endif
 
 extern char *WineIniFileName(void);
 extern char *WinIniFileName(void);
@@ -36,12 +33,8 @@ struct sigcontext_struct {
 	unsigned long cr2;
 };
 #define WINE_DATA_SELECTOR 0x2b
-#ifdef __ELF__
-#define WINE_CODE_SELECTOR 0x0f
-#else
 #define WINE_CODE_SELECTOR 0x23
-#endif
-#endif
+#endif  /* linux */
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <signal.h>
diff --git a/loader/dump.c b/loader/dump.c
index 77a2a06300650e2fdf659de598a2d6f8e8d892f7..2011bbe14f3c0a4c15e4c0c93791a9da28cb7f72 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -25,8 +25,8 @@ void
 PrintFileHeader(struct ne_header_s *ne_header)
 {
     printf("ne_header: %c%c\n",
-	   ne_header->header_type[0], 
-	   ne_header->header_type[1]);
+           ne_header->ne_magic & 0xff,
+           ne_header->ne_magic >> 8 );
     printf("linker version: %d.%d\n", ne_header->linker_version,
 	   ne_header->linker_revision);
     printf("format flags: %04x\n", ne_header->format_flags);
diff --git a/loader/library.c b/loader/library.c
index e610d3c7d7af665c34d57c9f39dfec7340843226..8c0218108f5b46de32ce58f0b1836f53a54d932c 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -381,6 +381,8 @@ HANDLE LoadLibrary(LPSTR libname)
 {
 	HANDLE h;
 	
+        dprintf_module(stddeb,"LoadLibrary: (%08x) %s\n",(int)libname,libname);
+
 	if ((h = LoadImage(libname, DLL, 0)) < 32)
 		return h;
 
@@ -435,8 +437,8 @@ FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
 #ifdef WINELIB
     WINELIB_UNIMP ("GetProcAddress");
 #else
-    int		addr, ret;
-    WORD        sel;
+    int		ret;
+    WORD        sel, addr;
     register struct w_files *w = wine_files;
     int 	ordinal, len;
     char 	* cpnt;
@@ -541,9 +543,9 @@ FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
 static void 
 FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
 {
-	lpModule->dwSize = dll->dll_table_length * 1024;
+	lpModule->dwSize = dll->table->dll_table_length * 1024;
 	strcpy(lpModule->szModule, dll->dll_name);
-	lpModule->hModule = 0xff00 + dll->dll_number;
+	lpModule->hModule = 0xff00 + dll->table->dll_number;
 	lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
 	GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
 	lpModule->wNext = 0;
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 0c18f4d96995f33e410c54d9b961942c168d5f07..d0bd13732e7a9c5fb00a4df78810e9bfd06be2fa 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -18,6 +18,7 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #include "library.h"
 #include "if1632.h"
 #include "selectors.h"
+#include "callback.h"
 #include "ne_image.h"
 #include "prototypes.h"
 #include "stddebug.h"
@@ -146,7 +147,7 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
 	    ordinal = rep->target2;
 
   	    status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
-					&address);
+					&offset);
 	    if (status)
 	    {
 		char s[80];
@@ -157,7 +158,7 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
 	    }
 
 	    dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1, 
-		   dll_name, ordinal, selector, address);
+		   dll_name, ordinal, selector, offset);
 	    break;
 	    
 	  case NE_RELTYPE_NAME:
@@ -172,7 +173,7 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
 	    }
 
   	    status = GetEntryDLLName(dll_name, func_name, &selector, 
-					   &address);
+					   &offset);
 	    if (status)
 	    {
 		char s[80];
@@ -181,8 +182,8 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
 		myerror(s);
 		return -1;
 	    }
-/*	    dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1, 
-                   func_name, dll_name, ordinal, selector, address);*/
+            dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1, 
+                          func_name, dll_name, ordinal, selector, offset);
 	    break;
 	    
 	  case NE_RELTYPE_INTERNAL:
@@ -190,16 +191,16 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
 	    {
 		address  = GetEntryPointFromOrdinal(wpnt, rep->target2);
 		selector = (address >> 16) & 0xffff;
-		address &= 0xffff;
+		offset   = address & 0xffff;
 	    }
 	    else
 	    {
 		selector = selector_table[rep->target1-1];
-		address  = rep->target2;
+		offset   = rep->target2;
 	    }
 	    
 	    dprintf_fixup(stddeb,"%d: %04x:%04x\n", 
-			  i + 1, selector, address);
+			  i + 1, selector, offset);
 	    break;
 
 	  case NE_RELTYPE_OSFIXUP:
@@ -240,7 +241,8 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
                           i+1, rep->address_type, rep->relocation_type,
                           rep->offset, rep->target1, rep->target2);
 
-	offset = rep->offset;
+        address = (unsigned int)offset;
+	offset  = rep->offset;
 
 	switch (rep->address_type)
 	{
@@ -290,8 +292,9 @@ int NE_FixupSegment(struct w_files *wpnt, int segment_num)
                               sel, offset, *sp, additive ? " additive" : "" );
 		offset = *sp;
 		*sp    = (unsigned short) selector;
-		if(additive)
-                    fprintf(stderr,"Additive selector, please report\n");
+		/* Borland creates additive records with offset zero. Strange, but OK */
+		if(additive && offset)
+        	fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
 	    } 
 	    while (offset != 0xffff && !additive);
 	    break;
@@ -321,20 +324,39 @@ int NE_unloadImage(struct w_files *wpnt)
 
 int NE_StartProgram(struct w_files *wpnt)
 {
-    int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
+    extern WORD PSPSelector;
+
+    int cs_reg, ds_reg, ip_reg;
+
+    /* Registers at initialization must be:
+     * ax   zero
+     * bx   stack size in bytes
+     * cx   heap size in bytes
+     * si   previous app instance
+     * di   current app instance
+     * bp   zero
+     * es   selector to the PSP
+     * ds   dgroup of the application
+     * ss   stack selector
+     * sp   top of the stack
+     */
+
     /*
      * Fixup stack and jump to start. 
      */
     WIN_StackSize = wpnt->ne->ne_header->stack_length;
     WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
 
-    ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
     cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
     ip_reg = wpnt->ne->ne_header->ip;
-    ss_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
-    sp_reg = wpnt->ne->ne_header->sp;
+    ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
 
-    return CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
+    IF1632_Saved16_ss = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
+    IF1632_Saved16_sp = wpnt->ne->ne_header->sp;
+    IF1632_Saved16_bp = 0;
+    return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                           PSPSelector /*es*/, 0 /*ax*/, WIN_StackSize /*bx*/,
+                           WIN_HeapSize, 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
 }
 
 void NE_InitDLL(struct w_files *wpnt)
@@ -363,7 +385,9 @@ void NE_InitDLL(struct w_files *wpnt)
 		    cx_reg = wpnt->ne->ne_header->local_heap_length;
   	    }
   
-  	    cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
+            dprintf_dll(stddeb,"InitDLL: ne_header->cs = %04x\n",wpnt->ne->ne_header->cs);
+            if (!wpnt->ne->ne_header->cs) cs_reg = 0;
+            else cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
   	    ip_reg = wpnt->ne->ne_header->ip;
   
             di_reg = wpnt->hinstance;
@@ -372,7 +396,9 @@ void NE_InitDLL(struct w_files *wpnt)
 		dprintf_dll(stddeb,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n", 
 		    wpnt->name, cs_reg, ip_reg, ds_reg, cx_reg);
 	    	    
-		rv = CallTo16cx(cs_reg << 16 | ip_reg, ds_reg | (cx_reg<<16));
+                rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                                     0 /*es*/, 0 /*ax*/, 0 /*bx*/, cx_reg,
+                                     0 /*dx*/, 0 /*si*/, di_reg );
 		dprintf_exec(stddeb,"rv = %x\n", rv);
 	    } else
 		dprintf_exec(stddeb,"%s skipped\n", wpnt->name);
diff --git a/loader/resource.c b/loader/resource.c
index 0446393e9d986fa310b57d4436cd2da20eadfdf8..0d1249bf8c62ef6bd24a94af27620cfa5a9b790b 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -623,8 +623,7 @@ int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
 int
 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
 {
-    HANDLE hmem;
-    int rsc_size;
+    HANDLE hmem, hrsrc;
     unsigned char *p;
     int string_num;
     int i;
@@ -632,10 +631,11 @@ LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
 	   "length = %d\n", instance, resource_id, (int) buffer, buflen);
 
-    hmem = RSC_LoadResource(instance, (SEGPTR)((resource_id >> 4) + 1),
-			    (SEGPTR) NE_RSCTYPE_STRING, &rsc_size );
-    if (hmem == 0)
-	return 0;
+    hrsrc = FindResource( instance, (SEGPTR)((resource_id >> 4) + 1),
+                          (SEGPTR) NE_RSCTYPE_STRING );
+    if (!hrsrc) return 0;
+    hmem = LoadResource( instance, hrsrc );
+    if (!hmem) return 0;
     
     p = GlobalLock(hmem);
     string_num = resource_id & 0x000f;
@@ -655,7 +655,7 @@ LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
 		fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
 		fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
 		}
-    GlobalFree(hmem);
+    FreeResource( hrsrc );
 
     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
     return i;
diff --git a/loader/selector.c b/loader/selector.c
index a8e687175d6111f4b3f0efe3f9dd07c2535f5380..142c70367d69a825af5cf0a468af67bf007160cd 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -31,7 +31,7 @@
 #include "windows.h"
 #include "ldt.h"
 #include "wine.h"
-
+#include "global.h"
 #include "dlls.h"
 #include "neexe.h"
 #include "if1632.h"
@@ -51,8 +51,6 @@ WORD PSPSelector = 0;
 int max_selectors = 0;
 
 
-extern void KERNEL_Ordinal_1();    /* FatalExit() */
-extern void KERNEL_Ordinal_102();  /* Dos3Call() */
 extern char WindowsPath[256];
 
 extern char **Argv;
@@ -62,46 +60,6 @@ extern char **environ;
 unsigned int 
 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
 
-#if 0
-
-
-/**********************************************************************
- *					InitSelectors
- */
-void
-InitSelectors(void) 
-{
-    int i;
-    max_selectors = MAX_SELECTORS;
-    SelectorMap = malloc(max_selectors * sizeof(unsigned short));
-    Segments    = malloc(max_selectors * sizeof(SEGDESC));
-    for (i = 0; i < max_selectors; i++) {
-	if (i < FIRST_SELECTOR) {
-	    SelectorMap[i] = SELECTOR_IS32BIT;
-#ifdef __ELF__
-	    /* quick hack, just reserves 4 meg for wine. */
-	} else if ((i << (16 + __AHSHIFT)) >= 0x8000000 &&
-		   (i << (16 + __AHSHIFT)) <= 0x8400000) {
-	    SelectorMap[i]= SELECTOR_IS32BIT;
-#endif
-	} else {
-	    SelectorMap[i]=0;
-	}
-    }
-#ifdef __ELF__
-    /* create an ldt. */
-    if (set_ldt_entry(1, 0x8000000, 65535, 1,0x1a ,1,0)) {
-	perror ("set_ldt_entry");
-	exit (1);
-    }
-#endif
-    }
-
-
-#endif /* 0 */
-
-
-
 
 /**********************************************************************
  *  Check whether pseudo-functions like __0040H for direct memory
@@ -110,8 +68,8 @@ InitSelectors(void)
  *         (e.g. reading from the Bios data segment (esp. clock!) )
  */
 
-unsigned int GetMemoryReference(char *dll_name, char *function, WORD *sel,
-				 int *addr)
+unsigned int GetMemoryReference( char *dll_name, char *function,
+                                 WORD *sel, WORD *offset )
 {
   static HANDLE memory_handles[ 10 ] = { 0,0,0,0,0,0,0,0,0,0 };
   static char *memory_names[ 10 ] = { "segment 0xA000",
@@ -143,13 +101,11 @@ unsigned int GetMemoryReference(char *dll_name, char *function, WORD *sel,
     else if( !strcasecmp( function, "__C000H" ) ) nr = 8;
     else if( !strcasecmp( function, "__0040H" ) ) nr = 9;
     else if( !strcasecmp( function, "__AHIncr" ) ) {
-      *sel = __AHINCR;   
-      *addr = MAKELONG(__AHINCR,__AHINCR);
+      *sel = *offset = __AHINCR;   
       return 1;      
     }
     else if( !strcasecmp( function, "__AHShift" ) ) {
-      *sel = __AHSHIFT;
-      *addr = MAKELONG(__AHSHIFT,__AHSHIFT);
+      *sel = *offset = __AHSHIFT;
       return 1;
     }
      else
@@ -168,12 +124,10 @@ unsigned int GetMemoryReference(char *dll_name, char *function, WORD *sel,
     case 195: nr = 8; break;
     case 193: nr = 9; break;
     case 114:
-      *sel = __AHINCR;  
-      *addr = MAKELONG(__AHINCR,__AHINCR);
+      *sel = *offset = __AHINCR;  
       return 1;
     case 113:
-      *sel = __AHSHIFT;
-      *addr = MAKELONG(__AHSHIFT,__AHSHIFT);
+      *sel = *offset = __AHSHIFT;
       return 1;
     default: return 0;
     }
@@ -183,8 +137,7 @@ unsigned int GetMemoryReference(char *dll_name, char *function, WORD *sel,
     fprintf( stderr, "Warning: Direct access to %s!\n", memory_names[ nr ] );
     memory_handles[ nr ] = GlobalAlloc( GMEM_FIXED, 65535 );
   }
-  *sel = memory_handles[ nr ];
-  *addr = MAKELONG(*sel,*sel);
+  *sel = *offset = memory_handles[ nr ];
   return 1;
 }
  
@@ -200,32 +153,31 @@ union lookup{
     char  * cpnt;
 };
 
-unsigned int GetEntryDLLName(char * dll_name, char * function, WORD* sel, 
-				int  * addr)
+unsigned int GetEntryDLLName( char * dll_name, char * function,
+                              WORD* sel, WORD *offset )
 {
-	struct dll_table_entry_s *dll_table;
+	struct dll_table_s *dll_table;
 	struct w_files * wpnt;
 	char * cpnt;
 	int ordinal, j, len;
 
-	if( GetMemoryReference( dll_name, function, sel, addr ) )
+	if( GetMemoryReference( dll_name, function, sel, offset ) )
 	  return 0;
 
 	dll_table = FindDLLTable(dll_name);
 
 	if(dll_table) {
-		ordinal = FindOrdinalFromName(dll_table, function);
+		ordinal = FindOrdinalFromName(dll_table->dll_table,function);
 		if(!ordinal){
 			dprintf_module(stddeb,"GetEntryDLLName: %s.%s not found\n",
 				dll_name, function);
-			*sel=0;
-			*addr=0;
+			*sel = *offset = 0;
 			return -1;
 		}
-		*sel = dll_table[ordinal].selector;
-		*addr  = (unsigned int) dll_table[ordinal].address;
+		*sel    = dll_table->dll_table[ordinal].selector;
+		*offset = dll_table->dll_table[ordinal].offset;
 #ifdef WINESTAT
-		dll_table[ordinal].used++;
+		dll_table->dll_table[ordinal].used++;
 #endif
 		return 0;
 	};
@@ -244,31 +196,30 @@ unsigned int GetEntryDLLName(char * dll_name, char * function, WORD* sel,
 		};
 		ordinal =  *((unsigned short *)  (cpnt +  len));
 		j = GetEntryPointFromOrdinal(wpnt, ordinal);		
-		*addr  = j & 0xffff;
-		j = j >> 16;
-		*sel = j;
+		*offset = LOWORD(j);
+		*sel    = HIWORD(j);
 		return 0;
 	};
 	return 1;
 }
 
-unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, WORD *sel, 
-				int  * addr)
+unsigned int GetEntryDLLOrdinal( char * dll_name, int ordinal,
+                                 WORD *sel, WORD *offset )
 {
-	struct dll_table_entry_s *dll_table;
+	struct dll_table_s *dll_table;
 	struct w_files * wpnt;
 	int j;
 
-	if( GetMemoryReference( dll_name, (char*)ordinal, sel, addr ) )
+	if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
 	  return 0;
 
 	dll_table = FindDLLTable(dll_name);
 
 	if(dll_table) {
-	    *sel = dll_table[ordinal].selector;
-	    *addr  = (unsigned int) dll_table[ordinal].address;
+	    *sel    = dll_table->dll_table[ordinal].selector;
+	    *offset = dll_table->dll_table[ordinal].offset;
 #ifdef WINESTAT
-		dll_table[ordinal].used++;
+            dll_table->dll_table[ordinal].used++;
 #endif
 	    return 0;
 	};
@@ -277,9 +228,8 @@ unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, WORD *sel,
 	for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
 		if(strcasecmp(wpnt->name, dll_name)) continue;
 		j = GetEntryPointFromOrdinal(wpnt, ordinal);
-		*addr  = j & 0xffff;
-		j = j >> 16;
-		*sel = j;
+		*offset = LOWORD(j);
+		*sel    = HIWORD(j);
 		return 0;
 	};
 	return 1;
@@ -345,6 +295,15 @@ GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
 }
 
 
+WNDPROC GetWndProcEntry16( char *name )
+{
+    WORD sel, offset;
+
+    GetEntryDLLName( "WINPROCS", name, &sel, &offset );
+    return (WNDPROC) MAKELONG( offset, sel );
+}
+
+
 /***********************************************************************
  *           GetDOSEnvironment   (KERNEL.131)
  */
@@ -413,9 +372,9 @@ static WORD CreatePSP(void)
 {
     HANDLE handle;
     struct dos_psp_s *psp;
-    unsigned short *usp;
     char *p1, *p2;
     int i;
+    WORD sel, offset;
 
     handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*psp) );
     if (!handle) return 0;
@@ -426,15 +385,16 @@ static WORD CreatePSP(void)
      */
     psp->pspInt20 = 0x20cd;
     psp->pspDispatcher[0] = 0x9a;
-    usp = (unsigned short *) &psp->pspDispatcher[1];
-    *usp       = (unsigned short) KERNEL_Ordinal_102;
-    *(usp + 1) = WINE_CODE_SELECTOR;
-    psp->pspTerminateVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspTerminateVector[1] = WINE_CODE_SELECTOR;
-    psp->pspControlCVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspControlCVector[1] = WINE_CODE_SELECTOR;
-    psp->pspCritErrorVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspCritErrorVector[1] = WINE_CODE_SELECTOR;
+    GetEntryDLLName( "KERNEL", "DOS3Call", &sel, &offset );
+    *(unsigned short *)&psp->pspDispatcher[1] = offset;
+    *(unsigned short *)&psp->pspDispatcher[3] = sel;
+    GetEntryDLLName( "KERNEL", "FatalAppExit", &sel, &offset );
+    psp->pspTerminateVector[0] = offset;
+    psp->pspTerminateVector[1] = sel;
+    psp->pspControlCVector[0]  = offset;
+    psp->pspControlCVector[1]  = sel;
+    psp->pspCritErrorVector[0] = offset;
+    psp->pspCritErrorVector[1] = sel;
     psp->pspEnvironment = SELECTOROF( GetDOSEnvironment() );
 
     p1 = psp->pspCommandTail;
@@ -473,7 +433,7 @@ unsigned short *CreateSelectors(struct w_files * wpnt)
     int i, length;
     void *base_addr;
     WORD *selectors;
-    ldt_entry entry;
+    HGLOBAL handle;
 
     auto_data_sel=0;
     /*
@@ -523,36 +483,21 @@ unsigned short *CreateSelectors(struct w_files * wpnt)
             dprintf_selectors(stddeb,"Auto data image length %x\n",file_image_length);
  	}
 
-        if (!(selectors[i] = AllocSelector( 0 )))
-        {
-            fprintf( stderr, "CreateSelectors: out of free LDT entries\n" );
-            exit( 1 );
-        }
-        if (!(base_addr = (void *) malloc( length )))
-        {
-            fprintf( stderr, "CreateSelectors: malloc() failed\n" );
-            exit( 1 );
-        }
-        entry.base           = (unsigned long) base_addr;
-        entry.limit          = length - 1;
-        entry.seg_32bit      = 0;
-        entry.limit_in_pages = 0;
-
 	/*
 	 * Is this a DATA or CODE segment?
 	 */
         if (seg_table[i].seg_flags & NE_SEGFLAGS_DATA)
         {
-            entry.type = SEGMENT_DATA;
-            entry.read_only = seg_table[i].seg_flags & NE_SEGFLAGS_READONLY;
-            memset( base_addr, 0, length );
+            handle = GLOBAL_Alloc( GMEM_ZEROINIT, length, 0, FALSE,
+                               seg_table[i].seg_flags & NE_SEGFLAGS_READONLY );
         }
         else
         {
-            entry.type = SEGMENT_CODE;
-            entry.read_only = seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY;
+            handle = GLOBAL_Alloc( 0, length, 0, TRUE,
+                            seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY );
         }
-        LDT_SetEntry( SELECTOR_TO_ENTRY(selectors[i]), &entry );
+        base_addr = GlobalLock( handle );
+        selectors[i] = GlobalHandleToSel( handle );
 
 	if (seg_table[i].seg_data_offset != 0)
 	{
@@ -578,14 +523,13 @@ unsigned short *CreateSelectors(struct w_files * wpnt)
 	    saved_old_length = old_length;
 	}
     }
-
     if(!auto_data_sel)dprintf_selectors(stddeb,"Warning: No auto_data_sel\n");
     for (i = 0; i < ne_header->n_segment_tab; i++)
     {
 /*	Segments[s->selector >> __AHSHIFT].owner = auto_data_sel; */
 	if (selectors[i] == auto_data_sel)
             LocalInit( auto_data_sel, saved_old_length,
-			   0x10000 - 2 - saved_old_length 
+			   0x10000 - 2
 			   - ne_header->stack_length );
 #if 0
 	    HEAP_LocalInit(auto_data_sel,
@@ -610,7 +554,6 @@ unsigned short *CreateSelectors(struct w_files * wpnt)
 void
 FixupFunctionPrologs(struct w_files * wpnt)
 {
-    struct ne_header_s *ne_header = wpnt->ne->ne_header;   
     union lookup entry_tab_pointer;
     struct entry_tab_header_s *eth;
     struct entry_tab_movable_s *etm;
@@ -618,9 +561,9 @@ FixupFunctionPrologs(struct w_files * wpnt)
     unsigned char *fixup_ptr;
     int i;
 
-    if (!(ne_header->format_flags & 0x0001))
+/*    if (!(ne_header->format_flags & NE_FFLAGS_SINGLEDATA))
 	return;
-
+*/
     entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
     /*
      * Let's walk through the table and fixup prologs as we go.
@@ -645,26 +588,42 @@ FixupFunctionPrologs(struct w_files * wpnt)
 	    if (eth->seg_number >= 0xfe)
 	    {
 		etm = entry_tab_pointer.etm++;
+	      /* FIXME: Does anyone know the exact meaning of these flags? */
+	      /* 0x0001 seems to mean: Fix up the function prolog          */
+	        dprintf_selector(stddeb,"ETM_Flags: %04x ",etm->flags);
+	        if (!(etm->flags & 0x0001)) continue;
 		fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[etm->seg_number-1]) + etm->offset;
 	    }
 	    else
 	    {
 		etf = entry_tab_pointer.etf++;
+	        dprintf_selector(stddeb,"ETF_Flags: %04x ",etf->flags);
+	        if (!(etf->flags & 0x0001)) continue;
 		fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[eth->seg_number-1])
 			     + (int) etf->offset[0] 
 			     + ((int) etf->offset[1] << 8);
 
 	    }
+	    dprintf_selector(stddeb,"Signature: %02x %02x %02x,ff %x\n",
+			     fixup_ptr[0],fixup_ptr[1],fixup_ptr[2],
+			     wpnt->ne->ne_header->format_flags);
 
 	    /* Verify the signature */
 	    if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
 		 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
 		&& fixup_ptr[2] == 0x90)
 	    {
+	      if (wpnt->ne->ne_header->format_flags & NE_FFLAGS_SINGLEDATA) {
+		
 		fixup_ptr[0] = 0xb8;	/* MOV AX, */
 		fixup_ptr[1] = wpnt->hinstance;
 		fixup_ptr[2] = (wpnt->hinstance >> 8);
-	    }
+	      } else  {
+		fixup_ptr[0] = 0x90; /* non-library: NOPs */	
+		fixup_ptr[1] = 0x90;
+		fixup_ptr[2] = 0x90;
+	      }
+	    } 
 	}
     }
 }
diff --git a/loader/signal.c b/loader/signal.c
index 5b348392e89c862a6e1add9caceb12eb24dcf0eb..c6943de5f899bac895b595770761cb58edd832ab 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -287,38 +287,4 @@ void init_wine_signals(void)
 #endif
 }
 
-static sigjmp_buf segv_jmpbuf;
-
-static void
-segv_handler()
-{
-    siglongjmp(segv_jmpbuf, 1);
-}
-
-int
-test_memory( char *p, int write )
-{
-    int ret = FALSE;
-    struct sigaction new_act;
-    struct sigaction old_act;
-
-    memset(&new_act, 0, sizeof new_act);
-    new_act.sa_handler = segv_handler;
-    if (sigsetjmp( segv_jmpbuf, 1 ) == 0) {
-	char c = 100;
-	if (sigaction(SIGSEGV, &new_act, &old_act) < 0)
-	    perror("sigaction");
-	c = *p;
-	if (write)
-	    *p = c;
-	ret = TRUE;
-    }
-#ifdef linux
-    wine_sigaction(SIGSEGV, &old_act, NULL);
-#else
-    sigaction(SIGSEGV, &old_act, NULL);
-#endif
-    return ret;
-}
-
 #endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index de42cc3ebf6a92f3b0e064c4b7c6f30e0e633338..93c14a55c8c3d211cc1b351c73248fd5bf043959 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -9,7 +9,7 @@ static char Copyright[] = "Copyright  Martin Ayotte, 1994";
 #include <sys/types.h>
 #include <unistd.h>
 #include "windows.h"
-#include "if1632.h"
+#include "callback.h"
 #include "task.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -102,11 +102,7 @@ BOOL EnumTaskWindows(HANDLE hTask, FARPROC lpEnumFunc, LONG lParam)
 	while ((hWnd = *(wptr++)) != 0) {
 		if (++count >= MAXWIN_PER_TASK) return FALSE;
 		dprintf_task(stddeb,"EnumTaskWindows // hWnd=%04X count=%d !\n", hWnd, count);
-#ifdef WINELIB
-		bRet = (*lpEnumFunc)(hWnd, lParam); 
-#else
-		bRet = CallBack16(lpEnumFunc, 2, 0, (int)hWnd, 2, (int)lParam);
-#endif
+                bRet = CallEnumTaskWndProc( lpEnumFunc, hWnd, lParam );
 		if (bRet == 0) break;
 		}
 	return TRUE;
diff --git a/memory/global.c b/memory/global.c
index f62f2fd0df2606e3d568ba5e3cca8e991365507f..2067ad0da6a3258e93e6ab5b3657ca98b791f182 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -13,20 +13,62 @@
 #include "stddebug.h"
 #include "debug.h"
 
+  /* Global arena block */
+typedef struct
+{
+    DWORD    base;           /* Base address  */
+    DWORD    size;           /* Size in bytes */
+    HGLOBAL  handle;         /* Handle for this block */
+    HGLOBAL  hOwner;         /* Owner of this block */
+    BYTE     lockCount;      /* Count of GlobalFix() calls */
+    BYTE     pageLockCount;  /* Count of GlobalPageLock() calls */
+    BYTE     flags;          /* Allocation flags */
+    BYTE     selCount;       /* Number of selectors allocated for this block */
+} GLOBALARENA;
+
+  /* Flags definitions */
+#define GA_DGROUP       0x04
+#define GA_DISCARDABLE  0x08
+
+  /* Arena array */
+static GLOBALARENA *pGlobalArena = NULL;
+static int globalArenaSize = 0;
+
 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000  /* Largest allocation is 16M - 64K */
 
-#define HGLOBAL_TO_SEL(handle) \
-     ((handle == (HGLOBAL)-1) ? CURRENT_DS : GlobalHandleToSel(handle))
+#define GET_ARENA_PTR(handle)  (pGlobalArena + ((handle) >> __AHSHIFT))
 
 /***********************************************************************
- *           GlobalAlloc   (KERNEL.15)
+ *           GLOBAL_GetArena
+ *
+ * Return the arena for a given selector, growing the arena array if needed.
  */
-HGLOBAL GlobalAlloc( WORD flags, DWORD size )
+static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
 {
-    WORD sel;
-    void *ptr;
+    if (((sel >> __AHSHIFT) + selcount) >= globalArenaSize)
+    {
+        GLOBALARENA *pNewArena = realloc( pGlobalArena,
+                               (globalArenaSize + 256) * sizeof(GLOBALARENA) );
+        if (!pNewArena) return 0;
+        pGlobalArena = pNewArena;
+        memset( pGlobalArena + globalArenaSize, 0, 256 * sizeof(GLOBALARENA) );
+        globalArenaSize += 256;
+    }
+    return pGlobalArena + (sel >> __AHSHIFT);
+}
 
-    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+
+/***********************************************************************
+ *           GLOBAL_Alloc
+ *
+ * Implementation of GlobalAlloc()
+ */
+HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
+                      BOOL isCode, BOOL isReadOnly )
+{
+    WORD sel, selcount;
+    void *ptr;
+    GLOBALARENA *pArena;
 
       /* Fixup the size */
 
@@ -41,20 +83,50 @@ HGLOBAL GlobalAlloc( WORD flags, DWORD size )
 
       /* Allocate the selector(s) */
 
-    sel = SELECTOR_AllocBlock( ptr, size, SEGMENT_DATA, 0, 0 );
+    sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
+                               0, isReadOnly );
     if (!sel)
     {
         free( ptr );
         return 0;
     }
+    selcount = (size + 0xffff) / 0x10000;
+
+    if (!(pArena = GLOBAL_GetArena( sel, selcount )))
+    {
+        free( ptr );
+        FreeSelector( sel );
+        return 0;
+    }
+
+      /* Fill the arena block */
+
+    pArena->base = (DWORD)ptr;
+    pArena->size = GET_SEL_LIMIT(sel) + 1;
+    pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+    pArena->hOwner = hOwner;
+    pArena->lockCount = 0;
+    pArena->pageLockCount = 0;
+    pArena->flags = flags & 0xff;
+    if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
+    if (!isCode) pArena->flags |= GA_DGROUP;
+    pArena->selCount = selcount;
+    if (selcount > 1)  /* clear the next arena blocks */
+        memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
 
     if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
+    return pArena->handle;
+}
+
 
-      /* Return the handle */
-      /* If allocating a GMEM_FIXED block, the handle is the selector. */
-      /* Otherwise, the handle is the selector-1 (don't ask me why :-) */
-    if (flags & GMEM_MOVEABLE) return sel - 1;
-    else return sel;
+/***********************************************************************
+ *           GlobalAlloc   (KERNEL.15)
+ */
+HGLOBAL GlobalAlloc( WORD flags, DWORD size )
+{
+    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+
+    return GLOBAL_Alloc( flags, size, GetCurrentPDB(), 0, 0 );
 }
 
 
@@ -63,12 +135,18 @@ HGLOBAL GlobalAlloc( WORD flags, DWORD size )
  */
 HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
 {
-    WORD sel;
+    WORD sel, selcount;
     DWORD oldsize;
     void *ptr;
+    GLOBALARENA *pArena, *pNewArena;
 
     dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
                     handle, size, flags );
+    if (!handle)
+    {
+        printf( "GlobalReAlloc: handle is 0.\n" );
+        return 0;
+    }
 
       /* Fixup the size */
 
@@ -78,15 +156,17 @@ HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
 
       /* Reallocate the linear memory */
 
+    pArena = GET_ARENA_PTR( handle );
     sel = GlobalHandleToSel( handle );
-    ptr = (void *)GET_SEL_BASE( sel );
-    oldsize = GlobalSize( handle );
+    ptr = (void *)pArena->base;
+    oldsize = pArena->size;
     if (size == oldsize) return handle;  /* Nothing to do */
 
     ptr = realloc( ptr, size );
     if (!ptr)
     {
         FreeSelector( sel );
+        memset( pArena, 0, sizeof(GLOBALARENA) );
         return 0;
     }
 
@@ -96,17 +176,39 @@ HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
     if (!sel)
     {
         free( ptr );
+        memset( pArena, 0, sizeof(GLOBALARENA) );
         return 0;
     }
+    selcount = (size + 0xffff) / 0x10000;
 
-    if ((oldsize < size) && (flags & GMEM_ZEROINIT))
-        memset( (char *)ptr + oldsize, 0, size - oldsize );
+    if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
+    {
+        free( ptr );
+        FreeSelector( sel );
+        return 0;
+    }
+
+      /* Fill the new arena block */
 
-    if (sel == GlobalHandleToSel( handle ))
-        return handle;  /* Selector didn't change */
+    if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
+    pNewArena->base = (DWORD)ptr;
+    pNewArena->size = GET_SEL_LIMIT(sel) + 1;
+    pNewArena->selCount = selcount;
+    if (flags & GMEM_MODIFY)
+    {
+          /* Change the flags, leaving GA_DGROUP alone */
+        pNewArena->flags = (pNewArena->flags & GA_DGROUP) |
+                           (flags & ~GA_DGROUP);
+        if (flags & GMEM_DISCARDABLE) pNewArena->flags |= GA_DISCARDABLE;
+    }
+    pNewArena->handle = (pNewArena->flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+
+    if (selcount > 1)  /* clear the next arena blocks */
+        memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
 
-    if (flags & GMEM_MOVEABLE) return sel - 1;
-    else return sel;
+    if ((oldsize < size) && (flags & GMEM_ZEROINIT))
+        memset( (char *)ptr + oldsize, 0, size - oldsize );
+    return pNewArena->handle;
 }
 
 
@@ -119,10 +221,12 @@ HGLOBAL GlobalFree( HGLOBAL handle )
     void *ptr;
 
     dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
+    if (!handle) return 0;
     sel = GlobalHandleToSel( handle );
     ptr = (void *)GET_SEL_BASE(sel);
     if (FreeSelector( sel )) return handle;  /* failed */
     free( ptr );
+    memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
     return 0;
 }
 
@@ -136,7 +240,7 @@ SEGPTR WIN16_GlobalLock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "WIN16_GlobalLock: %04x\n", handle );
     if (!handle) return 0;
-    return (SEGPTR)MAKELONG( 0, HGLOBAL_TO_SEL(handle) );
+    return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
 }
 
 
@@ -149,7 +253,7 @@ LPSTR GlobalLock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalLock: %04x\n", handle );
     if (!handle) return 0;
-    return (LPSTR)GET_SEL_BASE( HGLOBAL_TO_SEL(handle) );
+    return (LPSTR)GET_ARENA_PTR(handle)->base;
 }
 
 
@@ -170,7 +274,7 @@ DWORD GlobalSize( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalSize: %04x\n", handle );
     if (!handle) return 0;
-    return GET_SEL_LIMIT( HGLOBAL_TO_SEL(handle) ) + 1;
+    return GET_ARENA_PTR(handle)->size;
 }
 
 
@@ -179,11 +283,8 @@ DWORD GlobalSize( HGLOBAL handle )
  */
 DWORD GlobalHandle( WORD sel )
 {
-      /* FIXME: what about GMEM_FIXED blocks? */
-    WORD handle = sel & ~1;
-    dprintf_global( stddeb, "GlobalHandle(%04x): returning %08lx\n",
-                    sel, MAKELONG( handle, sel ) );
-    return MAKELONG( handle, sel );
+    dprintf_global( stddeb, "GlobalHandle: %04x\n", sel );
+    return MAKELONG( GET_ARENA_PTR(sel)->handle, sel );
 }
 
 
@@ -192,8 +293,12 @@ DWORD GlobalHandle( WORD sel )
  */
 WORD GlobalFlags( HGLOBAL handle )
 {
+    GLOBALARENA *pArena;
+
     dprintf_global( stddeb, "GlobalFlags: %04x\n", handle );
-    return 0;  /* lock count is always 0 */
+    pArena = GET_ARENA_PTR(handle);
+    return pArena->lockCount |
+           ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0);
 }
 
 
@@ -204,6 +309,7 @@ HGLOBAL LockSegment( HGLOBAL handle )
 {
     dprintf_global( stddeb, "LockSegment: %04x\n", handle );
     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    GET_ARENA_PTR(handle)->lockCount++;
     return handle;
 }
 
@@ -214,6 +320,8 @@ HGLOBAL LockSegment( HGLOBAL handle )
 void UnlockSegment( HGLOBAL handle )
 {
     dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
+    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    GET_ARENA_PTR(handle)->lockCount--;
     /* FIXME: this ought to return the lock count in CX (go figure...) */
 }
 
@@ -230,9 +338,9 @@ DWORD GlobalCompact( DWORD desired )
 /***********************************************************************
  *           GlobalWire   (KERNEL.111)
  */
-LPSTR GlobalWire( HGLOBAL handle )
+SEGPTR GlobalWire( HGLOBAL handle )
 {
-    return GlobalLock( handle );
+    return WIN16_GlobalLock( handle );
 }
 
 
@@ -312,8 +420,7 @@ DWORD GetFreeSpace( UINT wFlags )
 WORD GlobalPageLock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
-    /* Nothing to do, as we can't page-lock a block (and we don't want to) */
-    return 1;  /* lock count */
+    return ++(GET_ARENA_PTR(handle)->pageLockCount);
 }
 
 
@@ -323,7 +430,7 @@ WORD GlobalPageLock( HGLOBAL handle )
 WORD GlobalPageUnlock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
-    return 0;  /* lock count */
+    return --(GET_ARENA_PTR(handle)->pageLockCount);
 }
 
 
@@ -333,7 +440,7 @@ WORD GlobalPageUnlock( HGLOBAL handle )
 void GlobalFix( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
-    /* Nothing to do, as all the blocks are fixed in linear memory anyway */
+    GET_ARENA_PTR(handle)->lockCount++;
 }
 
 
@@ -343,7 +450,25 @@ void GlobalFix( HGLOBAL handle )
 void GlobalUnfix( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
-    /* This one is even more complicated that GlobalFix() :-) */
+    GET_ARENA_PTR(handle)->lockCount--;
+}
+
+
+/***********************************************************************
+ *           FarSetOwner   (KERNEL.403)
+ */
+void FarSetOwner( HANDLE handle, WORD hOwner )
+{
+    GET_ARENA_PTR(handle)->hOwner = hOwner;
+}
+
+
+/***********************************************************************
+ *           FarGetOwner   (KERNEL.404)
+ */
+WORD FarGetOwner( HANDLE handle )
+{
+    return GET_ARENA_PTR(handle)->hOwner;
 }
 
 
@@ -353,21 +478,98 @@ void GlobalUnfix( HGLOBAL handle )
 WORD GlobalHandleToSel( HGLOBAL handle )
 {
     dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
+    if (!handle) return 0;
     if (!(handle & 7))
     {
         fprintf( stderr, "Program attempted invalid selector conversion\n" );
         return handle - 1;
     }
-    return handle | 1;
+    return handle | 7;
 }
 
 
-/**********************************************************************
- *                      MemManInfo (toolhelp.72)
+/***********************************************************************
+ *           GlobalFirst   (TOOLHELP.51)
  */
-/*
-BOOL MemManInfo(LPMEMMANINFO lpmmi)
+BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
+{
+    if (wFlags == GLOBAL_LRU) return FALSE;
+    pGlobal->dwNext = 0;
+    return GlobalNext( pGlobal, wFlags );
+}
+
+
+/***********************************************************************
+ *           GlobalNext   (TOOLHELP.52)
+ */
+BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
+{
+    GLOBALARENA *pArena;
+
+    pArena = pGlobalArena + pGlobal->dwNext;
+    if (wFlags == GLOBAL_FREE)  /* only free blocks */
+    {
+        int i;
+        for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
+            if (pArena->size == 0) break;  /* block is free */
+        if (i >= globalArenaSize) return FALSE;
+        pGlobal->dwNext = i;
+    }
+
+    pGlobal->dwAddress    = pArena->base;
+    pGlobal->dwBlockSize  = pArena->size;
+    pGlobal->hBlock       = pArena->handle;
+    pGlobal->wcLock       = pArena->lockCount;
+    pGlobal->wcPageLock   = pArena->pageLockCount;
+    pGlobal->wFlags       = (GetCurrentPDB() == pArena->hOwner);
+    pGlobal->wHeapPresent = FALSE;
+    pGlobal->hOwner       = pArena->hOwner;
+    pGlobal->wType        = GT_UNKNOWN;
+    pGlobal->wData        = 0;
+    pGlobal->dwNext++;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GlobalInfo   (TOOLHELP.53)
+ */
+BOOL GlobalInfo( GLOBALINFO *pInfo )
+{
+    int i;
+    GLOBALARENA *pArena;
+
+    pInfo->wcItems = globalArenaSize;
+    pInfo->wcItemsFree = 0;
+    pInfo->wcItemsLRU = 0;
+    for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
+        if (pArena->size == 0) pInfo->wcItemsFree++;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GlobalEntryHandle   (TOOLHELP.54)
+ */
+BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem )
+{
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           GlobalEntryModule   (TOOLHELP.55)
+ */
+BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg )
+{
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           MemManInfo   (TOOLHELP.72)
+ */
+BOOL MemManInfo( MEMMANINFO *pInfo )
 {
-	return 1;
+    return TRUE;
 }
-*/
diff --git a/memory/local.c b/memory/local.c
index 5adf693b6ad6285f59f4b764846095c3a6f261f4..8c9a82933c9a3963736804ff132dec8988c7aa89 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -285,11 +285,19 @@ HLOCAL LocalInit( WORD selector, WORD start, WORD end )
       /* - large free block    (FREE)       */
       /* - last arena          (FREE)       */
 
-      /* FIXME: What should be done if there's already */
-      /* a local heap in this segment? */
     dprintf_local(stddeb, "LocalInit: %04x %04x-%04x\n", selector, start, end);
     if (!selector) selector = CURRENT_DS;
     ptr = PTR_SEG_OFF_TO_LIN( selector, 0 );
+    pHeapInfo = LOCAL_GetHeap(selector);
+      /* If there's already a local heap in this segment, */
+      /* we simply return TRUE. Helps some programs, but  */
+      /* does not seem to be 100% correct yet (there are  */
+      /* still some "heap corrupted" messages in LocalAlloc */
+    if (pHeapInfo)  {
+      dprintf_local(stddeb,"LocalInit: Heap %04x initialized twice.\n",selector);
+      if (debugging_local) LOCAL_PrintHeap(selector);
+      return TRUE;
+    }
     start = LALIGN( max( start, sizeof(INSTANCEDATA) ) );
     heapInfoArena = LALIGN(start + sizeof(LOCALARENA) );
     freeArena = LALIGN( heapInfoArena + ARENA_HEADER_SIZE
@@ -368,14 +376,20 @@ HLOCAL LOCAL_Alloc( WORD ds, WORD flags, WORD size )
 
       /* Find a suitable free block */
 
-    if (!(pInfo = LOCAL_GetHeap( ds ))) return 0;
+    if (!(pInfo = LOCAL_GetHeap( ds ))) {
+	  LOCAL_PrintHeap(ds);
+      return 0;
+    }
     size += ARENA_HEADER_SIZE;
     size = LALIGN( max( size, sizeof(LOCALARENA) ) );
     arena = pInfo->first;
     pArena = ARENA_PTR( ptr, arena );
     for (;;)
     {
-        if (arena == pArena->free_next) return 0;  /* not found */
+        if (arena == pArena->free_next) {
+	  LOCAL_PrintHeap(ds);
+	   return 0;  /* not found */
+	}
         arena = pArena->free_next;
         pArena = ARENA_PTR( ptr, arena );
         if (pArena->size >= size) break;
@@ -635,6 +649,7 @@ WORD LocalShrink( HLOCAL handle, WORD newsize )
  */
 DWORD GetHeapSpaces( HMODULE module )
 {
+    return MAKELONG( 0x7fff, 0xffff );
 }
 
 
diff --git a/memory/selector.c b/memory/selector.c
index c9dc5ae7c2d41ea2a203be8be94ed27ce0178c79..60556c2148599c6e3a74181a96221e67523de517 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -4,22 +4,16 @@
  * Copyright 1995 Alexandre Julliard
  */
 
+#include <string.h>
 #include "windows.h"
 #include "ldt.h"
+#include "selectors.h"
 #include "stddebug.h"
 #include "debug.h"
 
 ldt_copy_entry ldt_copy[LDT_SIZE] = { {0,0}, };
 
-#define FIRST_LDT_ENTRY_TO_ALLOC  10
-
-
-/***********************************************************************
- *           SELECTOR_Init
- */
-void SELECTOR_Init()
-{
-}
+#define FIRST_LDT_ENTRY_TO_ALLOC  4
 
 
 /***********************************************************************
@@ -74,7 +68,7 @@ WORD FreeSelector( WORD sel )
     dprintf_selector( stddeb, "FreeSelector(%04x)\n", sel );
     if (IS_SELECTOR_FREE(sel)) return sel;  /* error */
     count = (GET_SEL_LIMIT(sel) >> 16) + 1;
-    entry.base = entry.limit = 0;  /* clear the LDT entries */
+    memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
     for (i = 0; i < count; i++)
         LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
     return 0;
@@ -129,7 +123,7 @@ static WORD SELECTOR_ReallocArray( WORD sel, WORD newcount )
     {
           /* Check if the next selectors are free */
         for (i = oldcount; i < newcount; i++)
-            if (!IS_SELECTOR_FREE(sel)) break;
+            if (!IS_SELECTOR_FREE(sel+i)) break;
         if (i < newcount)
         {
             FreeSelector( sel );
@@ -138,7 +132,7 @@ static WORD SELECTOR_ReallocArray( WORD sel, WORD newcount )
     }
     else if (oldcount > newcount) /* We need to remove selectors */
     {
-        entry.base = entry.limit = 0;  /* clear the LDT entries */
+        memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
         for (i = oldcount; i < newcount; i++)
             LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
     }
diff --git a/misc/Imakefile b/misc/Imakefile
index a5f54d2c5cf9a19e0f23fe8828e2619bc8c3dd4a..c2b18115a3026c2bea366648ee4c500a0ecc4627 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -7,6 +7,7 @@ SRCS = \
 	clipboard.c \
 	comm.c \
 	commdlg.c \
+	compobj.c \
 	dos_fs.c \
 	driver.c \
 	exec.c \
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 1b6cd824ecdc5b22c07c4831cc3457dfab1120f0..31ad412efeb7e9c97ee66e9efdeb200e84c3d9c2 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -19,6 +19,7 @@
 #include "library.h"
 #include "commdlg.h"
 #include "dlgs.h"
+#include "selectors.h"
 
 #define OPENFILEDLG2			11
 #define SAVEFILEDLG2			12
@@ -97,7 +98,8 @@ BOOL GetOpenFileName(LPOPENFILENAME lpofn)
 	printf("GetOpenFileName // apres LoadResource hDlgTmpl=%04X!\n", hDlgTmpl);
     wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, (WNDPROC)FileOpenDlgProc, (DWORD)lpofn); 
+		lpofn->hwndOwner, GetWndProcEntry16("FileOpenDlgProc"), 
+	        (DWORD)lpofn); 
 
 /*	strcpy(lpofn->lpstrFile, "SETUP.TXT"); */
 /*	strcpy(lpofn->lpstrFileTitle, "SETUP.TXT");*/
@@ -156,7 +158,8 @@ BOOL GetSaveFileName(LPOPENFILENAME lpofn)
 		}
     wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, (WNDPROC)FileSaveDlgProc, (DWORD)lpofn);
+		lpofn->hwndOwner, GetWndProcEntry16("FileSaveDlgProc"), 
+		(DWORD)lpofn);
 	printf("GetSaveFileName // return lpstrFile='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrFile));
 	return bRet;
 }
@@ -175,7 +178,8 @@ BOOL ChooseColor(LPCHOOSECOLOR lpChCol)
 	hDlgTmpl = LoadResource(hSysRes, hResInfo);
     wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpChCol->hwndOwner, (WNDPROC)ColorDlgProc, (DWORD)lpChCol);
+		lpChCol->hwndOwner, GetWndProcEntry16("ColorDlgProc"), 
+		(DWORD)lpChCol);
 	return bRet;
 }
 
@@ -909,7 +913,8 @@ BOOL FindText(LPFINDREPLACE lpFind)
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, (WNDPROC)FindTextDlgProc, (DWORD)lpFind);
+		lpFind->hwndOwner, GetWndProcEntry16("FindTextDlgProc"), 
+	        (DWORD)lpFind);
 	return bRet;
 }
 
@@ -935,7 +940,8 @@ BOOL ReplaceText(LPFINDREPLACE lpFind)
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, (WNDPROC)ReplaceTextDlgProc, (DWORD)lpFind);
+		lpFind->hwndOwner, GetWndProcEntry16("ReplaceTextDlgProc"), 
+		(DWORD)lpFind);
 	return bRet;
 }
 
@@ -1018,10 +1024,12 @@ BOOL PrintDlg(LPPRINTDLG lpPrint)
     wndPtr = WIN_FindWndPtr(lpPrint->hwndOwner);
 	if (lpPrint->Flags & PD_PRINTSETUP)
 		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, (WNDPROC)PrintSetupDlgProc, (DWORD)lpPrint);
+			lpPrint->hwndOwner, GetWndProcEntry16("PrintSetupDlgProc"),
+			(DWORD)lpPrint);
 	else
 		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, (WNDPROC)PrintDlgProc, (DWORD)lpPrint);
+			lpPrint->hwndOwner, GetWndProcEntry16("PrintDlgProc"),
+		        (DWORD)lpPrint);
 	return bRet;
 }
 
diff --git a/misc/compobj.c b/misc/compobj.c
new file mode 100644
index 0000000000000000000000000000000000000000..c527b0fc241172f7c7d38224edff9a0bf365fecd
--- /dev/null
+++ b/misc/compobj.c
@@ -0,0 +1,25 @@
+/*
+ *	COMPOBJ library
+ *
+ *	Copyright 1995	Martin von Loewis
+ */
+
+/*	At the moment, these are only empty stubs.
+ */
+
+#include "windows.h"
+#include "compobj.h"
+#include "ole.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           CoDisconnectObject
+ */
+OLESTATUS WINAPI CoDisconnectObject(
+	LPUNKNOWN lpUnk,
+	DWORD reserved)
+{
+    dprintf_ole(stdnimp,"CoDisconnectObject:%x %x\n",lpUnk,reserved);
+    return OLE_OK;
+}
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index f2752561afc59c0c1731707a15445637ca60a8ee..dfc69ddbc828c1c38549278c013023967f4118c0 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -334,38 +334,24 @@ int DOS_ValidDirectory(char *name)
    ".."'s in names like "/usr/bin/../lib/test" */
 void DOS_SimplifyPath(char *name)
 {
-  char *p = name, *q = name, *l = NULL;
+  char *l,*p;
   BOOL changed;
 
- start:
-  p = name;
-  q = name;
-  while( *p ) {
-    *q++ = *p++;
-    if( ( *p == '/' ) && ( *(p-1) == '/' ) )
-      p++;
-  }
-  *q = 0;
-
-  p = name;
-  q = name;
-  changed = FALSE;
-  while( *p ) {
-    if( (!changed) &&( *p == '/' ) && ( *(p+1) == '.' ) && ( *(p+2) == '.' ) ) {
-      if( l ) {
-	q = l;
-	p += 3;
-        changed = TRUE;
-	continue;
-      }
+  dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
+  do {
+    changed = FALSE;
+    while ((l = strstr(name,"//"))) {
+      strcpy(l,l+1); changed = TRUE;
+    } 
+    while ((l = strstr(name,"/../"))) {
+      *l = 0;
+      p = strrchr(name,'/');
+      if (p == NULL) p = name;
+      strcpy(p,l+3);
+      changed = TRUE;
     }
-    else if( *p == '/' )
-      l = q;
-    *q++ = *p++;
-  }
-  *q = 0;
-  if( changed)
-    goto start;
+  } while (changed);
+  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
 }
 
 
@@ -887,14 +873,6 @@ struct dosdirent *DOS_opendir(char *dosdirname)
 	char *unixdirname;
 	char temp[256];
 	
-	for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
-		;
-
-	if (x == MAX_OPEN_DIRS) {
-		fprintf( stderr, "DOS_opendir(): Too many open directories\n");
-		return NULL;
-	}
-
 	if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL)
 		return NULL;
 
@@ -905,13 +883,23 @@ struct dosdirent *DOS_opendir(char *dosdirname)
 		if (temp[y] == '/') 
 		{
 			temp[y++] = '\0';
-			strcpy(DosDirs[x].filemask, temp +y);
-			ToDos(DosDirs[x].filemask);
+		        unixdirname += y;
 			break;
 		}
 	}
 
-    	dprintf_dosfs(stddeb,"DOS_opendir: %s -> %s\n", unixdirname, temp);
+        for (x=0; x <= MAX_OPEN_DIRS; x++) {
+	  if (x == MAX_OPEN_DIRS) {
+	    fprintf( stderr, "DOS_opendir(): Too many open directories\n");
+	    return NULL;
+	  }
+	  if (!DosDirs[x].inuse) break;
+	  if (strcmp(DosDirs[x].unixpath,temp) == 0) break;
+	}
+        
+        strcpy(DosDirs[x].filemask, unixdirname);
+        ToDos(DosDirs[x].filemask);
+    	dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, temp);
 
 	DosDirs[x].inuse = 1;
 	strcpy(DosDirs[x].unixpath, temp);
diff --git a/misc/exec.c b/misc/exec.c
index 7d53906aa7324dbcadd15845da3cd9136aa39c2a..771fba294c19ce6bf5ceb7a34d989a3303f46d2b 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -85,7 +85,9 @@ void InitializeLoadedNewDLLs(HINSTANCE hInst)
         dprintf_exec(stddeb, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
 		    wpnt->name, cs_reg, ip_reg, ds_reg);
 
-	    rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
+            rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                                 0 /*es*/, 0 /*ax*/, 0 /*bx*/, 0 /*cx*/,
+                                 0 /*dx*/, 0 /*si*/, wpnt->hinstance /*di*/ );
         dprintf_exec(stddeb,"rv = %x\n", rv);
 	}
     }
@@ -123,7 +125,9 @@ void StartNewTask(HINSTANCE hInst)
     sp_reg = wpnt->ne->ne_header->sp;
 
 	dprintf_exec(stddeb,"StartNewTask() before CallToInit16() !\n");
+/*
     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
+*/
     dprintf_exec(stddeb,"rv = %x\n", rv);
 
 }
diff --git a/misc/file.c b/misc/file.c
index 2f3aa2f4f05ba74868a35ae99bd2962383ea426f..c71673a409e13b2b9a4b8cee9817778c8e6e2085 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -23,11 +23,8 @@
 #include <sys/stat.h>
 #include <string.h>
 #include "dos_fs.h"
-#include "regfunc.h"
 #include "windows.h"
-#include "wine.h"
 #include "msdos.h"
-#include "registers.h"
 #include "options.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -118,11 +115,6 @@ INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
 #ifdef WINELIB
     dprintf_file(stdnimp, "OpenFile: not implemented\n");
 #else
-#ifndef PROCEMU
-    struct sigcontext_struct  ccontext;
-                              /* To make macros like EAX happy */
-    struct sigcontext_struct *context=&ccontext; 
-#endif
     char                      filename[MAX_PATH+1];
     int                       action;
     struct stat               s;
diff --git a/misc/main.c b/misc/main.c
index b672f44d49184bd2924f28fba541abb4a753c587..4da1c087bb488fdf20269a1b53eb8d5cdd9c80a7 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -28,8 +28,9 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 #include "desktop.h"
 #include "prototypes.h"
 #include "texts.h"
-#include "dlls.h"
 #include "library.h"
+#include "dlls.h"
+#include "if1632.h"
 #define DEBUG_DEFINE_VARIABLES
 #include "stddebug.h"
 #include "debug.h"
@@ -573,6 +574,7 @@ int main( int argc, char *argv[] )
     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
     else rootWindow = DefaultRootWindow( display );
 
+    RELAY_Init();
     MAIN_SaveSetup();
     DOS_InitFS();
     Comm_Init();
@@ -862,17 +864,6 @@ BOOL SwapMouseButton(BOOL fSwap)
 	return 0;	/* don't swap */
 }
 
-/***********************************************************************
-*	ISROMMODULE (KERNEL.323)
-*/
-BOOL IsRomModule(HANDLE x)
-{
-	/* I don't know the prototype, I assume that it returns true
-	   if the dll is located in rom */
-	   
-	return FALSE;
-}
-
 /***********************************************************************
 *	FileCDR (KERNEL.130)
 */
diff --git a/misc/message.c b/misc/message.c
index 6daf380ce053992b6259821ab69a2ae4a5514d8e..7d23f7e5eba408e00a7f8dcffb30d72c02071cee 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -19,6 +19,7 @@ static char Copyright[] = "Copyright Martin Ayotte, 1993";
 #include "win.h"
 #include "texts.h"
 #include "user.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_MSGBOX */
 #include "debug.h"
@@ -83,7 +84,7 @@ int MessageBox(HWND hWnd, LPSTR str, LPSTR title, WORD type)
 	HINSTANCE	hInst;
 	int			nRet;
 
-	if (title == NULL)
+        if (title == NULL)
 		title = "Error";
 	wndPtr = WIN_FindWndPtr(hWnd);
 	if (wndPtr == NULL) {
@@ -115,7 +116,7 @@ int MessageBox(HWND hWnd, LPSTR str, LPSTR title, WORD type)
 	lpmb->wType = type;
 	lpmb->ActiveFlg = TRUE;
 	wndClass.style           = CS_HREDRAW | CS_VREDRAW ;
-	wndClass.lpfnWndProc     = (WNDPROC)SystemMessageBoxProc;
+	wndClass.lpfnWndProc     = GetWndProcEntry16("SystemMessageBoxProc");
 	wndClass.cbClsExtra      = 0;
 	wndClass.cbWndExtra      = 4;
 	wndClass.hInstance       = hInst;
diff --git a/misc/network.c b/misc/network.c
index b662d99680131d90e81f296b482c3f7c01c2b4af..5c7ab4f60d9c079868b0cf721c430f9ec7dbef93 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -30,6 +30,124 @@
 
 typedef LPSTR 	LPNETRESOURCE;
 
+/**************************************************************************
+ *              WNetErrorText       [USER.499]
+ */
+int WNetErrorText(WORD nError,LPSTR lpszText,WORD cbText)
+{
+	printf("EMPTY STUB !!! WNetErrorText(%x,%p,%x)\n",
+		nError,lpszText,cbText);
+	return FALSE;
+}
+
+/**************************************************************************
+ *              WNetOpenJob       [USER.501]
+ */
+int WNetOpenJob(LPSTR szQueue,LPSTR szJobTitle,WORD nCopies,LPWORD pfh)
+{
+	printf("EMPTY STUB !!! WNetOpenJob('%s','%s',%x,%p)\n",
+		szQueue,szJobTitle,nCopies,pfh);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetCloseJob       [USER.502]
+ */
+int WNetCloseJob(WORD fh,LPWORD pidJob,LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetCloseJob(%x,%p,'%s')\n",
+		fh,pidJob,szQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetAbortJob       [USER.503]
+ */
+int WNetAbortJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetAbortJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetHoldJob       [USER.504]
+ */
+int WNetHoldJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetHoldJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetReleaseJob       [USER.505]
+ */
+int WNetReleaseJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetReleaseJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetCancelJob       [USER.506]
+ */
+int WNetCancelJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetCancelJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetSetJobCopies       [USER.507]
+ */
+int WNetSetJobCopies(LPSTR szQueue,WORD wJobId,WORD nCopies)
+{
+	printf("EMPTY STUB !!! WNetSetJobCopies('%s',%x,%x)\n",
+		szQueue,wJobId,nCopies);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetWatchQueue       [USER.508]
+ */
+int WNetWatchQueue(HWND hWnd,LPSTR szLocal,LPSTR szUser,WORD nQueue)
+{
+	printf("EMPTY STUB !!! WNetWatchQueue(%x,'%s','%s',%x)\n",
+		hWnd,szLocal,szUser,nQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetUnwatchQueue       [USER.509]
+ */
+int WNetUnwatchQueue(LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetUnwatchQueue('%s')\n", szQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetLockQueueData       [USER.510]
+ */
+int WNetLockQueueData(LPSTR szQueue,LPSTR szUser,void *lplpQueueStruct)
+{
+	printf("EMPTY STUB !!! WNetLockQueueData('%s','%s',%p)\n",
+		szQueue,szUser,lplpQueueStruct);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetUnlockQueueData       [USER.511]
+ */
+int WNetUnlockQueueData(LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetUnlockQueueData('%s')\n",szQueue);
+	return WN_NET_ERROR;
+}
+
 /**************************************************************************
  *				WNetGetConnection	[USER.512]
  */
@@ -49,6 +167,25 @@ int WNetGetCaps(WORD capability)
 	return 0;
 }
 
+/**************************************************************************
+ *              WNetDeviceMode       [USER.514]
+ */
+int WNetDeviceMode(HWND hWndOwner)
+{
+	printf("EMPTY STUB !!! WNetDeviceMode(%x)\n",hWndOwner);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetBrowseDialog       [USER.515]
+ */
+int WNetBrowseDialog(HWND hParent,WORD nType,LPSTR szPath)
+{
+	printf("EMPTY STUB !!! WNetBrowseDialog(%x,%x,'%s')\n",
+		hParent,nType,szPath);
+	return WN_NET_ERROR;
+}
+
 /**************************************************************************
  *				WNetGetUser			[USER.516]
  */
@@ -80,6 +217,126 @@ UINT WNetCancelConnection(LPSTR lpName, BOOL bForce)
 	return	WN_NET_ERROR;
 }
 
+/**************************************************************************
+ *              WNetGetError       [USER.519]
+ */
+int WNetGetError(LPWORD nError)
+{
+	printf("EMPTY STUB !!! WNetGetError(%p)\n",nError);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetErrorText       [USER.520]
+ */
+int WNetGetErrorText(WORD nError, LPSTR lpBuffer, LPWORD nBufferSize)
+{
+	printf("EMPTY STUB !!! WNetGetErrorText(%x,%p,%p)\n",
+		nError,lpBuffer,nBufferSize);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetRestoreConnection       [USER.523]
+ */
+int WNetRestoreConnection(HWND hwndOwner,LPSTR lpszDevice)
+{
+	printf("EMPTY STUB !!! WNetRestoreConnection(%x,'%s')\n",
+		hwndOwner,lpszDevice);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetWriteJob       [USER.524]
+ */
+int WNetWriteJob(WORD hJob,void *lpData,LPWORD lpcbData)
+{
+	printf("EMPTY STUB !!! WNetWriteJob(%x,%p,%p)\n",
+		hJob,lpData,lpcbData);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WnetConnectDialog       [USER.525]
+ */
+UINT WNetConnectDialog(HWND hWndParent, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetConnectDialog(%4X, %4X)\n", hWndParent, iType);
+	return WN_SUCCESS;
+}
+
+/**************************************************************************
+ *              WNetDisconnectDialog       [USER.526]
+ */
+int WNetDisconnectDialog(HWND hwndOwner, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetDisconnectDialog(%x,%x)\n",
+		hwndOwner,iType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WnetConnectionDialog     [USER.527]
+ */
+UINT WNetConnectionDialog(HWND hWndParent, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetConnectionDialog(%4X, %4X)\n", 
+		hWndParent, iType);
+	return WN_SUCCESS;
+}
+
+/**************************************************************************
+ *              WNetViewQueueDialog       [USER.528]
+ */
+int WNetViewQueueDialog(HWND hwndOwner,LPSTR lpszQueue)
+{
+	printf("EMPTY STUB !!! WNetViewQueueDialog(%x,'%s')\n",
+		hwndOwner,lpszQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetPropertyDialog       [USER.529]
+ */
+int WNetPropertyDialog(HWND hwndParent,WORD iButton,
+	WORD nPropSel,LPSTR lpszName,WORD nType)
+{
+	printf("EMPTY STUB !!! WNetPropertyDialog(%x,%x,%x,'%s',%x)\n",
+		hwndParent,iButton,nPropSel,lpszName,nType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetDirectoryType       [USER.530]
+ */
+int WNetGetDirectoryType(LPSTR lpName,void *lpType)
+{
+	printf("EMPTY STUB !!! WNetGetDirectoryType('%s',%p)\n",
+		lpName,lpType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetDirectoryNotify       [USER.531]
+ */
+int WNetDirectoryNotify(HWND hwndOwner,void *lpDir,WORD wOper)
+{
+	printf("EMPTY STUB !!! WNetDirectoryNotify(%x,%p,%x)\n",
+		hwndOwner,lpDir,wOper);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetPropertyText       [USER.532]
+ */
+int WNetGetPropertyText(HWND hwndParent,WORD iButton,WORD nPropSel,
+	LPSTR lpszName,WORD nType)
+{
+	printf("EMPTY STUB !!! WNetGetPropertyText(%x,%x,%x,'%s',%x)\n",
+		hwndParent,iButton,nPropSel,lpszName,nType);
+	return WN_NET_ERROR;
+}
+
 /**************************************************************************
  *				WNetAddConnection2	[USER.???]
  */
diff --git a/misc/property.c b/misc/property.c
index e97c3ea77269f8ac91158de42713220079c3d816..75f442f826196100c8a373c9ffc0f7014c6baa90 100644
--- a/misc/property.c
+++ b/misc/property.c
@@ -218,15 +218,8 @@ int EnumProps(HWND hWnd, FARPROC lpEnumFunc)
 	    	printf("EnumProps // lpProp->PropName='%s' !\n", lpProp->PropName);
 			str = lpProp->PropName; 
 			}
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)((HWND)hWnd, (WORD)0, 
-			(LPSTR)str, (HANDLE)lpProp->hData);
-#else
-		nRet = CallBack16(lpEnumFunc, 3,
-		    CALLBACK_SIZE_WORD, (HWND)hWnd,
-		    CALLBACK_SIZE_LONG, (LPSTR)str,
-		    CALLBACK_SIZE_WORD, (HANDLE)lpProp->hData);
-#endif
+                nRet = CallEnumPropProc( lpEnumFunc, hWnd,
+                                         (LONG)str, lpProp->hData);
 		if (nRet == 0) break;
 		if (lpProp->lpNextProp == NULL) break;
 		lpProp = lpProp->lpNextProp;
diff --git a/misc/shell.c b/misc/shell.c
index e5c804331bdd6148649e3fb6b0955be2f69182d0..f412887e1f06fa801b4602a460e87821b82284c7 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -9,6 +9,7 @@
 #include "library.h"
 #include "shell.h"
 #include "neexe.h"
+#include "selectors.h"
 #include "../rc/sysres.h"
 #include "stddebug.h"
 /* #define DEBUG_REG */
@@ -81,6 +82,7 @@ LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 	  dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
+        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
         while(*lpSubKey) {
           ptr = strchr(lpSubKey,'\\');
           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
@@ -128,6 +130,7 @@ LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 	  dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
+        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
         while (*lpSubKey) {
           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
           ptr = strchr(lpSubKey,'\\');
@@ -389,7 +392,7 @@ INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon)
 
 	return DialogBoxIndirectPtr( GetWindowWord(hWnd, GWW_HINSTANCE),
                                      sysres_DIALOG_SHELL_ABOUT_MSGBOX,
-                                     hWnd, (WNDPROC)AboutDlgProc);
+                                     hWnd, GetWndProcEntry16("AboutDlgProc"));
 }
 
 
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index 31c963449365ca717410114bcfc0f5151bdedaf0..70d8153a332e94d6d84472af1a7b5b416b6452d6 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include "regfunc.h"
+#include "wine.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
@@ -14,20 +14,21 @@ struct Win87EmInfoStruct {
   unsigned short Unused;
 };
 
-int
-WIN87_fpmath()
+void
+WIN87_fpmath( struct sigcontext_struct context )
 {
-  dprintf_int(stddeb, "_fpmath: (%x:%lx %x %x)\n",_CONTEXT->sc_cs, 
-	 _CONTEXT->sc_eip, _CONTEXT->sc_es, (unsigned int)_BX & 0xffff);
+  dprintf_int(stddeb, "_fpmath: (%x:%lx %x %x)\n",context.sc_cs, 
+              context.sc_eip, context.sc_es, (int)context.sc_ebx & 0xffff );
 
-  switch(_BX & 0xffff)
+  switch(context.sc_ebx & 0xffff)
     {
     case 11:
-      return 1;
+        context.sc_eax = 1;
+        break;
     default:
-      return 0;
+        context.sc_eax = 0;
+        break;
     }
-
 }
 
 void
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 03afeef18e2ba23c5b7b9a9941b3385b1595630f..28d4dca14597abe2709ab8162f39485d14444af0 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -16,7 +16,6 @@
 #include <utime.h>
 #include <ctype.h>
 #include "dos_fs.h"
-#include "regfunc.h"
 #include "windows.h"
 #include "msdos.h"
 #include "registers.h"
@@ -1669,10 +1668,9 @@ int do_int21(struct sigcontext_struct * context)
 /**********************************************************************
  *			DOS3Call
  */
-void DOS3Call(void)
+void DOS3Call( struct sigcontext_struct context )
 {
-    do_int21((struct sigcontext_struct *) _CONTEXT);
-    ReturnFromRegisterFunc();
+    do_int21( &context );
 }
 
 void INT21_Init(void)
diff --git a/miscemu/kernel.c b/miscemu/kernel.c
index 8f24c724d67d97a2f98a077f619bd723c2f6538b..f81410b8c78e1d264f7cbe8381b43f07503fdfc6 100644
--- a/miscemu/kernel.c
+++ b/miscemu/kernel.c
@@ -6,8 +6,8 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #include <stdio.h>
 #include <stdlib.h>
 #include "prototypes.h"
-#include "regfunc.h"
 #include "options.h"
+#include "wine.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -16,20 +16,14 @@ extern unsigned short WIN_StackSize;
 /**********************************************************************
  *					KERNEL_InitTask
  */
-void KERNEL_InitTask(void)
+void KERNEL_InitTask( struct sigcontext_struct context )
 {
-    _BX = 0x81;
-    _AX = 1;
-    _CX = WIN_StackSize;
-    _DX = Options.cmdShow;
-    _DI = _DS;
-
-/* FIXME: DI should contain the instance handle of the caller, _DS doesn't
-          always work as the caller might have changed it. */
-
-    _SI = 0;
-    ReturnFromRegisterFunc();
-    /* Function does not return */
+    context.sc_eax = 1;
+    context.sc_ebx = 0x81;
+    context.sc_ecx = WIN_StackSize;
+    context.sc_edx = Options.cmdShow;
+    context.sc_edi = 0;
+    context.sc_edi = context.sc_ds;
 }
 
 /**********************************************************************
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 27a2b3c004c5ca351eb98383e9d45646d2a30ba0..e2af222e62a9a21893517556bffc5a9314c1e93d 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -1833,14 +1833,9 @@ WORD FAR PASCAL MMSysTimeCallback(HWND hWnd, WORD wMsg, int nID, DWORD dwTime)
 			lpTimer->wCurTime = lpTimer->wDelay;
 			if (lpTimer->lpFunc != NULL) {
 				dprintf_mmtime(stddeb,"MMSysTimeCallback // before CallBack16 !\n");
-#ifdef WINELIB
-				(*lpTimer->lpFunc)(lpTimer->wTimerID, (WORD)0, 
-						lpTimer->dwUser, (DWORD)0, (DWORD)0);
-#else
-				CallBack16(lpTimer->lpFunc, 5, 
-					0, (int)lpTimer->wTimerID, 0, (int)0, 
-					2, lpTimer->dwUser, 2, 0, 2, 0);
-#endif
+                                CallTimeFuncProc( lpTimer->lpFunc,
+                                                  lpTimer->wTimerID, 0,
+                                                  lpTimer->dwUser, 0, 0 );
 				dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
 				fflush(stdout);
 				}
diff --git a/objects/font.c b/objects/font.c
index 15d1785b1eeb2315434c9d2e12d4bbfe2ac484de..5272b4f3ff0bad9b9e5c67f5b0a8b91a99f1641e 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -736,14 +736,10 @@ int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
 		SelectObject(hDC, hOldFont);
 		DeleteObject(hFont);
 		dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
-#else
-		nRet = CallBack16(lpEnumFunc, 4, 2, GDI_HEAP_SEG_ADDR(hLog),
-					2, GDI_HEAP_SEG_ADDR(hMet),
-                                        0, (int)0, 2, (int)lpData);
-#endif
+                nRet = CallEnumFontsProc( lpEnumFunc,
+                                          GDI_HEAP_SEG_ADDR(hLog),
+                                          GDI_HEAP_SEG_ADDR(hMet),
+                                          0, (LONG)lpData );
 		if (nRet == 0) {
 			dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
 			break;
@@ -823,13 +819,10 @@ int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData
 		DeleteObject(hFont);
 		dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
 
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
-#else
-		nRet = CallBack16(lpEnumFunc, 4, 2, GDI_HEAP_SEG_ADDR(hLog),
-					2, GDI_HEAP_SEG_ADDR(hMet),
-                                        0, (int)0, 2, (int)lpData);
-#endif
+                nRet = CallEnumFontFamProc( lpEnumFunc,
+                                            GDI_HEAP_SEG_ADDR(hLog),
+                                            GDI_HEAP_SEG_ADDR(hMet),
+                                            0, (LONG)lpData );
 		if (nRet == 0) {
 			dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
 			break;
@@ -840,5 +833,17 @@ int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData
 	return 0;
 }
 
+/*************************************************************************
+ *				GetRasterizerCaps	[GDI.313]
+ */
 
-
+BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
+{
+  /* This is not much more than a dummy */
+  RASTERIZER_STATUS rs;
+  
+  rs.nSize = sizeof(rs);
+  rs.wFlags = 0;
+  rs.nLanguageID = 0;
+  return True;
+}
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index fff10ce6d84cc517835defc092df32f6efe17bdd..ed865822b03a087867e65afb4f60604e3f7f8555 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -16,6 +16,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include "palette.h"
 #include "pen.h"
 #include "region.h"
+#include "callback.h"
 #include "stddebug.h"
 /* #define DEBUG_GDI */
 #include "debug.h"
@@ -486,16 +487,10 @@ int EnumObjects(HDC hDC, int nObjType, FARPROC lpEnumFunc, LPSTR lpData)
 				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
 				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
-			nRet = 1;
-/*
-#ifdef WINELIB
-			nRet = (*lpEnumFunc)(lpLog, lpData);
-#else
-			nRet = CallBack16(lpEnumFunc, 4, 2,
-                                      GDI_HEAP_SEG_ADDR(hLog), 2, (int)lpData);
-#endif
-*/
-			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
+			nRet = CallEnumObjectsProc( lpEnumFunc,
+                                                    GDI_HEAP_SEG_ADDR(hLog),
+                                                    (int)lpData );
+			dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
 			if (nRet == 0) {
 				GDI_HEAP_FREE(hLog);
 				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
@@ -524,16 +519,10 @@ int EnumObjects(HDC hDC, int nObjType, FARPROC lpEnumFunc, LPSTR lpData)
 				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
 				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
-/*
-#ifdef WINELIB
-			nRet = (*lpEnumFunc)(lpLog, lpData);
-#else
-			nRet = CallBack16(lpEnumFunc, 4, 2,
-                                      GDI_HEAP_SEG_ADDR(hLog), 2, (int)lpData);
-#endif
-*/
-			nRet = 1;
-			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
+			nRet = CallEnumObjectsProc( lpEnumFunc,
+                                                    GDI_HEAP_SEG_ADDR(hLog),
+                                                    (int)lpData );
+			dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
 			if (nRet == 0) {
 				GDI_HEAP_FREE(hLog);
 				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
diff --git a/objects/linedda.c b/objects/linedda.c
index 729f9ec26a80295525fade77b553c19a959c0154..d53e1336e022237f600f4a21189e4880b803a5c4 100644
--- a/objects/linedda.c
+++ b/objects/linedda.c
@@ -8,7 +8,7 @@ static char Copyright[] = "Copyright  Bob Amstadt, 1993";
 
 #include <stdlib.h>
 #include "windows.h"
-#include "if1632.h"
+#include "callback.h"
 
 /**********************************************************************
  *		LineDDA		(GDI.100)
@@ -16,32 +16,41 @@ static char Copyright[] = "Copyright  Bob Amstadt, 1993";
 void LineDDA(short nXStart, short nYStart, short nXEnd, short nYEnd,
 	     FARPROC callback, long lParam)
 {
-    int x, y;
-    int b;
-    int x_diff = nXEnd - nXStart;
-    int y_diff = nYEnd - nYStart;
+    int xadd = 1, yadd = 1;
+    int err,erradd;
+    int cnt;
+    int dx = nXEnd - nXStart;
+    int dy = nYEnd - nYStart;
 
-    if (x_diff == 0 && y_diff == 0)
-	return;
-    
-    if ((abs(x_diff) < abs(y_diff) && x_diff != 0) || y_diff == 0)
-    {
-	b = (nXStart * y_diff) / x_diff - nYStart;
-
-	for (x = nXStart; x <= nXEnd; x++)
-	{
-	    y = (x * y_diff) / x_diff + b;
-	    CallLineDDAProc(callback, x, y, lParam);
-	}
+    if (dx < 0)  {
+      dx = -dx; xadd = -1;
     }
-    else
-    {
-	b = (nYStart * x_diff) / y_diff - nXStart;
-
-	for (y = nYStart; y <= nYEnd; y++)
-	{
-	    x = (y * x_diff) / y_diff + b;
-	    CallLineDDAProc(callback, x, y, lParam);
+    if (dy < 0)  {
+      dy = -dy; yadd = -1;
+    }
+    if (dx > dy) { /* line is "more horizontal" */
+      err = 2*dy - dx; erradd = 2*dy - 2*dx;
+      for(cnt = 0;cnt <= dx; cnt++) {
+	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+	if (err > 0) {
+	  nYStart += yadd;
+	  err += erradd;
+	} else  {
+	  err += 2*dy;
+	}
+	nXStart += xadd;
+      }
+    } else  { /* line is "more vertical" */
+      err = 2*dx - dy; erradd = 2*dx - 2*dy;
+      for(cnt = 0;cnt <= dy; cnt++) {
+	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+	if (err > 0) {
+	  nXStart += xadd;
+	  err += erradd;
+	} else  {
+	  err += 2*dx;
 	}
+	nYStart += yadd;
+      }
     }
 }
diff --git a/toolkit/sup.c b/toolkit/sup.c
index 3d1be0c49874f335c58e7f877ddefcb9f6bc5da9..f22343c6b89678b898de7c3bae1ca444a585d3ba 100644
--- a/toolkit/sup.c
+++ b/toolkit/sup.c
@@ -13,21 +13,6 @@ LONG CallWindowProc (WNDPROC func, HWND hwnd, WORD message,
     return (*func)(hwnd, message, wParam, lParam);
 }
 
-CallLineDDAProc (FARPROC back, int x, int y, long lParam)
-{
-    return (*back)(x, y, lParam);
-}
-
-DWORD CallHookProc (HOOKPROC func, short code, WPARAM wParam, LPARAM lParam)
-{
-    return (*func)(code, wParam, lParam);
-}
-
-BOOL CallGrayStringProc (FARPROC func, HDC hdc, LPARAM lParam, INT cch)
-{
-    return (*func) (hdc, lParam, cch);
-}
-
 /*
  * Header loading routines for WineLib.
  */
diff --git a/tools/Imakefile b/tools/Imakefile
index 2c6613b0f40046cd44da556299fca23112c0a114..e5abd7b32439d1c8eb72e5aec5c1e19fe498483f 100644
--- a/tools/Imakefile
+++ b/tools/Imakefile
@@ -6,11 +6,7 @@ OBJS = $(SRCS:.c=.o)
 
 AllTarget(build)
 
-#ifndef NewBuild
 NormalProgramTarget(build,build.o,$(DEPLIBS),,)
-#else
-NormalProgramTarget(newbuild,$(OBJS),$(DEPLIBS),,)
-#endif
 
 DependTarget()
 
diff --git a/tools/build-spec.txt b/tools/build-spec.txt
index 25dfed69e6f3cfa6445cfefe7bf5ed766e1644db..af4c7fac2929f9960987d53f422c635820dc5df9 100644
--- a/tools/build-spec.txt
+++ b/tools/build-spec.txt
@@ -4,8 +4,7 @@ length	NUMBER_OF_ORDINALS
 
 ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]])
 
-ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]])
-		 HANDLERNAME([ARGNUM [ARGNUM [...]]])
+ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME
 
 ORDINAL equate EXPORTNAME DATA
 
@@ -36,34 +35,22 @@ ordinal 2 and containing 4 bytes:
 
 Function ordinals:
 
-    This type defines a function entry point.  The prototype defined
-by "EXPORTNAME ([ARGTYPE [ARGTYPE [...]]])" specifies the name available
-for dynamic linking and the format of the 16-bit stack.  By specifying
-"FUNCTYPE", the loader can automatically determine which order the
-parameters were pushed by the calling routine.  The prototype
-specified by "HANDLERNAME([ARGNUM [ARGNUM [...]]])"  specifies to
-the loader how to call the 32-bit library routine which will handle this
-call.  Note that specifying "ARGNUM" as 1 means the leftmost argument
-given to the function call, and not the first argument on the stack.
-For "pascal" functions, "ARGNUM" equal to 1 specifies the last
-argument on the stack.  If you do not specify any arguments to the
-handler function, then address of the 16-bit argument stack is
-passed to the handler function.
-    "ORDINAL" is replaced by the ordinal number corresponding to the
-function.  "FUNCTYPE" should be "c" or "pascal" ("pascal" may be
-shortened to "p").  "EXPORTNAME" will be the name available for
-dynamic linking.  "ARGTYPE" should be "byte", "word", "long", "ptr",
-"s_byte" (signed byte), "s_word" (signed word) or "s_long"
-(signed long).  "HANDLERNAME" is the name of the actual function
-that will process the request in 32-bit mode.  "ARGNUM" is the
-original argument number.  The first argument is numbered "1".
+    This type defines a function entry point.  The prototype defined by
+"EXPORTNAME ([ARGTYPE [ARGTYPE [...]]])" specifies the name available for
+dynamic linking and the format of the 16-bit stack. "ORDINAL" is replaced
+by the ordinal number corresponding to the function.  "FUNCTYPE" should be
+"pascal16" or "pascal" for 16-bit or 32-bit return values.  "ARGTYPE"
+should be "byte", "word", "long", "ptr" (linear pointer), "s_byte" (signed
+byte), "s_word" (signed word), "s_long" (signed long), or "segptr"
+(segmented pointer).  "HANDLERNAME" is the name of the actual function that
+will process the request in 32-bit mode.
 
     This first example defines an entry point for the CreateWindow()
 call (the ordinal 100 is just an example):
 
 	100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word
 				word word word ptr)
-		   WIN_CreateWindow(1 2 3 4 5 6 7 8 9 10 11)
+		   WIN_CreateWindow
 
    This second example defines an entry point for the GetFocus()
 call (the ordinal 100 is just an example):
diff --git a/tools/build.c b/tools/build.c
index c4e8125dc09f94acc69eda8f2a2ed1d857c49ea9..6c1d179dbee4ca78cba4ef3dd5053a27952c9564 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1,4 +1,7 @@
-/* static char Copyright[] = "Copyright  Robert J. Amstadt, 1993"; */
+/*
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,17 +9,6 @@
 #include <ctype.h>
 #include "wine.h"
 
-#ifdef linux
-#ifdef __ELF__
-#define UTEXTSEL 0x0f
-#else
-#define UTEXTSEL 0x23
-#endif
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UTEXTSEL 0x1f
-#endif
-
 /* ELF symbols do not have an underscore in front */
 #ifdef __ELF__
 #define PREFIX
@@ -24,66 +16,22 @@
 #define PREFIX "_"
 #endif
 
-#define VARTYPE_BYTE	0
-#define VARTYPE_SIGNEDWORD	0
-#define VARTYPE_WORD	1
-#define VARTYPE_LONG	2
-#define VARTYPE_FARPTR	3
-
-#define FUNCTYPE_PASCAL_16	16
-#define FUNCTYPE_PASCAL		17
-#define FUNCTYPE_REG		18
-
-#define EQUATETYPE_ABS	19
-#define TYPE_RETURN	20
+#define TYPE_INVALID     0
+#define TYPE_BYTE        1
+#define TYPE_WORD        2
+#define TYPE_LONG        3
+#define TYPE_PASCAL_16   4
+#define TYPE_PASCAL      5
+#define TYPE_REGISTER    6
+#define TYPE_ABS         7
+#define TYPE_RETURN      8
 
-/*#define MAX_ORDINALS	1024*/
 #define MAX_ORDINALS	1299
 
-#define PUSH_0		"\tpushl\t$0\n"
-#define PUSH_SS		"\tpushw\t$0\n\tpushw\t%%ss\n"
-#define PUSH_ESP	"\tpushl\t%%esp\n"
-#define PUSH_EFL	"\tpushfl\n"
-#define PUSH_CS		"\tpushw\t$0\n\tpushw\t%%cs\n"
-#define PUSH_EIP	"\tpushl\t$0\n"
-#define PUSH_DS		"\tpushw\t$0\n\tpushw\t%%ds\n"
-#define PUSH_ES		"\tpushw\t$0\n\tpushw\t%%es\n"
-#define PUSH_FS		"\tpushw\t$0\n\tpushw\t%%fs\n"
-#define PUSH_GS		"\tpushw\t$0\n\tpushw\t%%gs\n"
-#define PUSH_EAX	"\tpushl\t%%eax\n"
-#define PUSH_ECX	"\tpushl\t%%ecx\n"
-#define PUSH_EDX	"\tpushl\t%%edx\n"
-#define PUSH_EBX	"\tpushl\t%%ebx\n"
-#define PUSH_EBP	"\tpushl\t%%ebp\n"
-#define PUSH_ESI	"\tpushl\t%%esi\n"
-#define PUSH_EDI	"\tpushl\t%%edi\n"
-
-#define POP_0		"\tadd\t$4,%%esp\n"
-#define POP_SS		"\tpopw\t%%ss\n\tadd\t$2,%%esp\n"
-#define POP_ESP		"\tpopl\t%%esp\n"
-#define POP_EFL		"\tpopl\t%%gs:return_value\n"
-#define POP_CS		"\tpopw\t%%cs\n\tadd\t$2,%%esp\n"
-#define POP_EIP		"\tpopl\t$0\n"
-#define POP_DS		"\tpopw\t%%ds\n\tadd\t$2,%%esp\n"
-#define POP_ES		"\tpopw\t%%es\n\tadd\t$2,%%esp\n"
-#define POP_FS		"\tpopw\t%%fs\n\tadd\t$2,%%esp\n"
-#define POP_GS		"\tpopw\t%%gs\n\tadd\t$2,%%esp\n"
-#define POP_EAX		"\tpopl\t%%eax\n"
-#define POP_ECX		"\tpopl\t%%ecx\n"
-#define POP_EDX		"\tpopl\t%%edx\n"
-#define POP_EBX		"\tpopl\t%%ebx\n"
-#define POP_EBP		"\tpopl\t%%ebp\n"
-#define POP_ESI		"\tpopl\t%%esi\n"
-#define POP_EDI		"\tpopl\t%%edi\n"
-
-char **context_strings;
-char **pop_strings;
-int    n_context_strings;
-
 typedef struct ordinal_definition_s
 {
-    int valid;
     int type;
+    int offset;
     char export_name[80];
     void *additional_data;
 } ORDDEF;
@@ -96,10 +44,8 @@ typedef struct ordinal_variable_definition_s
 
 typedef struct ordinal_function_definition_s
 {
-    int n_args_16;
-    int arg_types_16[16];
-    int arg_16_offsets[16];
-    int arg_16_size;
+    int  n_args;
+    char arg_types[32];
     char internal_name[80];
 } ORDFUNCDEF;
 
@@ -109,7 +55,7 @@ typedef struct ordinal_return_definition_s
     int ret_value;
 } ORDRETDEF;
 
-ORDDEF OrdinalDefinitions[MAX_ORDINALS];
+static ORDDEF OrdinalDefinitions[MAX_ORDINALS];
 
 char LowerDLLName[80];
 char UpperDLLName[80];
@@ -122,7 +68,14 @@ char *ParseNext;
 char ParseSaveChar;
 int Line;
 
-int IsNumberString(char *s)
+static int debugging = 1;
+
+  /* Offset of register relative to the end of the context struct */
+#define CONTEXTOFFSET(reg) \
+   ((int)&(((struct sigcontext_struct *)1)->reg) - 1 \
+    - sizeof(struct sigcontext_struct))
+
+static int IsNumberString(char *s)
 {
     while (*s != '\0')
 	if (!isdigit(*s++))
@@ -131,7 +84,7 @@ int IsNumberString(char *s)
     return 1;
 }
 
-char *strlower(char *s)
+static char *strlower(char *s)
 {
     char *p;
     
@@ -141,7 +94,7 @@ char *strlower(char *s)
     return s;
 }
 
-char *strupper(char *s)
+static char *strupper(char *s)
 {
     char *p;
     
@@ -151,20 +104,7 @@ char *strupper(char *s)
     return s;
 }
 
-int stricmp(char *s1, char *s2)
-{
-    if (strlen(s1) != strlen(s2))
-	return -1;
-    
-    while (*s1 != '\0')
-	if (*s1++ != *s2++)
-	    return -1;
-    
-    return 0;
-}
-
-char *
-GetTokenInLine(void)
+static char * GetTokenInLine(void)
 {
     char *p;
     char *token;
@@ -200,8 +140,7 @@ GetTokenInLine(void)
     return token;
 }
 
-char *
-GetToken(void)
+static char * GetToken(void)
 {
     char *token;
 
@@ -235,8 +174,7 @@ GetToken(void)
     return token;
 }
 
-int
-ParseVariable(int ordinal, int type)
+static int ParseVariable(int ordinal, int type)
 {
     ORDDEF *odp;
     ORDVARDEF *vdp;
@@ -294,7 +232,6 @@ ParseVariable(int ordinal, int type)
     }
     
     odp = &OrdinalDefinitions[ordinal];
-    odp->valid = 1;
     odp->type = type;
     strcpy(odp->export_name, export_name);
     
@@ -307,16 +244,12 @@ ParseVariable(int ordinal, int type)
     return 0;
 }
 
-int
-ParseExportFunction(int ordinal, int type)
+static int ParseExportFunction(int ordinal, int type)
 {
     char *token;
     ORDDEF *odp;
     ORDFUNCDEF *fdp;
     int i;
-    int current_offset;
-    int arg_size;
-	
     
     if (ordinal >= MAX_ORDINALS)
     {
@@ -326,7 +259,6 @@ ParseExportFunction(int ordinal, int type)
     
     odp = &OrdinalDefinitions[ordinal];
     strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
     odp->type = type;
     fdp = malloc(sizeof(*fdp));
     odp->additional_data = fdp;
@@ -338,60 +270,39 @@ ParseExportFunction(int ordinal, int type)
 	exit(1);
     }
 
-    fdp->arg_16_size = 0;
     for (i = 0; i < 16; i++)
     {
 	token = GetToken();
 	if (*token == ')')
 	    break;
 
-	if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_WORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "s_byte") == 0 || 
-		 stricmp(token, "s_word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "long") == 0 || stricmp(token, "segptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_LONG;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else if (stricmp(token, "ptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_FARPTR;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
+	if (!strcmp(token, "byte") || !strcmp(token, "word"))
+            fdp->arg_types[i] = 'w';
+	else if (!strcmp(token, "s_byte") || !strcmp(token, "s_word"))
+            fdp->arg_types[i] = 's';
+	else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
+            fdp->arg_types[i] = 'l';
+	else if (!strcmp(token, "ptr"))
+            fdp->arg_types[i] = 'p';
 	else
 	{
 	    fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
 	    exit(1);
 	}
     }
-    fdp->n_args_16 = i;
+    fdp->arg_types[i] = '\0';
 
-    current_offset = 0;
-    for (i--; i >= 0; i--)
+    if ((type == TYPE_REGISTER) && (i > 0))
     {
-        arg_size = fdp->arg_16_offsets[i];
-        fdp->arg_16_offsets[i] = current_offset;
-        current_offset += arg_size;
+        fprintf( stderr, "%d: Register function can't have arguments\n", Line);
+        exit(1);
     }
 
     strcpy(fdp->internal_name, GetToken());
     return 0;
 }
 
-int
-ParseEquate(int ordinal)
+static int ParseEquate(int ordinal)
 {
     ORDDEF *odp;
     char *token;
@@ -416,15 +327,13 @@ ParseEquate(int ordinal)
 	exit(1);
     }
 
-    odp->valid = 1;
-    odp->type = EQUATETYPE_ABS;
+    odp->type = TYPE_ABS;
     odp->additional_data = (void *) value;
 
     return 0;
 }
 
-int
-ParseReturn(int ordinal)
+static int ParseReturn(int ordinal)
 {
     ORDDEF *odp;
     ORDRETDEF *rdp;
@@ -441,7 +350,6 @@ ParseReturn(int ordinal)
     
     odp = &OrdinalDefinitions[ordinal];
     strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
     odp->type = TYPE_RETURN;
     odp->additional_data = rdp;
 
@@ -466,8 +374,7 @@ ParseReturn(int ordinal)
     return 0;
 }
 
-int
-ParseOrdinal(int ordinal)
+static int ParseOrdinal(int ordinal)
 {
     char *token;
     
@@ -478,23 +385,23 @@ ParseOrdinal(int ordinal)
 	exit(1);
     }
 
-    if (stricmp(token, "byte") == 0)
-	return ParseVariable(ordinal, VARTYPE_BYTE);
-    else if (stricmp(token, "word") == 0)
-	return ParseVariable(ordinal, VARTYPE_WORD);
-    else if (stricmp(token, "long") == 0)
-	return ParseVariable(ordinal, VARTYPE_LONG);
-    else if (stricmp(token, "p") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal16") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL_16);
-    else if (stricmp(token, "register") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_REG);
-    else if (stricmp(token, "equate") == 0)
+    if (strcmp(token, "byte") == 0)
+	return ParseVariable(ordinal, TYPE_BYTE);
+    else if (strcmp(token, "word") == 0)
+	return ParseVariable(ordinal, TYPE_WORD);
+    else if (strcmp(token, "long") == 0)
+	return ParseVariable(ordinal, TYPE_LONG);
+    else if (strcmp(token, "p") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL);
+    else if (strcmp(token, "pascal") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL);
+    else if (strcmp(token, "pascal16") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL_16);
+    else if (strcmp(token, "register") == 0)
+	return ParseExportFunction(ordinal, TYPE_REGISTER);
+    else if (strcmp(token, "equate") == 0)
 	return ParseEquate(ordinal);
-    else if (stricmp(token, "return") == 0)
+    else if (strcmp(token, "return") == 0)
 	return ParseReturn(ordinal);
     else
     {
@@ -505,14 +412,13 @@ ParseOrdinal(int ordinal)
     }
 }
 
-int
-ParseTopLevel(void)
+static int ParseTopLevel(void)
 {
     char *token;
     
     while ((token = GetToken()) != NULL)
     {
-	if (stricmp(token, "name") == 0)
+	if (strcmp(token, "name") == 0)
 	{
 	    strcpy(LowerDLLName, GetToken());
 	    strlower(LowerDLLName);
@@ -520,7 +426,7 @@ ParseTopLevel(void)
 	    strcpy(UpperDLLName, LowerDLLName);
 	    strupper(UpperDLLName);
 	}
-	else if (stricmp(token, "id") == 0)
+	else if (strcmp(token, "id") == 0)
 	{
 	    token = GetToken();
 	    if (!IsNumberString(token))
@@ -531,7 +437,7 @@ ParseTopLevel(void)
 	    
 	    DLLId = atoi(token);
 	}
-	else if (stricmp(token, "length") == 0)
+	else if (strcmp(token, "length") == 0)
 	{
 	    token = GetToken();
 	    if (!IsNumberString(token))
@@ -562,85 +468,14 @@ ParseTopLevel(void)
     return 0;
 }
 
-void
-InitContext(void)
-{
-    struct sigcontext_struct context;
-    int i;
-    
-    n_context_strings = sizeof(context) / 4;
-    context_strings   = (char **) malloc(n_context_strings * sizeof(char **));
-    pop_strings       = (char **) malloc(n_context_strings * sizeof(char **));
-    for (i = 0; i < n_context_strings; i++)
-    {
-	context_strings[i] = PUSH_0;
-	pop_strings[i]     = POP_0;
-    }
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esp) / 4;
-    context_strings[i] = PUSH_ESP;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebp) / 4;
-    context_strings[i] = PUSH_EBP;
-    pop_strings[n_context_strings - 1 - i] = POP_EBP;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eip) / 4;
-    context_strings[i] = PUSH_EIP;
-
-#ifndef __FreeBSD__
-    i = n_context_strings - 1 + ((int) &context - (int)&context.sc_eflags) / 4;
-#else
-    i = n_context_strings - 1 + ((int) &context - (int)&context.sc_efl) / 4;
-#endif
-    context_strings[i] = PUSH_EFL;
-    pop_strings[n_context_strings - 1 - i] = POP_EFL;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_es) / 4;
-    context_strings[i] = PUSH_ES;
-    pop_strings[n_context_strings - 1 - i] = POP_ES;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ds) / 4;
-    context_strings[i] = PUSH_DS;
-    pop_strings[n_context_strings - 1 - i] = POP_DS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_cs) / 4;
-    context_strings[i] = PUSH_CS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ss) / 4;
-    context_strings[i] = PUSH_SS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edi) / 4;
-    context_strings[i] = PUSH_EDI;
-    pop_strings[n_context_strings - 1 - i] = POP_EDI;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esi) / 4;
-    context_strings[i] = PUSH_ESI;
-    pop_strings[n_context_strings - 1 - i] = POP_ESI;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebx) / 4;
-    context_strings[i] = PUSH_EBX;
-    pop_strings[n_context_strings - 1 - i] = POP_EBX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edx) / 4;
-    context_strings[i] = PUSH_EDX;
-    pop_strings[n_context_strings - 1 - i] = POP_EDX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ecx) / 4;
-    context_strings[i] = PUSH_ECX;
-    pop_strings[n_context_strings - 1 - i] = POP_ECX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eax) / 4;
-    context_strings[i] = PUSH_EAX;
-    pop_strings[n_context_strings - 1 - i] = POP_EAX;
-}
 
-void
-OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
+static int OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
 {
     ORDVARDEF *vdp;
     int i;
 
     vdp = odp->additional_data;
+    fprintf( fp, "\t.data\n" );
     for (i = 0; i < vdp->n_values; i++)
     {
 	if ((i & 7) == 0)
@@ -654,320 +489,770 @@ OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
 	    fprintf(fp, ", ");
     }
     fprintf(fp, "\n");
+    fprintf( fp, "\t.text\n" );
+    return vdp->n_values;
 }
 
-int main(int argc, char **argv)
+static void BuildSpecFiles( char *specname)
 {
     ORDDEF *odp;
     ORDFUNCDEF *fdp;
     ORDRETDEF *rdp;
     FILE *fp;
     char filename[80];
-    int i, ci, add_count, argnum;
-    int prev_index;      /* Index to previous #define (-1 if none) */
+    int i;
+    int code_offset, data_offset;
 
-    /* the difference between last #define and the current */
-    int prev_n_args;
-    
-    if (argc < 2)
+    SpecFp = fopen( specname, "r");
+    if (SpecFp == NULL)
     {
-	fprintf(stderr, "usage: build SPECNAME\n       build -p\n");
+	fprintf(stderr, "Could not open specification file, '%s'\n", specname);
 	exit(1);
     }
 
-    InitContext();
+    ParseTopLevel();
 
-    if (strcmp("-p", argv[1]) == 0)
+    sprintf(filename, "dll_%s.S", LowerDLLName);
+    fp = fopen(filename, "w");
+    fprintf( fp, "/* File generated automatically; do not edit! */\n" );
+    fprintf( fp, "\t.data\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Data_Start\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Data_Start:\n", UpperDLLName );
+    fprintf( fp, "\t.text\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Code_Start\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Code_Start:\n", UpperDLLName );
+    code_offset = data_offset = 0;
+
+    odp = OrdinalDefinitions;
+    for (i = 0; i <= Limit; i++, odp++)
     {
-	fp = fopen("pop.h", "w");
-	add_count = 0;
-	for (i = 0; i < n_context_strings; i++)
-	{
-	    if (strncmp(pop_strings[i], "\tadd\t", 5) == 0)
-	    {
-		add_count += atoi(pop_strings[i] + 6);
-	    }
-	    else
-	    {
-		if (add_count > 0)
-		{
-		    fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
-		    add_count = 0;
-		}
+        fdp = odp->additional_data;
+        rdp = odp->additional_data;
+	    
+        switch (odp->type)
+        {
+          case TYPE_INVALID:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf( fp, "\tpushw %%bp\n" );
+            fprintf( fp, "\tpushl $0x%08x\n", (DLLId << 16) | i);
+            fprintf( fp, "\tpushl $" PREFIX "RELAY_Unimplemented\n" );
+            fprintf( fp, "\tljmp $0x%04x, $" PREFIX "CallTo32_word_\n",
+                         WINE_CODE_SELECTOR );
+            odp->offset = code_offset;
+            code_offset += 19;  /* Assembly code is 19 bytes long */
+            break;
+
+          case TYPE_ABS:
+            odp->offset = (int)odp->additional_data & 0xffff;
+            break;
+
+          case TYPE_BYTE:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += OutputVariableCode(fp, ".byte", odp);
+            break;
+
+          case TYPE_WORD:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += 2 * OutputVariableCode(fp, ".word", odp);
+            break;
+
+          case TYPE_LONG:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += 4 * OutputVariableCode(fp, ".long", odp);
+            break;
+
+          case TYPE_RETURN:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf( fp, "\tmovw $%d,%%ax\n", rdp->ret_value & 0xffff );
+            fprintf( fp, "\tmovw $%d,%%dx\n", (rdp->ret_value >> 16) & 0xffff);
+            fprintf(fp, "\t.byte 0x66\n");
+            if (rdp->arg_size != 0)
+                fprintf(fp, "\tlret $%d\n", rdp->arg_size);
+            else
+                fprintf(fp, "\tlret\n");
+            odp->offset = code_offset;
+            code_offset += 10;  /* Assembly code is 10 bytes long */
+            if (rdp->arg_size != 0) code_offset += 2;
+            break;
+
+          case TYPE_REGISTER:
+          case TYPE_PASCAL:
+          case TYPE_PASCAL_16:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf(fp, "\tpushw %%bp\n" );
+            fprintf(fp, "\tpushl $0x%08x\n", (DLLId << 16) | i);
+            fprintf(fp, "\tpushl $" PREFIX "%s\n", fdp->internal_name );
+            fprintf(fp, "\tljmp $0x%04x, $" PREFIX "CallTo32_%s_%s\n\n",
+                        WINE_CODE_SELECTOR,
+                        (odp->type == TYPE_REGISTER) ? "regs" :
+                        (odp->type == TYPE_PASCAL) ? "long" : "word",
+                        fdp->arg_types );
+            odp->offset = code_offset;
+            code_offset += 19;  /* Assembly code is 19 bytes long */
+            break;
 		
-		fprintf(fp, pop_strings[i]);
-	    }
+          default:
+            fprintf( stderr, "build: Unknown function type; please report.\n");
+            break;
 	}
-    
-	if (add_count > 0)
-	    fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
-
-	fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
-		
-	fclose(fp);
-	exit(0);
     }
 
-    SpecFp = fopen(argv[1], "r");
-    if (SpecFp == NULL)
-    {
-	fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
-	exit(1);
-    }
+    fprintf( fp, "\t.data\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Data_End\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Data_End:\n", UpperDLLName );
+    fprintf( fp, "\t.text\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Code_End\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Code_End:\n", UpperDLLName );
 
-    ParseTopLevel();
+    fclose(fp);
 
-    sprintf(filename, "dll_%s.S", LowerDLLName);
+    sprintf(filename, "tab_%s.c", LowerDLLName);
     fp = fopen(filename, "w");
-#ifdef __ELF__
-    fprintf (fp, "#define __ASSEMBLY__\n");
-    fprintf (fp, "#include <asm/segment.h>\n");
-#endif
 
+    fprintf( fp, "/* File generated automatically; do not edit! */\n\n" );
+    fprintf( fp, "#include \"dlls.h\"\n\n" );
+    fprintf( fp, "static struct dll_table_entry_s %s_table_entries[%d] =\n{\n",
+                 UpperDLLName, Limit + 1);
     odp = OrdinalDefinitions;
     for (i = 0; i <= Limit; i++, odp++)
     {
-	fprintf(fp, "\t.globl " PREFIX "%s_Ordinal_%d\n", UpperDLLName, i);
+        int selector;
 
-	if (!odp->valid)
-	{
-	    fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-	    fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-	    fprintf(fp, "\tpushw\t$0\n");
-#ifdef __ELF__
-            fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-            fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-	}
-	else
+	fdp = odp->additional_data;
+
+	switch (odp->type)
 	{
-	    fdp = odp->additional_data;
-	    rdp = odp->additional_data;
-	    
-	    switch (odp->type)
-	    {
-	      case EQUATETYPE_ABS:
-		fprintf(fp, PREFIX "%s_Ordinal_%d = %d\n\n", 
-			UpperDLLName, i, (int) odp->additional_data);
-		break;
+        case TYPE_INVALID:
+        case TYPE_PASCAL:
+        case TYPE_PASCAL_16:
+        case TYPE_REGISTER:
+            selector = 1;  /* Code selector */
+            break;
+
+        case TYPE_BYTE:
+        case TYPE_WORD:
+        case TYPE_LONG:
+            selector = 2;  /* Data selector */
+            break;
+
+        case TYPE_ABS:
+            selector = 0xff;  /* Constant selector */
+            break;
+        }
 
-	      case VARTYPE_BYTE:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".byte", odp);
-		break;
+        fprintf(fp, "    { %d, %d, ", selector, odp->offset );
+        fprintf(fp, "\"%s\" ", odp->export_name);
+#ifdef WINESTAT
+        fprintf(fp, ",0 ");
+#endif	    
+        fprintf(fp, "}, \n");
+    }
 
-	      case VARTYPE_WORD:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".word", odp);
-		break;
+    fprintf(fp, "};\n\n");
+
+    fprintf( fp, "extern void %s_Code_Start();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Code_End();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Data_Start();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Data_End();\n\n", UpperDLLName );
+    fprintf( fp, "struct dll_table_s %s_table =\n{\n", UpperDLLName );
+    fprintf( fp, "  %s_table_entries, %d, %d,\n",
+             UpperDLLName, Limit + 1, DLLId );
+    fprintf( fp, "  (void *)%s_Code_Start, (void *)%s_Code_End,\n",
+             UpperDLLName, UpperDLLName );
+    fprintf( fp, "  (void *)%s_Data_Start, (void *)%s_Data_End\n};\n",
+             UpperDLLName, UpperDLLName );
+    fclose(fp);
+}
 
-	      case VARTYPE_LONG:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".long", odp);
-		break;
 
-	      case TYPE_RETURN:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
-		fprintf(fp, "\tmovw\t$%d,%%dx\n", 
-			(rdp->ret_value >> 16) & 0xffff);
-		fprintf(fp, "\t.byte\t0x66\n");
-		if (rdp->arg_size != 0)
-		    fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
-		else
-		    fprintf(fp, "\tlret\n");
-		break;
+/*******************************************************************
+ *         TransferArgs16To32
+ *
+ * Get the arguments from the 16-bit stack and push them on the 32-bit stack.
+ * The 16-bit stack layout is:
+ *   ...     ...
+ *  (bp+8)    arg2
+ *  (bp+6)    arg1
+ *  (bp+4)    cs
+ *  (bp+2)    ip
+ *  (bp)      bp
+ */
+static int TransferArgs16To32( char *args )
+{
+    int i, pos16, pos32;
 
-	      case FUNCTYPE_REG:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-
-		for (ci = 0; ci < n_context_strings; ci++)
-		    fprintf(fp, context_strings[ci]);
-
-		fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
-		fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
-		fprintf(fp, "\tpushl\t%d(%%ebp)\n",
-			sizeof(struct sigcontext_struct));
-		fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", 
-			sizeof(struct sigcontext_struct) + 4);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-		break;
+    /* Save ebx first */
 
-	      case FUNCTYPE_PASCAL:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-                break;
-		
-	      case FUNCTYPE_PASCAL_16:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32_16\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32_16\n\n");
-#endif
-		break;
-		
-	      default:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$0\n");
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-		break;
-	    }
-	}
+    printf( "\tpushl %%ebx\n" );
+
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Copy the arguments */
+
+    pos16 = 6;  /* skip bp and return address */
+    pos32 = 0;
+
+    for (i = strlen(args); i > 0; i--)
+    {
+        pos32 -= 4;
+        switch(args[i-1])
+        {
+        case 'w':  /* word */
+            printf( "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 2;
+            break;
+
+        case 's':  /* s_word */
+            printf( "\tmovswl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 2;
+            break;
+
+        case 'l':  /* long */
+            printf( "\tmovl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 4;
+            break;
+
+        case 'p':  /* ptr */
+            /* Get the selector */
+            printf( "\tmovw %d(%%ebp),%%ax\n", pos16 + 2 );
+            /* Get the selector base */
+            printf( "\tandl $0xfff8,%%eax\n" );
+            printf( "\tmovl " PREFIX "ldt_copy(%%eax),%%eax\n" );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            /* Add the offset */
+            printf( "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\taddl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 4;
+            break;
+
+        default:
+            fprintf( stderr, "Unknown arg type '%c'\n", args[i-1] );
+        }
     }
 
-    fclose(fp);
+    /* Restore ebx */
+    
+    printf( "\tpopl %%ebx\n" );
 
-#ifndef SHORTNAMES
-    sprintf(filename, "dll_%s_tab.c", LowerDLLName);
-#else
-    sprintf(filename, "dtb_%s.c", LowerDLLName);
+    return pos16 - 6;  /* Return the size of the 16-bit args */
+}
+
+
+/*******************************************************************
+ *         BuildContext
+ *
+ * Build the context structure on the 32-bit stack.
+ * The only valid registers in the context structure are:
+ *   eax, ebx, ecx, edx, esi, edi, ds, es, (some of the) flags
+ */
+static void BuildContext(void)
+{
+    /* Save ebx first */
+
+    printf( "\tpushl %%ebx\n" );
+
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Store the registers */
+
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_ebx) ); /* Get ebx from stack */
+    printf( "\tmovl %%eax,%d(%%ebx)\n", CONTEXTOFFSET(sc_eax) );
+    printf( "\tmovl %%ecx,%d(%%ebx)\n", CONTEXTOFFSET(sc_ecx) );
+    printf( "\tmovl %%edx,%d(%%ebx)\n", CONTEXTOFFSET(sc_edx) );
+    printf( "\tmovl %%esi,%d(%%ebx)\n", CONTEXTOFFSET(sc_esi) );
+    printf( "\tmovl %%edi,%d(%%ebx)\n", CONTEXTOFFSET(sc_edi) );
+    printf( "\tmovw %%es,%d(%%ebx)\n", CONTEXTOFFSET(sc_es) );
+    printf( "\tmovw -10(%%ebp),%%ax\n" );  /* Get saved ds from stack */
+    printf( "\tmovw %%ax,%d(%%ebx)\n", CONTEXTOFFSET(sc_ds) );
+    printf( "\tpushfl\n" );
+#ifndef __FreeBSD__
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
+#else    
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_efl) );
 #endif
-    fp = fopen(filename, "w");
+}
 
-    fprintf(fp, "#include <stdio.h>\n");
-    fprintf(fp, "#include <stdlib.h>\n");
-    fprintf(fp, "#include \042dlls.h\042\n\n");
 
-    for (i = 0; i <= Limit; i++)
+/*******************************************************************
+ *         RestoreContext
+ *
+ * Restore the registers from the context structure
+ */
+static void RestoreContext(void)
+{
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Restore the registers */
+
+    printf( "\tmovl %d(%%ebx),%%ecx\n", CONTEXTOFFSET(sc_ecx) );
+    printf( "\tmovl %d(%%ebx),%%edx\n", CONTEXTOFFSET(sc_edx) );
+    printf( "\tmovl %d(%%ebx),%%esi\n", CONTEXTOFFSET(sc_esi) );
+    printf( "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(sc_edi) );
+    printf( "\tmovw %d(%%ebx),%%es\n", CONTEXTOFFSET(sc_es) );
+    printf( "\tpopw %%ax\n" );  /* Remove old ds from the stack */
+    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_ds) ); /* Push new ds */
+#ifndef __FreeBSD__
+    printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
+#else    
+    printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(sc_efl) );
+#endif
+    printf( "\tpopfl\n" );
+    printf( "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(sc_eax) );
+    printf( "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(sc_ebx) );
+}
+
+
+/*******************************************************************
+ *         BuildCall32Func
+ *
+ * Build a 32-bit callback function. The syntax of the function
+ * profile is: type_xxxxx, where 'type' is one of 'regs', 'word' or
+ * 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
+ * 'l'=long, 'p'=pointer).
+ *
+ * Stack layout upon entry to the callback function:
+ *  ...      ...
+ * (sp+14)  first 16-bit arg
+ * (sp+12)  cs (word)
+ * (sp+10)  ip (word)
+ * (sp+8)   bp (word)
+ * (sp+4)   dll_id+ordinal (long)
+ * (sp)     entrypoint (long)
+ *
+ */
+static void BuildCall32Func( char *profile )
+{
+    int argsize = 0;
+    int short_ret = 0;
+    int reg_func = 0;
+    char *args = profile + 5;
+
+    /* Parse function type */
+
+    if (!strncmp( "word_", profile, 5 )) short_ret = 1;
+    else if (!strncmp( "regs_", profile, 5 )) reg_func = 1;
+    else if (strncmp( "long_", profile, 5 ))
     {
-	fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
+        fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
+        return;
     }
-    
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
+
+    /* Function header */
+
+    printf( "/**********\n" );
+    printf( " * " PREFIX "CallTo32_%s\n", profile );
+    printf( " **********/\n" );
+    printf( "\t.align 4\n" );
+    printf( "\t.global " PREFIX "CallTo32_%s\n\n", profile );
+    printf( PREFIX "CallTo32_%s:\n", profile );
+
+    /* Setup bp to point to its copy on the stack */
+
+    printf( "\tmovzwl %%sp,%%ebp\n" );
+    printf( "\taddw $8,%%bp\n" );
+
+    /* Save 16-bit ds */
+
+    printf( "\tpushw %%ds\n" );
+
+    /* Restore 32-bit ds */
+
+    printf( "\tpushw $0x%04x\n", WINE_DATA_SELECTOR );
+    printf( "\tpopw %%ds\n" );
+
+    /* Save the 16-bit stack */
+
+    printf( "\tpushw " PREFIX "IF1632_Saved16_bp\n" );
+    printf( "\tpushw " PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tpushw " PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tmovw %%ss," PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tmovw %%sp," PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tmovw %%bp," PREFIX "IF1632_Saved16_bp\n" );
+
+    /* Transfer the arguments */
+
+    if (reg_func) BuildContext();
+    else if (*args) argsize = TransferArgs16To32( args );
+
+    /* Get the address of the API function */
+
+    printf( "\tmovl -8(%%ebp),%%eax\n" );
+
+    /* Setup es */
+
+    printf( "\tpushw %%ds\n" );
+    printf( "\tpopw %%es\n" );
+
+    /* Switch to the 32-bit stack */
+
+    printf( "\tpushw %%ds\n" );
+    printf( "\tpopw %%ss\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_ebp,%%ebp\n" );
+    if (reg_func)
+        printf( "\tsubl $%d,%%esp\n", sizeof(struct sigcontext_struct) );
+    else if (*args)
+        printf( "\tsubl $%d,%%esp\n", 4 * strlen(args) );
+
+    /* Call the entry point */
+
+    if (debugging)
     {
-	if (odp->valid && 
-	    (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_PASCAL_16 ||
-	     odp->type == FUNCTYPE_REG))
-	{
-	    fdp = odp->additional_data;
-	    fprintf(fp, "extern int %s();\n", fdp->internal_name);
-	}
+        printf( "\tpushl %%eax\n" );
+        printf( "\tpushl $CALL32_Str_%s\n", profile );
+        printf( "\tcall " PREFIX "RELAY_DebugCall32\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
     }
-    /******* Michael Veksler 95-2-3 (pointers instead of fixed data) ****/
-    fprintf(fp,"unsigned short  %s_offsets[]={\n" , UpperDLLName);
-    prev_index=-1;  /* Index to previous #define (-1 if none) */
 
-    /* the difference between last #define and the current */
-    prev_n_args= 0;
-    
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
+    printf( "\tcall %%eax\n" );
+
+    if (debugging)
     {
-	fdp = odp->additional_data;
+        printf( "\tpushl %%eax\n" );
+        printf( "\tpushl $%d\n", short_ret );
+        printf( "\tcall " PREFIX "RELAY_DebugReturn\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+    }
 
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-            if (!odp->valid || fdp->n_args_16 <= 0) continue;
-            if (prev_index<0) 
-                fprintf(fp,"#\tdefine %s_ref_%d   0\n\t", UpperDLLName, i);
-            else
-                fprintf(fp,"#\tdefine %s_ref_%d   %s_ref_%d+%d\n\t",
-                        UpperDLLName,i, UpperDLLName,prev_index ,prev_n_args);
-            for (argnum = 0; argnum < fdp->n_args_16; argnum++)
-                fprintf(fp, "%d, ", fdp->arg_16_offsets[argnum]);
-            fprintf(fp,"\n");
-	    
-            prev_n_args=fdp->n_args_16;
-            prev_index=i;
+    if (reg_func)
+        printf( "\taddl $%d,%%esp\n", sizeof(struct sigcontext_struct) );
+    else if (*args)
+        printf( "\taddl $%d,%%esp\n", 4 * strlen(args) );
+
+    /* Restore the 16-bit stack */
+
+    printf( "\tmovw " PREFIX "IF1632_Saved16_ss,%%ss\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_sp,%%sp\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_bp,%%bp\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_bp\n" );
+
+    /* Restore registers from the context structure */
+
+    if (reg_func)
+    {
+        printf( "\tandl $0xffff,%%ebp\n" );
+        RestoreContext();
+    }
+    else  /* Store the return value in dx:ax if needed */
+    {
+        if (!short_ret)
+        {
+            printf( "\tpushl %%eax\n" );
+            printf( "\tpopw %%dx\n" );
+            printf( "\tpopw %%dx\n" );
         }
-    }    
-    fprintf(fp,"};\n");
+    }
 
+    /* Restore ds and bp */
 
-    fprintf(fp,"unsigned char  %s_types[]={\n" , UpperDLLName);
+    printf( "\tpopw %%ds\n" );
+    printf( "\tmovw %%bp,%%sp\n" );
+    printf( "\tpopw %%bp\n" );
 
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
+    /* Remove the arguments and return */
+
+    if (argsize)
     {
-	int argnum;
+        printf( "\t.byte 0x66\n" );
+        printf( "\tlret $%d\n", argsize );
+    }
+    else
+    {
+        printf( "\t.byte 0x66\n" );
+        printf( "\tlret\n" );
+    }
+}
 
-	fdp = odp->additional_data;
 
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-            if (!odp->valid || fdp->n_args_16 <= 0) continue;
-	    
-            fprintf(fp,"/* %s_%d */\n\t", UpperDLLName, i);
-	    
-            for (argnum = 0; argnum < fdp->n_args_16; argnum++)
-                fprintf(fp, "%d, ", fdp->arg_types_16[argnum]);
-            fprintf(fp,"\n");
+/*******************************************************************
+ *         BuildCall16Func
+ *
+ * Build a 16-bit callback function.
+ *
+ * Stack frame of the callback function:
+ *  ...      ...
+ * (ebp+22) arg2
+ * (ebp+18) arg1
+ * (ebp+14) 16-bit ds
+ * (ebp+10) func to call
+ * (ebp+8)  code selector
+ * (ebp+4)  return address
+ * (ebp)    previous ebp
+ *
+ * Prototypes for the CallTo16 functions:
+ *   extern WORD CallTo16_word_xxx( FARPROC func, WORD ds, args... );
+ *   extern LONG CallTo16_long_xxx( FARPROC func, WORD ds, args... );
+ *   extern void CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD ax,
+ *                               WORD bx, WORD cx, WORD dx, WORD si, WORD di );
+ */
+static void BuildCall16Func( char *profile )
+{
+    int short_ret = 0;
+    int reg_func = 0;
+    char *args = profile + 5;
+
+    if (!strncmp( "word_", profile, 5 )) short_ret = 1;
+    else if (!strncmp( "regs_", profile, 5 )) reg_func = short_ret = 1;
+    else if (strncmp( "long_", profile, 5 ))
+    {
+        fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
+        return;
+    }
+
+    /* Function header */
+
+    printf( "/**********\n" );
+    printf( " * " PREFIX "CallTo16_%s\n", profile );
+    printf( " **********/\n" );
+    printf( "\t.align 4\n" );
+    printf( "\t.global " PREFIX "CallTo16_%s\n\n", profile );
+    printf( PREFIX "CallTo16_%s:\n", profile );
+
+    /* Push code selector before return address to simulate a lcall */
+
+    printf( "\tpopl %%eax\n" );
+    printf( "\tpushw $0x%04x\n", WINE_CODE_SELECTOR );
+    printf( "\tpushl %%eax\n" );
+
+    /* Entry code */
+
+    printf( "\tpushl %%ebp\n" );
+    printf( "\tmovl %%esp,%%ebp\n" );
+
+    /* Save the 32-bit registers */
+
+    printf( "\tpushl %%ebx\n" );
+    printf( "\tpushl %%ecx\n" );
+    printf( "\tpushl %%edx\n" );
+    printf( "\tpushl %%esi\n" );
+    printf( "\tpushl %%edi\n" );
+
+    /* Save the 32-bit stack */
+
+    printf( "\tpushl " PREFIX "IF1632_Saved32_esp\n" );
+    printf( "\tpushl " PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tmovl %%esp," PREFIX "IF1632_Saved32_esp\n" );
+    printf( "\tmovl %%ebp," PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tmovl %%ebp,%%ebx\n" );
+
+    /* Print debugging info */
+
+    if (debugging)
+    {
+        /* Push the address of the first argument */
+        printf( "\tmovl %%ebx,%%eax\n" );
+        printf( "\taddl $10,%%eax\n" );
+        printf( "\tpushl $%d\n", reg_func ? 7 : strlen(args) );
+        printf( "\tpushl %%eax\n" );
+        printf( "\tcall " PREFIX "RELAY_DebugCall16\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+    }
+
+    /* Switch to the 16-bit stack */
+
+    printf( "\tmovw " PREFIX "IF1632_Saved16_ss,%%ss\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_sp,%%sp\n" );
+    printf( "\tmovzwl " PREFIX "IF1632_Saved16_bp,%%ebp\n" );
+
+    /* Transfer the arguments */
+
+    if (reg_func)
+    {
+        /* Get the registers. ebx is handled later on. */
+        printf( "\tmovl 18(%%ebx),%%es\n" );
+        printf( "\tmovl 22(%%ebx),%%eax\n" );
+        printf( "\tmovl 30(%%ebx),%%ecx\n" );
+        printf( "\tmovl 34(%%ebx),%%edx\n" );
+        printf( "\tmovl 38(%%ebx),%%esi\n" );
+        printf( "\tmovl 42(%%ebx),%%edi\n" );
+    }
+    else  /* not a register function */
+    {
+        int pos = 18;  /* first argument position */
+        while (*args)
+        {
+            switch(*args++)
+            {
+            case 'w': /* word */
+                printf( "\tpushw %d(%%ebx)\n", pos );
+                break;
+            case 'l': /* long */
+                printf( "\tpushl %d(%%ebx)\n", pos );
+                break;
+            }
+            pos += 4;
         }
-    }    
-    fprintf(fp,"};\n");
+    }
 
+    /* Push the return address */
 
-    /**************************************************/
-    fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
-	    UpperDLLName, Limit + 1);
-    fprintf(fp, "{\n");
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
+    printf( "\tpushl " PREFIX "CALL16_RetAddr_%s\n",
+            short_ret ? "word" : "long" );
+
+    /* Push the called routine address */
+
+    printf( "\tpushl 10(%%ebx)\n" );
+
+    /* Get the 16-bit ds */
+    /* FIXME: this shouldn't be necessary if function prologs fixup worked. */
+
+    printf( "\tmovw 14(%%ebx),%%ds\n" );
+
+    if (reg_func)
     {
-	fdp = odp->additional_data;
+        /* Retrieve ebx from the 32-bit stack */
+        printf( "\tmovl %%fs:26(%%ebx),%%ebx\n" );
+    }
+    else
+    {
+        /* Set ax equal to ds for window procedures */
+        printf( "\tmovw %%ds,%%ax\n" );
+    }
 
-	if (!odp->valid)
-	    odp->type = -1;
-	
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, ", fdp->internal_name);
-	    fprintf(fp, "%d, ", fdp->n_args_16);
-	    if (fdp->n_args_16 > 0)
-	       fprintf(fp,"%s_ref_%d", UpperDLLName, i);
-	    else
-	       fprintf(fp,"      0    ");
-	       
-#ifdef WINESTAT
-	    fprintf(fp, ",0 ");
-#endif	    
-	    fprintf(fp, "}, \n");
-	    break;
-		
-	  default:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
-		    UTEXTSEL, UpperDLLName, i);
-	    break;
-	}
+    /* Jump to the called routine */
+
+    printf( "\t.byte 0x66\n" );
+    printf( "\tlret\n" );
+}
+
+
+/*******************************************************************
+ *         BuildRet16Func
+ *
+ * Build the return code for 16-bit callbacks
+ */
+static void BuildRet16Func()
+{
+    printf( "\t.globl " PREFIX "CALL16_Ret_word\n" );
+    printf( "\t.globl " PREFIX "CALL16_Ret_long\n" );
+
+    /* Put return value into eax */
+
+    printf( PREFIX "CALL16_Ret_long:\n" );
+    printf( "\tpushw %%dx\n" );
+    printf( "\tpushw %%ax\n" );
+    printf( "\tpopl %%eax\n" );
+    printf( PREFIX "CALL16_Ret_word:\n" );
+
+    /* Restore 32-bit segment registers */
+
+    printf( "\tmovw $0x%04x,%%bx\n", WINE_DATA_SELECTOR );
+    printf( "\tmovw %%bx,%%ds\n" );
+    printf( "\tmovw %%bx,%%es\n" );
+    printf( "\tmovw %%bx,%%ss\n" );
+
+    /* Restore the 32-bit stack */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_ebp,%%ebp\n" );
+    printf( "\tpopl " PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tpopl " PREFIX "IF1632_Saved32_esp\n" );
+
+    /* Restore the 32-bit registers */
+
+    printf( "\tpopl %%edi\n" );
+    printf( "\tpopl %%esi\n" );
+    printf( "\tpopl %%edx\n" );
+    printf( "\tpopl %%ecx\n" );
+    printf( "\tpopl %%ebx\n" );
+
+    /* Return to caller */
+
+    printf( "\tmovl %%ebp,%%esp\n" );
+    printf( "\tpopl %%ebp\n" );
+    printf( "\tlret\n" );
+
+    /* Declare the return address variables */
+
+    printf( "\t.data\n" );
+    printf( "\t.globl " PREFIX "CALL16_RetAddr_word\n" );
+    printf( "\t.globl " PREFIX "CALL16_RetAddr_long\n" );
+    printf( PREFIX "CALL16_RetAddr_word:\t.long 0\n" );
+    printf( PREFIX "CALL16_RetAddr_long:\t.long 0\n" );
+    printf( "\t.text\n" );
+}
+
+
+static void usage(void)
+{
+    fprintf(stderr, "usage: build -spec SPECNAMES\n"
+                    "       build -call32 FUNCTION_PROFILES\n"
+                    "       build -call16 FUNCTION_PROFILES\n" );
+    exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+    int i;
+
+    if (argc <= 2) usage();
+
+    if (!strcmp( argv[1], "-spec" ))
+    {
+        for (i = 2; i < argc; i++) BuildSpecFiles( argv[i] );
     }
-    fprintf(fp, "};\n");
+    else if (!strcmp( argv[1], "-call32" ))  /* 32-bit callbacks */
+    {
+        /* File header */
+
+        printf( "/* File generated automatically. Do no edit! */\n\n" );
+        printf( "\t.text\n" );
+
+        /* Build the callback functions */
+
+        for (i = 2; i < argc; i++) BuildCall32Func( argv[i] );
+
+        /* Output the argument debugging strings */
+
+        if (debugging)
+        {
+            printf( "/* Argument strings */\n" );
+            for (i = 2; i < argc; i++)
+            {
+                printf( "CALL32_Str_%s:\n", argv[i] );
+                printf( "\t.ascii \"%s\\0\"\n", argv[i] + 5 );
+            }
+        }
+    }
+    else if (!strcmp( argv[1], "-call16" ))  /* 16-bit callbacks */
+    {
+        /* File header */
+
+        printf( "/* File generated automatically. Do no edit! */\n\n" );
+        printf( "\t.text\n" );
+        printf( "\t.globl " PREFIX "CALL16_Start\n" );
+        printf( PREFIX "CALL16_Start:\n" );
+
+        /* Build the callback functions */
+
+        for (i = 2; i < argc; i++) BuildCall16Func( argv[i] );
+
+        /* Output the 16-bit return code */
+
+        BuildRet16Func();
+
+        printf( "\t.globl " PREFIX "CALL16_End\n" );
+        printf( PREFIX "CALL16_End:\n" );
+    }
+    else usage();
 
-    fclose(fp);
     return 0;
 }
-
diff --git a/tools/newbuild.c b/tools/newbuild.c
deleted file mode 100644
index f9f8e42cf54f16979685f2983535ba74c5c67094..0000000000000000000000000000000000000000
--- a/tools/newbuild.c
+++ /dev/null
@@ -1,958 +0,0 @@
-static char RCSId[] = "$Id: build.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef linux
-#ifdef __ELF__
-#define UTEXTSEL 	0x0f
-#else
-#define UTEXTSEL 	0x23
-#endif
-#define UDATASEL	0x2b
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UTEXTSEL 	0x1f
-#define UDATASEL	0x27
-#endif
-
-#define VARTYPE_BYTE	0
-#define VARTYPE_SIGNEDWORD	0
-#define VARTYPE_WORD	1
-#define VARTYPE_LONG	2
-#define VARTYPE_FARPTR	3
-
-#define FUNCTYPE_PASCAL	16
-#define FUNCTYPE_C	17
-#define FUNCTYPE_REG	19
-
-#define EQUATETYPE_ABS	18
-#define TYPE_RETURN	20
-
-#define MAX_ORDINALS	1024
-
-typedef struct ordinal_definition_s
-{
-    int valid;
-    int type;
-    char export_name[80];
-    void *additional_data;
-} ORDDEF;
-
-typedef struct ordinal_variable_definition_s
-{
-    int n_values;
-    int *values;
-} ORDVARDEF;
-
-typedef struct ordinal_function_definition_s
-{
-    int n_args_16;
-    int arg_types_16[16];
-    int arg_16_offsets[16];
-    int arg_16_size;
-    char internal_name[80];
-    int n_args_32;
-    int arg_indices_32[16];
-} ORDFUNCDEF;
-
-typedef struct ordinal_return_definition_s
-{
-    int arg_size;
-    int ret_value;
-} ORDRETDEF;
-
-ORDDEF OrdinalDefinitions[MAX_ORDINALS];
-
-char LowerDLLName[80];
-char UpperDLLName[80];
-int Limit;
-int DLLId;
-FILE *SpecFp;
-
-char *ParseBuffer = NULL;
-char *ParseNext;
-char ParseSaveChar;
-int Line;
-
-int IsNumberString(char *s)
-{
-    while (*s != '\0')
-	if (!isdigit(*s++))
-	    return 0;
-
-    return 1;
-}
-
-char *strlower(char *s)
-{
-    char *p;
-    
-    for(p = s; *p != '\0'; p++)
-	*p = tolower(*p);
-
-    return s;
-}
-
-char *strupper(char *s)
-{
-    char *p;
-    
-    for(p = s; *p != '\0'; p++)
-	*p = toupper(*p);
-
-    return s;
-}
-
-int stricmp(char *s1, char *s2)
-{
-    if (strlen(s1) != strlen(s2))
-	return -1;
-    
-    while (*s1 != '\0')
-	if (*s1++ != *s2++)
-	    return -1;
-    
-    return 0;
-}
-
-char *
-GetTokenInLine(void)
-{
-    char *p;
-    char *token;
-
-    if (ParseNext != ParseBuffer)
-    {
-	if (ParseSaveChar == '\0')
-	    return NULL;
-	*ParseNext = ParseSaveChar;
-    }
-    
-    /*
-     * Remove initial white space.
-     */
-    for (p = ParseNext; isspace(*p); p++)
-	;
-    
-    if (*p == '\0')
-	return NULL;
-    
-    /*
-     * Find end of token.
-     */
-    token = p++;
-    if (*token != '(' && *token != ')')
-	while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
-	    p++;
-    
-    ParseSaveChar = *p;
-    ParseNext = p;
-    *p = '\0';
-
-    return token;
-}
-
-char *
-GetToken(void)
-{
-    char *token;
-
-    if (ParseBuffer == NULL)
-    {
-	ParseBuffer = malloc(512);
-	ParseNext = ParseBuffer;
-	Line++;
-	while (1)
-	{
-	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
-		return NULL;
-	    if (ParseBuffer[0] != '#')
-		break;
-	}
-    }
-
-    while ((token = GetTokenInLine()) == NULL)
-    {
-	ParseNext = ParseBuffer;
-	Line++;
-	while (1)
-	{
-	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
-		return NULL;
-	    if (ParseBuffer[0] != '#')
-		break;
-	}
-    }
-
-    return token;
-}
-
-int
-ParseVariable(int ordinal, int type)
-{
-    ORDDEF *odp;
-    ORDVARDEF *vdp;
-    char export_name[80];
-    char *token;
-    char *endptr;
-    int *value_array;
-    int n_values;
-    int value_array_size;
-    
-    strcpy(export_name, GetToken());
-
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-
-    n_values = 0;
-    value_array_size = 25;
-    value_array = malloc(sizeof(*value_array) * value_array_size);
-    
-    while ((token = GetToken()) != NULL)
-    {
-	if (*token == ')')
-	    break;
-
-	value_array[n_values++] = strtol(token, &endptr, 0);
-	if (n_values == value_array_size)
-	{
-	    value_array_size += 25;
-	    value_array = realloc(value_array, 
-				  sizeof(*value_array) * value_array_size);
-	}
-	
-	if (endptr == NULL || *endptr != '\0')
-	{
-	    fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		    token);
-	    exit(1);
-	}
-    }
-    
-    if (token == NULL)
-    {
-	fprintf(stderr, "%d: End of file in variable declaration\n", Line);
-	exit(1);
-    }
-
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    odp->valid = 1;
-    odp->type = type;
-    strcpy(odp->export_name, export_name);
-    
-    vdp = malloc(sizeof(*vdp));
-    odp->additional_data = vdp;
-    
-    vdp->n_values = n_values;
-    vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
-
-    return 0;
-}
-
-int
-ParseExportFunction(int ordinal, int type)
-{
-    char *token;
-    ORDDEF *odp;
-    ORDFUNCDEF *fdp;
-    int arg_types[16];
-    int i;
-    int arg_num;
-    int current_offset;
-    int arg_size;
-	
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
-    odp->type = type;
-    fdp = malloc(sizeof(*fdp));
-    odp->additional_data = fdp;
-
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-
-    fdp->arg_16_size = 0;
-    for (i = 0; i < 16; i++)
-    {
-	token = GetToken();
-	if (*token == ')')
-	    break;
-
-	if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_WORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "s_byte") == 0 || 
-		 stricmp(token, "s_word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_LONG;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else if (stricmp(token, "ptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_FARPTR;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else
-	{
-	    fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
-	    exit(1);
-	}
-    }
-    fdp->n_args_16 = i;
-
-    if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
-    {
-	current_offset = 0;
-	for (i--; i >= 0; i--)
-	{
-	    arg_size = fdp->arg_16_offsets[i];
-	    fdp->arg_16_offsets[i] = current_offset;
-	    current_offset += arg_size;
-	}
-    }
-    else
-    {
-	current_offset = 0;
-	for (i = 0; i < fdp->n_args_16; i++)
-	{
-	    arg_size = fdp->arg_16_offsets[i];
-	    fdp->arg_16_offsets[i] = current_offset;
-	    current_offset += arg_size;
-	}
-    }
-
-    strcpy(fdp->internal_name, GetToken());
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-    for (i = 0; i < 16; i++)
-    {
-	token = GetToken();
-	if (*token == ')')
-	    break;
-
-	fdp->arg_indices_32[i] = atoi(token);
-	if (fdp->arg_indices_32[i] < 1 || 
-	    fdp->arg_indices_32[i] > fdp->n_args_16)
-	{
-	    fprintf(stderr, "%d: Bad argument index %d\n", Line,
-		    fdp->arg_indices_32[i]);
-	    exit(1);
-	}
-    }
-    fdp->n_args_32 = i;
-
-    return 0;
-}
-
-int
-ParseEquate(int ordinal)
-{
-    ORDDEF *odp;
-    char *token;
-    char *endptr;
-    int value;
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-
-    token = GetToken();
-    value = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    odp->valid = 1;
-    odp->type = EQUATETYPE_ABS;
-    odp->additional_data = (void *) value;
-
-    return 0;
-}
-
-int
-ParseReturn(int ordinal)
-{
-    ORDDEF *odp;
-    ORDRETDEF *rdp;
-    char *token;
-    char *endptr;
-    int value;
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-
-    rdp = malloc(sizeof(*rdp));
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
-    odp->type = TYPE_RETURN;
-    odp->additional_data = rdp;
-
-    token = GetToken();
-    rdp->arg_size = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    token = GetToken();
-    rdp->ret_value = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    return 0;
-}
-
-int
-ParseOrdinal(int ordinal)
-{
-    char *token;
-    
-    token = GetToken();
-    if (token == NULL)
-    {
-	fprintf(stderr, "%d: Expected type after ordinal\n", Line);
-	exit(1);
-    }
-
-    if (stricmp(token, "byte") == 0)
-	return ParseVariable(ordinal, VARTYPE_BYTE);
-    else if (stricmp(token, "word") == 0)
-	return ParseVariable(ordinal, VARTYPE_WORD);
-    else if (stricmp(token, "long") == 0)
-	return ParseVariable(ordinal, VARTYPE_LONG);
-    else if (stricmp(token, "c") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_C);
-    else if (stricmp(token, "p") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "register") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_REG);
-    else if (stricmp(token, "equate") == 0)
-	return ParseEquate(ordinal);
-    else if (stricmp(token, "return") == 0)
-	return ParseReturn(ordinal);
-    else
-    {
-	fprintf(stderr, 
-		"%d: Expected type after ordinal, found '%s' instead\n",
-		Line, token);
-	exit(1);
-    }
-}
-
-int
-ParseTopLevel(void)
-{
-    char *token;
-    
-    while ((token = GetToken()) != NULL)
-    {
-	if (stricmp(token, "name") == 0)
-	{
-	    strcpy(LowerDLLName, GetToken());
-	    strlower(LowerDLLName);
-
-	    strcpy(UpperDLLName, LowerDLLName);
-	    strupper(UpperDLLName);
-	}
-	else if (stricmp(token, "id") == 0)
-	{
-	    token = GetToken();
-	    if (!IsNumberString(token))
-	    {
-		fprintf(stderr, "%d: Expected number after id\n", Line);
-		exit(1);
-	    }
-	    
-	    DLLId = atoi(token);
-	}
-	else if (stricmp(token, "length") == 0)
-	{
-	    token = GetToken();
-	    if (!IsNumberString(token))
-	    {
-		fprintf(stderr, "%d: Expected number after length\n", Line);
-		exit(1);
-	    }
-
-	    Limit = atoi(token);
-	}
-	else if (IsNumberString(token))
-	{
-	    int ordinal;
-	    int rv;
-	    
-	    ordinal = atoi(token);
-	    if ((rv = ParseOrdinal(ordinal)) < 0)
-		return rv;
-	}
-	else
-	{
-	    fprintf(stderr, 
-		    "%d: Expected name, id, length or ordinal\n", Line);
-	    exit(1);
-	}
-    }
-
-    return 0;
-}
-
-void
-OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
-{
-    ORDVARDEF *vdp;
-    int i;
-
-    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-
-    vdp = odp->additional_data;
-    for (i = 0; i < vdp->n_values; i++)
-    {
-	if ((i & 7) == 0)
-	    fprintf(fp, "\t%s\t", storage);
-	    
-	fprintf(fp, "%d", vdp->values[i]);
-	
-	if ((i & 7) == 7 || i == vdp->n_values - 1)
-	    fprintf(fp, "\n");
-	else
-	    fprintf(fp, ", ");
-    }
-    fprintf(fp, "\n");
-}
-
-main(int argc, char **argv)
-{
-    ORDDEF *odp;
-    ORDFUNCDEF *fdp;
-    ORDRETDEF *rdp;
-    FILE *fp;
-    char filename[80];
-    char buffer[80];
-    char *p;
-    int i;
-    
-    if (argc < 2)
-    {
-	fprintf(stderr, "usage: build SPECNAME\n");
-	exit(1);
-    }
-
-    SpecFp = fopen(argv[1], "r");
-    if (SpecFp == NULL)
-    {
-	fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
-	exit(1);
-    }
-
-    ParseTopLevel();
-
-    /**********************************************************************
-     *					DLL ENTRY POINTS
-     */
-    sprintf(filename, "dll_%s.S", LowerDLLName);
-    fp = fopen(filename, "w");
-
-    fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
-    fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
-    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-    fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
-    fprintf(fp, "\tjmp\t_CallTo32\n\n");
-
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
-
-	if (!odp->valid)
-	{
-	    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-	    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-	    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-	    fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-	    fprintf(fp, "\tpushw\t$0\n");
-	    fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
-	}
-	else
-	{
-	    fdp = odp->additional_data;
-	    rdp = odp->additional_data;
-	    
-	    switch (odp->type)
-	    {
-	      case EQUATETYPE_ABS:
-		fprintf(fp, "_%s_Ordinal_%d = %d\n\n", 
-			UpperDLLName, i, (int) odp->additional_data);
-		break;
-
-	      case VARTYPE_BYTE:
-		OutputVariableCode(fp, ".byte", odp);
-		break;
-
-	      case VARTYPE_WORD:
-		OutputVariableCode(fp, ".word", odp);
-		break;
-
-	      case VARTYPE_LONG:
-		OutputVariableCode(fp, ".long", odp);
-		break;
-
-	      case TYPE_RETURN:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
-		fprintf(fp, "\tmovw\t$%d,%%dx\n", 
-			(rdp->ret_value >> 16) & 0xffff);
-		fprintf(fp, "\t.byte\t0x66\n");
-		if (rdp->arg_size != 0)
-		    fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
-		else
-		    fprintf(fp, "\tlret\n");
-		break;
-
-	      case FUNCTYPE_REG:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-		fprintf(fp, "\tpushl\t$0\n");			/* cr2     */
-		fprintf(fp, "\tpushl\t$0\n");			/* oldmask */
-		fprintf(fp, "\tpushl\t$0\n");			/* i387    */
-		fprintf(fp, "\tpushw\t$0\n");			/* __ssh   */
-		fprintf(fp, "\tpushw\t%%ss\n");			/* ss      */
-		fprintf(fp, "\tpushl\t%%esp\n");		/* esp     */
-		fprintf(fp, "\tpushfl\n");			/* eflags  */
-		fprintf(fp, "\tpushw\t$0\n");			/* __csh   */
-		fprintf(fp, "\tpushw\t%%cs\n");			/* cs      */
-		fprintf(fp, "\tpushl\t$0\n");			/* eip     */
-		fprintf(fp, "\tpushl\t$0\n");			/* err     */
-		fprintf(fp, "\tpushl\t$0\n");			/* trapno  */
-		fprintf(fp, "\tpushal\n");			/* AX, ... */
-		fprintf(fp, "\tpushw\t$0\n");			/* __dsh   */
-		fprintf(fp, "\tpushw\t%%ds\n");			/* ds      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __esh   */
-		fprintf(fp, "\tpushw\t%%es\n");			/* es      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __fsh   */
-		fprintf(fp, "\tpushw\t%%fs\n");			/* fs      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __gsh   */
-		fprintf(fp, "\tpushw\t%%gs\n");			/* gs      */
-		fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
-		fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
-		fprintf(fp, "\tpushl\t88(%%ebp)\n");
-		fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$92\n");
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-
-	      case FUNCTYPE_PASCAL:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-		
-	      case FUNCTYPE_C:
-	      default:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$0\n");
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-	    }
-	}
-    }
-
-    fclose(fp);
-
-    /**********************************************************************
-     *					RELAY CODE
-     */
-    sprintf(filename, "rly_%s.S", LowerDLLName);
-    fp = fopen(filename, "w");
-
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	if (!odp->valid)
-	    continue;
-
-	fdp = odp->additional_data;
-	
-	fprintf(fp, "\t.globl _%s_Relay_%d\n", UpperDLLName, i);
-	fprintf(fp, "_%s_Relay_%d:\n", UpperDLLName, i);
-	fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-	fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-
-	fprintf(fp, "\tpushl\t%%ebp\n");
-	fprintf(fp, "\tmovl\t%%esp,%%ebp\n");
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	fprintf(fp, "\tpushw\t%%ds\n");
-	fprintf(fp, "\tpushw\t%%es\n");
-
-	/*
-	 * Restore segment registers.
-	 */
-	fprintf(fp, "\tmovw\t%d,%%ax\n", UDATASEL);
-	fprintf(fp, "\tmovw\t%%ax,%%ds\n");
-	fprintf(fp, "\tmovw\t%%ax,%%es\n");
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	fprintf(fp, "\tpushl\t_IF1632_Saved16_esp\n");
-	fprintf(fp, "\tpushl\t_IF1632_Saved16_ebp\n");
-	fprintf(fp, "\tpushw\t_IF1632_Saved16_ss\n");
-
-	fprintf(fp, "\tmovw\t%%ss,_IF1632_Saved16_ss\n");
-	fprintf(fp, "\tmovl\t%%esp,_IF1632_Saved16_esp\n");
-	fprintf(fp, "\tmovl\t%%ebp,_IF1632_Saved16_ebp\n");
-
-	fprintf(fp, "\tmovw\t%%ss,%%ax\n");
-	fprintf(fp, "\tshll\t16,%%eax\n");
-	fprintf(fp, "\torl\t%%esp,%%eax\n");
-
-	fprintf(fp, "\tmovw\t_IF1632_Saved32_ss,%%ss\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved32_esp,%%esp\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved32_ebp,%%ebp\n");
-
-	fprintf(fp, "\tpushl\t_Stack16Frame\n");
-	fprintf(fp, "\tmovl\t%%eax,_Stack16Frame\n");
-
-	/*
-	 * Move arguments.
-	 */
-	
-
-	/*
-	 * Call entry point
-	 */
-	fprintf(fp, "\tcall\t%s\n", fdp->internal_name);
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	fprintf(fp, "\tmovw\t_IF1632_Saved16_ss,%%ss\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved16_esp,%%esp\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved16_ebp,%%ebp\n");
-
-	fprintf(fp, "\tpopw\t_IF1632_Saved16_ss\n");
-	fprintf(fp, "\tpopl\t_IF1632_Saved16_ebp\n");
-	fprintf(fp, "\tpopl\t_IF1632_Saved16_esp\n");
-
-	fprintf(fp, "\tpopw\t%%es\n");
-	fprintf(fp, "\tpopw\t%%ds\n");
-
-	fprintf(fp, "\t.align\t2,0x90\n");
-	fprintf(fp, "\tleave\n");
-	
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	fprintf(fp, "\tpopw\t%%gs:nbytes\n");
-	fprintf(fp, "\tcmpw\t$0,%%gs:nbytes\n");
-	fprintf(fp, "\tje\tnoargs\n");
-	fprintf(fp, "\tpopw\t%%gs:offset\n");
-	fprintf(fp, "\tpopw\t%%gs:selector\n");
-	fprintf(fp, "\taddw\t%%gs:nbytes,%%esp\n");
-	fprintf(fp, "\tpushw\t%%gs:selector\n");
-	fprintf(fp, "\tpushw\t%%gs:offset\n");
-	fprintf(fp, "noargs:\n");
-
-	/*
-	 * Last, but not least we need to move the high word from eax to dx
-	 */
-	fprintf(fp, "\t	pushl\t%%eax\n");
-	fprintf(fp, "\tpopw\t%%dx\n");
-	fprintf(fp, "\tpopw\t%%dx\n");
-
-	fprintf(fp, "\t.byte\t0x66\n");
-	fprintf(fp, "\tlret\n");
-
-    }
-
-    fclose(fp);
-
-    /**********************************************************************
-     *					DLL ENTRY TABLE
-     */
-#ifndef SHORTNAMES
-    sprintf(filename, "dll_%s_tab.c", LowerDLLName);
-#else
-    sprintf(filename, "dtb_%s.c", LowerDLLName);
-#endif
-    fp = fopen(filename, "w");
-
-    fprintf(fp, "#include <stdio.h>\n");
-    fprintf(fp, "#include <stdlib.h>\n");
-    fprintf(fp, "#include \042dlls.h\042\n\n");
-
-    for (i = 0; i <= Limit; i++)
-    {
-	fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
-    }
-    
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	if (odp->valid && 
-	    (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
-	     odp->type == FUNCTYPE_REG))
-	{
-	    fdp = odp->additional_data;
-	    fprintf(fp, "extern int %s();\n", fdp->internal_name);
-	}
-    }
-    
-    fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
-	    UpperDLLName, Limit + 1);
-    fprintf(fp, "{\n");
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	fdp = odp->additional_data;
-
-	if (!odp->valid)
-	    odp->type = -1;
-	
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_REG:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
-#ifdef WINESTAT
-	    fprintf(fp, "0, ");
-#endif	    
-	    fprintf(fp, "%d, ", fdp->n_args_32);
-	    if (fdp->n_args_32 > 0)
-	    {
-		int argnum;
-		
-		fprintf(fp, "\n      {\n");
-		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
-		{
-		    fprintf(fp, "        { %d, %d },\n",
-			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
-			    fdp->arg_types_16[argnum]);
-		}
-		fprintf(fp, "      }\n    ");
-	    }
-	    fprintf(fp, "}, \n");
-	    break;
-		
-	  case FUNCTYPE_C:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
-#ifdef WINESTAT
-	    fprintf(fp, "0, ");
-#endif	    
-	    fprintf(fp, "%d, ", fdp->n_args_32);
-	    if (fdp->n_args_32 > 0)
-	    {
-		int argnum;
-		
-		fprintf(fp, "\n      {\n");
-		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
-		{
-		    fprintf(fp, "        { %d, %d },\n",
-			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
-			    fdp->arg_types_16[argnum]);
-		}
-		fprintf(fp, "      }\n    ");
-	    }
-	    fprintf(fp, "}, \n");
-	    break;
-	    
-	  default:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
-		    UTEXTSEL, UpperDLLName, i);
-	    break;
-	}
-    }
-    fprintf(fp, "};\n");
-
-    fclose(fp);
-}
-
diff --git a/windows/caret.c b/windows/caret.c
index 5c31d192afd8c65f2daecd7500c08ae94683c446..8f329902cfe232c5e65e7b113e964298e21c630b 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -7,6 +7,7 @@ static char Copyright[] = "Copyright  David Metcalfe, 1993";
 */
 
 #include "windows.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_CARET */
 #include "debug.h"
@@ -30,15 +31,13 @@ typedef struct
 static CARET Caret;
 static BOOL LockCaret;
 
-static WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime);
 static void CARET_HideCaret();
 
 
 /*****************************************************************
  *               CARET_Callback
  */
-
-static WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime)
+WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime)
 {
     HDC hdc;
     HBRUSH hBrush;
@@ -134,7 +133,8 @@ void CreateCaret(HWND hwnd, HBITMAP bitmap, short width, short height)
     Caret.timeout = 750;
     LockCaret = FALSE;
 
-    Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout, (FARPROC)CARET_Callback);
+    Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
+                                (FARPROC)GetWndProcEntry16("CARET_Callback"));
 
     dprintf_caret(stddeb,"CreateCaret: hwnd=%d, timerid=%d\n", 
 		  hwnd, Caret.timerid);
@@ -222,7 +222,8 @@ void SetCaretBlinkTime(WORD msecs)
 
     KillSystemTimer( (HWND)0, Caret.timerid);
     Caret.timeout = msecs;
-    Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout, (FARPROC)CARET_Callback);
+    Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
+                                 (FARPROC)GetWndProcEntry16("CARET_Callback"));
 }
 
 
diff --git a/windows/cursor.c b/windows/cursor.c
index 369506d471dc6cdaf7a65fc7788c4b012cbbf3ed..fb13b6d376126be63d8180ded20e66b71cc186f3 100644
--- a/windows/cursor.c
+++ b/windows/cursor.c
@@ -23,6 +23,7 @@ static char Copyright[] = "Copyright  Martin Ayotte, 1993";
 /* #define DEBUG_CURSOR   */
 /* #define DEBUG_RESOURCE */
 #include "debug.h"
+#include "arch.h"
 
 static int ShowCursCount = 0;
 static HCURSOR hActiveCursor;
@@ -52,16 +53,15 @@ static struct { SEGPTR name; HCURSOR cursor; } system_cursor[] =
  */
 HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 {
-    XColor	bkcolor;
-    XColor	fgcolor;
     HCURSOR 	hCursor;
     HANDLE 	rsc_mem;
     WORD 	*lp;
+    LONG        *lpl,size;
     CURSORDESCRIP *lpcurdesc;
     CURSORALLOC	  *lpcur;
     HDC 	hdc;
-    int i, j, image_size;
-
+    int i, image_size;
+    unsigned char *cp1,*cp2;
     dprintf_resource(stddeb,"LoadCursor: instance = %04x, name = %08lx\n",
 	   instance, cursor_name);
     if (!instance)
@@ -117,27 +117,29 @@ HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 	    }
 	}
 
-#if 1
+#if 0
+    /* this code replaces all bitmap cursors with the default cursor */
     lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
     GlobalUnlock(hCursor);
     return hCursor;
 #endif
 
-    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    if (!(hdc = GetDC(0))) return 0;
     rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
 			       &image_size);
     if (rsc_mem == (HANDLE)NULL) {
     fprintf(stderr,"LoadCursor / Cursor %08lx not Found !\n", cursor_name);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
     lp = (WORD *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
     lpcurdesc = (CURSORDESCRIP *)(lp + 3);
+#if 0
     dprintf_cursor(stddeb,"LoadCursor / image_size=%d\n", image_size);
     dprintf_cursor(stddeb,"LoadCursor / curReserved=%X\n", *lp);
     dprintf_cursor(stddeb,"LoadCursor / curResourceType=%X\n", *(lp + 1));
@@ -154,6 +156,7 @@ HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 		(DWORD)lpcurdesc->curDIBSize);
     dprintf_cursor(stddeb,"LoadCursor / cursor curDIBOffset=%lX\n", 
 		(DWORD)lpcurdesc->curDIBOffset);
+#endif
     lpcur->descriptor = *lpcurdesc;
     GlobalUnlock(rsc_mem);
     GlobalFree(rsc_mem);
@@ -163,63 +166,64 @@ HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
     if (rsc_mem == (HANDLE)NULL) {
     	fprintf(stderr,
 		"LoadCursor / Cursor %08lx Bitmap not Found !\n", cursor_name);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
-    lp = (WORD *)GlobalLock(rsc_mem);
+    lpl = (LONG *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
- 	}
-	lp++;
-    for (j = 0; j < 16; j++)
-        dprintf_cursor(stddeb,"%04X ", *(lp + j));
-/*
-    if (*lp == sizeof(BITMAPINFOHEADER))
-	lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
-    else
-*/
-        lpcur->hBitmap = 0;
-/*     lp += sizeof(BITMAP); */
-    for (i = 0; i < 81; i++) {
-	char temp = *((char *)lp + 162 + i);
-	*((char *)lp + 162 + i) = *((char *)lp + 324 - i);
-	*((char *)lp + 324 - i) = temp;
-	}
-    lpcur->pixshape = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        ((char *)lp + 211), 32, 32,
-/*
-        lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
-*/
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    lpcur->pixmask = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        ((char *)lp + 211), 32, 32,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    memset(&bkcolor, 0, sizeof(XColor));
-    memset(&fgcolor, 0, sizeof(XColor));
-    bkcolor.pixel = WhitePixel(display, DefaultScreen(display)); 
-    fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
-    dprintf_cursor(stddeb,"LoadCursor / before XCreatePixmapCursor !\n");
-    lpcur->xcursor = XCreatePixmapCursor(display,
- 	lpcur->pixshape, lpcur->pixmask, 
- 	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
- 	lpcur->descriptor.curYHotspot);
+    }
+    lpl++;
+    size = CONV_LONG (*lpl);
+    if (size == sizeof(BITMAPCOREHEADER)){
+	CONV_BITMAPCOREHEADER (lpl);
+        ((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
+	lpcur->hBitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lpl );
+    } else if (size == sizeof(BITMAPINFOHEADER)){
+	CONV_BITMAPINFO (lpl);
+        ((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
+	lpcur->hBitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lpl );
+    } else  {
+      fprintf(stderr,"No bitmap for cursor?\n");
+      lpcur->hBitmap = 0;
+    }
+    lpl = (char *)lpl + size + 8;
+  /* This is rather strange! The data is stored *BACKWARDS* and       */
+  /* mirrored! But why?? FIXME: the image must be flipped at the Y    */
+  /* axis, either here or in CreateCusor(); */
+    size = lpcur->descriptor.Height/2 * ((lpcur->descriptor.Width+7)/8);
+#if 0
+    dprintf_cursor(stddeb,"Before:\n");
+    for(i=0;i<2*size;i++)  {
+      dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
+      if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
+    }
+#endif
+    cp1 = (char *)lpl;
+    cp2 = cp1+2*size;
+    for(i = 0; i < size; i++)  {
+      char tmp=*--cp2;
+      *cp2 = *cp1;
+      *cp1++ = tmp;
+    }
+#if 0
+    dprintf_cursor(stddeb,"After:\n");
+    for(i=0;i<2*size;i++)  {
+      dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
+      if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
+    }
+#endif
+    hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
+ 	lpcur->descriptor.curYHotspot, lpcur->descriptor.Width,
+	lpcur->descriptor.Height/2,
+	(LPSTR)lpl, ((LPSTR)lpl)+size);
+
     GlobalUnlock(rsc_mem);
     GlobalFree(rsc_mem);
-/*
-    hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
- 	lpcur->descriptor.curYHotspot, 32, 32,
-	(LPSTR)lp + 211, , (LPSTR)lp + 211);
-*/
-    XFreePixmap(display, lpcur->pixshape);
-    XFreePixmap(display, lpcur->pixmask);
-    ReleaseDC(GetDesktopWindow(), hdc); 
     GlobalUnlock(hCursor);
+    ReleaseDC(0,hdc);
     return hCursor;
 }
 
@@ -231,12 +235,16 @@ HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot, 
 	short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
 {
-    XColor	bkcolor;
-    XColor	fgcolor;
     HCURSOR 	hCursor;
     CURSORALLOC	  *lpcur;
     HDC 	hdc;
-
+    int         bpllen = (nWidth + 7)/8 * nHeight;
+    char        *tmpbpl = malloc(bpllen);
+    int         i;
+  
+    XColor bkcolor,fgcolor;
+    Colormap cmap = XDefaultColormap(display,XDefaultScreen(display));
+    
     dprintf_resource(stddeb,"CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
        instance, nXhotspot, nYhotspot, nWidth, nHeight);
     dprintf_resource(stddeb,"CreateCursor: inst=%04x lpANDbitPlane=%p lpXORbitPlane=%p\n",
@@ -253,24 +261,21 @@ HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot,
     memset(lpcur, 0, sizeof(CURSORALLOC));
     lpcur->descriptor.curXHotspot = nXhotspot;
     lpcur->descriptor.curYHotspot = nYhotspot;
-    lpcur->pixshape = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        lpXORbitPlane, nWidth, nHeight,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
+    for(i=0; i<bpllen; i++) tmpbpl[i] = ~lpANDbitPlane[i];
     lpcur->pixmask = XCreatePixmapFromBitmapData(
     	display, DefaultRootWindow(display), 
-        lpANDbitPlane, nWidth, nHeight,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    memset(&bkcolor, 0, sizeof(XColor));
-    memset(&fgcolor, 0, sizeof(XColor));
-    bkcolor.pixel = WhitePixel(display, DefaultScreen(display)); 
-    fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
+        tmpbpl, nWidth, nHeight, 1, 0, 1);
+    for(i=0; i<bpllen; i++) tmpbpl[i] ^= lpXORbitPlane[i];
+    lpcur->pixshape = XCreatePixmapFromBitmapData(
+    	display, DefaultRootWindow(display),
+        tmpbpl, nWidth, nHeight, 1, 0, 1);
+    XParseColor(display,cmap,"#000000",&fgcolor);
+    XParseColor(display,cmap,"#ffffff",&bkcolor);
     lpcur->xcursor = XCreatePixmapCursor(display,
  	lpcur->pixshape, lpcur->pixmask, 
  	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
  	lpcur->descriptor.curYHotspot);
+    free(tmpbpl);
     XFreePixmap(display, lpcur->pixshape);
     XFreePixmap(display, lpcur->pixmask);
     ReleaseDC(GetDesktopWindow(), hdc); 
diff --git a/windows/message.c b/windows/message.c
index cf1d2cdc77c660342f15e5db6b03cf9b76506e97..279b32089d5edc3e04888f12604bc173800ddb10 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -882,10 +882,14 @@ BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
 {
     WND * wndPtr;
+    LONG ret;
 
     wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    return CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
+    ret = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
+    dprintf_msg( stddeb,"SendMessage(%4.4x,%x,%x,%lx) -> %lx\n",
+		 hwnd, msg, wParam, lParam, ret );
+	return ret;
 }
 
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 8e437522a91fe0f618a536afe02fc847f1ff4c3a..9604d35ff0970a29cd5555a19cc4c7bb3aac38d0 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -18,6 +18,7 @@
 #include "scroll.h"
 #include "nonclient.h"
 #include "graphics.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_NONCLIENT */
 #include "debug.h"
@@ -1321,7 +1322,7 @@ LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
 	if (wParam == SC_ABOUTWINE)
 	{   extern char sysres_DIALOG_2[];
 	    DialogBoxIndirectPtr( wndPtr->hInstance, sysres_DIALOG_2,
-		       hwnd, (WNDPROC)AboutWine_Proc );
+		       hwnd, GetWndProcEntry16("AboutWine_Proc") );
         }
 	break;
     }
diff --git a/windows/utility.c b/windows/utility.c
index 385848735f2928624d355b53f58acdb21b30f8c1..6bc0ef47828ddff38ddb6391648b453cbf6bcc45 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -14,6 +14,7 @@
 #include <stdlib.h>
 #include "windows.h"
 #include "ldt.h"
+#include "stackframe.h"
 #include "stddebug.h"
 /* #define DEBUG_UTILITY */
 #include "debug.h"
@@ -56,7 +57,7 @@ void UTILITY_strip015(char *dest) {
 int
 DebugPrintString(char *str)
 {
-    fprintf(stderr, "%s", str);
+    fprintf(stderr, "%s\n", str);
     return 0;
 }
 
@@ -268,12 +269,14 @@ char *UTILITY_convertArgs(char *format, char *winarg)
 };
 
 #ifndef WINELIB
-INT windows_wsprintf(BYTE *win_stack)
+INT windows_wsprintf(void)
 {
     LPSTR lpOutput, lpFormat, ptr;
     BYTE new_stack[1024], *stack_ptr;
     BOOL fLarge;
 
+    BYTE *win_stack = (BYTE *)CURRENT_STACK16->args;
+
     lpOutput = (LPSTR) PTR_SEG_TO_LIN(*(DWORD*)win_stack);
     win_stack += sizeof(DWORD);
     lpFormat = (LPSTR) PTR_SEG_TO_LIN(*(DWORD*)win_stack);
diff --git a/windows/win.c b/windows/win.c
index 6ed50d87a4674ae4cffc1862e8e2243726718db2..f17a885ccc7e1545280e242b083f05ae369ba663 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -21,8 +21,8 @@
 #include "nonclient.h"
 #include "winpos.h"
 #include "color.h"
-#include "stddebug.h"
 #include "callback.h"
+#include "stddebug.h"
 /* #define DEBUG_WIN  */ 
 /* #define DEBUG_MENU */
 #include "debug.h"
@@ -318,9 +318,15 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
     if (parent)
     {
 	  /* Make sure parent is valid */
-        if (!IsWindow( parent )) return 0;
+        if (!IsWindow( parent )) {
+			dprintf_win(stddeb,"CreateWindowEx: Parent %x is not a windows\n", parent);
+			return 0;
+		}
     }
-    else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
+    else if (style & WS_CHILD) {
+		dprintf_win(stddeb,"CreateWindowEx: no parent\n");
+		return 0;  /* WS_CHILD needs a parent */
+	}
 
     if (!(class = CLASS_FindClassByName( className, instance, &classPtr ))) {
 	fprintf(stderr,"CreateWindow BAD CLASSNAME '%s' !\n", className);
@@ -336,7 +342,10 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
       /* Create the window structure */
 
     hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
-    if (!hwnd) return 0;
+    if (!hwnd) {
+		dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
+		return 0;
+	}
 
       /* Fill the structure */
 
@@ -480,7 +489,10 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
 
     wmcreate = SendMessage( hwnd, WM_NCCREATE, 0,
                             USER_HEAP_SEG_ADDR(hcreateStruct) );
-    if (!wmcreate) wmcreate = -1;
+    if (!wmcreate) {
+		dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
+		wmcreate = -1;
+	}
     else
     {
 	WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
@@ -496,6 +508,7 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
     if (wmcreate == -1)
     {
 	  /* Abort window creation */
+	  dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
         WIN_DestroyWindow( hwnd );
 	return 0;
     }
@@ -991,8 +1004,6 @@ HWND GetLastActivePopup(HWND hwnd)
  *    pointers
  *
  *  o call wndenumprc for every child window the desktop has
- *    (parameters to Callback16 passed backwards so they are
- *    put in in pascal calling order)
  *
  *  o if wndenumprc returns 0 exit
  * 
@@ -1009,13 +1020,7 @@ BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
         if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
               return 0;
       }
-#ifdef WINELIB
-      (*wndenumprc)(hwnd, lParam);
-#else
-      result = CallBack16(wndenumprc, 2,
-		CALLBACK_SIZE_WORD, (int) hwnd,
-		CALLBACK_SIZE_LONG, lParam);
-#endif
+      result = CallEnumWindowsProc( wndenumprc, hwnd, lParam );
       if ( ! result )  {
               return 0;
       }
@@ -1030,7 +1035,7 @@ BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
  *   o hwnd is the first child to use, loop until all next windows
  *     are processed
  * 
- *   o call wdnenumprc with parameters in inverse order (pascal)
+ *   o call wdnenumprc
  *
  *   o call ourselves with the next child window
  * 
@@ -1039,22 +1044,11 @@ static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
 {
     WND *wndPtr;
 
-    while (hwnd) {
-      if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
-            return 0;
-        }
-#ifdef WINELIB
-        if (!(*wndenumprc)( 2, lParam, (int) hwnd)) {
-#else
-        if (!CallBack16(wndenumprc, 2,
-		CALLBACK_SIZE_WORD, (int) hwnd,
-		CALLBACK_SIZE_LONG, lParam)) {
-#endif
-                return 0;
-      }
-      if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
-          return 0;
-      }
+    while (hwnd)
+    {
+        if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
+        if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
+        if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
         hwnd=wndPtr->hwndNext;
     } 
     return 1;