Release 950430

Sat Apr 29 20:42:01 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [controls/static.c]
	Fixed painting of SS_*FRAME controls.

	* [if1632/callback.c]
	Pass the window instance as DS to the 16-bit window procedure.
	Rewrote Catch() and Throw() to make them work with multiple tasks.

	* [loader/main.c]
	New function MAIN_Init() to perform initializations before the
	first task is started instead of doing them in InitApp().
	Temporary hack to command-line parsing to load one program per
	command-line argument, to make testing task-switching easier.

	* [loader/*.c]
	Reimplemented modules to use a Windows-compatible layout and to
	allow multiple tasks and multiple module instances. Not really
	finished yet.

	* [loader/task.c] [misc/exec.c]
	Reimplemented tasks to use a common address space, and implemented
	preliminary task-switching capabilities.

	* [memory/global.c]
	Fixed bug in GlobalNext().

	* [misc/main.c]
	Updated the list of contributors. Let me know if I forgot someone.

	* [miscemu/int21.c]
	Use one DTA per task instead of a global one.

	* [objects/bitblt.c]
	Fixed bug in BitBlt() that could cause BadMatch errors.

	* [tools/build.c]
	Added new function type 'stub', that makes possible to export an
	unimplemented function by name as well as by ordinal. This will
	avoid loading errors for unimplemented functions.
	Generate an in-memory module layout for built-in DLLs so that the
	same code can be used for built-in and loaded modules.
	Changed relay code to make it unnecessary to save the value of the
	BP register.

	* [windows/message.c]
	Implemented multiple message queues and preliminary task-switching
	capabilities. Inter-task SendMessage() calls are not implemented
	yet and will probably cause crashes if used.

	* [windows/property.c]
	Reimplemented properties and allocate them on the USER heap.

	* [windows/win.c]
	Fixed bug in SetWindowWord().
	Reimplemented EnumWindows() and EnumTaskWindows().

Tue Apr 18 09:48:38 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [misc/main.c]
	GetSystemParametersInfo(): Additional action SPI_GETICONTITLEFONT.
	
	* [loader/resource.c]
	Removed the check for NE_SEGFLAGS_EXECUTEONLY, since it broke
	control.exe.
	Fixed icon loading.
	
	* [objects/font.c] [include/windows.h]
	Fixed a bug in InitFontsList() and worked on the EnumFonts()
	functions to make them comprehensible.

        * [controls/button.c]
	Fixed my previous patch to handle LBUTTONUP messages.

Fri Apr 14 11:41:28 1995  Cameron Heide  (heide@ee.ualberta.ca)

        * [misc/network.c, misc/dos_fs.c]
        Implemented WNetGetConnection.  All that is currently
        supported are drives, for which the remote name is simply
        the redirected UNIX directory name.

        * [miscemu/int2?.c]
        More drive number validity checking.

Wed Apr 12 11:28:37 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
        * [controls/listbox.c]
	Oops, my previous change to ListBoxDirectory broke the Borland
	file open dialog. Fixed.

Mon Apr 10 23:17:12 1995  Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/ole2nls.spec] [misc/ole2nls.c] [misc/Imakefile]
	New file ole2nls.c. Added stubs for GetUserDefaultLCID, 
	GetSystemDefaultLCID, GetUserDefaultLangID, GetSystemDefaultLangID.

Mon Apr 10 10:05:18 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [memory/global.c] [memory/local.c] [include/windows.h]
	GlobalReAlloc(): If GMEM_MODIFY is set, don't resize the block.
	LocalReAlloc(): Same for LMEM_MODIFY.
	
        * [controls/listbox.c]
	Fixed a bug in ListBoxDirectory that prevented commdlg from working.
	Check for errors in some more places.

        * [if1632/gdi.spec] [if1632/user.spec]
	16 bit callback functions should be passed as segptrs.
	
	* [include/dlls.h] [loader/ne_image.c] [loader/selector.c]
	[loader/library.c]
	Prevent a DLL from being initialized twice (Borlands Resource
	Workshop used to do this).
	Provide an additional flag for each w_file that indicates whether
	it's an EXE or a DLL, for combinations like pbrush.exe/.dll.
	
	* [controls/button.c]
	Handle LBUTTONUP messages even if the button no longer has the
	capture (for WinHelp).
	
	* [include/wintypes.h]
	FARPROC is now a segptr for the emulator and a function
	pointer for the library.
	
	* [misc/commdlg.c] [misc/commdlg.h]
	Cleaned the file dialogs up a little. They now work reasonably well,
	although there are still some problems (e.g. files are initially
        invisible).

	* [windows/class.c] [if1632/user.spec] [include/windows.h]
	GetClassInfo() must take a segptr, as it checks whether the
	highword is zero.
	GetClassName() called the wrong atom function. No surprise it didn't
        find anything.

	* [misc/lstr.c]
	AnsiToOem() and OemToAnsi() didn't terminate the strings. Fixed.
        Removed some warnings.

	* [if1632/relay.c] [if1632/ddeml.spec] [include/dlls.h]
	New spec file for the 3.1 DDEML DDL. 

	* [controls/menu.c]
	Small fix to ChangeMenu - mask out the obsolete flags
	(MF_APPEND == MF_OWNERDRAW, this led to problems). It also had
	problems with the MF_BYPOSITION flag.

        * [windows/message.c]
        SendMessage(): call the WH_CALLWNDPROC hook function. This is rather
        ugly, I'm afraid. Windows probably passes a pointer to the 16 bit
        stack for speed reasons.
	
        * [windows/hook.c] [include/windows.h]
        Set/HookWindowsHook() shouldn't just call their *Ex counterparts, as
        they have slightly different semantics.
        MS Hearts now works somewhat, if you disable the new builtin DDEML.
        The graphics are completely messed up, though.
diff --git a/ANNOUNCE b/ANNOUNCE
index f1033c9..4b746f9 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,16 +1,14 @@
-This is release 950403 of Wine the MS Windows emulator.  This is still a
+This is release 950430 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-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.
+WHAT'S NEW with Wine-950430: (see ChangeLog for details)
+	- Preliminary multitasking support.
+	- Better DOS drives support.
+	- Stubs for DDEML library.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -19,10 +17,10 @@
 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-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
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950430.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950430.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950430.tar.gz
+    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950430.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
@@ -34,13 +32,16 @@
 reading for new developers.
 
 Wine is available thanks to the work of Bob Amstadt, Dag Asheim,
-Martin Ayotte, Erik Bos, John Brezak, Andrew Bulhak, John Burton,
-Paul Falstad, Peter Galbavy, Jeffrey Hsu, Miguel de Icaza,
-Alexandre Julliard, Jon Konrath, Scott A. Laird, Martin von Loewis,
-Kenneth MacDonald, Peter MacDonald, David Metcalfe, Michael Patra,
-John Richardson, Johannes Ruscheinski, Yngvi Sigurjonsson,
-Rick Sladkey, William Smith, Jon Tombs, Linus Torvalds, Carl Williams,
-Karl Guenter Wuensch, and Eric Youngdale.
+Martin Ayotte, Ross Biro, Erik Bos, Fons Botman, John Brezak,
+Andrew Bulhak, John Burton, Paul Falstad, Olaf Flebbe, Peter Galbavy,
+Cameron Heide, Jeffrey Hsu, Miguel de Icaza, Alexandre Julliard,
+Jon Konrath, Scott A. Laird, Martin von Loewis, Kenneth MacDonald,
+Peter MacDonald, William Magro, David Metcalfe, Michael Patra,
+John Richardson, Johannes Ruscheinski, Thomas Sandford,
+Constantine Sapuntzakis, Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey,
+William Smith, Erik Svendsen, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs,
+Linus Torvalds, Michael Veksler, Carl Williams, Karl Guenter Wuensch,
+Eric Youngdale, and James Youngman.
 
 --
 Alexandre Julliard
diff --git a/ChangeLog b/ChangeLog
index dae439c..784fd76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,163 @@
 ----------------------------------------------------------------------
+Sat Apr 29 20:42:01 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
+
+	* [controls/static.c]
+	Fixed painting of SS_*FRAME controls.
+
+	* [if1632/callback.c]
+	Pass the window instance as DS to the 16-bit window procedure.
+	Rewrote Catch() and Throw() to make them work with multiple tasks.
+
+	* [loader/main.c]
+	New function MAIN_Init() to perform initializations before the
+	first task is started instead of doing them in InitApp().
+	Temporary hack to command-line parsing to load one program per
+	command-line argument, to make testing task-switching easier.
+
+	* [loader/*.c]
+	Reimplemented modules to use a Windows-compatible layout and to
+	allow multiple tasks and multiple module instances. Not really
+	finished yet.
+
+	* [loader/task.c] [misc/exec.c]
+	Reimplemented tasks to use a common address space, and implemented
+	preliminary task-switching capabilities.
+
+	* [memory/global.c]
+	Fixed bug in GlobalNext().
+
+	* [misc/main.c]
+	Updated the list of contributors. Let me know if I forgot someone.
+
+	* [miscemu/int21.c]
+	Use one DTA per task instead of a global one.
+
+	* [objects/bitblt.c]
+	Fixed bug in BitBlt() that could cause BadMatch errors.
+
+	* [tools/build.c]
+	Added new function type 'stub', that makes possible to export an
+	unimplemented function by name as well as by ordinal. This will
+	avoid loading errors for unimplemented functions.
+	Generate an in-memory module layout for built-in DLLs so that the
+	same code can be used for built-in and loaded modules.
+	Changed relay code to make it unnecessary to save the value of the
+	BP register.
+
+	* [windows/message.c]
+	Implemented multiple message queues and preliminary task-switching
+	capabilities. Inter-task SendMessage() calls are not implemented
+	yet and will probably cause crashes if used.
+
+	* [windows/property.c]
+	Reimplemented properties and allocate them on the USER heap.
+
+	* [windows/win.c]
+	Fixed bug in SetWindowWord().
+	Reimplemented EnumWindows() and EnumTaskWindows().
+
+Tue Apr 18 09:48:38 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [misc/main.c]
+	GetSystemParametersInfo(): Additional action SPI_GETICONTITLEFONT.
+	
+	* [loader/resource.c]
+	Removed the check for NE_SEGFLAGS_EXECUTEONLY, since it broke
+	control.exe.
+	Fixed icon loading.
+	
+	* [objects/font.c] [include/windows.h]
+	Fixed a bug in InitFontsList() and worked on the EnumFonts()
+	functions to make them comprehensible.
+
+        * [controls/button.c]
+	Fixed my previous patch to handle LBUTTONUP messages.
+
+Fri Apr 14 11:41:28 1995  Cameron Heide  (heide@ee.ualberta.ca)
+
+        * [misc/network.c, misc/dos_fs.c]
+        Implemented WNetGetConnection.  All that is currently
+        supported are drives, for which the remote name is simply
+        the redirected UNIX directory name.
+
+        * [miscemu/int2?.c]
+        More drive number validity checking.
+
+Wed Apr 12 11:28:37 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+        * [controls/listbox.c]
+	Oops, my previous change to ListBoxDirectory broke the Borland
+	file open dialog. Fixed.
+
+Mon Apr 10 23:17:12 1995  Martin von Loewis  <loewis@informatik.hu-berlin.de>
+
+	* [if1632/ole2nls.spec] [misc/ole2nls.c] [misc/Imakefile]
+	New file ole2nls.c. Added stubs for GetUserDefaultLCID, 
+	GetSystemDefaultLCID, GetUserDefaultLangID, GetSystemDefaultLangID.
+
+Mon Apr 10 10:05:18 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [memory/global.c] [memory/local.c] [include/windows.h]
+	GlobalReAlloc(): If GMEM_MODIFY is set, don't resize the block.
+	LocalReAlloc(): Same for LMEM_MODIFY.
+	
+        * [controls/listbox.c]
+	Fixed a bug in ListBoxDirectory that prevented commdlg from working.
+	Check for errors in some more places.
+
+        * [if1632/gdi.spec] [if1632/user.spec]
+	16 bit callback functions should be passed as segptrs.
+	
+	* [include/dlls.h] [loader/ne_image.c] [loader/selector.c]
+	[loader/library.c]
+	Prevent a DLL from being initialized twice (Borlands Resource
+	Workshop used to do this).
+	Provide an additional flag for each w_file that indicates whether
+	it's an EXE or a DLL, for combinations like pbrush.exe/.dll.
+	
+	* [controls/button.c]
+	Handle LBUTTONUP messages even if the button no longer has the
+	capture (for WinHelp).
+	
+	* [include/wintypes.h]
+	FARPROC is now a segptr for the emulator and a function
+	pointer for the library.
+	
+	* [misc/commdlg.c] [misc/commdlg.h]
+	Cleaned the file dialogs up a little. They now work reasonably well,
+	although there are still some problems (e.g. files are initially
+        invisible).
+
+	* [windows/class.c] [if1632/user.spec] [include/windows.h]
+	GetClassInfo() must take a segptr, as it checks whether the
+	highword is zero.
+	GetClassName() called the wrong atom function. No surprise it didn't
+        find anything.
+
+	* [misc/lstr.c]
+	AnsiToOem() and OemToAnsi() didn't terminate the strings. Fixed.
+        Removed some warnings.
+
+	* [if1632/relay.c] [if1632/ddeml.spec] [include/dlls.h]
+	New spec file for the 3.1 DDEML DDL. 
+
+	* [controls/menu.c]
+	Small fix to ChangeMenu - mask out the obsolete flags
+	(MF_APPEND == MF_OWNERDRAW, this led to problems). It also had
+	problems with the MF_BYPOSITION flag.
+
+        * [windows/message.c]
+        SendMessage(): call the WH_CALLWNDPROC hook function. This is rather
+        ugly, I'm afraid. Windows probably passes a pointer to the 16 bit
+        stack for speed reasons.
+	
+        * [windows/hook.c] [include/windows.h]
+        Set/HookWindowsHook() shouldn't just call their *Ex counterparts, as
+        they have slightly different semantics.
+        MS Hearts now works somewhat, if you disable the new builtin DDEML.
+        The graphics are completely messed up, though.
+
+----------------------------------------------------------------------
 Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
 
 	* [Configure] [if1632/Imakefile]
diff --git a/controls/button.c b/controls/button.c
index f15d5ff..c21d222 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -14,7 +14,8 @@
 #include "syscolor.h"
 #include "graphics.h"
 #include "button.h"
-
+#include "stddebug.h"
+#include "debug.h"
 extern void DEFWND_SetText( HWND hwnd, LPSTR text );  /* windows/defwnd.c */
 
 static void PB_Paint( HWND hWnd, HDC hDC, WORD action );
@@ -138,8 +139,8 @@
 		break;
 
 	case WM_LBUTTONUP:
-                if (GetCapture() != hWnd) break;
-                ReleaseCapture();
+	        ReleaseCapture();
+	        if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break;
                 SendMessage( hWnd, BM_SETSTATE, FALSE, 0 );
                 GetClientRect( hWnd, &rect );
                 if (PtInRect( &rect, MAKEPOINT(lParam) ))
diff --git a/controls/desktop.c b/controls/desktop.c
index 7a7d545..9ba78b4 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -16,6 +16,7 @@
 #include "dos_fs.h"
 #include "graphics.h"
 
+
 /***********************************************************************
  *           DESKTOP_LoadBitmap
  *
@@ -113,6 +114,31 @@
 
 
 /***********************************************************************
+ *           DESKTOP_Init
+ *
+ * Initialize the desktop window private information.
+ */
+BOOL DESKTOP_Init()
+{
+    HWND hwnd = GetDesktopWindow();
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
+
+    infoPtr->hbrushPattern = 0;
+    infoPtr->hbitmapWallPaper = 0;
+    SetDeskPattern();
+    SetDeskWallPaper( (LPSTR)-1 );
+    if (rootWindow != DefaultRootWindow(display))
+    {
+        HDC hdc = GetDC( hwnd );
+        DESKTOP_DoEraseBkgnd( hwnd, hdc, infoPtr );
+        ReleaseDC( hwnd, hdc );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           DesktopWndProc
  *
  * Window procedure for the desktop window.
diff --git a/controls/listbox.c b/controls/listbox.c
index 58d204c..d20e568 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -65,9 +65,11 @@
 #define LIST_HEAP_ADDR(lphl,handle) \
     ((void *)((handle) ? ((handle) | ((int)lphl->Heap & 0xffff0000)) : 0))
 #else
+/* FIXME: shouldn't each listbox have its own heap? */
 #define LIST_HEAP_ALLOC(lphl,f,size) USER_HEAP_ALLOC(size)
 #define LIST_HEAP_FREE(lphl,handle)  USER_HEAP_FREE(handle)
 #define LIST_HEAP_ADDR(lphl,handle)  USER_HEAP_LIN_ADDR(handle)
+#define LIST_HEAP_SEG_ADDR(lphl,handle) USER_HEAP_SEG_ADDR(handle)
 #endif
 
 #define LIST_HEAP_SIZE 0x10000
@@ -440,7 +442,7 @@
   LPHEADLIST lphl;
   WND        *wndPtr;
 
-  ReleaseCapture();
+  if (GetCapture() == hwnd) ReleaseCapture();
 
   lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
   if (lphl == NULL) return 0;
@@ -1214,7 +1216,6 @@
     }
     idx++;
   }
-  
   return DefWindowProc (hwnd, message, wParam, lParam);
 }
 
@@ -1280,15 +1281,14 @@
       dis->CtlID   = ParentWndPtr->wIDmenu;
     }
 
-    if (HasStrings(wndPtr)) dis->itemData = (DWORD)lpls->itemText;
+    if (HasStrings(wndPtr)) dis->itemData = LIST_HEAP_SEG_ADDR(lpls,lpls->hData);
    
     dis->itemAction = itemAction;
     dis->itemState  = itemState;
 
     SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, 
 		0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
-  }
-  else {
+  } else {
 
     if (itemAction == ODA_DRAWENTIRE ||
 	itemAction == ODA_SELECT) {
@@ -1476,7 +1476,7 @@
   lpmeasure->itemHeight = 0;
 
   if (HasStrings(wndPtr))
-    lpmeasure->itemData = (DWORD)lpls->itemText;
+    lpmeasure->itemData = LIST_HEAP_SEG_ADDR(lpls,lpls->hData);
   else
     lpmeasure->itemData = lpls->dis.itemData;
 
@@ -1563,8 +1563,7 @@
     newstr = str;
     lplsnew->itemText = str;
     dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
-  }
-  else {
+  } else {
     lplsnew->itemText = NULL;
     lplsnew->dis.itemData = (DWORD)newstr;
   }
@@ -1614,7 +1613,7 @@
   if (!bItemData) *OutStr=0;
 
   if ((lpls = ListBoxGetItem (hwnd, uIndex)) == NULL) 
-    return 0;
+    return LB_ERR;
 
   if (bItemData)
     return lpls->dis.itemData;
@@ -1634,7 +1633,7 @@
   LPLISTSTRUCT lpls;
 
   if ((lpls = ListBoxGetItem(hwnd, uIndex)) == NULL)
-    return 0;
+    return LB_ERR;
 
   lpls->dis.itemData = ItemData;
   return 1;
@@ -1807,12 +1806,14 @@
 
   if (lphl->ItemFocused != -1) {
     lpls = ListBoxGetItem(hwnd, lphl->ItemFocused);
+    if (lpls == 0) return LB_ERR;
     lpls->dis.itemState = 0;
   }
 
   if (wIndex != (UINT)-1) {
     lphl->ItemFocused = wIndex;
     lpls = ListBoxGetItem(hwnd, wIndex);
+    if (lpls == 0) return LB_ERR;
     lpls->dis.itemState = ODS_SELECTED | ODS_FOCUS;
 
     return 0;
@@ -1867,10 +1868,11 @@
 {
   struct dosdirent *dp, *dp_old;
   int	x, wRet = LB_OKAY;
-  BOOL    OldFlag;
+  BOOL  OldFlag;
   char 	temp[256];
   LPHEADLIST 	lphl;
-  int drive;
+  int   drive;
+  LPSTR tstr;
 
   dprintf_listbox(stddeb,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
 
@@ -1880,19 +1882,15 @@
       drive = toupper(filespec[0]) - 'A';
       filespec += 2;
     }
-    if( !strchr( filespec, '\\' ) ) 
+    strcpy(temp,filespec);
+    tstr = strrchr(temp, '\\');
+    if( tstr == NULL ) 
       DOS_SetDefaultDrive( drive );
     else {
-      int i;
-      strcpy( temp, filespec );
-      for( i=0; i<strlen(temp); i++ )
-	if( temp[i] == '\\' ) {
-	  temp[i] = 0;
-	  filespec += ( i+1 );
-	  break;
-	}
+      *tstr = 0;
+      filespec = tstr + 1;
       DOS_ChangeDir( drive, temp );
-      DOS_SetDefaultDrive( drive );
+      if (!DOS_ChangeDir( drive, temp )) return 0;
     }
     dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
 		    drive+'A', temp, filespec );
@@ -1908,15 +1906,14 @@
     dprintf_listbox( stddeb, "ListBoxDirectory %p '%s' !\n", dp->filename, 
 		    dp->filename);
     if (dp->attribute & FA_DIREC) {
-      if (attrib & DDL_DIRECTORY &&
-	  strcmp(dp->filename, ".")) {
+      if (attrib & DDL_DIRECTORY && strcmp(dp->filename, ".") != 0) {
 	sprintf(temp, "[%s]", dp->filename);
 	if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
       }
     } 
     else {
       if (attrib & DDL_EXCLUSIVE) {
-	if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | 
+	if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN |
 		      DDL_SYSTEM) )
 	  if ( (wRet = ListBoxAddString(hwnd, dp->filename)) 
 	      == LB_ERR) break;
diff --git a/controls/menu.c b/controls/menu.c
index 2b20dbe..be7df27 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -738,8 +738,8 @@
 	    items[lppop->FocusedItem].item_flags |= MF_HILITE;
 	    MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
 			       !(lppop->wFlags & MF_POPUP) );
-	    SendMessage(lppop->hWnd, WM_MENUSELECT,
-			items[lppop->FocusedItem].item_id, 
+	    dprintf_menu(stddeb,"Sending WM_MENUSELECT %04x %04x\n", items[lppop->FocusedItem].item_id,items[lppop->FocusedItem].item_flags);
+	    SendMessage(lppop->hWnd, WM_MENUSELECT, items[lppop->FocusedItem].item_id,
 		       MAKELONG( hmenu, items[lppop->FocusedItem].item_flags));
 	}
     }
@@ -1494,18 +1494,24 @@
 BOOL ChangeMenu(HMENU hMenu, WORD nPos, LPSTR lpNewItem, 
 			WORD wItemID, WORD wFlags)
 {
-	dprintf_menu(stddeb,"ChangeMenu(%04X, %X, '%s', %X, %X)\n",
-		hMenu, nPos, lpNewItem, wItemID, wFlags);
-	if (wFlags & MF_APPEND)
-		return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
-	if (wFlags & MF_DELETE)
-		return DeleteMenu(hMenu, wItemID, wFlags);
-	if (wFlags & MF_CHANGE) 
-		return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
-	if (wFlags & MF_REMOVE) 
-		return RemoveMenu(hMenu, wItemID, wFlags);
-	/* Default: MF_INSERT */
-	return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
+  dprintf_menu(stddeb,"ChangeMenu(%04X, %X, '%s', %X, %X)\n",
+	       hMenu, nPos, lpNewItem, wItemID, wFlags);
+  if (wFlags & MF_APPEND)  {
+    return AppendMenu(hMenu, wFlags & ~MF_APPEND, wItemID, lpNewItem);
+  }
+  if (wFlags & MF_DELETE) {
+    return DeleteMenu(hMenu, wFlags & MF_BYPOSITION ? nPos : wItemID, 
+		      wFlags & ~MF_DELETE);
+  }
+  if (wFlags & MF_CHANGE) {
+    return ModifyMenu(hMenu, nPos, wFlags & ~MF_CHANGE, wItemID, lpNewItem);
+  }
+  if (wFlags & MF_REMOVE) {
+    return RemoveMenu(hMenu, wFlags & MF_BYPOSITION ? nPos : wItemID,
+		      wFlags & ~MF_REMOVE);
+  }
+  /* Default: MF_INSERT */
+  return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
 }
 
 
@@ -2075,6 +2081,34 @@
 
 
 /**********************************************************************
+ *	    LoadMenu    (USER.150)
+ */
+HMENU LoadMenu( HINSTANCE instance, SEGPTR name )
+{
+    HRSRC hRsrc;
+    HGLOBAL handle;
+    HMENU hMenu;
+
+    if (HIWORD(name))
+    {
+        char *str = (char *)PTR_SEG_TO_LIN( name );
+        dprintf_menu( stddeb, "LoadMenu(%04x,'%s')\n", instance, str );
+        if (str[0] == '#') name = (SEGPTR)atoi( str + 1 );
+    }
+    else
+        dprintf_resource(stddeb,"LoadMenu(%04x,%04x)\n",instance,LOWORD(name));
+
+    if (!name) return 0;
+
+    if (!(hRsrc = FindResource( instance, name, RT_MENU ))) return 0;
+    if (!(handle = LoadResource( instance, hRsrc ))) return 0;
+    hMenu = LoadMenuIndirect( LockResource(handle) );
+    FreeResource( handle );
+    return hMenu;
+}
+
+
+/**********************************************************************
  *			LoadMenuIndirect	[USER.220]
  */
 HMENU LoadMenuIndirect(LPSTR menu_template)
diff --git a/controls/scroll.c b/controls/scroll.c
index b6a7e3c..1f30bee 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -99,6 +99,7 @@
     HANDLE handle;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
+    if (!wndPtr) return NULL;
     switch(nBar)
     {
         case SB_HORZ: handle = wndPtr->hHScroll; break;
@@ -588,7 +589,8 @@
         if (hittest == trackHitTest)
         {
             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
-                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+                            (FARPROC)0 );
             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
                 SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
                              SB_LINEUP, MAKELONG( 0, hwndCtl ));
@@ -603,7 +605,8 @@
         if (hittest == trackHitTest)
         {
             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
-                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+                            (FARPROC)0 );
             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
                 SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
                              SB_PAGEUP, MAKELONG( 0, hwndCtl ));
@@ -646,7 +649,8 @@
         if (hittest == trackHitTest)
         {
             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
-                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+                            (FARPROC)0 );
             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
                 SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
                              SB_PAGEDOWN, MAKELONG( 0, hwndCtl ));
@@ -660,7 +664,8 @@
         if (hittest == trackHitTest)
         {
             SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
-                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL );
+                            SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
+                            (FARPROC)0 );
             if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
                 SendMessage( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
                              SB_LINEDOWN, MAKELONG( 0, hwndCtl ));
diff --git a/controls/static.c b/controls/static.c
index 063ad23..b0c37ec 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -17,7 +17,6 @@
 
 static void PaintTextfn( HWND hwnd, HDC hdc );
 static void PaintRectfn( HWND hwnd, HDC hdc );
-static void PaintFramefn( HWND hwnd, HDC hdc );
 static void PaintIconfn( HWND hwnd, HDC hdc );
 
 
@@ -37,9 +36,9 @@
     PaintRectfn,             /* SS_BLACKRECT */
     PaintRectfn,             /* SS_GRAYRECT */
     PaintRectfn,             /* SS_WHITERECT */
-    PaintFramefn,            /* SS_BLACKFRAME */
-    PaintFramefn,            /* SS_GRAYFRAME */
-    PaintFramefn,            /* SS_WHITEFRAME */
+    PaintRectfn,             /* SS_BLACKFRAME */
+    PaintRectfn,             /* SS_GRAYFRAME */
+    PaintRectfn,             /* SS_WHITEFRAME */
     NULL,                    /* Not defined */
     PaintTextfn,             /* SS_SIMPLE */
     PaintTextfn              /* SS_LEFTNOWORDWRAP */
@@ -241,63 +240,36 @@
 
     GetClientRect(hwnd, &rc);
     
-    switch (wndPtr->dwStyle & 0x0000000F)
+    switch (wndPtr->dwStyle & 0x0f)
     {
     case SS_BLACKRECT:
 	hBrush = CreateSolidBrush(color_windowframe);
+        FillRect( hdc, &rc, hBrush );
 	break;
-
     case SS_GRAYRECT:
 	hBrush = CreateSolidBrush(color_background);
+        FillRect( hdc, &rc, hBrush );
 	break;
-
     case SS_WHITERECT:
 	hBrush = CreateSolidBrush(color_window);
+        FillRect( hdc, &rc, hBrush );
 	break;
-
-    default:
-        return;
-    }
-    FillRect( hdc, &rc, hBrush );
-}
-
-static void PaintFramefn( HWND hwnd, HDC hdc )
-{
-    RECT rc;
-    HPEN hOldPen, hPen;
-    HBRUSH hOldBrush, hBrush;
-
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-
-    GetClientRect(hwnd, &rc);
-    
-    switch (wndPtr->dwStyle & 0x0000000F)
-    {
     case SS_BLACKFRAME:
-	hPen = CreatePen(PS_SOLID, 1, color_windowframe);
+	hBrush = CreateSolidBrush(color_windowframe);
+        FrameRect( hdc, &rc, hBrush );
 	break;
-
     case SS_GRAYFRAME:
-	hPen = CreatePen(PS_SOLID, 1, color_background);
+	hBrush = CreateSolidBrush(color_background);
+        FrameRect( hdc, &rc, hBrush );
 	break;
-
     case SS_WHITEFRAME:
-	hPen = CreatePen(PS_SOLID, 1, color_window);
+	hBrush = CreateSolidBrush(color_window);
+        FrameRect( hdc, &rc, hBrush );
 	break;
-
     default:
         return;
     }
-
-    hBrush = CreateSolidBrush(color_window);
-    hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
-    hOldBrush = (HBRUSH)SelectObject(hdc, (HANDLE)hBrush);
-    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
-
-    SelectObject(hdc, (HANDLE)hOldPen);
-    SelectObject(hdc, (HANDLE)hOldBrush);
-    DeleteObject((HANDLE)hPen);
-    DeleteObject((HANDLE)hBrush);
+    DeleteObject( hBrush );
 }
 
 
diff --git a/debugger/hash.c b/debugger/hash.c
index 1bce11a..26d822b 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -154,6 +154,7 @@
 	int j, ordinal, len;
 	unsigned int address;
 
+#if 0
 	struct w_files * wpnt;
 	for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
 		cpnt  = wpnt->ne->nrname_table;
@@ -174,4 +175,5 @@
 		};
 	};
 	return;
+#endif
 }
diff --git a/debugger/info.c b/debugger/info.c
index 8b1604f..8166310 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -288,12 +288,8 @@
       if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
       fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, cs, 
 	      frame->u.win16.saved_ip);
+      if (!frame->u.win16.saved_bp) break;
       frame = (struct frame *) PTR_SEG_OFF_TO_LIN( SC_SS, frame->u.win16.saved_bp & ~1);
-      if ((cs & 7) != 7)  /* switching to 32-bit mode */
-      {
-          extern int IF1632_Saved32_ebp;
-          frame = (struct frame *)IF1632_Saved32_ebp;
-      }
     }
   }
   putchar('\n');
diff --git a/if1632/Imakefile b/if1632/Imakefile
index 99e872b..b3790ae 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -17,6 +17,7 @@
 DLLS = \
 	commdlg \
 	compobj \
+	ddeml \
 	gdi \
 	kernel \
 	keyboard \
@@ -41,7 +42,7 @@
 	winsock
 #endif
 
-OBJS = $(DLLS:%=dll_%.o) $(CALLOBJS) $(SRCS:.c=.o) $(DLLS:%=tab_%.o)
+OBJS = $(SRCS:.c=.o) $(CALLOBJS) $(DLLS:%=dll_%.o) $(DLLS:%=tab_%.o)
 
 BUILD = $(TOP)/tools/build
 
@@ -54,6 +55,7 @@
  */
 MakeDllFromSpec(commdlg)
 MakeDllFromSpec(compobj)
+MakeDllFromSpec(ddeml)
 MakeDllFromSpec(gdi)
 MakeDllFromSpec(kernel)
 MakeDllFromSpec(keyboard)
diff --git a/if1632/callback.c b/if1632/callback.c
index a941b16..2587ee6 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -6,169 +6,78 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <strings.h>
-#include <setjmp.h>
 #include "windows.h"
 #include "callback.h"
-#include "wine.h"
-#include "global.h"
 #include "stackframe.h"
-#include "dlls.h"
+#include "win.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "if1632.h"
 
-extern unsigned long  IF1632_Saved32_ebp;
-extern unsigned long  IF1632_Saved32_esp;
-
-static WORD ThunkSelector = 0;
-
-struct thunk_s
-{
-    int used;
-    unsigned char thunk[8];
-};
 
 
 /**********************************************************************
- *					MakeProcInstance
- */
-FARPROC MakeProcInstance( FARPROC func, WORD instance )
-{
-    char *thunks;
-    struct thunk_s *tp;
-    int i;
-
-    if (!ThunkSelector)
-    {
-        HGLOBAL handle = GLOBAL_Alloc( GMEM_ZEROINIT, 0x10000, 0, TRUE, FALSE);
-        ThunkSelector = GlobalHandleToSel(handle);
-    }
-
-    thunks = (char *)PTR_SEG_OFF_TO_LIN( ThunkSelector, 0 );
-    tp = (struct thunk_s *) thunks;
-    for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
-	if (!tp->used)
-	    break;
-    
-    if (tp->used) return (FARPROC)0;
-    
-    tp->thunk[0] = 0xb8;    /* movw instance, %ax */
-    tp->thunk[1] = (unsigned char) instance;
-    tp->thunk[2] = (unsigned char) (instance >> 8);
-    tp->thunk[3] = 0xea;    /* ljmp func */
-    *(LONG *)&tp->thunk[4] = (LONG)func;
-    tp->used = 1;
-
-    return (FARPROC)MAKELONG( (char *)tp->thunk - thunks, ThunkSelector );
-}
-
-/**********************************************************************
- *					FreeProcInstance (KERNEL.52)
- */
-void FreeProcInstance(FARPROC func)
-{
-    struct thunk_s *tp;
-    int i;
-    
-    tp = (struct thunk_s *) PTR_SEG_OFF_TO_LIN( ThunkSelector, 0 );
-    for (i = 0; i < 0x10000 / sizeof(*tp); i++, tp++)
-    {
-	if ((void *) tp->thunk == (void *) func)
-	{
-	    tp->used = 0;
-	    break;
-	}
-    }
-}
-
-/**********************************************************************
- *	    GetCodeHandle    (KERNEL.93)
- */
-HANDLE GetCodeHandle( FARPROC proc )
-{
-    struct thunk_s *tp = (struct thunk_s *)proc;
-
-    /* Return the code segment containing 'proc'. */
-    /* Not sure if this is really correct (shouldn't matter that much). */
-    printf( "STUB: GetCodeHandle(%p) returning %x\n",
-            proc, tp->thunk[8] + (tp->thunk[9] << 8) );
-    return tp->thunk[8] + (tp->thunk[9] << 8);
-}
-
-
-/**********************************************************************
- *					CallWindowProc    (USER.122)
+ *	     CallWindowProc    (USER.122)
  */
 LONG CallWindowProc( WNDPROC func, HWND hwnd, WORD message,
 		     WORD wParam, LONG lParam )
 {
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr) return 0;
     SpyMessage(hwnd, message, wParam, lParam);
-    return CallWndProc( (FARPROC)func, hwnd, message, wParam, lParam );
+    return CallWndProc( (FARPROC)func, wndPtr->hInstance, 
+                        hwnd, message, wParam, lParam );
 }
 
 
-/* ------------------------------------------------------------------------ */
-/*
- * The following functions realize the Catch/Throw functionality.
- * My thought is to use the setjmp, longjmp combination to do the
- * major part of this one. All I have to remember, in addition to
- * whatever the jmp_buf contains, is the contents of the 16-bit
- * sp, bp and ss. I do this by storing them in the structure passed
- * to me by the 16-bit program (including my own jmp_buf...). 
- * Hopefully there isn't any program that modifies the contents!
- * Bad thing: I have to save part of the stack, since this will 
- * get reused on the next call after my return, leaving it in an
- * undefined state.
+/**********************************************************************
+ *	     Catch    (KERNEL.55)
  */
-#define	STACK_DEPTH_16 	28
-
-struct special_buffer {
-	jmp_buf buffer;
-	long 	regs [5];
-	char 	stack_part [STACK_DEPTH_16];
-} *sb;
-
-int Catch (LPCATCHBUF cbuf)
+int Catch( LPCATCHBUF lpbuf )
 {
-	WORD retval;
-	jmp_buf *tmp_jmp;
+    STACK16FRAME *pFrame = CURRENT_STACK16;
 
-	sb = malloc (sizeof (struct special_buffer));
-	
-	sb -> regs [0] = IF1632_Saved16_sp & 0xffff;
-	sb -> regs [1] = IF1632_Saved16_bp & 0xffff;
-	sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
-	sb -> regs [3] = IF1632_Saved32_esp;
-	sb -> regs [4] = IF1632_Saved32_ebp;
-	memcpy (sb -> stack_part, CURRENT_STACK16, STACK_DEPTH_16);
-	tmp_jmp = &sb -> buffer;
-	*((struct special_buffer **)cbuf) = sb;
-	
-	if ((retval = setjmp (*tmp_jmp)))
-	{
-		IF1632_Saved16_sp = sb -> regs [0] & 0xffff;
-		IF1632_Saved16_bp = sb -> regs [1] & 0xffff;
-		IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
-		IF1632_Saved32_esp = sb -> regs [3];
-		IF1632_Saved32_ebp = sb -> regs [4];
+    dprintf_catch( stddeb, "Catch: buf=%p ss:sp=%04x:%04x\n",
+                   lpbuf, IF1632_Saved16_ss, IF1632_Saved16_sp );
 
-		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);
-		return (retval);
-	} else {
-		dprintf_catch (stddeb, "Will somtime get thrown here: %d\n", 
-			(int) sb);
-		return (retval);
-	}
+    /* Note: we don't save the current ss, as the catch buffer is */
+    /* only 9 words long. Hopefully no one will have the silly    */
+    /* idea to change the current stack before calling Throw()... */
+
+    lpbuf[0] = IF1632_Saved16_sp;
+    lpbuf[1] = LOWORD(IF1632_Saved32_esp);
+    lpbuf[2] = HIWORD(IF1632_Saved32_esp);
+    lpbuf[3] = pFrame->saved_ss;
+    lpbuf[4] = pFrame->saved_sp;
+    lpbuf[5] = pFrame->ds;
+    lpbuf[6] = pFrame->bp;
+    lpbuf[7] = pFrame->ip;
+    lpbuf[8] = pFrame->cs;
+    return 0;
 }
 
-void Throw (LPCATCHBUF cbuf, int val)
+
+/**********************************************************************
+ *	     Throw    (KERNEL.56)
+ */
+int Throw( LPCATCHBUF lpbuf, int retval )
 {
-	sb = *((struct special_buffer **)cbuf);
-	dprintf_catch (stddeb, "Throwing to: %d\n", (int) sb);
-	longjmp (sb -> buffer, val);
+    STACK16FRAME *pFrame;
+
+    dprintf_catch( stddeb, "Throw: buf=%p val=%04x ss:sp=%04x:%04x\n",
+                   lpbuf, retval, IF1632_Saved16_ss, IF1632_Saved16_sp );
+
+    IF1632_Saved16_sp  = lpbuf[0] - sizeof(WORD);
+    IF1632_Saved32_esp = MAKELONG( lpbuf[1], lpbuf[2] );
+    pFrame = CURRENT_STACK16;
+    pFrame->saved_ss   = lpbuf[3];
+    pFrame->saved_sp   = lpbuf[4];
+    pFrame->ds         = lpbuf[5];
+    pFrame->bp         = lpbuf[6];
+    pFrame->ip         = lpbuf[7];
+    pFrame->cs         = lpbuf[8];
+    return retval;
 }
+
+
 #endif /* !WINELIB */
diff --git a/if1632/commdlg.spec b/if1632/commdlg.spec
index d988e11..ab78653 100644
--- a/if1632/commdlg.spec
+++ b/if1632/commdlg.spec
@@ -1,8 +1,5 @@
-# $Id: commdlg.spec,v 1.3 1994/20/08 04:04:21 root Exp root $
-#
 name	commdlg
 id	14
-length	31
 
   1   pascal  GETOPENFILENAME(ptr) GetOpenFileName
   2   pascal  GETSAVEFILENAME(ptr) GetSaveFileName
diff --git a/if1632/compobj.spec b/if1632/compobj.spec
index 06618a8..248eecf 100644
--- a/if1632/compobj.spec
+++ b/if1632/compobj.spec
@@ -1,103 +1,102 @@
 name	compobj
 id	22
-length	163
 
-#1 COBUILDVERSION
-#2 COINITIALIZE
-#3 COUNINITIALIZE
-#4 COGETMALLOC
-#5 COREGISTERCLASSOBJECT
-#6 COREVOKECLASSOBJECT
-#7 COGETCLASSOBJECT
-#8 COMARSHALINTERFACE
-#9 COUNMARSHALINTERFACE
-#10 COLOADLIBRARY
-#11 COFREELIBRARY
-#12 COFREEALLLIBRARIES
-#13 COCREATEINSTANCE
-#14 STRINGFROMIID
+1 stub COBUILDVERSION
+2 stub COINITIALIZE
+3 stub COUNINITIALIZE
+4 stub COGETMALLOC
+5 stub COREGISTERCLASSOBJECT
+6 stub COREVOKECLASSOBJECT
+7 stub COGETCLASSOBJECT
+8 stub COMARSHALINTERFACE
+9 stub COUNMARSHALINTERFACE
+10 stub COLOADLIBRARY
+11 stub COFREELIBRARY
+12 stub COFREEALLLIBRARIES
+13 stub COCREATEINSTANCE
+14 stub STRINGFROMIID
 15 pascal CoDisconnectObject(ptr long) CoDisconnectObject
-#16 CORELEASEMARSHALDATA
-#17 COFREEUNUSEDLIBRARIES
-#18 ISEQUALGUID
-#19 STRINGFROMCLSID
-#20 CLSIDFROMSTRING
-#21 ISVALIDPTRIN
-#22 ISVALIDPTROUT
-#23 ISVALIDINTERFACE
-#24 ISVALIDIID
-#25 RESULTFROMSCODE
-#26 GETSCODE
-#27 COREGISTERMESSAGEFILTER
-#28 COISHANDLERCONNECTED
+16 stub CORELEASEMARSHALDATA
+17 stub COFREEUNUSEDLIBRARIES
+18 stub ISEQUALGUID
+19 stub STRINGFROMCLSID
+20 stub CLSIDFROMSTRING
+21 stub ISVALIDPTRIN
+22 stub ISVALIDPTROUT
+23 stub ISVALIDINTERFACE
+24 stub ISVALIDIID
+25 stub RESULTFROMSCODE
+26 stub GETSCODE
+27 stub COREGISTERMESSAGEFILTER
+28 stub COISHANDLERCONNECTED
 #29 WEP
-#30 COFILETIMETODOSDATETIME
-#31 CODOSDATETIMETOFILETIME
-#32 COMARSHALHRESULT
-#33 COUNMARSHALHRESULT
-#34 COGETCURRENTPROCESS
+30 stub COFILETIMETODOSDATETIME
+31 stub CODOSDATETIMETOFILETIME
+32 stub COMARSHALHRESULT
+33 stub COUNMARSHALHRESULT
+34 stub COGETCURRENTPROCESS
 #35 ___EXPORTEDSTUB
-#36 COISOLE1CLASS
-#37 _GUID_NULL
-#38 _IID_IUNKNOWN
-#39 _IID_ICLASSFACTORY
-#40 _IID_IMALLOC
-#41 _IID_IMARSHAL
-#42 _IID_IRPCCHANNEL
-#43 _IID_IRPCSTUB
-#44 _IID_ISTUBMANAGER
-#45 _IID_IRPCPROXY
-#46 _IID_IPROXYMANAGER
-#47 _IID_IPSFACTORY
-#48 _IID_ILOCKBYTES
-#49 _IID_ISTORAGE
-#50 _IID_ISTREAM
-#51 _IID_IENUMSTATSTG
-#52 _IID_IBINDCTX
-#53 _IID_IMONIKER
-#54 _IID_IRUNNINGOBJECTTABLE
-#55 _IID_IINTERNALMONIKER
-#56 _IID_IROOTSTORAGE
-#57 _IID_IDFRESERVED1
-#58 _IID_IDFRESERVED2
-#59 _IID_IDFRESERVED3
-#60 _IID_IMESSAGEFILTER
-#61 CLSIDFROMPROGID
-#62 PROGIDFROMCLSID
-#63 COLOCKOBJECTEXTERNAL
-#64 _CLSID_STDMARSHAL
-#65 COGETTREATASCLASS
-#66 COTREATASCLASS
-#67 COGETSTANDARDMARSHAL
-#68 PROPAGATERESULT
-#69 IIDFROMSTRING
-#70 _IID_ISTDMARSHALINFO
-#71 COCREATESTANDARDMALLOC
-#72 _IID_IEXTERNALCONNECTION
-#73 COCREATEGUID
-#75 FNASSERT
-#76 STRINGFROMGUID2
-#77 COGETCLASSEXT
-#78 OLE1CLASSFROMCLSID2
-#79 CLSIDFROMOLE1CLASS
-#80 COOPENCLASSKEY
-#81 GUIDFROMSTRING
-#82 COFILETIMENOW
-#83 REMALLOCOID
-#84 REMFREEOID
-#85 REMCREATEREMOTEHANDLER
-#86 REMCONNECTTOOBJECT
-#87 REMGETINFOFORCID
-#88 LRPCCALL
-#89 LRPCDISPATCH
-#90 LRPCREGISTERMONITOR
-#91 LRPCREVOKEMONITOR
-#92 LRPCGETTHREADWINDOW
-#93 TIMERCALLBACKPROC
-#94 LOOKUPETASK
-#95 SETETASK
-#96 LRPCFREEMONITORDATA
-#97 REMLOOKUPSHUNK
+36 stub COISOLE1CLASS
+37 stub _GUID_NULL
+38 stub _IID_IUNKNOWN
+39 stub _IID_ICLASSFACTORY
+40 stub _IID_IMALLOC
+41 stub _IID_IMARSHAL
+42 stub _IID_IRPCCHANNEL
+43 stub _IID_IRPCSTUB
+44 stub _IID_ISTUBMANAGER
+45 stub _IID_IRPCPROXY
+46 stub _IID_IPROXYMANAGER
+47 stub _IID_IPSFACTORY
+48 stub _IID_ILOCKBYTES
+49 stub _IID_ISTORAGE
+50 stub _IID_ISTREAM
+51 stub _IID_IENUMSTATSTG
+52 stub _IID_IBINDCTX
+53 stub _IID_IMONIKER
+54 stub _IID_IRUNNINGOBJECTTABLE
+55 stub _IID_IINTERNALMONIKER
+56 stub _IID_IROOTSTORAGE
+57 stub _IID_IDFRESERVED1
+58 stub _IID_IDFRESERVED2
+59 stub _IID_IDFRESERVED3
+60 stub _IID_IMESSAGEFILTER
+61 stub CLSIDFROMPROGID
+62 stub PROGIDFROMCLSID
+63 stub COLOCKOBJECTEXTERNAL
+64 stub _CLSID_STDMARSHAL
+65 stub COGETTREATASCLASS
+66 stub COTREATASCLASS
+67 stub COGETSTANDARDMARSHAL
+68 stub PROPAGATERESULT
+69 stub IIDFROMSTRING
+70 stub _IID_ISTDMARSHALINFO
+71 stub COCREATESTANDARDMALLOC
+72 stub _IID_IEXTERNALCONNECTION
+73 stub COCREATEGUID
+75 stub FNASSERT
+76 stub STRINGFROMGUID2
+77 stub COGETCLASSEXT
+78 stub OLE1CLASSFROMCLSID2
+79 stub CLSIDFROMOLE1CLASS
+80 stub COOPENCLASSKEY
+81 stub GUIDFROMSTRING
+82 stub COFILETIMENOW
+83 stub REMALLOCOID
+84 stub REMFREEOID
+85 stub REMCREATEREMOTEHANDLER
+86 stub REMCONNECTTOOBJECT
+87 stub REMGETINFOFORCID
+88 stub LRPCCALL
+89 stub LRPCDISPATCH
+90 stub LRPCREGISTERMONITOR
+91 stub LRPCREVOKEMONITOR
+92 stub LRPCGETTHREADWINDOW
+93 stub TIMERCALLBACKPROC
+94 stub LOOKUPETASK
+95 stub SETETASK
+96 stub LRPCFREEMONITORDATA
+97 stub REMLOOKUPSHUNK
 #100 ??0CARRAYFVALUE@@REC@KI@Z
 #101 ??1CARRAYFVALUE@@REC@XZ
 #102 ?ASSERTVALID@CARRAYFVALUE@@RFCXXZ
diff --git a/if1632/ddeml.spec b/if1632/ddeml.spec
new file mode 100644
index 0000000..d585ef5
--- /dev/null
+++ b/if1632/ddeml.spec
@@ -0,0 +1,32 @@
+name	ddeml
+id	25
+
+2 stub DdeInitialize #(ptr segptr long long) DdeInitialize
+3 stub DdeUnInitialize #(long) DdeUnInitialize
+4 stub DdeConnectList #(long word word word ptr) DdeConnectList
+5 stub DdeQueryNextServer #(word word) DdeQueryNextServer
+6 stub DdeDisconnectList #(word) DdeDisconnectList
+7 stub DdeConnect #(long word word ptr) DdeConnect
+8 stub DdeDisconnect #(word) DdeDisconnect
+9 stub DdeQueryConvInfo #(word long ptr) DdeQueryConvInfo
+10 stub DdeSetUserHandle #(word long long) DdeSetUserHandle
+11 stub DdeClientTransaction #(ptr long word word word word long ptr) DdeClientTransaction
+12 stub DdeAbandonTransaction #(long word long) DdeAbandonTransaction
+13 stub DdePostAdvise #(long word word) DdePostAdvise
+14 stub DdeCreateDataHandle #(long ptr long long word word word) DdeCreateDataHandle
+15 stub DdeAddData #(word ptr long long) DdeAddData
+16 stub DdeGetData #(word ptr long long) DdeGetData
+17 stub DdeAccessData #(word ptr) DdeAccessData
+18 stub DdeUnaccessData #(word) DdeUnaccessData
+19 stub DdeFreeDataHandle #(word) DdeFreeDataHandle
+20 stub DdeGetLastError #(long) DdeGetLastError
+21 stub DdeCreateStringHandle #(long ptr word) DdeCreateStringHandle
+22 stub DdeFreeStringHandle #(long word) DdeFreeStringHandle
+23 stub   DdeQueryString #(long word ptr long word) DdeQueryString
+24 stub DdeKeepStringHandle #(long word) DdeKeepStringHandle
+
+26 stub DdeEnableCallback #(long word word) DdeEnableCallback
+27 stub DdeNameService #(long word word word)
+
+36 stub DdeCmpStringHandles #(word word) DdeCmpStringHandles
+37 stub DdeReconnect #(word) DdeReconnect
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 4389097..a514fc6 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -1,8 +1,5 @@
-# $Id: gdi.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	gdi
 id	3
-length	490
 
 1   pascal SetBkColor(word long) SetBkColor
 2   pascal16 SetBkMode(word word) SetBkMode
@@ -50,7 +47,7 @@
 38  pascal Escape(word word word ptr ptr) Escape
 39  pascal16 RestoreDC(word s_word) RestoreDC
 40  pascal16 FillRgn(word word word) FillRgn
-#41  pascal FrameRgn
+41  stub FrameRgn
 42  pascal16 InvertRgn(word word) InvertRgn
 43  pascal16 PaintRgn(word word) PaintRgn
 44  pascal16 SelectClipRgn(word word) SelectClipRgn
@@ -80,7 +77,7 @@
 68  pascal16 DeleteDC(word) DeleteDC
 69  pascal16 DeleteObject(word) DeleteObject
 70  pascal16 EnumFonts(word ptr segptr long) EnumFonts
-71  pascal16 EnumObjects(word word ptr long) EnumObjects
+71  pascal16 EnumObjects(word word segptr long) EnumObjects
 72  pascal16 EqualRgn(word word) EqualRgn
 73  pascal16 ExcludeVisRect(word s_word s_word s_word s_word) ExcludeVisRect
 74  pascal GetBitmapBits(word long ptr) GetBitmapBits
@@ -138,84 +135,84 @@
 148 pascal SetBrushOrg(word s_word s_word) SetBrushOrg
 149 pascal GetBrushOrg(word) GetBrushOrg
 150 pascal16 UnrealizeObject(word) UnrealizeObject
-#151 pascal CopyMetaFile
+151 stub CopyMetaFile
 153 pascal16 CreateIC(ptr ptr ptr ptr) CreateIC
 154 pascal GetNearestColor(word long) GetNearestColor
-#155 pascal QueryAbort
+155 stub QueryAbort
 156 pascal16 CreateDiscardableBitmap(word word word) CreateDiscardableBitmap
-#159 pascal GetMetaFileBits
-#160 pascal SetMetaFileBits
+159 stub GetMetaFileBits
+160 stub SetMetaFileBits
 161 pascal16 PtInRegion(word s_word s_word) PtInRegion
 162 pascal GetBitmapDimension(word) GetBitmapDimension
 163 pascal SetBitmapDimension(word s_word s_word) SetBitmapDimension
-#169 pascal IsDCDirty
-#170 pascal SetDCStatus
+169 stub IsDCDirty
+170 stub SetDCStatus
 172 pascal16 SetRectRgn(word s_word s_word s_word s_word) SetRectRgn
 173 pascal16 GetClipRgn(word) GetClipRgn
-#175 pascal EnumMetaFile
+175 stub EnumMetaFile
 176 pascal16 PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord
 179 pascal16 GetDCState(word) GetDCState
 180 pascal16 SetDCState(word word) SetDCState
 181 pascal16 RectInRegionOld(word ptr) RectInRegion
-#190 pascal SetDCHook
-#191 pascal GetDCHook
-#192 pascal SetHookFlags
-#193 pascal SetBoundsRect
-#194 pascal GetBoundsRect
-#195 pascal SelectBitmap
-#196 pascal SetMetaFileBitsBetter
-#201 pascal DMBITBLT
-#202 pascal DMCOLORINFO
-#206 pascal DMENUMDFONTS
-#207 pascal DMENUMOBJ
-#208 pascal DMOUTPUT
-#209 pascal DMPIXEL
-#210 pascal DMREALIZEOBJECT
-#211 pascal DMSTRBLT
-#212 pascal DMSCANLR
-#213 pascal BRUTE
-#214 pascal DMEXTTEXTOUT
-#215 pascal DMGETCHARWIDTH
-#216 pascal DMSTRETCHBLT
-#217 pascal DMDIBBITS
-#218 pascal DMSTRETCHDIBITS
-#219 pascal DMSETDIBTODEV
-#220 pascal DMTRANSPOSE
-#230 pascal CREATEPQ
-#231 pascal MINPQ
-#232 pascal EXTRACTPQ
-#233 pascal INSERTPQ
-#234 pascal SIZEPQ
-#235 pascal DELETEPQ
-#240 pascal OPENJOB
-#241 pascal WRITESPOOL
-#242 pascal WRITEDIALOG
-#243 pascal CLOSEJOB
-#244 pascal DELETEJOB
-#245 pascal GETSPOOLJOB
-#246 pascal STARTSPOOLPAGE
-#247 pascal ENDSPOOLPAGE
-#248 pascal QUERYJOB
+190 stub SetDCHook
+191 stub GetDCHook
+192 stub SetHookFlags
+193 stub SetBoundsRect
+194 stub GetBoundsRect
+195 stub SelectBitmap
+196 stub SetMetaFileBitsBetter
+201 stub DMBITBLT
+202 stub DMCOLORINFO
+206 stub DMENUMDFONTS
+207 stub DMENUMOBJ
+208 stub DMOUTPUT
+209 stub DMPIXEL
+210 stub DMREALIZEOBJECT
+211 stub DMSTRBLT
+212 stub DMSCANLR
+213 stub BRUTE
+214 stub DMEXTTEXTOUT
+215 stub DMGETCHARWIDTH
+216 stub DMSTRETCHBLT
+217 stub DMDIBBITS
+218 stub DMSTRETCHDIBITS
+219 stub DMSETDIBTODEV
+220 stub DMTRANSPOSE
+230 stub CREATEPQ
+231 stub MINPQ
+232 stub EXTRACTPQ
+233 stub INSERTPQ
+234 stub SIZEPQ
+235 stub DELETEPQ
+240 stub OPENJOB
+241 stub WRITESPOOL
+242 stub WRITEDIALOG
+243 stub CLOSEJOB
+244 stub DELETEJOB
+245 stub GetSpoolJob
+246 stub StartSpoolPage
+247 stub EndSpoolPage
+248 stub QueryJob
 250 pascal16 Copy(ptr ptr word) Copy
-#253 pascal DeleteSpoolPage
-#254 pascal SpoolFile
-#300 pascal ENGINEENUMERATEFONT
-#301 pascal ENGINEDELETEFONT
-#302 pascal ENGINEREALIZEFONT
-#303 pascal ENGINEGETCHARWIDTH
-#304 pascal ENGINESETFONTCONTEXT
-#305 pascal ENGINEGETGLYPHBMP
-#306 pascal ENGINEMAKEFONTDIR
-#307 pascal GETCHARABCWIDTHS
-#308 pascal GETOUTLINETEXTMETRICS
-#309 pascal GETGLYPHOUTLINE
-#310 pascal CREATESCALABLEFONTRESOURCE
-#311 pascal GETFONTDATA
-#312 pascal CONVERTOUTLINEFONTFILE
+253 stub DeleteSpoolPage
+254 stub SpoolFile
+300 stub ENGINEENUMERATEFONT
+301 stub ENGINEDELETEFONT
+302 stub ENGINEREALIZEFONT
+303 stub ENGINEGETCHARWIDTH
+304 stub ENGINESETFONTCONTEXT
+305 stub ENGINEGETGLYPHBMP
+306 stub ENGINEMAKEFONTDIR
+307 stub GetCharABCWidths
+308 stub GetOutLineTextMetrics
+309 stub GetGlyphOutLine
+310 stub CreateScalableFontResource
+311 stub GetFontData
+312 stub ConvertOutLineFontFile
 313 pascal16 GetRasterizerCaps(ptr word) GetRasterizerCaps
-#314 pascal ENGINEEXTTEXTOUT
+314 stub EngineExtTextOut
 330 pascal16 EnumFontFamilies(word ptr segptr long) EnumFontFamilies
-#332 pascal GETKERNINGPAIRS
+332 stub GetKerningPairs
 345 pascal16 GetTextAlign(word) GetTextAlign
 346 pascal16 SetTextAlign(word word) SetTextAlign
 348 pascal16 Chord(word s_word s_word s_word s_word s_word s_word
@@ -223,39 +220,39 @@
 349 pascal SetMapperFlags(word word) SetMapperFlags
 350 pascal16 GetCharWidth(word word word ptr) GetCharWidth
 351 pascal16 ExtTextOut(word s_word s_word word ptr ptr s_word ptr) ExtTextOut
-#352 pascal GETPHYSICALFONTHANDLE
-#353 pascal GETASPECTRATIOFILTER
-#354 pascal SHRINKGDIHEAP
+352 stub GetPhysicalFontHandle
+353 stub GetAspectRatioFilter
+354 stub ShrinkGDIHeap
 360 pascal16 CreatePalette(ptr) CreatePalette
 361 pascal16 GDISelectPalette(word word) GDISelectPalette
 362 pascal16 GDIRealizePalette(word) GDIRealizePalette
 363 pascal16 GetPaletteEntries(word word word ptr) GetPaletteEntries
 364 pascal16 SetPaletteEntries(word word word ptr) SetPaletteEntries
 365 pascal16 RealizeDefaultPalette(word) RealizeDefaultPalette
-#366 pascal UPDATECOLORS
-#367 pascal ANIMATEPALETTE
-#368 pascal RESIZEPALETTE
+366 stub UpdateColors
+367 stub AnimatePalette
+368 stub ResizePalette
 370 pascal16 GetNearestPaletteIndex(word long) GetNearestPaletteIndex
 372 pascal16 ExtFloodFill(word s_word s_word long word) ExtFloodFill
 375 pascal16 GetSystemPaletteEntries(word word word ptr)
              GetSystemPaletteEntries
-#376 pascal RESETDC
-#377 pascal STARTDOC
-#378 pascal ENDDOC
-#379 pascal STARTPAGE
-#380 pascal ENDPAGE
-#381 pascal SETABORTPROC
-#382 pascal ABORTDOC
-#400 pascal FASTWINDOWFRAME
-#401 pascal GDIMOVEBITMAP
-#403 pascal GDIINIT2
-#405 pascal FINALGDIINIT
-#407 pascal CREATEUSERBITMAP
-#409 pascal CREATEUSERDISCARDABLEBITMAP
-#410 pascal ISVALIDMETAFILE
+376 stub ResetDC
+377 stub STARTDOC
+378 stub ENDDOC
+379 stub STARTPAGE
+380 stub ENDPAGE
+381 stub SETABORTPROC
+382 stub ABORTDOC
+400 stub FASTWINDOWFRAME
+401 stub GDIMOVEBITMAP
+403 stub GDIINIT2
+405 stub FINALGDIINIT
+407 stub CREATEUSERBITMAP
+409 stub CREATEUSERDISCARDABLEBITMAP
+410 stub ISVALIDMETAFILE
 411 pascal16 GetCurLogFont(word) GetCurLogFont
-#412 pascal ISDCCURRENTPALETTE
-#439 pascal STRETCHDIBITS
+412 stub IsDCCurrentPalette
+439 stub StretchDIBits
 440 pascal16 SetDIBits(word word word word ptr ptr word) SetDIBits
 441 pascal16 GetDIBits(word word word word ptr ptr word) GetDIBits
 442 pascal16 CreateDIBitmap(word ptr long ptr ptr word) CreateDIBitmap
@@ -264,18 +261,18 @@
 444 pascal16 CreateRoundRectRgn(s_word s_word s_word s_word s_word s_word)
              CreateRoundRectRgn
 445 pascal16 CreateDIBPatternBrush(word word) CreateDIBPatternBrush
-#449 pascal DEVICECOLORMATCH
+449 stub DEVICECOLORMATCH
 450 pascal16 PolyPolygon(word ptr ptr word) PolyPolygon
 451 pascal16 CreatePolyPolygonRgn(ptr ptr word word) CreatePolyPolygonRgn
-#452 pascal GDISEEGDIDO
-#460 pascal GDITASKTERMINATION
+452 stub GDISEEGDIDO
+460 stub GDITASKTERMINATION
 461 return SetObjectOwner 4 0
 462 pascal16 IsGDIObject(word) IsGDIObject
-#463 pascal MAKEOBJECTPRIVATE
-#464 pascal FIXUPBOGUSPUBLISHERMETAFILE
+463 stub MAKEOBJECTPRIVATE
+464 stub FIXUPBOGUSPUBLISHERMETAFILE
 465 pascal16 RectVisible(word ptr) RectVisible
 466 pascal16 RectInRegion(word ptr) RectInRegion
-#467 pascal UNICODETOANSI
+467 stub UNICODETOANSI
 468 pascal16 GetBitmapDimensionEx(word ptr) GetBitmapDimensionEx
 469 pascal16 GetBrushOrgEx(word ptr) GetBrushOrgEx
 470 pascal16 GetCurrentPositionEx(word ptr) GetCurrentPositionEx
@@ -296,4 +293,4 @@
              ScaleViewportExtEx
 485 pascal16 ScaleWindowExtEx(word s_word s_word s_word s_word ptr)
              ScaleWindowExtEx
-#486 pascal GETASPECTRATIOFILEREX
+486 stub GETASPECTRATIOFILEREX
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index bdaa2ef..89081f4 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -1,11 +1,8 @@
-# $Id: kernel.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	kernel
 id	1
-length	415
 
-#1 FATALEXIT
-#2 EXITKERNEL
+1   stub FatalExit
+2   stub ExitKernel
 3   pascal GetVersion() GetVersion
 4   pascal16 LocalInit(word word word) LocalInit
 5   pascal16 LocalAlloc(word word) LocalAlloc
@@ -29,18 +26,18 @@
 23  pascal16 LockSegment(word) LockSegment
 24  pascal16 UnlockSegment(word) UnlockSegment
 25  pascal GlobalCompact(long) GlobalCompact
-#26 GLOBALFREEALL
-#28 GLOBALMASTERHANDLE
-29  return Yield 0 0
-30  pascal WaitEvent(word) KERNEL_WaitEvent
-#31 POSTEVENT
-#32 SETPRIORITY
-#33 LOCKCURRENTTASK
+26  pascal16 GlobalFreeAll(word) GlobalFreeAll
+28  stub GlobalMasterHandle
+29  pascal16 Yield() Yield
+30  pascal16 WaitEvent(word) WaitEvent
+31  pascal16 PostEvent(word) PostEvent
+32  pascal16 SetPriority(word s_word) SetPriority
+33  stub LockCurrentTask
 34  pascal SetTaskQueue(word word) SetTaskQueue
-35  pascal GetTaskQueue(word) GetTaskQueue
-36  pascal16 GetCurrentTask() GetCurrentTask
-37  pascal16 GetCurrentPDB() GetCurrentPDB
-#38 SETTASKSIGNALPROC
+35  pascal16 GetTaskQueue(word) GetTaskQueue
+36  pascal GetCurrentTask() GetCurrentTask
+37  pascal GetCurrentPDB() GetCurrentPDB
+38  stub SetTaskSignalProc
 41  return EnableDos 0 0
 42  return DisableDos 0 0
 45  pascal16 LoadModule(ptr ptr) LoadModule
@@ -48,13 +45,13 @@
 47  pascal16 GetModuleHandle(ptr) GetModuleHandle
 48  pascal16 GetModuleUsage(word) GetModuleUsage
 49  pascal16 GetModuleFileName(word ptr s_word) GetModuleFileName
-50  pascal GetProcAddress(word ptr) GetProcAddress
+50  pascal GetProcAddress(word segptr) GetProcAddress
 51  pascal MakeProcInstance(segptr word) MakeProcInstance
-52  pascal FreeProcInstance(segptr) FreeProcInstance
-#53 CALLPROCINSTANCE
-#54 pascal16 GETINSTANCEDATA
+52  pascal16 FreeProcInstance(segptr) FreeProcInstance
+53  stub CallProcInstance
+54  stub GetInstanceData
 55  pascal16 Catch(ptr) Catch 
-56  pascal Throw(ptr word) Throw
+56  pascal16 Throw(ptr word) Throw
 57  pascal16 GetProfileInt(ptr ptr word) GetProfileInt
 58  pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString
 59  pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString
@@ -65,7 +62,7 @@
 64  pascal16 AccessResource(word word) AccessResource
 65  pascal SizeofResource(word word) SizeofResource
 66  pascal16 AllocResource(word word long) AllocResource
-#67 SETRESOURCEHANDLER
+67  stub SetResourceHandler
 68  pascal16 InitAtomTable(word) InitAtomTable
 69  pascal16 FindAtom(ptr) FindAtom
 70  pascal16 AddAtom(ptr) AddAtom
@@ -73,8 +70,8 @@
 72  pascal16 GetAtomName(word ptr word) GetAtomName
 73  pascal16 GetAtomHandle(word) GetAtomHandle
 74  pascal16 OpenFile(ptr ptr word) OpenFile
-#75 OPENPATHNAME
-#76 DELETEPATHNAME
+75  stub OpenPathName
+76  stub DeletePathName
 #77 RESERVED1
 #78 RESERVED2
 #79 RESERVED3
@@ -91,40 +88,40 @@
 90  pascal16 lstrlen(ptr) lstrlen
 91  register InitTask() KERNEL_InitTask
 92  pascal16 GetTempDrive(byte) GetTempDrive
-93 pascal16 GetCodeHandle(ptr) GetCodeHandle
-#94 DEFINEHANDLETABLE
+93  pascal16 GetCodeHandle(segptr) GetCodeHandle
+94  stub DefineHandleTable
 95  pascal16 LoadLibrary(ptr) LoadLibrary
 96  pascal16 FreeLibrary(word) FreeLibrary
 97  pascal16 GetTempFileName(byte ptr word ptr) GetTempFileName
-#98 GETLASTDISKCHANGE
-#99 GETLPERRMODE
-#100 VALIDATECODESEGMENTS
-#101 NOHOOKDOSCALL
+98  stub GetLastDiskChange
+99  stub GetLPErrMode
+100 stub ValidateCodeSegments
+101 stub NoHookDosCall
 102 register DOS3Call() DOS3Call
-#103 NETBIOSCALL
-#104 GETCODEINFO
-#105 GETEXEVERSION
+103 stub NetBiosCall
+104 stub GetCodeInfo
+105 stub GetExeVersion
 106 pascal SetSwapAreaSize(word) SetSwapAreaSize
 107 pascal SetErrorMode(word) SetErrorMode
-#108 SWITCHSTACKTO
-#109 SWITCHSTACKBACK
-#110 PATCHCODEHANDLE
+108 stub SwitchStackTo
+109 stub SwitchStackBack
+110 stub PatchCodeHandle
 111 pascal GlobalWire(word) GlobalWire
 112 pascal16 GlobalUnWire(word) GlobalUnWire
 113 equate __AHSHIFT 3
 114 equate __AHINCR 8
 115 pascal OutputDebugString(ptr) OutputDebugString
-#116 INITLIB
-117 return OldYield 0 0
-#118 GETTASKQUEUEDS
-#119 GETTASKQUEUEES
-#120 UNDEFDYNLINK
+116 stub InitLib
+117 pascal16 OldYield() OldYield
+118 stub GetTaskQueueDS
+119 stub GetTaskQueueES
+120 stub UndefDynLink
 121 pascal16 LocalShrink(word word) LocalShrink
-#122 ISTASKLOCKED
-#123 KBDRST
+122 stub IsTaskLocked
+123 stub KbdRst
 124 return EnableKernel 0 0
 125 return DisableKernel 0 0
-#126 MEMORYFREED
+126 stub MemoryFreed
 127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt
 128 pascal16 GetPrivateProfileString(ptr ptr ptr ptr s_word ptr)
              GetPrivateProfileString
@@ -133,33 +130,33 @@
 130 pascal FileCDR(ptr) FileCDR
 131 pascal GetDOSEnvironment() GetDOSEnvironment
 132 pascal GetWinFlags() GetWinFlags
-#133 GETEXEPTR
+133 pascal16 GetExePtr(word) GetExePtr
 134 pascal16 GetWindowsDirectory(ptr word) GetWindowsDirectory
 135 pascal16 GetSystemDirectory(ptr word) GetSystemDirectory
 136 pascal16 GetDriveType(byte) GetDriveType
 137 pascal FatalAppExit(word ptr) FatalAppExit
 138 pascal GetHeapSpaces(word) GetHeapSpaces
-#139 DOSIGNAL
-#140 SETSIGHANDLER
-#141 INITTASK1
-150 return DirectedYield 2 0
-#151 WINOLDAPCALL
+139 stub DoSignal
+140 stub SetSigHandler
+141 stub InitTask1
+150 pascal16 DirectedYield(word) DirectedYield
+151 stub WinOldApCall
 152 pascal16 GetNumTasks() GetNumTasks
 154 return GlobalNotify 4 0
-#155 GETTASKDS
-#156 LIMITEMSPAGES
-#157 GETCURPID
-#158 ISWINOLDAPTASK
-#159 GLOBALHANDLENORIP
-#160 EMSCOPY
+155 pascal16 GetTaskDS() GetTaskDS
+156 stub LimitEMSPages
+157 return GetCurPID 4 0
+158 stub IsWinOldApTask
+159 stub GlobalHandleNoRIP
+160 stub EMSCopy
 161 pascal16 LocalCountFree() LocalCountFree
 162 pascal16 LocalHeapSize() LocalHeapSize
 163 pascal16 GlobalLRUOldest(word) GlobalLRUOldest
 164 pascal16 GlobalLRUNewest(word) GlobalLRUNewest
-#165 A20PROC
+165 stub A20Proc
 166 pascal16 WinExec(ptr word) WinExec
-#167 GETEXPWINVER
-#168 DIRECTRESALLOC
+167 stub GetExpWinVer
+168 stub DirectResAlloc
 169 pascal GetFreeSpace(word) GetFreeSpace
 170 pascal16 AllocCStoDSAlias(word) AllocCStoDSAlias
 171 pascal16 AllocDStoCSAlias(word) AllocDStoCSAlias
@@ -191,42 +188,42 @@
 197 pascal16 GlobalFix(word) GlobalFix
 198 pascal16 GlobalUnfix(word) GlobalUnfix
 199 pascal16 SetHandleCount(word) SetHandleCount
-#200 VALIDATEFREESPACES
-#201 REPLACEINST
-#202 REGISTERPTRACE
-#203 DEBUGBREAK
-#204 SWAPRECORDING
-#205 CVWBREAK
+200 stub ValidateFreeSpaces
+201 stub ReplaceInst
+202 stub RegisterPtrace
+203 stub DebugBreak
+204 stub SwapRecording
+205 stub CVWBreak
 206 pascal16 AllocSelectorArray(word) AllocSelectorArray
 207 return IsDBCSLeadByte 2 0
 310 pascal16 LocalHandleDelta(word) LocalHandleDelta
-#311 GETSETKERNELDOSPROC
-#314 DEBUGDEFINESEGMENT
+311 stub GetSetKernelDosProc
+314 stub DebugDefineSegment
 315 pascal WriteOutProfiles() sync_profiles
-#316 GETFREEMEMINFO
-#318 FATALEXITHOOK
-#319 FLUSHCACHEDFILEHANDLE
-#320 ISTASK
+316 stub GetFreeMemInfo
+318 stub FatalExitHook
+319 stub FlushCachedFileHandle
+320 pascal16 IsTask(word) IsTask
 323 return IsRomModule 2 0
-#324 LOGERROR
-#325 LOGPARAMERROR
+324 stub LogError
+325 stub LogParamError
 326 return IsRomFile 2 0
 #327 K327
-#328 _DEBUGOUTPUT
+328 stub _DebugOutput
 #329 K329
-#332 THHOOK
+332 stub THHOOK
 334 pascal16 IsBadReadPtr(segptr word) IsBadReadPtr
 335 pascal16 IsBadWritePtr(segptr word) IsBadWritePtr
 336 pascal16 IsBadCodePtr(segptr) IsBadCodePtr
 337 pascal16 IsBadStringPtr(segptr word) IsBadStringPtr
-#338 HASGPHANDLER
-#339 DIAGQUERY
-#340 DIAGOUTPUT
-#341 TOOLHELPHOOK
-#342 __GP
-#343 REGISTERWINOLDAPHOOK
-#344 GETWINOLDAPHOOKS
-#345 ISSHAREDSELECTOR
+338 stub HasGPHandler
+339 stub DiagQuery
+340 stub DiagOutput
+341 stub ToolHelpHook
+342 stub __GP
+343 stub RegisterWinOldApHook
+344 stub GetWinOldApHooks
+345 stub IsSharedSelector
 346 pascal16 IsBadHugeReadPtr(segptr long) IsBadHugeReadPtr
 347 pascal16 IsBadHugeWritePtr(segptr long) IsBadHugeWritePtr
 348 pascal hmemcpy(ptr ptr long) hmemcpy
@@ -234,8 +231,8 @@
 350 pascal16 _hwrite(word ptr long) _hwrite
 #351 BUNNY_351
 353 pascal lstrcpyn(segptr segptr word) lstrcpyn
-#354 GETAPPCOMPATFLAGS
-#355 GETWINDEBUGINFO
-#356 SETWINDEBUGINFO
+354 stub GetAppCompatFlags
+355 stub GetWinDebugInfo
+356 stub SetWinDebugInfo
 403 pascal16 FarSetOwner(word word) FarSetOwner
 404 pascal16 FarGetOwner(word) FarGetOwner
diff --git a/if1632/keyboard.spec b/if1632/keyboard.spec
index a23cf06..afea764 100644
--- a/if1632/keyboard.spec
+++ b/if1632/keyboard.spec
@@ -1,8 +1,5 @@
-# $Id: keyboard.spec,v 1.1 1993/09/10 05:32:12 scott Exp $
-#
 name	keyboard
 id	7
-length	137
 
 #1	pascal	Inquire
 #2	pascal	Enable
diff --git a/if1632/mmsystem.spec b/if1632/mmsystem.spec
index 9814960..8e03c21 100644
--- a/if1632/mmsystem.spec
+++ b/if1632/mmsystem.spec
@@ -1,8 +1,5 @@
-# $Id: mmsystem.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	mmsystem
 id	10
-length 1226
 
 1      pascal  MMSYSTEM_WEP(word word word ptr) MMSYSTEM_WEP
 2      pascal  SNDPLAYSOUND(ptr word) sndPlaySound
diff --git a/if1632/mouse.spec b/if1632/mouse.spec
index c387396..879ecfc 100644
--- a/if1632/mouse.spec
+++ b/if1632/mouse.spec
@@ -1,11 +1,10 @@
 name	mouse
 id	13
-length	8
 
-#1 pascal INQUIRE
-#2 pascal ENABLE
-#3 pascal DISABLE
-#4 pascal MOUSEGETINTVECT
-#5 pascal GETSETMOUSEDATA
-#6 pascal CPLAPPLET
-#7 pascal POWEREVENTPROC
+1 stub INQUIRE
+2 stub ENABLE
+3 stub DISABLE
+4 stub MOUSEGETINTVECT
+5 stub GETSETMOUSEDATA
+6 stub CPLAPPLET
+7 stub POWEREVENTPROC
diff --git a/if1632/ole2.spec b/if1632/ole2.spec
index 8d63886..8b47478 100644
--- a/if1632/ole2.spec
+++ b/if1632/ole2.spec
@@ -1,150 +1,149 @@
 name	OLE2
 id	15
-length	161
 
-#1 OLEBUILDVERSION
-#2 OLEINITIALIZE
-#3 OLEUNINITIALIZE
-#4 DLLGETCLASSOBJECT
+1 stub OLEBUILDVERSION
+2 stub OLEINITIALIZE
+3 stub OLEUNINITIALIZE
+4 stub DLLGETCLASSOBJECT
 #5 WEP
-#6 OLEQUERYLINKFROMDATA
-#7 OLEQUERYCREATEFROMDATA
-#8 OLECREATEFROMDATA
-#9 OLECREATELINKFROMDATA
-#10 OLECREATE
-#11 OLECREATELINK
-#12 OLELOAD
-#13 OLESAVE
-#14 OLERUN
+6 stub OLEQUERYLINKFROMDATA
+7 stub OLEQUERYCREATEFROMDATA
+8 stub OLECREATEFROMDATA
+9 stub OLECREATELINKFROMDATA
+10 stub OLECREATE
+11 stub OLECREATELINK
+12 stub OLELOAD
+13 stub OLESAVE
+14 stub OLERUN
 #15 ___EXPORTEDSTUB
-#16 OLEISRUNNING
-#17 OLELOCKRUNNING
-#18 READCLASSSTG
-#19 WRITECLASSSTG
-#20 READCLASSSTM
-#21 WRITECLASSSTM
-#22 BINDMONIKER
-#23 MKPARSEDISPLAYNAME
-#24 OLESAVETOSTREAM
-#25 OLELOADFROMSTREAM
-#26 CREATEBINDCTX
-#27 CREATEITEMMONIKER
-#28 CREATEFILEMONIKER
-#29 CREATEGENERICCOMPOSITE
-#30 GETRUNNINGOBJECTTABLE
-#31 OLEGETMALLOC
-#32 RELEASESTGMEDIUM
-#33 READSTRINGSTREAM
-#34 WRITESTRINGSTREAM
-#35 REGISTERDRAGDROP
-#36 REVOKEDRAGDROP
-#37 DODRAGDROP
-#38 CREATEOLEADVISEHOLDER
-#39 CREATEDATAADVISEHOLDER
-#40 OLECREATEMENUDESCRIPTOR
-#41 OLESETMENUDESCRIPTOR
-#42 OLEDESTROYMENUDESCRIPTOR
-#43 OPENORCREATESTREAM
-#44 CREATEANTIMONIKER
-#45 CREATEPOINTERMONIKER
-#46 MONIKERRELATIVEPATHTO
-#47 MONIKERCOMMONPREFIXWITH
-#48 ISACCELERATOR
-#49 OLESETCLIPBOARD
-#50 OLEGETCLIPBOARD
-#51 OLEDUPLICATEDATA
-#52 OLEGETICONOFFILE
-#53 OLEGETICONOFCLASS
-#54 CREATEILOCKBYTESONHGLOBAL
-#55 GETHGLOBALFROMILOCKBYTES
-#56 OLEMETAFILEPICTFROMICONANDLABEL
-#57 GETCLASSFILE
-#58 OLEDRAW
-#59 OLECREATEDEFAULTHANDLER
-#60 OLECREATEEMBEDDINGHELPER
-#61 OLECONVERTISTORAGETOOLESTREAMEX
-#62 OLECONVERTOLESTREAMTOISTORAGEEX
-#63 SETDOCUMENTBITSTG
-#64 GETDOCUMENTBITSTG
-#65 WRITEOLESTG
-#66 READOLESTG
-#67 OLECREATEFROMFILE
-#68 OLECREATELINKTOFILE
-#69 CREATEDATACACHE
-#70 OLECONVERTISTORAGETOOLESTREAM
-#71 OLECONVERTOLESTREAMTOISTORAGE
-#74 READFMTUSERTYPESTG
-#75 WRITEFMTUSERTYPESTG
-#76 OLEFLUSHCLIPBOARD
-#77 OLEISCURRENTCLIPBOARD
-#78 OLETRANSLATEACCELERATOR
-#79 OLEDOAUTOCONVERT
-#80 OLEGETAUTOCONVERT
-#81 OLESETAUTOCONVERT
-#82 GETCONVERTSTG
-#83 SETCONVERTSTG
-#84 CREATESTREAMONHGLOBAL
-#85 GETHGLOBALFROMSTREAM
-#86 OLESETCONTAINEDOBJECT
-#87 OLENOTEOBJECTVISIBLE
-#88 OLECREATESTATICFROMDATA
-#89 OLEREGGETUSERTYPE
-#90 OLEREGGETMISCSTATUS
-#91 OLEREGENUMFORMATETC
-#92 OLEREGENUMVERBS
-#93 OLEGETENUMFORMATETC
-#100 MAKEDEBUGSTREAM
-#104 DBGLOGOPEN
-#105 DBGLOGCLOSE
-#106 DBGLOGOUTPUTDEBUGSTRING
-#107 DBGLOGWRITE
-#108 DBGLOGTIMESTAMP
-#109 DBGLOGWRITEBANNER
-#110 DBGDUMPOBJECT
-#111 DBGISOBJECTVALID
-#112 DUMPALLOBJECTS
-#113 VALIDATEALLOBJECTS
-#114 DBGDUMPCLASSNAME
-#115 DBGDUMPEXTERNALOBJECT
-#120 _IID_IENUMUNKNOWN
-#121 _IID_IENUMSTRING
-#122 _IID_IENUMMONIKER
-#123 _IID_IENUMFORMATETC
-#124 _IID_IENUMOLEVERB
-#125 _IID_IENUMSTATDATA
-#126 _IID_IENUMGENERIC
-#127 _IID_IENUMHOLDER
-#128 _IID_IENUMCALLBACK
-#129 _IID_IPERSISTSTREAM
-#130 _IID_IPERSISTSTORAGE
-#131 _IID_IPERSISTFILE
-#132 _IID_IPERSIST
-#133 _IID_IVIEWOBJECT
-#134 _IID_IDATAOBJECT
-#135 _IID_IADVISESINK
-#136 _IID_IDATAADVISEHOLDER
-#137 _IID_IOLEADVISEHOLDER
-#138 _IID_IOLEOBJECT
-#139 _IID_IOLEINPLACEOBJECT
-#140 _IID_IOLEWINDOW
-#141 _IID_IOLEINPLACEUIWINDOW
-#142 _IID_IOLEINPLACEFRAME
-#143 _IID_IOLEINPLACEACTIVEOBJECT
-#144 _IID_IOLECLIENTSITE
-#145 _IID_IOLEINPLACESITE
-#146 _IID_IPARSEDISPLAYNAME
-#147 _IID_IOLECONTAINER
-#148 _IID_IOLEITEMCONTAINER
-#149 _IID_IOLELINK
-#150 _IID_IOLECACHE
-#151 _IID_IOLEMANAGER
-#152 _IID_IOLEPRESOBJ
-#153 _IID_IDROPSOURCE
-#154 _IID_IDROPTARGET
-#155 _IID_IDEBUG
-#156 _IID_IDEBUGSTREAM
-#157 _IID_IADVISESINK2
-#158 _IID_IVIEWOBJECT2
-#159 _IID_IOLECACHE2
-#160 _IID_IOLECACHECONTROL
-#161 _IID_IRUNNABLEOBJECT
+16 stub OLEISRUNNING
+17 stub OLELOCKRUNNING
+18 stub READCLASSSTG
+19 stub WRITECLASSSTG
+20 stub READCLASSSTM
+21 stub WRITECLASSSTM
+22 stub BINDMONIKER
+23 stub MKPARSEDISPLAYNAME
+24 stub OLESAVETOSTREAM
+25 stub OLELOADFROMSTREAM
+26 stub CREATEBINDCTX
+27 stub CREATEITEMMONIKER
+28 stub CREATEFILEMONIKER
+29 stub CREATEGENERICCOMPOSITE
+30 stub GETRUNNINGOBJECTTABLE
+31 stub OLEGETMALLOC
+32 stub RELEASESTGMEDIUM
+33 stub READSTRINGSTREAM
+34 stub WRITESTRINGSTREAM
+35 stub REGISTERDRAGDROP
+36 stub REVOKEDRAGDROP
+37 stub DODRAGDROP
+38 stub CREATEOLEADVISEHOLDER
+39 stub CREATEDATAADVISEHOLDER
+40 stub OLECREATEMENUDESCRIPTOR
+41 stub OLESETMENUDESCRIPTOR
+42 stub OLEDESTROYMENUDESCRIPTOR
+43 stub OPENORCREATESTREAM
+44 stub CREATEANTIMONIKER
+45 stub CREATEPOINTERMONIKER
+46 stub MONIKERRELATIVEPATHTO
+47 stub MONIKERCOMMONPREFIXWITH
+48 stub ISACCELERATOR
+49 stub OLESETCLIPBOARD
+50 stub OLEGETCLIPBOARD
+51 stub OLEDUPLICATEDATA
+52 stub OLEGETICONOFFILE
+53 stub OLEGETICONOFCLASS
+54 stub CREATEILOCKBYTESONHGLOBAL
+55 stub GETHGLOBALFROMILOCKBYTES
+56 stub OLEMETAFILEPICTFROMICONANDLABEL
+57 stub GETCLASSFILE
+58 stub OLEDRAW
+59 stub OLECREATEDEFAULTHANDLER
+60 stub OLECREATEEMBEDDINGHELPER
+61 stub OLECONVERTISTORAGETOOLESTREAMEX
+62 stub OLECONVERTOLESTREAMTOISTORAGEEX
+63 stub SETDOCUMENTBITSTG
+64 stub GETDOCUMENTBITSTG
+65 stub WRITEOLESTG
+66 stub READOLESTG
+67 stub OLECREATEFROMFILE
+68 stub OLECREATELINKTOFILE
+69 stub CREATEDATACACHE
+70 stub OLECONVERTISTORAGETOOLESTREAM
+71 stub OLECONVERTOLESTREAMTOISTORAGE
+74 stub READFMTUSERTYPESTG
+75 stub WRITEFMTUSERTYPESTG
+76 stub OLEFLUSHCLIPBOARD
+77 stub OLEISCURRENTCLIPBOARD
+78 stub OLETRANSLATEACCELERATOR
+79 stub OLEDOAUTOCONVERT
+80 stub OLEGETAUTOCONVERT
+81 stub OLESETAUTOCONVERT
+82 stub GETCONVERTSTG
+83 stub SETCONVERTSTG
+84 stub CREATESTREAMONHGLOBAL
+85 stub GETHGLOBALFROMSTREAM
+86 stub OLESETCONTAINEDOBJECT
+87 stub OLENOTEOBJECTVISIBLE
+88 stub OLECREATESTATICFROMDATA
+89 stub OLEREGGETUSERTYPE
+90 stub OLEREGGETMISCSTATUS
+91 stub OLEREGENUMFORMATETC
+92 stub OLEREGENUMVERBS
+93 stub OLEGETENUMFORMATETC
+100 stub MAKEDEBUGSTREAM
+104 stub DBGLOGOPEN
+105 stub DBGLOGCLOSE
+106 stub DBGLOGOUTPUTDEBUGSTRING
+107 stub DBGLOGWRITE
+108 stub DBGLOGTIMESTAMP
+109 stub DBGLOGWRITEBANNER
+110 stub DBGDUMPOBJECT
+111 stub DBGISOBJECTVALID
+112 stub DUMPALLOBJECTS
+113 stub VALIDATEALLOBJECTS
+114 stub DBGDUMPCLASSNAME
+115 stub DBGDUMPEXTERNALOBJECT
+120 stub _IID_IENUMUNKNOWN
+121 stub _IID_IENUMSTRING
+122 stub _IID_IENUMMONIKER
+123 stub _IID_IENUMFORMATETC
+124 stub _IID_IENUMOLEVERB
+125 stub _IID_IENUMSTATDATA
+126 stub _IID_IENUMGENERIC
+127 stub _IID_IENUMHOLDER
+128 stub _IID_IENUMCALLBACK
+129 stub _IID_IPERSISTSTREAM
+130 stub _IID_IPERSISTSTORAGE
+131 stub _IID_IPERSISTFILE
+132 stub _IID_IPERSIST
+133 stub _IID_IVIEWOBJECT
+134 stub _IID_IDATAOBJECT
+135 stub _IID_IADVISESINK
+136 stub _IID_IDATAADVISEHOLDER
+137 stub _IID_IOLEADVISEHOLDER
+138 stub _IID_IOLEOBJECT
+139 stub _IID_IOLEINPLACEOBJECT
+140 stub _IID_IOLEWINDOW
+141 stub _IID_IOLEINPLACEUIWINDOW
+142 stub _IID_IOLEINPLACEFRAME
+143 stub _IID_IOLEINPLACEACTIVEOBJECT
+144 stub _IID_IOLECLIENTSITE
+145 stub _IID_IOLEINPLACESITE
+146 stub _IID_IPARSEDISPLAYNAME
+147 stub _IID_IOLECONTAINER
+148 stub _IID_IOLEITEMCONTAINER
+149 stub _IID_IOLELINK
+150 stub _IID_IOLECACHE
+151 stub _IID_IOLEMANAGER
+152 stub _IID_IOLEPRESOBJ
+153 stub _IID_IDROPSOURCE
+154 stub _IID_IDROPTARGET
+155 stub _IID_IDEBUG
+156 stub _IID_IDEBUGSTREAM
+157 stub _IID_IADVISESINK2
+158 stub _IID_IVIEWOBJECT2
+159 stub _IID_IOLECACHE2
+160 stub _IID_IOLECACHECONTROL
+161 stub _IID_IRUNNABLEOBJECT
diff --git a/if1632/ole2conv.spec b/if1632/ole2conv.spec
index 9a61768..d2414bd 100644
--- a/if1632/ole2conv.spec
+++ b/if1632/ole2conv.spec
@@ -1,12 +1,12 @@
 name	ole2conv
 id	16
-length	10
-#1 GETFILTERINFO
-#2 IMPORTGR
-#3 GETFILTERPREF
-#4 IMPORTEMBEDDEDGR
-#5 QD2GDI
-#6 STATUSPROC
-#7 ENUMFONTFUNC
+
+1 stub GETFILTERINFO
+2 stub IMPORTGR
+3 stub GETFILTERPREF
+4 stub IMPORTEMBEDDEDGR
+5 stub QD2GDI
+6 stub STATUSPROC
+7 stub ENUMFONTFUNC
 #8 WEP
 #9 ___EXPORTEDSTUB
diff --git a/if1632/ole2disp.spec b/if1632/ole2disp.spec
index b4fdeba..86475f6 100644
--- a/if1632/ole2disp.spec
+++ b/if1632/ole2disp.spec
@@ -1,113 +1,113 @@
 name	ole2disp
 id	17
-length	110
-#1 DLLGETCLASSOBJECT
-#2 SYSALLOCSTRING
-#3 SYSREALLOCSTRING
-#4 SYSALLOCSTRINGLEN
-#5 SYSREALLOCSTRINGLEN
-#6 SYSFREESTRING
-#7 SYSSTRINGLEN
-#8 VARIANTINIT
-#9 VARIANTCLEAR
-#10 VARIANTCOPY
-#11 VARIANTCOPYIND
-#12 VARIANTCHANGETYPE
-#13 VARIANTTIMETODOSDATETIME
-#14 DOSDATETIMETOVARIANTTIME
-#15 SAFEARRAYCREATE
-#16 SAFEARRAYDESTROY
-#17 SAFEARRAYGETDIM
-#18 SAFEARRAYGETELEMSIZE
-#19 SAFEARRAYGETUBOUND
-#20 SAFEARRAYGETLBOUND
-#21 SAFEARRAYLOCK
-#22 SAFEARRAYUNLOCK
-#23 SAFEARRAYACCESSDATA
-#24 SAFEARRAYUNACCESSDATA
-#25 SAFEARRAYGETELEMENT
-#26 SAFEARRAYPUTELEMENT
-#27 SAFEARRAYCOPY
-#28 DISPGETPARAM
-#29 DISPGETIDSOFNAMES
-#30 DISPINVOKE
-#31 CREATEDISPTYPEINFO
-#32 CREATESTDDISPATCH
-#33 _IID_IDISPATCH
-#34 _IID_IENUMVARIANT
-#35 REGISTERACTIVEOBJECT
-#36 REVOKEACTIVEOBJECT
-#37 GETACTIVEOBJECT
-#38 SAFEARRAYALLOCDESCRIPTOR
-#39 SAFEARRAYALLOCDATA
-#40 SAFEARRAYDESTROYDESCRIPTOR
-#41 SAFEARRAYDESTROYDATA
-#42 SAFEARRAYREDIM
-#43 VARI2FROMI4
-#44 VARI2FROMR4
-#45 VARI2FROMR8
-#46 VARI2FROMCY
-#47 VARI2FROMDATE
-#48 VARI2FROMSTR
-#49 VARI2FROMDISP
-#50 VARI2FROMBOOL
-#51 VARI4FROMI2
-#52 VARI4FROMR4
-#53 VARI4FROMR8
-#54 VARI4FROMCY
-#55 VARI4FROMDATE
-#56 VARI4FROMSTR
-#57 VARI4FROMDISP
-#58 VARI4FROMBOOL
-#59 VARR4FROMI2
-#60 VARR4FROMI4
-#61 VARR4FROMR8
-#62 VARR4FROMCY
-#63 VARR4FROMDATE
-#64 VARR4FROMSTR
-#65 VARR4FROMDISP
-#66 VARR4FROMBOOL
-#67 VARR8FROMI2
-#68 VARR8FROMI4
-#69 VARR8FROMR4
-#70 VARR8FROMCY
-#71 VARR8FROMDATE
-#72 VARR8FROMSTR
-#73 VARR8FROMDISP
-#74 VARR8FROMBOOL
-#75 VARDATEFROMI2
-#76 VARDATEFROMI4
-#77 VARDATEFROMR4
-#78 VARDATEFROMR8
-#79 VARDATEFROMCY
-#80 VARDATEFROMSTR
-#81 VARDATEFROMDISP
-#82 VARDATEFROMBOOL
-#83 VARCYFROMI2
-#84 VARCYFROMI4
-#85 VARCYFROMR4
-#86 VARCYFROMR8
-#87 VARCYFROMDATE
-#88 VARCYFROMSTR
-#89 VARCYFROMDISP
-#90 VARCYFROMBOOL
-#91 VARBSTRFROMI2
-#92 VARBSTRFROMI4
-#93 VARBSTRFROMR4
-#94 VARBSTRFROMR8
-#95 VARBSTRFROMCY
-#96 VARBSTRFROMDATE
-#97 VARBSTRFROMDISP
-#98 VARBSTRFROMBOOL
-#99 VARBOOLFROMI2
-#100 VARBOOLFROMI4
-#101 VARBOOLFROMR4
-#102 VARBOOLFROMR8
-#103 VARBOOLFROMDATE
-#104 VARBOOLFROMCY
-#105 VARBOOLFROMSTR
-#106 VARBOOLFROMDISP
-#107 DOINVOKEMETHOD
-#108 VARIANTCHANGETYPEEX
+
+1 stub DLLGETCLASSOBJECT
+2 stub SYSALLOCSTRING
+3 stub SYSREALLOCSTRING
+4 stub SYSALLOCSTRINGLEN
+5 stub SYSREALLOCSTRINGLEN
+6 stub SYSFREESTRING
+7 stub SYSSTRINGLEN
+8 stub VARIANTINIT
+9 stub VARIANTCLEAR
+10 stub VARIANTCOPY
+11 stub VARIANTCOPYIND
+12 stub VARIANTCHANGETYPE
+13 stub VARIANTTIMETODOSDATETIME
+14 stub DOSDATETIMETOVARIANTTIME
+15 stub SAFEARRAYCREATE
+16 stub SAFEARRAYDESTROY
+17 stub SAFEARRAYGETDIM
+18 stub SAFEARRAYGETELEMSIZE
+19 stub SAFEARRAYGETUBOUND
+20 stub SAFEARRAYGETLBOUND
+21 stub SAFEARRAYLOCK
+22 stub SAFEARRAYUNLOCK
+23 stub SAFEARRAYACCESSDATA
+24 stub SAFEARRAYUNACCESSDATA
+25 stub SAFEARRAYGETELEMENT
+26 stub SAFEARRAYPUTELEMENT
+27 stub SAFEARRAYCOPY
+28 stub DISPGETPARAM
+29 stub DISPGETIDSOFNAMES
+30 stub DISPINVOKE
+31 stub CREATEDISPTYPEINFO
+32 stub CREATESTDDISPATCH
+33 stub _IID_IDISPATCH
+34 stub _IID_IENUMVARIANT
+35 stub REGISTERACTIVEOBJECT
+36 stub REVOKEACTIVEOBJECT
+37 stub GETACTIVEOBJECT
+38 stub SAFEARRAYALLOCDESCRIPTOR
+39 stub SAFEARRAYALLOCDATA
+40 stub SAFEARRAYDESTROYDESCRIPTOR
+41 stub SAFEARRAYDESTROYDATA
+42 stub SAFEARRAYREDIM
+43 stub VARI2FROMI4
+44 stub VARI2FROMR4
+45 stub VARI2FROMR8
+46 stub VARI2FROMCY
+47 stub VARI2FROMDATE
+48 stub VARI2FROMSTR
+49 stub VARI2FROMDISP
+50 stub VARI2FROMBOOL
+51 stub VARI4FROMI2
+52 stub VARI4FROMR4
+53 stub VARI4FROMR8
+54 stub VARI4FROMCY
+55 stub VARI4FROMDATE
+56 stub VARI4FROMSTR
+57 stub VARI4FROMDISP
+58 stub VARI4FROMBOOL
+59 stub VARR4FROMI2
+60 stub VARR4FROMI4
+61 stub VARR4FROMR8
+62 stub VARR4FROMCY
+63 stub VARR4FROMDATE
+64 stub VARR4FROMSTR
+65 stub VARR4FROMDISP
+66 stub VARR4FROMBOOL
+67 stub VARR8FROMI2
+68 stub VARR8FROMI4
+69 stub VARR8FROMR4
+70 stub VARR8FROMCY
+71 stub VARR8FROMDATE
+72 stub VARR8FROMSTR
+73 stub VARR8FROMDISP
+74 stub VARR8FROMBOOL
+75 stub VARDATEFROMI2
+76 stub VARDATEFROMI4
+77 stub VARDATEFROMR4
+78 stub VARDATEFROMR8
+79 stub VARDATEFROMCY
+80 stub VARDATEFROMSTR
+81 stub VARDATEFROMDISP
+82 stub VARDATEFROMBOOL
+83 stub VARCYFROMI2
+84 stub VARCYFROMI4
+85 stub VARCYFROMR4
+86 stub VARCYFROMR8
+87 stub VARCYFROMDATE
+88 stub VARCYFROMSTR
+89 stub VARCYFROMDISP
+90 stub VARCYFROMBOOL
+91 stub VARBSTRFROMI2
+92 stub VARBSTRFROMI4
+93 stub VARBSTRFROMR4
+94 stub VARBSTRFROMR8
+95 stub VARBSTRFROMCY
+96 stub VARBSTRFROMDATE
+97 stub VARBSTRFROMDISP
+98 stub VARBSTRFROMBOOL
+99 stub VARBOOLFROMI2
+100 stub VARBOOLFROMI4
+101 stub VARBOOLFROMR4
+102 stub VARBOOLFROMR8
+103 stub VARBOOLFROMDATE
+104 stub VARBOOLFROMCY
+105 stub VARBOOLFROMSTR
+106 stub VARBOOLFROMDISP
+107 stub DOINVOKEMETHOD
+108 stub VARIANTCHANGETYPEEX
 #109 WEP
 #110 ___EXPORTEDSTUB
diff --git a/if1632/ole2nls.spec b/if1632/ole2nls.spec
index 2ee586e..f975990 100644
--- a/if1632/ole2nls.spec
+++ b/if1632/ole2nls.spec
@@ -1,14 +1,14 @@
 name	ole2nls
 id	18
-length	11
-#1 GETUSERDEFAULTLCID
-#2 GETSYSTEMDEFAULTLCID
-#3 GETUSERDEFAULTLANGID
-#4 GETSYSTEMDEFAULTLANGID
-#5 GETLOCALEINFOA
-#6 LCMAPSTRINGA
-#7 GETSTRINGTYPEA
-#8 COMPARESTRINGA
+
+1 pascal GetUserDefaultLCID()      GetUserDefaultLCID
+2 pascal GetSystemDefaultLCID()    GetSystemDefaultLCID
+3 pascal GetUserDefaultLangID()    GetUserDefaultLangID
+4 pascal GetSystemDefaultLangID()  GetSystemDefaultLangID
+5 stub GETLOCALEINFOA
+6 stub LCMAPSTRINGA
+7 stub GETSTRINGTYPEA
+8 stub COMPARESTRINGA
 #9 WEP
-#10 LIBMAIN
-#11 NOTIFYWINDOWPROC
+10 stub LIBMAIN
+11 stub NOTIFYWINDOWPROC
diff --git a/if1632/ole2prox.spec b/if1632/ole2prox.spec
index 8328722..1d3868a 100644
--- a/if1632/ole2prox.spec
+++ b/if1632/ole2prox.spec
@@ -1,6 +1,6 @@
 name	ole2prox
 id	19
-length	3
-#1 DLLGETCLASSOBJECT
+
+1 stub DLLGETCLASSOBJECT
 #2 WEP
 #3 ___EXPORTEDSTUB
diff --git a/if1632/olecli.spec b/if1632/olecli.spec
index 97c3ded..a476791 100644
--- a/if1632/olecli.spec
+++ b/if1632/olecli.spec
@@ -1,182 +1,181 @@
 name	olecli
 id	20
-length	954
 
 #1 WEP
-#2 OLEDELETE
-#3 OLESAVETOSTREAM
-#4 OLELOADFROMSTREAM
-#6 OLECLONE
-#7 OLECOPYFROMLINK
-#8 OLEEQUAL
-#9 OLEQUERYLINKFROMCLIP
-#10 OLEQUERYCREATEFROMCLIP
-#11 OLECREATELINKFROMCLIP
-#12 OLECREATEFROMCLIP
-#13 OLECOPYTOCLIPBOARD
-#14 OLEQUERYTYPE
-#15 OLESETHOSTNAMES
-#16 OLESETTARGETDEVICE
-#17 OLESETBOUNDS
-#18 OLEQUERYBOUNDS
-#19 OLEDRAW
-#20 OLEQUERYOPEN
-#21 OLEACTIVATE
-#22 OLEUPDATE
-#23 OLERECONNECT
-#24 OLEGETLINKUPDATEOPTIONS
-#25 OLESETLINKUPDATEOPTIONS
-#26 OLEENUMFORMATS
-#27 OLECLOSE
-#28 OLEGETDATA
-#29 OLESETDATA
-#30 OLEQUERYPROTOCOL
-#31 OLEQUERYOUTOFDATE
-#32 OLEOBJECTCONVERT
-#33 OLECREATEFROMTEMPLATE
-#34 OLECREATE
-#35 OLEQUERYRELEASESTATUS
-#36 OLEQUERYRELEASEERROR
-#37 OLEQUERYRELEASEMETHOD
-#38 OLECREATEFROMFILE
-#39 OLECREATELINKFROMFILE
-#40 OLERELEASE
+2 stub OLEDELETE
+3 stub OLESAVETOSTREAM
+4 stub OLELOADFROMSTREAM
+6 stub OLECLONE
+7 stub OLECOPYFROMLINK
+8 stub OLEEQUAL
+9 stub OLEQUERYLINKFROMCLIP
+10 stub OLEQUERYCREATEFROMCLIP
+11 stub OLECREATELINKFROMCLIP
+12 stub OLECREATEFROMCLIP
+13 stub OLECOPYTOCLIPBOARD
+14 stub OLEQUERYTYPE
+15 stub OLESETHOSTNAMES
+16 stub OLESETTARGETDEVICE
+17 stub OLESETBOUNDS
+18 stub OLEQUERYBOUNDS
+19 stub OLEDRAW
+20 stub OLEQUERYOPEN
+21 stub OLEACTIVATE
+22 stub OLEUPDATE
+23 stub OLERECONNECT
+24 stub OLEGETLINKUPDATEOPTIONS
+25 stub OLESETLINKUPDATEOPTIONS
+26 stub OLEENUMFORMATS
+27 stub OLECLOSE
+28 stub OLEGETDATA
+29 stub OLESETDATA
+30 stub OLEQUERYPROTOCOL
+31 stub OLEQUERYOUTOFDATE
+32 stub OLEOBJECTCONVERT
+33 stub OLECREATEFROMTEMPLATE
+34 stub OLECREATE
+35 stub OLEQUERYRELEASESTATUS
+36 stub OLEQUERYRELEASEERROR
+37 stub OLEQUERYRELEASEMETHOD
+38 stub OLECREATEFROMFILE
+39 stub OLECREATELINKFROMFILE
+40 stub OLERELEASE
 41  pascal OleRegisterClientDoc(ptr ptr long ptr) OleRegisterClientDoc
 42  pascal OleRevokeClientDoc(long) OleRevokeClientDoc
 43  pascal OleRenameClientDoc(long ptr) OleRenameClientDoc
-#44 OLEREVERTCLIENTDOC
-#45 OLESAVEDCLIENTDOC
-#46 OLERENAME
-#47 OLEENUMOBJECTS
-#48 OLEQUERYNAME
-#49 OLESETCOLORSCHEME
-#50 OLEREQUESTDATA
-#54 OLELOCKSERVER
-#55 OLEUNLOCKSERVER
-#56 OLEQUERYSIZE
-#57 OLEEXECUTE
-#58 OLECREATEINVISIBLE
-#59 OLEQUERYCLIENTVERSION
-#60 OLEISDCMETA
-#100 DOCWNDPROC
-#101 SRVRWNDPROC
-#102 MFCALLBACKFUNC
-#110 DEFLOADFROMSTREAM
-#111 DEFCREATEFROMCLIP
-#112 DEFCREATELINKFROMCLIP
-#113 DEFCREATEFROMTEMPLATE
-#114 DEFCREATE
-#115 DEFCREATEFROMFILE
-#116 DEFCREATELINKFROMFILE
-#117 DEFCREATEINVISIBLE
-#200 LERELEASE
-#201 LESHOW
-#202 LEGETDATA
-#203 LESETDATA
-#204 LESETHOSTNAMES
-#205 LESETTARGETDEVICE
-#206 LESETBOUNDS
-#207 LESAVETOSTREAM
-#208 LECLONE
-#209 LECOPYFROMLINK
-#210 LEEQUAL
-#211 LECOPY
-#212 LEQUERYTYPE
-#213 LEQUERYBOUNDS
-#214 LEDRAW
-#215 LEQUERYOPEN
-#216 LEACTIVATE
-#218 LEUPDATE
-#219 LERECONNECT
-#220 LEENUMFORMAT
-#221 LEQUERYPROTOCOL
-#222 LEQUERYOUTOFDATE
-#223 LEOBJECTCONVERT
-#224 LECHANGEDATA
-#225 LECLOSE
-#226 LEGETUPDATEOPTIONS
-#227 LESETUPDATEOPTIONS
-#228 LEEXECUTE
-#229 LEOBJECTLONG
-#230 LECREATEINVISIBLE
-#300 MFRELEASE
-#301 MFGETDATA
-#302 MFSAVETOSTREAM
-#303 MFCLONE
-#304 MFEQUAL
-#305 MFCOPY
-#307 MFQUERYBOUNDS
-#308 MFDRAW
-#309 MFENUMFORMAT
-#310 MFCHANGEDATA
-#400 BMRELEASE
-#401 BMGETDATA
-#402 BMSAVETOSTREAM
-#403 BMCLONE
-#404 BMEQUAL
-#405 BMCOPY
-#407 BMQUERYBOUNDS
-#408 BMDRAW
-#409 BMENUMFORMAT
-#410 BMCHANGEDATA
-#500 DIBRELEASE
-#501 DIBGETDATA
-#502 DIBSAVETOSTREAM
-#503 DIBCLONE
-#504 DIBEQUAL
-#505 DIBCOPY
-#507 DIBQUERYBOUNDS
-#508 DIBDRAW
-#509 DIBENUMFORMAT
-#510 DIBCHANGEDATA
-#600 GENRELEASE
-#601 GENGETDATA
-#602 GENSETDATA
-#603 GENSAVETOSTREAM
-#604 GENCLONE
-#605 GENEQUAL
-#606 GENCOPY
-#608 GENQUERYBOUNDS
-#609 GENDRAW
-#610 GENENUMFORMAT
-#611 GENCHANGEDATA
-#701 ERRSHOW
-#702 ERRSETDATA
-#703 ERRSETHOSTNAMES
-#704 ERRSETTARGETDEVICE
-#705 ERRSETBOUNDS
-#706 ERRCOPYFROMLINK
-#707 ERRQUERYOPEN
-#708 ERRACTIVATE
-#709 ERRCLOSE
-#710 ERRUPDATE
-#711 ERRRECONNECT
-#712 ERRQUERYPROTOCOL
-#713 ERRQUERYOUTOFDATE
-#714 ERROBJECTCONVERT
-#715 ERRGETUPDATEOPTIONS
-#716 ERRSETUPDATEOPTIONS
-#717 ERREXECUTE
-#718 ERROBJECTLONG
-#800 PBLOADFROMSTREAM
-#801 PBCREATEFROMCLIP
-#802 PBCREATELINKFROMCLIP
-#803 PBCREATEFROMTEMPLATE
-#804 PBCREATE
-#805 PBDRAW
-#806 PBQUERYBOUNDS
-#807 PBCOPYTOCLIPBOARD
-#808 PBCREATEFROMFILE
-#809 PBCREATELINKFROMFILE
-#810 PBENUMFORMATS
-#811 PBGETDATA
-#812 PBCREATEINVISIBLE
-#910 OBJQUERYNAME
-#911 OBJRENAME
-#912 OBJQUERYTYPE
-#913 OBJQUERYSIZE
-#950 CONNECTDLGPROC
-#951 SETNETNAME
-#952 CHECKNETDRIVE
-#953 SETNEXTNETDRIVE
-#954 GETTASKVISIBLEWINDOW
+44 stub OLEREVERTCLIENTDOC
+45 stub OLESAVEDCLIENTDOC
+46 stub OLERENAME
+47 stub OLEENUMOBJECTS
+48 stub OLEQUERYNAME
+49 stub OLESETCOLORSCHEME
+50 stub OLEREQUESTDATA
+54 stub OLELOCKSERVER
+55 stub OLEUNLOCKSERVER
+56 stub OLEQUERYSIZE
+57 stub OLEEXECUTE
+58 stub OLECREATEINVISIBLE
+59 stub OLEQUERYCLIENTVERSION
+60 stub OLEISDCMETA
+100 stub DOCWNDPROC
+101 stub SRVRWNDPROC
+102 stub MFCALLBACKFUNC
+110 stub DEFLOADFROMSTREAM
+111 stub DEFCREATEFROMCLIP
+112 stub DEFCREATELINKFROMCLIP
+113 stub DEFCREATEFROMTEMPLATE
+114 stub DEFCREATE
+115 stub DEFCREATEFROMFILE
+116 stub DEFCREATELINKFROMFILE
+117 stub DEFCREATEINVISIBLE
+200 stub LERELEASE
+201 stub LESHOW
+202 stub LEGETDATA
+203 stub LESETDATA
+204 stub LESETHOSTNAMES
+205 stub LESETTARGETDEVICE
+206 stub LESETBOUNDS
+207 stub LESAVETOSTREAM
+208 stub LECLONE
+209 stub LECOPYFROMLINK
+210 stub LEEQUAL
+211 stub LECOPY
+212 stub LEQUERYTYPE
+213 stub LEQUERYBOUNDS
+214 stub LEDRAW
+215 stub LEQUERYOPEN
+216 stub LEACTIVATE
+218 stub LEUPDATE
+219 stub LERECONNECT
+220 stub LEENUMFORMAT
+221 stub LEQUERYPROTOCOL
+222 stub LEQUERYOUTOFDATE
+223 stub LEOBJECTCONVERT
+224 stub LECHANGEDATA
+225 stub LECLOSE
+226 stub LEGETUPDATEOPTIONS
+227 stub LESETUPDATEOPTIONS
+228 stub LEEXECUTE
+229 stub LEOBJECTLONG
+230 stub LECREATEINVISIBLE
+300 stub MFRELEASE
+301 stub MFGETDATA
+302 stub MFSAVETOSTREAM
+303 stub MFCLONE
+304 stub MFEQUAL
+305 stub MFCOPY
+307 stub MFQUERYBOUNDS
+308 stub MFDRAW
+309 stub MFENUMFORMAT
+310 stub MFCHANGEDATA
+400 stub BMRELEASE
+401 stub BMGETDATA
+402 stub BMSAVETOSTREAM
+403 stub BMCLONE
+404 stub BMEQUAL
+405 stub BMCOPY
+407 stub BMQUERYBOUNDS
+408 stub BMDRAW
+409 stub BMENUMFORMAT
+410 stub BMCHANGEDATA
+500 stub DIBRELEASE
+501 stub DIBGETDATA
+502 stub DIBSAVETOSTREAM
+503 stub DIBCLONE
+504 stub DIBEQUAL
+505 stub DIBCOPY
+507 stub DIBQUERYBOUNDS
+508 stub DIBDRAW
+509 stub DIBENUMFORMAT
+510 stub DIBCHANGEDATA
+600 stub GENRELEASE
+601 stub GENGETDATA
+602 stub GENSETDATA
+603 stub GENSAVETOSTREAM
+604 stub GENCLONE
+605 stub GENEQUAL
+606 stub GENCOPY
+608 stub GENQUERYBOUNDS
+609 stub GENDRAW
+610 stub GENENUMFORMAT
+611 stub GENCHANGEDATA
+701 stub ERRSHOW
+702 stub ERRSETDATA
+703 stub ERRSETHOSTNAMES
+704 stub ERRSETTARGETDEVICE
+705 stub ERRSETBOUNDS
+706 stub ERRCOPYFROMLINK
+707 stub ERRQUERYOPEN
+708 stub ERRACTIVATE
+709 stub ERRCLOSE
+710 stub ERRUPDATE
+711 stub ERRRECONNECT
+712 stub ERRQUERYPROTOCOL
+713 stub ERRQUERYOUTOFDATE
+714 stub ERROBJECTCONVERT
+715 stub ERRGETUPDATEOPTIONS
+716 stub ERRSETUPDATEOPTIONS
+717 stub ERREXECUTE
+718 stub ERROBJECTLONG
+800 stub PBLOADFROMSTREAM
+801 stub PBCREATEFROMCLIP
+802 stub PBCREATELINKFROMCLIP
+803 stub PBCREATEFROMTEMPLATE
+804 stub PBCREATE
+805 stub PBDRAW
+806 stub PBQUERYBOUNDS
+807 stub PBCOPYTOCLIPBOARD
+808 stub PBCREATEFROMFILE
+809 stub PBCREATELINKFROMFILE
+810 stub PBENUMFORMATS
+811 stub PBGETDATA
+812 stub PBCREATEINVISIBLE
+910 stub OBJQUERYNAME
+911 stub OBJRENAME
+912 stub OBJQUERYTYPE
+913 stub OBJQUERYSIZE
+950 stub CONNECTDLGPROC
+951 stub SETNETNAME
+952 stub CHECKNETDRIVE
+953 stub SETNEXTNETDRIVE
+954 stub GETTASKVISIBLEWINDOW
diff --git a/if1632/olesvr.spec b/if1632/olesvr.spec
index 75d471c..ca3f1bd 100644
--- a/if1632/olesvr.spec
+++ b/if1632/olesvr.spec
@@ -1,6 +1,6 @@
 name	olesvr
 id	21
-length	31
+
 #1 WEP
 2  pascal OleRegisterServer(ptr ptr ptr word word) OleRegisterServer
 3  pascal OleRevokeServer(long) OleRevokeServer
@@ -8,19 +8,19 @@
 5  pascal OleUnblockServer(long ptr) OleUnblockServer
 6  pascal OleRegisterServerDoc(long ptr ptr ptr) OleRegisterServerDoc
 7  pascal OleRevokeServerDoc(long) OleRevokeServerDoc
-#8 OLERENAMESERVERDOC
-#9 OLEREVERTSERVERDOC
-#10 OLESAVEDSERVERDOC
-#11 OLEREVOKEOBJECT
-#12 OLEQUERYSERVERVERSION
-#21 SRVRWNDPROC
-#22 DOCWNDPROC
-#23 ITEMWNDPROC
-#24 SENDDATAMSG
-#25 FINDITEMWND
-#26 ITEMCALLBACK
-#27 TERMINATECLIENTS
-#28 TERMINATEDOCCLIENTS
-#29 DELETECLIENTINFO
-#30 SENDRENAMEMSG
-#31 ENUMFORTERMINATE
+8 stub OLERENAMESERVERDOC
+9 stub OLEREVERTSERVERDOC
+10 stub OLESAVEDSERVERDOC
+11 stub OLEREVOKEOBJECT
+12 stub OLEQUERYSERVERVERSION
+21 stub SRVRWNDPROC
+22 stub DOCWNDPROC
+23 stub ITEMWNDPROC
+24 stub SENDDATAMSG
+25 stub FINDITEMWND
+26 stub ITEMCALLBACK
+27 stub TERMINATECLIENTS
+28 stub TERMINATEDOCCLIENTS
+29 stub DELETECLIENTINFO
+30 stub SENDRENAMEMSG
+31 stub ENUMFORTERMINATE
diff --git a/if1632/relay.c b/if1632/relay.c
index c855e81..0a3ccf5 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -67,27 +67,25 @@
     { "COMPOBJ",  WineLibSkip(&COMPOBJ_table), 1 },
     { "STORAGE",  WineLibSkip(&STORAGE_table), 1 },
     { "WINPROCS", WineLibSkip(&WINPROCS_table), 1 },
+    { "DDEML",    WineLibSkip(&DDEML_table), 1 }
+    
 };
 /* don't forget to increase N_BUILTINS in dlls.h if you add a dll */
 
   /* Saved 16-bit stack */
 WORD IF1632_Saved16_ss = 0;
 WORD IF1632_Saved16_sp = 0;
-WORD IF1632_Saved16_bp = 0;
 
   /* Saved 32-bit stack */
 DWORD IF1632_Saved32_esp = 0;
-DWORD IF1632_Saved32_ebp = 0;
+
 
 /***********************************************************************
  *           RELAY_Init
  */
 BOOL RELAY_Init(void)
 {
-    WORD codesel, datasel;
-    struct dll_table_s *table;
-    struct dll_table_entry_s *entry;
-    int i, j;
+    WORD codesel;
 
       /* Allocate the code selector for CallTo16 routines */
 
@@ -107,31 +105,6 @@
     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++)
-    {
-        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;
 }
 
@@ -212,9 +185,10 @@
 {
     STACK16FRAME *frame = CURRENT_STACK16;
 
-    fprintf( stderr, "No handler for routine %s.%d\n",
+    fprintf( stderr, "No handler for routine %s.%d (%s)\n",
              dll_builtin_table[frame->dll_id-1].dll_name,
-             frame->ordinal_number );
+             frame->ordinal_number,
+             dll_builtin_table[frame->dll_id-1].table->dll_table[frame->ordinal_number].export_name );
     exit(1);
 }
 
diff --git a/if1632/shell.spec b/if1632/shell.spec
index f559912..cab447f 100644
--- a/if1632/shell.spec
+++ b/if1632/shell.spec
@@ -1,8 +1,5 @@
-# $Id: shell.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	shell
 id	5
-length	103
 
 #
 # WARNING ! These functions are not documented, so I didn't look for
diff --git a/if1632/sound.spec b/if1632/sound.spec
index 825fc4e..7447932 100644
--- a/if1632/sound.spec
+++ b/if1632/sound.spec
@@ -1,8 +1,5 @@
-# $Id: sound.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	sound
 id	6
-length	20
 
 1    pascal  OPENSOUND() OpenSound
 2    pascal  CLOSESOUND() CloseSound
diff --git a/if1632/storage.spec b/if1632/storage.spec
index 8876ef9..d6d59c7 100644
--- a/if1632/storage.spec
+++ b/if1632/storage.spec
@@ -1,6 +1,5 @@
 name	storage
 id	23
-length	104
  
 #1 STGCREATEDOCFILE
 #2 STGCREATEDOCFILEONILOCKBYTES
diff --git a/if1632/stress.spec b/if1632/stress.spec
index 2e2e880..738de00 100644
--- a/if1632/stress.spec
+++ b/if1632/stress.spec
@@ -2,7 +2,6 @@
 #
 name	stress
 id	9
-length	15
 
 2   pascal allocmem(long)		AllocMem
 3   pascal freeallmem()			FreeAllMem
diff --git a/if1632/system.spec b/if1632/system.spec
index 4f2b816..6adb534 100644
--- a/if1632/system.spec
+++ b/if1632/system.spec
@@ -1,5 +1,4 @@
 name	system
 id	11
-length	20
 
 6 pascal GetSystemmsecCount() GetTickCount
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index a7d8243..7db2d70 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -1,6 +1,5 @@
 name	toolhelp
 id	12
-length	83
 
 50 pascal16 GlobalHandleToSel(word) GlobalHandleToSel
 51 pascal16 GlobalFirst(ptr word) GlobalFirst
@@ -18,21 +17,21 @@
 63 pascal16 TaskFirst(ptr) TaskFirst
 64 pascal16 TaskNext(ptr) TaskNext
 65 pascal16 TaskFindHandle(ptr word) TaskFindHandle
-# 66   1  0f1c  STACKTRACEFIRST exported, shared data
-# 67   1  0f67  STACKTRACECSIPFIRST exported, shared data
-# 68   1  0fca  STACKTRACENEXT exported, shared data
+66 stub STACKTRACEFIRST
+67 stub STACKTRACECSIPFIRST
+68 stub STACKTRACENEXT
 69 pascal16 ClassFirst(ptr) ClassFirst
 70 pascal16 ClassNext(ptr) ClassNext
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo
 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
-# 76   1  2111  INTERRUPTUNREGISTER exported, shared data
-# 77   1  26ea  TERMINATEAPP exported, shared data
+73 stub NOTIFYREGISTER
+74 stub NOTIFYUNREGISTER
+75 stub INTERRUPTREGISTER
+76 stub INTERRUPTUNREGISTER
+77 stub TERMINATEAPP
 78 pascal MemoryRead(word long ptr long) MemoryRead
 79 pascal MemoryWrite(word long ptr long) MemoryWrite
-# 80   1  2dae  TIMERCOUNT exported, shared data
-# 81   1  0d68  TASKSETCSIP exported, shared data
-# 82   1  0d97  TASKGETCSIP exported, shared data
-# 83   1  0dc0  TASKSWITCH exported, shared data
+80 stub TIMERCOUNT
+81 stub TASKSETCSIP
+82 stub TASKGETCSIP
+83 stub TASKSWITCH
diff --git a/if1632/user.spec b/if1632/user.spec
index 58a1a79..969eb14 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -1,13 +1,10 @@
-# $Id: user.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
-#
 name	user
 id	2
-length	540
 
 1   pascal MessageBox(word ptr ptr word) MessageBox
-#2 OLDEXITWINDOWS
-#3 ENABLEOEMLAYER
-#4 DISABLEOEMLAYER
+2   stub OldExitWindows
+3   stub EnableOEMLayer
+4   stub DisableOEMLayer
 5   pascal InitApp(word) USER_InitApp
 6   pascal PostQuitMessage(word) PostQuitMessage
 7   pascal ExitWindows(long word) ExitWindows
@@ -25,10 +22,10 @@
 21  pascal GetDoubleClickTime() GetDoubleClickTime
 22  pascal SetFocus(word) SetFocus
 23  pascal GetFocus() GetFocus
-24  pascal RemoveProp(word ptr) RemoveProp
-25  pascal GetProp(word ptr) GetProp
-26  pascal SetProp(word ptr word) SetProp
-27  pascal EnumProps(word ptr) EnumProps
+24  pascal16 RemoveProp(word segptr) RemoveProp
+25  pascal16 GetProp(word segptr) GetProp
+26  pascal16 SetProp(word segptr word) SetProp
+27  pascal16 EnumProps(word segptr) EnumProps
 28  pascal ClientToScreen(word ptr) ClientToScreen
 29  pascal ScreenToClient(word ptr) ScreenToClient
 30  pascal WindowFromPoint(long) WindowFromPoint
@@ -56,8 +53,8 @@
 #51 BEAR51
 52  pascal AnyPopup() AnyPopup
 53  pascal DestroyWindow(word) DestroyWindow
-54  pascal EnumWindows(ptr long) EnumWindows
-55  pascal EnumChildWindows(word ptr long) EnumChildWindows
+54  pascal EnumWindows(segptr long) EnumWindows
+55  pascal EnumChildWindows(word segptr long) EnumChildWindows
 56  pascal MoveWindow(word word word word word word) MoveWindow
 57  pascal RegisterClass(ptr) RegisterClass
 58  pascal GetClassName(word ptr word) GetClassName
@@ -116,8 +113,8 @@
 112 pascal WaitMessage() WaitMessage
 113 pascal TranslateMessage(ptr) TranslateMessage
 114 pascal DispatchMessage(ptr) DispatchMessage
-#115 REPLYMESSAGE
-#116 POSTAPPMESSAGE
+115 stub ReplyMessage
+116 stub PostAppMessage
 118 pascal RegisterWindowMessage(ptr) RegisterWindowMessage
 119 pascal GetMessagePos() GetMessagePos
 120 pascal GetMessageTime() GetMessageTime
@@ -172,7 +169,7 @@
 169 pascal GetCaretBlinkTime() GetCaretBlinkTime
 170 pascal ArrangeIconicWindows(word) ArrangeIconicWindows
 171 pascal WinHelp(word ptr word long) WinHelp
-#172 SWITCHTOTHISWINDOW
+172 stub SwitchToThisWindow
 173 pascal16 LoadCursor(word segptr) LoadCursor
 174 pascal16 LoadIcon(word segptr) LoadIcon
 175 pascal16 LoadBitmap(word segptr) LoadBitmap
@@ -184,7 +181,7 @@
 181 pascal SetSysColors(word ptr ptr) SetSysColors
 182 pascal KillSystemTimer(word word) KillSystemTimer
 183 pascal GetCaretPos(ptr) GetCaretPos
-#184 QUERYSENDMESSAGE
+184 stub QuerySendMessage
 185 pascal GrayString(word word ptr ptr word word word word word) GrayString
 186 pascal SwapMouseButton(word) SwapMouseButton
 187 pascal EndMenu() EndMenu
@@ -224,15 +221,15 @@
 220 pascal LoadMenuIndirect(ptr) LoadMenuIndirect
 221 pascal ScrollDC(word s_word s_word ptr ptr word ptr) ScrollDC
 222 pascal16 GetKeyboardState(ptr) GetKeyboardState
-#223 SETKEYBOARDSTATE
+223 stub SetKeyboardState
 224 pascal16 GetWindowTask(word) GetWindowTask
 225 pascal EnumTaskWindows(word segptr long) EnumTaskWindows
-#226 LOCKINPUT
+226 stub LockInput
 227 pascal GetNextDlgGroupItem(word word word) GetNextDlgGroupItem
 228 pascal GetNextDlgTabItem(word word word) GetNextDlgTabItem
 229 pascal GetTopWindow(word) GetTopWindow
 230 pascal GetNextWindow(word word) GetNextWindow
-#231 GETSYSTEMDEBUGSTATE
+231 stub GetSystemDebugState
 232 pascal SetWindowPos(word word word word word word word) SetWindowPos
 233 pascal SetParent(word word) SetParent
 234 pascal UnhookWindowsHook(s_word segptr) UnhookWindowsHook
@@ -248,8 +245,8 @@
              CreateDialogIndirectParam
 243 pascal GetDialogBaseUnits() GetDialogBaseUnits
 244 pascal EqualRect(ptr ptr) EqualRect
-#245 ENABLECOMMNOTIFICATION
-#246 EXITWINDOWSEXEC
+245 stub EnableCommNotification
+246 stub ExitWindowsExec
 247 pascal GetCursor() GetCursor
 248 pascal GetOpenClipboardWindow() GetOpenClipboardWindow
 249 pascal GetAsyncKeyState(word) GetAsyncKeyState
@@ -269,7 +266,7 @@
 262 pascal GetWindow(word word) GetWindow
 263 pascal GetMenuItemCount(word) GetMenuItemCount
 264 pascal GetMenuItemID(word word) GetMenuItemID
-#265 SHOWOWNEDPOPUPS
+265 stub ShowOwnedPopups
 266 pascal SetMessageQueue(word) SetMessageQueue
 267 pascal ShowScrollBar(word word word) ShowScrollBar
 268 pascal GlobalAddAtom(ptr) GlobalAddAtom
@@ -277,14 +274,14 @@
 270 pascal GlobalFindAtom(ptr) GlobalFindAtom
 271 pascal GlobalGetAtomName(word ptr s_word) GlobalGetAtomName
 272 pascal IsZoomed(word) IsZoomed
-#273 CONTROLPANELINFO
-#274 GETNEXTQUEUEWINDOW
-#275 REPAINTSCREEN
-#276 LOCKMYTASK
+273 stub ControlPanelInfo
+274 stub GetNextQueueWindow
+275 stub RepaintScreen
+276 stub LockMyTask
 277 pascal GetDlgCtrlID(word) GetDlgCtrlID
 278 pascal GetDeskTopHwnd() GetDesktopWindow
-#279 OLDSETDESKPATTERN
-#280 SETSYSTEMMENU
+279 stub OldSetDeskPattern
+280 stub SetSystemMenu
 281 pascal GetSysColorBrush(word) GetSysColorBrush
 282 pascal SelectPalette(word word word) SelectPalette
 283 pascal RealizePalette(word) RealizePalette
@@ -298,49 +295,49 @@
 291 pascal SetWindowsHookEx(s_word segptr word word) SetWindowsHookEx
 292 pascal UnhookWindowsHookEx(segptr) UnhookWindowsHookEx
 293 pascal CallNextHookEx(segptr s_word word long) CallNextHookEx
-#294 LOCKWINDOWUPDATE
+294 stub LockWindowUpdate
 #299 MOUSE_EVENT
 #301 BOZOSLIVEHERE :-))
 #306 BEAR306
 308 pascal DefDlgProc(word word word long) DefDlgProc
-#314 SIGNALPROC
+314 stub SignalProc
 319 pascal ScrollWindowEx(word s_word s_word ptr ptr word ptr word)
            ScrollWindowEx
-#320 SYSERRORBOX
-#321 SETEVENTHOOK
-#322 WINOLDAPPHACKOMATIC
-#323 GETMESSAGE2
+320 stub SysErrorBox
+321 stub SetEventHook
+322 stub WinOldAppHackOMatic
+323 stub GetMessage2
 324 pascal FillWindow(word word word word) FillWindow
 325 pascal PaintRect(word word word word ptr) PaintRect
 326 pascal16 GetControlBrush(word word word) GetControlBrush
 331 pascal EnableHardwareInput(word) EnableHardwareInput
 332 return UserYield 0 0
-#333 ISUSERIDLE
+333 stub IsUserIdle
 334 pascal GetQueueStatus(word) GetQueueStatus
 335 pascal GetInputState() GetInputState
-#336 LOADCURSORICONHANDLER
-#337 GETMOUSEEVENTPROC
+336 stub LoadCursorIconHandler
+337 stub GetMouseEventProc
 #341 _FFFE_FARFRAME
-#343 GETFILEPORTNAME
-#356 LOADDIBCURSORHANDLER
-#357 LOADDIBICONHANDLER
+343 stub GetFilePortName
+356 stub LoadDIBCursorHandler
+357 stub LoadDIBIconHandler
 358 pascal IsMenu(word) IsMenu
 359 pascal GetDCEx(word word long) GetDCEx
-#362 DCHOOK
-#368 COPYICON
-#369 COPYCURSOR
+362 stub DCHook
+368 stub CopyIcon
+369 stub CopyCursor
 370 pascal GetWindowPlacement(word ptr) GetWindowPlacement
 371 pascal SetWindowPlacement(word ptr) SetWindowPlacement
-#372 GETINTERNALICONHEADER
+372 stub GetInternalIconHeader
 373 pascal SubtractRect(ptr ptr ptr) SubtractRect
-#400 FINALUSERINIT
+400 stub FinalUserInit
 402 pascal GetPriorityClipboardFormat(word ptr s_word)
            GetPriorityClipboardFormat
 403 pascal UnregisterClass(ptr word) UnregisterClass
-404 pascal GetClassInfo(word ptr ptr) GetClassInfo
+404 pascal GetClassInfo(word segptr ptr) GetClassInfo
 406 pascal CreateCursor(word word word word word ptr ptr) CreateCursor
 407 pascal CreateIcon(word word word byte byte ptr ptr) CreateIcon
-#408 CREATECURSORICONINDIRECT
+408 stub CreateCursorIconIndirect
 410 pascal InsertMenu(word word word word ptr) InsertMenu
 411 pascal AppendMenu(word word word ptr) AppendMenu
 412 pascal RemoveMenu(word word word) RemoveMenu
@@ -354,8 +351,8 @@
 # windows_wsprintf() handles arguments itself, as libc can't handle an
 # 16-bit stack. DLLRelay() will pass 16-bit stack pointer as 1st arg.
 421 pascal wvsprintf(ptr ptr ptr) wvsprintf
-#422 DLGDIRSELECTEX
-#423 DLGDIRSELECTCOMBOBOXEX
+422 stub DlgDirSelectEx
+423 stub DlgDirSelectComboBoxEx
 430 pascal16 lstrcmp(ptr ptr) lstrcmp
 431 pascal AnsiUpper(segptr) WIN16_AnsiUpper
 432 pascal AnsiLower(segptr) WIN16_AnsiLower
@@ -371,23 +368,23 @@
 452 pascal CreateWindowEx(long ptr ptr long s_word s_word s_word s_word
                           word word word segptr) CreateWindowEx
 454 pascal AdjustWindowRectEx(ptr long word long) AdjustWindowRectEx
-#455 GETICONID
-#456 LOADICONHANDLER
+455 stub GetIconId
+456 stub LoadIconHandler
 457 pascal DestroyIcon(word) DestroyIcon
 458 pascal DestroyCursor(word) DestroyCursor
-#459 DUMPICON
+459 stub DumpIcon
 460 pascal GetInternalWindowPos(word ptr ptr) GetInternalWindowPos
 461 pascal SetInternalWindowPos(word word ptr ptr) SetInternalWindowPos
-#462 CALCCHILDSCROLL
-#463 SCROLLCHILDREN
-#464 DRAGOBJECT
-#465 DRAGDETECT
+462 stub CalcChildScroll
+463 stub ScrollChildren
+464 stub DragObject
+465 stub DragDetect
 466 pascal DrawFocusRect(word ptr) DrawFocusRect
-#470 STRINGFUNC
+470 stub StringFunc
 471 pascal16 lstrcmpi(ptr ptr) lstrcmpi
 472 pascal AnsiNext(segptr) AnsiNext
 473 pascal AnsiPrev(segptr segptr) AnsiPrev
-#480 GETUSERLOCALOBJTYPE
+480 stub GetUserLocalObjType
 #481 HARDWARE_EVENT
 482 pascal16 EnableScrollBar(word word word) EnableScrollBar
 483 pascal SystemParametersInfo(word word ptr word) SystemParametersInfo
@@ -413,8 +410,8 @@
 518 pascal16 WNetCancelConnection(ptr word) WNetCancelConnection
 519 pascal WNetGetError(ptr) WNetGetError
 520 pascal WNetGetErrorText(word ptr ptr) WNetGetErrorText
-#521 WNETENABLE
-#522 WNETDISABLE
+521 stub WNetEnable
+522 stub WNetDisable
 523 pascal WNetRestoreConnection(word ptr) WNetRestoreConnection
 524 pascal WNetWriteJob(word ptr ptr) WNetWriteJob
 525 pascal WnetConnectDialog(word word) WNetConnectDialog
diff --git a/if1632/win87em.spec b/if1632/win87em.spec
index 1db0d41..fa50432 100644
--- a/if1632/win87em.spec
+++ b/if1632/win87em.spec
@@ -1,6 +1,5 @@
 name	win87em
 id	4
-length	10
 
 1 register _fpMath() WIN87_fpmath
 3 pascal __WinEm87Info(ptr word) WIN87_WinEm87Info
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
index c276817..a1c54f6 100644
--- a/if1632/winprocs.spec
+++ b/if1632/winprocs.spec
@@ -1,6 +1,5 @@
 name	winprocs
 id	24
-length	23
 
 1  pascal ButtonWndProc(word word word long) ButtonWndProc
 2  pascal StaticWndProc(word word word long) StaticWndProc
@@ -25,3 +24,4 @@
 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
+24 pascal16 TASK_Reschedule() TASK_Reschedule
diff --git a/if1632/winsock.spec b/if1632/winsock.spec
index 75edb2d..2418716 100644
--- a/if1632/winsock.spec
+++ b/if1632/winsock.spec
@@ -5,7 +5,6 @@
 #  
 name	winsock
 id	8
-length	155
 
 1   pascal16 accept(word ptr ptr) WINSOCK_accept
 2   pascal16 bind(word ptr word) WINSOCK_bind
diff --git a/include/arch.h b/include/arch.h
index ad1865c..be237fa 100644
--- a/include/arch.h
+++ b/include/arch.h
@@ -11,8 +11,8 @@
 #define CONV_CHAR_TO_LONG(x) ((unsigned long)(x) >> 24)
 #define CONV_SHORT_TO_LONG(x) ((unsigned long)(x) >> 16)
 
-#define CONV_BITMAPINFO ARCH_ConvBitmapInfo
-#define CONV_BITMAPCOREHEADER ARCH_ConvCoreHeader
+#define CONV_BITMAPINFO(a) ARCH_ConvBitmapInfo(a)
+#define CONV_BITMAPCOREHEADER(a) ARCH_ConvCoreHeader(a)
 #else
 #define CONV_LONG(a) (a)
 #define CONV_SHORT(a) (a)
diff --git a/include/callback.h b/include/callback.h
index 01a87d6..0510758 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -18,6 +18,7 @@
 /* by the build program to generate the file if1632/call16.S */
 
                                /* func     ds    parameters */
+extern WORD CallTo16_word_     ( FARPROC, WORD );
 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 );
@@ -28,8 +29,8 @@
 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 );
+extern WORD CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD bp, 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 )
@@ -55,8 +56,8 @@
     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 )
+#define CallWndProc( func, ds, hwnd, msg, wParam, lParam ) \
+    CallTo16_long_wwwl( func, ds, hwnd, msg, wParam, lParam )
 
 #else  /* WINELIB */
 
diff --git a/include/comm.h b/include/comm.h
index af2d3f01..0d3df44 100644
--- a/include/comm.h
+++ b/include/comm.h
@@ -12,7 +12,6 @@
     int baudrate;
 };
 
-extern void Comm_Init(void);
-extern void Comm_DeInit(void);
+extern void COMM_Init(void);
 
 #endif  /* COMM_H */
diff --git a/include/commdlg.h b/include/commdlg.h
index 737e6e0..95eefb6 100644
--- a/include/commdlg.h
+++ b/include/commdlg.h
@@ -50,23 +50,24 @@
 	DWORD		lStructSize;
 	HWND		hwndOwner;
 	HINSTANCE	hInstance;
-	LPCSTR		lpstrFilter;
-	LPSTR		lpstrCustomFilter;
+	SEGPTR	        lpstrFilter;
+	SEGPTR          lpstrCustomFilter;
 	DWORD		nMaxCustFilter;
 	DWORD		nFilterIndex;
-	LPSTR		lpstrFile;
+	SEGPTR          lpstrFile;
 	DWORD		nMaxFile;
-	LPSTR		lpstrFileTitle;
+	SEGPTR		lpstrFileTitle;
 	DWORD		nMaxFileTitle;
-	LPCSTR 		lpstrInitialDir;
-	LPCSTR 		lpstrTitle;
+	SEGPTR 		lpstrInitialDir;
+	SEGPTR 		lpstrTitle;
 	DWORD		Flags;
 	UINT		nFileOffset;
 	UINT		nFileExtension;
-	LPCSTR		lpstrDefExt;
+	SEGPTR		lpstrDefExt;
 	LPARAM 		lCustData;
-	UINT 		(CALLBACK *lpfnHook)(HWND, UINT, WPARAM, LPARAM);
-	LPCSTR 		lpTemplateName;
+/*	UINT 		(CALLBACK *lpfnHook)(HWND, UINT, WPARAM, LPARAM);*/
+        FARPROC         lpfnHook;
+	SEGPTR 		lpTemplateName;
 	}   OPENFILENAME;
 typedef OPENFILENAME * LPOPENFILENAME;
 
@@ -98,13 +99,14 @@
 	HINSTANCE	hInstance; 				/* instance handle of.EXE that  */
 										/*	contains cust. dlg. template */
 	DWORD		Flags;                  /* one or more of the FR_?? */
-	LPSTR		lpstrFindWhat;          /* ptr. to search string    */
-	LPSTR		lpstrReplaceWith;       /* ptr. to replace string   */
+	SEGPTR		lpstrFindWhat;          /* ptr. to search string    */
+	SEGPTR		lpstrReplaceWith;       /* ptr. to replace string   */
 	UINT		wFindWhatLen;           /* size of find buffer      */
 	UINT 		wReplaceWithLen;        /* size of replace buffer   */
 	LPARAM 		lCustData;              /* data passed to hook fn.  */
-	UINT		(CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);
-	LPCSTR 		lpTemplateName;         /* custom template name     */
+/*	UINT		(CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM); */
+        FARPROC         lpfnHook;
+	SEGPTR 		lpTemplateName;         /* custom template name     */
 	} FINDREPLACE;
 typedef FINDREPLACE *LPFINDREPLACE;
 
@@ -130,17 +132,18 @@
 typedef struct {
 	DWORD			lStructSize;
 	HWND			hwndOwner;          /* caller's window handle   */
-	HDC				hDC;                /* printer DC/IC or NULL    */
-	LOGFONT FAR*	lpLogFont;          /* ptr. to a LOGFONT struct */
+	HDC            	        hDC;                /* printer DC/IC or NULL    */
+	SEGPTR                  lpLogFont;          /* ptr. to a LOGFONT struct */
 	short			iPointSize;         /* 10 * size in points of selected font */
 	DWORD			Flags;              /* enum. type flags         */
 	COLORREF		rgbColors;          /* returned text color      */
-	LPARAM			lCustData;          /* data passed to hook fn.  */
-	UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);
-	LPCSTR			lpTemplateName;     /* custom template name     */
+	LPARAM	                lCustData;          /* data passed to hook fn.  */
+/*	UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);*/
+        FARPROC                 lpfnHook;
+	SEGPTR			lpTemplateName;     /* custom template name     */
 	HINSTANCE		hInstance;          /* instance handle of.EXE that   */
 										/* contains cust. dlg. template  */
-	LPSTR			lpszStyle;          /* return the style field here   */
+	SEGPTR			lpszStyle;          /* return the style field here   */
 										/* must be LF_FACESIZE or bigger */
 	UINT			nFontType;          /* same value reported to the    */
 										/* EnumFonts callback with the   */
@@ -204,7 +207,7 @@
 	HWND 		hwndOwner;
 	HGLOBAL		hDevMode;
 	HGLOBAL		hDevNames;
-	HDC			hDC;
+	HDC	       	hDC;
 	DWORD 		Flags;
 	UINT		nFromPage;
 	UINT		nToPage;
@@ -213,10 +216,12 @@
 	UINT		nCopies;
 	HINSTANCE 	hInstance;
 	LPARAM 		lCustData;
-	UINT		(CALLBACK* lpfnPrintHook)(HWND, UINT, WPARAM, LPARAM);
-	UINT		(CALLBACK* lpfnSetupHook)(HWND, UINT, WPARAM, LPARAM);
-	LPCSTR 		lpPrintTemplateName;
-	LPCSTR 		lpSetupTemplateName;
+/*	UINT		(CALLBACK* lpfnPrintHook)(HWND, UINT, WPARAM, LPARAM);
+	UINT		(CALLBACK* lpfnSetupHook)(HWND, UINT, WPARAM, LPARAM);*/
+        FARPROC         lpfnPrintHook;
+        FARPROC         lpfnSetupHook;
+	SEGPTR 		lpPrintTemplateName;
+	SEGPTR 		lpSetupTemplateName;
 	HGLOBAL 	hPrintTemplate;
 	HGLOBAL 	hSetupTemplate;
 	} PRINTDLG;
diff --git a/include/desktop.h b/include/desktop.h
index e7667a2..024dfb4 100644
--- a/include/desktop.h
+++ b/include/desktop.h
@@ -17,6 +17,7 @@
     BOOL     fTileWallPaper;
 } DESKTOPINFO;
 
+extern BOOL DESKTOP_Init();
 extern BOOL DESKTOP_SetPattern(char *pattern );
 
 #endif  /* DESKTOP_H */
diff --git a/include/dlls.h b/include/dlls.h
index 10f2f08..681d821 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -11,22 +11,9 @@
 
 #define MAX_NAME_LENGTH		64
 
-typedef struct resource_name_table
-{
-    struct resource_name_table *next;
-    unsigned short type_ord;
-    unsigned short id_ord;
-    char id[MAX_NAME_LENGTH];
-} RESNAMTAB;
 
 struct ne_data {
     struct ne_header_s *ne_header;
-    struct ne_segment_table_entry_s *seg_table;
-    unsigned short *selector_table;
-    char *lookup_table;
-    char *nrname_table;
-    char *rname_table;
-    RESNAMTAB *resnamtab;
 };
 
 struct pe_data {
@@ -43,8 +30,10 @@
     struct w_files  * next;
     char * name;   /* Name, as it appears in the windows binaries */
     char * filename; /* Actual name of the unix file that satisfies this */
+    int type;        /* DLL or EXE */
     int fd;
     unsigned short hinstance;
+    HANDLE hModule;
     int initialised;
     struct mz_header_s *mz_header;
     struct ne_data *ne;
@@ -59,12 +48,6 @@
 struct dll_table_entry_s
 {
     /*
-     * Relocation data
-     */
-    WORD selector;  /* Selector of entry point */
-    WORD offset;    /* Offset in segment of entry point */
-
-    /*
      * 16->32 bit interface data
      */
     char *export_name;
@@ -78,10 +61,11 @@
     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;
+    BYTE *code_start;    /* 32-bit address of DLL code */
+    BYTE *data_start;    /* 32-bit address of DLL data */
+    BYTE *module_start;  /* 32-bit address of the module data */
+    BYTE *module_end;
+    HMODULE hModule;
 };
 
 struct dll_name_table_entry_s
@@ -115,8 +99,9 @@
 extern struct dll_table_s COMPOBJ_table;
 extern struct dll_table_s STORAGE_table;
 extern struct dll_table_s WINPROCS_table;
+extern struct dll_table_s DDEML_table;
 
-#define N_BUILTINS	24
+#define N_BUILTINS	25
 
 #endif /* DLLS_H */
 
diff --git a/include/dos_fs.h b/include/dos_fs.h
index b32d900..d0b2492 100644
--- a/include/dos_fs.h
+++ b/include/dos_fs.h
@@ -31,6 +31,7 @@
 extern void DOS_closedir(struct dosdirent *de);
 extern void DOS_ExpandToFullPath(char *filename, int drive);
 extern void DOS_ExpandToFullUnixPath(char *filename);
+extern char *DOS_GetRedirectedDir(int drive);
 
 extern char WindowsPath[256];
 
diff --git a/include/global.h b/include/global.h
index 626890f..dd912ce 100644
--- a/include/global.h
+++ b/include/global.h
@@ -9,8 +9,12 @@
 
 #include "wintypes.h"
 
+extern HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
+                                   HGLOBAL hOwner, BOOL isCode,
+                                   BOOL is32Bit, BOOL isReadOnly );
+extern BOOL GLOBAL_FreeBlock( HGLOBAL handle );
 extern HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
-                             BOOL isCode, BOOL isReadOnly );
+                             BOOL isCode, BOOL is32Bit, BOOL isReadOnly );
 extern WORD GlobalHandleToSel( HGLOBAL handle );
 
 #endif  /* __WINE_GLOBAL_H */
diff --git a/include/module.h b/include/module.h
new file mode 100644
index 0000000..d3973a0
--- /dev/null
+++ b/include/module.h
@@ -0,0 +1,92 @@
+/*
+ * Module definitions
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#ifndef _WINE_MODULE_H
+#define _WINE_MODULE_H
+
+#include "wintypes.h"
+
+#ifndef WINELIB
+#pragma pack(1)
+#endif
+
+  /* In-memory module structure. See 'Windows Internals' p. 219 */
+typedef struct
+{
+    WORD    magic;            /* 'NE' signature */
+    WORD    count;            /* Usage count */
+    WORD    entry_table;      /* Near ptr to entry table */
+    WORD    next;             /* Selector to next module */
+    WORD    dgroup_entry;     /* Near ptr to segment entry for DGROUP */
+    WORD    fileinfo;         /* Near ptr to file info (LOADEDFILEINFO) */
+    WORD    flags;            /* Module flags */
+    WORD    dgroup;           /* Logical segment for DGROUP */
+    WORD    heap_size;        /* Initial heap size */
+    WORD    stack_size;       /* Initial stack size */
+    WORD    ip;               /* Initial ip */
+    WORD    cs;               /* Initial cs (logical segment) */
+    WORD    sp;               /* Initial stack pointer */
+    WORD    ss;               /* Initial ss (logical segment) */
+    WORD    seg_count;        /* Number of segments in segment table */
+    WORD    modref_count;     /* Number of module references */
+    WORD    nrname_size;      /* Size of non-resident names table */
+    WORD    seg_table;        /* Near ptr to segment table */
+    WORD    res_table;        /* Near ptr to resource table */
+    WORD    name_table;       /* Near ptr to resident names table */
+    WORD    modref_table;     /* Near ptr to module reference table */
+    WORD    import_table;     /* Near ptr to imported names table */
+    DWORD   nrname_fpos;      /* File offset of non-resident names table */
+    WORD    moveable_entries; /* Number of moveable entries in entry table */
+    WORD    alignment;        /* Alignment shift count */
+    WORD    truetype;         /* Set to 2 if TrueType font */
+    BYTE    os_flags;         /* Operating system flags */
+    BYTE    misc_flags;       /* Misc. flags */
+    WORD    reserved;         /* Same value as import_table */
+    HANDLE  nrname_handle;    /* Handle to non-resident name table in memory */
+    WORD    min_swap_area;    /* Min. swap area size */
+    WORD    expected_version; /* Expected Windows version */
+} NE_MODULE;
+
+  /* Loaded file info */
+typedef struct
+{
+    BYTE  length;       /* Length of the structure, not counting this byte */
+    BYTE  fixed_media;  /* File is on removable media */
+    WORD  error;        /* Error code (?) */
+    WORD  date;         /* File date in MS-DOS format */
+    WORD  time;         /* File time in MS-DOS format */
+    char  filename[1];  /* File name */
+} LOADEDFILEINFO;
+
+  /* In-memory segment table */
+typedef struct
+{
+    WORD    filepos;   /* Position in file, in sectors */
+    WORD    size;      /* Segment size on disk */
+    WORD    flags;     /* Segment flags */
+    WORD    minsize;   /* Min. size of segment in memory */
+    WORD    selector;  /* Selector of segment in memory */
+} SEGTABLEENTRY;
+
+
+#define NE_SEG_TABLE(pModule) \
+    ((SEGTABLEENTRY *)((char *)(pModule) + (pModule)->seg_table))
+
+#define NE_MODULE_TABLE(pModule) \
+    ((WORD *)((char *)(pModule) + (pModule)->modref_table))
+
+#ifndef WINELIB
+#pragma pack(4)
+#endif
+
+extern BOOL MODULE_Init(void);
+extern int MODULE_OpenFile( HMODULE hModule );
+extern LPSTR MODULE_GetModuleName( HMODULE hModule );
+extern WORD MODULE_GetOrdinal( HMODULE hModule, char *name );
+extern DWORD MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal );
+extern void MODULE_FixupPrologs( HMODULE hModule );
+
+#endif  /* _WINE_MODULE_H */
diff --git a/include/ne_image.h b/include/ne_image.h
index df89336..b4d3ea7 100644
--- a/include/ne_image.h
+++ b/include/ne_image.h
@@ -3,8 +3,8 @@
 
 extern int NE_FixupSegment(struct w_files *wpnt, int segment_num);
 extern int NE_unloadImage(struct w_files *wpnt);
-extern int NE_StartProgram(struct w_files *wpnt);
-extern void NE_InitDLL(struct w_files *wpnt);
+extern int NE_StartProgram( HMODULE hModule );
+extern BOOL NE_InitDLL( HMODULE hModule );
 extern HINSTANCE NE_LoadImage(struct w_files *wpnt);
 
 #endif /* __WINE_NE_IMAGE_H */
diff --git a/include/neexe.h b/include/neexe.h
index 51e860d..ad596fe 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -6,15 +6,17 @@
 #ifndef NEEXE_H
 #define NEEXE_H
 
+#include "wintypes.h"
+
 /*
  * Old MZ header for DOS programs.  Actually just a couple of fields
  * from it, so that we can find the start of the NE header.
  */
 struct mz_header_s
 {
-    u_short mz_magic;         /* MZ Header signature */
-    u_char  dont_care[0x3a];  /* MZ Header stuff */
-    u_short ne_offset;        /* Offset to extended header */
+    WORD mz_magic;         /* MZ Header signature */
+    BYTE  dont_care[0x3a];  /* MZ Header stuff */
+    WORD ne_offset;        /* Offset to extended header */
 };
 
 #define MZ_SIGNATURE  ('M' | ('Z' << 8))
@@ -24,38 +26,38 @@
  */
 struct ne_header_s
 {
-    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 */
-    u_short entry_tab_length;	/* Length of entry table in bytes	*/
-    u_long  reserved1;		/* Reserved by Microsoft		*/
-    u_short format_flags;	/* Flags about segments in this file	*/
-    u_short auto_data_seg;	/* Automatic data segment number	*/
-    u_short local_heap_length;	/* Initial size of local heap		*/
-    u_short stack_length;	/* Initial size of stack		*/
-    u_short ip;			/* Initial IP				*/
-    u_short cs;			/* Initial CS				*/
-    u_short sp;			/* Initial SP				*/
-    u_short ss;			/* Initial SS				*/
-    u_short n_segment_tab;	/* # of entries in segment table	*/
-    u_short n_mod_ref_tab;	/* # of entries in module reference tab.*/
-    u_short nrname_tab_length; 	/* Length of nonresident-name table     */
-    u_short segment_tab_offset;	/* Offset to segment table		*/
-    u_short resource_tab_offset;/* Offset to resource table		*/
-    u_short rname_tab_offset;	/* Offset to resident-name table	*/
-    u_short moduleref_tab_offset;/* Offset to module reference table	*/
-    u_short iname_tab_offset;	/* Offset to imported name table	*/
-    u_long  nrname_tab_offset;	/* Offset to nonresident-name table	*/
-    u_short n_mov_entry_points;	/* # of movable entry points		*/
-    u_short align_shift_count;	/* Logical sector alignment shift count */
-    u_short n_resource_seg;	/* # of resource segments		*/
-    u_char  operating_system;	/* Flags indicating target OS		*/
-    u_char  additional_flags;	/* Additional information flags		*/
-    u_short fastload_offset;	/* Offset to fast load area		*/
-    u_short fastload_length;	/* Length of fast load area		*/
-    u_short reserved2;		/* Reserved by Microsoft		*/
-    u_short expect_version;	/* Expected Windows version number	*/
+    WORD  ne_magic;           /* NE signature 'NE' */
+    BYTE  linker_version;	/* Linker version number		*/
+    BYTE  linker_revision;	/* Linker revision number		*/
+    WORD  entry_tab_offset;	/* Offset to entry table relative to NE */
+    WORD  entry_tab_length;	/* Length of entry table in bytes	*/
+    DWORD reserved1;		/* Reserved by Microsoft		*/
+    WORD  format_flags;	/* Flags about segments in this file	*/
+    WORD  auto_data_seg;	/* Automatic data segment number	*/
+    WORD  local_heap_length;	/* Initial size of local heap		*/
+    WORD  stack_length;	/* Initial size of stack		*/
+    WORD  ip;			/* Initial IP				*/
+    WORD  cs;			/* Initial CS				*/
+    WORD  sp;			/* Initial SP				*/
+    WORD  ss;			/* Initial SS				*/
+    WORD  n_segment_tab;	/* # of entries in segment table	*/
+    WORD  n_mod_ref_tab;	/* # of entries in module reference tab.*/
+    WORD  nrname_tab_length; 	/* Length of nonresident-name table     */
+    WORD  segment_tab_offset;	/* Offset to segment table		*/
+    WORD  resource_tab_offset;/* Offset to resource table		*/
+    WORD  rname_tab_offset;	/* Offset to resident-name table	*/
+    WORD  moduleref_tab_offset;/* Offset to module reference table	*/
+    WORD  iname_tab_offset;	/* Offset to imported name table	*/
+    DWORD nrname_tab_offset;	/* Offset to nonresident-name table	*/
+    WORD  n_mov_entry_points;	/* # of movable entry points		*/
+    WORD  align_shift_count;	/* Logical sector alignment shift count */
+    WORD  n_resource_seg;	/* # of resource segments		*/
+    BYTE  operating_system;	/* Flags indicating target OS		*/
+    BYTE  additional_flags;	/* Additional information flags		*/
+    WORD  fastload_offset;	/* Offset to fast load area		*/
+    WORD  fastload_length;	/* Length of fast load area		*/
+    WORD  reserved2;		/* Reserved by Microsoft		*/
+    WORD  expect_version;	/* Expected Windows version number	*/
 };
 
 #define NE_SIGNATURE  ('N' | ('E' << 8))
@@ -88,10 +90,10 @@
  */
 struct ne_segment_table_entry_s
 {
-    u_short seg_data_offset;	/* Sector offset of segment data	*/
-    u_short seg_data_length;	/* Length of segment data		*/
-    u_short seg_flags;		/* Flags associated with this segment	*/
-    u_short min_alloc;		/* Minimum allocation size for this	*/
+    WORD seg_data_offset;	/* Sector offset of segment data	*/
+    WORD seg_data_length;	/* Length of segment data		*/
+    WORD seg_flags;		/* Flags associated with this segment	*/
+    WORD min_alloc;		/* Minimum allocation size for this	*/
 };
 
 /*
@@ -113,11 +115,11 @@
  */
 struct relocation_entry_s
 {
-    u_char  address_type;	/* Relocation address type		*/
-    u_char  relocation_type;	/* Relocation type			*/
-    u_short offset;		/* Offset in segment to fixup		*/
-    u_short target1;		/* Target specification			*/
-    u_short target2;		/* Target specification			*/
+    BYTE address_type;	/* Relocation address type		*/
+    BYTE relocation_type;	/* Relocation type			*/
+    WORD offset;		/* Offset in segment to fixup		*/
+    WORD target1;		/* Target specification			*/
+    WORD target2;		/* Target specification			*/
 };
 
 /*
diff --git a/include/resource.h b/include/resource.h
index 88c3585a..d389ce4 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -1,27 +1,28 @@
+/*
+ * Resource definitions
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
 #ifndef __WINE_RESOURCE_H
 #define __WINE_RESOURCE_H
 
-#include "dlls.h"
+#include "wintypes.h"
 
-typedef struct resource_s {
-	struct resource_s *next;
-	HANDLE info_mem;	/* this struct */
-	HANDLE rsc_mem;		/* resource data */
-	/* */
-	HANDLE instance;	/* resource instance */
-	LPSTR name;		/* resource name */
-	LPSTR type;		/* resource type */
-	int count;		/* lock count */
-	int size;		/* resource size */
-	int fd;			/* fd */
-	int offset;		/* offset */
-	struct w_files *wpnt;
-} RESOURCE;
+extern int NE_AccessResource( HMODULE hModule, HRSRC hRsrc );
+extern BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle );
+extern HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId );
+extern DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc );
+extern SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle );
+extern HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size );
+extern HGLOBAL NE_LoadResource( HMODULE hModule,  HRSRC hRsrc );
 
-struct ResourceTable{
+struct ResourceTable
+{
         int id,type;
         char *name;
         unsigned char* value;
         unsigned size;
 };
+
 #endif /* __WINE_RESOURCE_H */
diff --git a/include/selectors.h b/include/selectors.h
index 13cb836..9f7ef80 100644
--- a/include/selectors.h
+++ b/include/selectors.h
@@ -18,14 +18,12 @@
 
 #include "dlls.h"
 
-extern WORD *CreateSelectors( struct w_files * wpnt );
+extern void CreateSelectors(void);
 
 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 );
diff --git a/include/stackframe.h b/include/stackframe.h
index 3a1bf2d..a6a9ac7 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -14,10 +14,10 @@
 #pragma pack(1)
 #endif
 
+  /* 16-bit stack layout after CallTo32() */
 typedef struct
 {
     WORD    saved_ss;                /* saved previous 16-bit stack */
-    WORD    saved_bp;
     WORD    saved_sp;
     WORD    ds;                      /* 16-bit ds */
     DWORD   entry_point WINE_PACKED; /* entry point to call */
@@ -29,13 +29,32 @@
     WORD    args[1];                 /* arguments to API function */
 } STACK16FRAME;
 
+  /* 32-bit stack layout after CallTo16() */
+typedef struct
+{
+    DWORD   saved_esp;      /* saved previous 32-bit stack */
+    DWORD   edi;            /* saved registers */
+    DWORD   esi;
+    DWORD   edx;
+    DWORD   ecx;
+    DWORD   ebx;
+    DWORD   ebp;            /* saved 32-bit frame pointer */
+    DWORD   retaddr;        /* return address */
+    DWORD   codeselector;   /* code selector for return address */
+    DWORD   args[1];        /* arguments to 16-bit function */
+} STACK32FRAME;
+
 #ifndef WINELIB
 #pragma pack(4)
 #endif
 
+  /* Saved 16-bit stack */
 extern WORD IF1632_Saved16_ss;
 extern WORD IF1632_Saved16_sp;
-extern WORD IF1632_Saved16_bp;
+
+  /* Saved 32-bit stack */
+extern DWORD IF1632_Saved32_esp;
+
 
 #define CURRENT_STACK16 \
     ((STACK16FRAME *)PTR_SEG_OFF_TO_LIN(IF1632_Saved16_ss,IF1632_Saved16_sp))
diff --git a/include/task.h b/include/task.h
index 8be9787..a69fea7 100644
--- a/include/task.h
+++ b/include/task.h
@@ -1,27 +1,114 @@
 /*
  * Task definitions
+ *
+ * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef TASK_H
-#define TASK_H
+#ifndef _WINE_TASK_H
+#define _WINE_TASK_H
 
-#include "toolhelp.h"
+#include "wintypes.h"
 
-typedef struct {
-	TASKENTRY	te;
-	int		unix_pid;
-	HICON		hIcon;
-	HWND		*lpWndList;
-	void		*lpPrevTask;
-	void		*lpNextTask;
-} WINETASKENTRY;
-typedef WINETASKENTRY *LPWINETASKENTRY;
+#ifndef WINELIB
+#pragma pack(1)
+#endif
 
-#define MAXWIN_PER_TASK  256
+  /* Process database (i.e. a normal DOS PSP) */
 
-HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent);
-BOOL RemoveWindowFromTask(HTASK hTask, HWND hWnd);
-BOOL AddWindowToTask(HTASK hTask, HWND hWnd);
+typedef struct
+{
+    WORD   int20;            /* int 20h instruction */
+    WORD   nextParagraph;    /* Segment of next paragraph */
+    BYTE   reserved1;
+    BYTE   dispatcher[5];    /* Long call to DOS */
+    DWORD  savedint22;       /* Saved int 22h handler */
+    DWORD  savedint23;       /* Saved int 23h handler */
+    DWORD  savedint24;       /* Saved int 24h handler */
+    WORD   parentPSP;        /* Selector of parent PSP */
+    BYTE   fileHandles[20];  /* Open file handles */
+    HANDLE environment;      /* Selector of environment */
+    WORD   reserved2[23];
+    BYTE   fcb1[16];         /* First FCB */
+    BYTE   fcb2[20];         /* Second FCB */
+    BYTE   cmdLine[128];     /* Command-line (first byte is length) */
+} PDB;
 
-#endif /* TASK_H */
 
+  /* Segment containing MakeProcInstance() thunks */
+typedef struct
+{
+    WORD  next;       /* Selector of next segment */
+    WORD  magic;      /* Thunks signature */
+    WORD  unused;
+    WORD  free;       /* Head of the free list */
+    WORD  thunks[4];  /* Each thunk is 4 words long */
+} THUNKS;
+
+#define THUNK_MAGIC  ('P' | ('T' << 8))
+
+
+  /* Task database. See 'Windows Internals' p. 226 */
+typedef struct
+{
+    HTASK   hNext;                      /* Selector of next TDB */
+    WORD    sp;                         /* Stack pointer of task */
+    WORD    ss;                         /* Stack segment of task */
+    WORD    nEvents;                    /* Events for this task */
+    char    priority;                   /* Task priority, between -32 and 15 */
+    BYTE    unused1;
+    HGLOBAL hStack32;                   /* Handle to 32-bit stack */
+    WORD    hSelf;                      /* Selector of this TDB */
+    WORD    unused3;
+    DWORD   esp;                        /* 32-bit stack pointer */
+    WORD    ctrlword8087;               /* 80x87 control word */
+    WORD    flags;                      /* Task flags */
+    WORD    error_flags;                /* Error handling flags */
+    WORD    version;                    /* Expected Windows version */
+    HANDLE  hInstance;                  /* Instance handle  for this task */
+    HMODULE hModule;                    /* Module handle */
+    HANDLE  hQueue;                     /* Selector of task message queue */
+    HTASK   hParent;                    /* Selector of TDB of parent task */
+    WORD    signal_flags;               /* Flags related to signal handler */
+    DWORD   sighandler WINE_PACKED;     /* Signal handler */
+    DWORD   userhandler WINE_PACKED;    /* USER signal handler */
+    DWORD   discardhandler WINE_PACKED; /* Handler for GlobalDiscard() */
+    DWORD   int0 WINE_PACKED;           /* int 0 (divide by zero) handler */
+    DWORD   int2 WINE_PACKED;           /* int 2 (NMI) handler */
+    DWORD   int4 WINE_PACKED;           /* int 4 (INTO) handler */
+    DWORD   int6 WINE_PACKED;           /* int 6 (invalid opcode) handler */
+    DWORD   int7 WINE_PACKED;           /* int 7 (coprocessor) handler */
+    DWORD   int3e WINE_PACKED;          /* int 3e (80x87 emulator) handler */
+    DWORD   int75 WINE_PACKED;          /* int 75 (80x87 error) handler */
+    DWORD   compat_flags WINE_PACKED;   /* Compatibility flags */
+    BYTE    unused4[14];
+    HANDLE  hPDB;                       /* Selector of PDB (i.e. PSP) */
+    DWORD   dta WINE_PACKED;            /* Current DTA */
+    BYTE    curdrive;                   /* Current drive */
+    BYTE    curdir[65];                 /* Current directory */
+    WORD    unused5;
+    HTASK   hYieldTo;                   /* Next task to schedule */
+    DWORD   dlls_to_init;               /* Ptr to list of DLL to initialize */
+    HANDLE  hCSAlias;                   /* Code segment alias for this TDB */
+    THUNKS  thunks WINE_PACKED;         /* Make proc instance thunks */
+    WORD    more_thunks[6*4];           /* Space for 6 more thunks */
+    BYTE    module_name[8];             /* Module name for task */
+    WORD    magic;                      /* TDB signature */
+    DWORD   unused7;
+    PDB     pdb;                        /* PDB for this task */
+} TDB;
+
+#define TDB_MAGIC    ('T' | ('D' << 8))
+
+  /* TDB flags */
+#define TDBF_WINOLDAP   0x0001
+#define TDBF_OS2APP     0x0008
+#define TDBF_WIN32S     0x0010
+
+#ifndef WINELIB
+#pragma pack(4)
+#endif
+
+  /* TASK_Reschedule() 16-bit entry point */
+extern FARPROC RELAY_RescheduleProcAddr;
+
+#endif /* _WINE_TASK_H */
diff --git a/include/win.h b/include/win.h
index e9cbb90..e1d1efe 100644
--- a/include/win.h
+++ b/include/win.h
@@ -35,7 +35,7 @@
     RECT         rectNormal;     /* Window rect. when in normal state */
     POINT        ptIconPos;      /* Icon position */
     POINT        ptMaxPos;       /* Maximized window position */
-    HANDLE       hmemTaskQ;      /* Task queue global memory handle */
+    HGLOBAL      hmemTaskQ;      /* Task queue global memory handle */
     HRGN         hrgnUpdate;     /* Update region */
     HWND         hwndPrevActive; /* Previous active top-level window */
     HWND         hwndLastActive; /* Last active popup hwnd */
@@ -51,7 +51,6 @@
     Window       window;         /* X window (only for top-level windows) */
     HMENU        hSysMenu;	 /* window's copy of System Menu */
     HANDLE       hProp;          /* Handle of Properties List */
-    HTASK        hTask;          /* Task Handle of the owner */
     WORD         wExtra[1];      /* Window extra bytes */
 } WND;
 
diff --git a/include/windows.h b/include/windows.h
index 2e639f9..f74aa3e 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -567,7 +567,9 @@
 
   /* Fonts */
 
-#define LF_FACESIZE 32
+#define LF_FACESIZE     32
+#define LF_FULLFACESIZE 64
+
 typedef struct tagLOGFONT
 {
     INT lfHeight, lfWidth, lfEscapement, lfOrientation, lfWeight;
@@ -576,6 +578,13 @@
     BYTE lfFaceName[LF_FACESIZE] WINE_PACKED;
 } LOGFONT, *PLOGFONT, *NPLOGFONT, *LPLOGFONT;
 
+typedef struct tagENUMLOGFONT
+{
+  LOGFONT elfLogFont;
+  BYTE elfFullName[LF_FULLFACESIZE] WINE_PACKED;
+  BYTE elfStyle[LF_FACESIZE] WINE_PACKED;
+} ENUMLOGFONT,*PENUMLOGFONT,*NPENUMLOGFONT,*LPENUMLOGFONT;
+
   /* lfWeight values */
 #define FW_DONTCARE	    0
 #define FW_THIN 	    100
@@ -1248,6 +1257,21 @@
 
 #define MAKEINTRESOURCE(i) (SEGPTR)((DWORD)((WORD)(i)))
 
+/* Predefined resource types */
+#define RT_CURSOR	    MAKEINTRESOURCE(1)
+#define RT_BITMAP	    MAKEINTRESOURCE(2)
+#define RT_ICON 	    MAKEINTRESOURCE(3)
+#define RT_MENU 	    MAKEINTRESOURCE(4)
+#define RT_DIALOG	    MAKEINTRESOURCE(5)
+#define RT_STRING	    MAKEINTRESOURCE(6)
+#define RT_FONTDIR	    MAKEINTRESOURCE(7)
+#define RT_FONT 	    MAKEINTRESOURCE(8)
+#define RT_ACCELERATOR	    MAKEINTRESOURCE(9)
+#define RT_RCDATA	    MAKEINTRESOURCE(10)
+#define RT_GROUP_CURSOR     MAKEINTRESOURCE(12)
+#define RT_GROUP_ICON	    MAKEINTRESOURCE(14)
+
+/* Predefined resources */
 #define IDI_APPLICATION  MAKEINTRESOURCE(32512)
 #define IDI_HAND         MAKEINTRESOURCE(32513)
 #define IDI_QUESTION     MAKEINTRESOURCE(32514)
@@ -2091,6 +2115,7 @@
 #define LMEM_FIXED          0   
 #define LMEM_MOVEABLE       0x0002
 #define LMEM_ZEROINIT       0x0040
+#define LMEM_MODIFY         0x0080
 #define LMEM_DISCARDABLE    0x0F00
 #define LMEM_WINE_ALIGN     0x1000
 
@@ -2431,7 +2456,7 @@
 Fa(HANDLE,GetCodeHandle,FARPROC,a)
 Fa(HANDLE,GetMetaFile,LPSTR,a)
 Fa(HANDLE,GetMetaFileBits,HANDLE,a)
-Fa(HANDLE,GetModuleHandle,LPSTR,a)
+Fa(HANDLE,GetModuleHandle,LPCSTR,a)
 Fa(HANDLE,GetStockObject,int,a)
 Fa(HANDLE,GetWindowTask,HWND,a)
 Fa(HANDLE,LoadLibrary,LPSTR,a)
@@ -2449,6 +2474,7 @@
 Fa(HDC,GetWindowDC,HWND,a)
 Fa(HDWP,BeginDeferWindowPos,INT,nNumWindows)
 Fa(HFONT,CreateFontIndirect,LOGFONT FAR*,a)
+Fa(HGLOBAL,GetTaskQueue,HTASK,a)
 Fa(HGLOBAL,GlobalFree,HGLOBAL,a)
 Fa(HGLOBAL,GlobalLRUNewest,HGLOBAL,a)
 Fa(HGLOBAL,GlobalLRUOldest,HGLOBAL,a)
@@ -2456,6 +2482,7 @@
 Fa(HMENU,GetMenu,HWND,a)
 Fa(HMENU,LoadMenuIndirect,LPSTR,a)
 Fa(HMETAFILE,CloseMetaFile,HANDLE,a)
+Fa(HMODULE, GetExePtr,HANDLE,a)
 Fa(HPALETTE,CreatePalette,LPLOGPALETTE,a)
 Fa(HPEN,CreatePenIndirect,LOGPEN FAR*,a)
 Fa(HRGN,CreateEllipticRgnIndirect,LPRECT,a)
@@ -2477,11 +2504,12 @@
 Fa(LONG,DispatchMessage,LPMSG,msg)
 Fa(LONG,SetSwapAreaSize,WORD,a)
 Fa(LPSTR,AnsiLower,LPSTR,a)
-Fa(SEGPTR,AnsiNext,SEGPTR,a)
 Fa(LPSTR,AnsiUpper,LPSTR,a)
 Fa(LPSTR,GlobalLock,HGLOBAL,a)
 Fa(LPSTR,LockResource,HANDLE,a)
+Fa(SEGPTR,AnsiNext,SEGPTR,a)
 Fa(SEGPTR,GlobalWire,HGLOBAL,a)
+Fa(SEGPTR,WIN16_LockResource,HANDLE,a)
 Fa(SEGPTR,WIN16_GlobalLock,HGLOBAL,a)
 Fa(UINT,GDIRealizePalette,HDC,a)
 Fa(UINT,RealizePalette,HDC,a)
@@ -2490,6 +2518,7 @@
 Fa(WORD,AllocSelectorArray,WORD,a)
 Fa(WORD,ArrangeIconicWindows,HWND,a)
 Fa(WORD,EnumClipboardFormats,WORD,a)
+Fa(WORD,FarGetOwner,HANDLE,a)
 Fa(WORD,FreeSelector,WORD,a)
 Fa(WORD,GetBkMode,HDC,a)
 Fa(WORD,GetDriveType,INT,a)
@@ -2499,7 +2528,6 @@
 Fa(WORD,GetROP2,HDC,a)
 Fa(WORD,GetRelAbs,HDC,a)
 Fa(WORD,GetStretchBltMode,HDC,a)
-Fa(WORD,GetTaskQueue,HANDLE,a)
 Fa(WORD,GetTextAlign,HDC,a)
 Fa(WORD,GlobalDOSFree,WORD,a)
 Fa(WORD,GlobalFlags,HGLOBAL,a)
@@ -2545,6 +2573,7 @@
 Fa(void,GetCursorPos,LPPOINT,a)
 Fa(void,GetKeyboardState,BYTE FAR*,a)
 Fa(void,GlobalFix,HGLOBAL,a)
+Fa(void,GlobalFreeAll,HANDLE,a)
 Fa(void,GlobalNotify,FARPROC,a)
 Fa(void,GlobalUnfix,HGLOBAL,a)
 Fa(void,HideCaret,HWND,a)
@@ -2602,21 +2631,23 @@
 Fb(BOOL,SetWindowPlacement,HWND,a,LPWINDOWPLACEMENT,b)
 Fb(BOOL,ShowWindow,HWND,a,int,b) 
 Fb(BOOL,TranslateMDISysAccel,HWND,a,LPMSG,b)
-Fb(BOOL,UnhookWindowsHook,short,a,HHOOK,b)
+Fb(BOOL,UnhookWindowsHook,short,a,FARPROC,b)
 Fb(BOOL,UnregisterClass,LPSTR,a,HANDLE,b)
 Fb(DWORD,GetNearestColor,HDC,a,DWORD,b)
 Fb(DWORD,SetBkColor,HDC,a,COLORREF,b)
 Fb(DWORD,SetMapperFlags,HDC,a,DWORD,b)
 Fb(DWORD,SetTextColor,HDC,a,DWORD,b)
-Fb(FARPROC,GetProcAddress,HANDLE,a,LPSTR,b)
+Fb(DWORD,SizeofResource,HANDLE,a,HRSRC,b)
+Fb(FARPROC,GetProcAddress,HANDLE,a,SEGPTR,b)
 Fb(FARPROC,MakeProcInstance,FARPROC,a,HANDLE,b)
+Fb(FARPROC,SetWindowsHook,short,a,FARPROC,b)
 Fb(HANDLE,CopyMetaFile,HANDLE,a,LPSTR,b)
-Fb(HANDLE,GetProp,HWND,a,LPSTR,b)
+Fb(HANDLE,GetProp,HWND,a,SEGPTR,b)
 Fb(HANDLE,LoadAccelerators,HANDLE,a,SEGPTR,b)
 Fb(HANDLE,LoadModule,LPSTR,a,LPVOID,b)
 Fb(HANDLE,LoadResource,HANDLE,a,HANDLE,b)
 Fb(HANDLE,LocalAlloc,WORD,a,WORD,b)
-Fb(HANDLE,RemoveProp,HWND,a,LPSTR,b)
+Fb(HANDLE,RemoveProp,HWND,a,SEGPTR,b)
 Fb(HANDLE,SelectObject,HDC,a,HANDLE,b)
 Fb(HANDLE,SetClipboardData,WORD,a,HANDLE,b)
 Fb(HBITMAP,LoadBitmap,HANDLE,a,SEGPTR,b)
@@ -2625,7 +2656,7 @@
 Fb(HCURSOR,LoadCursor,HANDLE,a,SEGPTR,b)
 Fb(HDC,BeginPaint,HWND,a,LPPAINTSTRUCT,b) 
 Fb(HGLOBAL,GlobalAlloc,WORD,a,DWORD,b)
-Fb(HHOOK,SetWindowsHook,short,a,HOOKPROC,b)
+Fb(HGLOBAL,SetTaskQueue,HTASK,a,HGLOBAL,b)
 Fb(HICON,LoadIcon,HANDLE,a,SEGPTR,b)
 Fb(HMENU,GetSubMenu,HMENU,a,short,b)
 Fb(HMENU,GetSystemMenu,HWND,a,BOOL,b)
@@ -2672,9 +2703,7 @@
 Fb(WORD,SetRelAbs,HDC,a,WORD,b)
 Fb(WORD,SetStretchBltMode,HDC,a,WORD,b)
 Fb(WORD,SetSystemPaletteUse,HDC,a,WORD,b)
-Fb(WORD,SetTaskQueue,HANDLE,a,HANDLE,b)
 Fb(WORD,SetTextAlign,HDC,a,WORD,b)
-Fb(WORD,SizeofResource,HANDLE,a,HANDLE,b)
 Fb(WORD,WinExec,LPSTR,a,WORD,b)
 Fb(int,AccessResource,HANDLE,a,HANDLE,b)
 Fb(int,BuildCommDCB,LPSTR,a,DCB*,b)
@@ -2695,6 +2724,7 @@
 Fb(int,SetSoundNoise,int,a,int,b)
 Fb(int,SetVoiceQueueSize,int,a,int,b)
 Fb(int,SetVoiceThreshold,int,a,int,b)
+Fb(int,Throw,LPCATCHBUF,a,int,b)
 Fb(int,TransmitCommChar,int,a,char,b)
 Fb(int,UngetCommChar,int,a,char,b)
 Fb(short,SetTextCharacterExtra,HDC,a,short,b)
@@ -2703,6 +2733,7 @@
 Fb(void,DrawFocusRect,HDC,a,LPRECT,b)
 Fb(void,EndDialog,HWND,a,short,b)
 Fb(void,EndPaint,HWND,a,LPPAINTSTRUCT,b)
+Fb(void,FarSetOwner,HANDLE,a,WORD,b)
 Fb(void,GetClientRect,HWND,a,LPRECT,b)
 Fb(void,GetCodeInfo,FARPROC,lpProc,LPVOID,lpSegInfo)
 Fb(void,GetWindowRect,HWND,a,LPRECT,b)
@@ -2716,7 +2747,6 @@
 Fb(void,SetDCState,HDC,a,HDC,b)
 Fb(void,SetWindowText,HWND,a,LPSTR,b)
 Fb(void,ShowOwnedPopups,HWND,a,BOOL,b)
-Fb(void,Throw,LPCATCHBUF,a,int,b)
 Fb(void,ValidateRect,HWND,a,LPRECT,b)
 Fb(void,ValidateRgn,HWND,a,HRGN,b)
 Fc(BOOL,CheckMenuItem,HMENU,a,WORD,b,WORD,c)
@@ -2729,7 +2759,7 @@
 Fc(BOOL,EnumChildWindows,HWND,a,FARPROC,b,LONG,c)
 Fc(BOOL,EnumTaskWindows,HANDLE,a,FARPROC,b,LONG,c)
 Fc(BOOL,FillRgn,HDC,a,HRGN,b,HBRUSH,c)
-Fc(BOOL,GetClassInfo,HANDLE,a,LPSTR,b,LPWNDCLASS,c)
+Fc(BOOL,GetClassInfo,HANDLE,a,SEGPTR,b,LPWNDCLASS,c)
 Fc(BOOL,GetUpdateRect,HWND,a,LPRECT,b,BOOL,c)
 Fc(BOOL,IntersectRect,LPRECT,a,LPRECT,b,LPRECT,c)
 Fc(BOOL,LPtoDP,HDC,a,LPPOINT,b,int,c)
@@ -2740,7 +2770,7 @@
 Fc(BOOL,PtInRegion,HRGN,a,short,b,short,c)
 Fc(BOOL,PtVisible,HDC,a,short,b,short,c)
 Fc(BOOL,RemoveMenu,HMENU,a,WORD,b,WORD,c)
-Fc(BOOL,SetProp,HWND,a,LPSTR,b,HANDLE,c)
+Fc(BOOL,SetProp,HWND,a,SEGPTR,b,HANDLE,c)
 Fc(BOOL,SubtractRect,LPRECT,a,LPRECT,b,LPRECT,c)
 Fc(BOOL,UnionRect,LPRECT,a,LPRECT,b,LPRECT,c)
 Fc(BOOL,WriteProfileString,LPSTR,a,LPSTR,b,LPSTR,c)
diff --git a/include/wintypes.h b/include/wintypes.h
index 88c627f..ade3d57 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -23,7 +23,11 @@
 typedef DWORD *LPDWORD;
 typedef LONG *LPLONG;
 typedef void *LPVOID;
+#ifdef WINELIB
 typedef long (*FARPROC)();
+#else
+typedef SEGPTR FARPROC;
+#endif
 typedef FARPROC DLGPROC;
 typedef int CATCHBUF[9];
 typedef int *LPCATCHBUF;
@@ -50,6 +54,7 @@
 DECLARE_HANDLE(HPALETTE);
 DECLARE_HANDLE(HPEN);
 DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HRSRC);
 DECLARE_HANDLE(HTASK);
 DECLARE_HANDLE(HWND);
 DECLARE_HANDLE(LOCALHANDLE);
@@ -65,7 +70,7 @@
 #define CALLBACK            PASCAL
 
 #ifndef NULL
-#define NULL (void *)0
+#define NULL (0)
 #endif
 
 #ifdef WINELIB
diff --git a/loader/Imakefile b/loader/Imakefile
index 69bf07a..b3863a6 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -6,6 +6,7 @@
 	dump.c \
 	ldt.c \
 	main.c \
+	module.c \
 	ne_image.c \
 	ne_resource.c \
 	pe_image.c \
diff --git a/loader/dump.c b/loader/dump.c
index 2011bbe..39344e5 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -40,24 +40,6 @@
 }
 
 /**********************************************************************
- *					PrintSegmentTable
- */
-void
-PrintSegmentTable(struct ne_segment_table_entry_s *seg_table, int nentries)
-{
-    int i;
-
-    for (i = 0; i < nentries; i++)
-    {
-	printf("  %2d: OFFSET %04x, LENGTH %04x, ",
-	       i + 1, seg_table[i].seg_data_offset, 
-	       seg_table[i].seg_data_length);
-	printf("FLAGS %04x, MIN ALLOC %04x\n",
-	       seg_table[i].seg_flags, seg_table[i].min_alloc);
-    }
-}
-
-/**********************************************************************
  *					PrintRelocationTable
  */
 void 
diff --git a/loader/library.c b/loader/library.c
index 8c02181..e303bbb 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -21,12 +21,13 @@
 #include "task.h"
 #include "toolhelp.h"
 #include "selectors.h"
-#include "stddebug.h"
-#include "debug.h"
 #include "prototypes.h"
 #include "library.h"
 #include "ne_image.h"
 #include "pe_image.h"
+#include "module.h"
+#include "stddebug.h"
+#include "debug.h"
 
 struct w_files *wine_files = NULL;
 static char *DLL_Extensions[] = { "dll", NULL };
@@ -63,7 +64,7 @@
     
     return w;
 }
-
+/*
 int IsDLLLoaded(char *name)
 {
 	struct w_files *wpnt;
@@ -72,16 +73,16 @@
 		return 1;
 
 	for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
-		if(strcmp(wpnt->name, name) == 0)
+		if(strcmp(wpnt->name, name) == 0 )
 			return 1;
 
 	return 0;
 }
-
+*/
 void InitDLL(struct w_files *wpnt)
 {
 	if (wpnt->ne) 
-		NE_InitDLL(wpnt);
+		NE_InitDLL(wpnt->hModule);
 	else
 		PE_InitDLL(wpnt);
 }
@@ -142,9 +143,11 @@
     }
     
     /* already loaded ? */
-    for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next)
-    	if (strcasecmp(wpnt->name, modulename) == 0)
-    		return wpnt->hinstance;
+    for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next)  {
+      if (strcasecmp(wpnt->name, modulename) == 0 && filetype == wpnt->type) {
+	return wpnt->hinstance;
+      }
+    }
 
     /*
      * search file
@@ -195,6 +198,8 @@
      */
     wpnt->filename = strdup(buffer);
     wpnt->name = strdup(modulename);
+    wpnt->type = filetype;
+    wpnt->initialised = FALSE;
 
     /* read mz header */
     wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
@@ -260,121 +265,6 @@
 }
 
 /**********************************************************************
- *				GetModuleHandle	[KERNEL.47]
- */
-HANDLE GetModuleHandle(LPSTR lpModuleName)
-{
-	register struct w_files *w = wine_files;
-	int 	i;
-	char dllname[256];
-
-	if ((int) lpModuleName & 0xffff0000)
-		ExtractDLLName(lpModuleName, dllname);
-
-	if ((int) lpModuleName & 0xffff0000)
-	 	dprintf_module(stddeb,"GetModuleHandle('%s');\n", lpModuleName);
-	else
-	 	dprintf_module(stddeb,"GetModuleHandle('%p');\n", lpModuleName);
-
-/* 	dprintf_module(stddeb,"GetModuleHandle // searching in builtin libraries\n");*/
-	for (i = 0; i < N_BUILTINS; i++) {
-		if (dll_builtin_table[i].dll_name == NULL) break;
-		if (!dll_builtin_table[i].dll_is_used){
-			dprintf_module(stddeb,"Skipping builtin %s\n",
-			dll_builtin_table[i].dll_name);
-			continue;
-		}
-		if (((int) lpModuleName & 0xffff0000) == 0) {
-			if (0xFF00 + i == (int) lpModuleName) {
-				dprintf_module(stddeb,"GetModuleHandle('%s') return %04X \n",
-				       lpModuleName, 0xff00 + i);
-				return 0xFF00 + i;
-				}
-			}
-		else if (strcasecmp(dll_builtin_table[i].dll_name, dllname) == 0) {
-			dprintf_module(stddeb,"GetModuleHandle('%p') return %04X \n", 
-							lpModuleName, 0xFF00 + i);
-			return (0xFF00 + i);
-			}
-		}
-
- 	dprintf_module(stddeb,"GetModuleHandle // searching in loaded modules\n");
-	while (w) {
-/*		dprintf_module(stddeb,"GetModuleHandle // '%x' \n", w->name);  */
-		if (((int) lpModuleName & 0xffff0000) == 0) {
-			if (w->hinstance == (int) lpModuleName) {
-				dprintf_module(stddeb,"GetModuleHandle('%p') return %04X \n",
-				       lpModuleName, w->hinstance);
-				return w->hinstance;
-				}
-			}
-		else if (strcasecmp(w->name, dllname) == 0) {
-			dprintf_module(stddeb,"GetModuleHandle('%s') return %04X \n", 
-							lpModuleName, w->hinstance);
-			return w->hinstance;
-			}
-		w = w->next;
-		}
-	printf("GetModuleHandle('%p') not found !\n", lpModuleName);
-	return 0;
-}
-
-
-/**********************************************************************
- *				GetModuleUsage	[KERNEL.48]
- */
-int GetModuleUsage(HANDLE hModule)
-{
-	struct w_files *w;
-
-	dprintf_module(stddeb,"GetModuleUsage(%04X);\n", hModule);
-
-	/* built-in dll ? */
-	if (IS_BUILTIN_DLL(hModule)) 
-		return 2;
-		
-	w = GetFileInfo(hModule);
-/*	return w->Usage; */
-	return 1;
-}
-
-
-/**********************************************************************
- *				GetModuleFilename [KERNEL.49]
- */
-int GetModuleFileName(HANDLE hModule, LPSTR lpFileName, short nSize)
-{
-    struct w_files *w;
-    LPSTR str;
-    char windir[256], temp[256];
-
-    dprintf_module(stddeb,"GetModuleFileName(%04X, %p, %d);\n", hModule, lpFileName, nSize);
-
-    if (lpFileName == NULL) return 0;
-    if (nSize < 1) return 0;
-
-    /* built-in dll ? */
-    if (IS_BUILTIN_DLL(hModule)) {
-	GetWindowsDirectory(windir, sizeof(windir));
-	sprintf(temp, "%s\\%s.DLL", windir, dll_builtin_table[hModule & 0x00ff].dll_name);
-	ToDos(temp);
-	strncpy(lpFileName, temp, nSize);
-        dprintf_module(stddeb,"GetModuleFileName copied '%s' (internal dll) return %d \n", lpFileName, nSize);
-	return strlen(lpFileName);
-    }
-
-    /* check loaded dlls */
-    if ((w = GetFileInfo(hModule)) == NULL)
-    	return 0;
-    str = DOS_GetDosFileName(w->filename);
-    if (nSize > strlen(str)) nSize = strlen(str) + 1;
-    strncpy(lpFileName, str, nSize);
-    dprintf_module(stddeb,"GetModuleFileName copied '%s' return %d \n", lpFileName, nSize);
-    return nSize - 1;
-}
-
-
-/**********************************************************************
  *				LoadLibrary	[KERNEL.95]
  */
 HANDLE LoadLibrary(LPSTR libname)
@@ -429,214 +319,33 @@
 }
 
 
-/**********************************************************************
- *					GetProcAddress	[KERNEL.50]
+/***********************************************************************
+ *           GetProcAddress   (KERNEL.50)
  */
-FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
+FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
 {
-#ifdef WINELIB
-    WINELIB_UNIMP ("GetProcAddress");
-#else
-    int		ret;
-    WORD        sel, addr;
-    register struct w_files *w = wine_files;
-    int 	ordinal, len;
-    char 	* cpnt;
-    char	C[128];
-    HTASK	hTask;
-    LPTASKENTRY lpTask;
+    WORD ordinal;
+    SEGPTR ret;
 
-    /* built-in dll ? */
-    if (IS_BUILTIN_DLL(hModule))
+    if (!hModule) hModule = GetCurrentTask();
+    hModule = GetExePtr( hModule );
+
+    if (HIWORD(name) != 0)
     {
-	if ((int) proc_name & 0xffff0000) 
-	{
-	    dprintf_module(stddeb,"GetProcAddress: builtin %#04X, '%s'\n", 
-		   hModule, proc_name);
-	    if (GetEntryDLLName(dll_builtin_table[hModule - 0xFF00].dll_name,
-				proc_name, &sel, &addr)) 
-	    {
-		printf("Address not found !\n");
-	    }
-	}
-	else 
-	{
-	    dprintf_module(stddeb,"GetProcAddress: builtin %#04X, %d\n", 
-		   hModule, (int)proc_name);
-	    if (GetEntryDLLOrdinal(dll_builtin_table[hModule-0xFF00].dll_name,
-				   (int)proc_name & 0x0000FFFF, &sel, &addr)) 
-	    {
-		printf("Address not found !\n");
-	    }
-	}
-	ret = MAKELONG(addr, sel);
-	dprintf_module(stddeb,"GetProcAddress // ret=%08X sel=%04X addr=%04X\n", 
-	       ret, sel, addr);
-	return (FARPROC)ret;
+        ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
+        dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
+                        hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
     }
-    if (hModule == 0) 
+    else
     {
-	hTask = GetCurrentTask();
-	dprintf_module(stddeb,"GetProcAddress // GetCurrentTask()=%04X\n", hTask);
-	lpTask = (LPTASKENTRY) GlobalLock(hTask);
-	if (lpTask == NULL) 
-	{
-	    printf("GetProcAddress: can't find current module handle !\n");
-	    return NULL;
-	}
-	hModule = lpTask->hInst;
-	dprintf_module(stddeb,"GetProcAddress: current module=%04X instance=%04X!\n", 
-	       lpTask->hModule, lpTask->hInst);
-	GlobalUnlock(hTask);
+        ordinal = LOWORD(name);
+        dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
+                        hModule, ordinal );
     }
-    while (w && w->hinstance != hModule) 
-	w = w->next;
-    if (w == NULL) 
-	return NULL;
-    dprintf_module(stddeb,"GetProcAddress // Module Found ! w->filename='%s'\n", w->filename);
-    if ((int)proc_name & 0xFFFF0000) 
-    {
-	AnsiUpper(proc_name);
-	dprintf_module(stddeb,"GetProcAddress: %04X, '%s'\n", hModule, proc_name);
-	cpnt = w->ne->nrname_table;
-	while(TRUE) 
-	{
-	    if (((int) cpnt)  - ((int)w->ne->nrname_table) >  
-		w->ne->ne_header->nrname_tab_length)  return NULL;
-	    len = *cpnt++;
-	    strncpy(C, cpnt, len);
-	    C[len] = '\0';
-	    dprintf_module(stddeb,"pointing Function '%s' ordinal=%d !\n", 
-		   C, *((unsigned short *)(cpnt +  len)));
-	    if (strncmp(cpnt, proc_name, len) ==  0) 
-	    {
-		ordinal =  *((unsigned short *)(cpnt +  len));
-		break;
-	    }
-	    cpnt += len + 2;
-	}
-	if (ordinal == 0) 
-	{
-	    printf("GetProcAddress // function '%s' not found !\n", proc_name);
-	    return NULL;
-	}
-    }
-    else 
-    {
-	dprintf_module(stddeb,"GetProcAddress: %#04x, %d\n", hModule, (int) proc_name);
-	ordinal = (int)proc_name;
-    }
-    ret = GetEntryPointFromOrdinal(w, ordinal);
-    if (ret == -1) 
-    {
-	printf("GetProcAddress // Function #%d not found !\n", ordinal);
-	return NULL;
-    }
-    addr  = ret & 0xffff;
-    sel = (ret >> 16);
-    dprintf_module(stddeb,"GetProcAddress // ret=%08X sel=%04X addr=%04X\n", ret, sel, addr);
-    return (FARPROC) ret;
-#endif /* WINELIB */
+    if (!ordinal) return (FARPROC)0;
+
+    ret = MODULE_GetEntryPoint( hModule, ordinal );
+
+    dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", ret );
+    return (FARPROC)ret;
 }
-
-/* internal dlls */
-static void 
-FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
-{
-	lpModule->dwSize = dll->table->dll_table_length * 1024;
-	strcpy(lpModule->szModule, dll->dll_name);
-	lpModule->hModule = 0xff00 + dll->table->dll_number;
-	lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
-	GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
-	lpModule->wNext = 0;
-}
-
-/* loaded dlls */
-static void 
-FillModStructLoaded(MODULEENTRY *lpModule, struct w_files *dll)
-{
-	lpModule->dwSize = 16384;
-	strcpy(lpModule->szModule, dll->name);
-	lpModule->hModule = dll->hinstance;
-	lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
-	GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
-	lpModule->wNext = 0;
-}
-
-/**********************************************************************
- *		ModuleFirst [TOOLHELP.59]
- */
-BOOL ModuleFirst(MODULEENTRY *lpModule)
-{
-	dprintf_module(stddeb,"ModuleFirst(%08X)\n", (int) lpModule);
-	
-	FillModStructBuiltIn(lpModule, &dll_builtin_table[0]);
-	return TRUE;
-}
-
-/**********************************************************************
- *		ModuleNext [TOOLHELP.60]
- */
-BOOL ModuleNext(MODULEENTRY *lpModule)
-{
-	struct w_files *w;
-
-	dprintf_module(stddeb,"ModuleNext(%08X)\n", (int) lpModule);
-
-	if (IS_BUILTIN_DLL(lpModule->hModule)) 
-	{
-		int builtin_no=lpModule->hModule & 0xff;
-		do{
-			/* last built-in ? */
-			if (builtin_no == (N_BUILTINS - 1) ) {
-				if (wine_files) {
-					FillModStructLoaded(lpModule, wine_files);
-					return TRUE;
-				} else
-					return FALSE;
-			}
-			builtin_no++;
-		}while(!dll_builtin_table[builtin_no].dll_is_used);
-
-		FillModStructBuiltIn(lpModule, &dll_builtin_table[builtin_no]);
-		return TRUE;
-	}
-	w = GetFileInfo(lpModule->hModule);
-	if (w->next) {
-		FillModStructLoaded(lpModule, w->next);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/**********************************************************************
- *		ModuleFindHandle [TOOLHELP.62]
- */
-HMODULE ModuleFindHandle(MODULEENTRY *lpModule, HMODULE hModule)
-{
-	struct w_files *w;
-
-	dprintf_module(stddeb,"ModuleFindHandle(%08X, %04X)\n", (int) lpModule, (int)hModule);
-
-	/* built-in dll ? */
-	if (IS_BUILTIN_DLL(hModule)) {
-		FillModStructBuiltIn(lpModule, &dll_builtin_table[hModule & 0xff]);
-		return hModule;
-	}
-
-	/* check loaded dlls */
-	if ((w = GetFileInfo(hModule)) == NULL)
-	    	return (HMODULE) NULL;
-	
-	FillModStructLoaded(lpModule, w);
-	return w->hinstance;
-}
-
-/**********************************************************************
- *		ModuleFindName [TOOLHELP.61]
- */
-HMODULE ModuleFindName(MODULEENTRY *lpModule, LPCSTR lpstrName)
-{
-	return (ModuleFindHandle(lpModule, GetModuleHandle((char*)lpstrName)));
-}
-
diff --git a/loader/main.c b/loader/main.c
index 6fa103e..ce712ae 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -30,7 +30,6 @@
 int Argc;
 HINSTANCE hSysRes, hInstMain;
 unsigned short WIN_StackSize;
-unsigned short WIN_HeapSize;
 
 /**********************************************************************
  *					myerror
@@ -45,21 +44,90 @@
 
     exit(1);
 }
-
+
+
+/***********************************************************************
+ *           Main initialisation routine
+ */
+int MAIN_Init(void)
+{
+    int queueSize;
+
+    SpyInit();
+
+      /* Initialize relay code */
+    if (!RELAY_Init()) return 0;
+
+      /* Create built-in modules */
+    if (!MODULE_Init()) return 0;
+
+      /* Initialize tasks */
+    if (!TASK_Init()) return 0;
+
+      /* Initialize the DOS file system */
+    DOS_InitFS();
+
+      /* Initialize communications */
+    COMM_Init();
+
+#ifndef WINELIB    
+      /* Initialize the DOS memory */
+    INT21_Init();
+
+      /* Create USER heap */
+    if (!USER_HeapInit()) return 0;
+#endif
+    
+      /* Global atom table initialisation */
+    if (!ATOM_Init()) return 0;
+    
+      /* GDI initialisation */
+    if (!GDI_Init()) return 0;
+
+      /* Initialize system colors and metrics*/
+    SYSMETRICS_Init();
+    SYSCOLOR_Init();
+
+      /* Create the DCEs */
+    DCE_Init();
+    
+      /* Initialize built-in window classes */
+    if (!WIDGETS_Init()) return 0;
+
+      /* Initialize dialog manager */
+    if (!DIALOG_Init()) return 0;
+
+      /* Initialize menus */
+    if (!MENU_Init()) return 0;
+
+      /* Create desktop window */
+    if (!WIN_CreateDesktopWindow()) return 0;
+    if (!DESKTOP_Init()) return 0;
+
+      /* Create system message queue */
+    queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
+    if (!MSG_CreateSysMsgQueue( queueSize )) return 0;
+
+    return 1;
+}
+
+
 #ifndef WINELIB
 /**********************************************************************
  *					main
  */
 int _WinMain(int argc, char **argv)
 {
-	char *p, filename[256];
-	HANDLE	hTaskMain;
+    char *p, filename[256];
+    int i;
 
-	struct w_files *wpnt;
+    struct w_files *wpnt;
 #ifdef WINESTAT
-	char * cp;
+    char * cp;
 #endif
 
+    if (!MAIN_Init()) return 0;
+
 	Argc = argc - 1;
 	Argv = argv + 1;
 
@@ -76,13 +144,13 @@
 	    	    strcat(WindowsPath, filename);
 	}
 
-	if ((hInstMain = LoadImage(Argv[0], EXE, 1)) < 32) {
-		fprintf(stderr, "wine: can't load %s!.\n", Argv[0]);
+	for (i = 0; i < Argc; i++)
+        {
+            if ((hInstMain = LoadImage(Argv[i], EXE, 1)) < 32) {
+		fprintf(stderr, "wine: can't load %s!.\n", Argv[i]);
 		exit(1);
-	}
-	hTaskMain = CreateNewTask(hInstMain, 0);
-	dprintf_dll(stddeb,"_WinMain // hTaskMain=%04X hInstMain=%04X !\n",
-		    hTaskMain, hInstMain);
+            }
+        }
 
 	GetPrivateProfileString("wine", "SystemResources", "sysres.dll", 
 				filename, sizeof(filename), WINE_INI);
@@ -110,15 +178,14 @@
      * Initialize signal handling.
      */
     init_wine_signals();
-
+        
     wpnt = GetFileInfo(hInstMain);
     if (Options.debug)
 	wine_debug(0, NULL);
 
-    if (wpnt->ne)
-	return(NE_StartProgram(wpnt));
-    else
-	return(PE_StartProgram(wpnt));
+    Yield();  /* Start the first task */
+    fprintf( stderr, "WinMain: Should never happen: returned from Yield()\n" );
+    return 0;
 }
 
 #endif /* #ifndef WINELIB */
diff --git a/loader/module.c b/loader/module.c
new file mode 100644
index 0000000..7ea2944
--- /dev/null
+++ b/loader/module.c
@@ -0,0 +1,723 @@
+/*
+ * Modules
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "windows.h"
+#include "dlls.h"
+#include "global.h"
+#include "ldt.h"
+#include "module.h"
+#include "neexe.h"
+#include "toolhelp.h"
+#include "stddebug.h"
+/* #define DEBUG_MODULE */
+#include "debug.h"
+
+
+extern BYTE KERNEL_Module_Start[], KERNEL_Module_End[];
+
+extern struct dll_name_table_entry_s dll_builtin_table[];
+
+static HMODULE hFirstModule = 0;
+
+
+/***********************************************************************
+ *           MODULE_Init
+ *
+ * Create the built-in modules.
+ */
+BOOL MODULE_Init(void)
+{
+    HMODULE hModule;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable;
+    struct dll_table_s *table;
+    int i;
+
+      /* Create the built-in modules */
+
+    for (i = 0; i < N_BUILTINS; i++)
+    {
+        if (!dll_builtin_table[i].dll_is_used) continue;
+        table = dll_builtin_table[i].table;
+
+        hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
+                                      table->module_end - table->module_start,
+                                      0, FALSE, FALSE, FALSE );
+        if (!hModule) return FALSE;
+        FarSetOwner( hModule, hModule );
+
+        table->hModule = hModule;
+
+        dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
+                        dll_builtin_table[i].dll_name, hModule );
+
+          /* Allocate the code segment */
+
+        pModule = (NE_MODULE *)GlobalLock( hModule );
+        pSegTable = NE_SEG_TABLE( pModule );
+
+        pSegTable->selector = GLOBAL_CreateBlock(GMEM_FIXED, table->code_start,
+                                                 pSegTable->minsize, hModule,
+                                                 TRUE, TRUE, FALSE );
+        if (!pSegTable->selector) return FALSE;
+        pSegTable++;
+
+          /* Allocate the data segment */
+
+        pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
+                                            hModule, FALSE, FALSE, FALSE );
+        if (!pSegTable->selector) return FALSE;
+        memcpy( GlobalLock( pSegTable->selector ), table->data_start,
+                pSegTable->minsize );
+
+        pModule->next = hFirstModule;
+        hFirstModule = hModule;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MODULE_PrintModule
+ */
+void MODULE_PrintModule( HMODULE hmodule )
+{
+    int i, ordinal;
+    SEGTABLEENTRY *pSeg;
+    BYTE *pstr;
+    WORD *pword;
+    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
+
+      /* Dump the module info */
+
+    printf( "Module %04x:\n", hmodule );
+    printf( "count=%d flags=%04x heap=%d stack=%d\n",
+            pModule->count, pModule->flags,
+            pModule->heap_size, pModule->stack_size );
+    printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
+           pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
+           pModule->seg_count, pModule->modref_count );
+    printf( "os_flags=%d swap_area=%d version=%04x\n",
+            pModule->os_flags, pModule->min_swap_area,
+            pModule->expected_version );
+
+      /* Dump the file info */
+
+    printf( "Filename: '%s'\n",
+         ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
+
+      /* Dump the segment table */
+
+    printf( "\nSegment table:\n" );
+    pSeg = NE_SEG_TABLE( pModule );
+    for (i = 0; i < pModule->seg_count; i++, pSeg++)
+        printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
+                i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
+                pSeg->minsize, pSeg->selector );
+
+      /* Dump the resource table */
+
+    printf( "\nResource table:\n" );
+    if (pModule->res_table)
+    {
+        pword = (WORD *)((BYTE *)pModule + pModule->res_table);
+        printf( "Alignment: %d\n", *pword++ );
+        while (*pword)
+        {
+            struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
+            struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
+            printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
+            for (i = 0; i < ptr->count; i++, pname++)
+                printf( "offset=%d len=%d id=%04x\n",
+                       pname->offset, pname->length, pname->id );
+            pword = (WORD *)pname;
+        }
+    }
+    else printf( "None\n" );
+
+      /* Dump the resident name table */
+
+    printf( "\nResident-name table:\n" );
+    pstr = (char *)pModule + pModule->name_table;
+    while (*pstr)
+    {
+        printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+                *(WORD *)(pstr + *pstr + 1) );
+        pstr += *pstr + 1 + sizeof(WORD);
+    }
+
+      /* Dump the module reference table */
+
+    printf( "\nModule ref table:\n" );
+    if (pModule->modref_table)
+    {
+        pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
+        for (i = 0; i < pModule->modref_count; i++, pword++)
+        {
+            char *name = (char *)pModule + pModule->import_table + *pword;
+            printf( "%d: %04x -> '%*.*s'\n",
+                    i, *pword, *name, *name, name + 1 );
+        }
+    }
+    else printf( "None\n" );
+
+      /* Dump the entry table */
+
+    printf( "\nEntry table:\n" );
+    pstr = (char *)pModule + pModule->entry_table;
+    ordinal = 1;
+    while (*pstr)
+    {
+        printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
+        if (!pstr[1])
+        {
+            ordinal += *pstr;
+            pstr += 2;
+        }
+        else if ((BYTE)pstr[1] == 0xff)  /* moveable */
+        {
+            struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
+            for (i = 0; i < *pstr; i++, pe++)
+                printf( "%d: %02x:%04x (moveable)\n",
+                        ordinal++, pe->seg_number, pe->offset );
+            pstr = (char *)pe;
+        }
+        else  /* fixed */
+        {
+            struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
+            for (i = 0; i < *pstr; i++, pe++)
+                printf( "%d: %04x (fixed)\n",
+                        ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
+            pstr = (char *)pe;
+        }
+    }
+
+    /* Dump the non-resident names table */
+
+    printf( "\nNon-resident names table:\n" );
+    if (pModule->nrname_handle)
+    {
+        pstr = (char *)GlobalLock( pModule->nrname_handle );
+        while (*pstr)
+        {
+            printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+                   *(WORD *)(pstr + *pstr + 1) );
+            pstr += *pstr + 1 + sizeof(WORD);
+        }
+    }
+    printf( "\n" );
+}
+
+
+/***********************************************************************
+ *           MODULE_OpenFile
+ */
+int MODULE_OpenFile( HMODULE hModule )
+{
+    NE_MODULE *pModule;
+    char *name;
+
+    static HMODULE hCachedModule = 0;
+    static int cachedfd = -1;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
+                    hModule, hCachedModule, cachedfd );
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
+    if (hCachedModule == hModule) return cachedfd;
+    close( cachedfd );
+    hCachedModule = hModule;
+    name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+    cachedfd = open( name /* DOS_GetUnixFileName( name ) */, O_RDONLY );
+    dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
+                    name, cachedfd );
+    return cachedfd;
+}
+
+
+/***********************************************************************
+ *           MODULE_CreateSegments
+ */
+BOOL MODULE_CreateSegments( HMODULE hModule )
+{
+    SEGTABLEENTRY *pSegment;
+    NE_MODULE *pModule;
+    int i, minsize;
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    pSegment = NE_SEG_TABLE( pModule );
+    for (i = 1; i <= pModule->seg_count; i++, pSegment++)
+    {
+        minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
+        if (i == pModule->ss) minsize += pModule->stack_size;
+        if (i == pModule->dgroup)
+        {
+            /* FIXME: this is needed because heap growing is not implemented */
+            pModule->heap_size = 0x10000 - minsize;
+            minsize = 0x10000;
+        }
+        pSegment->selector = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
+                                      minsize, hModule,
+                                      !(pSegment->flags & NE_SEGFLAGS_DATA),
+                                      FALSE,
+                            FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
+        if (!pSegment->selector) return FALSE;
+    }
+
+    pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
+                            (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MODULE_LoadExeHeader
+ */
+HMODULE MODULE_LoadExeHeader( int fd, char *filename )
+{
+    struct mz_header_s mz_header;
+    struct ne_header_s ne_header;
+    int size;
+    HMODULE hModule;
+    NE_MODULE *pModule;
+    BYTE *pData;
+    char *buffer, *fastload = NULL;
+    int fastload_offset = 0, fastload_length = 0;
+
+  /* Read a block from either the file or the fast-load area. */
+#define READ(offset,size,buffer) \
+       ((fastload && ((offset) >= fastload_offset) && \
+         ((offset)+(size) <= fastload_offset+fastload_length)) ? \
+        (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
+        (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
+         read( fd, (buffer), (size) ) == (size)))
+
+    lseek( fd, 0, SEEK_SET );
+    if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
+        (mz_header.mz_magic != MZ_SIGNATURE)) return 11;  /* invalid exe */
+
+    lseek( fd, mz_header.ne_offset, SEEK_SET );
+    if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
+        return 11;  /* invalid exe */
+
+    if (ne_header.ne_magic == PE_SIGNATURE) return 21;  /* win32 exe */
+    if (ne_header.ne_magic != NE_SIGNATURE) return 11;  /* invalid exe */
+
+    /* We now have a valid NE header */
+
+    size = sizeof(NE_MODULE) +
+             /* loaded file info */
+           sizeof(LOADEDFILEINFO) + strlen(filename) +
+             /* segment table */
+           ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
+             /* resource table */
+           ne_header.rname_tab_offset - ne_header.resource_tab_offset +
+             /* resident names table */
+           ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
+             /* module ref table */
+           ne_header.n_mod_ref_tab * sizeof(WORD) + 
+             /* imported names table */
+           ne_header.entry_tab_offset - ne_header.iname_tab_offset +
+             /* entry table length */
+           ne_header.entry_tab_length;
+
+    hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
+    if (!hModule) return 11;  /* invalid exe */
+    FarSetOwner( hModule, hModule );
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
+    pData = (BYTE *)(pModule + 1);
+
+    /* Read the fast-load area */
+
+    if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
+    {
+        fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
+        fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
+        dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
+                        fastload_offset, fastload_length );
+        if ((fastload = (char *)malloc( fastload_length )) != NULL)
+        {
+            lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
+            if (read( fd, fastload, fastload_length ) != fastload_length)
+            {
+                free( fastload );
+                fastload = NULL;
+            }
+        }
+    }
+
+    /* Store the filename information */
+
+    pModule->fileinfo = (int)pData - (int)pModule;
+    ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(filename);
+    ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
+    ((LOADEDFILEINFO*)pData)->error = 0;
+    ((LOADEDFILEINFO*)pData)->date = 0;
+    ((LOADEDFILEINFO*)pData)->time = 0;
+    strcpy( ((LOADEDFILEINFO*)pData)->filename, filename );
+    pData += ((LOADEDFILEINFO*)pData)->length--;
+
+    /* Get the segment table */
+
+    pModule->seg_table = (int)pData - (int)pModule;
+    buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
+    if (buffer)
+    {
+        int i;
+        struct ne_segment_table_entry_s *pSeg;
+
+        if (!READ( ne_header.segment_tab_offset,
+             ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
+             buffer )) return 11;  /* invalid exe */
+        pSeg = (struct ne_segment_table_entry_s *)buffer;
+        for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
+        {
+            memcpy( pData, pSeg, sizeof(*pSeg) );
+            pData += sizeof(SEGTABLEENTRY);
+        }
+        free( buffer );
+    }
+    else return 11;  /* invalid exe */
+
+    /* Get the resource table */
+
+    if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
+    {
+        pModule->res_table = (int)pData - (int)pModule;
+        if (!READ(ne_header.resource_tab_offset,
+                  ne_header.rname_tab_offset - ne_header.resource_tab_offset,
+                  pData )) return 11;  /* invalid exe */
+        pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
+    }
+    else pModule->res_table = 0;  /* No resource table */
+
+    /* Get the resident names table */
+
+    pModule->name_table = (int)pData - (int)pModule;
+    if (!READ( ne_header.rname_tab_offset,
+               ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
+               pData )) return 11;  /* invalid exe */
+    pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
+
+    /* Get the module references table */
+
+    if (ne_header.n_mod_ref_tab > 0)
+    {
+        pModule->modref_table = (int)pData - (int)pModule;
+        if (!READ( ne_header.moduleref_tab_offset,
+                  ne_header.n_mod_ref_tab * sizeof(WORD),
+                  pData )) return 11;  /* invalid exe */
+        pData += ne_header.n_mod_ref_tab * sizeof(WORD);
+    }
+    else pModule->modref_table = 0;  /* No module references */
+
+    /* Get the imported names table */
+
+    pModule->import_table = (int)pData - (int)pModule;
+    if (!READ( ne_header.iname_tab_offset, 
+               ne_header.entry_tab_offset - ne_header.iname_tab_offset,
+               pData )) return 11;  /* invalid exe */
+    pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
+
+    /* Get the entry table */
+
+    pModule->entry_table = (int)pData - (int)pModule;
+    if (!READ( ne_header.entry_tab_offset,
+               ne_header.entry_tab_length,
+               pData )) return 11;  /* invalid exe */
+    pData += ne_header.entry_tab_length;
+
+    /* Get the non-resident names table */
+
+    if (ne_header.nrname_tab_length)
+    {
+        pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
+                                               hModule, FALSE, FALSE, FALSE );
+        if (!pModule->nrname_handle) return 11;  /* invalid exe */
+        buffer = GlobalLock( pModule->nrname_handle );
+        lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
+        if (read( fd, buffer, ne_header.nrname_tab_length )
+              != ne_header.nrname_tab_length) return 11;  /* invalid exe */
+    }
+    else pModule->nrname_handle = 0;
+
+    if (debugging_module) MODULE_PrintModule( hModule );
+    pModule->next = hFirstModule;
+    hFirstModule = hModule;
+    return hModule;
+}
+
+
+/***********************************************************************
+ *           MODULE_GetOrdinal
+ *
+ * Lookup the ordinal for a given name.
+ */
+WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
+{
+    char buffer[256], *cpnt;
+    BYTE len;
+    NE_MODULE *pModule;
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+
+    dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
+                    hModule, name );
+
+      /* First handle names of the form '#xxxx' */
+
+    if (name[0] == '#') return atoi( name + 1 );
+
+      /* Now copy and uppercase the string */
+
+    strcpy( buffer, name );
+    AnsiUpper( buffer );
+    len = strlen( buffer );
+
+      /* First search the resident names */
+
+    cpnt = (char *)pModule + pModule->name_table;
+
+      /* Skip the first entry (module name) */
+    cpnt += *cpnt + 1 + sizeof(WORD);
+    while (*cpnt)
+    {
+        dprintf_module( stddeb, "  Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
+        if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
+        {
+            dprintf_module( stddeb, "  Found: ordinal=%d\n",
+                            *(WORD *)(cpnt + *cpnt + 1) );
+            return *(WORD *)(cpnt + *cpnt + 1);
+        }
+        cpnt += *cpnt + 1 + sizeof(WORD);
+    }
+
+      /* Now search the non-resident names table */
+
+    if (!pModule->nrname_handle) return 0;  /* No non-resident table */
+    cpnt = (char *)GlobalLock( pModule->nrname_handle );
+
+      /* Skip the first entry (module description string) */
+    cpnt += *cpnt + 1 + sizeof(WORD);
+    while (*cpnt)
+    {
+        dprintf_module( stddeb, "  Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
+        if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
+        {
+            dprintf_module( stddeb, "  Found: ordinal=%d\n",
+                            *(WORD *)(cpnt + *cpnt + 1) );
+            return *(WORD *)(cpnt + *cpnt + 1);
+        }
+        cpnt += *cpnt + 1 + sizeof(WORD);
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           MODULE_GetEntryPoint
+ *
+ * Return the entry point for a given ordinal.
+ */
+DWORD MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
+{
+    NE_MODULE *pModule;
+    WORD curOrdinal = 1;
+    BYTE *p;
+    WORD sel, offset;
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+
+    dprintf_module( stddeb, "MODULE_GetEntryPoint(%04x,%d)\n",
+                    hModule, ordinal );
+    p = (BYTE *)pModule + pModule->entry_table;
+    while (*p && (curOrdinal + *p <= ordinal))
+    {
+          /* Skipping this bundle */
+        curOrdinal += *p;
+        switch(p[1])
+        {
+            case 0:    p += 2; break;  /* unused */
+            case 0xff: p += 2 + *p * 6; break;  /* moveable */
+            default:   p += 2 + *p * 3; break;  /* fixed */
+        }
+    }
+    if (!*p)
+    {
+        dprintf_module( stddeb, "  Not found (last=%d)\n", curOrdinal-1 );
+        return 0;
+    }
+
+    switch(p[1])
+    {
+        case 0:  /* unused */
+            dprintf_module( stddeb, "  Found, but entry is unused\n" );
+            return 0;
+        case 0xff:  /* moveable */
+            p += 2 + 6 * (ordinal - curOrdinal);
+            sel = p[3];
+            offset = *(WORD *)(p + 4);
+            break;
+        default:  /* fixed */
+            sel = p[1];
+            p += 2 + 3 * (ordinal - curOrdinal);
+            offset = *(WORD *)(p + 1);
+            break;
+    }
+
+    dprintf_module( stddeb, "  Found, logical addr = %04x:%04x\n",
+                    sel, offset );
+    if (sel == 0xfe) sel = 0xffff;  /* constant entry */
+    else sel = NE_SEG_TABLE(pModule)[sel-1].selector;
+    return MAKELONG( offset, sel );
+}
+
+
+/***********************************************************************
+ *           MODULE_GetModuleName
+ */
+LPSTR MODULE_GetModuleName( HMODULE hModule )
+{
+    NE_MODULE *pModule;
+    BYTE *p, len;
+    static char buffer[10];
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
+    p = (BYTE *)pModule + pModule->name_table;
+    len = min( *p, 8 );
+    memcpy( buffer, p + 1, len );
+    buffer[len] = '\0';
+    return buffer;
+}
+
+
+/**********************************************************************
+ *	    LoadModule    (KERNEL.45)
+ */
+HINSTANCE MODULE_LoadModule( LPCSTR name, LPVOID paramBlock )
+{
+}
+
+
+/**********************************************************************
+ *	    GetModuleHandle    (KERNEL.47)
+ */
+HMODULE GetModuleHandle( LPCSTR name )
+{
+    char buffer[16];
+    BYTE len;
+    HMODULE hModule;
+
+    strncpy( buffer, name, 15 );
+    buffer[15] = '\0';
+    len = strlen(buffer);
+    AnsiUpper( buffer );
+
+    hModule = hFirstModule;
+    while( hModule )
+    {
+        NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
+        char *pname = (char *)pModule + pModule->name_table;
+        if (((BYTE)*pname == len) && !memcmp( pname+1, buffer, len )) break;
+        hModule = pModule->next;
+    }
+    dprintf_module( stddeb, "GetModuleHandle('%s'): returning %04x\n",
+                    name, hModule );
+    return hModule;
+}
+
+
+/**********************************************************************
+ *	    GetModuleUsage    (KERNEL.48)
+ */
+int GetModuleUsage( HANDLE hModule )
+{
+    NE_MODULE *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
+                    hModule, pModule->count );
+    return pModule->count;
+}
+
+
+/**********************************************************************
+ *	    GetModuleFileName    (KERNEL.49)
+ */
+int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
+{
+    NE_MODULE *pModule;
+    char *name;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+    strncpy( lpFileName, name, nSize );
+    lpFileName[nSize-1] = '\0';
+    return strlen(lpFileName);
+}
+
+
+/**********************************************************************
+ *	    ModuleFirst    (TOOLHELP.59)
+ */
+BOOL ModuleFirst( MODULEENTRY *lpme )
+{
+    lpme->wNext = hFirstModule;
+    return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleNext    (TOOLHELP.60)
+ */
+BOOL ModuleNext( MODULEENTRY *lpme )
+{
+    NE_MODULE *pModule;
+
+    if (!lpme->wNext) return FALSE;
+    if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
+    strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
+             MAX_MODULE_NAME );
+    lpme->szModule[MAX_MODULE_NAME] = '\0';
+    lpme->hModule = lpme->wNext;
+    lpme->wcUsage = pModule->count;
+    strncpy( lpme->szExePath,
+             ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
+             MAX_PATH );
+    lpme->szExePath[MAX_PATH] = '\0';
+    lpme->wNext = pModule->next;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    ModuleFindName    (TOOLHELP.61)
+ */
+BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
+{
+    lpme->wNext = GetModuleHandle( name );
+    return ModuleNext( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleFindHandle    (TOOLHELP.62)
+ */
+BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
+{
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    lpme->wNext = hModule;
+    return ModuleNext( lpme );
+}
diff --git a/loader/ne_image.c b/loader/ne_image.c
index d0bd137..92e37f5 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -1,7 +1,10 @@
 /*
-static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-*/
+ * NE modules
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -21,109 +24,61 @@
 #include "callback.h"
 #include "ne_image.h"
 #include "prototypes.h"
+#include "module.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 
-extern unsigned short WIN_StackSize;
-extern unsigned short WIN_HeapSize;
 
-void FixupFunctionPrologs(struct w_files *);
-
-/**********************************************************************
- *					GetImportedName
+/***********************************************************************
+ *           NE_LoadSegment
  */
-static
-char *NE_GetImportedName(struct w_files *wpnt, int name_offset, char *buffer)
+static BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
 {
-    BYTE length;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable, *pSeg;
+    WORD *pModuleTable;
+    WORD count, i, module, offset;
+    DWORD address;
+    int fd;
+    struct relocation_entry_s *rep, *reloc_entries;
+    char *dll_name, *func_name;
 
-    lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-    	wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
-    read(wpnt->fd, &length, 1);  /* Get the length byte */
-    read(wpnt->fd, buffer, length);
-    buffer[length] = 0;
-
-    return buffer;
-}
-
-struct w_files *current_exe;
-WORD current_nodata=0xfd00;
-/**********************************************************************
- *					GetModuleName
- */
-static char *NE_GetModuleName(struct w_files *wpnt, int index, char *buffer)
-{
-    BYTE length;
-    WORD name_offset;
-    int i;
-    
-    lseek(wpnt->fd, wpnt->mz_header->ne_offset +
-    	wpnt->ne->ne_header->moduleref_tab_offset + 2 * (index - 1), SEEK_SET);
-    read(wpnt->fd, &name_offset, 2);
-    name_offset = CONV_SHORT (name_offset);
-
-    lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-    	wpnt->ne->ne_header->iname_tab_offset + name_offset, SEEK_SET);
-    read(wpnt->fd, &length, 1);  /* Get the length byte */
-    read(wpnt->fd, buffer, length);
-    buffer[length] = 0;
-
-    /* Module names  are always upper case */
-    for(i=0; i<length; i++)
-    	if (islower(buffer[i]))
-    		buffer[i] = toupper(buffer[i]);
-
-    return buffer;
-}
-
-#ifndef WINELIB
-/**********************************************************************
- *				NE_FixupSegment
- */
-int NE_FixupSegment(struct w_files *wpnt, int segment_num)
-{
-    WORD *selector_table = wpnt->ne->selector_table;
-    WORD selector, sel, offset;
-    struct relocation_entry_s *rep, *rep1;
-    struct ne_segment_table_entry_s *seg;
-    int status, ordinal, i, n_entries, additive;
+    char buffer[100], buffer2[100];
+    int ordinal, additive;
     unsigned short *sp;
-    unsigned int address;
-    unsigned char dll_name[257], func_name[257];
 
-    seg = &wpnt->ne->seg_table[segment_num];
-    sel = selector_table[segment_num];
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    pSegTable = NE_SEG_TABLE( pModule );
+    pSeg = pSegTable + segnum - 1;
+    pModuleTable = NE_MODULE_TABLE( pModule );
+    if (!pSeg->filepos) return TRUE;  /* No file image, just return */
 
-    dprintf_fixup(stddeb, "Segment fixups for %s, segment %d, selector %04x\n", 
-                  wpnt->name, segment_num, sel );
+    fd = MODULE_OpenFile( hModule );
+    dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
+                    segnum, pSeg->selector );
+    lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
+    read( fd, GlobalLock( pSeg->selector ), pSeg->size ? pSeg->size : 0x10000);
 
-    if ((seg->seg_data_offset == 0) ||
-	!(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
-	return 0;
+    if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
+        return TRUE;  /* No relocation data, we are done */
+
+    read( fd, &count, sizeof(count) );
+    if (!count) return TRUE;
+
+    reloc_entries = (struct relocation_entry_s *)malloc(count * sizeof(struct relocation_entry_s));
+    if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
+            count * sizeof(struct relocation_entry_s))
+    {
+        dprintf_fixup( stddeb, "Unable to read relocation information\n" );
+        return FALSE;
+    }
 
     /*
      * Go through the relocation table on entry at a time.
      */
-    i = seg->seg_data_length;
-    if (i == 0)
-	i = 0x10000;
-
-    status = lseek(wpnt->fd, seg->seg_data_offset * 
-		(1 << wpnt->ne->ne_header->align_shift_count) + i, SEEK_SET);
-    n_entries = 0;
-    read(wpnt->fd, &n_entries, sizeof(short int));
-    rep = (struct relocation_entry_s *)
-	  malloc(n_entries * sizeof(struct relocation_entry_s));
-
-    if (read(wpnt->fd, rep, n_entries * sizeof(struct relocation_entry_s)) !=
-        n_entries * sizeof(struct relocation_entry_s))
-    {
-	myerror("Unable to read relocation information");
-    }
-    
-    rep1 = rep;
-
-    for (i = 0; i < n_entries; i++, rep++)
+    rep = reloc_entries;
+    for (i = 0; i < count; i++, rep++)
     {
 	/*
 	 * Get the target address corresponding to this entry.
@@ -137,70 +92,57 @@
 	switch (rep->relocation_type)
 	{
 	  case NE_RELTYPE_ORDINAL:
-	    if (NE_GetModuleName(wpnt, rep->target1,
-			      dll_name) == NULL)
-	    {
-	      fprintf(stderr, "NE_RELTYPE_ORDINAL failed");
-		return -1;
-	    }
-	    
-	    ordinal = rep->target2;
+            module = pModuleTable[rep->target1-1];
+            dll_name = (char *)pModule + pModule->import_table + module;
+            memcpy( buffer, dll_name+1, *dll_name );
+            buffer[*dll_name] = '\0';
+            dll_name = buffer;
+            module = GetModuleHandle( dll_name );
 
-  	    status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
-					&offset);
-	    if (status)
-	    {
-		char s[80];
-		
-		sprintf(s, "Bad DLL name '%s.%d'", dll_name, ordinal);
-		myerror(s);
-		return -1;
-	    }
+	    ordinal = rep->target2;
+            address = MODULE_GetEntryPoint( module, ordinal );
+            if (!address) fprintf( stderr, "Warning: no handler for %s.%d, setting to 0:0\n",
+                                  dll_name, ordinal );
 
 	    dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1, 
-		   dll_name, ordinal, selector, offset);
+                        dll_name, ordinal, HIWORD(address), LOWORD(address) );
 	    break;
 	    
 	  case NE_RELTYPE_NAME:
-	    if (NE_GetModuleName(wpnt, rep->target1, dll_name) == NULL) {
-	        fprintf(stderr,"NE_RELTYPE_NAME failed");
-		return -1;
-	    }
+            module = pModuleTable[rep->target1-1];
+            dll_name = (char *)pModule + pModule->import_table + module;
+            memcpy( buffer, dll_name+1, *dll_name );
+            buffer[*dll_name] = '\0';
+            dll_name = buffer;
+            module = GetModuleHandle( dll_name );
 
-	    if (NE_GetImportedName(wpnt, rep->target2, func_name) == NULL) {
-	        fprintf(stderr,"NE_getimportedname failed");
-		return -1;
-	    }
+            func_name = (char *)pModule + pModule->import_table + rep->target2;
+            memcpy( buffer2, func_name+1, *func_name );
+            buffer2[*func_name] = '\0';
+            func_name = buffer2;
+            ordinal = MODULE_GetOrdinal( module, func_name );
 
-  	    status = GetEntryDLLName(dll_name, func_name, &selector, 
-					   &offset);
-	    if (status)
-	    {
-		char s[80];
-		
-		sprintf(s, "Bad DLL name '%s (%s)'", dll_name,func_name);
-		myerror(s);
-		return -1;
-	    }
-            dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1, 
-                          func_name, dll_name, ordinal, selector, offset);
+            address = MODULE_GetEntryPoint( module, ordinal );
+
+            if (!address) fprintf( stderr, "Warning: no handler for %s.%s, setting to 0:0\n",
+                                  dll_name, func_name );
+
+            dprintf_fixup(stddeb,"%d: %s.%s: %04x:%04x\n", i + 1, 
+                       dll_name, func_name, HIWORD(address), LOWORD(address) );
 	    break;
 	    
 	  case NE_RELTYPE_INTERNAL:
 	    if (rep->target1 == 0x00ff)
 	    {
-		address  = GetEntryPointFromOrdinal(wpnt, rep->target2);
-		selector = (address >> 16) & 0xffff;
-		offset   = address & 0xffff;
+		address  = MODULE_GetEntryPoint( hModule, rep->target2 );
 	    }
 	    else
 	    {
-		selector = selector_table[rep->target1-1];
-		offset   = rep->target2;
+                address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
 	    }
 	    
 	    dprintf_fixup(stddeb,"%d: %04x:%04x\n", 
-			  i + 1, selector, offset);
+			  i + 1, HIWORD(address), LOWORD(address) );
 	    break;
 
 	  case NE_RELTYPE_OSFIXUP:
@@ -227,46 +169,46 @@
 		   rep->offset);
 	    dprintf_fixup(stddeb,"TARGET %04x %04x\n", 
 		    rep->target1, rep->target2);
-	    free(rep1);
-	    return -1;
+	    free(reloc_entries);
+	    return FALSE;
 	}
 
         /* I'm not sure why a DLL entry point fixup could be additive.
            Old code used to ignore additive if the target is a built-in
            DLL. This doesn't seem to work for __AHSHIFT */
+#if 0
         if (additive && FindDLLTable(dll_name) != NULL)
             dprintf_fixup(stddeb,"Additive for builtin???\n"
                           "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, "
                           "TARGET %04x %04x\n",
                           i+1, rep->address_type, rep->relocation_type,
                           rep->offset, rep->target1, rep->target2);
-
-        address = (unsigned int)offset;
+#endif
 	offset  = rep->offset;
 
 	switch (rep->address_type)
 	{
 	  case NE_RADDR_LOWBYTE:
             do {
-                sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+                sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
                 dprintf_fixup(stddeb,"    %04x:%04x:%04x BYTE%s\n",
-                              sel, offset, *sp, additive ? " additive":"");
+                              pSeg->selector, offset, *sp, additive ? " additive":"");
                 offset = *sp;
 		if(additive)
-                    *(unsigned char*)sp = (unsigned char)(address & 0xFF);
-		else
                     *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
+		else
+                    *(unsigned char*)sp = (unsigned char)(address & 0xFF);
             }
             while (offset != 0xffff && !additive);
             break;
 
 	  case NE_RADDR_OFFSET16:
 	    do {
-                sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+                sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
 		dprintf_fixup(stddeb,"    %04x:%04x:%04x OFFSET16%s\n",
-                              sel, offset, *sp, additive ? " additive" : "" );
+                              pSeg->selector, offset, *sp, additive ? " additive" : "" );
 		offset = *sp;
-		*sp = (unsigned short) address;
+		*sp = LOWORD(address);
 		if (additive) *sp += offset;
 	    } 
 	    while (offset != 0xffff && !additive);
@@ -274,24 +216,24 @@
 	    
 	  case NE_RADDR_POINTER32:
 	    do {
-                sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+                sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
 		dprintf_fixup(stddeb,"    %04x:%04x:%04x POINTER32%s\n",
-                              sel, offset, *sp, additive ? " additive" : "" );
+                              pSeg->selector, offset, *sp, additive ? " additive" : "" );
 		offset = *sp;
-		*sp    = (unsigned short) address;
+		*sp    = LOWORD(address);
 		if (additive) *sp += offset;
-		*(sp+1) = selector;
+		*(sp+1) = HIWORD(address);
 	    } 
 	    while (offset != 0xffff && !additive);
 	    break;
 	    
 	  case NE_RADDR_SELECTOR:
 	    do {
-                sp = PTR_SEG_OFF_TO_LIN( sel, offset );
+                sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
 		dprintf_fixup(stddeb,"    %04x:%04x:%04x SELECTOR%s\n",
-                              sel, offset, *sp, additive ? " additive" : "" );
+                              pSeg->selector, offset, *sp, additive ? " additive" : "" );
 		offset = *sp;
-		*sp    = (unsigned short) selector;
+		*sp    = HIWORD(address);
 		/* Borland creates additive records with offset zero. Strange, but OK */
 		if(additive && offset)
         	fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
@@ -306,15 +248,91 @@
 		   rep->offset);
 	    dprintf_fixup(stddeb,
 		   "TARGET %04x %04x\n", rep->target1, rep->target2);
-	    free(rep1);
-	    return -1;
+	    free(reloc_entries);
+	    return FALSE;
 	}
     }
 
-    free(rep1);
-    return 0;
+    free(reloc_entries);
+    return TRUE;
 }
 
+
+/***********************************************************************
+ *           NE_FixupPrologs
+ *
+ * Fixup the exported functions prologs.
+ */
+static void NE_FixupPrologs( HMODULE hModule )
+{
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable;
+    WORD dgroup = 0;
+    WORD sel;
+    BYTE *p, *fixup_ptr, count;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    pSegTable = NE_SEG_TABLE(pModule);
+    if (pModule->flags & NE_FFLAGS_SINGLEDATA)
+        dgroup = pSegTable[pModule->dgroup-1].selector;
+
+    dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
+    p = (BYTE *)pModule + pModule->entry_table;
+    while (*p)
+    {
+        if (p[1] == 0)  /* Unused entry */
+        {
+            p += 2;  /* Skip it */
+            continue;
+        }
+        if (p[1] == 0xfe)  /* Constant entry */
+        {
+            p += 2 + *p * 3;  /* Skip it */
+            continue;
+        }
+
+        /* Now fixup the entries of this bundle */
+        count = *p;
+        sel = p[1];
+        p += 2;
+        while (count-- > 0)
+        {
+            dprintf_module( stddeb,"Flags: %04x ", *p );
+            /* FIXME: Does anyone know the exact meaning of these flags? */
+            /* 0x0001 seems to mean: Fix up the function prolog          */
+            if (*p & 0x0001)
+            {
+                if (sel == 0xff)  /* moveable */
+                    fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
+                else  /* fixed */
+                    fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
+                dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
+                                fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
+                                pModule->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 (pModule->flags & NE_FFLAGS_SINGLEDATA)
+                    {
+                        *fixup_ptr = 0xb8;	/* MOV AX, */
+                        *(WORD *)(fixup_ptr+1) = dgroup;
+                    }
+                    else
+                    {
+                        fixup_ptr[0] = 0x90; /* non-library: NOPs */	
+                        fixup_ptr[1] = 0x90;
+                        fixup_ptr[2] = 0x90;
+                    }
+                } 
+            }
+            p += (sel == 0xff) ? 6 : 3;  
+        }
+    }
+}
+
+
 int NE_unloadImage(struct w_files *wpnt)
 {
 	dprintf_fixup(stdnimp, "NEunloadImage() called!\n");
@@ -322,88 +340,59 @@
 	return 1;
 }
 
-int NE_StartProgram(struct w_files *wpnt)
-{
-    extern WORD PSPSelector;
 
-    int cs_reg, ds_reg, ip_reg;
+BOOL NE_InitDLL( HMODULE hModule )
+{
+    int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable;
 
     /* 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
+     * cx     heap size
+     * di     library instance
+     * ds     data segment if any
+     * es:si  command line (always 0)
      */
 
-    /*
-     * Fixup stack and jump to start. 
-     */
-    WIN_StackSize = wpnt->ne->ne_header->stack_length;
-    WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    pSegTable = NE_SEG_TABLE( pModule );
 
-    cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
-    ip_reg = wpnt->ne->ne_header->ip;
-    ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
+    if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
+    if (!pModule->cs) return TRUE;  /* no initialization code */
 
-    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;
+    if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
+    {
+        if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
+        {
+            /* Not SINGLEDATA */
+            fprintf(stderr, "Library is not marked SINGLEDATA\n");
+            exit(1);
+        }
+        else  /* DATA NONE DLL */
+        {
+            ds_reg = 0;
+            cx_reg = 0;
+        }
+    }
+    else  /* DATA SINGLE DLL */
+    {
+        ds_reg = pSegTable[pModule->dgroup-1].selector;
+        cx_reg = pModule->heap_size;
+    }
+
+    cs_reg = pSegTable[pModule->cs-1].selector;
+    ip_reg = pModule->ip;
+    di_reg = ds_reg ? ds_reg : hModule;
+    bp_reg = IF1632_Saved16_sp + (&((STACK16FRAME*)1)->bp - 1);
+
+    pModule->cs = 0;  /* Don't initialize it twice */
+    dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n", 
+                 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
     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*/ );
+                           0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
+                           cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
 }
 
-void NE_InitDLL(struct w_files *wpnt)
-{
-	int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, rv;
-	extern struct w_files *current_exe;
-	/* 
-	 * Is this a library? 
-	 */
-	if (wpnt->ne->ne_header->format_flags & 0x8000)
-	{
-  	    if (!(wpnt->ne->ne_header->format_flags & 0x0001))
-	    if(wpnt->ne->ne_header->format_flags & NE_FFLAGS_MULTIPLEDATA
-		|| wpnt->ne->ne_header->auto_data_seg)
-  	    {
-  		/* Not SINGLEDATA */
-  		fprintf(stderr, "Library is not marked SINGLEDATA\n");
-  		exit(1);
-	    } else { /* DATA NONE DLL */
-		ds_reg = current_exe->ne->selector_table[
-		        current_exe->ne->ne_header->auto_data_seg-1];
-		cx_reg = 0;
-	    } else { /* DATA SINGLE DLL */
-		    ds_reg = wpnt->ne->selector_table[wpnt->ne->
-					  ne_header->auto_data_seg-1];
-		    cx_reg = wpnt->ne->ne_header->local_heap_length;
-  	    }
-  
-            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;
-  
-	    if (cs_reg) {
-		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 = 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);
-	}
-}
 
 /**********************************************************************
  *			NE_LoadImage
@@ -411,94 +400,86 @@
  */
 HINSTANCE NE_LoadImage(struct w_files *wpnt)
 {
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable;
+    WORD *pModRef;
     unsigned int read_size, status, segment;
     int i;
+    char cmdLine[256];
+    extern int Argc;
+    extern char **Argv;
 
     wpnt->ne = malloc(sizeof(struct ne_data));
-    wpnt->ne->resnamtab = NULL;
     wpnt->ne->ne_header = malloc(sizeof(struct ne_header_s));
 
     lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
     if (read(wpnt->fd, wpnt->ne->ne_header, sizeof(struct ne_header_s)) 
 	!= sizeof(struct ne_header_s))
 	myerror("Unable to read NE header from file");
-    if(!(wpnt->ne->ne_header->format_flags & NE_FFLAGS_LIBMODULE)){
-	if(current_exe)printf("Warning: more than one EXE\n");
-        current_exe=wpnt;
-    }
 
+    wpnt->hModule = MODULE_LoadExeHeader( wpnt->fd, wpnt->filename );
+    pModule = (NE_MODULE *)GlobalLock( wpnt->hModule );
+    pSegTable = NE_SEG_TABLE(pModule);
+
+      /* Create the module segments */
+
+    MODULE_CreateSegments( wpnt->hModule );
 #ifndef WINELIB
     /*
      * Create segment selectors.
      */
-    status = lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-		   wpnt->ne->ne_header->segment_tab_offset,
-		   SEEK_SET);
-    read_size  = wpnt->ne->ne_header->n_segment_tab *
-	sizeof(struct ne_segment_table_entry_s);
-    wpnt->ne->seg_table = (struct ne_segment_table_entry_s *) malloc(read_size);
-    if (read(wpnt->fd, wpnt->ne->seg_table, read_size) != read_size)
-	myerror("Unable to read segment table header from file");
-    wpnt->ne->selector_table = CreateSelectors(wpnt);
-    if(wpnt->ne->ne_header->auto_data_seg==0)
-    {
-        printf("DATA NONE DLL %s\n",wpnt->name);
-        wpnt->hinstance=current_nodata++;
-    } else
-    wpnt->hinstance = (wpnt->ne->
-		       selector_table[wpnt->ne->ne_header->auto_data_seg-1]);
-    if (wpnt->hinstance == 0)
-    	wpnt->hinstance = 0xf000;
+    CreateSelectors();
+
+    if (pModule->dgroup)
+        wpnt->hinstance = NE_SEG_TABLE(pModule)[pModule->dgroup-1].selector;
+    else
+        wpnt->hinstance = wpnt->hModule;
 #endif
-    /* Get the lookup  table.  This is used for looking up the addresses
-       of functions that are exported */
 
-    read_size  = wpnt->ne->ne_header->entry_tab_length;
-    wpnt->ne->lookup_table = (char *) malloc(read_size);
-    lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-	  wpnt->ne->ne_header->entry_tab_offset, SEEK_SET);
-    if (read(wpnt->fd, wpnt->ne->lookup_table, read_size) != read_size)
-	myerror("Unable to read lookup table header from file");
+      /* Create a task for this module */
 
-    /* Get the iname table.  This is used for looking up the names
-       of functions that are exported */
-
-    status = lseek(wpnt->fd, wpnt->ne->ne_header->nrname_tab_offset,  SEEK_SET);
-    read_size  = wpnt->ne->ne_header->nrname_tab_length;
-    wpnt->ne->nrname_table = (char *) malloc(read_size);
-    if (read(wpnt->fd, wpnt->ne->nrname_table, read_size) != read_size)
-	myerror("Unable to read nrname table header from file");
-
-    status = lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-		   wpnt->ne->ne_header->rname_tab_offset,  SEEK_SET);
-    read_size  = wpnt->ne->ne_header->moduleref_tab_offset - 
-	    wpnt->ne->ne_header->rname_tab_offset;
-    wpnt->ne->rname_table = (char *) malloc(read_size);
-    if (read(wpnt->fd, wpnt->ne->rname_table, read_size) != read_size)
-	myerror("Unable to read rname table header from file");
+    cmdLine[0] = '\0';
+    for (i = 1; i < Argc; i++)
+    {
+        strcat( cmdLine, Argv[i] );
+        strcat( cmdLine, " " );
+    }
+    if (!(pModule->flags & NE_FFLAGS_LIBMODULE))
+        TASK_CreateTask( wpnt->hModule, SELECTOROF( GetDOSEnvironment() ),
+                         GetCurrentTask(), cmdLine );
 
     /*
      * Now load any DLLs that  this module refers to.
      */
-    for(i=0; i<wpnt->ne->ne_header->n_mod_ref_tab; i++)
+    pModRef = (WORD *)((char *)pModule + pModule->modref_table);
+    for (i = 0; i < pModule->modref_count; i++, pModRef++)
     {
-      char buff[14];
-      NE_GetModuleName(wpnt, i + 1, buff);
-
-      if (strcasecmp(buff, wpnt->name) != 0 )
-	LoadImage(buff, DLL, 0);
+        char buffer[80];
+        char *pstr = (char *)pModule + pModule->import_table + *pModRef;
+        memcpy( buffer, pstr + 1, *pstr );
+        buffer[*pstr] = '\0';
+        dprintf_module( stddeb, "Loading '%s'\n", buffer );
+        LoadImage( buffer, DLL, 0 );
     }
-#ifndef WINELIB
+
     /* fixup references */
 
-    for (segment = 0; segment < wpnt->ne->ne_header->n_segment_tab; segment++)
-	if (NE_FixupSegment(wpnt, segment) < 0)
-		myerror("fixup failed.");
+    for (i = 1; i <= pModule->seg_count; i++)
+        NE_LoadSegment( wpnt->hModule, i );
 
-    FixupFunctionPrologs(wpnt);
+    NE_FixupPrologs( wpnt->hModule );
     InitializeLoadedDLLs(wpnt);
-#endif
+
+
+      /* Initialize the local heap */
+
+    if (pModule->dgroup)
+    {
+        int start = pSegTable[pModule->dgroup-1].minsize;
+        if (pModule->ss == pModule->dgroup) start += pModule->stack_size;
+        LocalInit( pSegTable[pModule->dgroup-1].selector,
+                   start, start + pModule->heap_size );
+    }
+
     return(wpnt->hinstance);
 }
-
-#endif /* !WINELIB */
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index 6114d95..e3e4428 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -1,7 +1,9 @@
 /*
-static char RCSId[] = "$Id: ne_resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-*/
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -10,375 +12,341 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include "windows.h"
-#include "ldt.h"
-#include "neexe.h"
-#include "peexe.h"
 #include "arch.h"
-#include "dlls.h"
-#include "library.h"
+#include "dos_fs.h"
+#include "global.h"
+#include "ldt.h"
+#include "module.h"
+#include "neexe.h"
 #include "resource.h"
 #include "stddebug.h"
 #include "debug.h"
-
-/**********************************************************************
- *			NE_LoadNameTable
+
+typedef struct resource_typeinfo_s NE_TYPEINFO;
+typedef struct resource_nameinfo_s NE_NAMEINFO;
+
+
+/***********************************************************************
+ *           NE_FindNameTableId
+ *
+ * Find the type and resource id from their names.
+ * Return value is MAKELONG( typeId, resId ), or 0 if not found.
  */
-static void NE_LoadNameTable(struct w_files *wpnt)
+static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
 {
-    struct resource_typeinfo_s typeinfo;
-    struct resource_nameinfo_s nameinfo;
-    unsigned short             size_shift;
-    RESNAMTAB                 *top, *new;
-    char                       read_buf[1024];
-    char                      *p;
-    int                        i;
-    unsigned short             len;
-    off_t		       saved_pos;
-    
-    top = NULL;
-    /*
-     * Move to beginning of resource table.
-     */
-    lseek(wpnt->fd, wpnt->mz_header->ne_offset + 
-	    	wpnt->ne->ne_header->resource_tab_offset, SEEK_SET);
+    NE_MODULE *pModule;
+    NE_TYPEINFO *pTypeInfo;
+    NE_NAMEINFO *pNameInfo;
+    HGLOBAL handle;
+    WORD *p;
+    DWORD ret = 0;
+    int count;
 
-    /*
-     * Read block size.
-     */
-    if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
-	return;
-
-    size_shift = CONV_SHORT(size_shift);
-
-    /*
-     * Find resource.
-     */
-    typeinfo.type_id = 0xffff;
-    while (typeinfo.type_id != 0) 
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+    for (; pTypeInfo->type_id != 0;
+             pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+                                       pTypeInfo->count * sizeof(NE_NAMEINFO)))
     {
-	if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo))
-	    break;
+        if (pTypeInfo->type_id != 0x800f) continue;
+        pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
+        for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+        {
+            dprintf_resource( stddeb, "NameTable entry: type=%04x id=%04x\n",
+                              pTypeInfo->type_id, pNameInfo->id );
+            handle = LoadResource( hModule, (int)pNameInfo - (int)pModule );
+            for(p = (WORD*)LockResource(handle); *p; p = (WORD *)((char*)p+*p))
+            {
+                dprintf_resource( stddeb,"  type=%04x '%s' id=%04x '%s'\n",
+                                  p[1], (char *)(p+3), p[2],
+                                  (char *)(p+3)+strlen((char *)(p+3))+1 );
+                /* Check for correct type */
 
-	if (typeinfo.type_id == 0) 
-	    break;
+                if (p[1] & 0x8000)
+                {
+                    if (!HIWORD(typeId)) continue;
+                    if (strcasecmp( (char *)PTR_SEG_TO_LIN(typeId),
+                                   (char *)(p + 3) )) continue;
+                }
+                else if (HIWORD(typeId) || ((typeId & ~0x8000)!= p[1]))
+                  continue;
 
-	if (typeinfo.type_id == 0x800f) 
-	{
-	    for (i = 0; i < typeinfo.count; i++) 
-	    {
-		if (read(wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
-		    break;
-		
-		saved_pos = lseek(wpnt->fd, 0, SEEK_CUR);
-		lseek(wpnt->fd, (long) nameinfo.offset << size_shift, 
-		      SEEK_SET);
-		read(wpnt->fd, &len, sizeof(len));
-		while (len)
-		{
-		    new = (RESNAMTAB *) GlobalLock(GlobalAlloc(GMEM_MOVEABLE,sizeof(*new)));
-		    new->next = top;
-		    top = new;
+                /* Now check for the id */
 
-		    read(wpnt->fd, &new->type_ord, 2);
-		    read(wpnt->fd, &new->id_ord, 2);
-		    read(wpnt->fd, read_buf, len - 6);
-		    
-		    p = read_buf + strlen(read_buf) + 1;
-		    strncpy(new->id, p, MAX_NAME_LENGTH);
-		    new->id[MAX_NAME_LENGTH - 1] = '\0';
+                if (p[2] & 0x8000)
+                {
+                    if (!HIWORD(resId)) continue;
+                    if (strcasecmp( (char *)PTR_SEG_TO_LIN(resId),
+                               (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
+                    
+                }
+                else if (HIWORD(resId) || ((resId & ~0x8000) != p[2]))
+                  continue;
 
-		    read(wpnt->fd, &len, sizeof(len));
-		}
-		lseek(wpnt->fd, saved_pos, SEEK_SET);
-	    }
-	} else 
-		lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
-    }
-    wpnt->ne->resnamtab = top;
-}
+                /* If we get here, we've found the entry */
 
-static int type_match(int type_id1, int type_id2, int fd, off_t off)
-{
-	off_t old_pos;
-	unsigned char c;
-	size_t nbytes;
-	char name[256];
-
-	if (type_id1 == -1)
-		return 1;
-	if ((type_id1 & 0xffff0000) == 0) {
-		if ((type_id2 & 0x8000) == 0)
-			return 0;
-		return (type_id1 & 0x000f) == (type_id2 & 0x000f);
-	}
-	if ((type_id2 & 0x8000) != 0)
-		return 0;
-	dprintf_resource(stddeb, "type_compare: type_id2=%04X !\n", type_id2);
-
-	old_pos = lseek(fd, 0, SEEK_CUR);
-	lseek(fd, off + type_id2, SEEK_SET);
-	read(fd, &c, 1);
-	nbytes = CONV_CHAR_TO_LONG(c);
-
-	dprintf_resource(stddeb, "type_compare: namesize=%d\n", nbytes);
-	read(fd, name, nbytes);
-	lseek(fd, old_pos, SEEK_SET);
-	name[nbytes] = '\0';
-	dprintf_resource(stddeb, "type_compare: name=`%s'\n", name);
-	return strcasecmp((char *) type_id1, name) == 0;
-}
-
-/**********************************************************************
- *					FindResourceByNumber
- */
-static int FindResourceByNumber(RESOURCE *r, int type_id, int resource_id)
-{
-    struct resource_typeinfo_s typeinfo;
-    struct resource_nameinfo_s nameinfo;
-    unsigned short size_shift;
-    int i;
-    off_t rtoff;
-
-    dprintf_resource(stddeb, "FindResourceByNumber: type_id =%x,m res_id = %x\n",
-		type_id, resource_id);
-
-    /* Move to beginning of resource table */
-    rtoff = (r->wpnt->mz_header->ne_offset +
-	     r->wpnt->ne->ne_header->resource_tab_offset);
-    lseek(r->wpnt->fd, rtoff, SEEK_SET);
-
-    /* Read block size */
-    if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
-    	printf("FindResourceByNumber (%d) bad block size !\n",(int) resource_id);
-	return -1;
-    }
-    size_shift = CONV_SHORT(size_shift);
-
-    /* Find resource */
-    for (;;) {
-	if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
-	    printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
-	    return -1;
-	}
-	dprintf_resource(stddeb, "FindResourceByNumber type=%X count=%d ?=%ld searched=%08X\n", 
-		typeinfo.type_id, typeinfo.count, typeinfo.reserved, type_id);
-	if (typeinfo.type_id == 0)
-		break;
-	if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff)) {
-
-	    for (i = 0; i < typeinfo.count; i++) {
-#ifndef WINELIB
-		if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
-#else
-		if (!load_nameinfo(r->wpnt->fd, &nameinfo))
-#endif
-		{
-		    printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
-		    return -1;
-		}
-		dprintf_resource(stddeb, "FindResource: search type=%X id=%X // type=%X id=%X\n",
-			type_id, resource_id, typeinfo.type_id, nameinfo.id);
-		if (nameinfo.id == resource_id) {
-			r->size = nameinfo.length << size_shift;
-			r->offset = nameinfo.offset << size_shift;
-			return size_shift;
-		    }
-	        }
-	    }
-	else
-	    lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
+                dprintf_resource( stddeb, "  Found!\n" );
+                ret = MAKELONG( p[1], p[2] );
+                break;
+            }
+            FreeResource( handle );
+            if (ret) return ret;
         }
-    return -1;
-}
-
-/**********************************************************************
- *					FindResourceByName
- */
-static int FindResourceByName(RESOURCE *r, int type_id, char *resource_name)
-{
-    struct resource_typeinfo_s typeinfo;
-    struct resource_nameinfo_s nameinfo;
-    unsigned short size_shift;
-    off_t old_pos, new_pos;
-    unsigned char nbytes;
-    char name[256];
-    int i;
-    off_t rtoff;
-
-    /* Check for loaded name table */
-    if (r->wpnt->ne->resnamtab != NULL) {
-	RESNAMTAB *e;
-
-	for (e = r->wpnt->ne->resnamtab; e != NULL; e = e->next)
-	    if (e->type_ord == (type_id & 0x000f) && 
-	    	strcasecmp(e->id, resource_name) == 0)
-	    {
-		return FindResourceByNumber(r, type_id, e->id_ord);
-	    }
-	    return -1;
-    }
-
-    /* Move to beginning of resource table */
-    rtoff = (r->wpnt->mz_header->ne_offset +
-	     r->wpnt->ne->ne_header->resource_tab_offset);
-    lseek(r->wpnt->fd, rtoff, SEEK_SET);
-
-    /* Read block size */
-    if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
-    {
-    	printf("FindResourceByName (%s) bad block size !\n", resource_name);
-	return -1;
-    }
-    size_shift = CONV_SHORT (size_shift);
-    
-    /* Find resource */
-    for (;;)
-    {
-	if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
-	    printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
-	    return -1;
-	}
-	dprintf_resource(stddeb, "FindResourceByName typeinfo.type_id=%X count=%d type_id=%X\n",
-			typeinfo.type_id, typeinfo.count, type_id);
-	if (typeinfo.type_id == 0)
-		break;
-	if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff))
-	{
-	    for (i = 0; i < typeinfo.count; i++)
-	    {
-#ifndef WINELIB
-		if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
-#else
-		if (!load_nameinfo (r->wpnt->fd, &nameinfo))
-#endif
-		{
-		    printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
-		    return -1;
-		}
-/*
-		if ((nameinfo.id & 0x8000) != 0) continue;
-*/		
-		dprintf_resource(stddeb, "FindResourceByName // nameinfo.id=%04X !\n", nameinfo.id);
-		old_pos = lseek(r->wpnt->fd, 0, SEEK_CUR);
-		new_pos = rtoff + nameinfo.id;
-		lseek(r->wpnt->fd, new_pos, SEEK_SET);
-		read(r->wpnt->fd, &nbytes, 1);
-		dprintf_resource(stddeb, "FindResourceByName // namesize=%d !\n", nbytes);
- 		nbytes = CONV_CHAR_TO_LONG (nbytes);
-		read(r->wpnt->fd, name, nbytes);
-		lseek(r->wpnt->fd, old_pos, SEEK_SET);
-		name[nbytes] = '\0';
-		dprintf_resource(stddeb, "FindResourceByName type_id=%X (%d of %d) name='%s' resource_name='%s'\n", 
-			typeinfo.type_id, i + 1, typeinfo.count, 
-			name, resource_name);
-		if (strcasecmp(name, resource_name) == 0) {
-			r->size = nameinfo.length << size_shift;
-			r->offset = nameinfo.offset << size_shift;
-			return size_shift;
-		}
-	    }
-	}
-	else
-	    lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
-    }
-    return -1;
-}
-
-
-/**********************************************************************
- *					GetRsrcCount		[internal]
- */
-int GetRsrcCount(HINSTANCE hInst, int type_id)
-{
-    struct w_files *wpnt;
-    struct resource_typeinfo_s typeinfo;
-    struct resource_nameinfo_s nameinfo;
-    unsigned short size_shift;
-    off_t rtoff;
-
-    if (hInst == 0)
-    	return 0;
-    dprintf_resource(stddeb, "GetRsrcCount hInst=%04X typename=%08X\n", 
-	hInst, type_id);
-
-    if ((wpnt = GetFileInfo(hInst)) == NULL)
-    	return 0;
-    /*
-     * Move to beginning of resource table.
-     */
-    rtoff = (wpnt->mz_header->ne_offset +
-    		wpnt->ne->ne_header->resource_tab_offset);
-    lseek(wpnt->fd, rtoff, SEEK_SET);
-    /*
-     * Read block size.
-     */
-    if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
-		printf("GetRsrcCount // bad block size !\n");
-		return -1;
-    }
-    size_shift = CONV_SHORT (size_shift);
-    for (;;) {
-	if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
-		printf("GetRsrcCount // bad typeinfo size !\n");
-		return 0;
-	}
-	dprintf_resource(stddeb, "GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
-				typeinfo.type_id, typeinfo.count, type_id);
-	if (typeinfo.type_id == 0)
-		break;
-	if (type_match(type_id, typeinfo.type_id, wpnt->fd, rtoff))
-		return typeinfo.count;
-	else
-		lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
     }
     return 0;
 }
 
-/**********************************************************************
- *			NE_FindResource	[KERNEL.60]
+
+/***********************************************************************
+ *           NE_FindResourceFromType
+ *
+ * Find a resource once the type info structure has been found.
  */
-int NE_FindResource(HANDLE instance, SEGPTR resource_name, SEGPTR type_name,
-                    RESOURCE *r)
+static HRSRC NE_FindResourceFromType( NE_MODULE *pModule,
+                                      NE_TYPEINFO *pTypeInfo, SEGPTR resId )
 {
-    int type, x;
-    char *type_name_ptr, *resource_name_ptr;
+    BYTE *p;
+    int count;
+    NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
 
-    dprintf_resource(stddeb, "NE_FindResource hInst=%04X typename=%08lx resname=%08lx\n", 
-			instance, type_name, resource_name);
+    if (HIWORD(resId) != 0)  /* Named resource */
+    {
+        char *str = (char *)PTR_SEG_TO_LIN( resId );
+        BYTE len = strlen( str );
+        for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+        {
+            if (pNameInfo->id & 0x8000) continue;
+            p = (BYTE *)pModule + pModule->res_table + pNameInfo->id;
+            if ((*p == len) && !strncasecmp( p+1, str, len ))
+                return (int)pNameInfo - (int)pModule;
+        }
+    }
+    else  /* Numeric resource id */
+    {
+        WORD id = LOWORD(resId) | 0x8000;
+        for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
+            if (pNameInfo->id == id) return (int)pNameInfo - (int)pModule;
+    }
+    return 0;
+}
 
-    r->size = r->offset = 0;
 
-    /* nametable loaded ? */
-    if (r->wpnt->ne->resnamtab == NULL)
-	NE_LoadNameTable(r->wpnt);
+/***********************************************************************
+ *           NE_FindResource
+ */
+HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
+{
+    NE_MODULE *pModule;
+    NE_TYPEINFO *pTypeInfo;
+    HRSRC hRsrc;
 
-    if (HIWORD(type_name) == 0)
-	type = (int) type_name;
-    else {
-        type_name_ptr = PTR_SEG_TO_LIN( type_name );
-    	if (type_name_ptr[0] == '\0')
-		type = -1;
-    	if (type_name_ptr[0] == '#')
-		type = atoi(type_name_ptr + 1);
-	    else
-    		type = (int) type_name_ptr;
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return 0;
+    pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+
+    if (HIWORD(typeId) || HIWORD(resId))
+    {
+        /* Search the names in the nametable */
+        DWORD id = NE_FindNameTableId( hModule, typeId, resId );
+        if (id)  /* found */
+        {
+            typeId = LOWORD(id);
+            resId  = HIWORD(id);
+        }
     }
 
-    if (HIWORD(resource_name) == 0)
-	x = FindResourceByNumber(r, type, LOWORD(resource_name) | 0x8000);
-    else {
-        resource_name_ptr = PTR_SEG_TO_LIN( resource_name );
-	if (resource_name_ptr[0] == '\0')
-		x = FindResourceByNumber(r, type, -1);
-	if (resource_name_ptr[0] == '#')
-		x = FindResourceByNumber(r, type, atoi(resource_name_ptr + 1));
-	else
-		x = FindResourceByName(r, type, resource_name_ptr);
+    if (HIWORD(typeId) != 0)  /* Named type */
+    {
+        char *str = (char *)PTR_SEG_TO_LIN( typeId );
+        BYTE len = strlen( str );
+        while (pTypeInfo->type_id)
+        {
+            if (!(pTypeInfo->type_id & 0x8000))
+            {
+                BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id;
+                if ((*p == len) && !strncasecmp( p+1, str, len ))
+                {
+                    dprintf_resource( stddeb, "  Found type '%s'\n", str );
+                    hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
+                    if (hRsrc)
+                    {
+                        dprintf_resource( stddeb, "    Found id %08lx\n", resId );
+                        return hRsrc;
+                    }
+                    dprintf_resource( stddeb, "    Not found, going on\n" );
+                }
+            }
+            dprintf_resource( stddeb, "  Skipping type %04x\n",
+                              pTypeInfo->type_id );
+            pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+                                       pTypeInfo->count * sizeof(NE_NAMEINFO));
+        }
     }
-    if (x == -1) {
-        printf("NE_FindResource hInst=%04x typename=%p resname=%p not found!\n", 
-		instance, type_name_ptr, resource_name_ptr);
-	return 0;
+    else  /* Numeric type id */
+    {
+        WORD id = LOWORD(typeId) | 0x8000;
+        while (pTypeInfo->type_id)
+        {
+            if (pTypeInfo->type_id == id)
+            {
+                dprintf_resource( stddeb, "  Found type %04x\n", id );
+                hRsrc = NE_FindResourceFromType( pModule, pTypeInfo, resId );
+                if (hRsrc)
+                {
+                    dprintf_resource( stddeb, "    Found id %08lx\n", resId );
+                    return hRsrc;
+                }
+                dprintf_resource( stddeb, "    Not found, going on\n" );
+            }
+            dprintf_resource( stddeb, "  Skipping type %04x\n",
+                              pTypeInfo->type_id );
+            pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
+                                       pTypeInfo->count * sizeof(NE_NAMEINFO));
+        }
     }
-    return 1;
+    fprintf( stderr, "FindResource(%04x,%08lx,%08lx): Not found.\n",
+             hModule, typeId, resId );
+    return 0;
+}
+
+
+
+/***********************************************************************
+ *           NE_AllocResource
+ */
+HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
+{
+    NE_MODULE *pModule;
+    NE_NAMEINFO *pNameInfo;
+    WORD sizeShift;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return 0;
+    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+    pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+    if (size < (DWORD)pNameInfo->length << sizeShift)
+        size = (DWORD)pNameInfo->length << sizeShift;
+    return GLOBAL_Alloc( GMEM_FIXED, size, hModule, FALSE, FALSE, FALSE );
+}
+
+
+/***********************************************************************
+ *           NE_AccessResource
+ */
+int NE_AccessResource( HMODULE hModule, HRSRC hRsrc )
+{
+    NE_MODULE *pModule;
+    NE_NAMEINFO *pNameInfo;
+    WORD sizeShift;
+    char *name;
+    int fd;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return 0;
+    pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+
+    name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
+    fd = open( name, O_RDONLY );
+    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+    lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+    return fd;
+}
+
+
+/***********************************************************************
+ *           NE_SizeofResource
+ */
+DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc )
+{
+    NE_MODULE *pModule;
+    NE_NAMEINFO *pNameInfo;
+    WORD sizeShift;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return 0;
+    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+    pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+    return (DWORD)pNameInfo->length << sizeShift;
+}
+
+
+/***********************************************************************
+ *           NE_LoadResource
+ */
+HGLOBAL NE_LoadResource( HMODULE hModule,  HRSRC hRsrc )
+{
+    NE_MODULE *pModule;
+    NE_NAMEINFO *pNameInfo;
+    WORD sizeShift;
+    int fd;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return 0;
+    pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
+    if (pNameInfo->handle)
+    {
+        pNameInfo->usage++;
+        dprintf_resource( stddeb, "  Already loaded, new count=%d\n",
+                          pNameInfo->usage );
+        return pNameInfo->handle;
+    }
+    sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
+    dprintf_resource( stddeb, "  Loading, pos=%d, len=%d\n",
+                      (int)pNameInfo->offset << sizeShift,
+                      (int)pNameInfo->length << sizeShift );
+    if ((fd = MODULE_OpenFile( hModule )) == -1) return 0;
+    pNameInfo->handle = NE_AllocResource( hModule, hRsrc, 0 );
+    pNameInfo->usage = 1;
+    lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
+    read( fd, GlobalLock( pNameInfo->handle ),
+          (int)pNameInfo->length << sizeShift );
+    return pNameInfo->handle;
+}
+
+
+/***********************************************************************
+ *           NE_LockResource
+ */
+SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle )
+{
+    /* May need to reload the resource if discarded */
+
+    return WIN16_GlobalLock( handle );
+}
+
+
+/***********************************************************************
+ *           NE_FreeResource
+ */
+BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle )
+{
+    NE_MODULE *pModule;
+    NE_TYPEINFO *pTypeInfo;
+    NE_NAMEINFO *pNameInfo;
+    WORD count;
+
+    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || !pModule->res_table) return FALSE;
+    pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
+    while (pTypeInfo->type_id)
+    {
+        pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
+        for (count = pTypeInfo->count; count > 0; count--)
+        {
+            if (pNameInfo->handle == handle)
+            {
+                if (pNameInfo->usage > 0) pNameInfo->usage--;
+                if (pNameInfo->usage == 0)
+                {
+                    GlobalFree( pNameInfo->handle );
+                    pNameInfo->handle = 0;
+                }
+                return TRUE;
+            }
+            pNameInfo++;
+        }
+        pTypeInfo = (NE_TYPEINFO *)pNameInfo;
+    }
+    fprintf( stderr, "FreeResource: %04x %04x not found!\n", hModule, handle );
+    return FALSE;
 }
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 9caded6..9dcad50 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -198,12 +198,6 @@
 	return 1;
 }
 
-int PE_StartProgram(struct w_files *wpnt)
-{
-	printf("StartPEprogram() called!\n");
-	return 0;
-}
-
 void PE_InitDLL(struct w_files *wpnt)
 {
 	/* Is this a library? */
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 181b90b..0bfc987 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -24,6 +24,7 @@
 /* #define DEBUG_RESOURCE */
 #include "debug.h"
 
+#if 0
 
 static int
 find_lang(char *root, struct PE_Resource_Directory *resource, RESOURCE *r)
@@ -88,7 +89,7 @@
 
 static int 
 find_type(struct PE_Resource_Directory *resource, LPSTR resource_name,
-		LPSTR type_name, RESOURCE *r)
+		LPSTR type_name)
 {
 	int i;
 	char *root, res_name[256];
@@ -146,5 +147,6 @@
                 else
                         type_name = (SEGPTR) type_name_ptr;
         }
-	return find_type(r->wpnt->pe->pe_resource, resource_name, type_name,r);
+	return find_type(r->wpnt->pe->pe_resource, resource_name, type_name);
 }
+#endif
diff --git a/loader/resource.c b/loader/resource.c
index 0d1249b..cfc7dbd 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -1,7 +1,10 @@
 /*
-static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-*/
+ * Resources
+ *
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -15,233 +18,211 @@
 #include "bitmap.h"
 #include "neexe.h"
 #include "icon.h"
-#include "menu.h"
 #include "accel.h"
 #include "dlls.h"
+#include "module.h"
 #include "resource.h"
 #include "library.h"
 #include "stddebug.h"
 #include "debug.h"
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-
-RESOURCE *Top = NULL;
-
-extern int NE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
-extern int PE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
-
 #define PrintId(name) \
-	if (HIWORD((DWORD)name)) \
-		printf(", '%s'", (char *)PTR_SEG_TO_LIN(name)); \
-  	else \
-		printf(", #%d", LOWORD(name)); 
+    if (HIWORD((DWORD)name)) \
+        dprintf_resource( stddeb, "'%s'", (char *)PTR_SEG_TO_LIN(name)); \
+    else \
+        dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
 
 /**********************************************************************
- *			FindResource	[KERNEL.60]
+ *	    FindResource    (KERNEL.60)
  */
-HANDLE FindResource(HANDLE instance, SEGPTR name, SEGPTR type)
+HRSRC FindResource( HMODULE hModule, SEGPTR name, SEGPTR type )
 {
-	int status;
-	RESOURCE *r;
-	HANDLE rh;
+    WORD *pModule;
 
-	if(debugging_resource){
-	printf("FindResource(%04X", instance);
-	PrintId(name);
-	PrintId(type);
-	printf(")\n");
-	}
-	
-	/* FIXME: did we already find this one ? */
-
-	if ((rh = GlobalAlloc(GMEM_MOVEABLE, sizeof(RESOURCE))) == 0)
-		return 0;
-
-	r = (RESOURCE *)GlobalLock(rh);
-	r->next = Top;
-	Top = r;
-	r->info_mem = rh;
-	r->rsc_mem = 0;
-	r->count = 0;
-	if (HIWORD((DWORD)name))
-		r->name = strdup(PTR_SEG_TO_LIN(name));
-	else
-		r->name = (LPSTR)name;
-
-	if (HIWORD((DWORD)type))
-		r->type = strdup(PTR_SEG_TO_LIN(type));
-	else
-		r->type = (LPSTR)type;
-
-	r->wpnt = GetFileInfo(instance);
-	r->fd = dup(r->wpnt->fd);
-	if (r->wpnt->ne)
-		status = NE_FindResource(instance, name, type, r);
-	else
-		status = PE_FindResource(instance, name, type, r);
-
-	if (!status) {
-		if (HIWORD((DWORD)r->name))
-			free(r->name);
-
-		if (HIWORD((DWORD)r->type))
-			free(r->type);
-		close(r->fd);
-
-		Top = r->next;
-		GlobalUnlock(rh);
-		return 0;
-	} else
-		return rh;
-}
-
-/**********************************************************************
- *			AllocResource	[KERNEL.66]
- */
-HANDLE AllocResource(HANDLE instance, HANDLE hResInfo, DWORD dwSize)
-{
-	RESOURCE *r;
-	int image_size;
-
-	dprintf_resource(stddeb, "AllocResource(%04X, %04X, %08X);\n", 
-		instance, hResInfo, (int) dwSize);
-
-	if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
-		return 0;
-    
-	image_size = r->size;
-
-	if (dwSize == 0)
-		r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
-	else
-		r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, dwSize);
-
-	GlobalUnlock(hResInfo);
-
-	return r->rsc_mem;
-}
-
-/**********************************************************************
- *				AccessResource	[KERNEL.64]
- */
-int AccessResource(HANDLE instance, HANDLE hResInfo)
-{
-	int fd;
-	RESOURCE *r;
-
-	dprintf_resource(stddeb, "AccessResource(%04X, %04X);\n", 
-		instance, hResInfo);
-
-	if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
-		return -1;
-
-	fd = r->fd;
-	lseek(fd, r->offset, SEEK_SET);
-	GlobalUnlock(hResInfo);
-
-	return fd;
-}
-
-/**********************************************************************
- *				SizeofResource	[KERNEL.65]
- */
-WORD SizeofResource(HANDLE instance, HANDLE hResInfo)
-{
-	RESOURCE *r;
-	int size;
-	
-	dprintf_resource(stddeb, "SizeofResource(%04X, %04X);\n", 
-		instance, hResInfo);
-
-	if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
-		return 0;
-
-	size = r->size;
-	GlobalUnlock(hResInfo);
-
-	return size;
-}
-
-/**********************************************************************
- *			LoadResource	[KERNEL.61]
- */
-HANDLE LoadResource(HANDLE instance, HANDLE hResInfo)
-{
-    RESOURCE *r;
-    int image_size, fd;
-    void *image;
-    HANDLE h;
-
-    dprintf_resource(stddeb, "LoadResource(%04X, %04X);\n", instance, hResInfo);
-
-    if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
-	return 0;
-    
-    h = r->rsc_mem = AllocResource(instance, hResInfo, 0);
-    image = GlobalLock(h);
-    image_size = r->size;
-    fd = AccessResource(instance, hResInfo);
-
-    if (image == NULL || read(fd, image, image_size) != image_size) {
-	GlobalFree(h);
-	GlobalUnlock(hResInfo);
-	return 0;
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "FindResource: module=%04x type=", hModule );
+    PrintId( type );
+    dprintf_resource( stddeb, " name=" );
+    PrintId( name );
+    dprintf_resource( stddeb, "\n" );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_FindResource( hModule, type, name );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
     }
-    r->count++;
-    close(fd);
-    GlobalUnlock(h);
-    GlobalUnlock(hResInfo);
-    return h;
 }
 
-/**********************************************************************
- *				LockResource	[KERNEL.62]
- */
 
-/* 16-bit version */
-SEGPTR WIN16_LockResource(HANDLE hResData)
+/**********************************************************************
+ *	    LoadResource    (KERNEL.61)
+ */
+HGLOBAL LoadResource( HMODULE hModule, HRSRC hRsrc )
 {
-    return WIN16_GlobalLock(hResData);
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
+                     hModule, hRsrc );
+    if (!hRsrc) return 0;
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_LoadResource( hModule, hRsrc );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	    LockResource    (KERNEL.62)
+ */
+/* 16-bit version */
+SEGPTR WIN16_LockResource( HGLOBAL handle )
+{
+    HMODULE hModule;
+    WORD *pModule;
+
+    dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
+    if (!handle) return (SEGPTR)0;
+    hModule = GetExePtr( handle );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_LockResource( hModule, handle );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
 }
 
 /* 32-bit version */
-LPSTR LockResource(HANDLE hResData)
+LPSTR LockResource( HGLOBAL handle )
 {
-    return GlobalLock(hResData);
+    HMODULE hModule;
+    WORD *pModule;
+
+    dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
+    if (!handle) return NULL;
+    hModule = GetExePtr( handle );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
 }
 
+
 /**********************************************************************
- *				FreeResource	[KERNEL.63]
+ *	    FreeResource    (KERNEL.63)
  */
-HANDLE FreeResource(HANDLE hResData)
+BOOL FreeResource( HGLOBAL handle )
 {
-    RESOURCE *r, *rp;
+    HMODULE hModule;
+    WORD *pModule;
 
-    dprintf_resource(stddeb, "FreeResource: handle %04x\n", hResData);
-
-    for (r = rp = Top; r ; r = r->next) {
-	if (r->rsc_mem == hResData) {
-	    if (r->count == 0) {
-		    if (rp != r)
-			rp->next = r->next;
-		    else
-			Top = r->next;
-
-		    if (HIWORD((DWORD)r->name))
-		    	free(r->name);
-                    if (HIWORD((DWORD)r->type))
-			free(r->type);
-		    GlobalFree(r->rsc_mem);
-		    GlobalFree(r->info_mem);
-		    return 0;
-	    } else
-	    	r->count--;
-	}
-	rp = r;
+    dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle );
+    if (!handle) return FALSE;
+    hModule = GetExePtr( handle );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_FreeResource( hModule, handle );
+      case PE_SIGNATURE:
+        return FALSE;
+      default:
+        return FALSE;
     }
-    return hResData;
 }
-
+
+
+/**********************************************************************
+ *	    AccessResource    (KERNEL.64)
+ */
+int AccessResource( HMODULE hModule, HRSRC hRsrc )
+{
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
+                     hModule, hRsrc );
+    if (!hRsrc) return 0;
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_AccessResource( hModule, hRsrc );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	    SizeofResource    (KERNEL.65)
+ */
+DWORD SizeofResource( HMODULE hModule, HRSRC hRsrc )
+{
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
+                     hModule, hRsrc );
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_SizeofResource( hModule, hRsrc );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+}
+
+
+/**********************************************************************
+ *	    AllocResource    (KERNEL.66)
+ */
+HGLOBAL AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
+{
+    WORD *pModule;
+
+    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
+    dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
+                     hModule, hRsrc, size );
+    if (!hRsrc) return 0;
+    if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
+    switch(*pModule)
+    {
+      case NE_SIGNATURE:
+        return NE_AllocResource( hModule, hRsrc, size );
+      case PE_SIGNATURE:
+        return 0;
+      default:
+        return 0;
+    }
+}
+
+
 /**********************************************************************
  *			ConvertCoreBitmap
  */
@@ -306,35 +287,14 @@
 			   bits, image, DIB_RGB_COLORS );
 } 
 
-/**********************************************************************
- *			RSC_LoadResource
- */
-HANDLE
-RSC_LoadResource(int instance, SEGPTR rsc_name, SEGPTR type, int *image_size_ret)
-{
-	HANDLE hResInfo;
-	RESOURCE *r;
 
-	dprintf_resource(stddeb, "RSC_LoadResource: instance = %04x, name = %08lx, type = %08lx\n",
-	   instance, rsc_name, type);
-
-	if ((hResInfo = FindResource(instance, rsc_name, type)) == (HANDLE) NULL) {
-		return (HANDLE)NULL;
-	}
-	r = (RESOURCE *)GlobalLock(hResInfo);
-	if (image_size_ret) 
-		*image_size_ret = r->size;
-	r->count++;
-	GlobalUnlock(hResInfo);
-	return LoadResource(instance, hResInfo);
-}
-
 /**********************************************************************
  *			LoadIcon [USER.174]
  */
 HICON LoadIcon( HANDLE instance, SEGPTR icon_name )
 {
     HICON 	hIcon;
+    HRSRC       hRsrc;
     HANDLE 	rsc_mem;
     WORD 	*lp;
     ICONDESCRIP *lpicodesc;
@@ -344,7 +304,9 @@
     BITMAPINFOHEADER 	*bih;
     RGBQUAD	*rgbq;
     HDC 	hdc;
-    int 	image_size;
+    BITMAPINFO *pInfo;
+    char *bits;
+    int size;
 
     if (HIWORD(icon_name))
         dprintf_resource( stddeb, "LoadIcon: %04x '%s'\n",
@@ -359,85 +321,73 @@
         return OBM_LoadIcon( LOWORD((int)icon_name) );
     }
 
-    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
-    rsc_mem = RSC_LoadResource(instance, icon_name,
-                               (SEGPTR) NE_RSCTYPE_GROUP_ICON, &image_size);
+    if (!(hRsrc = FindResource( instance, icon_name, RT_GROUP_ICON))) return 0;
+    rsc_mem = LoadResource( instance, hRsrc );
     if (rsc_mem == (HANDLE)NULL) {
 	printf("LoadIcon / Icon %08x not Found !\n", (int) icon_name);
-	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
 	}
-    lp = (WORD *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
-	return 0;
-	}
+    lp = (WORD *)LockResource(rsc_mem);
     lpicodesc = (ICONDESCRIP *)(lp + 3);
     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
     if (hIcon == (HICON)NULL) {
-	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+        FreeResource( rsc_mem );
 	return 0;
 	}
     lpico = (ICONALLOC *)GlobalLock(hIcon);
     lpico->descriptor = *lpicodesc;
     width = lpicodesc->Width;
     height = lpicodesc->Height;
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
-    rsc_mem = RSC_LoadResource( instance, 
-                                MAKEINTRESOURCE(lpicodesc->icoDIBOffset), 
-                                (SEGPTR) NE_RSCTYPE_ICON, &image_size );
-    if (rsc_mem == (HANDLE)NULL) {
-	printf("LoadIcon / Icon %08lx Bitmaps not Found !\n", icon_name );
-	ReleaseDC(GetDesktopWindow(), hdc); 
-	return 0;
-	}
-    lp = (WORD *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
-	return 0;
- 	}
-    bmi = (BITMAPINFO *)lp;
-    bih = (BITMAPINFOHEADER *)lp;
-    rgbq = &bmi->bmiColors[0];
-    bih->biHeight = bih->biHeight / 2;
-/*
-    printf("LoadIcon / image_size=%d width=%d height=%d bih->biBitCount=%d bih->biSizeImage=%ld\n", 
-    	image_size, width, height, bih->biBitCount, bih->biSizeImage);
-*/
-    if (bih->biSize == sizeof(BITMAPINFOHEADER))
-	lpico->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)bih);
-    else
-        lpico->hBitmap = 0;
+    FreeResource( rsc_mem );
+    if (!(hRsrc = FindResource( instance,
+                              MAKEINTRESOURCE(lpico->descriptor.icoDIBOffset), 
+                              RT_ICON ))) return 0;
+    if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+
+    bmi = (BITMAPINFO *)LockResource(rsc_mem);
+    size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
+    pInfo = (BITMAPINFO *)malloc( size );
+    memcpy( pInfo, bmi, size );
+    bih = &pInfo->bmiHeader;
+    bih->biHeight /= 2;
+
+    if (!(hdc = GetDC( 0 ))) return 0;
+    if (bih->biSize != sizeof(BITMAPINFOHEADER)) return 0;
+    lpico->hBitmap = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
+                                    (char*)bmi + size, pInfo, DIB_RGB_COLORS );
+    if (bih->biSizeImage == 0)
+    {
+	if (bih->biCompression != BI_RGB)
+        {
+	    fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
+            FreeResource( rsc_mem );
+	    ReleaseDC( 0, hdc); 
+	    return 0;
+        }
+	bih->biSizeImage = DIB_GetImageWidthBytes(bih->biWidth,bih->biBitCount)
+                             * bih->biHeight;
+    }
+    bits = (char *)bmi + size +
+             bih->biSizeImage * bih->biBitCount / (bih->biBitCount+1);
     bih->biBitCount = 1;
-    bih->biClrUsed = bih->biClrImportant  = 2;
+    bih->biClrUsed = bih->biClrImportant = 2;
+    rgbq = &bmi->bmiColors[0];
     rgbq[0].rgbBlue = rgbq[0].rgbGreen = rgbq[0].rgbRed = 0x00;
     rgbq[1].rgbBlue = rgbq[1].rgbGreen = rgbq[1].rgbRed = 0xff;
     rgbq[0].rgbReserved = rgbq[1].rgbReserved = 0;
-    if (bih->biSizeImage == 0) {
-	if (bih->biCompression != BI_RGB) {
-	    fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
-	    GlobalFree(rsc_mem);
-	    ReleaseDC(GetDesktopWindow(), hdc); 
-	    return 0;
-	    }
-	bih->biSizeImage = (bih->biWidth * bih->biHeight * bih->biBitCount
-			    + 7) / 8;
-	}
-    lpico->hBitMask = CreateDIBitmap(hdc, bih, CBM_INIT,
-    	(LPSTR)lp + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
-	(BITMAPINFO *)bih, DIB_RGB_COLORS );
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
-    ReleaseDC(GetDesktopWindow(), hdc);
+    lpico->hBitMask = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT,
+/*  	(LPSTR)bmi + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
+   (LPSTR)lp + bih->biSizeImage + bih->biSize + 4*lpicodesc->ColorCount, */
+                                     bits, pInfo, DIB_RGB_COLORS );
+    FreeResource( rsc_mem );
+    ReleaseDC( 0, hdc);
+    free( pInfo );
     GlobalUnlock(hIcon);
     dprintf_resource(stddeb,"LoadIcon Alloc hIcon=%X\n", hIcon);
     return hIcon;
 }
-
+
+
 /**********************************************************************
  *			CreateIcon [USER.407]
  */
@@ -516,9 +466,10 @@
 {
     HANDLE 	hAccel;
     HANDLE 	rsc_mem;
+    HRSRC hRsrc;
     BYTE 	*lp;
     ACCELHEADER	*lpAccelTbl;
-    int 	i, image_size, n;
+    int 	i, n;
 
     if (HIWORD(lpTableName))
         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
@@ -527,19 +478,12 @@
         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
                        instance, LOWORD(lpTableName) );
 
-    rsc_mem = RSC_LoadResource( instance, lpTableName,
-                                (SEGPTR) NE_RSCTYPE_ACCELERATOR, &image_size );
-    if (rsc_mem == (HANDLE)NULL) {
-	printf("LoadAccelerators(%08lx) not found!\n", lpTableName );
-	return 0;
-	}
-    lp = (BYTE *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	return 0;
-	}
-    dprintf_accel(stddeb,"LoadAccelerators / image_size=%d\n", image_size);
-    n = image_size/5;
+    if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
+      return 0;
+    if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
+
+    lp = (BYTE *)LockResource(rsc_mem);
+    n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
     hAccel = GlobalAlloc(GMEM_MOVEABLE, 
     	sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
@@ -558,8 +502,7 @@
 	lpAccelTbl->wCount++;
  	}
     GlobalUnlock(hAccel);
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
+    FreeResource( rsc_mem );
     return hAccel;
 }
 
@@ -631,18 +574,17 @@
     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
 	   "length = %d\n", instance, resource_id, (int) buffer, buflen);
 
-    hrsrc = FindResource( instance, (SEGPTR)((resource_id >> 4) + 1),
-                          (SEGPTR) NE_RSCTYPE_STRING );
+    hrsrc = FindResource( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING );
     if (!hrsrc) return 0;
     hmem = LoadResource( instance, hrsrc );
     if (!hmem) return 0;
     
-    p = GlobalLock(hmem);
+    p = LockResource(hmem);
     string_num = resource_id & 0x000f;
     for (i = 0; i < string_num; i++)
 	p += *p + 1;
     
-    i = MIN(buflen - 1, *p);
+    i = min(buflen - 1, *p);
 	if (i > 0) {
 		memcpy(buffer, p + 1, i);
 		buffer[i] = '\0';
@@ -655,87 +597,11 @@
 		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);
 		}
-    FreeResource( hrsrc );
+    FreeResource( hmem );
 
     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
     return i;
 }
-
-/**********************************************************************
- *			LoadMenu		[USER.150]
- */
-HMENU LoadMenu( HINSTANCE instance, SEGPTR menu_name )
-{
-    HMENU     		hMenu;
-    HANDLE		hMenu_desc;
-    MENU_HEADER 	*menu_desc;
 
-    if (HIWORD(menu_name))
-        dprintf_resource( stddeb, "LoadMenu(%04x,'%s')\n",
-                          instance, (char *)PTR_SEG_TO_LIN( menu_name ) );
-    else
-        dprintf_resource( stddeb, "LoadMenu(%04x,%04x)\n",
-                          instance, LOWORD(menu_name) );
 
-    if (!menu_name) return 0;
 
-    if (!(hMenu_desc = RSC_LoadResource( instance, menu_name,
-                                         (SEGPTR) NE_RSCTYPE_MENU, NULL )))
-        return 0;
-	
-    menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc);
-    hMenu = LoadMenuIndirect((LPSTR)menu_desc);
-    return hMenu;
-}
-
-/**********************************************************************
- *					LoadBitmap
- */
-HBITMAP LoadBitmap( HANDLE instance, SEGPTR bmp_name )
-{
-    HBITMAP hbitmap;
-    HANDLE rsc_mem;
-    HDC hdc;
-    long *lp;
-    int image_size;
-    int size;
-    
-    if (HIWORD(bmp_name))
-        dprintf_resource( stddeb, "LoadBitmap(%04x,'%s')\n",
-                          instance, (char *)PTR_SEG_TO_LIN( bmp_name ) );
-    else
-        dprintf_resource( stddeb, "LoadBitmap(%04x,%04x)\n",
-                          instance, LOWORD( bmp_name ) );
-
-    if (!instance)
-    {
-        if (HIWORD((int)bmp_name)) return 0;  /* FIXME: should handle '#xxx' */
-        return OBM_LoadBitmap( LOWORD((int)bmp_name) );
-    }
-
-    rsc_mem = RSC_LoadResource(instance, bmp_name, (SEGPTR) NE_RSCTYPE_BITMAP, 
-			       &image_size);
-    if (rsc_mem == (HANDLE)NULL) {
-	printf("LoadBitmap(%04x,%08lx)\n", instance, bmp_name);
-	return 0;
-	}
-    lp = (long *) GlobalLock(rsc_mem);
-    if (lp == NULL)
-    {
-	GlobalFree(rsc_mem);
-	return 0;
-    }
-
-    if (!(hdc = GetDC(0))) lp = NULL;
-    size = CONV_LONG (*lp);
-    if (size == sizeof(BITMAPCOREHEADER)){
-	CONV_BITMAPCOREHEADER (lp);
-	hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
-    } else if (size == sizeof(BITMAPINFOHEADER)){
-	CONV_BITMAPINFO (lp);
-	hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
-    } else hbitmap = 0;
-    GlobalFree(rsc_mem);
-    ReleaseDC( 0, hdc );
-    return hbitmap;
-}
diff --git a/loader/selector.c b/loader/selector.c
index 142c703..f54605a 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -36,6 +36,7 @@
 #include "neexe.h"
 #include "if1632.h"
 #include "prototypes.h"
+#include "module.h"
 #include "stddebug.h"
 /* #define DEBUG_SELECTORS */
 #include "debug.h"
@@ -44,11 +45,6 @@
 #define MAX_ENV_SIZE 16384  /* Max. environment size (ought to be dynamic) */
 
 static HANDLE EnvironmentHandle = 0;
-WORD PSPSelector = 0;
-
-#define MAX_SELECTORS (512 * 2)
-
-int max_selectors = 0;
 
 
 extern char WindowsPath[256];
@@ -57,9 +53,6 @@
 extern int Argc;
 extern char **environ;
 
-unsigned int 
-GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
-
 
 /**********************************************************************
  *  Check whether pseudo-functions like __0040H for direct memory
@@ -100,14 +93,6 @@
     else if( !strcasecmp( function, "__F000H" ) ) nr = 7;
     else if( !strcasecmp( function, "__C000H" ) ) nr = 8;
     else if( !strcasecmp( function, "__0040H" ) ) nr = 9;
-    else if( !strcasecmp( function, "__AHIncr" ) ) {
-      *sel = *offset = __AHINCR;   
-      return 1;      
-    }
-    else if( !strcasecmp( function, "__AHShift" ) ) {
-      *sel = *offset = __AHSHIFT;
-      return 1;
-    }
      else
       return 0;
   }
@@ -123,12 +108,6 @@
     case 194: nr = 7; break;
     case 195: nr = 8; break;
     case 193: nr = 9; break;
-    case 114:
-      *sel = *offset = __AHINCR;  
-      return 1;
-    case 113:
-      *sel = *offset = __AHSHIFT;
-      return 1;
     default: return 0;
     }
   }
@@ -143,155 +122,53 @@
  
 
 
-/**********************************************************************
- *					GetEntryPointFromOrdinal
- */
-union lookup{
-    struct entry_tab_header_s *eth;
-    struct entry_tab_movable_s *etm;
-    struct entry_tab_fixed_s *etf;
-    char  * cpnt;
-};
-
 unsigned int GetEntryDLLName( char * dll_name, char * function,
                               WORD* sel, WORD *offset )
 {
-	struct dll_table_s *dll_table;
-	struct w_files * wpnt;
-	char * cpnt;
-	int ordinal, j, len;
+    HMODULE hModule;
+    struct dll_table_s *dll_table;
+    int ordinal, addr;
 
-	if( GetMemoryReference( dll_name, function, sel, offset ) )
-	  return 0;
+    if( GetMemoryReference( dll_name, function, sel, offset ) )
+        return 0;
 
-	dll_table = FindDLLTable(dll_name);
-
-	if(dll_table) {
-		ordinal = FindOrdinalFromName(dll_table->dll_table,function);
-		if(!ordinal){
-			dprintf_module(stddeb,"GetEntryDLLName: %s.%s not found\n",
-				dll_name, function);
-			*sel = *offset = 0;
-			return -1;
-		}
-		*sel    = dll_table->dll_table[ordinal].selector;
-		*offset = dll_table->dll_table[ordinal].offset;
+    hModule = GetModuleHandle( dll_name );
+    ordinal = MODULE_GetOrdinal( hModule, function );
+    if (!ordinal) return 1;
+    addr = MODULE_GetEntryPoint( hModule, ordinal );
+    if (!addr) return 1;
 #ifdef WINESTAT
-		dll_table->dll_table[ordinal].used++;
+    if ((dll_table = FindDLLTable(dll_name)) != NULL)
+    {
+        dll_table->dll_table[ordinal].used++;
+    }
 #endif
-		return 0;
-	};
-
-	/* We need a means  of determining the ordinal for the function. */
-	/* Not a builtin symbol, look to see what the file has for us */
-	for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
-		if(strcasecmp(wpnt->name, dll_name)) continue;
-		cpnt  = wpnt->ne->nrname_table;
-		while(1==1){
-			if( ((int) cpnt)  - ((int)wpnt->ne->nrname_table) >  
-			   wpnt->ne->ne_header->nrname_tab_length)  return 1;
-			len = *cpnt++;
-			if(strncmp(cpnt, function, len) ==  0) break;
-			cpnt += len + 2;
-		};
-		ordinal =  *((unsigned short *)  (cpnt +  len));
-		j = GetEntryPointFromOrdinal(wpnt, ordinal);		
-		*offset = LOWORD(j);
-		*sel    = HIWORD(j);
-		return 0;
-	};
-	return 1;
+    *offset = LOWORD(addr);
+    *sel    = HIWORD(addr);
+    return 0;
 }
 
+
 unsigned int GetEntryDLLOrdinal( char * dll_name, int ordinal,
                                  WORD *sel, WORD *offset )
 {
-	struct dll_table_s *dll_table;
-	struct w_files * wpnt;
-	int j;
+    HMODULE hModule;
+    struct dll_table_s *dll_table;
+    int addr;
 
-	if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
-	  return 0;
+    if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
+        return 0;
 
-	dll_table = FindDLLTable(dll_name);
-
-	if(dll_table) {
-	    *sel    = dll_table->dll_table[ordinal].selector;
-	    *offset = dll_table->dll_table[ordinal].offset;
+    hModule = GetModuleHandle( dll_name );
+    addr = MODULE_GetEntryPoint( hModule, ordinal );
+    if (!addr) return 1;
 #ifdef WINESTAT
-            dll_table->dll_table[ordinal].used++;
+    if ((dll_table = FindDLLTable(dll_name)) != NULL)
+        dll_table->dll_table[ordinal].used++;
 #endif
-	    return 0;
-	};
-
-	/* Not a builtin symbol, look to see what the file has for us */
-	for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
-		if(strcasecmp(wpnt->name, dll_name)) continue;
-		j = GetEntryPointFromOrdinal(wpnt, ordinal);
-		*offset = LOWORD(j);
-		*sel    = HIWORD(j);
-		return 0;
-	};
-	return 1;
-}
-
-unsigned int 
-GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal)
-{
-    union lookup entry_tab_pointer;
-    struct entry_tab_header_s *eth;
-    struct entry_tab_movable_s *etm;
-    struct entry_tab_fixed_s *etf;
-    int current_ordinal;
-    int i;
-    
-   entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
-    /*
-     * Let's walk through the table until we get to our entry.
-     */
-    current_ordinal = 1;
-    while (1)
-    {
-	/*
-	 * Read header for this bundle.
-	 */
-	eth = entry_tab_pointer.eth++;
-	
-	if (eth->n_entries == 0)
-	    return 0xffffffff;  /* Yikes - we went off the end of the table */
-
-	if (eth->seg_number == 0)
-	{
-	    current_ordinal += eth->n_entries;
-	    if(current_ordinal > ordinal) return 0;
-	    continue;
-	}
-
-	/*
-	 * Read each of the bundle entries.
-	 */
-	for (i = 0; i < eth->n_entries; i++, current_ordinal++)
-	{
-	    if (eth->seg_number >= 0xfe)
-	    {
-                etm = entry_tab_pointer.etm++;
-		if (current_ordinal == ordinal)
-		{
-		    return MAKELONG(etm->offset,
-                                  wpnt->ne->selector_table[etm->seg_number-1]);
-		}
-	    }
-	    else
-	    {
-                etf = entry_tab_pointer.etf++;
-		if (current_ordinal == ordinal)
-		{
-		    return MAKELONG( etf->offset[0] + ((int)etf->offset[1]<<8),
-                                  wpnt->ne->selector_table[eth->seg_number-1]);
-		}
-	    }
-	}
-    }
+    *offset = LOWORD(addr);
+    *sel    = HIWORD(addr);
+    return 0;
 }
 
 
@@ -356,276 +233,14 @@
 }
 
 
-/**********************************************************************
- *           GetCurrentPDB   (KERNEL.37)
- */
-WORD GetCurrentPDB()
-{
-    return PSPSelector;
-}
-
-
-/**********************************************************************
- *           CreatePSP
- */
-static WORD CreatePSP(void)
-{
-    HANDLE handle;
-    struct dos_psp_s *psp;
-    char *p1, *p2;
-    int i;
-    WORD sel, offset;
-
-    handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*psp) );
-    if (!handle) return 0;
-    psp = (struct dos_psp_s *) GlobalLock( handle );
-
-    /*
-     * Fill PSP
-     */
-    psp->pspInt20 = 0x20cd;
-    psp->pspDispatcher[0] = 0x9a;
-    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;
-    for (i = 1; i < Argc; i++)
-    {
-	if ((int) ((int) p1 - (int) psp->pspCommandTail) + 
-	    strlen(Argv[i]) > 124)
-	    break;
-	
-	if (i != 1)
-	    *p1++ = ' ';
-
-	for (p2 = Argv[i]; *p2 != '\0'; )
-	    *p1++ = *p2++;
-	
-    }
-    *p1 = '\0';
-    psp->pspCommandTailCount = strlen(psp->pspCommandTail);
-
-    return SELECTOROF( WIN16_GlobalLock( handle ) );
-}
-
 
 /**********************************************************************
  *					CreateSelectors
  */
-unsigned short *CreateSelectors(struct w_files * wpnt)
+void CreateSelectors(void)
 {
-    int fd = wpnt->fd;
-    struct ne_segment_table_entry_s *seg_table = wpnt->ne->seg_table;
-    struct ne_header_s *ne_header = wpnt->ne->ne_header;
-    unsigned short auto_data_sel;
-
-    int old_length, file_image_length = 0;
-    int saved_old_length = 0;
-    int i, length;
-    void *base_addr;
-    WORD *selectors;
-    HGLOBAL handle;
-
-    auto_data_sel=0;
-    /*
-     * Allocate memory for the table to keep track of all selectors.
-     */
-    selectors = (WORD *) malloc( ne_header->n_segment_tab * sizeof(WORD) );
-    if (selectors == NULL)
-	return NULL;
-
-    /*
-     * Step through the segment table in the exe header.
-     */
-    for (i = 0; i < ne_header->n_segment_tab; i++)
-    {
-	/*
-	 * Is there an image for this segment in the file?
-	 */
-	if (seg_table[i].seg_data_offset == 0)
-	{
-	    /*
-	     * No image in exe file, let's allocate some memory for it.
-	     */
-	    length = seg_table[i].min_alloc;
-	}
-	else
-	{
-	    /*
-	     * Image in file, let's just point to the image in memory.
-	     */
-	    length            = seg_table[i].min_alloc;
-	    file_image_length = seg_table[i].seg_data_length;
-	    if (file_image_length == 0)	file_image_length = 0x10000;
-	}
-
-	if (length == 0) length = 0x10000;
-	old_length = length;
-
-	/*
-	 * If this is the automatic data segment, its size must be adjusted.
-	 * First we need to check for local heap.  Second we nee to see if
-	 * this is also the stack segment.
-	 */
-	if (i + 1 == ne_header->auto_data_seg || i + 1 == ne_header->ss)
-	{
-	    length = 0x10000;
-	    ne_header->sp = length - 2;
-            dprintf_selectors(stddeb,"Auto data image length %x\n",file_image_length);
- 	}
-
-	/*
-	 * Is this a DATA or CODE segment?
-	 */
-        if (seg_table[i].seg_flags & NE_SEGFLAGS_DATA)
-        {
-            handle = GLOBAL_Alloc( GMEM_ZEROINIT, length, 0, FALSE,
-                               seg_table[i].seg_flags & NE_SEGFLAGS_READONLY );
-        }
-        else
-        {
-            handle = GLOBAL_Alloc( 0, length, 0, TRUE,
-                            seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY );
-        }
-        base_addr = GlobalLock( handle );
-        selectors[i] = GlobalHandleToSel( handle );
-
-	if (seg_table[i].seg_data_offset != 0)
-	{
-	    /*
-	     * Image in file.
-	     */
-	    lseek( fd, seg_table[i].seg_data_offset * 
-                   (1 << ne_header->align_shift_count), SEEK_SET );
-	    if(read(fd, base_addr, file_image_length) != file_image_length)
-            {
-                fprintf( stderr, "Unable to read segment %d from file\n", i+1);
-                exit(1);
-            }
-	}
-
-	/*
-	 * If this is the automatic data segment, then we must initialize
-	 * the local heap.
-	 */
-	if (i + 1 == ne_header->auto_data_seg)
-	{
-	    auto_data_sel = selectors[i];
-	    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
-			   - ne_header->stack_length );
-#if 0
-	    HEAP_LocalInit(auto_data_sel,
-                           (char *)GET_SEL_BASE(selectors[i]) + saved_old_length, 
-			   0x10000 - 2 - saved_old_length 
-			   - ne_header->stack_length);
-#endif
-    }
-
-    if(!EnvironmentHandle)
-    {
-        EnvironmentHandle = CreateEnvironment();
-        PSPSelector = CreatePSP();
-    }
-
-    return selectors;
+    if(!EnvironmentHandle) EnvironmentHandle = CreateEnvironment();
 }
 
 
-/**********************************************************************
- */
-void
-FixupFunctionPrologs(struct w_files * wpnt)
-{
-    union lookup entry_tab_pointer;
-    struct entry_tab_header_s *eth;
-    struct entry_tab_movable_s *etm;
-    struct entry_tab_fixed_s *etf;
-    unsigned char *fixup_ptr;
-    int i;
-
-/*    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.
-     */
-    while (1)
-    {
-	/* Get bundle header */
-	eth = entry_tab_pointer.eth++;
-
-	/* Check for end of table */
-	if (eth->n_entries == 0)
-	    return;
-
-	/* Check for empty bundle */
-	if (eth->seg_number == 0)
-	    continue;
-
-	/* Examine each bundle */
-	for (i = 0; i < eth->n_entries; i++)
-	{
-	    /* Moveable segment */
-	    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;
-	      }
-	    } 
-	}
-    }
-}
-
 #endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index 93c14a5..7f26131 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -1,279 +1,831 @@
 /*
- *        Tasks functions
+ * Task functions
  *
-static char Copyright[] = "Copyright  Martin Ayotte, 1994";
-*/
+ * Copyright 1995 Alexandre Julliard
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
 #include "windows.h"
-#include "callback.h"
 #include "task.h"
+#include "callback.h"
+#include "global.h"
+#include "instance.h"
+#include "module.h"
+#include "neexe.h"
+#include "selectors.h"
+#include "toolhelp.h"
+#include "wine.h"
 #include "stddebug.h"
 #include "debug.h"
 
-static LPWINETASKENTRY lpTaskList = NULL;
-static int nTaskCount = 0;
 
-/**********************************************************************
- *				GetCurrentTask	[KERNEL.36]
+#define MIN_THUNKS  32  /* Min. thunks allocated when creating a new segment */
+
+#define STACK32_SIZE 0x10000  /* 32-bit stack size for each task */
+
+
+static HTASK hFirstTask = 0;
+static HTASK hCurrentTask = 0;
+static HTASK hTaskToKill = 0;
+static WORD nTaskCount = 0;
+
+  /* TASK_Reschedule() 16-bit entry point */
+static FARPROC TASK_RescheduleProc;
+
+#define TASK_SCHEDULE()  CallTo16_word_(TASK_RescheduleProc,0)
+
+
+/***********************************************************************
+ *           TASK_Init
  */
-HTASK GetCurrentTask(void)
+BOOL TASK_Init(void)
 {
-	LPWINETASKENTRY lpTask = lpTaskList;
-	int pid = getpid();
-	dprintf_task(stddeb,"GetCurrentTask() // unix_pid=%08X !\n", pid);
-	if (lpTask == NULL) return 0;
-	while (TRUE) {
-		if (lpTask->unix_pid == pid) break;
-		if (lpTask->lpNextTask == NULL) return 0;
-		lpTask = lpTask->lpNextTask;
-		}
-	dprintf_task(stddeb,"GetCurrentTask() returned hTask=%04X !\n", lpTask->te.hTask);
-	return lpTask->te.hTask;
+    TASK_RescheduleProc = (FARPROC)GetWndProcEntry16( "TASK_Reschedule" );
+    return TRUE;
 }
 
 
-/**********************************************************************
- *				GetNumTasks	[KERNEL.152]
+/***********************************************************************
+ *           TASK_LinkTask
  */
-WORD GetNumTasks(void)
+static void TASK_LinkTask( HTASK hTask )
 {
-	dprintf_task(stddeb,"GetNumTasks() returned %d !\n", nTaskCount);
-	return nTaskCount;
+    HTASK *prevTask;
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+    prevTask = &hFirstTask;
+    while (*prevTask)
+    {
+        TDB *prevTaskPtr = (TDB *)GlobalLock( *prevTask );
+        if (prevTaskPtr->priority >= pTask->priority) break;
+        prevTask = &prevTaskPtr->hNext;
+    }
+    pTask->hNext = *prevTask;
+    *prevTask = hTask;
+    nTaskCount++;
 }
 
 
-/**********************************************************************
- *				GetWindowTask	[USER.224]
+/***********************************************************************
+ *           TASK_UnlinkTask
  */
-HTASK GetWindowTask(HWND hWnd)
+static void TASK_UnlinkTask( HTASK hTask )
 {
-	HWND 	*wptr;
-	int		count;
-	LPWINETASKENTRY lpTask = lpTaskList;
-	dprintf_task(stddeb,"GetWindowTask(%04X) !\n", hWnd);
-	while (lpTask != NULL) {
-		wptr = lpTask->lpWndList;
-		if (wptr != NULL) {
-			count = 0;
-			while (++count < MAXWIN_PER_TASK) {
-				dprintf_task(stddeb,"GetWindowTask // searching %04X %04X !\n",
-										lpTask->te.hTask, *(wptr));
-				if (*(wptr) == hWnd) {
-					dprintf_task(stddeb,"GetWindowTask(%04X) found hTask=%04X !\n", 
-												hWnd, lpTask->te.hTask);
-					return lpTask->te.hTask;
-					}
-				wptr++;
-				}
-			}
-		lpTask = lpTask->lpNextTask;
-		}
-	return 0;
+    HTASK *prevTask;
+    TDB *pTask;
+
+    prevTask = &hFirstTask;
+    while (*prevTask && (*prevTask != hTask))
+    {
+        pTask = (TDB *)GlobalLock( *prevTask );
+        prevTask = &pTask->hNext;
+    }
+    if (*prevTask)
+    {
+        pTask = (TDB *)GlobalLock( *prevTask );
+        *prevTask = pTask->hNext;
+        pTask->hNext = 0;
+        nTaskCount--;
+    }
 }
 
 
-/**********************************************************************
- *				EnumTaskWindows	[USER.225]
+/***********************************************************************
+ *           TASK_CreateThunks
+ *
+ * Create a thunk free-list in segment 'handle', starting from offset 'offset'
+ * and containing 'count' entries.
  */
-BOOL EnumTaskWindows(HANDLE hTask, FARPROC lpEnumFunc, LONG lParam)
+static void TASK_CreateThunks( HGLOBAL handle, WORD offset, WORD count )
 {
-	HWND 	*wptr, hWnd;
-	BOOL	bRet;
-	int		count = 0;
-	LPWINETASKENTRY lpTask = lpTaskList;
-	dprintf_task(stddeb,"EnumTaskWindows(%04X, %08X, %08X) !\n", hTask, 
-		(unsigned int) lpEnumFunc, (unsigned int) lParam);
-	while (TRUE) {
-		if (lpTask->te.hTask == hTask) break;
-		if (lpTask == NULL) {
-			dprintf_task(stddeb,"EnumTaskWindows // hTask=%04X not found !\n", hTask);
-			return FALSE;
-			}
-		lpTask = lpTask->lpNextTask;
-		}
-	dprintf_task(stddeb,"EnumTaskWindows // found hTask=%04X !\n", hTask);
-	wptr = lpTask->lpWndList;
-	if (wptr == NULL) return FALSE;
-	if (lpEnumFunc == NULL)	return FALSE;
-	while ((hWnd = *(wptr++)) != 0) {
-		if (++count >= MAXWIN_PER_TASK) return FALSE;
-		dprintf_task(stddeb,"EnumTaskWindows // hWnd=%04X count=%d !\n", hWnd, count);
-                bRet = CallEnumTaskWndProc( lpEnumFunc, hWnd, lParam );
-		if (bRet == 0) break;
-		}
-	return TRUE;
+    int i;
+    WORD free;
+    THUNKS *pThunk;
+
+    pThunk = (THUNKS *)((BYTE *)GlobalLock( handle ) + offset);
+    pThunk->next = 0;
+    pThunk->magic = THUNK_MAGIC;
+    pThunk->free = (int)&pThunk->thunks - (int)pThunk;
+    free = pThunk->free;
+    for (i = 0; i < count-1; i++)
+    {
+        free += 8;  /* Offset of next thunk */
+        pThunk->thunks[4*i] = free;
+    }
+    pThunk->thunks[4*i] = 0;  /* Last thunk */
 }
 
 
-/**********************************************************************
- *				CreateNewTask		[internal]
+/***********************************************************************
+ *           TASK_AllocThunk
+ *
+ * Allocate a thunk for MakeProcInstance().
  */
-HANDLE CreateNewTask(HINSTANCE hInst, HTASK hTaskParent)
+static SEGPTR TASK_AllocThunk( HTASK hTask )
 {
-	HANDLE hTask;
-	LPWINETASKENTRY lpTask = lpTaskList;
-	LPWINETASKENTRY lpNewTask;
-	MODULEENTRY module;
+    TDB *pTask;
+    THUNKS *pThunk;
+    WORD sel, base;
+    
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+    sel = pTask->hCSAlias;
+    pThunk = &pTask->thunks;
+    base = (int)pThunk - (int)pTask;
+    while (!pThunk->free)
+    {
+        sel = pThunk->next;
+        if (!sel)  /* Allocate a new segment */
+        {
+            sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
+                                pTask->hPDB, TRUE, FALSE, FALSE );
+            if (!sel) return (SEGPTR)0;
+            TASK_CreateThunks( sel, 0, MIN_THUNKS );
+            pThunk->next = sel;
+        }
+        pThunk = (THUNKS *)GlobalLock( sel );
+        base = 0;
+    }
+    base += pThunk->free;
+    pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
+    return MAKELONG( base, sel );
+}
 
-	module.dwSize = sizeof(module);
-	ModuleFindHandle(&module, hInst);
 
-	if (lpTask != NULL) {
-		while (TRUE) {
-			if (lpTask->lpNextTask == NULL) break;
-			lpTask = lpTask->lpNextTask;
-			}
-		}
-	hTask = GlobalAlloc(GMEM_MOVEABLE, sizeof(WINETASKENTRY));
-	lpNewTask = (LPWINETASKENTRY) GlobalLock(hTask);
-    	dprintf_task(stddeb,"CreateNewTask entry allocated %p\n", lpNewTask);
-	if (lpNewTask == NULL) return 0;
-	if (lpTaskList == NULL) {
-		lpTaskList = lpNewTask;
-		lpNewTask->lpPrevTask = NULL;
-		}
-	else {
-		lpTask->lpNextTask = lpNewTask;
-		lpTask->te.hNext = lpNewTask->te.hTask;
-		lpNewTask->lpPrevTask = lpTask;
-		}
-	lpNewTask->lpNextTask = NULL;
-	lpNewTask->hIcon = 0;
-	lpNewTask->te.dwSize = sizeof(TASKENTRY);
-	lpNewTask->te.hModule = 0;
-	lpNewTask->te.hInst = hInst;
-	lpNewTask->te.hTask = hTask;
-	lpNewTask->te.hTaskParent = hTaskParent;
-	lpNewTask->te.wSS = 0;
-	lpNewTask->te.wSP = 0;
-	lpNewTask->te.wStackTop = 0;
-	lpNewTask->te.wStackMinimum = 0;
-	lpNewTask->te.wStackBottom = 0;
-	lpNewTask->te.wcEvents = 0;
-	lpNewTask->te.hQueue = 0;
-	strcpy(lpNewTask->te.szModule, module.szModule);
-	lpNewTask->te.wPSPOffset = 0;
-	lpNewTask->unix_pid = getpid();
-	lpNewTask->lpWndList = (HWND *) malloc(MAXWIN_PER_TASK * sizeof(HWND));
-	if (lpNewTask->lpWndList != NULL) 
-		memset((LPSTR)lpNewTask->lpWndList, 0, MAXWIN_PER_TASK * sizeof(HWND));
-    	dprintf_task(stddeb,"CreateNewTask // unix_pid=%08X return hTask=%04X\n", 
-									lpNewTask->unix_pid, hTask);
-	GlobalUnlock(hTask);	
-	nTaskCount++;
+/***********************************************************************
+ *           TASK_FreeThunk
+ *
+ * Free a MakeProcInstance() thunk.
+ */
+static BOOL TASK_FreeThunk( HTASK hTask, SEGPTR thunk )
+{
+    TDB *pTask;
+    THUNKS *pThunk;
+    WORD sel, base;
+    
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+    sel = pTask->hCSAlias;
+    pThunk = &pTask->thunks;
+    base = (int)pThunk - (int)pTask;
+    while (sel && (sel != HIWORD(thunk)))
+    {
+        sel = pThunk->next;
+        pThunk = (THUNKS *)GlobalLock( sel );
+        base = 0;
+    }
+    if (!sel) return FALSE;
+    *(WORD *)((BYTE *)pThunk + LOWORD(thunk) - base) = pThunk->free;
+    pThunk->free = LOWORD(thunk) - base;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           TASK_CallToStart
+ *
+ * 32-bit entry point for a new task. This function is responsible for
+ * setting up the registers and jumping to the 16-bit entry point.
+ */
+static void TASK_CallToStart(void)
+{
+    int cs_reg, ds_reg, ip_reg;
+    TDB *pTask = (TDB *)GlobalLock( hCurrentTask );
+    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( pTask->hModule );
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+    extern unsigned short WIN_StackSize;
+
+    /* 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
+     */
+
+    WIN_StackSize = pModule->stack_size;
+
+    cs_reg = pSegTable[pModule->cs - 1].selector;
+    ip_reg = pModule->ip;
+    ds_reg = pSegTable[pModule->dgroup - 1].selector;
+    IF1632_Saved16_ss = pTask->ss;
+    IF1632_Saved16_sp = pTask->sp;
+/*    dprintf_task( stddeb, "Starting main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n",
+                 cs_reg, ip_reg, ds_reg,
+                 IF1632_Saved16_ss, IF1632_Saved16_sp);
+*/
+    CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                   pTask->hPDB /*es*/, 0 /*bp*/, 0 /*ax*/,
+                   WIN_StackSize /*bx*/, pModule->heap_size /*cx*/,
+                   0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
+    /* This should never return */
+    fprintf( stderr, "TASK_CallToStart: Main program returned!\n" );
+    exit(1);
+}
+
+
+/***********************************************************************
+ *           TASK_CreateTask
+ */
+HTASK TASK_CreateTask( HMODULE hModule, HANDLE hEnvironment,
+                       HTASK hTaskParent, char *cmdLine )
+{
+    HTASK hTask;
+    TDB *pTask;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegTable;
+    LPSTR name;
+    char *stack16Top, *stack32Top;
+    STACK16FRAME *frame16;
+    STACK32FRAME *frame32;
+    extern DWORD CALL16_RetAddr_word;
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    pSegTable = NE_SEG_TABLE( pModule );
+
+      /* Allocate the task structure */
+
+    hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
+                          hModule, FALSE, FALSE, FALSE );
+    if (!hTask) return 0;
+    pTask = (TDB *)GlobalLock( hTask );
+
+      /* Fill the task structure */
+
+    pTask->nEvents   = 1;  /* So the task can be started */
+    pTask->hSelf     = hTask;
+    pTask->flags     = 0;
+    pTask->version   = pModule->expected_version;
+    pTask->hInstance = NE_SEG_TABLE(pModule)[pModule->dgroup-1].selector,
+    pTask->hModule   = hModule;
+    pTask->hParent   = hTaskParent;
+    pTask->curdrive  = 'C' - 'A' + 0x80;
+    pTask->magic     = TDB_MAGIC;
+    strcpy( pTask->curdir, "WINDOWS" );
+
+      /* Create the thunks block */
+
+    TASK_CreateThunks( hTask, (int)&pTask->thunks - (int)pTask, 7 );
+
+      /* Copy the module name */
+
+    name = MODULE_GetModuleName( hModule );
+    strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
+
+      /* Fill the PDB */
+
+    pTask->pdb.int20 = 0x20cd;
+    pTask->pdb.dispatcher[0] = 0x9a;
+    *(DWORD *)&pTask->pdb.dispatcher[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 );  /* KERNEL.102 is DOS3Call() */
+    pTask->pdb.savedint22 = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"),
+                                    137 );  /* KERNEL.137 is FatalAppExit() */
+    pTask->pdb.savedint23 = pTask->pdb.savedint22;
+    pTask->pdb.savedint24 = pTask->pdb.savedint22;
+    pTask->pdb.environment = hEnvironment;
+    strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 );
+    pTask->pdb.cmdLine[127] = '\0';
+    pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 );
+
+      /* Get the compatibility flags */
+
+    pTask->compat_flags = GetProfileInt( name, "Compatibility", 0 );
+
+      /* Allocate a selector for the PDB */
+
+    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
+                                      hModule, FALSE, FALSE, FALSE );
+
+      /* Allocate a code segment alias for the TDB */
+
+    pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
+                                          sizeof(TDB), pTask->hPDB, TRUE,
+                                          FALSE, FALSE );
+
+      /* Set the owner of the environment block */
+
+    FarSetOwner( pTask->pdb.environment, pTask->hPDB );
+
+      /* Default DTA overwrites command-line */
+
+    pTask->dta = MAKELONG( (int)&pTask->pdb.cmdLine - (int)&pTask->pdb,
+                           pTask->hPDB );
+
+      /* Allocate the 32-bit stack */
+
+    pTask->hStack32 = GLOBAL_Alloc( GMEM_FIXED, STACK32_SIZE, pTask->hPDB,
+                                    FALSE, FALSE, FALSE );
+
+      /* Create the 32-bit stack frame */
+
+    stack32Top = (char*)GlobalLock(pTask->hStack32) + STACK32_SIZE;
+    frame32 = (STACK32FRAME *)stack32Top - 1;
+    frame32->saved_esp = (DWORD)stack32Top;
+    frame32->edi = 0;
+    frame32->esi = 0;
+    frame32->edx = 0;
+    frame32->ecx = 0;
+    frame32->ebx = 0;
+    frame32->ebp = 0;
+    frame32->retaddr = (DWORD)TASK_CallToStart;
+    frame32->codeselector = WINE_CODE_SELECTOR;
+    pTask->esp = (DWORD)frame32;
+
+      /* Create the 16-bit stack frame */
+
+    pTask->ss = pSegTable[pModule->ss - 1].selector;
+    pTask->sp = (pModule->sp != 0) ? pModule->sp :
+                pSegTable[pModule->ss-1].minsize + pModule->stack_size;
+    stack16Top = (char *)PTR_SEG_OFF_TO_LIN( pTask->ss, pTask->sp );
+    frame16 = (STACK16FRAME *)stack16Top - 1;
+    frame16->saved_ss = pTask->ss;
+    frame16->saved_sp = pTask->sp;
+    frame16->ds = pTask->hInstance;
+    frame16->entry_point = 0;
+    frame16->ordinal_number = 1;
+    frame16->dll_id = 1;
+    frame16->bp = 0;
+    frame16->ip = LOWORD( CALL16_RetAddr_word );
+    frame16->cs = HIWORD( CALL16_RetAddr_word );
+    pTask->sp -= sizeof(STACK16FRAME);
+
+      /* If there's no 16-bit stack yet, use a part of the new task stack */
+      /* This is only needed to have a stack to switch from on the first  */
+      /* call to DirectedYield(). */
+
+    if (!IF1632_Saved16_ss)
+    {
+        IF1632_Saved16_ss = pTask->ss;
+        IF1632_Saved16_sp = pTask->sp;
+    }
+
+      /* Add the task to the linked list */
+
+    TASK_LinkTask( hTask );
+
+    dprintf_task( stddeb, "CreateTask: module='%s' cmdline='%s' task=%04x\n",
+                  name, cmdLine, hTask );
+
     return hTask;
 }
 
 
-/**********************************************************************
- *				AddWindowToTask		[internal]
+/***********************************************************************
+ *           TASK_DeleteTask
  */
-BOOL AddWindowToTask(HTASK hTask, HWND hWnd)
+void TASK_DeleteTask( HTASK hTask )
 {
-	HWND 	*wptr;
-	int		count = 0;
-	LPWINETASKENTRY lpTask = lpTaskList;
-	dprintf_task(stddeb,"AddWindowToTask(%04X, %04X); !\n", hTask, hWnd);
-	while (TRUE) {
-		if (lpTask->te.hTask == hTask) break;
-		if (lpTask == NULL) {
-			fprintf(stderr,"AddWindowToTask // hTask=%04X not found !\n", hTask);
-			return FALSE;
-			}
-		lpTask = lpTask->lpNextTask;
-		}
-	wptr = lpTask->lpWndList;
-	if (wptr == NULL) return FALSE;
-	while (*(wptr) != 0) {
-		if (++count >= MAXWIN_PER_TASK) return FALSE;
-		wptr++;
-		}
-	*wptr = hWnd;
-	dprintf_task(stddeb,"AddWindowToTask // window added, count=%d !\n", count);
-	return TRUE;
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+
+      /* Free all memory used by this task (including the 32-bit stack, */
+      /* the environment block and the thunk segments). */
+
+    GlobalFreeAll( pTask->hPDB );
+
+      /* Free the selector aliases */
+
+    GLOBAL_FreeBlock( pTask->hCSAlias );
+    GLOBAL_FreeBlock( pTask->hPDB );
+
+    GlobalFree( hTask );  /* Free the task structure */
+}
+
+
+/***********************************************************************
+ *           TASK_KillCurrentTask
+ *
+ * Kill the currently running task. As it's not possible to kill the
+ * current task like this, it is simply marked for destruction, and will
+ * be killed when either TASK_Reschedule or this function is called again 
+ * in the context of another task.
+ */
+void TASK_KillCurrentTask( int exitCode )
+{
+    if (hTaskToKill && (hTaskToKill != hCurrentTask))
+    {
+        /* If another task is already marked for destruction, */
+        /* we call kill it now, as we are in another context. */
+        TASK_DeleteTask( hTaskToKill );
+    }
+
+    if (nTaskCount <= 1)
+    {
+        dprintf_task( stddeb, "Killing the last task, exiting\n" );
+        exit(0);
+    }
+
+    /* Remove the task from the list to be sure we never switch back to it */
+    TASK_UnlinkTask( hCurrentTask );
+    
+    hTaskToKill = hCurrentTask;
+    Yield();
+    /* We never return from Yield() */
+}
+
+
+/***********************************************************************
+ *           TASK_Reschedule
+ *
+ * This is where all the magic of task-switching happens!
+ *
+ * This function should only be called via the TASK_SCHEDULE() macro, to make
+ * sure that all the context is saved correctly.
+ */
+void TASK_Reschedule(void)
+{
+    TDB *pOldTask = NULL, *pNewTask;
+    HTASK hTask = 0;
+
+      /* First check if there's a task to kill */
+
+    if (hTaskToKill && (hTaskToKill != hCurrentTask))
+        TASK_DeleteTask( hTaskToKill );
+
+      /* Find a task to yield to */
+
+    pOldTask = (TDB *)GlobalLock( hCurrentTask );
+    if (pOldTask && pOldTask->hYieldTo)
+    {
+        /* If a task is stored in hYieldTo of the current task (put there */
+        /* by DirectedYield), yield to it only if it has events pending.  */
+        hTask = pOldTask->hYieldTo;
+        if (!(pNewTask = (TDB *)GlobalLock( hTask )) || !pNewTask->nEvents)
+            hTask = 0;
+    }
+
+    if (!hTask)
+    {
+        hTask = hFirstTask;
+        while (hTask)
+        {
+            pNewTask = (TDB *)GlobalLock( hTask );
+            if (pNewTask->nEvents && (hTask != hCurrentTask)) break;
+            hTask = pNewTask->hNext;
+        }
+    }
+
+     /* If there's a task to kill, switch to any other task, */
+     /* even if it doesn't have events pending. */
+
+    if (!hTask && hTaskToKill) hTask = hFirstTask;
+
+    if (!hTask) return;  /* Do nothing */
+
+    pNewTask = (TDB *)GlobalLock( hTask );
+    dprintf_task( stddeb, "Switching to task %04x (%.8s)\n",
+                  hTask, pNewTask->module_name );
+
+      /* Save the stacks of the previous task (if any) */
+
+    if (pOldTask)
+    {
+        pOldTask->ss  = IF1632_Saved16_ss;
+        pOldTask->sp  = IF1632_Saved16_sp;
+        pOldTask->esp = IF1632_Saved32_esp;
+    }
+
+     /* Make the task the last in the linked list (round-robin scheduling) */
+
+    pNewTask->priority++;
+    TASK_UnlinkTask( hTask );
+    TASK_LinkTask( hTask );
+    pNewTask->priority--;
+
+      /* Switch to the new stack */
+
+    hCurrentTask = hTask;
+    IF1632_Saved16_ss  = pNewTask->ss;
+    IF1632_Saved16_sp  = pNewTask->sp;
+    IF1632_Saved32_esp = pNewTask->esp;
+}
+
+
+/***********************************************************************
+ *           WaitEvent  (KERNEL.30)
+ */
+BOOL WaitEvent( HTASK hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = hCurrentTask;
+    pTask = (TDB *)GlobalLock( hTask );
+    if (pTask->nEvents > 0)
+    {
+        pTask->nEvents--;
+        return FALSE;
+    }
+    TASK_SCHEDULE();
+    /* When we get back here, we have an event */
+    pTask->nEvents--;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PostEvent  (KERNEL.31)
+ */
+void PostEvent( HTASK hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = hCurrentTask;
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+    pTask->nEvents++;
+}
+
+
+/***********************************************************************
+ *           SetPriority  (KERNEL.32)
+ */
+void SetPriority( HTASK hTask, int delta )
+{
+    TDB *pTask;
+    int newpriority;
+
+    if (!hTask) hTask = hCurrentTask;
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return;
+    newpriority = pTask->priority + delta;
+    if (newpriority < -32) newpriority = -32;
+    else if (newpriority > 15) newpriority = 15;
+
+    pTask->priority = newpriority + 1;
+    TASK_UnlinkTask( hTask );
+    TASK_LinkTask( hTask );
+    pTask->priority--;
+}
+
+
+/***********************************************************************
+ *           OldYield  (KERNEL.117)
+ */
+void OldYield(void)
+{
+    TDB *pCurTask;
+
+    pCurTask = (TDB *)GlobalLock( hCurrentTask );
+    if (pCurTask) pCurTask->nEvents++;  /* Make sure we get back here */
+    TASK_SCHEDULE();
+    if (pCurTask) pCurTask->nEvents--;
+}
+
+
+/***********************************************************************
+ *           DirectedYield  (KERNEL.150)
+ */
+void DirectedYield( HTASK hTask )
+{
+    TDB *pCurTask;
+
+    if ((pCurTask = (TDB *)GlobalLock( hCurrentTask )) != NULL)
+        pCurTask->hYieldTo = hTask;
+
+    OldYield();
+}
+
+
+/***********************************************************************
+ *           Yield  (KERNEL.29)
+ */
+void Yield(void)
+{
+    DirectedYield( 0 );
+}
+
+
+/***********************************************************************
+ *           MakeProcInstance  (KERNEL.51)
+ */
+FARPROC MakeProcInstance( FARPROC func, HANDLE hInstance )
+{
+    BYTE *thunk;
+    SEGPTR thunkaddr;
+    
+    thunkaddr = TASK_AllocThunk( hCurrentTask );
+    if (!thunkaddr) return (FARPROC)0;
+    thunk = PTR_SEG_TO_LIN( thunkaddr );
+
+    dprintf_task( stddeb, "MakeProcInstance(%08lx,%04x): got thunk %08lx\n",
+                  (SEGPTR)func, hInstance, (SEGPTR)thunkaddr );
+    
+    *thunk++ = 0xb8;    /* movw instance, %ax */
+    *thunk++ = (BYTE)(hInstance & 0xff);
+    *thunk++ = (BYTE)(hInstance >> 8);
+    *thunk++ = 0xea;    /* ljmp func */
+    *(DWORD *)thunk = (DWORD)func;
+    return (FARPROC)thunkaddr;
+}
+
+
+/***********************************************************************
+ *           FreeProcInstance  (KERNEL.52)
+ */
+void FreeProcInstance( FARPROC func )
+{
+    dprintf_task( stddeb, "FreeProcInstance(%08lx)\n", (SEGPTR)func );
+    TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
 }
 
 
 /**********************************************************************
- *				RemoveWindowFromTask		[internal]
+ *	    GetCodeHandle    (KERNEL.93)
  */
-BOOL RemoveWindowFromTask(HTASK hTask, HWND hWnd)
+HANDLE GetCodeHandle( FARPROC proc )
 {
-	HWND 	*wptr;
-	int		count = 0;
-	LPWINETASKENTRY lpTask = lpTaskList;
-	dprintf_task(stddeb,"RemoveWindowFromTask (%04X, %04X); !\n", hTask, hWnd);
-	while (TRUE) {
-		if (lpTask->te.hTask == hTask) break;
-		if (lpTask == NULL) {
-			fprintf(stderr,"RemoveWindowFromTask // hTask=%04X not found !\n", hTask);
-			return FALSE;
-			}
-		lpTask = lpTask->lpNextTask;
-		}
-	wptr = lpTask->lpWndList;
-	if (wptr == NULL) return FALSE;
-	while (*(wptr) != hWnd) {
-		if (++count >= MAXWIN_PER_TASK) return FALSE;
-		wptr++;
-		}
-	while (*(wptr) != 0) {
-		*(wptr) = *(wptr + 1);
-		if (++count >= MAXWIN_PER_TASK) return FALSE;
-		wptr++;
-		}
-	dprintf_task(stddeb,"RemoveWindowFromTask // window removed, count=%d !\n", --count);
-	return TRUE;
+    HANDLE handle;
+    BYTE *thunk = (BYTE *)PTR_SEG_TO_LIN( proc );
+
+    /* Return the code segment containing 'proc'. */
+    /* Not sure if this is really correct (shouldn't matter that much). */
+
+    /* Check if it is really a thunk */
+    if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
+        handle = GlobalHandle( thunk[6] + (thunk[7] << 8) );
+    else
+        handle = GlobalHandle( HIWORD(proc) );
+
+    printf( "STUB: GetCodeHandle(%p) returning %04x\n", proc, handle );
+    return handle;
 }
 
-BOOL TaskFirst(LPTASKENTRY lpTask)
+
+/***********************************************************************
+ *           SetTaskQueue  (KERNEL.34)
+ */
+HGLOBAL SetTaskQueue( HANDLE hTask, HGLOBAL hQueue )
 {
-	dprintf_task(stddeb,"TaskFirst(%8x)\n", (int) lpTask);
-	if (lpTaskList) {
-		memcpy(lpTask, &lpTaskList->te, lpTask->dwSize);
-		return TRUE;
-	} else
-		return FALSE;
+    HGLOBAL hPrev;
+    TDB *pTask;
+
+    if (!hTask) hTask = hCurrentTask;
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+    hPrev = pTask->hQueue;
+    pTask->hQueue = hQueue;
+    return hPrev;
 }
 
-BOOL TaskNext(LPTASKENTRY lpTask)
+
+/***********************************************************************
+ *           GetTaskQueue  (KERNEL.35)
+ */
+HGLOBAL GetTaskQueue( HANDLE hTask )
 {
-	LPWINETASKENTRY list;
-	dprintf_task(stddeb,"TaskNext(%8x)\n", (int) lpTask);
-	list = lpTaskList;
-	while (list) {
-		if (list->te.hTask == lpTask->hTask) {
-			list = list->lpNextTask;
-			if (list) {
-				memcpy(lpTask, &list->te, lpTask->dwSize);
-				return TRUE;
-			} else
-				return FALSE;
-		}
-		list = list->lpNextTask;
-	}
-	return FALSE;
+    TDB *pTask;
+
+    if (!hTask) hTask = hCurrentTask;
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return 0;
+    return pTask->hQueue;
 }
 
-BOOL TaskFindHandle(LPTASKENTRY lpTask, HTASK hTask)
+
+/***********************************************************************
+ *           GetCurrentTask   (KERNEL.36)
+ */
+HTASK GetCurrentTask(void)
 {
-	static LPWINETASKENTRY list;
-	dprintf_task(stddeb,"TaskFindHandle(%8x,%4x)\n", (int) lpTask, hTask);
-	list = lpTaskList;
-	while (list) {
-		if (list->te.hTask == hTask) {
-			list = list->lpNextTask;
-			if (list) {
-				memcpy(lpTask, &list->te, lpTask->dwSize);
-				return TRUE;
-			} else
-				return FALSE;
-		}
-		list = list->lpNextTask;
-	}
-	return FALSE;
+      /* Undocumented: first task is returned in high word */
+    return MAKELONG( hCurrentTask, hFirstTask );
+}
+
+
+/***********************************************************************
+ *           GetCurrentPDB   (KERNEL.37)
+ */
+WORD GetCurrentPDB(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0;
+    return pTask->hPDB;
+}
+
+
+/***********************************************************************
+ *           GetNumTasks   (KERNEL.152)
+ */
+WORD GetNumTasks(void)
+{
+    return nTaskCount;
+}
+
+
+/***********************************************************************
+ *           GetTaskDS   (KERNEL.155)
+ */
+WORD GetTaskDS(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return 0;
+    return pTask->hInstance;
+}
+
+
+/***********************************************************************
+ *           IsTask   (KERNEL.320)
+ */
+BOOL IsTask( HTASK hTask )
+{
+    TDB *pTask;
+
+    if (!(pTask = (TDB *)GlobalLock( hTask ))) return FALSE;
+    if (GlobalSize( hTask ) < sizeof(TDB)) return FALSE;
+    return (pTask->magic == TDB_MAGIC);
+}
+
+
+/***********************************************************************
+ *           GetExePtr   (KERNEL.133)
+ */
+HMODULE GetExePtr( HANDLE handle )
+{
+    char *ptr;
+    HTASK hTask;
+    HANDLE owner;
+
+      /* Check for module handle */
+
+    if (!(ptr = GlobalLock( handle ))) return 0;
+    if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return handle;
+
+      /* Check the owner for module handle */
+
+    owner = FarGetOwner( handle );
+    if (!(ptr = GlobalLock( owner ))) return 0;
+    if (((NE_MODULE *)ptr)->magic == NE_SIGNATURE) return owner;
+
+      /* Search for this handle and its owner inside all tasks */
+
+    hTask = hFirstTask;
+    while (hTask)
+    {
+        TDB *pTask = (TDB *)GlobalLock( hTask );
+        if ((hTask == handle) ||
+            (pTask->hInstance == handle) ||
+            (pTask->hQueue == handle) ||
+            (pTask->hPDB == handle)) return pTask->hModule;
+        if ((hTask == owner) ||
+            (pTask->hInstance == owner) ||
+            (pTask->hQueue == owner) ||
+            (pTask->hPDB == owner)) return pTask->hModule;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           TaskFirst   (TOOLHELP.63)
+ */
+BOOL TaskFirst( TASKENTRY *lpte )
+{
+    lpte->hNext = hFirstTask;
+    return TaskNext( lpte );
+}
+
+
+/***********************************************************************
+ *           TaskNext   (TOOLHELP.64)
+ */
+BOOL TaskNext( TASKENTRY *lpte )
+{
+    TDB *pTask;
+    INSTANCEDATA *pInstData;
+
+    dprintf_toolhelp( stddeb, "TaskNext(%p): task=%04x\n", lpte, lpte->hNext );
+    if (!lpte->hNext) return FALSE;
+    pTask = (TDB *)GlobalLock( lpte->hNext );
+    if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
+    pInstData = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( pTask->hInstance, 0 );
+    lpte->hTask         = lpte->hNext;
+    lpte->hTaskParent   = pTask->hParent;
+    lpte->hInst         = pTask->hInstance;
+    lpte->hModule       = pTask->hModule;
+    lpte->wSS           = pTask->ss;
+    lpte->wSP           = pTask->sp;
+    lpte->wStackTop     = pInstData->stacktop;
+    lpte->wStackMinimum = pInstData->stackmin;
+    lpte->wStackBottom  = pInstData->stackbottom;
+    lpte->wcEvents      = pTask->nEvents;
+    lpte->hQueue        = pTask->hQueue;
+    strncpy( lpte->szModule, pTask->module_name, 8 );
+    lpte->szModule[8]   = '\0';
+    lpte->wPSPOffset    = 0x100;  /*??*/
+    lpte->hNext         = pTask->hNext;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           TaskFindHandle   (TOOLHELP.65)
+ */
+BOOL TaskFindHandle( TASKENTRY *lpte, HTASK hTask )
+{
+    lpte->hNext = hTask;
+    return TaskNext( lpte );
 }
diff --git a/memory/global.c b/memory/global.c
index 2067ad0..32a19f0 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -59,42 +59,26 @@
 
 
 /***********************************************************************
- *           GLOBAL_Alloc
+ *           GLOBAL_CreateBlock
  *
- * Implementation of GlobalAlloc()
+ * Create a global heap block for a fixed range of linear memory.
  */
-HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
-                      BOOL isCode, BOOL isReadOnly )
+HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
+                            HGLOBAL hOwner, BOOL isCode,
+                            BOOL is32Bit, BOOL isReadOnly  )
 {
     WORD sel, selcount;
-    void *ptr;
     GLOBALARENA *pArena;
 
-      /* Fixup the size */
-
-    if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
-    if (size == 0) size = 0x10;
-    else size = (size + 0x0f) & ~0x0f;
-
-      /* Allocate the linear memory */
-
-    ptr = malloc( size );
-    if (!ptr) return 0;
-
       /* Allocate the selector(s) */
 
     sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
-                               0, isReadOnly );
-    if (!sel)
-    {
-        free( ptr );
-        return 0;
-    }
+                               is32Bit, isReadOnly );
+    if (!sel) return 0;
     selcount = (size + 0xffff) / 0x10000;
 
     if (!(pArena = GLOBAL_GetArena( sel, selcount )))
     {
-        free( ptr );
         FreeSelector( sel );
         return 0;
     }
@@ -114,19 +98,78 @@
     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;
 }
 
 
 /***********************************************************************
+ *           GLOBAL_FreeBlock
+ *
+ * Free a block allocated by GLOBAL_CreateBlock, without touching
+ * the associated linear memory range.
+ */
+BOOL GLOBAL_FreeBlock( HGLOBAL handle )
+{
+    WORD sel;
+
+    if (!handle) return TRUE;
+    sel = GlobalHandleToSel( handle );
+    if (FreeSelector( sel )) return FALSE;  /* failed */
+    memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GLOBAL_Alloc
+ *
+ * Implementation of GlobalAlloc()
+ */
+HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
+                      BOOL isCode, BOOL is32Bit, BOOL isReadOnly )
+{
+    void *ptr;
+    HGLOBAL handle;
+
+    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+
+      /* Fixup the size */
+
+    if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
+    if (size == 0) size = 0x20;
+    else size = (size + 0x1f) & ~0x1f;
+
+      /* Allocate the linear memory */
+
+    ptr = malloc( size );
+    if (!ptr) return 0;
+
+      /* Allocate the selector(s) */
+
+    handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
+                                 isCode, is32Bit, isReadOnly);
+    if (!handle)
+    {
+        free( ptr );
+        return 0;
+    }
+
+    if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
+    return handle;
+}
+
+
+/***********************************************************************
  *           GlobalAlloc   (KERNEL.15)
  */
 HGLOBAL GlobalAlloc( WORD flags, DWORD size )
 {
-    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+    HANDLE owner = GetCurrentPDB();
 
-    return GLOBAL_Alloc( flags, size, GetCurrentPDB(), 0, 0 );
+    if (flags & GMEM_DDESHARE)
+        owner = GetExePtr(owner);  /* Make it a module handle */
+
+    return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
 }
 
 
@@ -142,11 +185,8 @@
 
     dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
                     handle, size, flags );
-    if (!handle)
-    {
-        printf( "GlobalReAlloc: handle is 0.\n" );
-        return 0;
-    }
+    if (!handle) return 0;
+    pArena = GET_ARENA_PTR( handle );
 
       /* Fixup the size */
 
@@ -154,12 +194,23 @@
     if (size == 0) size = 0x10;
     else size = (size + 0x0f) & ~0x0f;
 
+      /* Change the flags */
+
+    if (flags & GMEM_MODIFY)
+    {
+          /* Change the flags, leaving GA_DGROUP alone */
+        pArena->flags = (pArena->flags & GA_DGROUP) |
+                           (flags & ~GA_DGROUP);
+        if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
+        return handle;
+    }
+
       /* Reallocate the linear memory */
 
-    pArena = GET_ARENA_PTR( handle );
     sel = GlobalHandleToSel( handle );
     ptr = (void *)pArena->base;
     oldsize = pArena->size;
+    dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
     if (size == oldsize) return handle;  /* Nothing to do */
 
     ptr = realloc( ptr, size );
@@ -194,13 +245,6 @@
     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 */
@@ -217,16 +261,12 @@
  */
 HGLOBAL GlobalFree( HGLOBAL handle )
 {
-    WORD sel;
     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 */
+    if (!(ptr = GlobalLock( handle ))) return handle;  /* failed */
+    if (!GLOBAL_FreeBlock( handle )) return handle;  /* failed */
     free( ptr );
-    memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
     return 0;
 }
 
@@ -238,7 +278,8 @@
  */
 SEGPTR WIN16_GlobalLock( HGLOBAL handle )
 {
-    dprintf_global( stddeb, "WIN16_GlobalLock: %04x\n", handle );
+    dprintf_global( stddeb, "WIN16_GlobalLock(%04x) -> %08lx\n",
+                    handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
     if (!handle) return 0;
     return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
 }
@@ -336,6 +377,23 @@
 
 
 /***********************************************************************
+ *           GlobalFreeAll   (KERNEL.26)
+ */
+void GlobalFreeAll( HANDLE owner )
+{
+    DWORD i;
+    GLOBALARENA *pArena;
+
+    pArena = pGlobalArena;
+    for (i = 0; i < globalArenaSize; i++, pArena++)
+    {
+        if ((pArena->size != 0) && (pArena->hOwner == owner))
+            GlobalFree( pArena->handle );
+    }
+}
+
+
+/***********************************************************************
  *           GlobalWire   (KERNEL.111)
  */
 SEGPTR GlobalWire( HGLOBAL handle )
@@ -506,6 +564,7 @@
 {
     GLOBALARENA *pArena;
 
+    if (pGlobal->dwNext >= globalArenaSize) return FALSE;
     pArena = pGlobalArena + pGlobal->dwNext;
     if (wFlags == GLOBAL_FREE)  /* only free blocks */
     {
diff --git a/memory/local.c b/memory/local.c
index 8c9a829..c7d5231 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -377,7 +377,7 @@
       /* Find a suitable free block */
 
     if (!(pInfo = LOCAL_GetHeap( ds ))) {
-	  LOCAL_PrintHeap(ds);
+      LOCAL_PrintHeap(ds);
       return 0;
     }
     size += ARENA_HEADER_SIZE;
@@ -388,7 +388,7 @@
     {
         if (arena == pArena->free_next) {
 	  LOCAL_PrintHeap(ds);
-	   return 0;  /* not found */
+          return 0;  /* not found */
 	}
         arena = pArena->free_next;
         pArena = ARENA_PTR( ptr, arena );
@@ -428,6 +428,10 @@
     if (!(pInfo = LOCAL_GetHeap( ds ))) return 0;
     arena = handle - ARENA_HEADER_SIZE;
     pArena = ARENA_PTR( ptr, arena );
+    if (flags & LMEM_MODIFY) {
+      dprintf_local( stddeb, "LMEM_MODIFY set\n");
+      return handle;
+    }
     if (!size) size = 1;
     size = LALIGN( size );
 
diff --git a/misc/Imakefile b/misc/Imakefile
index c2b1811..5c32ba5 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -16,12 +16,12 @@
 	keyboard.c \
 	lstr.c \
 	main.c \
+	ole2nls.c \
 	olecli.c \
 	olesvr.c \
 	message.c \
 	network.c \
 	profile.c \
-	property.c \
 	rect.c \
 	shell.c \
 	sound.c \
diff --git a/misc/comm.c b/misc/comm.c
index 49c08ce..4da7e7e 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -29,7 +29,7 @@
 struct DosDeviceStruct COM[MAX_PORTS];
 struct DosDeviceStruct LPT[MAX_PORTS];
 
-void Comm_Init(void)
+void COMM_Init(void)
 {
 	int x;
 	char option[10], temp[256], *btemp;
@@ -90,24 +90,6 @@
 	}
 }
 
-void Comm_DeInit(void)
-{
-	int x;
-
-	for (x=0; x!=MAX_PORTS; x++) {
-
-		if (COM[x].devicename) {
-			if (COM[x].fd)
-	    			close(COM[x].fd);
-	        	free(COM[x].devicename);
-	    	}
-		if (LPT[x].devicename) {
-			if (LPT[x].fd)
-		    		close(LPT[x].fd);
-			free(LPT[x].devicename);
-		}
-	}
-}
 
 struct DosDeviceStruct *GetDeviceStruct(int fd)
 {
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 31ad412..356835f 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -4,11 +4,6 @@
  * Copyright 1994 Martin Ayotte
  */
 
-/*
-#define DEBUG_OPENDLG
-#define DEBUG_OPENDLG_DRAW
-*/
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -37,11 +32,6 @@
 char *DOS_GetCurrentDir(int drive);
 int DOS_ChangeDir(int drive, char *dirname);
 
-BOOL FileDlg_Init(HWND hWnd, DWORD lParam);
-BOOL OpenDlg_ScanFiles(HWND hWnd, WORD nDrive, LPSTR newPath, LPSTR fileSpec);
-BOOL OpenDlg_ScanDir(HWND hWnd, WORD nDrive, LPSTR newPath, LPSTR fileSpec);
-LPSTR OpenDlg_GetFileType(LPCSTR types, WORD index);
-LPSTR OpenDlg_ExtractCurDir(LPSTR FullPath, short MaxLen);
 BOOL FileOpenDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
 BOOL FileSaveDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
 BOOL ColorDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
@@ -51,524 +41,67 @@
 BOOL FindTextDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
 
 /***********************************************************************
- * 				GetOpenFileName			[COMMDLG.1]
+ * COMMDLG_IsPathName [internal]
  */
-BOOL GetOpenFileName(LPOPENFILENAME lpofn)
+
+static BOOL COMMDLG_IsPathName(LPSTR str)
 {
-	HANDLE		hDlgTmpl;
-	HANDLE		hResInfo;
-	HINSTANCE	hInst;
-	WND 		*wndPtr;
-	BOOL		bRet;
-	printf("GetOpenFileName(%p); !\n", lpofn);
-	if (lpofn == NULL) return FALSE;
-	printf("GetOpenFileName // Flags=%08lX !\n", lpofn->Flags);
-	printf("GetOpenFileName // nMaxFile=%ld lpstrFile='%s' !\n", 
-						lpofn->nMaxFile, PTR_SEG_TO_LIN(lpofn->lpstrFile));
-	printf("GetOpenFileName // lpstrInitialDir='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
-	printf("GetOpenFileName // lpstrFilter=%p !\n", lpofn->lpstrFilter);
-	printf("GetOpenFileName // nFilterIndex=%ld !\n", lpofn->nFilterIndex);
-	if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
-		hDlgTmpl = lpofn->hInstance;
-		}
-	else {
-		if (lpofn->Flags & OFN_ENABLETEMPLATE) {
-			printf("GetOpenFileName // avant FindResource hInstance=%04X lpTemplateName='%s' !\n", 
-								lpofn->hInstance, PTR_SEG_TO_LIN(lpofn->lpTemplateName));
-			hInst = lpofn->hInstance;
-			hResInfo = FindResource(hInst, 
-				(LPSTR)lpofn->lpTemplateName, RT_DIALOG);
-			}
-		else {
-			printf("GetOpenFileName // avant FindResource hSysRes=%04X !\n", hSysRes);
-			hInst = hSysRes;
-			hResInfo = FindResource(hInst, MAKEINTRESOURCE(OPENFILEDLG2), RT_DIALOG);
-			}
-		if (hResInfo == 0) {
-			CommDlgLastError = CDERR_FINDRESFAILURE;
-			return FALSE;
-			}
-		printf("GetOpenFileName // apres FindResource hResInfo=%04X!\n", hResInfo);
-		hDlgTmpl = LoadResource(hInst, hResInfo);
-		}
-	if (hDlgTmpl == 0) {
-		CommDlgLastError = CDERR_LOADRESFAILURE;
-		return FALSE;
-		}
-	printf("GetOpenFileName // apres LoadResource hDlgTmpl=%04X!\n", hDlgTmpl);
-    wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
-	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, GetWndProcEntry16("FileOpenDlgProc"), 
-	        (DWORD)lpofn); 
-
-/*	strcpy(lpofn->lpstrFile, "SETUP.TXT"); */
-/*	strcpy(lpofn->lpstrFileTitle, "SETUP.TXT");*/
-/*
-	lpofn->nFileOffset = 0;
-	lpofn->nFileExtension = strlen(lpofn->lpstrFile) - 3;
-	bRet = TRUE;
-*/
-	printf("GetOpenFileName // return lpstrFile='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrFile));
-	return bRet;
+  if (str[strlen(str)-1] == ':' && strlen(str) == 2) return TRUE;
+  if (str[strlen(str)-1] == '\\') return TRUE;
+  if (strchr(str,'*') != NULL) return TRUE;
+  return FALSE;
 }
 
-
-/***********************************************************************
- * 				GetSaveFileName			[COMMDLG.2]
- */
-BOOL GetSaveFileName(LPOPENFILENAME lpofn)
-{
-	HANDLE		hDlgTmpl;
-	HANDLE		hResInfo;
-	HINSTANCE	hInst;
-    WND 		*wndPtr;
-	BOOL		bRet;
-	printf("GetSaveFileName(%p); !\n", lpofn);
-	if (lpofn == NULL) return FALSE;
-	printf("GetSaveFileName // Flags=%08lX !\n", lpofn->Flags);
-	printf("GetSaveFileName // nMaxFile=%ld lpstrFile='%s' !\n", 
-						lpofn->nMaxFile, PTR_SEG_TO_LIN(lpofn->lpstrFile));
-	printf("GetSaveFileName // lpstrInitialDir='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
-	printf("GetSaveFileName // lpstrFilter=%p !\n", lpofn->lpstrFilter);
-	if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
-		hDlgTmpl = lpofn->hInstance;
-		}
-	else {
-		if (lpofn->Flags & OFN_ENABLETEMPLATE) {
-			printf("GetSaveFileName // avant FindResource lpTemplateName='%s' !\n", 
-                               PTR_SEG_TO_LIN(lpofn->lpTemplateName));
-			hInst = lpofn->hInstance;
-			hResInfo = FindResource(hInst, 
-				(LPSTR)lpofn->lpTemplateName, RT_DIALOG);
-			}
-		else {
-			printf("GetSaveFileName // avant FindResource !\n");
-			hInst = hSysRes;
-			hResInfo = FindResource(hInst, MAKEINTRESOURCE(SAVEFILEDLG2), RT_DIALOG);
-			}
-		if (hResInfo == 0) {
-			CommDlgLastError = CDERR_FINDRESFAILURE;
-			return FALSE;
-			}
-		hDlgTmpl = LoadResource(hInst, hResInfo);
-		}
-	if (hDlgTmpl == 0) {
-		CommDlgLastError = CDERR_LOADRESFAILURE;
-		return FALSE;
-		}
-    wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
-	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, GetWndProcEntry16("FileSaveDlgProc"), 
-		(DWORD)lpofn);
-	printf("GetSaveFileName // return lpstrFile='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrFile));
-	return bRet;
-}
-
-
-/***********************************************************************
- * 				ChooseColor				[COMMDLG.5]
- */
-BOOL ChooseColor(LPCHOOSECOLOR lpChCol)
-{
-	HANDLE	hDlgTmpl;
-	HANDLE	hResInfo;
-    WND 	*wndPtr;
-	BOOL	bRet;
-	hResInfo = FindResource(hSysRes, MAKEINTRESOURCE(COLORDLG), RT_DIALOG);
-	hDlgTmpl = LoadResource(hSysRes, hResInfo);
-    wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
-	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpChCol->hwndOwner, GetWndProcEntry16("ColorDlgProc"), 
-		(DWORD)lpChCol);
-	return bRet;
-}
-
-
-/***********************************************************************
- * 				FileOpenDlgProc			[COMMDLG.6]
- */
-BOOL FileOpenDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
-{
-	int		n;
-	LPSTR	ptr;
-	LPSTR	fspec;
-	char	str[512];
-	char	C2[128];
-	WORD	wRet;
-	HBRUSH	hBrush;
-	HDC 	hMemDC;
-	HBITMAP	hBitmap;
-	BITMAP	bm;
-	LPMEASUREITEMSTRUCT lpmeasure;
-	LPDRAWITEMSTRUCT lpdis;
-	static	int		nDrive;
-	static 	char	CurPath[512];
-	static LPOPENFILENAME lpofn;
-
-	switch (wMsg) {
-		case WM_INITDIALOG:
-#ifdef DEBUG_OPENDLG
-			printf("FileOpenDlgProc // WM_INITDIALOG lParam=%08X\n", lParam);
-#endif
-			printf("FileOpenDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
-			if (!FileDlg_Init(hWnd, lParam)) return TRUE;
-			SendDlgItemMessage(hWnd, cmb1, CB_RESETCONTENT, 0, 0L);
-			lpofn = (LPOPENFILENAME)lParam;
-			ptr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
-			strcpy(CurPath, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
-#ifdef DEBUG_OPENDLG
-			printf("FileOpenDlgProc // lpstrInitialDir='%s' !\n", CurPath);
-#endif
-			while((n = strlen(ptr)) != 0) {
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // file type '%s' !\n", ptr);
-#endif
-				SendDlgItemMessage(hWnd, cmb1, CB_ADDSTRING, 0, (DWORD)ptr);
-				ptr += ++n;
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // file spec '%s' !\n", ptr);
-#endif
-				n = strlen(ptr);
-				ptr += ++n;
-				}
-			SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (DWORD)str);
-			SendDlgItemMessage(hWnd, cmb1, CB_SETCURSEL, 
-						lpofn->nFilterIndex - 1, 0L);
-			DlgDirListComboBox(hWnd, "", cmb2, 0, 0xC000);
-			nDrive = 2; 		/* Drive 'C:' */
-			SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, nDrive, 0L);
-			sprintf(str, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-			fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), 
-									lpofn->nFilterIndex);
-#ifdef DEBUG_OPENDLG
-			printf("FileOpenDlgProc // WM_INITDIALOG fspec #%d = '%s' !\n", 
-											lpofn->nFilterIndex, fspec);
-#endif
-			if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-				printf("OpenDlg_ScanDir // ChangeDir Error !\n");
-				}
-			else {
-				strcpy(CurPath, str);
-				}
-			ShowWindow(hWnd, SW_SHOWNORMAL);
-			return TRUE;
-
-	case WM_SHOWWINDOW:
-		if (wParam == 0) break;
-		if (!(lpofn->Flags & OFN_SHOWHELP)) {
-			ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
-			}
-		if (lpofn->Flags & OFN_HIDEREADONLY) {
-			ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
-			}
-		return TRUE;
-
-    case WM_MEASUREITEM:
-		GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
-		lpmeasure = (LPMEASUREITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
-		lpmeasure->itemHeight = bm.bmHeight;
-#ifdef DEBUG_OPENDLG_DRAW
-		printf("FileOpenDlgProc WM_MEASUREITEM Height=%d !\n", bm.bmHeight);
-#endif
-		return TRUE;
-
-	case WM_DRAWITEM:
-#ifdef DEBUG_OPENDLG_DRAW
-		printf("FileOpenDlgProc // WM_DRAWITEM w=%04X l=%08X\n", wParam, lParam);
-#endif
-		if (lParam == 0L) break;
-		lpdis = (LPDRAWITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
-#ifdef DEBUG_OPENDLG_DRAW
-		printf("FileOpenDlgProc // WM_DRAWITEM CtlType=%04X CtlID=%04X \n", 
-									lpdis->CtlType, lpdis->CtlID);
-#endif
-		if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst1)) {
-			hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-			SelectObject(lpdis->hDC, hBrush);
-			FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-			ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
-			if (ptr == NULL) break;
-			TextOut(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top, 
-											ptr, strlen(ptr));
-			}
-		if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst2)) {
-			hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-			SelectObject(lpdis->hDC, hBrush);
-			FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-			ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
-			if (ptr == NULL) break;
-			if (strcmp(ptr, "[.]") == 0) {
-				hBitmap = hFolder2;
-/*				ptr = OpenDlg_ExtractCurDir(CurPath, -1); */
-				ptr = CurPath;
-				}
-			else
-				hBitmap = hFolder;
-			GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-			TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
-							lpdis->rcItem.top, ptr, strlen(ptr));
-			hMemDC = CreateCompatibleDC(lpdis->hDC);
-			SelectObject(hMemDC, hBitmap);
-			BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
-						bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-			DeleteDC(hMemDC);
-			}
-		if ((lpdis->CtlType == ODT_COMBOBOX) && (lpdis->CtlID == cmb2)) {
-			hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-			SelectObject(lpdis->hDC, hBrush);
-			FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-			ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
-			if (ptr == NULL) break;
-			switch(ptr[2]) {
-				case 'a':
-				case 'b':
-					hBitmap = hFloppy;
-					break;
-				default:
-					hBitmap = hHDisk;
-				}
-			GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-			TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
-							lpdis->rcItem.top, ptr, strlen(ptr));
-			hMemDC = CreateCompatibleDC(lpdis->hDC);
-			SelectObject(hMemDC, hBitmap);
-			BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
-						bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-			DeleteDC(hMemDC);
-			}
-		if (lpdis->itemState != 0) {
-		    InvertRect(lpdis->hDC, &lpdis->rcItem);
-		    }
-        break;
-
-	case WM_COMMAND:
-		switch (wParam) {
-			case lst1:
-				if (HIWORD(lParam) == LBN_DBLCLK ||
-					HIWORD(lParam) == LBN_SELCHANGE) {
-#ifdef DEBUG_OPENDLG
-					printf("FileOpenDlgProc // LBN_SELCHANGE on lst1 !\n");
-#endif
-					wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
-					SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, (DWORD)C2);
-					}
-				if (HIWORD(lParam) == LBN_DBLCLK) {
-#ifdef DEBUG_OPENDLG
-					printf("FileOpenDlgProc // LBN_DBLCLK on lst1 !\n");
-#endif
-					return SendMessage(hWnd, WM_COMMAND, IDOK, 0L);
-					}
-				break;
-			case lst2:
-				if (HIWORD(lParam) == LBN_DBLCLK) {
-#ifdef DEBUG_OPENDLG
-					printf("FileOpenDlgProc // LBN_DBLCLK on lst2 !\n");
-#endif
-					wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-					if (wRet == (WORD)LB_ERR) return 0;
-					fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-					C2[0] = '\0';
-					wRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0L);
-					if (wRet == (WORD)LB_ERR) return 0;
-					SendDlgItemMessage(hWnd, lst2, LB_GETTEXT, wRet, (DWORD)C2);
-					if (C2[0] == '[') {
-						C2[strlen(C2) - 1] = '\0';
-						sprintf(str, "%s\\%s", CurPath, &C2[1]);
-						if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-							printf("OpenDlg_ScanDir // ChangeDir Error !\n");
-							}
-						else {
-							strcpy(CurPath, str);
-							}
-						}
-					}
-				break;
-			case cmb1:
-				if (HIWORD(lParam) == CBN_SELCHANGE) {
-					wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-					if (wRet == (WORD)LB_ERR) return 0;
-					fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-					printf("FileOpenDlgProc // new fspec #%d = '%s' !\n", wRet, fspec);
-					if (!OpenDlg_ScanFiles(hWnd, nDrive, CurPath, fspec)) {
-						printf("OpenDlg_ScanFiles // Change FileType Error !\n");
-						}
-					}
-				break;
-			case cmb2:
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // combo #2 changed !\n");
-#endif
-				wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-				if (wRet == (WORD)LB_ERR) return 0;
-				fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-				wRet = SendDlgItemMessage(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
-				if (wRet == (WORD)LB_ERR) return 0;
-				printf("FileOpenDlgProc // combo #2 CB_GETCURSEL=%d !\n", wRet);
-				SendDlgItemMessage(hWnd, cmb2, CB_GETLBTEXT, wRet, (DWORD)C2);
-				nDrive = C2[2] - 'a';
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // new drive selected=%d !\n", nDrive);
-#endif
-				sprintf(str, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // new drive , curPath='%s' !\n", str);
-#endif
-				if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-					printf("OpenDlg_ScanDir // ChangeDir Error !\n");
-					}
-				else {
-					strcpy(CurPath, str);
-					}
-				break;
-			case chx1:
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // read-only toggled !\n");
-#endif
-				break;
-			case pshHelp:
-#ifdef DEBUG_OPENDLG
-				printf("FileOpenDlgProc // pshHelp pressed !\n");
-#endif
-				break;
-			case IDOK:
-				ShowWindow(hWnd, SW_HIDE); 
-				SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 0, (DWORD)str);
-				wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
-				SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, (DWORD)str);
-				printf("FileOpenDlgProc // IDOK str='%s'\n", str);
-				strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFile), str);
-				lpofn->nFileOffset = 0;
-				lpofn->nFileExtension = strlen(PTR_SEG_TO_LIN(lpofn->lpstrFile)) - 3;
-				if (lpofn->lpstrFileTitle != NULL) {
-					wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
-					SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, (DWORD)str);
-					strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFileTitle), str);
-					}
-				EndDialog(hWnd, TRUE);
-				return(TRUE);
-			case IDCANCEL:
-				EndDialog(hWnd, FALSE);
-				return(TRUE);
-			}
-		return(FALSE);
-	}
-
-
-/*
-    case WM_CTLCOLOR:
-        SetBkColor((HDC)wParam, 0x00C0C0C0);
-        switch (HIWORD(lParam))
-            {
-            case CTLCOLOR_BTN:
-                SetTextColor((HDC)wParam, 0x00000000);
-                return(hGRAYBrush);
-            case CTLCOLOR_STATIC:
-                SetTextColor((HDC)wParam, 0x00000000);
-                return(hGRAYBrush);
-            }
-        return(FALSE);
-
-*/
-	return FALSE;
-}
-
-
 /***********************************************************************
  * 				FileDlg_Init			[internal]
  */
-BOOL FileDlg_Init(HWND hWnd, DWORD lParam)
+static BOOL FileDlg_Init()
 {
-	LPOPENFILENAME	lpofn;
-	lpofn = (LPOPENFILENAME)lParam;
-	if (lpofn == NULL) {
-		fprintf(stderr, "FileDlg_Init // Bad LPOPENFILENAME pointer !");
-		return FALSE;
-		}
-	if (hFolder == (HBITMAP)NULL) 
-		hFolder = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_FOLDER));
-	if (hFolder2 == (HBITMAP)NULL) 
-		hFolder2 = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_FOLDER2));
-	if (hFloppy == (HBITMAP)NULL) 
-		hFloppy = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_FLOPPY));
-	if (hHDisk == (HBITMAP)NULL) 
-		hHDisk = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_HDISK));
-	if (hCDRom == (HBITMAP)NULL) 
-		hCDRom = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_CDROM));
-	if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
-		hHDisk == 0 || hCDRom == 0)
-		fprintf(stderr, "FileDlg_Init // Error loading bitmaps !");
-	return TRUE;
+  if (!hFolder) hFolder = LoadBitmap(hSysRes, MAKEINTRESOURCE(OBM_FOLDER));
+  if (!hFolder2) hFolder2 = LoadBitmap(hSysRes, MAKEINTRESOURCE(OBM_FOLDER2));
+  if (!hFloppy) hFloppy = LoadBitmap(hSysRes, MAKEINTRESOURCE(OBM_FLOPPY));
+  if (!hHDisk) hHDisk = LoadBitmap(hSysRes, MAKEINTRESOURCE(OBM_HDISK));
+  if (!hCDRom) hCDRom = LoadBitmap(hSysRes, MAKEINTRESOURCE(OBM_CDROM));
+  if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
+      hHDisk == 0 || hCDRom == 0)
+  fprintf(stderr, "FileDlg_Init // Error loading bitmaps !");
+  return TRUE;
 }
 
-
-/***********************************************************************
- * 				OpenDlg_ScanFiles		[internal]
- */
-BOOL OpenDlg_ScanFiles(HWND hWnd, WORD nDrive, LPSTR newPath, LPSTR fileSpec)
-{
-	int		OldDrive;
-	char	OldPath[512];
-	char	str[512];
-	OldDrive = DOS_GetDefaultDrive();
-	DOS_SetDefaultDrive(nDrive) ;
-	strcpy(OldPath, DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-	printf("OpenDlg_ScanFiles // OldDrive=%d OldPath='%s'\n", OldDrive, OldPath);
-	printf("OpenDlg_ScanFiles // wanted newPath='%s'\n", newPath);
-#endif
-	if (newPath[1] == ':')
-		DOS_ChangeDir(nDrive, &newPath[2]);
-	else
-		DOS_ChangeDir(nDrive, newPath);
-	sprintf(newPath, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-	printf("OpenDlg_ScanFiles // actual newPath='%s'\n", newPath);
-#endif
-	if (strlen(newPath) == 3) newPath[2] = '\0';
-	sprintf(str, "%s\\%s", newPath, fileSpec);
-	DlgDirList(hWnd, str, lst1, 0, 0x0000);
-	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (DWORD)str);
-	DOS_ChangeDir(nDrive, OldPath);
-	DOS_SetDefaultDrive(OldDrive);
-	return TRUE;
-}
-
-
-
 /***********************************************************************
  * 				OpenDlg_ScanDir			[internal]
  */
-BOOL OpenDlg_ScanDir(HWND hWnd, WORD nDrive, LPSTR newPath, LPSTR fileSpec)
+static BOOL OpenDlg_ScanDir(HWND hWnd, LPSTR newPath)
 {
-	int		OldDrive;
-	char	OldPath[512];
-	char	str[512];
-	OldDrive = DOS_GetDefaultDrive();
-	DOS_SetDefaultDrive(nDrive) ;
-	strcpy(OldPath, DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-	printf("OpenDlg_ScanDir // OldDrive=%d OldPath='%s'\n", OldDrive, OldPath);
-	printf("OpenDlg_ScanDir // wanted newPath='%s'\n", newPath);
-#endif
-	if (newPath[1] == ':')
-		DOS_ChangeDir(nDrive, &newPath[2]);
-	else
-		DOS_ChangeDir(nDrive, newPath);
-	sprintf(newPath, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-	printf("OpenDlg_ScanDir // actual newPath='%s'\n", newPath);
-#endif
-	if (strlen(newPath) == 3) newPath[2] = '\0';
-	sprintf(str, "%s\\%s", newPath, fileSpec);
-	DlgDirList(hWnd, str, lst1, 0, 0x0000);
-	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (DWORD)str);
-	sprintf(str, "%s\\*.*", newPath);
-	DlgDirList(hWnd, str, lst2, 0, 0x8010);
-	if (strlen(newPath) == 2) strcat(newPath, "\\");
-	SendDlgItemMessage(hWnd, stc1, WM_SETTEXT, 0, (DWORD)newPath);
-	DOS_ChangeDir(nDrive, OldPath);
-	DOS_SetDefaultDrive(OldDrive);
-	return TRUE;
+  static HANDLE hStr = 0;
+  static LPSTR  str  = NULL;
+  static SEGPTR str16 = 0;
+  LPSTR strp;
+  
+  if (str == NULL)  {
+    hStr = GlobalAlloc(0,512);
+    str = GlobalLock(hStr);
+    str16 = WIN16_GlobalLock(hStr);
+  }
+  
+  strcpy(str,newPath);
+  DlgDirList(hWnd, str, lst1, 0, 0x0000);
+  strp = strrchr(str,'\\');
+  if (strp == NULL)  {
+    if (str[1] == ':') {
+      strp = str+2;
+    } else  {
+      strp = str;
+    }
+  } else strp++;
+  strcpy(str,strp);
+  SendDlgItemMessage(hWnd,edt1,WM_SETTEXT, 0, str16);
+  strcpy(str,newPath);
+  *strp = 0;
+  strcat(str,"*.*");
+  DlgDirList(hWnd, str, lst2, stc1, 0x8010);
+  
+  return TRUE;
 }
 
 
@@ -597,21 +130,376 @@
 	return NULL;
 }
 
+/***********************************************************************
+ * 				GetOpenFileName			[COMMDLG.1]
+ */
+BOOL GetOpenFileName(LPOPENFILENAME lpofn)
+{
+	HANDLE		hDlgTmpl;
+	HANDLE		hResInfo;
+	HINSTANCE	hInst;
+	WND 		*wndPtr;
+	BOOL		bRet;
+
+        if (lpofn == NULL) return FALSE;
+	if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
+		hDlgTmpl = lpofn->hInstance;
+	} else {
+		if (lpofn->Flags & OFN_ENABLETEMPLATE) {
+			hInst = lpofn->hInstance;
+			hResInfo = FindResource(hInst,
+				lpofn->lpTemplateName, RT_DIALOG);
+		} else {
+			hInst = hSysRes;
+			hResInfo = FindResource(hInst, MAKEINTRESOURCE(OPENFILEDLG2), RT_DIALOG);
+		}
+		if (hResInfo == 0) {
+			CommDlgLastError = CDERR_FINDRESFAILURE;
+			return FALSE;
+		}
+		printf("GetOpenFileName // apres FindResource hResInfo=%04X!\n", hResInfo);
+		hDlgTmpl = LoadResource(hInst, hResInfo);
+       	}
+	if (hDlgTmpl == 0) {
+		CommDlgLastError = CDERR_LOADRESFAILURE;
+		return FALSE;
+	}
+	printf("GetOpenFileName // apres LoadResource hDlgTmpl=%04X!\n", hDlgTmpl);
+        wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
+	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl,
+                                      lpofn->hwndOwner,
+                                      GetWndProcEntry16("FileOpenDlgProc"),
+                                      (DWORD)lpofn); 
+
+	printf("GetOpenFileName // return lpstrFile='%s' !\n", 
+	       (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
+	return bRet;
+}
+
 
 /***********************************************************************
- * 				OpenDlg_ExtractCurDir	[internal]
+ * 				GetSaveFileName			[COMMDLG.2]
  */
-LPSTR OpenDlg_ExtractCurDir(LPSTR FullPath, short MaxLen)
+BOOL GetSaveFileName(LPOPENFILENAME lpofn)
 {
-	LPSTR 	ptr;
-	if (MaxLen < 0) MaxLen = strlen(FullPath);
-	ptr = FullPath + MaxLen - 1;
-	if (*ptr == '\\') return NULL;
-	while (ptr > FullPath) {
-		if (*ptr == '\\') return (ptr + 1);
-		ptr--;
+        HANDLE	        hDlgTmpl;
+        HANDLE	        hResInfo;
+        HINSTANCE       hInst;
+        WND 	        *wndPtr;
+        BOOL	        bRet;
+
+        if (lpofn == NULL) return FALSE;
+	if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
+		hDlgTmpl = lpofn->hInstance;
+	} else {
+		if (lpofn->Flags & OFN_ENABLETEMPLATE) {
+			hInst = lpofn->hInstance;
+                        hResInfo = FindResource(hInst, lpofn->lpTemplateName,
+						RT_DIALOG);
+		} else {
+			hInst = hSysRes;
+			hResInfo = FindResource(hInst, MAKEINTRESOURCE(SAVEFILEDLG2), RT_DIALOG);
 		}
-	return NULL;
+		if (hResInfo == 0) {
+			CommDlgLastError = CDERR_FINDRESFAILURE;
+			return FALSE;
+		}
+		hDlgTmpl = LoadResource(hInst, hResInfo);
+	}
+	if (hDlgTmpl == 0) {
+		CommDlgLastError = CDERR_LOADRESFAILURE;
+		return FALSE;
+	}
+        wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
+	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
+                                      lpofn->hwndOwner,
+                                      GetWndProcEntry16("FileSaveDlgProc"),
+                                      (DWORD)lpofn );
+	printf("GetSaveFileName // return lpstrFile='%s' !\n", 
+	       (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
+	return bRet;
+}
+
+
+/***********************************************************************
+ * 				ChooseColor				[COMMDLG.5]
+ */
+BOOL ChooseColor(LPCHOOSECOLOR lpChCol)
+{
+        WND     *wndPtr;
+	BOOL	bRet;
+
+        wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
+	bRet = DialogBoxParam( wndPtr->hInstance,
+                               MAKEINTRESOURCE(COLORDLG), 
+                               lpChCol->hwndOwner,
+                               GetWndProcEntry16("ColorDlgProc"), 
+                               (DWORD)lpChCol);
+	return bRet;
+}
+
+
+/***********************************************************************
+ * 				FileOpenDlgProc			[COMMDLG.6]
+ */
+BOOL FileOpenDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
+{
+  int		n;
+  LPSTR	  ptr;
+  LPSTR	  fspec;
+  WORD	  wRet;
+  LONG    lRet;
+  HBRUSH  hBrush;
+  HDC 	  hMemDC;
+  HBITMAP hBitmap;
+  BITMAP  bm;
+  LPMEASUREITEMSTRUCT lpmeasure;
+  LPDRAWITEMSTRUCT lpdis;
+  int  nDrive;
+  static LPOPENFILENAME lpofn;/* FIXME - this won't multitask */
+  
+  SEGPTR tempsegp;
+  
+  static HANDLE hStr  = 0;
+  static LPSTR  str   = NULL;
+  static SEGPTR str16 = 0;
+  
+  if (str == NULL)  {
+    hStr = GlobalAlloc(0,512);
+    str = GlobalLock(hStr);
+    str16 = WIN16_GlobalLock(hStr);
+  }
+  
+  switch (wMsg) {
+   case WM_INITDIALOG:
+    printf("FileOpenDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
+    if (!FileDlg_Init()) return TRUE;
+    SendDlgItemMessage(hWnd, cmb1, CB_RESETCONTENT, 0, 0);
+    lpofn = (LPOPENFILENAME)lParam;
+    ptr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
+    tempsegp = lpofn->lpstrFilter;
+    while(*ptr) {
+      n = strlen(ptr);
+      SendDlgItemMessage(hWnd, cmb1, CB_ADDSTRING, 0, tempsegp);
+      ptr += n + 1; tempsegp += n + 1;
+      n = strlen(ptr);
+      ptr += n + 1; tempsegp += n + 1;
+    }
+    /* set default filter */
+    SendDlgItemMessage(hWnd, cmb1, CB_SETCURSEL,
+		       lpofn->nFilterIndex - 1, 0L);
+    /* get drive information into combo 2 */
+    strcpy(str,"");
+    DlgDirListComboBox(hWnd, str16, cmb2, 0, 0xC000);
+    
+    if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) { 
+      strcpy(str, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
+      if (str[strlen(str)-1] != '\\' && str[strlen(str)-1] != ':') {
+        strcat(str,"\\");
+      }
+    } else  {
+      strcpy(str,"");
+    }
+    lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+    if (lRet == LB_ERR) return FALSE;
+    fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+    strcat(str,fspec);
+    
+    if (!OpenDlg_ScanDir(hWnd, str)) {
+      printf("OpenDlg_ScanDir // ChangeDir Error !\n");
+    }
+    /* select current drive in combo */
+    nDrive = DOS_GetDefaultDrive();
+    SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, nDrive, 0L);
+    
+    ShowWindow(hWnd, SW_SHOWNORMAL);
+    return TRUE;
+    
+   case WM_SHOWWINDOW:
+    if (wParam == 0) break;
+    if (!(lpofn->Flags & OFN_SHOWHELP)) {
+      ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
+    }
+    if (lpofn->Flags & OFN_HIDEREADONLY) {
+      ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
+    }
+    return TRUE;
+
+   case WM_MEASUREITEM:
+    GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
+    lpmeasure = (LPMEASUREITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    lpmeasure->itemHeight = bm.bmHeight;
+    return TRUE;
+    
+   case WM_DRAWITEM:
+    if (lParam == 0L) break;
+    lpdis = (LPDRAWITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst1)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      TextOut(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
+	      ptr, strlen(ptr));
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst2)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      hBitmap = hFolder;
+      GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+      TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
+	      lpdis->rcItem.top, ptr, strlen(ptr));
+      hMemDC = CreateCompatibleDC(lpdis->hDC);
+      SelectObject(hMemDC, hBitmap);
+      BitBlt(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+	     bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+      DeleteDC(hMemDC);
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    if ((lpdis->CtlType == ODT_COMBOBOX) && (lpdis->CtlID == cmb2)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      switch(ptr[2]) {
+       case 'a': case 'b':
+	hBitmap = hFloppy;
+	break;
+       default:
+	hBitmap = hHDisk;
+	break;
+      }
+      GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+      TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
+	      lpdis->rcItem.top, ptr, strlen(ptr));
+      hMemDC = CreateCompatibleDC(lpdis->hDC);
+      SelectObject(hMemDC, hBitmap);
+      BitBlt(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+	     bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+      DeleteDC(hMemDC);
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    break;
+    
+   case WM_COMMAND:
+    switch (wParam) {
+     case lst1:
+      if (HIWORD(lParam) == LBN_DBLCLK) {
+	lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return 0;
+	SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, lRet, str16);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);
+      }
+      break;
+     case lst2:
+      if (HIWORD(lParam) == LBN_DBLCLK) {
+	lRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return 0;
+	SendDlgItemMessage(hWnd, lst2, LB_GETTEXT, lRet, str16);
+
+	if (str[0] == '[') {
+	  str[strlen(str) - 1] = 0;
+	  strcpy(str,str+1);
+	}
+	strcat(str,"\\"); 
+	lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+	if (lRet == LB_ERR) return FALSE;
+	fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+	strcat(str,"\\"); strcat(str,fspec);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);
+      }
+      break;
+     case cmb1:
+      if (HIWORD(lParam) == CBN_SELCHANGE) {
+	lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return FALSE;
+	fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+	strcpy(str,fspec);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);	
+      }
+      break;
+     case cmb2:
+      wRet = SendDlgItemMessage(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
+      if (wRet == (WORD)LB_ERR) return 0;
+      SendDlgItemMessage(hWnd, cmb2, CB_GETLBTEXT, wRet, str16);
+      str[0] = str[2]; str[1] = ':'; str[2] = 0;
+      lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
+      if (lRet == LB_ERR) return FALSE;
+      fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+      strcat(str,fspec);
+      SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+      return SendMessage(hWnd, WM_COMMAND, IDOK, 0);	
+      break;
+     case chx1:
+#ifdef DEBUG_OPENDLG
+      printf("FileOpenDlgProc // read-only toggled !\n");
+#endif
+      break;
+     case pshHelp:
+#ifdef DEBUG_OPENDLG
+      printf("FileOpenDlgProc // pshHelp pressed !\n");
+#endif
+      break;
+     case IDOK:
+      SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 0, str16);
+      printf("OK: str %s\n",str);
+      if (COMMDLG_IsPathName(str)) {
+	OpenDlg_ScanDir(hWnd, str);
+      } else  {	
+	ShowWindow(hWnd, SW_HIDE); 
+	printf("FileOpenDlgProc // IDOK str='%s'\n", str);
+	strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFile), str);
+	lpofn->nFileOffset = 0;
+	lpofn->nFileExtension = strlen(PTR_SEG_TO_LIN(lpofn->lpstrFile)) - 3;
+	if (PTR_SEG_TO_LIN(lpofn->lpstrFileTitle) != NULL) {
+	  wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
+	  SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, str16);
+	  strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFileTitle), str);
+	}
+	EndDialog(hWnd, TRUE);
+      }
+      return TRUE;
+     case IDCANCEL:
+      EndDialog(hWnd, FALSE);
+      return TRUE;
+    }
+/*    return FALSE;*/
+  }
+  
+  /*
+  case WM_CTLCOLOR:
+   SetBkColor((HDC)wParam, 0x00C0C0C0);
+   switch (HIWORD(lParam))
+   {
+    case CTLCOLOR_BTN:
+     SetTextColor((HDC)wParam, 0x00000000);
+     return hGRAYBrush;
+    case CTLCOLOR_STATIC:
+     SetTextColor((HDC)wParam, 0x00000000);
+     return hGRAYBrush;
+   }
+   return FALSE;
+   
+   */
+  return FALSE;
 }
 
 
@@ -620,249 +508,261 @@
  */
 BOOL FileSaveDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
 {
-	int		n;
-	LPSTR	ptr;
-	LPSTR	fspec;
-	char	str[512];
-	char	C2[128];
-	WORD	wRet;
-	HBRUSH	hBrush;
-	HDC 	hMemDC;
-	HBITMAP	hBitmap;
-	BITMAP	bm;
-	LPMEASUREITEMSTRUCT lpmeasure;
-	LPDRAWITEMSTRUCT lpdis;
-	static	int		nDrive;
-	static 	char	CurPath[512];
-	static LPOPENFILENAME lpofn;
+  int		n;
+  LPSTR	  ptr;
+  LPSTR	  fspec;
+  WORD	  wRet;
+  LONG    lRet;
+  HBRUSH  hBrush;
+  HDC 	  hMemDC;
+  HBITMAP hBitmap;
+  BITMAP  bm;
+  LPMEASUREITEMSTRUCT lpmeasure;
+  LPDRAWITEMSTRUCT lpdis;
+  int  nDrive;
+  static LPOPENFILENAME lpofn;/* FIXME - this won't multitask */
+  
+  SEGPTR tempsegp;
+  
+  static HANDLE hStr  = 0;
+  static LPSTR  str   = NULL;
+  static SEGPTR str16 = 0;
+  
+  if (str == NULL)  {
+    hStr = GlobalAlloc(0,512);
+    str = GlobalLock(hStr);
+    str16 = WIN16_GlobalLock(hStr);
+  }
+  
+  switch (wMsg) {
+   case WM_INITDIALOG:
+    printf("FileSaveDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
+    if (!FileDlg_Init()) return TRUE;
+    SendDlgItemMessage(hWnd, cmb1, CB_RESETCONTENT, 0, 0);
+    lpofn = (LPOPENFILENAME)lParam;
+    ptr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
+    tempsegp = lpofn->lpstrFilter;
+    while(*ptr) {
+      n = strlen(ptr);
+      SendDlgItemMessage(hWnd, cmb1, CB_ADDSTRING, 0, tempsegp);
+      ptr += n + 1; tempsegp += n + 1;
+      n = strlen(ptr);
+      ptr += n + 1; tempsegp += n + 1;
+    }
+    /* set default filter */
+    SendDlgItemMessage(hWnd, cmb1, CB_SETCURSEL,
+		       lpofn->nFilterIndex - 1, 0L);
+    /* get drive information into combo 2 */
+    strcpy(str,"");
+    DlgDirListComboBox(hWnd, str16, cmb2, 0, 0xC000);
+    
+    if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) { 
+      strcpy(str, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
+      if (str[strlen(str)-1] != '\\' && str[strlen(str)-1] != ':') {
+        strcat(str,"\\");
+      }
+    } else  {
+      strcpy(str,"");
+    }
+    lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+    if (lRet == LB_ERR) return FALSE;
+    fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+    strcat(str,fspec);
+    
+    if (!OpenDlg_ScanDir(hWnd, str)) {
+      printf("SaveDlg_ScanDir // ChangeDir Error !\n");
+    } 
+    /* select current drive in combo */
+    nDrive = DOS_GetDefaultDrive();
+    SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, nDrive, 0L);
+    
+    ShowWindow(hWnd, SW_SHOWNORMAL);
+    return TRUE;
+    
+   case WM_SHOWWINDOW:
+    if (wParam == 0) break;
+    if (!(lpofn->Flags & OFN_SHOWHELP)) {
+      ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
+    }
+    if (lpofn->Flags & OFN_HIDEREADONLY) {
+      ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
+    }
+    return TRUE;
 
-	switch (wMsg) {
-		case WM_INITDIALOG:
-#ifdef DEBUG_OPENDLG
-			printf("FileSaveDlgProc // WM_INITDIALOG lParam=%08X\n", lParam);
-#endif
-			if (!FileDlg_Init(hWnd, lParam)) return TRUE;
-			SendDlgItemMessage(hWnd, cmb1, CB_RESETCONTENT, 0, 0L);
-			lpofn = (LPOPENFILENAME)lParam;
-			ptr = (LPSTR)lpofn->lpstrFilter;
-			strcpy(CurPath, lpofn->lpstrInitialDir);
-			while((n = strlen(ptr)) != 0) {
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // file type '%s' !\n", ptr);
-#endif
-				SendDlgItemMessage(hWnd, cmb1, CB_ADDSTRING, 0, (DWORD)ptr);
-				ptr += ++n;
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // file spec '%s' !\n", ptr);
-#endif
-				n = strlen(ptr);
-				ptr += ++n;
-				}
-			SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, (DWORD)str);
-			SendDlgItemMessage(hWnd, cmb1, CB_SETCURSEL, 
-						lpofn->nFilterIndex - 1, 0L);
-			DlgDirListComboBox(hWnd, "", cmb2, 0, 0xC000);
-			nDrive = 2; 		/* Drive 'C:' */
-			SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, nDrive, 0L);
-			sprintf(str, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-			fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, 
-									lpofn->nFilterIndex);
-#ifdef DEBUG_OPENDLG
-			printf("FileSaveDlgProc // WM_INITDIALOG fspec #%d = '%s' !\n", 
-											lpofn->nFilterIndex, fspec);
-#endif
-			if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-				printf("OpenDlg_ScanDir // ChangeDir Error !\n");
-				}
-			else {
-				strcpy(CurPath, str);
-				}
-			ShowWindow(hWnd, SW_SHOWNORMAL);
-			return (TRUE);
+   case WM_MEASUREITEM:
+    GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
+    lpmeasure = (LPMEASUREITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    lpmeasure->itemHeight = bm.bmHeight;
+    return TRUE;
+    
+   case WM_DRAWITEM:
+    if (lParam == 0L) break;
+    lpdis = (LPDRAWITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst1)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      TextOut(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
+	      ptr, strlen(ptr));
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst2)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      hBitmap = hFolder;
+      GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+      TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
+	      lpdis->rcItem.top, ptr, strlen(ptr));
+      hMemDC = CreateCompatibleDC(lpdis->hDC);
+      SelectObject(hMemDC, hBitmap);
+      BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
+	     bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+      DeleteDC(hMemDC);
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    if ((lpdis->CtlType == ODT_COMBOBOX) && (lpdis->CtlID == cmb2)) {
+      hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
+      SelectObject(lpdis->hDC, hBrush);
+      FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
+      ptr = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+      if (ptr == NULL) break;
+      switch(ptr[2]) {
+       case 'a': case 'b':
+	hBitmap = hFloppy;
+	break;
+       default:
+	hBitmap = hHDisk;
+	break;
+      }
+      GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+      TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
+	      lpdis->rcItem.top, ptr, strlen(ptr));
+      hMemDC = CreateCompatibleDC(lpdis->hDC);
+      SelectObject(hMemDC, hBitmap);
+      BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
+	     bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+      DeleteDC(hMemDC);
+      if (lpdis->itemState != 0) {
+	InvertRect(lpdis->hDC, &lpdis->rcItem);
+      }
+      return TRUE;
+    }
+    break;
+    
+   case WM_COMMAND:
+    switch (wParam) {
+     case lst1:
+      if (HIWORD(lParam) == LBN_DBLCLK) {
+	lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return 0;
+	SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, lRet, str16);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);
+      }
+      break;
+     case lst2:
+      if (HIWORD(lParam) == LBN_DBLCLK) {
+	lRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return 0;
+	SendDlgItemMessage(hWnd, lst2, LB_GETTEXT, lRet, str16);
 
-	case WM_SHOWWINDOW:
-		if (wParam == 0) break;
-		if (!(lpofn->Flags & OFN_SHOWHELP)) {
-			ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
-			}
-		if (lpofn->Flags & OFN_HIDEREADONLY) {
-			ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 
-			}
-		return TRUE;
-
-    case WM_MEASUREITEM:
-		GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
-		lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
-		lpmeasure->itemHeight = bm.bmHeight;
-#ifdef DEBUG_OPENDLG_DRAW
-		printf("FileSaveDlgProc WM_MEASUREITEM Height=%d !\n", bm.bmHeight);
-#endif
-		return TRUE;
-
-		case WM_DRAWITEM:
-#ifdef DEBUG_OPENDLG_DRAW
-			printf("FileSaveDlgProc // WM_DRAWITEM w=%04X l=%08X\n", wParam, lParam);
-#endif
-			if (lParam == 0L) break;
-			lpdis = (LPDRAWITEMSTRUCT)lParam;
-#ifdef DEBUG_OPENDLG_DRAW
-			printf("FileSaveDlgProc // WM_DRAWITEM lpdis->CtlID=%04X\n", lpdis->CtlID);
-#endif
-			if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst1)) {
-				hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-				SelectObject(lpdis->hDC, hBrush);
-				FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-				ptr = (LPSTR) lpdis->itemData;
-				if (ptr == NULL) break;
-				TextOut(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top, 
-														ptr, strlen(ptr));
-				}
-			if ((lpdis->CtlType == ODT_LISTBOX) && (lpdis->CtlID == lst2)) {
-				hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-				SelectObject(lpdis->hDC, hBrush);
-				FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-				ptr = (LPSTR) lpdis->itemData;
-				if (ptr == NULL) break;
-				if (strcmp(ptr, "[.]") == 0) {
-					hBitmap = hFolder2;
-					ptr = CurPath;
-					}
-				else
-					hBitmap = hFolder;
-				GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-				TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
-								lpdis->rcItem.top, ptr, strlen(ptr));
-				hMemDC = CreateCompatibleDC(lpdis->hDC);
-				SelectObject(hMemDC, hBitmap);
-				BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
-							bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-				DeleteDC(hMemDC);
-				}
-			if ((lpdis->CtlType == ODT_COMBOBOX) && (lpdis->CtlID == cmb2)) {
-				hBrush = SelectObject(lpdis->hDC, GetStockObject(LTGRAY_BRUSH));
-				SelectObject(lpdis->hDC, hBrush);
-				FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
-				ptr = (LPSTR) lpdis->itemData;
-				if (ptr == NULL) break;
-				switch(ptr[2]) {
-					case 'a':
-					case 'b':
-						hBitmap = hFloppy;
-						break;
-					default:
-						hBitmap = hHDisk;
-					}
-				GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-				TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
-								lpdis->rcItem.top, ptr, strlen(ptr));
-				hMemDC = CreateCompatibleDC(lpdis->hDC);
-				SelectObject(hMemDC, hBitmap);
-				BitBlt(lpdis->hDC, lpdis->rcItem.left,	lpdis->rcItem.top,
-							bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-				DeleteDC(hMemDC);
-				}
-	        break;
-
-		case WM_COMMAND:
-			switch (wParam) {
-				case lst1:
-					if (HIWORD(lParam) == LBN_DBLCLK ||
-						HIWORD(lParam) == LBN_SELCHANGE) {
+	if (str[0] == '[') {
+	  str[strlen(str) - 1] = 0;
+	  strcpy(str,str+1);
+	}
+	strcat(str,"\\"); 
+	lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+	if (lRet == LB_ERR) return FALSE;
+	fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+	strcat(str,"\\"); strcat(str,fspec);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);
+      }
+      break;
+     case cmb1:
+      if (HIWORD(lParam) == CBN_SELCHANGE) {
+	lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return FALSE;
+	fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+	strcpy(str,fspec);
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+	return SendMessage(hWnd, WM_COMMAND, IDOK, 0);	
+      }
+      break;
+     case cmb2:
+      wRet = SendDlgItemMessage(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
+      if (wRet == (WORD)LB_ERR) return 0;
+      SendDlgItemMessage(hWnd, cmb2, CB_GETLBTEXT, wRet, str16);
+      str[0] = str[2]; str[1] = ':'; str[2] = 0;
+      lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
+      if (lRet == LB_ERR) return FALSE;
+      fspec = OpenDlg_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), lRet + 1);
+      strcat(str,fspec);
+      SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, str16);
+      return SendMessage(hWnd, WM_COMMAND, IDOK, 0);	
+      break;
+     case chx1:
 #ifdef DEBUG_OPENDLG
-						printf("FileSaveDlgProc // LBN_SELCHANGE on lst1 !\n");
+      printf("FileSaveDlgProc // read-only toggled !\n");
 #endif
-						wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
-						SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, (DWORD)C2);
-						}
-					if (HIWORD(lParam) == LBN_DBLCLK) {
+      break;
+     case pshHelp:
 #ifdef DEBUG_OPENDLG
-						printf("FileSaveDlgProc // LBN_DBLCLK on lst1 !\n");
+      printf("FileSaveDlgProc // pshHelp pressed !\n");
 #endif
-						return SendMessage(hWnd, WM_COMMAND, IDOK, 0L);
-						}
-					break;
-				case lst2:
-				if (HIWORD(lParam) == LBN_DBLCLK) {
-#ifdef DEBUG_OPENDLG
-					printf("FileSaveDlgProc // LBN_DBLCLK on lst2 !\n");
-#endif
-					wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-					fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-					C2[0] = '\0';
-					wRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0L);
-					SendDlgItemMessage(hWnd, lst2, LB_GETTEXT, wRet, (DWORD)C2);
-					if (C2[0] == '[') {
-						C2[strlen(C2) - 1] = '\0';
-						sprintf(str, "%s\\%s", CurPath, &C2[1]);
-						if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-							printf("FileSaveDlgProc // ChangeDir Error !\n");
-							}
-						else {
-							strcpy(CurPath, str);
-							}
-						}
-					}
-				break;
-			case cmb1:
-				if (HIWORD(lParam) == CBN_SELCHANGE) {
-					wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-					fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-					printf("FileSaveDlgProc // new fspec #%d = '%s' !\n", wRet, fspec);
-					if (!OpenDlg_ScanFiles(hWnd, nDrive, CurPath, fspec)) {
-						printf("OpenDlg_ScanFile // Change FileType Error !\n");
-						}
-					}
-				break;
-			case cmb2:
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // combo #2 changed !\n");
-#endif
-				wRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0L);
-				if (wRet == (WORD)LB_ERR) return 0;
-				fspec = OpenDlg_GetFileType(lpofn->lpstrFilter, wRet + 1);
-				wRet = SendDlgItemMessage(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
-				if (wRet == (WORD)LB_ERR) return 0;
-				printf("FileSaveDlgProc // combo #2 CB_GETCURSEL=%d !\n", wRet);
-				SendDlgItemMessage(hWnd, cmb2, CB_GETLBTEXT, wRet, (DWORD)C2);
-				nDrive = C2[2] - 'a';
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // new drive selected=%d !\n", nDrive);
-#endif
-				sprintf(str, "%c:\\%s", nDrive + 'A', DOS_GetCurrentDir(nDrive));
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // new drive , curPath='%s' !\n", str);
-#endif
-				if (!OpenDlg_ScanDir(hWnd, nDrive, str, fspec)) {
-					printf("FileSaveDlgProc // Change Drive Error !\n");
-					}
-				else {
-					strcpy(CurPath, str);
-					}
-				break;
-			case chx1:
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // read-only toggled !\n");
-#endif
-				break;
-			case pshHelp:
-#ifdef DEBUG_OPENDLG
-				printf("FileSaveDlgProc // pshHelp pressed !\n");
-#endif
-				break;
-				case IDOK:
-					strcpy(lpofn->lpstrFile, "titi.txt");
-					if (lpofn->lpstrFileTitle != NULL) {
-						strcpy(lpofn->lpstrFileTitle, "titi.txt");
-						}
-					EndDialog(hWnd, TRUE);
-					return(TRUE);
-				case IDCANCEL:
-					EndDialog(hWnd, FALSE);
-					return(TRUE);
-				}
-			return(FALSE);
-		}
-	return FALSE;
+      break;
+     case IDOK:
+      SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 0, str16);
+      if (COMMDLG_IsPathName(str)) {
+	OpenDlg_ScanDir(hWnd, str);
+      } else  {	
+	ShowWindow(hWnd, SW_HIDE); 
+	strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFile), str);
+	lpofn->nFileOffset = 0;
+	lpofn->nFileExtension = strlen(PTR_SEG_TO_LIN(lpofn->lpstrFile)) - 3;
+	if (PTR_SEG_TO_LIN(lpofn->lpstrFileTitle) != NULL) {
+	  wRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0L);
+	  SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, wRet, str16);
+	  strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFileTitle), str);
+	}
+	EndDialog(hWnd, TRUE);
+      }
+      return TRUE;
+     case IDCANCEL:
+      EndDialog(hWnd, FALSE);
+      return TRUE;
+    }
+/*    return FALSE;*/
+  }
+  
+  
+  /*
+  case WM_CTLCOLOR:
+   SetBkColor((HDC)wParam, 0x00C0C0C0);
+   switch (HIWORD(lParam))
+   {
+    case CTLCOLOR_BTN:
+     SetTextColor((HDC)wParam, 0x00000000);
+     return hGRAYBrush;
+    case CTLCOLOR_STATIC:
+     SetTextColor((HDC)wParam, 0x00000000);
+     return hGRAYBrush;
+   }
+   return FALSE;
+   
+   */
+  return FALSE;
 }
 
 
@@ -912,9 +812,10 @@
 		return FALSE;
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
-	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, GetWndProcEntry16("FindTextDlgProc"), 
-	        (DWORD)lpFind);
+	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl,
+                                      lpFind->hwndOwner,
+                                      GetWndProcEntry16("FindTextDlgProc"),
+                                      (DWORD)lpFind);
 	return bRet;
 }
 
@@ -939,9 +840,10 @@
 		return FALSE;
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
-	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, GetWndProcEntry16("ReplaceTextDlgProc"), 
-		(DWORD)lpFind);
+	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl,
+                                      lpFind->hwndOwner,
+                                      GetWndProcEntry16("ReplaceTextDlgProc"),
+                                      (DWORD)lpFind);
 	return bRet;
 }
 
@@ -1023,13 +925,15 @@
 		}
     wndPtr = WIN_FindWndPtr(lpPrint->hwndOwner);
 	if (lpPrint->Flags & PD_PRINTSETUP)
-		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, GetWndProcEntry16("PrintSetupDlgProc"),
-			(DWORD)lpPrint);
+            bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl,
+                                          lpPrint->hwndOwner,
+                                          GetWndProcEntry16("PrintSetupDlgProc"),
+                                          (DWORD)lpPrint);
 	else
-		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, GetWndProcEntry16("PrintDlgProc"),
-		        (DWORD)lpPrint);
+            bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl,
+                                          lpPrint->hwndOwner,
+                                          GetWndProcEntry16("PrintDlgProc"),
+                                          (DWORD)lpPrint);
 	return bRet;
 }
 
@@ -1126,6 +1030,3 @@
 	else
 		return 0;
 }
-
-
-
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index dfc69dd..c26f69ba 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -957,3 +957,11 @@
 		de->inuse = 0;
 	}
 }
+
+char *DOS_GetRedirectedDir(int drive)
+{
+    if(DOS_ValidDrive(drive))
+        return (DosDrives[drive].rootdir);
+    else
+        return ("/");
+}
diff --git a/misc/exec.c b/misc/exec.c
index 771fba2..e10cb21 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -42,102 +42,6 @@
 
 typedef BOOL (CALLBACK * LPFNWINMAIN)(HANDLE, HANDLE, LPSTR, int);
 
-HANDLE CreateNewTask(HINSTANCE hInst);
-
-#ifndef WINELIB
-void InitializeLoadedNewDLLs(HINSTANCE hInst)
-{
-    struct w_files * w;
-    struct w_files * wpnt;
-    int cs_reg, ds_reg, ip_reg;
-    int rv;
-
-    dprintf_exec(stddeb, "Initializing New DLLs\n");
-
-    /*
-     * Initialize libraries
-     */
-    dprintf_exec(stddeb,
-	"InitializeLoadedNewDLLs() before searching hInst=%04X !\n", hInst);
-	w = wine_files;
-	while (w && w->hinstance != hInst) w = w->next;
-	if (w == NULL) return;
-    dprintf_exec(stddeb,"InitializeLoadedNewDLLs() // before InitLoop !\n");
-    for(wpnt = w; wpnt; wpnt = wpnt->next)
-    {
-	/* 
-	 * Is this a library? 
-	 */
-	if (wpnt->ne->ne_header->format_flags & 0x8000)
-	{
-	    if (!(wpnt->ne->ne_header->format_flags & 0x0001))
-	    {
-		/* Not SINGLEDATA */
-		fprintf(stderr, "Library is not marked SINGLEDATA\n");
-		exit(1);
-	    }
-
-	    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;
-
-        dprintf_exec(stddeb, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
-		    wpnt->name, cs_reg, 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);
-	}
-    }
-}
-
-
-void StartNewTask(HINSTANCE hInst)
-{
-	struct w_files * wpnt;
-	struct w_files * w;
-	int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
-	int rv;
-	int segment;
-
-    	dprintf_exec(stddeb,
-		"StartNewTask() before searching hInst=%04X !\n", hInst);
-	wpnt = wine_files;
-	while (wpnt && wpnt->hinstance != hInst) wpnt = wpnt->next;
-	if (wpnt == NULL) return;
-    	dprintf_exec(stddeb,"StartNewTask() // before FixupSegment !\n");
-	for(w = wpnt; w; w = w->next)	{
-		for (segment = 0; segment < w->ne->ne_header->n_segment_tab; segment++) {
-			if (NE_FixupSegment(w, segment) < 0) {
-				myerror("fixup failed.");
-				}
-			}
-		}
-	dprintf_exec(stddeb,"StartNewTask() before InitializeLoadedNewDLLs !\n");
-	InitializeLoadedNewDLLs(hInst);
-	dprintf_exec(stddeb,"StartNewTask() before setup register !\n");
-    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;
-
-	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);
-
-}
-
-#else
-void StartNewTask (HINSTANCE hInst)
-{
-    fprintf(stdnimp, "StartNewTask(): Not yet implemented\n");
-}
-#endif
 
 /**********************************************************************
  *				LoadModule	[KERNEL.45]
@@ -177,6 +81,11 @@
 	ArgV[c] = NULL;
     for (c = 0; ArgV[c] != NULL; c++) 
 	dprintf_exec(stddeb,"--> '%s' \n", ArgV[c]);
+
+        if ((hInst = LoadImage(ArgV[0], EXE, 1)) == (HINSTANCE) NULL ) {
+            fprintf(stderr, "wine: can't find %s!.\n", ArgV[0]);
+        }
+#if 0
 	switch(fork()) {
 		case -1:
             fprintf(stderr,"Can't 'fork' process !\n");
@@ -187,20 +96,7 @@
                 		fprintf(stderr,"Child process died !\n");
 				exit(1);
 				}
-			hTask = CreateNewTask(hInst);
-            		dprintf_exec(stddeb,
-			"WinExec // hTask=%04X hInst=%04X !\n", hTask, hInst);
 			StartNewTask(hInst); 
-/*
-			lpfnMain = (LPFNWINMAIN)GetProcAddress(hInst, (LPSTR)0L);
-            		dprintf_exec(stddeb,
-			"WineExec() // lpfnMain=%08X\n", (LONG)lpfnMain);
-			if (lpfnMain != NULL) {
-				(lpfnMain)(hInst, 0, lpCmdLine, nCmdShow);
-                		dprintf_exec(stddeb,
-					"WineExec() // after lpfnMain\n");
-				}
-*/
 /*			hTask = CreateNewTask(0);
             		dprintf_exec(stddeb,
 				"WinExec // New Task hTask=%04X !\n", hTask);
@@ -214,6 +110,7 @@
 			hTask);
 			break;         
 		}
+#endif
 	for (c = 0; ArgV[c] != NULL; c++) 	free(ArgV[c]);
 	return hTask;
 }
diff --git a/misc/lstr.c b/misc/lstr.c
index 41db38d..9d7be42 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -11,6 +11,8 @@
 
 #include "ldt.h"
 #include "windows.h"
+#include "stddebug.h"
+#include "debug.h"
 
 #define ToUpper(c)	toupper(c)
 #define ToLower(c)	tolower(c)
@@ -220,8 +222,9 @@
 {
   InitOemAnsiTranslations(); /* should called called in some init function*/
   while(*lpAnsiStr){
-    *lpOemStr++=Ansi2Oem[*lpAnsiStr++];
+    *lpOemStr++=Ansi2Oem[(unsigned char)(*lpAnsiStr++)];
   }
+  *lpOemStr = 0;
   return -1;
 }
 
@@ -230,8 +233,9 @@
 {
   InitOemAnsiTranslations(); /* should called called in some init function*/
   while(*lpOemStr){
-    *lpAnsiStr++=Oem2Ansi[*lpOemStr++];
+    *lpAnsiStr++=Oem2Ansi[(unsigned char)(*lpOemStr++)];
   }
+  *lpAnsiStr = 0;
   return -1;
 }
 
@@ -241,7 +245,7 @@
   int i;
   InitOemAnsiTranslations(); /* should called called in some init function*/
   for(i=0;i<nLength;i++)
-    lpOemStr[i]=Ansi2Oem[lpAnsiStr[i]];  
+    lpOemStr[i]=Ansi2Oem[(unsigned char)(lpAnsiStr[i])];
 }
 
 /* OemToAnsi Keyboard.135 */
@@ -250,5 +254,5 @@
   int i;
   InitOemAnsiTranslations(); /* should called called in some init function*/
   for(i=0;i<nLength;i++)
-    lpAnsiStr[i]=Oem2Ansi[lpOemStr[i]];
+    lpAnsiStr[i]=Oem2Ansi[(unsigned char)(lpOemStr[i])];
 }
diff --git a/misc/main.c b/misc/main.c
index 4da1c08..0d2dc23 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -20,11 +20,9 @@
 #include "wine.h"
 #include "msdos.h"
 #include "windows.h"
-#include "comm.h"
 #include "miscemu.h"
 #include "winsock.h"
 #include "options.h"
-#include "dos_fs.h"
 #include "desktop.h"
 #include "prototypes.h"
 #include "texts.h"
@@ -38,13 +36,16 @@
 extern ButtonTexts ButtonText;
 
 static const char people[] = "Wine is available thanks to the work of "\
-"Bob Amstadt, Dag Asheim, Martin Ayotte, Erik Bos, John Brezak, "\
-"Andrew Bulhak, John Burton, Paul Falstad, Peter Galbavy, Jeffrey Hsu, "\
-"Miguel de Icaza, Alexandre Julliard, Jon Konrath, Scott A. Laird, "\
-"Martin von Loewis, Kenneth MacDonald, Peter MacDonald, David Metcalfe, "\
-"Michael Patra, John Richardson, Johannes Ruscheinski, Yngvi Sigurjonsson, "\
-"Rick Sladkey, William Smith, Jon Tombs, Linus Torvalds, Carl Williams, "\
-"Karl Guenter Wuensch, and Eric Youngdale.";
+"Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Erik Bos, Fons Botman, "\
+"John Brezak, Andrew Bulhak, John Burton, Paul Falstad, Olaf Flebbe, "\
+"Peter Galbavy, Cameron Heide, Jeffrey Hsu, Miguel de Icaza, "\
+"Alexandre Julliard, Jon Konrath, Scott A. Laird, Martin von Loewis, "\
+"Kenneth MacDonald, Peter MacDonald, William Magro, David Metcalfe, "\
+"Michael Patra, John Richardson, Johannes Ruscheinski, Thomas Sandford, "\
+"Constantine Sapuntzakis, Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey, "\
+"William Smith, Erik Svendsen, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, "\
+"Linus Torvalds, Michael Veksler, Carl Williams, Karl Guenter Wuensch, "\
+"Eric Youngdale, and James Youngman.";
 
 #define WINE_CLASS    "Wine"    /* Class name for resources */
 
@@ -516,7 +517,6 @@
 
 static void called_at_exit(void)
 {
-    Comm_DeInit();
     sync_profiles();
     MAIN_RestoreSetup();
     WSACleanup();
@@ -574,13 +574,7 @@
     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
     else rootWindow = DefaultRootWindow( display );
 
-    RELAY_Init();
     MAIN_SaveSetup();
-    DOS_InitFS();
-    Comm_Init();
-#ifndef WINELIB
-    INT21_Init();
-#endif
 #ifndef sparc
     atexit(called_at_exit);
 #else
@@ -822,6 +816,20 @@
 				return (DESKTOP_SetPattern((LPSTR) lpvParam));
 			break;
 
+	        case SPI_GETICONTITLELOGFONT: 
+	        {
+		  LPLOGFONT lpLogFont = (LPLOGFONT)lpvParam;
+		  lpLogFont->lfHeight = 10;
+		  lpLogFont->lfWidth = 0;
+		  lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
+		  lpLogFont->lfWeight = FW_NORMAL;
+		  lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
+		  lpLogFont->lfCharSet = ANSI_CHARSET;
+		  lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+		  lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+		  lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
+		  break;
+		}
 		case SPI_LANGDRIVER:
 		case SPI_SETBORDER:
 		case SPI_SETDOUBLECLKHEIGHT:
diff --git a/misc/network.c b/misc/network.c
index 5c7ab4f..fd10f65 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -2,10 +2,14 @@
  * Network functions
  */
 
+#include <ctype.h>
 #include "stdio.h"
 #include "windows.h"
 #include "user.h"
 
+#include "msdos.h"
+#include "dos_fs.h"
+
 #define WN_SUCCESS       			0x0000
 #define WN_NOT_SUPPORTED 			0x0001
 #define WN_NET_ERROR     			0x0002
@@ -154,9 +158,29 @@
 int WNetGetConnection(LPSTR lpLocalName, 
 	LPSTR lpRemoteName, UINT FAR *cbRemoteName)
 {
-	printf("EMPTY STUB !!! WNetGetConnection('%s', %p, %p);\n", 
-		lpLocalName, lpRemoteName, cbRemoteName);
-	return	WN_NET_ERROR;
+    int drive, rc;
+
+    if(lpLocalName[1] == ':')
+    {
+        drive = toupper(lpLocalName[0]) - 'A';
+        if(!DOS_ValidDrive(drive))
+            rc = WN_NOT_CONNECTED;
+        else
+        {
+            if(strlen(DOS_GetRedirectedDir(drive)) + 1 > *cbRemoteName)
+                rc = WN_MORE_DATA;
+            else
+            {
+                strcpy(lpRemoteName, DOS_GetRedirectedDir(drive));
+                *cbRemoteName = strlen(lpRemoteName) + 1;
+                rc = WN_SUCCESS;
+            }
+        }
+    }
+    else
+        rc = WN_BAD_LOCALNAME;
+
+    return rc;
 }
 
 /**************************************************************************
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
new file mode 100644
index 0000000..68cbaa4
--- /dev/null
+++ b/misc/ole2nls.c
@@ -0,0 +1,55 @@
+/*
+ *	OLE2NLS library
+ *
+ *	Copyright 1995	Martin von Loewis
+ */
+
+/*	At the moment, these are only empty stubs.
+ */
+
+#include "windows.h"
+#include "ole.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           GetUserDefaultLCID       (OLE2NLS.1)
+ */
+DWORD WINAPI GetUserDefaultLCID()
+{
+/* Default sorting, neutral sublanguage */
+#if #LANG(En)
+	return 9;
+#elif #LANG(De)
+	return 7;
+#elif #LANG(No)
+	return 0x14;
+#else
+	/* Neutral language */
+	return 0;
+#endif
+}
+
+/***********************************************************************
+ *         GetSystemDefaultLCID       (OLE2NLS.2)
+ */
+DWORD WINAPI GetSystemDefaultLCID()
+{
+	return GetUserDefaultLCID();
+}
+
+/***********************************************************************
+ *         GetUserDefaultLangID       (OLE2NLS.3)
+ */
+WORD WINAPI GetUserDefaultLangID()
+{
+	return (WORD)GetUserDefaultLCID();
+}
+
+/***********************************************************************
+ *         GetSystemDefaultLangID     (OLE2NLS.4)
+ */
+WORD WINAPI GetSystemDefaultLangID()
+{
+	return GetUserDefaultLangID();
+}
diff --git a/misc/profile.c b/misc/profile.c
index 7fd305d..9796d49 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -320,18 +320,18 @@
 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
 			   LPSTR File)
 {
-    static char IntBuf [6];
-    static char buf [6];
+    static char IntBuf[10];
+    static char buf[10];
 
     sprintf (buf, "%d", Default);
     
     /* Check the exact semantic with the SDK */
-    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File);
+    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 10, File);
     if (!strcasecmp (IntBuf, "true"))
 	return 1;
     if (!strcasecmp (IntBuf, "yes"))
 	return 1;
-    return atoi (IntBuf);
+    return strtoul( IntBuf, NULL, 0 );
 }
 
 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
diff --git a/misc/property.c b/misc/property.c
deleted file mode 100644
index 75f442f..0000000
--- a/misc/property.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * 				Windows Properties Functions
- *
-static char Copyright[] = "Copyright Martin Ayotte, 1994";
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include "windows.h"
-#include "win.h"
-#include "callback.h"
-#include "stddebug.h"
-/* #define DEBUG_PROP */
-/* #undef  DEBUG_PROP */
-#include "debug.h"
-
-typedef struct tagPROPENTRY {
-	LPSTR		PropName;
-	WORD		Atom;
-	HANDLE		hData;
-	struct tagPROPENTRY	*lpPrevProp;
-	struct tagPROPENTRY	*lpNextProp;
-} PROPENTRY;
-typedef PROPENTRY *LPPROPENTRY;
-
-
-/*************************************************************************
- *				RemoveProp			[USER.24]
- */
-HANDLE RemoveProp(HWND hWnd, LPSTR lpStr)
-{
-    WND 		*wndPtr;
-	LPPROPENTRY lpProp;
-	HANDLE		hOldData;
-	if (((DWORD)lpStr & 0xFFFF0000) == 0L)
-		dprintf_prop(stddeb, "RemoveProp(%04X, Atom %04X)\n", hWnd, LOWORD((DWORD)lpStr));
-	else
-		dprintf_prop(stddeb, "RemoveProp(%04X, '%s')\n", hWnd, lpStr);
-	wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) {
-    	printf("RemoveProp // Bad Window handle !\n");
-    	return FALSE;
-    	}
-	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
-	if (lpProp == NULL) {
-		dprintf_prop(stddeb, "Property List Empty !\n");
-		return 0;
-		}
-	while (TRUE) {
-		if ((((DWORD)lpStr & 0xFFFF0000) == 0L && 
-			lpProp->Atom == LOWORD((DWORD)lpStr)) ||
-			(((DWORD)lpStr & 0xFFFF0000) != 0L && 
-			lpProp->PropName != NULL &&
-			strcmp(lpProp->PropName, lpStr) == 0)) {
-		   	dprintf_prop(stddeb, "RemoveProp // Property found ! hData=%04X\n", lpProp->hData);
-			hOldData = lpProp->hData;
-			if (lpProp->lpPrevProp != NULL) 
-				lpProp->lpPrevProp->lpNextProp = lpProp->lpNextProp;
-			if (lpProp->lpNextProp != NULL) 
-				lpProp->lpNextProp->lpPrevProp = lpProp->lpPrevProp;
-			if (lpProp->PropName != NULL) free(lpProp->PropName);
-			GlobalFree(lpProp);
-			GlobalUnlock(wndPtr->hProp);
-			return hOldData;
-			}
-		if (lpProp->lpNextProp == NULL) break;
-		lpProp = lpProp->lpNextProp;
-		}
-	GlobalUnlock(wndPtr->hProp);
-   	dprintf_prop(stddeb, "RemoveProp // Property not found !\n");
-	return 0;
-}
-
-
-/*************************************************************************
- *				GetProp			[USER.25]
- */
-HANDLE GetProp(HWND hWnd, LPSTR lpStr)
-{
-    WND 		*wndPtr;
-	LPPROPENTRY lpProp;
-	if (((DWORD)lpStr & 0xFFFF0000) == 0L)
-		dprintf_prop(stddeb, "GetProp(%04X, Atom %04X)\n", hWnd, LOWORD((DWORD)lpStr));
-	else
-		dprintf_prop(stddeb, "GetProp(%04X, '%s')\n", hWnd, lpStr);
-	wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) {
-    	printf("GetProp // Bad Window handle !\n");
-    	return 0;
-    	}
-	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
-	if (lpProp == NULL) {
-		dprintf_prop(stddeb, "Property List Empty !\n");
-		return 0;
-		}
-	while (TRUE) {
-		if ((((DWORD)lpStr & 0xFFFF0000) == 0L && 
-			lpProp->Atom == LOWORD((DWORD)lpStr)) ||
-			(((DWORD)lpStr & 0xFFFF0000) != 0L && 
-			lpProp->PropName != NULL &&
-			strcmp(lpProp->PropName, lpStr) == 0)) {
-		   	dprintf_prop(stddeb, "GetProp // Property found ! hData=%04X\n", lpProp->hData);
-			GlobalUnlock(wndPtr->hProp);
-			return lpProp->hData;
-			}
-		if (lpProp->lpNextProp == NULL) break;
-		lpProp = lpProp->lpNextProp;
-		}
-   	dprintf_prop(stddeb, "GetProp // Property not found !\n");
-	GlobalUnlock(wndPtr->hProp);
-	return 0;
-}
-
-
-/*************************************************************************
- *				SetProp			[USER.26]
- */
-BOOL SetProp(HWND hWnd, LPSTR lpStr, HANDLE hData)
-{
-    WND 		*wndPtr;
-    HANDLE 		hNewProp;
-	LPPROPENTRY lpNewProp;
-	LPPROPENTRY lpProp;
-	if (((DWORD)lpStr & 0xFFFF0000) == 0L)
-		dprintf_prop(stddeb, "SetProp(%04X, Atom %04X, %04X)\n", 
-				hWnd, LOWORD((DWORD)lpStr), hData);
-	else
-		dprintf_prop(stddeb, "SetProp(%04X, '%s', %04X)\n", hWnd, lpStr, hData);
-	wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) {
-    	printf("SetProp // Bad Window handle !\n");
-    	return FALSE;
-    	}
-	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
-	if (lpProp != NULL) {
-		while (TRUE) {
-			if ((((DWORD)lpStr & 0xFFFF0000) == 0L && 
-				lpProp->Atom == LOWORD((DWORD)lpStr)) ||
-				(((DWORD)lpStr & 0xFFFF0000) != 0L && 
-				lpProp->PropName != NULL &&
-				strcmp(lpProp->PropName, lpStr) == 0)) {
-			    dprintf_prop(stddeb, "SetProp // change already exinsting property !\n");
-				lpProp->hData = hData;
-				GlobalUnlock(wndPtr->hProp);
-				return TRUE;
-				}
-			if (lpProp->lpNextProp == NULL) break;
-			lpProp = lpProp->lpNextProp;
-			}
-		}
-	hNewProp = GlobalAlloc(GMEM_MOVEABLE, sizeof(PROPENTRY));
-	lpNewProp = (LPPROPENTRY) GlobalLock(hNewProp);
-	if (lpNewProp == NULL) {
-    	printf("SetProp // Can't allocate Property entry !\n");
-		GlobalUnlock(wndPtr->hProp);
-    	return FALSE;
-		}
-	dprintf_prop(stddeb, "SetProp // entry allocated %08X\n", 
-    		(unsigned int) lpNewProp);
-	if (lpProp == NULL) {
-		wndPtr->hProp = hNewProp;
-		lpNewProp->lpPrevProp = NULL;
-	    dprintf_prop(stddeb, "SetProp // first entry \n");
-		}
-	else {
-		lpProp->lpNextProp = lpNewProp;
-		lpNewProp->lpPrevProp = lpProp;
-		}
-	lpNewProp->lpNextProp = NULL;
-	lpNewProp->hData = hData;
-	if (((DWORD)lpStr & 0xFFFF0000) == 0L) {
-		lpNewProp->PropName = NULL;
-		lpNewProp->Atom = LOWORD((DWORD)lpStr);
-		}
-	else {
-		lpNewProp->Atom = 0;
-		lpNewProp->PropName = malloc(strlen(lpStr) + 1);
-		if (lpNewProp->PropName == NULL) {
-	    	printf("SetProp // Can't allocate memory for Property Name !\n");
-			GlobalUnlock(wndPtr->hProp);
-    		return FALSE;
-			}
-		strcpy(lpNewProp->PropName, lpStr);
-		}
-	GlobalUnlock(hNewProp);
-	GlobalUnlock(wndPtr->hProp);
-	return TRUE;
-}
-
-
-/*************************************************************************
- *				EnumProps			[USER.27]
- */
-int EnumProps(HWND hWnd, FARPROC lpEnumFunc)
-{
-    WND 		*wndPtr;
-	LPPROPENTRY lpProp;
-	LPSTR		str;
-	int			nRet;
-	printf("EnumProps(%04X, %08X)\n", hWnd, (unsigned int) lpEnumFunc);
-	wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) {
-    	printf("EnumProps // Bad Window handle !\n");
-    	return 0;
-    	}
-	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
-	if (lpProp == NULL) {
-		printf("Property List Empty !\n");
-		return 0;
-		}
-	if (lpEnumFunc == NULL)	return 0;
-	while (TRUE) {
-    	printf("EnumProps // lpProp->Atom=%04X !\n", lpProp->Atom);
-		str = (LPSTR)MAKELONG(lpProp->Atom, 0); 
-		if (lpProp->PropName != NULL) {
-	    	printf("EnumProps // lpProp->PropName='%s' !\n", lpProp->PropName);
-			str = lpProp->PropName; 
-			}
-                nRet = CallEnumPropProc( lpEnumFunc, hWnd,
-                                         (LONG)str, lpProp->hData);
-		if (nRet == 0) break;
-		if (lpProp->lpNextProp == NULL) break;
-		lpProp = lpProp->lpNextProp;
-		}
-	GlobalUnlock(wndPtr->hProp);
-	return 0;
-}
-
-
diff --git a/misc/shell.c b/misc/shell.c
index f412887..f6a8db6 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -434,9 +434,11 @@
 		hInst2 = LoadLibrary(lpszExeFileName);
 		}
 	if (hInst2 != 0 && nIconIndex == (UINT)-1) {
+#if 0
 		count = GetRsrcCount(hInst2, NE_RSCTYPE_GROUP_ICON);
 		dprintf_reg(stddeb, "ExtractIcon // '%s' has %d icons !\n", lpszExeFileName, count);
 		return (HICON)count;
+#endif
 		}
 	if (hInst2 != hInst && hInst2 != 0) {
 		FreeLibrary(hInst2);
diff --git a/misc/user.c b/misc/user.c
index 91cc3d9..e68f443 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -5,8 +5,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "atom.h"
+#include "comm.h"
 #include "gdi.h"
+#include "desktop.h"
 #include "dlls.h"
+#include "dos_fs.h"
 #include "sysmetrics.h"
 #include "menu.h"
 #include "dce.h"
@@ -74,7 +77,7 @@
 /***********************************************************************
  *           USER_HeapInit
  */
-static BOOL USER_HeapInit(void)
+BOOL USER_HeapInit(void)
 {
     if (!(USER_HeapSel = GlobalAlloc(GMEM_FIXED,USER_HEAP_SIZE))) return FALSE;
     USER_Heap = GlobalLock( USER_HeapSel );
@@ -83,56 +86,18 @@
 }
 #endif
 
+
 /**********************************************************************
  *					USER_InitApp
- *
- * Load necessary resources?
  */
-int
-USER_InitApp(int hInstance)
+int USER_InitApp(int hInstance)
 {
     int queueSize;
 
-    SpyInit();
-
-#ifndef WINELIB    
-      /* Create USER heap */
-    if (!USER_HeapInit()) return 0;
-#endif
-    
-      /* Global atom table initialisation */
-    if (!ATOM_Init()) return 0;
-    
-      /* GDI initialisation */
-    if (!GDI_Init()) return 0;
-
-      /* Initialize system colors and metrics*/
-    SYSMETRICS_Init();
-    SYSCOLOR_Init();
-
-      /* Create the DCEs */
-    DCE_Init();
-    
-      /* Initialize built-in window classes */
-    if (!WIDGETS_Init()) return 0;
-
-      /* Initialize dialog manager */
-    if (!DIALOG_Init()) return 0;
-
-      /* Initialize menus */
-    if (!MENU_Init()) return 0;
-
-      /* Create system message queue */
-    queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
-    if (!MSG_CreateSysMsgQueue( queueSize )) return 0;
-
       /* Create task message queue */
     queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
     if (!SetMessageQueue( queueSize )) return 0;
 
-      /* Create desktop window */
-    if (!WIN_CreateDesktopWindow()) return 0;
-
 #ifndef WINELIB
     /* Initialize DLLs */
     InitializeLoadedDLLs(NULL);
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 28d4dca..44cb0ce 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -20,6 +20,7 @@
 #include "msdos.h"
 #include "registers.h"
 #include "ldt.h"
+#include "task.h"
 #include "options.h"
 #include "miscemu.h"
 #include "stddebug.h"
@@ -55,13 +56,10 @@
 
 WORD ExtendedError, CodePage = 437;
 BYTE ErrorClass, Action, ErrorLocus;
-BYTE *dta;
-DWORD dtasegptr;
 struct DPB *dpb;
 DWORD dpbsegptr;
 
 struct DosHeap {
-	BYTE dta[256];
 	BYTE InDosFlag;
         BYTE mediaID;
 	BYTE biosdate[8];
@@ -125,6 +123,13 @@
 	}
 }
 
+BYTE *GetCurrentDTA(void)
+{
+    TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+    return (BYTE *)PTR_SEG_TO_LIN( pTask->dta );
+}
+
+
 void ChopOffWhiteSpace(char *string)
 {
 	int length;
@@ -694,7 +699,8 @@
 {
 	struct dosdirent *dp;
         struct tm *t;
-	
+	BYTE *dta = GetCurrentDTA();
+
         memcpy(&dp, dta+0x11, sizeof(dp));
 
 	do {
@@ -730,6 +736,8 @@
 	BYTE drive, *path = PTR_SEG_OFF_TO_LIN(DS, DX);
 	struct dosdirent *dp;
 
+	BYTE *dta = GetCurrentDTA();
+
         dprintf_int(stddeb, "int21: FindFirst path = %s\n", path);
 
 	if ((*path)&&(path[1] == ':')) {
@@ -934,6 +942,8 @@
 	int drive;
 	char path[12];
 
+	BYTE *dta = GetCurrentDTA();
+
 	DumpFCB( fcb );
 	
 	if ((*fcb) == 0xff)
@@ -1167,6 +1177,8 @@
 
 int do_int21(struct sigcontext_struct * context)
 {
+    int drive;
+
     dprintf_int(stddeb,"int21: AX %04x, BX %04x, CX %04x, DX %04x, "
            "SI %04x, DI %04x, DS %04x, ES %04x\n",
            AX, BX, CX, DX, SI, DI, DS, ES);
@@ -1182,7 +1194,8 @@
 	switch(AH) 
 	{
 	  case 0x00: /* TERMINATE PROGRAM */
-	    exit(0);
+            TASK_KillCurrentTask( 0 );
+            break;
 
 	  case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
 	  case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
@@ -1266,8 +1279,10 @@
 	    break;
 
 	  case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
-            dtasegptr = MAKELONG( DX, DS );
-            dta = PTR_SEG_TO_LIN(dtasegptr);
+            {
+                TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+                pTask->dta = MAKELONG( DX, DS );
+            }
             break;
 
 	  case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
@@ -1298,8 +1313,11 @@
 	    break;
 
 	  case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
-            ES = SELECTOROF(dtasegptr);
-            BX = OFFSETOF(dtasegptr);
+            {
+                TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
+                ES = SELECTOROF( pTask->dta );
+                BX = OFFSETOF( pTask->dta );
+            }
             break;
             
 	  case 0x30: /* GET DOS VERSION */
@@ -1436,13 +1454,34 @@
 		break;
 
               case 0x08:   /* Check if drive is removable. */
-                EAX = (EAX & 0xFFFF0000) | 0x0001;   /* Nope, not removable. */
-                ResetCflag;
+                drive = BL ? (BL - 1) : DOS_GetDefaultDrive();
+                if(!DOS_ValidDrive(drive))
+                {
+                    SetCflag;
+                    AX = 0x000F;        /* Bad drive number */
+                }
+                else
+                {
+                    if(drive > 1)
+                        EAX = (EAX & 0xFFFF0000) | 0x0001;   /* not removable */
+                    else
+                        EAX = (EAX & 0xFFFF0000);       /* removable */
+                    ResetCflag;
+                }
                 break;
 		   
 	      case 0x09:   /* CHECK IF BLOCK DEVICE REMOTE */
-		EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12) | (1<<15);
-		ResetCflag;
+                drive = BL ? (BL - 1) : DOS_GetDefaultDrive();
+                if(!DOS_ValidDrive(drive))
+                {
+                    SetCflag;
+                    AX = 0x000F;        /* Bad drive number */
+                }
+                else
+                {
+		    EDX = (EDX & 0xffff0000) | (1<<9) | (1<<12) | (1<<15);
+		    ResetCflag;
+                }
 		break;
 
 	      case 0x0b:   /* SET SHARING RETRY COUNT */
@@ -1498,7 +1537,7 @@
 	    break;		
 	
 	  case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
-	    exit(AL);
+            TASK_KillCurrentTask( AL );
 	    break;
 
 	  case 0x4d: /* GET RETURN CODE */
@@ -1682,9 +1721,7 @@
     }
     heap = (struct DosHeap *) GlobalLock(DosHeapHandle);
 
-    dta = heap->dta;
     dpb = &heap->dpb;
-    dtasegptr = MAKELONG( 0, DosHeapHandle );
     dpbsegptr = MAKELONG( (int)&heap->dpb - (int)heap, DosHeapHandle );
     heap->InDosFlag = 0;
     strcpy(heap->biosdate, "01/01/80");
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 2f5eaaf..ea568e3 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -15,6 +15,17 @@
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
+        if(!DOS_ValidDrive(AL))
+        {
+            SetCflag;
+            AX = 0x0101;        /* unknown unit */
+
+            /* push flags on stack */
+            SP -= sizeof(WORD);
+            setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
+            return 1;
+        }
+
 	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
diff --git a/miscemu/int26.c b/miscemu/int26.c
index 051a4de..046c6bd 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -14,6 +14,17 @@
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
+        if(!DOS_ValidDrive(AL))
+        {
+            SetCflag;
+            AX = 0x0101;        /* unknown unit */
+
+            /* push flags on stack */
+            SP -= sizeof(WORD);
+            setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
+            return 1;
+        }
+
 	if (CX == 0xffff) {
 		begin = getdword(dataptr);
 		length = getword(&dataptr[4]);
diff --git a/miscemu/kernel.c b/miscemu/kernel.c
index f81410b..8dac7ee 100644
--- a/miscemu/kernel.c
+++ b/miscemu/kernel.c
@@ -26,13 +26,3 @@
     context.sc_edi = context.sc_ds;
 }
 
-/**********************************************************************
- *					KERNEL_WaitEvent
- */
-int
-KERNEL_WaitEvent(int task)
-{
-    if (debugging_relay)
-    	fprintf(stddeb,"WaitEvent: task %d\n", task);
-    return 0;
-}
diff --git a/objects/bitblt.c b/objects/bitblt.c
index 41f889d..6822f53 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -979,17 +979,17 @@
         visRectSrc->left = xDst + (visRectSrc->left-xSrc)*widthDst/widthSrc;
         visRectSrc->top = yDst + (visRectSrc->top-ySrc)*heightDst/heightSrc;
         visRectSrc->right = xDst +
-             ((visRectSrc->right-xSrc) * widthDst + widthSrc-1) / widthSrc;
+                            ((visRectSrc->right-xSrc) * widthDst) / widthSrc;
         visRectSrc->bottom = yDst +
-             ((visRectSrc->bottom-ySrc) * heightDst + heightSrc-1) / heightSrc;
+                         ((visRectSrc->bottom-ySrc) * heightDst) / heightSrc;
         if (!IntersectRect( &tmpRect, visRectSrc, visRectDst )) return FALSE;
         *visRectSrc = *visRectDst = tmpRect;
         visRectSrc->left = xSrc + (visRectSrc->left-xDst)*widthSrc/widthDst;
         visRectSrc->top = ySrc + (visRectSrc->top-yDst)*heightSrc/heightDst;
         visRectSrc->right = xSrc +
-             ((visRectSrc->right-xDst) * widthSrc + widthDst-1) / widthDst;
+                            ((visRectSrc->right-xDst) * widthSrc) / widthDst;
         visRectSrc->bottom = ySrc +
-             ((visRectSrc->bottom-yDst) * heightSrc + heightDst-1) / heightDst;
+                         ((visRectSrc->bottom-yDst) * heightSrc) / heightDst;
         if (IsRectEmpty( visRectSrc )) return FALSE;
     }
     return TRUE;
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 40cb61d..0783036 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -10,6 +10,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include "gdi.h"
+#include "arch.h"
 #include "dc.h"
 #include "bitmap.h"
 #include "stddebug.h"
@@ -203,6 +204,51 @@
 }
 
 
+/**********************************************************************
+ *	    LoadBitmap    (USER.175)
+ */
+HBITMAP LoadBitmap( HANDLE instance, SEGPTR name )
+{
+    HBITMAP hbitmap = 0;
+    HDC hdc;
+    HRSRC hRsrc;
+    HGLOBAL handle;
+    int size;
+    long *lp;
+
+    if (HIWORD(name))
+    {
+        char *str = (char *)PTR_SEG_TO_LIN( name );
+        dprintf_bitmap( stddeb, "LoadBitmap(%04x,'%s')\n", instance, str );
+        if (str[0] == '#') name = (SEGPTR)atoi( str + 1 );
+    }
+    else
+        dprintf_bitmap(stddeb,"LoadBitmap(%04x,%04x)\n",instance,LOWORD(name));
+
+    if (!instance)  /* OEM bitmap */
+    {
+        if (HIWORD((int)name)) return 0;
+        return OBM_LoadBitmap( LOWORD((int)name) );
+    }
+
+    if (!(hRsrc = FindResource( instance, name, RT_BITMAP ))) return 0;
+    if (!(handle = LoadResource( instance, hRsrc ))) return 0;
+
+    lp = (long *)LockResource( handle );
+    size = CONV_LONG(*lp);
+    if ((hdc = GetDC(0)) != 0)
+    {
+        if (size == sizeof(BITMAPCOREHEADER))
+            hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
+        else if (size == sizeof(BITMAPINFOHEADER))
+            hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
+        ReleaseDC( 0, hdc );
+    }
+    FreeResource( handle );
+    return hbitmap;
+}
+
+
 /***********************************************************************
  *           BITMAP_DeleteObject
  */
diff --git a/objects/font.c b/objects/font.c
index 5272b4f..cae64d1 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -164,7 +164,7 @@
       break;
     }
     
-	while (TRUE) {
+    while (TRUE) {
 	    /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
 	    if ( width == 0 )
 	      sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
@@ -180,7 +180,7 @@
                 dprintf_font(stddeb,"*** No match for %s\n", pattern );
                 return NULL;
             }
-        }
+    }
     dprintf_font(stddeb,"        Found '%s'\n", *names );
     fontStruct = XLoadQueryFont( display, *names );
     XFreeFontNames( names );
@@ -600,73 +600,81 @@
 /*************************************************************************
  *				InitFontsList		[internal]
  */
+
+static int logfcmp(const void *a,const void *b) 
+{
+  return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
+}
+
 void InitFontsList(void)
 {
-    char 	str[32];
-    char 	pattern[100];
-    char 	*family, *weight, *charset;
-	char 	**names;
-    char 	slant, spacing;
-    int 	i, count;
-	LPLOGFONT	lpNewFont;
-    weight = "medium";
-    slant = 'r';
-    spacing = '*';
-    charset = "*";
-    family = "*-*";
-    dprintf_font(stddeb,"InitFontsList !\n");
-    sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
-	      family, weight, slant, spacing, charset);
-    names = XListFonts( display, pattern, MAX_FONTS, &count );
-    dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
-	for (i = 0; i < count; i++) {
-		lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
-		if (lpNewFont == NULL) {
-			dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
-			break;
-			}
-		dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
-		ParseFontParms(names[i], 2, str, sizeof(str));
-		if (strcmp(str, "fixed") == 0) strcat(str, "sys");
-		AnsiUpper(str);
-		strcpy(lpNewFont->lfFaceName, str);
-		ParseFontParms(names[i], 7, str, sizeof(str));
-		lpNewFont->lfHeight = atoi(str) / 10;
-		ParseFontParms(names[i], 12, str, sizeof(str));
-		lpNewFont->lfWidth = atoi(str) / 10;
-		lpNewFont->lfEscapement = 0;
-		lpNewFont->lfOrientation = 0;
-		lpNewFont->lfWeight = FW_REGULAR;
-		lpNewFont->lfItalic = 0;
-		lpNewFont->lfUnderline = 0;
-		lpNewFont->lfStrikeOut = 0;
-		ParseFontParms(names[i], 13, str, sizeof(str));
-		if (strcmp(str, "iso8859") == 0)
-			lpNewFont->lfCharSet = ANSI_CHARSET;
-		else
-			lpNewFont->lfCharSet = OEM_CHARSET;
-		lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
-		lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
-		lpNewFont->lfQuality = DEFAULT_QUALITY;
-		ParseFontParms(names[i], 11, str, sizeof(str));
-		switch(str[0]) {
-			case 'p':
-				lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
-				break;
-			case 'm':
-				lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
-				break;
-			default:
-				lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
-				break;
-			}
-		dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
-		dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
-		dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
-		lpLogFontList[i] = lpNewFont;
-		lpLogFontList[i+1] = NULL;
-		}
-    XFreeFontNames(names);
+  char 	str[32];
+  char 	pattern[100];
+  char 	*family, *weight, *charset;
+  char 	**names;
+  char 	slant, spacing;
+  int 	i, count;
+  LPLOGFONT lpNewFont;
+  weight = "medium";
+  slant = 'r';
+  spacing = '*';
+  charset = "*";
+  family = "*-*";
+  dprintf_font(stddeb,"InitFontsList !\n");
+  sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
+	  family, weight, slant, spacing, charset);
+  names = XListFonts( display, pattern, MAX_FONTS, &count );
+  dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
+  for (i = 0; i < count; i++) {
+    lpNewFont = malloc(sizeof(LOGFONT));
+    if (lpNewFont == NULL) {
+      dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
+      break;
+    }
+    dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
+    ParseFontParms(names[i], 2, str, sizeof(str));
+    if (strcmp(str, "fixed") == 0) strcat(str, "sys");
+    AnsiUpper(str);
+    strcpy(lpNewFont->lfFaceName, str);
+    ParseFontParms(names[i], 8, str, sizeof(str));
+    lpNewFont->lfHeight = atoi(str) / 10;
+    ParseFontParms(names[i], 12, str, sizeof(str));
+    lpNewFont->lfWidth = atoi(str) / 10;
+    lpNewFont->lfEscapement = 0;
+    lpNewFont->lfOrientation = 0;
+    lpNewFont->lfWeight = FW_REGULAR;
+    lpNewFont->lfItalic = 0;
+    lpNewFont->lfUnderline = 0;
+    lpNewFont->lfStrikeOut = 0;
+    ParseFontParms(names[i], 13, str, sizeof(str));
+    if (strcmp(str, "iso8859") == 0)  {
+      lpNewFont->lfCharSet = ANSI_CHARSET;
+    } else  {
+      lpNewFont->lfCharSet = OEM_CHARSET;
+    }
+    lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+    lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+    lpNewFont->lfQuality = DEFAULT_QUALITY;
+    ParseFontParms(names[i], 11, str, sizeof(str));
+    switch(str[0]) {
+     case 'p':
+      lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
+      break;
+     case 'm':
+      lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
+      break;
+     default:
+      lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+      break;
+    }
+    dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
+    dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
+    dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
+    lpLogFontList[i] = lpNewFont;
+    lpLogFontList[i+1] = NULL;
+  }
+  qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
+  XFreeFontNames(names);
 }
 
 
@@ -675,79 +683,67 @@
  */
 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
 {
-	HANDLE			hLog;
-	HANDLE			hMet;
-	HFONT			hFont;
-	HFONT			hOldFont;
-	LPLOGFONT		lpLogFont;
-	LPTEXTMETRIC	lptm;
-	LPSTR			lpFaceList[MAX_FONTS];
-	char			FaceName[LF_FACESIZE];
-	int				nRet;
-	int				j, i = 0;
-
-	dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %p, %p)\n", 
-		hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
-	if (lpEnumFunc == NULL) return 0;
-	hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
-	lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
-	if (lpLogFont == NULL) {
-		dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
-		return 0;
-		}
-	hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
-	lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
-	if (lptm == NULL) {
-		GDI_HEAP_FREE(hLog);
-		dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
-		return 0;
-		}
-	if (lpFaceName != NULL) {
-		strcpy(FaceName, lpFaceName);
-		AnsiUpper(FaceName);
-		}
-	if (lpLogFontList[0] == NULL) InitFontsList();
-	memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
-	while (TRUE) {
-		if (lpLogFontList[i] == NULL) break;
-		if (lpFaceName == NULL) {
-			for (j = 0; j < MAX_FONTS; j++)	{
-				if (lpFaceList[j] == NULL) break;
-				if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
-					i++; j = 0;
-					if (lpLogFontList[i] == NULL) break;
-					}
-				}
-			if (lpLogFontList[i] == NULL) break;
-			lpFaceList[j] = lpLogFontList[i]->lfFaceName;
-			dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
-			}
-		else {
-			while(lpLogFontList[i] != NULL) {
-				if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
-				i++;
-				}
-			if (lpLogFontList[i] == NULL) break;
-			}
-		memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
-		hFont = CreateFontIndirect(lpLogFont);
-		hOldFont = SelectObject(hDC, hFont);
-		GetTextMetrics(hDC, lptm);
-		SelectObject(hDC, hOldFont);
-		DeleteObject(hFont);
-		dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-                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;
-			}
-		}
-	GDI_HEAP_FREE(hMet);
-	GDI_HEAP_FREE(hLog);
-	return 0;
+  HANDLE       hLog;
+  HANDLE       hMet;
+  HFONT	       hFont;
+  HFONT	       hOldFont;
+  LPLOGFONT    lpLogFont;
+  LPTEXTMETRIC lptm;
+  LPSTR	       lpOldName;
+  char	       FaceName[LF_FACESIZE];
+  int          nRet;
+  int          i;
+  
+  dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %p, %p)\n", 
+	       hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
+  if (lpEnumFunc == NULL) return 0;
+  hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
+  lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
+  if (lpLogFont == NULL) {
+    fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
+    return 0;
+  }
+  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
+  lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
+  if (lptm == NULL) {
+    GDI_HEAP_FREE(hLog);
+    fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
+    return 0;
+  }
+  if (lpFaceName != NULL) {
+    strcpy(FaceName, lpFaceName);
+    AnsiUpper(FaceName);
+  } 
+  lpOldName = NULL;
+  
+  if (lpLogFontList[0] == NULL) InitFontsList();
+  for(i = 0; lpLogFontList[i] != NULL; i++) {
+    if (lpFaceName == NULL) {
+      if (lpOldName != NULL) {
+	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
+      }
+      lpOldName = lpLogFontList[i]->lfFaceName;
+    } else {
+      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
+    }
+    dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
+    memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
+    hFont = CreateFontIndirect(lpLogFont);
+    hOldFont = SelectObject(hDC, hFont);
+    GetTextMetrics(hDC, lptm);
+    SelectObject(hDC, hOldFont);
+    DeleteObject(hFont);
+    dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
+    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;
+    }
+  }
+  GDI_HEAP_FREE(hMet);
+  GDI_HEAP_FREE(hLog);
+  return nRet;
 }
 
 
@@ -756,81 +752,70 @@
  */
 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
 {
-	HANDLE			hLog;
-	HANDLE			hMet;
-	HFONT			hFont;
-	HFONT			hOldFont;
-	LPLOGFONT		lpLogFont;
-	LPTEXTMETRIC	lptm;
-	LPSTR			lpFaceList[MAX_FONTS];
-	char			FaceName[LF_FACESIZE];
-	int				nRet;
-	int				j, i = 0;
-
-	dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %p, %p)\n", 
-					hDC, lpszFamily, lpEnumFunc, lpData);
-	if (lpEnumFunc == NULL) return 0;
-	hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
-	lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
-	if (lpLogFont == NULL) {
-		dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
-		return 0;
-		}
-	hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
-	lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
-	if (lptm == NULL) {
-		GDI_HEAP_FREE(hLog);
-		dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
-		return 0;
-		}
-	if (lpszFamily != NULL) {
-		strcpy(FaceName, lpszFamily);
-		AnsiUpper(FaceName);
-		}
-	if (lpLogFontList[0] == NULL) InitFontsList();
-	memset(lpFaceList, 0, MAX_FONTS * sizeof(LPSTR));
-	while (TRUE) {
-		if (lpLogFontList[i] == NULL) break;
-		if (lpszFamily == NULL) {
-			if (lpLogFontList[i] == NULL) break;
-			for (j = 0; j < MAX_FONTS; j++)	{
-				if (lpFaceList[j] == NULL) break;
-				if (lpLogFontList[i] == NULL) break;
-				if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
-					i++; j = 0;
-					}
-				}
-			if (lpLogFontList[i] == NULL) break;
-			lpFaceList[j] = lpLogFontList[i]->lfFaceName;
-			dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
-			}
-		else {
-			while(lpLogFontList[i] != NULL) {
-				if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) == 0) break;
-				i++;
-				}
-			if (lpLogFontList[i] == NULL) break;
-			}
-		memcpy(lpLogFont, lpLogFontList[i++], sizeof(LOGFONT) + LF_FACESIZE);
-		hFont = CreateFontIndirect(lpLogFont);
-		hOldFont = SelectObject(hDC, hFont);
-		GetTextMetrics(hDC, lptm);
-		SelectObject(hDC, hOldFont);
-		DeleteObject(hFont);
-		dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-
-                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;
-			}
-		}
-	GDI_HEAP_FREE(hMet);
-	GDI_HEAP_FREE(hLog);
-	return 0;
+  HANDLE       	hLog;
+  HANDLE       	hMet;
+  HFONT	       	hFont;
+  HFONT	       	hOldFont;
+  LPENUMLOGFONT lpEnumLogFont;
+  LPTEXTMETRIC	lptm;
+  LPSTR	       	lpOldName;
+  char	       	FaceName[LF_FACESIZE];
+  int	       	nRet;
+  int	       	i;
+  
+  dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %p, %p)\n", 
+	       hDC, lpszFamily, lpEnumFunc, lpData);
+  if (lpEnumFunc == NULL) return 0;
+  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
+  lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
+  if (lpEnumLogFont == NULL) {
+    fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
+    return 0;
+  }
+  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
+  lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
+  if (lptm == NULL) {
+    GDI_HEAP_FREE(hLog);
+    fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
+    return 0;
+  }
+  lpOldName = NULL;
+  if (lpszFamily != NULL) {
+    strcpy(FaceName, lpszFamily);
+    AnsiUpper(FaceName);
+  }
+  if (lpLogFontList[0] == NULL) InitFontsList();
+  for(i = 0; lpLogFontList[i] != NULL; i++) {
+    if (lpszFamily == NULL) {
+      if (lpOldName != NULL) {
+	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
+      }
+      lpOldName = lpLogFontList[i]->lfFaceName;
+    } else {
+      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
+    }
+    memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
+    strcpy(lpEnumLogFont->elfFullName,"");
+    strcpy(lpEnumLogFont->elfStyle,"");
+    hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
+    hOldFont = SelectObject(hDC, hFont);
+    GetTextMetrics(hDC, lptm);
+    SelectObject(hDC, hOldFont);
+    DeleteObject(hFont);
+    dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
+    
+    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;
+    }
+  }
+  GDI_HEAP_FREE(hMet);
+  GDI_HEAP_FREE(hLog);
+  return nRet;
 }
 
 /*************************************************************************
diff --git a/tools/build-spec.txt b/tools/build-spec.txt
index af4c7fa..141a066 100644
--- a/tools/build-spec.txt
+++ b/tools/build-spec.txt
@@ -1,11 +1,12 @@
 name	NAME
 id	ID_NUMBER
-length	NUMBER_OF_ORDINALS
 
 ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]])
 
 ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME
 
+ORDINAL stub EXPORTNAME
+
 ORDINAL equate EXPORTNAME DATA
 
 ORDINAL return EXPORTNAME ARGLENGTH RETVALUE
@@ -15,10 +16,9 @@
 --------------------
 General:
 
-    "name", "id" and "length" fields are mandatory.  Specific ordinal 
-declarations are optional, but the default handler will print an
-error message.  Lines whose first character is a '#' will be ignored
-as comments.
+    "name" and "id" fields are mandatory.  Specific ordinal declarations
+are optional, but the default handler will print an error message.  Lines
+whose first character is a '#' will be ignored as comments.
 
 Variable ordinals:
 
@@ -57,6 +57,12 @@
 
 	100 pascal GetFocus() WIN_GetFocus()
 
+Stub ordinals:
+
+    This type defines a stub function. It makes the name and ordinal
+available for dynamic linking, but will terminate execution with an
+error message if the function is ever called.
+
 Equate ordinals:
 
     This type defines an ordinal as an absolute value.
diff --git a/tools/build.c b/tools/build.c
index 6c1d179..ef0b2b6 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -8,6 +8,8 @@
 #include <string.h>
 #include <ctype.h>
 #include "wine.h"
+#include "module.h"
+#include "neexe.h"
 
 /* ELF symbols do not have an underscore in front */
 #ifdef __ELF__
@@ -25,9 +27,13 @@
 #define TYPE_REGISTER    6
 #define TYPE_ABS         7
 #define TYPE_RETURN      8
+#define TYPE_STUB        9
 
 #define MAX_ORDINALS	1299
 
+  /* Callback function used for stub functions */
+#define STUB_CALLBACK  "RELAY_Unimplemented"
+
 typedef struct ordinal_definition_s
 {
     int type;
@@ -59,7 +65,7 @@
 
 char LowerDLLName[80];
 char UpperDLLName[80];
-int Limit;
+int Limit = 0;
 int DLLId;
 FILE *SpecFp;
 
@@ -122,7 +128,7 @@
     for (p = ParseNext; isspace(*p); p++)
 	;
     
-    if (*p == '\0')
+    if ((*p == '\0') || (*p == '#'))
 	return NULL;
     
     /*
@@ -234,7 +240,7 @@
     odp = &OrdinalDefinitions[ordinal];
     odp->type = type;
     strcpy(odp->export_name, export_name);
-    
+
     vdp = malloc(sizeof(*vdp));
     odp->additional_data = vdp;
     
@@ -251,12 +257,6 @@
     ORDFUNCDEF *fdp;
     int i;
     
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
     odp = &OrdinalDefinitions[ordinal];
     strcpy(odp->export_name, GetToken());
     odp->type = type;
@@ -309,12 +309,6 @@
     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());
 
@@ -340,12 +334,6 @@
     char *token;
     char *endptr;
     
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-
     rdp = malloc(sizeof(*rdp));
     
     odp = &OrdinalDefinitions[ordinal];
@@ -374,10 +362,34 @@
     return 0;
 }
 
+
+static int ParseStub( int ordinal )
+{
+    ORDDEF *odp;
+    ORDFUNCDEF *fdp;
+    
+    odp = &OrdinalDefinitions[ordinal];
+    strcpy( odp->export_name, GetToken() );
+    odp->type = TYPE_STUB;
+    fdp = malloc(sizeof(*fdp));
+    odp->additional_data = fdp;
+    fdp->arg_types[0] = '\0';
+    strcpy( fdp->internal_name, STUB_CALLBACK );
+    return 0;
+}
+
+
 static int ParseOrdinal(int ordinal)
 {
     char *token;
     
+    if (ordinal >= MAX_ORDINALS)
+    {
+	fprintf(stderr, "%d: Ordinal number too large\n", Line);
+	exit(1);
+    }
+    if (ordinal > Limit) Limit = ordinal;
+
     token = GetToken();
     if (token == NULL)
     {
@@ -403,6 +415,8 @@
 	return ParseEquate(ordinal);
     else if (strcmp(token, "return") == 0)
 	return ParseReturn(ordinal);
+    else if (strcmp(token, "stub") == 0)
+	return ParseStub(ordinal);
     else
     {
 	fprintf(stderr, 
@@ -437,17 +451,6 @@
 	    
 	    DLLId = atoi(token);
 	}
-	else if (strcmp(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;
@@ -493,6 +496,202 @@
     return vdp->n_values;
 }
 
+
+/*******************************************************************
+ *         BuildModule
+ *
+ * Build the in-memory representation of the module, and dump it
+ * as a byte stream into the assembly code.
+ */
+static void BuildModule( FILE *fp, int max_code_offset, int max_data_offset )
+{
+    ORDDEF *odp;
+    int i, size;
+    char *buffer;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegment;
+    LOADEDFILEINFO *pFileInfo;
+    BYTE *pstr, *bundle;
+    WORD *pword;
+
+    /*   Module layout:
+     * NE_MODULE       Module
+     * LOADEDFILEINFO  File information
+     * SEGTABLEENTRY   Segment 1 (code)
+     * SEGTABLEENTRY   Segment 2 (data)
+     * WORD[2]         Resource table (empty)
+     * BYTE[2]         Imported names (empty)
+     * BYTE[n]         Resident names table
+     * BYTE[n]         Entry table
+     */
+
+    buffer = malloc( 0x10000 );
+
+    pModule = (NE_MODULE *)buffer;
+    pModule->magic = NE_SIGNATURE;
+    pModule->count = 1;
+    pModule->next = 0;
+    pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE;
+    pModule->dgroup = 2;
+    pModule->heap_size = 0xffff;
+    pModule->stack_size = 0;
+    pModule->ip = 0;
+    pModule->cs = 0;
+    pModule->sp = 0;
+    pModule->ss = 0;
+    pModule->seg_count = 2;
+    pModule->modref_count = 0;
+    pModule->nrname_size = 0;
+    pModule->modref_table = 0;
+    pModule->nrname_fpos = 0;
+    pModule->moveable_entries = 0;
+    pModule->alignment = 0;
+    pModule->truetype = 0;
+    pModule->os_flags = NE_OSFLAGS_WINDOWS;
+    pModule->misc_flags = 0;
+    pModule->reserved = 0;
+    pModule->nrname_handle = 0;
+    pModule->min_swap_area = 0;
+    pModule->expected_version = 0x030a;
+
+      /* File information */
+
+    pFileInfo = (LOADEDFILEINFO *)(pModule + 1);
+    pModule->fileinfo = (int)pFileInfo - (int)pModule;
+    pFileInfo->length = sizeof(LOADEDFILEINFO) + strlen(UpperDLLName) + 3;
+    pFileInfo->fixed_media = 0;
+    pFileInfo->error = 0;
+    pFileInfo->date = 0;
+    pFileInfo->time = 0;
+    sprintf( pFileInfo->filename, "%s.DLL", UpperDLLName );
+    pstr = (char *)pFileInfo + pFileInfo->length + 1;
+        
+      /* Segment table */
+
+    pSegment = (SEGTABLEENTRY *)pstr;
+    pModule->seg_table = (int)pSegment - (int)pModule;
+    pSegment->filepos = 0;
+    pSegment->size = max_code_offset;
+    pSegment->flags = 0;
+    pSegment->minsize = max_code_offset;
+    pSegment->selector = 0;
+    pSegment++;
+
+    pModule->dgroup_entry = (int)pSegment - (int)pModule;
+    pSegment->filepos = 0;
+    pSegment->size = max_data_offset;
+    pSegment->flags = NE_SEGFLAGS_DATA;
+    pSegment->minsize = max_data_offset;
+    pSegment->selector = 0;
+    pSegment++;
+
+      /* Resource table */
+
+    pword = (WORD *)pSegment;
+    pModule->res_table = (int)pword - (int)pModule;
+    *pword++ = 0;
+    *pword++ = 0;
+
+      /* Imported names table */
+
+    pstr = (char *)pword;
+    pModule->import_table = (int)pstr - (int)pModule;
+    *pstr++ = 0;
+    *pstr++ = 0;
+
+      /* Resident names table */
+
+    pModule->name_table = (int)pstr - (int)pModule;
+    /* First entry is module name */
+    *pstr = strlen(UpperDLLName );
+    strcpy( pstr + 1, UpperDLLName );
+    pstr += *pstr + 1;
+    *(WORD *)pstr = 0;
+    pstr += sizeof(WORD);
+    /* Store all ordinals */
+    odp = OrdinalDefinitions + 1;
+    for (i = 1; i <= Limit; i++, odp++)
+    {
+        if (!odp->export_name[0]) continue;
+        *pstr = strlen( odp->export_name );
+        strcpy( pstr + 1, odp->export_name );
+        strupper( pstr + 1 );
+        pstr += *pstr + 1;
+        *(WORD *)pstr = i;
+        pstr += sizeof(WORD);
+    }
+    *pstr++ = 0;
+
+      /* Entry table */
+
+    pModule->entry_table = (int)pstr - (int)pModule;
+    bundle = NULL;
+    odp = OrdinalDefinitions + 1;
+    for (i = 1; i <= Limit; i++, odp++)
+    {
+        int selector = 0;
+
+	switch (odp->type)
+	{
+        case TYPE_INVALID:
+            selector = 0;  /* Invalid selector */
+            break;
+
+        case TYPE_PASCAL:
+        case TYPE_PASCAL_16:
+        case TYPE_REGISTER:
+        case TYPE_RETURN:
+        case TYPE_STUB:
+            selector = 1;  /* Code selector */
+            break;
+
+        case TYPE_BYTE:
+        case TYPE_WORD:
+        case TYPE_LONG:
+            selector = 2;  /* Data selector */
+            break;
+
+        case TYPE_ABS:
+            selector = 0xfe;  /* Constant selector */
+            break;
+        }
+
+          /* create a new bundle if necessary */
+        if (!bundle || (bundle[0] >= 254) || (bundle[1] != selector))
+        {
+            bundle = pstr;
+            bundle[0] = 0;
+            bundle[1] = selector;
+            pstr += 2;
+        }
+
+        (*bundle)++;
+        if (selector != 0)
+        {
+            *pstr++ = 1;
+            *(WORD *)pstr = odp->offset;
+            pstr += sizeof(WORD);
+        }
+    }
+    *pstr++ = 0;
+
+      /* Dump the module content */
+
+    fprintf( fp, "\t.data\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Module_Start\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Module_Start:\n", UpperDLLName );
+    size = (int)pstr - (int)pModule;
+    for (i = 0, pstr = buffer; i < size; i++, pstr++)
+    {
+        if (!(i & 7)) fprintf( fp, "\t.byte " );
+        fprintf( fp, "%d%c", *pstr, ((i & 7) != 7) ? ',' : '\n' );
+    }
+    if (i & 7) fprintf( fp, "0\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Module_End\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Module_End:\n", UpperDLLName );
+}
+
+
 static void BuildSpecFiles( char *specname)
 {
     ORDDEF *odp;
@@ -518,10 +717,12 @@
     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.word 0,0,0,0,0,0,0,0\n" );
+    data_offset = 16;
     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;
+    code_offset = 0;
 
     odp = OrdinalDefinitions;
     for (i = 0; i <= Limit; i++, odp++)
@@ -532,14 +733,7 @@
         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 */
+            odp->offset = 0xffff;
             break;
 
           case TYPE_ABS:
@@ -581,6 +775,7 @@
           case TYPE_REGISTER:
           case TYPE_PASCAL:
           case TYPE_PASCAL_16:
+          case TYPE_STUB:
             fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
             fprintf(fp, "\tpushw %%bp\n" );
             fprintf(fp, "\tpushl $0x%08x\n", (DLLId << 16) | i);
@@ -600,12 +795,13 @@
 	}
     }
 
-    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 );
+    if (!code_offset)  /* Make sure the code segment is not empty */
+    {
+        fprintf( fp, "\t.byte 0\n" );
+        code_offset++;
+    }
+
+    BuildModule( fp, code_offset, data_offset );
 
     fclose(fp);
 
@@ -619,16 +815,19 @@
     odp = OrdinalDefinitions;
     for (i = 0; i <= Limit; i++, odp++)
     {
-        int selector;
-
-	fdp = odp->additional_data;
+        int selector = 0;
 
 	switch (odp->type)
 	{
         case TYPE_INVALID:
+            selector = 0;  /* Invalid selector */
+            break;
+
         case TYPE_PASCAL:
         case TYPE_PASCAL_16:
         case TYPE_REGISTER:
+        case TYPE_RETURN:
+        case TYPE_STUB:
             selector = 1;  /* Code selector */
             break;
 
@@ -643,7 +842,8 @@
             break;
         }
 
-        fprintf(fp, "    { %d, %d, ", selector, odp->offset );
+/*         fprintf(fp, "    { %d, %d, ", selector, odp->offset ); */
+        fprintf( fp, "    { " );
         fprintf(fp, "\"%s\" ", odp->export_name);
 #ifdef WINESTAT
         fprintf(fp, ",0 ");
@@ -653,16 +853,16 @@
 
     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, "extern BYTE %s_Code_Start[];\n", UpperDLLName );
+    fprintf( fp, "extern BYTE %s_Data_Start[];\n", UpperDLLName );
+    fprintf( fp, "extern BYTE %s_Module_Start[];\n", UpperDLLName );
+    fprintf( fp, "extern BYTE %s_Module_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",
+    fprintf( fp, "  %s_Code_Start, %s_Data_Start,\n",
              UpperDLLName, UpperDLLName );
-    fprintf( fp, "  (void *)%s_Data_Start, (void *)%s_Data_End\n};\n",
+    fprintf( fp, "  %s_Module_Start, %s_Module_End\n};\n",
              UpperDLLName, UpperDLLName );
     fclose(fp);
 }
@@ -771,7 +971,8 @@
     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( "\tpushw %%es\n" );
+    printf( "\tpopw %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" );
@@ -800,7 +1001,8 @@
     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( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_es) );
+    printf( "\tpopw %%es\n" );
     printf( "\tpopw %%ax\n" );  /* Remove old ds from the stack */
     printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_ds) ); /* Push new ds */
 #ifndef __FreeBSD__
@@ -855,7 +1057,7 @@
     printf( " * " PREFIX "CallTo32_%s\n", profile );
     printf( " **********/\n" );
     printf( "\t.align 4\n" );
-    printf( "\t.global " PREFIX "CallTo32_%s\n\n", profile );
+    printf( "\t.globl " PREFIX "CallTo32_%s\n\n", profile );
     printf( PREFIX "CallTo32_%s:\n", profile );
 
     /* Setup bp to point to its copy on the stack */
@@ -874,12 +1076,10 @@
 
     /* 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 */
 
@@ -900,7 +1100,12 @@
     printf( "\tpushw %%ds\n" );
     printf( "\tpopw %%ss\n" );
     printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
-    printf( "\tmovl " PREFIX "IF1632_Saved32_ebp,%%ebp\n" );
+
+    /* Setup %ebp to point to the previous stack frame (built by CallTo16) */
+
+    printf( "\tmovl %%esp,%%ebp\n" );
+    printf( "\taddl $24,%%ebp\n" );
+
     if (reg_func)
         printf( "\tsubl $%d,%%esp\n", sizeof(struct sigcontext_struct) );
     else if (*args)
@@ -937,16 +1142,12 @@
 
     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" );
+        /* Restore registers from the context structure */
         RestoreContext();
     }
     else  /* Store the return value in dx:ax if needed */
@@ -962,7 +1163,8 @@
     /* Restore ds and bp */
 
     printf( "\tpopw %%ds\n" );
-    printf( "\tmovw %%bp,%%sp\n" );
+    printf( "\tpopl %%ebp\n" );  /* Remove entry point address */
+    printf( "\tpopl %%ebp\n" );  /* Remove DLL id and ordinal */
     printf( "\tpopw %%bp\n" );
 
     /* Remove the arguments and return */
@@ -987,10 +1189,10 @@
  *
  * Stack frame of the callback function:
  *  ...      ...
- * (ebp+22) arg2
- * (ebp+18) arg1
- * (ebp+14) 16-bit ds
- * (ebp+10) func to call
+ * (ebp+24) arg2
+ * (ebp+20) arg1
+ * (ebp+16) 16-bit ds
+ * (ebp+12) func to call
  * (ebp+8)  code selector
  * (ebp+4)  return address
  * (ebp)    previous ebp
@@ -998,8 +1200,9 @@
  * 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 );
+ *   extern void CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD bp,
+ *                               WORD ax, WORD bx, WORD cx, WORD dx,
+ *                               WORD si, WORD di );
  */
 static void BuildCall16Func( char *profile )
 {
@@ -1021,13 +1224,13 @@
     printf( " * " PREFIX "CallTo16_%s\n", profile );
     printf( " **********/\n" );
     printf( "\t.align 4\n" );
-    printf( "\t.global " PREFIX "CallTo16_%s\n\n", profile );
+    printf( "\t.globl " 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 $0x%04x\n", WINE_CODE_SELECTOR );
     printf( "\tpushl %%eax\n" );
 
     /* Entry code */
@@ -1046,9 +1249,7 @@
     /* 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 */
@@ -1057,7 +1258,7 @@
     {
         /* Push the address of the first argument */
         printf( "\tmovl %%ebx,%%eax\n" );
-        printf( "\taddl $10,%%eax\n" );
+        printf( "\taddl $12,%%eax\n" );
         printf( "\tpushl $%d\n", reg_func ? 7 : strlen(args) );
         printf( "\tpushl %%eax\n" );
         printf( "\tcall " PREFIX "RELAY_DebugCall16\n" );
@@ -1069,23 +1270,29 @@
 
     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" );
+        printf( "\tpushw 20(%%ebx)\n" );
+        printf( "\tpopw %%es\n" );
+        printf( "\tmovl 24(%%ebx),%%ebp\n" );
+        printf( "\tmovl 28(%%ebx),%%eax\n" );
+        printf( "\tmovl 36(%%ebx),%%ecx\n" );
+        printf( "\tmovl 40(%%ebx),%%edx\n" );
+        printf( "\tmovl 44(%%ebx),%%esi\n" );
+        printf( "\tmovl 48(%%ebx),%%edi\n" );
     }
     else  /* not a register function */
     {
-        int pos = 18;  /* first argument position */
+        int pos = 20;  /* first argument position */
+
+        /* Make %bp point to the previous stackframe (built by CallTo32) */
+        printf( "\tmovw %%sp,%%bp\n" );
+        printf( "\taddw $16,%%bp\n" );
+
         while (*args)
         {
             switch(*args++)
@@ -1108,17 +1315,18 @@
 
     /* Push the called routine address */
 
-    printf( "\tpushl 10(%%ebx)\n" );
+    printf( "\tpushl 12(%%ebx)\n" );
 
     /* Get the 16-bit ds */
     /* FIXME: this shouldn't be necessary if function prologs fixup worked. */
 
-    printf( "\tmovw 14(%%ebx),%%ds\n" );
+    printf( "\tpushw 16(%%ebx)\n" );
+    printf( "\tpopw %%ds\n" );
 
     if (reg_func)
     {
         /* Retrieve ebx from the 32-bit stack */
-        printf( "\tmovl %%fs:26(%%ebx),%%ebx\n" );
+        printf( "\tmovl %%fs:28(%%ebx),%%ebx\n" );
     }
     else
     {
@@ -1161,8 +1369,6 @@
     /* 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 */
@@ -1175,7 +1381,6 @@
 
     /* Return to caller */
 
-    printf( "\tmovl %%ebp,%%esp\n" );
     printf( "\tpopl %%ebp\n" );
     printf( "\tlret\n" );
 
diff --git a/windows/Imakefile b/windows/Imakefile
index 6d5ca0d..47e6796 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -20,6 +20,7 @@
 	message.c \
 	nonclient.c \
 	painting.c \
+	property.c \
 	scroll.c \
 	syscolor.c \
 	sysmetrics.c \
diff --git a/windows/class.c b/windows/class.c
index fc7a4b5..6ce7cc6 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -258,43 +258,44 @@
     CLASS *classPtr;
 
     /* FIXME: We have the find the correct hInstance */
-    dprintf_class(stddeb,"GetClassName(%x,%p,%d\n)",hwnd,lpClassName,maxCount);
+    dprintf_class(stddeb,"GetClassName(%x,%p,%d)\n",hwnd,lpClassName,maxCount);
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
     if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
-
-    return (GetAtomName(classPtr->atomName, lpClassName, maxCount));
+    
+    return GlobalGetAtomName(classPtr->atomName, lpClassName, maxCount);
 }
 
 
 /***********************************************************************
  *           GetClassInfo      (USER.404)
  */
-BOOL GetClassInfo(HANDLE hInstance, LPSTR lpClassName, 
+BOOL GetClassInfo(HANDLE hInstance, SEGPTR ClassName, 
 		                    LPWNDCLASS lpWndClass)
 {
     CLASS *classPtr;
-
-    if (HIWORD(lpClassName))
-    {
-        dprintf_class(stddeb, "GetClassInfo   hInstance=%04x  lpClassName=%s\n",
-            hInstance, lpClassName);
+    LPSTR lpClassName = 0;
+    char  temp[10];
+    if (HIWORD(ClassName)) {
+      lpClassName = PTR_SEG_TO_LIN(ClassName);
+    } else  {
+      sprintf(temp,"#%d",(int)LOWORD(ClassName));
+      lpClassName = temp;
     }
-    else
-       dprintf_class(stddeb, "GetClassInfo   hInstance=%04x  lpClassName=#%d\n",
-            hInstance, (int)lpClassName);    
+    dprintf_class(stddeb, "GetClassInfo   hInstance=%04x  lpClassName=%s\n",
+		  hInstance, lpClassName);
 
 
     /* if (!(CLASS_FindClassByName(lpClassName, &classPtr))) return FALSE; */
     if (!(CLASS_FindClassByName(lpClassName, hInstance, &classPtr)))
     {
-        if (!HIWORD(lpClassName))
+/*        if (!HIWORD(lpClassName))
         {
             char temp[10];
             sprintf(temp, "#%d", (int)lpClassName);
-            if (!(CLASS_FindClassByName(temp, hInstance, &classPtr))) return FALSE;        
-    
+            if (!(CLASS_FindClassByName(temp, hInstance, &classPtr))) return FALSE;
+
         }
-        else return FALSE;
+        else */return FALSE;
     }
 
     if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
diff --git a/windows/cursor.c b/windows/cursor.c
index fb13b6d..509fbf4 100644
--- a/windows/cursor.c
+++ b/windows/cursor.c
@@ -54,6 +54,7 @@
 HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 {
     HCURSOR 	hCursor;
+    HRSRC       hRsrc;
     HANDLE 	rsc_mem;
     WORD 	*lp;
     LONG        *lpl,size;
@@ -125,16 +126,20 @@
 #endif
 
     if (!(hdc = GetDC(0))) return 0;
-    rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
-			       &image_size);
+    if (!(hRsrc = FindResource( instance, cursor_name, RT_GROUP_CURSOR )))
+    {
+	ReleaseDC(0, hdc); 
+	return 0;
+    }
+    rsc_mem = LoadResource(instance, hRsrc );
     if (rsc_mem == (HANDLE)NULL) {
     fprintf(stderr,"LoadCursor / Cursor %08lx not Found !\n", cursor_name);
 	ReleaseDC(0, hdc); 
 	return 0;
 	}
-    lp = (WORD *)GlobalLock(rsc_mem);
+    lp = (WORD *)LockResource(rsc_mem);
     if (lp == NULL) {
-	GlobalFree(rsc_mem);
+        FreeResource( rsc_mem );
 	ReleaseDC(0, hdc); 
 	return 0;
 	}
@@ -158,23 +163,22 @@
 		(DWORD)lpcurdesc->curDIBOffset);
 #endif
     lpcur->descriptor = *lpcurdesc;
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
-    rsc_mem = RSC_LoadResource(instance, 
-    	MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
-    	NE_RSCTYPE_CURSOR, &image_size);
+    FreeResource( rsc_mem );
+    if (!(hRsrc = FindResource( instance,
+                                MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
+                                RT_CURSOR )))
+    {
+	ReleaseDC(0, hdc); 
+	return 0;
+    }
+    rsc_mem = LoadResource(instance, hRsrc );
     if (rsc_mem == (HANDLE)NULL) {
     	fprintf(stderr,
 		"LoadCursor / Cursor %08lx Bitmap not Found !\n", cursor_name);
 	ReleaseDC(0, hdc); 
 	return 0;
 	}
-    lpl = (LONG *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	ReleaseDC(0, hdc); 
-	return 0;
-    }
+    lpl = (LONG *)LockResource(rsc_mem);
     lpl++;
     size = CONV_LONG (*lpl);
     if (size == sizeof(BITMAPCOREHEADER)){
@@ -220,8 +224,7 @@
 	lpcur->descriptor.Height/2,
 	(LPSTR)lpl, ((LPSTR)lpl)+size);
 
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
+    FreeResource( rsc_mem );
     GlobalUnlock(hCursor);
     ReleaseDC(0,hdc);
     return hCursor;
diff --git a/windows/dialog.c b/windows/dialog.c
index 479592f..aef8c7c 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -187,16 +187,15 @@
 		        HWND owner, WNDPROC dlgProc, LPARAM param )
 {
     HWND hwnd = 0;
-    HANDLE hres, hmem;
+    HRSRC hRsrc;
+    HGLOBAL hmem;
     LPCSTR data;
 
     dprintf_dialog(stddeb, "CreateDialogParam: %d,%08lx,%d,%p,%ld\n",
 	    hInst, dlgTemplate, owner, dlgProc, param );
      
-      /* FIXME: MAKEINTRESOURCE should be replaced by RT_DIALOG */
-    if (!(hres = FindResource( hInst, dlgTemplate, MAKEINTRESOURCE(0x8005) )))
-	return 0;
-    if (!(hmem = LoadResource( hInst, hres ))) return 0;
+    if (!(hRsrc = FindResource( hInst, dlgTemplate, RT_DIALOG ))) return 0;
+    if (!(hmem = LoadResource( hInst, hRsrc ))) return 0;
     if (!(data = LockResource( hmem ))) hwnd = 0;
     else hwnd = CreateDialogIndirectParam(hInst, data, owner, dlgProc, param);
     FreeResource( hmem );
diff --git a/windows/hook.c b/windows/hook.c
index e91a22b..2110dd9 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -12,7 +12,6 @@
 #include "hook.h"
 #include "user.h"
 
-
 HHOOK systemHooks[LAST_HOOK-FIRST_HOOK+1] = { 0, };
 
   /* Task-specific hooks should probably be in the task structure */
@@ -23,18 +22,49 @@
 /***********************************************************************
  *           SetWindowsHook   (USER.121)
  */
-HHOOK SetWindowsHook( short id, HOOKPROC proc )
+FARPROC SetWindowsHook( short id, HOOKPROC proc )
 {
-    return SetWindowsHookEx( id, proc, 0, 0 );
+  HHOOK hhook = SetWindowsHookEx( id, proc, 0, 0 );
+  HOOKDATA *data = PTR_SEG_TO_LIN(hhook);
+  if (data != NULL)  {
+    data = PTR_SEG_TO_LIN(data->next);
+    if (data != NULL)  {
+      return data->proc;
+    }
+  }
+  return 0;
 }
 
 
 /***********************************************************************
  *           UnhookWindowsHook   (USER.234)
  */
-BOOL UnhookWindowsHook( short id, HHOOK hhook )
+BOOL UnhookWindowsHook( short id, FARPROC hproc )
 {
-    return UnhookWindowsHookEx( hhook );
+  HHOOK *prevHook,hhook;
+  
+  prevHook = &TASK_HOOK(id);
+  while (*prevHook)  {
+    HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(*prevHook);
+
+    if (data->proc == hproc) {
+      hhook = *prevHook;
+      *prevHook = data->next;
+      USER_HEAP_FREE(LOWORD(hhook));
+      return TRUE;
+    }
+  }
+  prevHook = &SYSTEM_HOOK(id);
+  while (*prevHook) {
+    HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(*prevHook);
+    if (data->proc == hproc) {
+      hhook = *prevHook;
+      *prevHook = data->next;
+      USER_HEAP_FREE(LOWORD(hhook));
+      return TRUE;
+    }
+  }
+  return FALSE;
 }
 
 
@@ -101,8 +131,9 @@
 
     if (!data) return FALSE;
     prevHook = data->htask ? &TASK_HOOK(data->id) : &SYSTEM_HOOK(data->id);
-    while (*prevHook && (*prevHook != hhook))
+    while (*prevHook && (*prevHook != hhook)) {    
 	prevHook = &((HOOKDATA *)*prevHook)->next;
+    }
     if (!*prevHook) return FALSE;
     *prevHook = data->next;
     USER_HEAP_FREE( hhook & 0xffff );
diff --git a/windows/message.c b/windows/message.c
index 279b320..4d18594 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -38,10 +38,6 @@
 static HANDLE hmemSysMsgQueue = 0;
 static MESSAGEQUEUE * sysMsgQueue = NULL;
 
-  /* Application message queue (should be a list, one queue per task) */
-static HANDLE hmemAppMsgQueue = 0;
-static MESSAGEQUEUE * appMsgQueue = NULL;
-
   /* Double-click time */
 static int doubleClickSpeed = 452;
 
@@ -108,11 +104,12 @@
  *
  * Add a message to the queue. Return FALSE if queue is full.
  */
-static int MSG_AddMsg( MESSAGEQUEUE * msgQueue, MSG * msg, DWORD extraInfo )
+static int MSG_AddMsg( HANDLE hQueue, MSG * msg, DWORD extraInfo )
 {
     int pos;
-  
-    if (!msgQueue) return FALSE;
+    MESSAGEQUEUE *msgQueue;
+
+    if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return FALSE;
     pos = msgQueue->nextFreeMessage;
 
       /* Check if queue is full */
@@ -379,6 +376,8 @@
         if (hwnd && (msg->hwnd != hwnd)) continue;
         if ((first || last) && 
             ((msg->message < first) || (msg->message > last))) continue;
+        if (GetWindowTask(msg->hwnd) != GetCurrentTask())
+            continue;  /* Not for this task */
         if (remove) MSG_RemoveMsg( sysMsgQueue, pos );
         return TRUE;
     }
@@ -412,10 +411,12 @@
  */
 void MSG_IncPaintCount( HANDLE hQueue )
 {
-    if (hQueue != hmemAppMsgQueue) return;
-    appMsgQueue->wPaintCount++;
-    appMsgQueue->status |= QS_PAINT;
-    appMsgQueue->tempStatus |= QS_PAINT;    
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
+    queue->wPaintCount++;
+    queue->status |= QS_PAINT;
+    queue->tempStatus |= QS_PAINT;    
 }
 
 
@@ -424,9 +425,11 @@
  */
 void MSG_DecPaintCount( HANDLE hQueue )
 {
-    if (hQueue != hmemAppMsgQueue) return;
-    appMsgQueue->wPaintCount--;
-    if (!appMsgQueue->wPaintCount) appMsgQueue->status &= ~QS_PAINT;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
+    queue->wPaintCount--;
+    if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
 }
 
 
@@ -435,10 +438,12 @@
  */
 void MSG_IncTimerCount( HANDLE hQueue )
 {
-    if (hQueue != hmemAppMsgQueue) return;
-    appMsgQueue->wTimerCount++;
-    appMsgQueue->status |= QS_TIMER;
-    appMsgQueue->tempStatus |= QS_TIMER;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
+    queue->wTimerCount++;
+    queue->status |= QS_TIMER;
+    queue->tempStatus |= QS_TIMER;
 }
 
 
@@ -447,9 +452,11 @@
  */
 void MSG_DecTimerCount( HANDLE hQueue )
 {
-    if (hQueue != hmemAppMsgQueue) return;
-    appMsgQueue->wTimerCount--;
-    if (!appMsgQueue->wTimerCount) appMsgQueue->status &= ~QS_TIMER;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( hQueue ))) return;
+    queue->wTimerCount--;
+    if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
 }
 
 
@@ -537,31 +544,12 @@
 
 
 /***********************************************************************
- *           SetTaskQueue  (KERNEL.34)
- */
-WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
-{
-    HANDLE prev = hmemAppMsgQueue;
-    hmemAppMsgQueue = hQueue;
-    return prev;
-}
-
-
-/***********************************************************************
- *           GetTaskQueue  (KERNEL.35)
- */
-WORD GetTaskQueue( HANDLE hTask )
-{
-    return hmemAppMsgQueue;
-}
-
-
-/***********************************************************************
  *           SetMessageQueue  (USER.266)
  */
 BOOL SetMessageQueue( int size )
 {
-    HANDLE hQueue;
+    HGLOBAL hQueue;
+    MESSAGEQUEUE *queuePtr;
 
     if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
 
@@ -573,20 +561,38 @@
     }
   
     if (!(hQueue = MSG_CreateMsgQueue( size ))) return FALSE;
+    queuePtr = (MESSAGEQUEUE *)GlobalLock( hQueue );
+    queuePtr->hTask = GetCurrentTask();
     SetTaskQueue( 0, hQueue );
-    appMsgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
     return TRUE;
 }
 
 
 /***********************************************************************
+ *           GetWindowTask  (USER.224)
+ */
+HTASK GetWindowTask( HWND hwnd )
+{
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    MESSAGEQUEUE *queuePtr;
+
+    if (!wndPtr) return 0;
+    queuePtr = (MESSAGEQUEUE *)GlobalLock( wndPtr->hmemTaskQ );
+    if (!queuePtr) return 0;
+    return queuePtr->hTask;
+}
+
+
+/***********************************************************************
  *           PostQuitMessage   (USER.6)
  */
 void PostQuitMessage( int exitCode )
 {
-    if (!appMsgQueue) return;
-    appMsgQueue->wPostQMsg = TRUE;
-    appMsgQueue->wExitCode = exitCode;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return;
+    queue->wPostQMsg = TRUE;
+    queue->wExitCode = exitCode;
 }
 
 
@@ -595,9 +601,13 @@
  */
 DWORD GetQueueStatus( int flags )
 {
-    unsigned long ret = (appMsgQueue->status << 16) | appMsgQueue->tempStatus;
-    appMsgQueue->tempStatus = 0;
-    return ret & ((flags << 16) | flags);
+    MESSAGEQUEUE *queue;
+    DWORD ret;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+    ret = MAKELONG( queue->tempStatus, queue->status );
+    queue->tempStatus = 0;
+    return ret & MAKELONG( flags, flags );
 }
 
 
@@ -606,7 +616,10 @@
  */
 BOOL GetInputState()
 {
-    return appMsgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return FALSE;
+    return queue->status & (QS_KEY | QS_MOUSEBUTTON);
 }
 
 
@@ -666,10 +679,11 @@
 /***********************************************************************
  *           MSG_PeekMessage
  */
-static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
-			     WORD first, WORD last, WORD flags, BOOL peek )
+static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last,
+                             WORD flags, BOOL peek )
 {
     int pos, mask;
+    MESSAGEQUEUE *msgQueue;
     LONG nextExp;  /* Next timer expiration time */
 
     if (first || last)
@@ -685,6 +699,9 @@
 
     while(1)
     {    
+        msgQueue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) );
+        if (!msgQueue) return FALSE;
+
 	  /* First handle a message put by SendMessage() */
 	if (msgQueue->status & QS_SENDMESSAGE)
 	{
@@ -755,6 +772,8 @@
 	}
 	else nextExp = -1;  /* No timeout needed */
 
+        Yield();
+
 	  /* Wait until something happens */
         if (peek)
         {
@@ -785,17 +804,17 @@
     {
 	if (sendIdle)
 	{
-	    if (!MSG_PeekMessage( appMsgQueue, (MSG *)PTR_SEG_TO_LIN(msg),
+	    if (!MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                                   0, 0, 0, flags, TRUE ))
 	    {
 		  /* No message present -> send ENTERIDLE and wait */
 		SendMessage( hwndOwner, WM_ENTERIDLE, code, (LPARAM)hwnd );
-		MSG_PeekMessage( appMsgQueue, (MSG *)PTR_SEG_TO_LIN(msg),
+		MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                                  0, 0, 0, flags, FALSE );
 	    }
 	}
 	else  /* Always wait for a message */
-	    MSG_PeekMessage( appMsgQueue, (MSG *)PTR_SEG_TO_LIN(msg),
+	    MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                              0, 0, 0, flags, FALSE );
 
 	if (!CallMsgFilter( msg, code ))
@@ -804,7 +823,7 @@
 	  /* Message filtered -> remove it from the queue */
 	  /* if it's still there. */
 	if (!(flags & PM_REMOVE))
-	    MSG_PeekMessage( appMsgQueue, (MSG *)PTR_SEG_TO_LIN(msg),
+	    MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                              0, 0, 0, PM_REMOVE, TRUE );
     }
 }
@@ -815,7 +834,7 @@
  */
 BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
 {
-    return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, flags, TRUE );
+    return MSG_PeekMessage( msg, hwnd, first, last, flags, TRUE );
 }
 
 
@@ -824,7 +843,7 @@
  */
 BOOL GetMessage( SEGPTR msg, HWND hwnd, WORD first, WORD last ) 
 {
-    MSG_PeekMessage( appMsgQueue, (MSG *)PTR_SEG_TO_LIN(msg),
+    MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
                      hwnd, first, last, PM_REMOVE, FALSE );
     CALL_SYSTEM_HOOK( WH_GETMESSAGE, 0, 0, (LPARAM)msg );
     CALL_TASK_HOOK( WH_GETMESSAGE, 0, 0, (LPARAM)msg );
@@ -841,7 +860,7 @@
     MSG 	msg;
     WND 	*wndPtr;
 
-	if (hwnd == HWND_BROADCAST) {
+    if (hwnd == HWND_BROADCAST) {
 	    dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
 	    hwnd = GetTopWindow(GetDesktopWindow());
 	    while (hwnd) {
@@ -872,7 +891,7 @@
     msg.pt.x    = 0;
     msg.pt.y    = 0;
 
-    return MSG_AddMsg( appMsgQueue, &msg, 0 );
+    return MSG_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
 }
 
 
@@ -886,10 +905,32 @@
 
     wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    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;
+    else {
+      /* Argh. This is inefficient. */
+      typedef struct {
+	LONG lParam;
+	WORD wParam;
+	WORD wMsg;
+	WORD hWnd;
+      } msgstruct;
+      HANDLE msgh    = GlobalAlloc(0,sizeof(msgstruct));
+      SEGPTR segmsg  = WIN16_GlobalLock(msgh);
+      msgstruct *Msg = PTR_SEG_TO_LIN(segmsg);
+    
+      Msg->hWnd    = hwnd;
+      Msg->wMsg    = msg;
+      Msg->wParam  = wParam;
+      Msg->lParam  = lParam;
+      CALL_SYSTEM_HOOK( WH_CALLWNDPROC, 0, 0, (LPARAM)segmsg );
+      CALL_TASK_HOOK( WH_CALLWNDPROC, 0, 0, (LPARAM)segmsg );
+      ret = CallWindowProc( wndPtr->lpfnWndProc, Msg->hWnd, Msg->wMsg, Msg->wParam,
+			   Msg->lParam );
+      GlobalUnlock(msgh);
+      GlobalFree(msgh);
+      dprintf_msg( stddeb,"SendMessage(%4.4x,%x,%x,%lx) -> %lx\n",
+		  hwnd, msg, wParam, lParam, ret );
+      return ret;
+    }
 }
 
 
@@ -899,13 +940,15 @@
 void WaitMessage( void )
 {
     MSG msg;
+    MESSAGEQUEUE *queue;
     LONG nextExp = -1;  /* Next timer expiration time */
 
-    if ((appMsgQueue->wPostQMsg) || 
-        (appMsgQueue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
-        (appMsgQueue->msgCount) || (sysMsgQueue->msgCount) )
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return;
+    if ((queue->wPostQMsg) || 
+        (queue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
+        (queue->msgCount) || (sysMsgQueue->msgCount) )
         return;
-    if ((appMsgQueue->status & QS_TIMER) && 
+    if ((queue->status & QS_TIMER) && 
         TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
         return;
     MSG_WaitXEvent( nextExp );
@@ -973,7 +1016,10 @@
  */
 DWORD GetMessagePos(void)
 {
-    return appMsgQueue->GetMessagePosVal;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+    return queue->GetMessagePosVal;
 }
 
 
@@ -982,7 +1028,10 @@
  */
 LONG GetMessageTime(void)
 {
-    return appMsgQueue->GetMessageTimeVal;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+    return queue->GetMessageTimeVal;
 }
 
 
@@ -991,7 +1040,10 @@
  */
 LONG GetMessageExtraInfo(void)
 {
-    return appMsgQueue->GetMessageExtraInfoVal;
+    MESSAGEQUEUE *queue;
+
+    if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+    return queue->GetMessageExtraInfoVal;
 }
 
 
diff --git a/windows/property.c b/windows/property.c
new file mode 100644
index 0000000..dfffc0b
--- /dev/null
+++ b/windows/property.c
@@ -0,0 +1,143 @@
+/*
+ * Window properties
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include <string.h>
+#include "win.h"
+#include "user.h"
+#include "callback.h"
+#include "stddebug.h"
+/* #define DEBUG_PROP */
+#include "debug.h"
+
+
+typedef struct
+{
+    HANDLE next;       /* Next property in window list */
+    ATOM   atom;       /* Atom (or 0 if string) */
+    HANDLE hData;      /* User's data */
+    char   string[1];  /* Property string */
+} PROPERTY;
+
+
+/***********************************************************************
+ *           SetProp   (USER.26)
+ */
+BOOL SetProp( HWND hwnd, SEGPTR str, HANDLE hData )
+{
+    HANDLE hProp;
+    PROPERTY *prop;
+    WND *wndPtr;
+
+    dprintf_prop( stddeb, "SetProp: %04x %08lx %04x\n", hwnd, str, hData );
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+    hProp = USER_HEAP_ALLOC( sizeof(PROPERTY) + 
+                             (HIWORD(str) ? strlen(PTR_SEG_TO_LIN(str)) : 0 ));
+    if (!hProp) return FALSE;
+    prop = (PROPERTY *) USER_HEAP_LIN_ADDR( hProp );
+    if (HIWORD(str))  /* string */
+    {
+        prop->atom = 0;
+        strcpy( prop->string, PTR_SEG_TO_LIN(str) );
+    }
+    else  /* atom */
+    {
+        prop->atom = LOWORD(str);
+        prop->string[0] = '\0';
+    }
+    prop->hData = hData;
+    prop->next = wndPtr->hProp;
+    wndPtr->hProp = hProp;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetProp   (USER.25)
+ */
+HANDLE GetProp( HWND hwnd, SEGPTR str )
+{
+    HANDLE hProp;
+    WND *wndPtr;
+
+    dprintf_prop( stddeb, "GetProp: %04x %08lx\n", hwnd, str );
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    hProp = wndPtr->hProp;
+    while (hProp)
+    {
+        PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR(hProp);
+        if (HIWORD(str))
+        {
+            if (!prop->atom && !strcasecmp( prop->string, PTR_SEG_TO_LIN(str)))
+                return prop->hData;
+        }
+        else if (prop->atom && (prop->atom == LOWORD(str))) return prop->hData;
+        hProp = prop->next;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           RemoveProp   (USER.24)
+ */
+HANDLE RemoveProp( HWND hwnd, SEGPTR str )
+{
+    HANDLE *hProp;
+    WND *wndPtr;
+
+    dprintf_prop( stddeb, "RemoveProp: %04x %08lx\n", hwnd, str );
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    hProp = &wndPtr->hProp;
+    while (*hProp)
+    {
+        PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR( *hProp );
+        if ((HIWORD(str) && !prop->atom &&
+             !strcasecmp( prop->string, PTR_SEG_TO_LIN(str))) ||
+            (!HIWORD(str) && prop->atom && (prop->atom == LOWORD(str))))
+        {
+            HANDLE hNext = prop->next;
+            HANDLE hData = prop->hData;
+            USER_HEAP_FREE( *hProp );
+            *hProp = hNext;
+            return hData;
+        }
+        hProp = &prop->next;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           EnumProps   (USER.27)
+ */
+int EnumProps( HWND hwnd, FARPROC func )
+{
+    int ret = -1;
+    HANDLE hProp;
+    WND *wndPtr;
+
+    dprintf_prop( stddeb, "EnumProps: %04x %p\n", hwnd, func );
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    hProp = wndPtr->hProp;
+    while (hProp)
+    {
+        PROPERTY *prop = (PROPERTY *)USER_HEAP_LIN_ADDR(hProp);
+        
+        dprintf_prop( stddeb, "  Callback: atom=%04x data=%04x str='%s'\n",
+                      prop->atom, prop->hData, prop->string );
+
+          /* Already get the next in case the callback */
+          /* function removes the current property.    */
+        hProp = prop->next;
+        ret = CallEnumPropProc( func, hwnd,
+                                prop->atom ? MAKELONG( prop->atom, 0 ) :
+                                USER_HEAP_SEG_ADDR(hProp) +
+                                ((int)prop->string - (int)prop),
+                                prop->hData );
+        if (!ret) break;
+    }
+    return ret;
+}
diff --git a/windows/win.c b/windows/win.c
index f17a885..fc63ae8 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -254,14 +254,8 @@
     wndPtr->flags             = 0;
     wndPtr->window            = rootWindow;
     wndPtr->hSysMenu          = 0;
-    wndPtr->hProp	          = 0;
-    wndPtr->hTask	          = 0;
-
-      /* Send dummy WM_NCCREATE message */
-    SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
+    wndPtr->hProp	      = 0;
     EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
-    RedrawWindow( hwndDesktop, NULL, 0,
-		  RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
     return TRUE;
 }
 
@@ -382,7 +376,6 @@
     wndPtr->hHScroll          = 0;
     wndPtr->hSysMenu          = 0;
     wndPtr->hProp             = 0;
-    wndPtr->hTask             = 0;
 
     if (classPtr->wc.cbWndExtra)
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
@@ -516,9 +509,6 @@
       /* Create a copy of SysMenu */
     if (style & WS_SYSMENU) wndPtr->hSysMenu = CopySysMenu();
 
-      /* Register window in current task windows list */
-    AddWindowToTask(GetCurrentTask(), hwnd);
-
     WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
     
     if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
@@ -576,9 +566,6 @@
 	DestroyWindow( wndPtr->hwndChild );
     SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
 
-      /* Remove the window from current task windows list */
-	RemoveWindowFromTask(GetCurrentTask(), hwnd);
-
       /* Destroy the window */
 
     WIN_DestroyWindow( hwnd );
@@ -725,8 +712,8 @@
     if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
     else switch(offset)
     {
-	case GWW_ID: ptr = &wndPtr->wIDmenu;
-	case GWW_HINSTANCE: ptr = &wndPtr->hInstance;
+	case GWW_ID:        ptr = &wndPtr->wIDmenu;   break;
+	case GWW_HINSTANCE: ptr = &wndPtr->hInstance; break;
 	default: return 0;
     }
     retval = *ptr;
@@ -764,12 +751,9 @@
     if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
     else switch(offset)
     {
-	case GWL_STYLE:   ptr = &wndPtr->dwStyle;
-	  break;
-        case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
-	  break;
-	case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
-	  break;
+	case GWL_STYLE:   ptr = &wndPtr->dwStyle; break;
+        case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
+	case GWL_WNDPROC: ptr = (LONG *)&wndPtr->lpfnWndProc; break;
 	default: return 0;
     }
     retval = *ptr;
@@ -996,39 +980,97 @@
 
 
 /*******************************************************************
- *    EnumWindows             (USER.54)
- * 
- *  o gets the desktop window and iterates over all the windows
- *    which are direct decendents of the desktop * by iterating over
- *    the desktop's child window and all the child windows next
- *    pointers
- *
- *  o call wndenumprc for every child window the desktop has
- *
- *  o if wndenumprc returns 0 exit
- * 
+ *           EnumWindows   (USER.54)
  */
-BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
+BOOL EnumWindows( FARPROC lpEnumFunc, LPARAM lParam )
 {
-    HWND hwnd = GetTopWindow( GetDesktopWindow() );
+    HWND hwnd;
     WND *wndPtr;
-    int result;
+    HWND *list, *pWnd;
+    int count;
 
-    dprintf_enum(stddeb,"EnumWindows\n");
+    /* We have to build a list of all windows first, to avoid */
+    /* unpleasant side-effects, for instance if the callback  */
+    /* function changes the Z-order of the windows.           */
 
-    while (hwnd) {
-        if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
-              return 0;
-      }
-      result = CallEnumWindowsProc( wndenumprc, hwnd, lParam );
-      if ( ! result )  {
-              return 0;
-      }
-      hwnd=wndPtr->hwndNext;
+      /* First count the windows */
+
+    count = 0;
+    for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
+    {
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+        count++;
     }
-    return 1; /* for now */
+    if (!count) return TRUE;
+
+      /* Now build the list of all windows */
+
+    if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
+    for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
+    {
+        wndPtr = WIN_FindWndPtr( hwnd );
+        *pWnd++ = hwnd;
+    }
+
+      /* Now call the callback function for every window */
+
+    for (pWnd = list; count > 0; count--, pWnd++)
+    {
+          /* Make sure that window still exists */
+        if (!IsWindow(*pWnd)) continue;
+        if (!CallEnumWindowsProc( lpEnumFunc, *pWnd, lParam )) break;
+    }
+    free( list );
+    return TRUE;
 }
 
+
+/**********************************************************************
+ *           EnumTaskWindows   (USER.225)
+ */
+BOOL EnumTaskWindows( HTASK hTask, FARPROC lpEnumFunc, LONG lParam )
+{
+    HWND hwnd;
+    WND *wndPtr;
+    HWND *list, *pWnd;
+    HANDLE hQueue = GetTaskQueue( hTask );
+    int count;
+
+    /* This function is the same as EnumWindows(),    */
+    /* except for an added check on the window queue. */
+
+      /* First count the windows */
+
+    count = 0;
+    for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
+    {
+        if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+        if (wndPtr->hmemTaskQ == hQueue) count++;
+    }
+    if (!count) return TRUE;
+
+      /* Now build the list of all windows */
+
+    if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
+    for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
+    {
+        wndPtr = WIN_FindWndPtr( hwnd );
+        if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
+    }
+
+      /* Now call the callback function for every window */
+
+    for (pWnd = list; count > 0; count--, pWnd++)
+    {
+          /* Make sure that window still exists */
+        if (!IsWindow(*pWnd)) continue;
+        if (!CallEnumTaskWndProc( lpEnumFunc, *pWnd, lParam )) break;
+    }
+    free( list );
+    return TRUE;
+}
+
+
 /*******************************************************************
  *    WIN_EnumChildWin
  *
@@ -1073,6 +1115,7 @@
     return WIN_EnumChildWin(hwnd, wndenumprc, lParam);         
 }
 
+
 /*******************************************************************
  *			AnyPopup		[USER.52]
  */