Release 950606

Tue Jun  6 12:11:41 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [controls/menu.c]
	Fixed bug with drawing multi-column menus with vertical separator.

	* [debugger/debug.l]
	Fixed NULL-pointer reference after readline().

	* [if1632/winprocs.spec] [miscemu/int21.c] [miscemu/interrupts.c]
	Added interrupt vector emulation. Allows to retrieve an interrupt
	vector and jump to it without crashing.

	* [loader/ldt.c]
	Moved ldt.c to memory directory.

	* [loader/task.c]
	Implemented LockCurrentTask() and GetInstanceData().

	* [objects/bitblt.c]
	Fixed a bug that caused StretchBlt() to use wrong colors when
	stretching a monochrome bitmap to a color display.

	* [objects/bitmap.c]
	Fixed a segmented pointer bug in CreateBitmapIndirect().

	* [tools/build.c]
	Added possibility to have arguments for register functions; used
	by interrupt vectors to remove the flags from the stack.
	Generate a new function CallTo32_LargeStack(), that allows calling
	a 32-bit function using the original 32-bit stack, for functions
	that need more that 64k of stack.

Tue May 30 10:29:56 1995  Martin von Loewis  <martin@informatik.hu-berlin.de>

	* [if1632/shell.spec] [misc/shell.c]
	DoEnvironmentSubst: fixed prototype

	* [if1632/gdi.spec] [objects/palette.c]
	SetSystemPaletteUse: new function

	* [if1632/kernel.spec] [loader/resource.c]
	DirectResAlloc: new function

	* [if1632/user.spec] [windows/keyboard.c]
	SetKeyboardState: new function

Mon May 29 12:58:28 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [tools/build.c]
        Prevent interrupts from destroying the args for a 32 bit function
        by loading the correct value into %esp directly after %ss.

	* [loader/ne_image.c] [loader/module.c]
	The new instance must be created earlier in LoadModule(), so that
	fixups referencing it will be handled correctly.
        Initialize the local heap for a DGROUP in NE_LoadSegment().
	
	* [objects/dib.c]
	Like RLE8 bitmaps, RLE4 bitmaps don't always end with a proper code.
	This used to crash Wine. Fixed.

        * [objects/text.c]
	Fix possible null pointer dereference in debugging output.
	
	* [misc/commdlg.c]
	Handle user input in the edit control better. Some bugs fixed.
	
	* [memory/local.c]
	Started implementing moveable blocks. This is unfinished (!), but
	at least it does not seem to break things.

Wed May 24 13:26:36 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/module.c]
	LoadModule(): DLLs occasionally have a data segment, and they work
	much better if it is loaded :-)
	LoadLibrary(): pass HMODULE instead of HINSTANCE to NE_InitializeDLLs.
	FindModule(): also strip off the last backslash of the pathnames
	(Winhelp tried to load C:\WINDOWS\SYSTEM\COMMDLG.DLL).
	GetModuleHandle(): just call MODULE_FindModule, it does the same job,
	only better.
	
	* [loader/ne_image.c]
	LocalInit() the heap of a DLL in NE_InitDLL. (This is probably
	not really correct, it seems that all programs and DLLs try to do
	this themselves. But they pass weird parameters.)
	NE_InitializeDLLs should also call NE_InitDLL for the passed hModule.
	
	* [loader/task.c] [misc/user.c]
	Finish global initializations in InitTask instead of InitApp, or
	all the DLLs will be initialized in InitTask without any available
	window classes!
diff --git a/ANNOUNCE b/ANNOUNCE
index 03f377e..1fbc97c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,15 +1,14 @@
-This is release 950522 of Wine the MS Windows emulator.  This is still a
+This is release 950606 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-950522: (see ChangeLog for details)
-	- Preliminary Win32 support.
-	- Multimedia code works better.
-	- Better message boxes, listboxes and combos.
-	- SYSRES.DLL is no longer needed.
+WHAT'S NEW with Wine-950606: (see ChangeLog for details)
+	- Lots of module fixes.
+	- Better interrupt vectors emulation.
+	- Stack no longer limited to 64k when calling X bitmap functions.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -18,10 +17,11 @@
 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-950522.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950522.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950522.tar.gz
-    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950522.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950606.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950606.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950606.tar.gz
+    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950606.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-950606.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index fb55ccd..4cef5d6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,98 @@
 ----------------------------------------------------------------------
+Tue Jun  6 12:11:41 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
+
+	* [controls/menu.c]
+	Fixed bug with drawing multi-column menus with vertical separator.
+
+	* [debugger/debug.l]
+	Fixed NULL-pointer reference after readline().
+
+	* [if1632/winprocs.spec] [miscemu/int21.c] [miscemu/interrupts.c]
+	Added interrupt vector emulation. Allows to retrieve an interrupt
+	vector and jump to it without crashing.
+
+	* [loader/ldt.c]
+	Moved ldt.c to memory directory.
+
+	* [loader/task.c]
+	Implemented LockCurrentTask() and GetInstanceData().
+
+	* [objects/bitblt.c]
+	Fixed a bug that caused StretchBlt() to use wrong colors when
+	stretching a monochrome bitmap to a color display.
+
+	* [objects/bitmap.c]
+	Fixed a segmented pointer bug in CreateBitmapIndirect().
+
+	* [tools/build.c]
+	Added possibility to have arguments for register functions; used
+	by interrupt vectors to remove the flags from the stack.
+	Generate a new function CallTo32_LargeStack(), that allows calling
+	a 32-bit function using the original 32-bit stack, for functions
+	that need more that 64k of stack.
+
+Tue May 30 10:29:56 1995  Martin von Loewis  <martin@informatik.hu-berlin.de>
+
+	* [if1632/shell.spec] [misc/shell.c]
+	DoEnvironmentSubst: fixed prototype
+
+	* [if1632/gdi.spec] [objects/palette.c]
+	SetSystemPaletteUse: new function
+
+	* [if1632/kernel.spec] [loader/resource.c]
+	DirectResAlloc: new function
+
+	* [if1632/user.spec] [windows/keyboard.c]
+	SetKeyboardState: new function
+
+Mon May 29 12:58:28 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [tools/build.c]
+        Prevent interrupts from destroying the args for a 32 bit function
+        by loading the correct value into %esp directly after %ss.
+
+	* [loader/ne_image.c] [loader/module.c]
+	The new instance must be created earlier in LoadModule(), so that
+	fixups referencing it will be handled correctly.
+        Initialize the local heap for a DGROUP in NE_LoadSegment().
+	
+	* [objects/dib.c]
+	Like RLE8 bitmaps, RLE4 bitmaps don't always end with a proper code.
+	This used to crash Wine. Fixed.
+
+        * [objects/text.c]
+	Fix possible null pointer dereference in debugging output.
+	
+	* [misc/commdlg.c]
+	Handle user input in the edit control better. Some bugs fixed.
+	
+	* [memory/local.c]
+	Started implementing moveable blocks. This is unfinished (!), but
+	at least it does not seem to break things.
+
+Wed May 24 13:26:36 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [loader/module.c]
+	LoadModule(): DLLs occasionally have a data segment, and they work
+	much better if it is loaded :-)
+	LoadLibrary(): pass HMODULE instead of HINSTANCE to NE_InitializeDLLs.
+	FindModule(): also strip off the last backslash of the pathnames
+	(Winhelp tried to load C:\WINDOWS\SYSTEM\COMMDLG.DLL).
+	GetModuleHandle(): just call MODULE_FindModule, it does the same job,
+	only better.
+	
+	* [loader/ne_image.c]
+	LocalInit() the heap of a DLL in NE_InitDLL. (This is probably
+	not really correct, it seems that all programs and DLLs try to do
+	this themselves. But they pass weird parameters.)
+	NE_InitializeDLLs should also call NE_InitDLL for the passed hModule.
+	
+	* [loader/task.c] [misc/user.c]
+	Finish global initializations in InitTask instead of InitApp, or
+	all the DLLs will be initialized in InitTask without any available
+	window classes!
+
+----------------------------------------------------------------------
 Sun May 21 12:30:30 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
 
 	* [debugger/hash.c] [debugger/info.c]
diff --git a/controls/menu.c b/controls/menu.c
index 01a040c..6cea09d 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -344,6 +344,7 @@
 	    if ((i != start) &&
 		(lpitem->item_flags & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
 	    MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, FALSE );
+            if (lpitem->item_flags & MF_MENUBARBREAK) orgX++;
 	    maxX = max( maxX, lpitem->rect.right );
 	    orgY = lpitem->rect.bottom;
 	    if (lpitem->xTab)
diff --git a/debugger/debug.l b/debugger/debug.l
index 18a6b5a..6e9817e 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -173,34 +173,27 @@
 	do{
 		flush_symbols();
 		line = readline ("Wine-dbg>");
+                if (!line) return 0;
 		len = strlen(line);
-				
-		if (!line)
-		{
-			return 0;
-		}
-		else
-		{
-			/* Remove leading and trailing whitespace from the line.
-			   Then, if there is anything left, add it to the history list
-			   and execute it. */
-			stripwhite (line);
-			
-			if (*line)
-			{
-				add_history (line);
-				if(size < len + 1){
-					fprintf(stderr,"Fatal readline goof.\n");
-					exit(0);
-				};
-				strcpy(buf, line);
-				buf[len] = '\n';
-				buf[len+1] = 0;
-				free(line);
-				return len + 1;
-			}
-		}
 
+                /* Remove leading and trailing whitespace from the line.
+                   Then, if there is anything left, add it to the history list
+                   and execute it. */
+                stripwhite (line);
+			
+                if (*line)
+                {
+                    add_history (line);
+                    if(size < len + 1){
+                        fprintf(stderr,"Fatal readline goof.\n");
+                        exit(0);
+                    }
+                    strcpy(buf, line);
+                    buf[len] = '\n';
+                    buf[len+1] = 0;
+                    free(line);
+                    return len + 1;
+                }
 	} while (1==1);
 }
 
diff --git a/debugger/info.c b/debugger/info.c
index b31eeae..938150a 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -284,12 +284,10 @@
   while((cs & 3) == 3) {
     /* See if in 32 bit mode or not.  Assume GDT means 32 bit. */
     if ((cs & 7) != 7) {
-      extern int main();
       fprintf(stderr,"%d ",frameno++);
       print_address(frame->u.win32.saved_ip,stderr,32);
       fprintf( stderr, "\n" );
-      if (frame->u.win32.saved_ip >= ((unsigned long)main) &&
-          frame->u.win32.saved_ip <= ((unsigned long)main+1000)) break;
+      if (!frame->u.win32.saved_ip) break;
       frame = (struct frame *) frame->u.win32.saved_bp;
     } else {
       if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 598d289..81584db 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -234,6 +234,7 @@
 368 stub ResizePalette
 370 pascal16 GetNearestPaletteIndex(word long) GetNearestPaletteIndex
 372 pascal16 ExtFloodFill(word s_word s_word long word) ExtFloodFill
+373 pascal16 SetSystemPaletteUse(word word) SetSystemPaletteUse
 374 pascal16 GetSystemPaletteUse(word) GetSystemPaletteUse
 375 pascal16 GetSystemPaletteEntries(word word word ptr)
              GetSystemPaletteEntries
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 7ca626c..1fbeb4e 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -32,7 +32,7 @@
 30  pascal16 WaitEvent(word) WaitEvent
 31  pascal16 PostEvent(word) PostEvent
 32  pascal16 SetPriority(word s_word) SetPriority
-33  stub LockCurrentTask
+33  pascal16 LockCurrentTask(word) LockCurrentTask
 34  pascal SetTaskQueue(word word) SetTaskQueue
 35  pascal16 GetTaskQueue(word) GetTaskQueue
 36  pascal GetCurrentTask() GetCurrentTask
@@ -49,7 +49,7 @@
 51  pascal MakeProcInstance(segptr word) MakeProcInstance
 52  pascal16 FreeProcInstance(segptr) FreeProcInstance
 53  stub CallProcInstance
-54  stub GetInstanceData
+54  pascal16 GetInstanceData(word word word) GetInstanceData
 55  pascal16 Catch(ptr) Catch 
 56  pascal16 Throw(ptr word) Throw
 57  pascal16 GetProfileInt(ptr ptr word) GetProfileInt
@@ -98,7 +98,7 @@
 100 stub ValidateCodeSegments
 101 stub NoHookDosCall
 102 register DOS3Call() DOS3Call
-103 stub NetBiosCall
+103 register NetBIOSCall() NetBIOSCall
 104 stub GetCodeInfo
 105 stub GetExeVersion
 106 pascal SetSwapAreaSize(word) SetSwapAreaSize
@@ -117,7 +117,7 @@
 119 stub GetTaskQueueES
 120 stub UndefDynLink
 121 pascal16 LocalShrink(word word) LocalShrink
-122 stub IsTaskLocked
+122 pascal16 IsTaskLocked() IsTaskLocked
 123 stub KbdRst
 124 return EnableKernel 0 0
 125 return DisableKernel 0 0
@@ -156,7 +156,7 @@
 165 stub A20Proc
 166 pascal16 WinExec(ptr word) WinExec
 167 stub GetExpWinVer
-168 stub DirectResAlloc
+168 pascal16 DirectResAlloc(word word word) DirectResAlloc
 169 pascal GetFreeSpace(word) GetFreeSpace
 170 pascal16 AllocCStoDSAlias(word) AllocCStoDSAlias
 171 pascal16 AllocDStoCSAlias(word) AllocDStoCSAlias
diff --git a/if1632/relay.c b/if1632/relay.c
index 5049827..c628457 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -60,6 +60,7 @@
   /* Saved 32-bit stack */
 DWORD IF1632_Saved32_esp = 0;
 SEGPTR IF1632_Stack32_base = 0;
+DWORD IF1632_Original32_esp = 0;
 
 /***********************************************************************
  *           RELAY_Init
diff --git a/if1632/shell.spec b/if1632/shell.spec
index b00a5c4..ad04c35 100644
--- a/if1632/shell.spec
+++ b/if1632/shell.spec
@@ -23,7 +23,7 @@
  33 pascal AboutDlgProc(word word word long) AboutDlgProc
  34 pascal ExtractIcon(word ptr s_word) ExtractIcon
  36 pascal ExtractAssociatedIcon(word ptr ptr) ExtractAssociatedIcon
- 37 pascal DoEnvironmentSubst(ptr word word) DoEnvironmentSubst
+ 37 pascal DoEnvironmentSubst(ptr word) DoEnvironmentSubst
  39 stub InternalExtractIcon
 102 pascal RegisterShellHook(ptr) RegisterShellHook
 103 pascal ShellHookProc() ShellHookProc
diff --git a/if1632/user.spec b/if1632/user.spec
index e69390c..f4156d4 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -221,7 +221,7 @@
 220 pascal LoadMenuIndirect(ptr) LoadMenuIndirect
 221 pascal ScrollDC(word s_word s_word ptr ptr word ptr) ScrollDC
 222 pascal16 GetKeyboardState(ptr) GetKeyboardState
-223 stub SetKeyboardState
+223 pascal16 SetKeyboardState(ptr) SetKeyboardState
 224 pascal16 GetWindowTask(word) GetWindowTask
 225 pascal EnumTaskWindows(word segptr long) EnumTaskWindows
 226 stub LockInput
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
index 16240c4..8a0e88d 100644
--- a/if1632/winprocs.spec
+++ b/if1632/winprocs.spec
@@ -25,3 +25,23 @@
 22 pascal ComboLBoxWndProc(word word word long) ComboLBoxWndProc
 23 pascal16 CARET_Callback(word word word long) CARET_Callback
 24 pascal16 TASK_Reschedule() TASK_Reschedule
+
+# Interrupt vectors 0-255 are ordinals 100-355
+# Undefined functions are mapped to the dummy handler (ordinal 356)
+# The 'word' parameter are the flags pushed on the stack by the interrupt
+
+116 register INT_Int10Handler(word) INT_Int10Handler
+119 register INT_Int13Handler(word) INT_Int13Handler
+121 register INT_Int15Handler(word) INT_Int15Handler
+122 register INT_Int16Handler(word) INT_Int16Handler
+126 register INT_Int1aHandler(word) INT_Int1aHandler
+133 register INT_Int21Handler(word) INT_Int21Handler
+137 register INT_Int25Handler(word) INT_Int25Handler
+138 register INT_Int26Handler(word) INT_Int26Handler
+142 register INT_Int2aHandler(word) INT_Int2aHandler
+147 register INT_Int2fHandler(word) INT_Int2fHandler
+149 register INT_Int31Handler(word) INT_Int31Handler
+192 register INT_Int5cHandler(word) INT_Int5cHandler
+
+# Dummy interrupt vector
+356 register INT_DummyHandler(word) INT_DummyHandler
diff --git a/include/callback.h b/include/callback.h
index 0510758..3a2dba3 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -14,6 +14,9 @@
 
 #ifndef WINELIB
 
+extern int CallTo32_LargeStack( int (*func)(), int nbargs, ... );
+
+
 /* List of the 16-bit callback functions. This list is used  */
 /* by the build program to generate the file if1632/call16.S */
 
diff --git a/include/miscemu.h b/include/miscemu.h
index 1cc6fcc..4f8b378 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -1,6 +1,9 @@
 #ifndef __WINE_MISCEMU_H
 #define __WINE_MISCEMU_H
 
+#include "wintypes.h"
+#include "wine.h"
+
 extern int do_int10(struct sigcontext_struct *);
 extern int do_int13(struct sigcontext_struct *);
 extern int do_int15(struct sigcontext_struct *);
@@ -12,6 +15,7 @@
 extern int do_int2a(struct sigcontext_struct *);
 extern int do_int2f(struct sigcontext_struct *);
 extern int do_int31(struct sigcontext_struct *);
+extern int do_int5c(struct sigcontext_struct *);
 
 extern void inportb(struct sigcontext_struct *context);
 extern void inport(struct sigcontext_struct *context);
@@ -24,6 +28,10 @@
 
 extern void IntBarf(int i, struct sigcontext_struct *context);
 
+extern BOOL INT_Init(void);
+extern SEGPTR INT_GetHandler( BYTE intnum );
+extern void INT_SetHandler( BYTE intnum, SEGPTR handler );
+
 extern void INT21_Init(void);
 
 #endif /* __WINE_MISCEMU_H */
diff --git a/include/stackframe.h b/include/stackframe.h
index 8196461..3295e83 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -55,6 +55,7 @@
   /* Saved 32-bit stack */
 extern DWORD IF1632_Saved32_esp;
 extern SEGPTR IF1632_Stack32_base;
+extern DWORD IF1632_Original32_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 e78f6d5..cbd28ae 100644
--- a/include/task.h
+++ b/include/task.h
@@ -21,9 +21,9 @@
     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 */
+    SEGPTR savedint22;       /* Saved int 22h handler */
+    SEGPTR savedint23;       /* Saved int 23h handler */
+    SEGPTR savedint24;       /* Saved int 24h handler */
     WORD   parentPSP;        /* Selector of parent PSP */
     BYTE   fileHandles[20];  /* Open file handles */
     HANDLE environment;      /* Selector of environment */
diff --git a/include/windows.h b/include/windows.h
index 76ec59d..7230f39 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2836,7 +2836,7 @@
 Fc(int,GetClassName,HWND,a,LPSTR,b,short,c)
 Fc(int,GetClipboardFormatName,WORD,a,LPSTR,b,short,c)
 Fc(int,GetEnvironment,LPSTR,a,LPSTR,b,WORD,c)
-Fc(int,GetInstanceData,HANDLE,a,NPSTR,b,int,c)
+Fc(int,GetInstanceData,HANDLE,a,WORD,b,int,c)
 Fc(int,GetKeyNameText,LONG,a,LPSTR,b,int,c)
 Fc(int,GetModuleFileName,HANDLE,a,LPSTR,b,short,c)
 Fc(int,GetObject,HANDLE,a,int,b,LPSTR,c)
diff --git a/loader/Imakefile b/loader/Imakefile
index 9c15c28..befe47a 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -4,7 +4,6 @@
 
 SRCS = \
 	dump.c \
-	ldt.c \
 	main.c \
 	module.c \
 	ne_image.c \
diff --git a/loader/main.c b/loader/main.c
index 3ace9d3..e6ad03e 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -10,12 +10,12 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include "neexe.h"
+#include "windows.h"
 #include "dos_fs.h"
 #include "dlls.h"
-#include "windows.h"
+#include "miscemu.h"
+#include "neexe.h"
 #include "wineopts.h"
-#include "wine.h"
 #include "task.h"
 #include "options.h"
 #include "pe_image.h"
@@ -46,6 +46,9 @@
       /* Initialize tasks */
     if (!TASK_Init()) return 0;
 
+      /* Initialize interrupt vectors */
+    if (!INT_Init()) return 0;
+
       /* Initialize the DOS file system */
     DOS_InitFS();
 
diff --git a/loader/module.c b/loader/module.c
index c4af5bf..aa397d8 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -292,7 +292,7 @@
 /***********************************************************************
  *           MODULE_CreateSegments
  */
-BOOL MODULE_CreateSegments( HMODULE hModule )
+static BOOL MODULE_CreateSegments( HMODULE hModule )
 {
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
@@ -308,9 +308,8 @@
         {
             /* FIXME: this is needed because heap growing is not implemented */
             pModule->heap_size = 0x10000 - minsize;
-            /* For tasks, the DGROUP is allocated by MODULE_MakeNewInstance */
-            minsize = 0x10000;
-            if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) continue;
+            /* The DGROUP is allocated by MODULE_CreateInstance */
+            continue;
         }
         pSegment->selector = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
                                       minsize, hModule,
@@ -327,6 +326,57 @@
 
 
 /***********************************************************************
+ *           MODULE_GetInstance
+ */
+static HINSTANCE MODULE_GetInstance( HMODULE hModule )
+{
+    SEGTABLEENTRY *pSegment;
+    NE_MODULE *pModule;
+    
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (pModule->dgroup == 0) return hModule;
+
+    pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
+    
+    return pSegment->selector;
+}
+
+
+/***********************************************************************
+ *           MODULE_CreateInstance
+ */
+static HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
+{
+    SEGTABLEENTRY *pSegment;
+    NE_MODULE *pModule;
+    int minsize;
+    HINSTANCE hNewInstance, hPrevInstance;
+
+    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (pModule->dgroup == 0) return hModule;
+
+    pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
+    hPrevInstance = pSegment->selector;
+
+      /* if it's a library, create a new instance only the first time */
+    if (hPrevInstance)
+    {
+        if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
+        if (params == (LOADPARAMS*)-1) return hPrevInstance;
+    }
+
+    minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
+    if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
+    minsize += pModule->heap_size;
+    hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
+                                 minsize, hModule, FALSE, FALSE, FALSE );
+    if (!hNewInstance) return 0;
+    pSegment->selector = hNewInstance;
+    return hNewInstance;
+}
+
+
+/***********************************************************************
  *           MODULE_LoadExeHeader
  */
 HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
@@ -518,62 +568,6 @@
 
 
 /***********************************************************************
- *           MODULE_MakeNewInstance
- *
- * Create a new instance of the specified module.
- */
-HINSTANCE MODULE_MakeNewInstance( HMODULE hModule, LOADPARAMS *params )
-{
-    NE_MODULE *pModule;
-    SEGTABLEENTRY *pSegment;
-    HINSTANCE hNewInstance, hPrevInstance;
-    int minsize;
-
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
-    if (!pModule->dgroup) return hModule;  /* No DGROUP -> return the module */
-
-    pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
-    hPrevInstance = pSegment->selector;
-
-      /* Don't create a new instance if it's a library */
-
-    if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
-    if (params == (LOADPARAMS*)-1) return hPrevInstance;
-
-      /* Allocate the new data segment */
-
-    minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
-    if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
-    minsize += pModule->heap_size;
-    hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
-                                 minsize, hModule, FALSE, FALSE, FALSE );
-    if (!hNewInstance) return 0;
-    pSegment->selector = hNewInstance;
-    NE_LoadSegment( hModule, pModule->dgroup );
-
-      /* Create a new task for this instance */
-    if (!TASK_CreateTask( hModule, hNewInstance, hPrevInstance,
-                          params->hEnvironment,
-                          (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
-                          *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) ))
-    {
-        GlobalFree( hNewInstance );
-        return 0;
-    }
-
-      /* Initialize the local heap */
-
-    if (pModule->heap_size)
-    {
-        WORD heapstart = pSegment->minsize;
-        if (pModule->ss == pModule->dgroup) heapstart += pModule->stack_size;
-        LocalInit( hNewInstance, heapstart, heapstart + pModule->heap_size );
-    }
-    return hNewInstance;
-}
-
-
-/***********************************************************************
  *           MODULE_GetOrdinal
  *
  * Lookup the ordinal for a given name.
@@ -800,6 +794,7 @@
     BYTE len, *name_table;
 
     if (!(filename = strrchr( path, '\\' ))) filename = path;
+    else filename++;
     if ((dotptr = strrchr( filename, '.' )) != NULL)
         len = (BYTE)(dotptr - filename);
     else len = strlen( filename );
@@ -811,6 +806,7 @@
         modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
         if (!(modulename = strrchr( modulepath, '\\' )))
             modulename = modulepath;
+        else modulename++;
         if (!strcasecmp( modulename, filename )) return hModule;
 
         name_table = (BYTE *)pModule + pModule->name_table;
@@ -878,8 +874,9 @@
 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
 {
     HMODULE hModule;
-    HANDLE hInstance;
+    HANDLE hInstance, hPrevInstance;
     NE_MODULE *pModule;
+    LOADPARAMS *params = (LOADPARAMS *)paramBlock;
     WORD *pModRef, *pDLLs;
     int i, fd;
 
@@ -906,6 +903,9 @@
 
         MODULE_CreateSegments( hModule );
 
+        hPrevInstance = 0;
+        hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
+
           /* Load the referenced DLLs */
 
         pModRef = (WORD *)((char *)pModule + pModule->modref_table);
@@ -950,14 +950,9 @@
             }
         }
 
-          /* Load the segments (except the DGROUP) */
+          /* Load the segments */
 
-        for (i = 1; i <= pModule->seg_count; i++)
-            if (i != pModule->dgroup) NE_LoadSegment( hModule, i );
-
-          /* Create an instance for this module */
-
-        hInstance = MODULE_MakeNewInstance( hModule, (LOADPARAMS*)paramBlock );
+        for (i = 1; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
 
           /* Fixup the functions prologs */
 
@@ -971,10 +966,23 @@
     else
     {
         pModule = (NE_MODULE *)GlobalLock( hModule );
-        hInstance = MODULE_MakeNewInstance( hModule, (LOADPARAMS*)paramBlock );
+        hPrevInstance = MODULE_GetInstance( hModule );
+        hInstance = MODULE_CreateInstance( hModule, params );
+        if (hInstance != hPrevInstance)  /* not a library */
+            NE_LoadSegment( hModule, pModule->dgroup );
         pModule->count++;
     }
 
+      /* Create a task for this instance */
+
+    if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
+    {
+        TASK_CreateTask( hModule, hInstance, hPrevInstance,
+                         params->hEnvironment,
+                         (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
+                         *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
+    }
+
     return hInstance;
 }
 
@@ -999,20 +1007,7 @@
  */
 HMODULE GetModuleHandle( LPCSTR name )
 {
-    BYTE len = strlen(name);
-    HMODULE hModule = hFirstModule;
-
-    while( hModule )
-    {
-        NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
-        char *pname = (char *)pModule + pModule->name_table;
-        if (((BYTE)*pname == len) && !strncasecmp( pname+1, name, len ))
-            break;
-        hModule = pModule->next;
-    }
-    dprintf_module( stddeb, "GetModuleHandle('%s'): returning %04x\n",
-                    name, hModule );
-    return hModule;
+    return MODULE_FindModule( name );
 }
 
 
@@ -1044,6 +1039,7 @@
     name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
     strncpy( lpFileName, name, nSize );
     lpFileName[nSize-1] = '\0';
+    dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
     return strlen(lpFileName);
 }
 
@@ -1056,6 +1052,8 @@
     HANDLE handle;
 
     dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
+    if ((handle = MODULE_FindModule( libname )) != 0) return handle;
+
     handle = LoadModule( libname, (LPVOID)-1 );
     if (handle == 2)  /* file not found */
     {
@@ -1064,7 +1062,7 @@
         strcat( buffer, ".dll" );
         handle = LoadModule( buffer, (LPVOID)-1 );
     }
-    if (handle >= 32) NE_InitializeDLLs( handle );
+    if (handle >= 32) NE_InitializeDLLs( GetExePtr(handle) );
     return handle;
 }
 
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 1a14ef2..4529f62 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -56,6 +56,14 @@
     lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
     read( fd, GlobalLock( pSeg->selector ), pSeg->size ? pSeg->size : 0x10000);
 
+    if ( pModule->heap_size && pModule->dgroup == segnum )
+    {
+        /* Initialize the local heap */
+        WORD heapstart = pSeg->minsize;
+        if (pModule->ss == pModule->dgroup) heapstart += pModule->stack_size;
+        LocalInit( pSeg->selector, heapstart, heapstart + pModule->heap_size );
+    }    
+
     if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
         return TRUE;  /* No relocation data, we are done */
 
@@ -413,12 +421,15 @@
     WORD *pDLL;
 
     pModule = (NE_MODULE *)GlobalLock( hModule );
-    if (!pModule->dlls_to_init) return;
-    for (pDLL = (WORD *)GlobalLock( pModule->dlls_to_init ); *pDLL; pDLL++)
+    if (pModule->dlls_to_init)
     {
-        NE_InitDLL( *pDLL );
-        NE_InitializeDLLs( *pDLL );
+        for (pDLL = (WORD *)GlobalLock( pModule->dlls_to_init ); *pDLL; pDLL++)
+        {
+            NE_InitDLL( *pDLL );
+            NE_InitializeDLLs( *pDLL );
+        }
+        GlobalFree( pModule->dlls_to_init );
+        pModule->dlls_to_init = 0;
     }
-    GlobalFree( pModule->dlls_to_init );
-    pModule->dlls_to_init = 0;
+    NE_InitDLL( hModule );
 }
diff --git a/loader/resource.c b/loader/resource.c
index adbfc80..0970786 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -16,6 +16,7 @@
 #include "windows.h"
 #include "gdi.h"
 #include "bitmap.h"
+#include "global.h"
 #include "neexe.h"
 #include "icon.h"
 #include "accel.h"
@@ -221,6 +222,23 @@
     }
 }
 
+/**********************************************************************
+ *      DirectResAlloc    (KERNEL.168)
+ * Check Schulman, p. 232 for details
+ */
+HANDLE DirectResAlloc(HANDLE hInstance, WORD wType, WORD wSize)
+{
+	HANDLE hModule;
+	dprintf_resource(stddeb,"DirectResAlloc(%x,%x,%x)\n",hInstance,wType,wSize);
+	hModule = GetExePtr(hInstance);
+	if(!hModule)return 0;
+	if(wType != 0x10)	/* 0x10 is the only observed value, passed from
+                           CreateCursorIndirect. */
+		fprintf(stderr, "DirectResAlloc: wType = %x\n", wType);
+	/* This hopefully does per-module allocation rather than per-instance */
+	return GLOBAL_Alloc(GMEM_FIXED, wSize, hModule, FALSE, FALSE, FALSE);
+}
+
 
 /**********************************************************************
  *			ConvertCoreBitmap
diff --git a/loader/signal.c b/loader/signal.c
index b395d41..6ac04ad 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -18,6 +18,7 @@
 #include "dos_fs.h"
 #include "prototypes.h"
 #include "miscemu.h"
+#include "registers.h"
 #include "win.h"
 
 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
@@ -44,57 +45,59 @@
 }
 #endif
 
-int do_int(int intnum, struct sigcontext_struct *scp)
+int do_int(int intnum, struct sigcontext_struct *context)
 {
 	switch(intnum)
 	{
-	      case 0x10: return do_int10(scp);
+	      case 0x10: return do_int10(context);
 
 	      case 0x11:  
-		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | DOS_GetEquipment();
+		AX = DOS_GetEquipment();
 		return 1;
 
 	      case 0x12:               
-		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | 640L; 
+		AX = 640;
 		return 1;	/* get base mem size */                
 
-              case 0x13: return do_int13(scp);
-	      case 0x15: return do_int15(scp);
-	      case 0x16: return do_int16(scp);
-	      case 0x1a: return do_int1a(scp);
-	      case 0x21: return do_int21(scp);
+              case 0x13: return do_int13(context);
+	      case 0x15: return do_int15(context);
+	      case 0x16: return do_int16(context);
+	      case 0x1a: return do_int1a(context);
+	      case 0x21: return do_int21(context);
 
 	      case 0x22:
-		scp->sc_eax = 0x1234;
-		scp->sc_ebx = 0x5678;
-		scp->sc_ecx = 0x9abc;
-		scp->sc_edx = 0xdef0;
+		AX = 0x1234;
+		BX = 0x5678;
+		CX = 0x9abc;
+		DX = 0xdef0;
 		return 1;
 
-              case 0x25: return do_int25(scp);
-              case 0x26: return do_int26(scp);
-              case 0x2a: return do_int2a(scp);
-	      case 0x2f: return do_int2f(scp);
-	      case 0x31: return do_int31(scp);
+              case 0x25: return do_int25(context);
+              case 0x26: return do_int26(context);
+              case 0x2a: return do_int2a(context);
+	      case 0x2f: return do_int2f(context);
+	      case 0x31: return do_int31(context);
+	      case 0x5c: return do_int5c(context);
 
               default:
-                printf("int%02x: Unimplemented!\n", intnum);
+                fprintf(stderr,"int%02x: Unimplemented!\n", intnum);
                 break;
 	}
 	return 0;
 }
 
 #ifdef linux
-static void win_fault(int signal, struct sigcontext_struct context)
+static void win_fault(int signal, struct sigcontext_struct context_struct)
 {
-    struct sigcontext_struct *scp = &context;
+    struct sigcontext_struct *context = &context_struct;
 #else
-static void win_fault(int signal, int code, struct sigcontext *scp)
+static void win_fault(int signal, int code, struct sigcontext *context)
 {
 #endif
     unsigned char * instr;
+    WORD *stack;
 #if !(defined (linux) || defined (__NetBSD__))
-	int i, *dump;
+    int i, *dump;
 #endif
 
 	/* First take care of a few preliminaries */
@@ -112,7 +115,7 @@
 
     /* And back up over the int3 instruction. */
     if(signal == SIGTRAP) {
-      scp->sc_eip--;
+      EIP--;
       goto oops;
     }
 #endif
@@ -126,76 +129,83 @@
     if(signal != SIGBUS && signal != SIGSEGV && signal != SIGTRAP) 
 	exit(1);
 #endif
-    if (scp->sc_cs == WINE_CODE_SELECTOR)
+    if (CS == WINE_CODE_SELECTOR)
     {
 	fprintf(stderr,
 		"Segmentation fault in Wine program (%x:%lx)."
-		"  Please debug\n",
-		scp->sc_cs, scp->sc_eip);
+		"  Please debug\n", CS, EIP );
 	goto oops;
     }
 
     /*  Now take a look at the actual instruction where the program
 	bombed */
-    instr = (unsigned char *) PTR_SEG_OFF_TO_LIN(scp->sc_cs, scp->sc_eip);
+    instr = (unsigned char *) PTR_SEG_OFF_TO_LIN( CS, EIP );
 
     switch(*instr)
     {
       case 0xcd: /* int <XX> */
             instr++;
-	    if (!do_int(*instr, scp)) {
+	    if (!do_int(*instr, context)) {
 		fprintf(stderr,"Unexpected Windows interrupt %x\n", *instr);
 		goto oops;
 	    }
-	    scp->sc_eip += 2;  /* Bypass the int instruction */
+	    EIP += 2;  /* Bypass the int instruction */
             break;
-            
+
+      case 0xcf: /* iret */
+            stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
+            EIP = *stack++;
+            CS  = *stack++;
+            EFL = *stack;
+            SP += 6;  /* Pop the return address and flags */
+            break;
+
       case 0xe4: /* inb al,XX */
-            inportb_abs(scp);
-	    scp->sc_eip += 2;
+            inportb_abs(context);
+	    EIP += 2;
             break;
 
       case 0xe5: /* in ax,XX */
-            inport_abs(scp);
-	    scp->sc_eip += 2;
+            inport_abs(context);
+	    EIP += 2;
             break;
 
       case 0xe6: /* outb XX,al */
-            outportb_abs(scp);
-	    scp->sc_eip += 2;
+            outportb_abs(context);
+	    EIP += 2;
             break;
 
       case 0xe7: /* out XX,ax */
-            outport_abs(scp);
-	    scp->sc_eip += 2;
+            outport_abs(context);
+	    EIP += 2;
             break;
 
       case 0xec: /* inb al,dx */
-            inportb(scp);
-	    scp->sc_eip++;
+            inportb(context);
+	    EIP++;
             break;
 
       case 0xed: /* in ax,dx */
-            inport(scp);
-	    scp->sc_eip++;  
+            inport(context);
+	    EIP++;  
             break;
 
       case 0xee: /* outb dx,al */
-            outportb(scp);
-	    scp->sc_eip++;
+            outportb(context);
+	    EIP++;
             break;
       
       case 0xef: /* out dx,ax */
-            outport(scp);
-	    scp->sc_eip++;
+            outport(context);
+	    EIP++;
             break;
 
       case 0xfa: /* cli, ignored */
-	    scp->sc_eip++;
+	    EIP++;
             break;
 
       case 0xfb: /* sti, ignored */
-	    scp->sc_eip++;
+	    EIP++;
             break;
 
       default:
@@ -210,14 +220,14 @@
 
   oops:
     XUngrabPointer(display, CurrentTime);
-	XUngrabServer(display);
-	XFlush(display);
-    fprintf(stderr,"In win_fault %x:%lx\n", scp->sc_cs, scp->sc_eip);
+    XUngrabServer(display);
+    XFlush(display);
+    fprintf(stderr,"In win_fault %x:%lx\n", CS, EIP );
 #if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__)
-    wine_debug(signal, (int *)scp);  /* Enter our debugger */
+    wine_debug(signal, (int *)context);  /* Enter our debugger */
 #else
-    fprintf(stderr,"Stack: %x:%x\n", scp->sc_ss, scp->sc_esp);
-    dump = (int*) scp;
+    fprintf(stderr,"Stack: %x:%x\n", SS, ESP );
+    dump = (int*) context;
     for(i=0; i<22; i++) 
     {
 	fprintf(stderr," %8.8x", *dump++);
diff --git a/loader/task.c b/loader/task.c
index 33d53de..5663419 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -12,6 +12,7 @@
 #include "callback.h"
 #include "global.h"
 #include "instance.h"
+#include "miscemu.h"
 #include "module.h"
 #include "neexe.h"
 #include "selectors.h"
@@ -31,6 +32,7 @@
 static HTASK hFirstTask = 0;
 static HTASK hCurrentTask = 0;
 static HTASK hTaskToKill = 0;
+static HTASK hLockedTask = 0;
 static WORD nTaskCount = 0;
 
   /* TASK_Reschedule() 16-bit entry point */
@@ -281,12 +283,11 @@
       /* Fill the PDB */
 
     pTask->pdb.int20 = 0x20cd;
-    pTask->pdb.dispatcher[0] = 0x9a;
+    pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
     *(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.savedint22 = INT_GetHandler( 0x22 );
+    pTask->pdb.savedint23 = INT_GetHandler( 0x23 );
+    pTask->pdb.savedint24 = INT_GetHandler( 0x24 );
     pTask->pdb.environment = hEnvironment;
     strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 );
     pTask->pdb.cmdLine[127] = '\0';
@@ -347,8 +348,8 @@
     frame16->saved_sp = pTask->sp;
     frame16->ds = pTask->hInstance;
     frame16->entry_point = 0;
-    frame16->ordinal_number = 1;
-    frame16->dll_id = 1;
+    frame16->ordinal_number = 24;  /* WINPROCS.24 is TASK_Reschedule */
+    frame16->dll_id = 24; /* WINPROCS */
     frame16->bp = 0;
     frame16->ip = LOWORD( CALL16_RetAddr_word );
     frame16->cs = HIWORD( CALL16_RetAddr_word );
@@ -431,6 +432,7 @@
     TASK_UnlinkTask( hCurrentTask );
     
     hTaskToKill = hCurrentTask;
+    hLockedTask = 0;
     Yield();
     /* We never return from Yield() */
 }
@@ -454,6 +456,10 @@
     if (hTaskToKill && (hTaskToKill != hCurrentTask))
         TASK_DeleteTask( hTaskToKill );
 
+      /* If current task is locked, simply return */
+
+    if (hLockedTask) return;
+
       /* Find a task to yield to */
 
     pOldTask = (TDB *)GlobalLock( hCurrentTask );
@@ -496,6 +502,7 @@
         pOldTask->sp  = IF1632_Saved16_sp;
         pOldTask->esp = IF1632_Saved32_esp;
     }
+    else IF1632_Original32_esp = IF1632_Saved32_esp;
 
      /* Make the task the last in the linked list (round-robin scheduling) */
 
@@ -519,6 +526,7 @@
  */
 void InitTask( struct sigcontext_struct context )
 {
+    static int firstTask = 1;
     TDB *pTask;
     NE_MODULE *pModule;
 
@@ -526,6 +534,22 @@
     if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return;
     if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return;
 
+    if (firstTask)
+    {
+        extern BOOL WIDGETS_Init(void);
+        extern BOOL WIN_CreateDesktopWindow(void);
+
+        /* Perform global initialisations that need a task context */
+
+          /* Initialize built-in window classes */
+        if (!WIDGETS_Init()) return;
+
+          /* Create desktop window */
+        if (!WIN_CreateDesktopWindow()) return;
+
+        firstTask = 0;
+    }
+
     NE_InitializeDLLs( pTask->hModule );
 
     /* Registers on return are:
@@ -602,6 +626,26 @@
 
 
 /***********************************************************************
+ *           LockCurrentTask  (KERNEL.33)
+ */
+HTASK LockCurrentTask( BOOL bLock )
+{
+    if (bLock) hLockedTask = hCurrentTask;
+    else hLockedTask = 0;
+    return hLockedTask;
+}
+
+
+/***********************************************************************
+ *           IsTaskLocked  (KERNEL.122)
+ */
+WORD IsTaskLocked(void)
+{
+    return hLockedTask;
+}
+
+
+/***********************************************************************
  *           OldYield  (KERNEL.117)
  */
 void OldYield(void)
@@ -747,6 +791,19 @@
 
 
 /***********************************************************************
+ *           GetInstanceData   (KERNEL.54)
+ */
+int GetInstanceData( HANDLE instance, WORD buffer, int len )
+{
+    char *ptr = (char *)GlobalLock( instance );
+    if (!ptr || !len) return 0;
+    if ((int)buffer + len >= 0x10000) len = 0x10000 - buffer;
+    memcpy( ptr + buffer, (char *)GlobalLock( CURRENT_DS ) + buffer, len );
+    return len;
+}
+
+
+/***********************************************************************
  *           GetNumTasks   (KERNEL.152)
  */
 WORD GetNumTasks(void)
diff --git a/memory/Imakefile b/memory/Imakefile
index 3364fec..8dbf16f 100644
--- a/memory/Imakefile
+++ b/memory/Imakefile
@@ -5,6 +5,7 @@
 SRCS = \
 	selector.c \
 	global.c \
+	ldt.c \
 	local.c
 
 OBJS = $(SRCS:.c=.o)
diff --git a/memory/global.c b/memory/global.c
index 7a0a144..d7fd15b 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -139,7 +139,7 @@
 
       /* Fixup the size */
 
-    if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x0f) return 0;
+    if (size >= GLOBAL_MAX_ALLOC_SIZE - 0x1f) return 0;
     if (size == 0) size = 0x20;
     else size = (size + 0x1f) & ~0x1f;
 
diff --git a/loader/ldt.c b/memory/ldt.c
similarity index 100%
rename from loader/ldt.c
rename to memory/ldt.c
diff --git a/memory/local.c b/memory/local.c
index 134c1bf..1cd4a58 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -17,6 +17,7 @@
 #include "ldt.h"
 #include "instance.h"
 #include "local.h"
+#include "module.h"
 #include "stackframe.h"
 #include "toolhelp.h"
 #include "stddebug.h"
@@ -39,13 +40,15 @@
 } LOCALARENA;
 
 #define ARENA_HEADER_SIZE      4
+#define ARENA_HEADER( handle) ( ((handle) & ~3) - ARENA_HEADER_SIZE)
 
   /* Arena types (stored in 'prev' field of the arena) */
 #define LOCAL_ARENA_FREE       0
 #define LOCAL_ARENA_FIXED      1
 #define LOCAL_ARENA_MOVEABLE   3
 
-
+#define LMEM_NOCOMPACT 0x0010
+#define LMEM_NODISCARD 0x0020
 
 typedef struct
 {
@@ -93,6 +96,9 @@
 #define ARENA_NEXT(ptr,arena)      (ARENA_PTR(ptr,arena)->next)
 #define ARENA_FLAGS(ptr,arena)     (ARENA_PTR(ptr,arena)->prev & 3)
 
+  /* determine whether the handle belongs to a fixed or a moveable block */
+#define HANDLE_FIXED(handle) (((handle) & 3) == 0)
+#define HANDLE_MOVEABLE(handle) (((handle) & 3) == 2)
 
 /***********************************************************************
  *           LOCAL_GetHeap
@@ -103,6 +109,7 @@
 {
     LOCALHEAPINFO *pInfo;
     INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 );
+    dprintf_local( stddeb, "Heap at %04x\n", ptr->heap );
     if (!ptr->heap) return 0;
     pInfo = (LOCALHEAPINFO*)((char*)ptr + ptr->heap);
     if (pInfo->magic != LOCAL_HEAP_MAGIC) return NULL;
@@ -138,6 +145,7 @@
         next = pNext->next;
     }
 
+    dprintf_local( stddeb, "Local_AddFreeBlock %04x, next %04x\n", block, next );
       /* Insert the free block in the free-list */
 
     pArena->free_prev = pNext->free_prev;
@@ -202,6 +210,7 @@
 
       /* Remove the block from the free-list */
 
+    dprintf_local( stddeb, "Local_RemoveBlock\n");
     pArena = ARENA_PTR( baseptr, block );
     if ((pArena->prev & 3) == LOCAL_ARENA_FREE)
         LOCAL_RemoveFreeBlock( baseptr, block );
@@ -229,6 +238,7 @@
     LOCALHEAPINFO *pInfo = LOCAL_GetHeap( ds );
     WORD arena;
 
+    if (!debugging_local) return;
     if (!pInfo)
     {
         printf( "Local Heap corrupted!  ds=%04x\n", ds );
@@ -266,7 +276,8 @@
         }
         if ((ARENA_PTR(ptr,pArena->next)->prev & ~3) != arena)
         {
-            printf( "*** arena->next->prev != arena\n" );
+            printf( "*** arena->next->prev != arena (%04x, %04x)\n",
+		   pArena->next, ARENA_PTR(ptr,pArena->next)->prev);
             break;
         }
         arena = pArena->next;
@@ -283,7 +294,8 @@
     WORD heapInfoArena, freeArena, lastArena;
     LOCALHEAPINFO *pHeapInfo;
     LOCALARENA *pArena, *pFirstArena, *pLastArena;
-
+    NE_MODULE *pModule;
+    
       /* The initial layout of the heap is: */
       /* - first arena         (FIXED)      */
       /* - heap info structure (FIXED)      */
@@ -295,14 +307,24 @@
     ptr = PTR_SEG_OFF_TO_LIN( selector, 0 );
     pHeapInfo = LOCAL_GetHeap(selector);
       /* If there's already a local heap in this segment, */
-      /* we simply return TRUE. Helps some programs, but  */
-      /* does not seem to be 100% correct yet (there are  */
-      /* still some "heap corrupted" messages in LocalAlloc */
+      /* we simply return TRUE. This helps some programs. */
     if (pHeapInfo)  {
       dprintf_local(stddeb,"LocalInit: Heap %04x initialized twice.\n",selector);
       if (debugging_local) LOCAL_PrintHeap(selector);
       return TRUE;
     }
+
+#if 0
+      /* Check if the segment is the DGROUP of a module */
+
+    if ((pModule = (NE_MODULE *)GlobalLock( GetExePtr( selector ) )))
+    {
+        SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
+        if (pModule->dgroup && (pSeg->selector == selector))
+            start = max( start, pSeg->minsize );
+    }
+#endif
+
     start = LALIGN( max( start, sizeof(INSTANCEDATA) ) );
     heapInfoArena = LALIGN(start + sizeof(LOCALARENA) );
     freeArena = LALIGN( heapInfoArena + ARENA_HEADER_SIZE
@@ -335,6 +357,7 @@
     pHeapInfo->items   = 4;
     pHeapInfo->first   = start;
     pHeapInfo->last    = lastArena;
+    pHeapInfo->htable  = 0;
     pHeapInfo->hdelta  = 0x20;
     pHeapInfo->extra   = 0x200;
     pHeapInfo->minsize = lastArena - freeArena;
@@ -352,7 +375,7 @@
       /* Initialise the last block */
 
     pLastArena = ARENA_PTR( ptr, lastArena );
-    pLastArena->prev      = heapInfoArena | LOCAL_ARENA_FREE;
+    pLastArena->prev      = freeArena | LOCAL_ARENA_FREE;
     pLastArena->next      = lastArena;  /* this one */
     pLastArena->size      = LALIGN(sizeof(LOCALARENA));
     pLastArena->free_prev = freeArena;
@@ -361,49 +384,80 @@
       /* Store the local heap address in the instance data */
 
     ((INSTANCEDATA *)ptr)->heap = heapInfoArena + ARENA_HEADER_SIZE;
+    LOCAL_PrintHeap( selector );
     return TRUE;
 }
 
+/***********************************************************************
+ *           LOCAL_Compact
+ */
+static WORD LOCAL_Compact( WORD ds, WORD minfree, WORD flags )
+{
+    if (flags & LMEM_NOCOMPACT) return 0;
+    
+    return 0;
+}
 
 /***********************************************************************
- *           LOCAL_Alloc
- *
- * Implementation of LocalAlloc().
+ *           LOCAL_FindFreeBlock
  */
-HLOCAL LOCAL_Alloc( WORD ds, WORD flags, WORD size )
+static HLOCAL LOCAL_FindFreeBlock( WORD ds, WORD size )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
     LOCALARENA *pArena;
     WORD arena;
 
-    dprintf_local( stddeb, "LocalAlloc: %04x %d ds=%04x\n", flags, size, ds );
-
-      /* Find a suitable free block */
-
     if (!(pInfo = LOCAL_GetHeap( ds ))) {
-      dprintf_local( stddeb, "LocalAlloc: Heap not found\n");
-      LOCAL_PrintHeap(ds);
-      return 0;
+	dprintf_local( stddeb, "Local_FindFreeBlock: Local heap not found\n" );
+	LOCAL_PrintHeap(ds);
+	return 0;
     }
-    size += ARENA_HEADER_SIZE;
-    size = LALIGN( max( size, sizeof(LOCALARENA) ) );
+
     arena = pInfo->first;
     pArena = ARENA_PTR( ptr, arena );
-    for (;;)
-    {
-        if (arena == pArena->free_next) {
-	  fprintf(stderr, "Local heap full\n");
-	  if (debugging_local) LOCAL_PrintHeap(ds);
-          return 0;  /* not found */
-	}
+    while (arena != pArena->free_next) {
         arena = pArena->free_next;
         pArena = ARENA_PTR( ptr, arena );
-        if (pArena->size >= size) break;
+        if (pArena->size >= size) return arena;
+    }
+    dprintf_local( stddeb, "Local_FindFreeBlock: not enough space\n" );
+    if (debugging_local) LOCAL_PrintHeap(ds);
+    return 0;
+}
+
+/***********************************************************************
+ *           LOCAL_GetBlock
+ */
+static HLOCAL LOCAL_GetBlock( WORD ds, WORD size, WORD flags )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHEAPINFO *pInfo;
+    LOCALARENA *pArena;
+    WORD arena;
+
+    if (!(pInfo = LOCAL_GetHeap( ds ))) {
+	dprintf_local( stddeb, "Local_GetBlock: Local heap not found\n");
+	LOCAL_PrintHeap(ds);
+	return 0;
+    }
+    
+    size += ARENA_HEADER_SIZE;
+    size = LALIGN( max( size, sizeof(LOCALARENA) ) );
+
+      /* Find a suitable free block */
+    arena = LOCAL_FindFreeBlock( ds, size );
+    if (arena == 0) {
+	LOCAL_Compact( ds, size, flags );
+	arena = LOCAL_FindFreeBlock( ds, size );
+    }
+    if (arena == 0) {
+	fprintf( stderr, "Local_GetBlock: not enough space!\n" );
     }
 
+    dprintf_local( stddeb, "LOCAL_GetBlock size = %04x\n", size );
       /* Make a block out of the free arena */
-
+    pArena = ARENA_PTR( ptr, arena );
     if (pArena->size > size + LALIGN(sizeof(LOCALARENA)))
     {
         LOCAL_AddBlock( ptr, arena, arena+size );
@@ -412,97 +466,78 @@
     }
     LOCAL_RemoveFreeBlock( ptr, arena );
 
-    dprintf_local( stddeb, "LocalAlloc: returning %04x\n",
-                   arena + ARENA_HEADER_SIZE );
+    dprintf_local( stddeb, "Local_GetBlock: arena at %04x\n", arena );
     return arena + ARENA_HEADER_SIZE;
 }
 
-
 /***********************************************************************
- *           LOCAL_ReAlloc
- *
- * Implementation of LocalReAlloc().
+ *           LOCAL_NewHTable
  */
-HLOCAL LOCAL_ReAlloc( WORD ds, HLOCAL handle, WORD size, WORD flags )
+static BOOL LOCAL_NewHTable( WORD ds )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
-    LOCALARENA *pArena, *pNext;
-    WORD arena, newhandle;
+    HLOCAL handle;
 
-    dprintf_local( stddeb, "LocalReAlloc: %04x %d %04x ds=%04x\n",
-                   handle, size, flags, ds );
-    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 );
-
-      /* Check for size reduction */
-
-    if (size < pArena->next - handle)
-    {
-        if (handle + size < pArena->next - LALIGN(sizeof(LOCALARENA)))
-        {
-              /* It is worth making a new free block */
-            LOCAL_AddBlock( ptr, arena, handle + size );
-            LOCAL_AddFreeBlock( ptr, handle + size );
-            pInfo->items++;
-        }
-        dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", handle );
-        return handle;
+    dprintf_local( stddeb, "Local_NewHTable\n" );
+    if (!(pInfo = LOCAL_GetHeap( ds ))) {
+      dprintf_local( stddeb, "Local heap not found\n");
+      LOCAL_PrintHeap(ds);
+      return FALSE;
     }
 
-      /* Check if the next block is free */
-
-    pNext = ARENA_PTR( ptr, pArena->next );
-    if (((pNext->prev & 3) == LOCAL_ARENA_FREE) &&
-        (size <= pNext->next - handle))
-    {
-        LOCAL_RemoveBlock( ptr, pArena->next );
-        if (handle + size < pArena->next - LALIGN(sizeof(LOCALARENA)))
-        {
-              /* It is worth making a new free block */
-            LOCAL_AddBlock( ptr, arena, handle + size );
-            LOCAL_AddFreeBlock( ptr, handle + size );
-            pInfo->items++;
-        }
-        dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", handle );
-        return handle;
-    }
-
-      /* Now we have to allocate a new block */
-
-    newhandle = LOCAL_Alloc( ds, flags, size );
-    if (!newhandle) return 0;
-    memcpy( ptr + newhandle, ptr + handle, pArena->next - handle );
-    LOCAL_Free( ds, handle );
-    dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", newhandle );
-    return newhandle;
+    handle = LOCAL_GetBlock( ds, pInfo->hdelta*4 + 2, LMEM_FIXED );
+    if (handle == 0) return FALSE;
+    *(WORD *)(ptr + handle) = 0; /* no handles in this block yet */
+    pInfo->htable = handle;
+    return TRUE;
 }
 
+/***********************************************************************
+ *           LOCAL_GetNewHandle
+ */
+static HLOCAL LOCAL_GetNewHandle( WORD ds )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHEAPINFO *pInfo;
+    WORD count;
+    
+    if (!(pInfo = LOCAL_GetHeap( ds ))) {
+	dprintf_local( stddeb, "LOCAL_GetNewHandle: Local heap not found\n");
+	LOCAL_PrintHeap(ds);
+	return 0;
+    }
+    /* Check if we need a new handle table */
+    if (pInfo->htable == 0) 
+        if (!LOCAL_NewHTable( ds )) return 0;
+    if (*(WORD *)(ptr + pInfo->htable) == pInfo->hdelta) 
+        if (!LOCAL_NewHTable( ds )) return 0;
+
+    /* increase count */
+    count = (*(WORD *)(ptr + pInfo->htable))++;
+    dprintf_local( stddeb, "Local_GetNewHandle: %04x\n", pInfo->htable + 2 + 4*count );
+    return pInfo->htable + 2 + 4*count;
+}
 
 /***********************************************************************
- *           LOCAL_Free
- *
- * Implementation of LocalFree().
+ *           LOCAL_FreeArena
  */
-HLOCAL LOCAL_Free( WORD ds, HLOCAL handle )
+HLOCAL LOCAL_FreeArena( WORD ds, WORD arena )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
     LOCALARENA *pArena, *pPrev, *pNext;
-    WORD arena;
 
-    dprintf_local( stddeb, "LocalFree: %04x ds=%04x\n", handle, ds );
-    if (!(pInfo = LOCAL_GetHeap( ds ))) return handle;
-    arena = handle - ARENA_HEADER_SIZE;
+    dprintf_local( stddeb, "LocalFreeArena: %04x ds=%04x\n", arena, ds );
+    if (!(pInfo = LOCAL_GetHeap( ds ))) return arena;
+
     pArena = ARENA_PTR( ptr, arena );
-    if ((pArena->prev & 3) == LOCAL_ARENA_FREE) return handle;
+    if ((pArena->prev & 3) == LOCAL_ARENA_FREE) {
+	/* shouldn't happen */
+	fprintf( stderr, "LocalFreeArena: Trying to free a block twice!\n" );
+	LOCAL_PrintHeap( ds );
+	return arena;
+    }
 
       /* Check if we can merge with the previous block */
 
@@ -533,6 +568,153 @@
 
 
 /***********************************************************************
+ *           LOCAL_Free
+ *
+ * Implementation of LocalFree().
+ */
+HLOCAL LOCAL_Free( WORD ds, HLOCAL handle )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    WORD arena;
+
+    dprintf_local( stddeb, "LocalFree: %04x ds=%04x\n", handle, ds );
+    
+    if (HANDLE_FIXED( handle )) {
+	arena = ARENA_HEADER( handle );
+    } else {
+	arena = ARENA_HEADER( *(WORD *)(ptr + handle) );
+	dprintf_local( stddeb, "LocalFree: real block at %04x\n", arena);
+    }
+    arena = LOCAL_FreeArena( ds, arena );
+    if (arena != 0) return handle; /* couldn't free it */
+    return 0;
+}
+
+
+/***********************************************************************
+ *           LOCAL_Alloc
+ *
+ * Implementation of LocalAlloc().
+ */
+HLOCAL LOCAL_Alloc( WORD ds, WORD flags, WORD size )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    HLOCAL handle;
+    
+    dprintf_local( stddeb, "LocalAlloc: %04x %d ds=%04x\n", flags, size, ds );
+
+    if (flags & LMEM_MOVEABLE) {
+	LOCALHANDLEENTRY *plhe;
+	HLOCAL hmem;
+	
+	hmem = LOCAL_GetBlock( ds, size + 2, flags );
+	if (hmem == 0) return 0;
+	handle = LOCAL_GetNewHandle( ds );
+	if (handle == 0) {
+	    fprintf( stderr, "LocalAlloc: couldn't get handle\n");
+	    LOCAL_FreeArena( ds, ARENA_HEADER(hmem) );
+	    return 0;
+	}
+	*(WORD *)(ptr + hmem) = handle;
+	plhe = (LOCALHANDLEENTRY *)(ptr + handle);
+	plhe->addr = hmem + 2;
+	plhe->lock = 0;
+    } else {
+	handle = LOCAL_GetBlock( ds, size, flags );
+    }
+    return handle;
+}
+
+
+/***********************************************************************
+ *           LOCAL_ReAlloc
+ *
+ * Implementation of LocalReAlloc().
+ */
+HLOCAL LOCAL_ReAlloc( WORD ds, HLOCAL handle, WORD size, WORD flags )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHEAPINFO *pInfo;
+    LOCALARENA *pArena, *pNext;
+    WORD arena, newhandle, blockhandle, nextarena;
+
+    dprintf_local( stddeb, "LocalReAlloc: %04x %d %04x ds=%04x\n",
+                   handle, size, flags, ds );
+    if (!(pInfo = LOCAL_GetHeap( ds ))) return 0;
+    
+    if (HANDLE_FIXED( handle )) {
+	blockhandle = handle;
+    } else {
+	size += 2;
+	blockhandle = *(WORD *)(ptr + handle);
+	dprintf_local( stddeb, "  blockhandle %04x (%04x)\n", blockhandle,
+		      *(WORD *)(ptr + blockhandle - 2));
+    }
+    arena = ARENA_HEADER( blockhandle );
+    dprintf_local( stddeb, "LocalReAlloc: arena is %04x\n", arena );
+    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 );
+    nextarena = LALIGN(blockhandle + size);
+
+      /* Check for size reduction */
+
+    if (nextarena < pArena->next)
+    {
+        if (nextarena < pArena->next - LALIGN(sizeof(LOCALARENA)))
+        {
+	    dprintf_local( stddeb, "size reduction, making new free block\n");
+              /* It is worth making a new free block */
+            LOCAL_AddBlock( ptr, arena, nextarena );
+            LOCAL_AddFreeBlock( ptr, nextarena );
+            pInfo->items++;
+        }
+        dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", handle );
+        return handle;
+    }
+
+      /* Check if the next block is free */
+
+    pNext = ARENA_PTR( ptr, pArena->next );
+    if (((pNext->prev & 3) == LOCAL_ARENA_FREE) &&
+        (nextarena <= pNext->next))
+    {
+        LOCAL_RemoveBlock( ptr, pArena->next );
+        if (nextarena < pArena->next - LALIGN(sizeof(LOCALARENA)))
+        {
+	    dprintf_local( stddeb, "size increase, making new free block\n");
+              /* It is worth making a new free block */
+            LOCAL_AddBlock( ptr, arena, nextarena );
+            LOCAL_AddFreeBlock( ptr, nextarena );
+            pInfo->items++;
+        }
+        dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", handle );
+        return handle;
+    }
+
+      /* Now we have to allocate a new block */
+
+    newhandle = LOCAL_GetBlock( ds, size, flags );
+    if (newhandle == 0) return 0;
+    memcpy( ptr + newhandle, ptr + (arena + ARENA_HEADER_SIZE), size );
+    LOCAL_FreeArena( ds, arena );
+    if (HANDLE_MOVEABLE( handle )) {
+	newhandle += 2;
+	dprintf_local( stddeb, "LocalReAlloc: fixing handle\n");
+	*(WORD *)(ptr + handle) = newhandle;
+	newhandle = handle;
+    }
+    dprintf_local( stddeb, "LocalReAlloc: returning %04x\n", newhandle );
+    return newhandle;
+}
+
+
+/***********************************************************************
  *           LOCAL_Size
  *
  * Implementation of LocalSize().
@@ -589,6 +771,11 @@
  */
 WORD LocalLock( HLOCAL handle )
 {
+    char *ptr = PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
+
+    if (HANDLE_MOVEABLE(handle)) {
+	handle = *(WORD *)(ptr + handle);
+    }
     return handle;
 }
 
@@ -616,7 +803,12 @@
  */
 HLOCAL LocalHandle( WORD addr )
 {
+    char *ptr = PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
+
     dprintf_local( stddeb, "LocalHandle: %04x\n", addr );
+    if (HANDLE_MOVEABLE( addr )) {
+	addr = *(WORD *)(ptr + addr - 2);
+    }
     return addr;
 }
 
diff --git a/misc/commdlg.c b/misc/commdlg.c
index d9a0f31..47d08ed 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -15,6 +15,8 @@
 #include "dlgs.h"
 #include "selectors.h"
 #include "../rc/sysres.h"
+#include "dos_fs.h"
+#include "stackframe.h"
 
 #define OPENFILEDLG2			11
 #define SAVEFILEDLG2			12
@@ -27,128 +29,28 @@
 static	HBITMAP		hHDisk = 0;
 static	HBITMAP		hCDRom = 0;
 
-int DOS_GetDefaultDrive(void);
-void DOS_SetDefaultDrive(int drive);
-char *DOS_GetCurrentDir(int drive);
-int DOS_ChangeDir(int drive, char *dirname);
-
-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);
-BOOL PrintDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
-BOOL PrintSetupDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
-BOOL ReplaceTextDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
-BOOL FindTextDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam);
-
-/***********************************************************************
- * COMMDLG_IsPathName [internal]
- */
-
-static BOOL COMMDLG_IsPathName(LPSTR str)
-{
-  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;
-}
-
 /***********************************************************************
  * 				FileDlg_Init			[internal]
  */
 static BOOL FileDlg_Init()
 {
-  if (!hFolder) hFolder = LoadBitmap(0, MAKEINTRESOURCE(OBM_FOLDER));
-  if (!hFolder2) hFolder2 = LoadBitmap(0, MAKEINTRESOURCE(OBM_FOLDER2));
-  if (!hFloppy) hFloppy = LoadBitmap(0, MAKEINTRESOURCE(OBM_FLOPPY));
-  if (!hHDisk) hHDisk = LoadBitmap(0, MAKEINTRESOURCE(OBM_HDISK));
-  if (!hCDRom) hCDRom = LoadBitmap(0, MAKEINTRESOURCE(OBM_CDROM));
-  if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
-      hHDisk == 0 || hCDRom == 0)
-  fprintf(stderr, "FileDlg_Init // Error loading bitmaps !");
-  return TRUE;
-}
-
-/***********************************************************************
- *                              OpenDlg_FixDirName              [internal]
- */
-void OpenDlg_FixDirName(LPSTR dirname)
-{
-  char temp[512];
-  char* strp1;
-  char* strp2;
-
-  strp1=dirname;
-  if( dirname[1] != ':'){
-    temp[0]=(char)((char)DOS_GetDefaultDrive()+'A');
-    temp[1]=':';
-    temp[2]='\\';
-    temp[3]= '\0';
-    strcat(temp, DOS_GetCurrentDir(DOS_GetDefaultDrive()));
-    if(dirname[0]=='.' && dirname[1]=='.') {
-      strp2 = strrchr(temp, '\\');
-      if (strp2 != NULL){
-	*strp2='\0';
-	strp1+=2;
-      }
-    }
-    strcat(temp, "\\");
-    strcat(temp, strp1);
-    strcpy(dirname, temp);
-  } 
-}
-  
-
-/***********************************************************************
- * 				OpenDlg_ScanDir			[internal]
- */
-static BOOL OpenDlg_ScanDir(HWND hWnd, LPSTR newPath)
-{
-  static HANDLE hStr = 0;
-  static LPSTR  str  = NULL;
-  static SEGPTR str16 = 0;
-  LPSTR strp;
-
-  OpenDlg_FixDirName(newPath);
-  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,"*.*");
-  DlgDirList(hWnd, str, lst2, stc1, 0x8010);
-  
-  return TRUE;
-}
-
-/***********************************************************************
- * 				OpenDlg_GetFileType		[internal]
- */
-static LPSTR OpenDlg_GetFileType(LPCSTR types, WORD index)
-{
-	int		n;
-	int		i = 1;
-	LPSTR 	ptr = (LPSTR) types;
-	if	(ptr == NULL) return NULL;
-	while((n = strlen(ptr)) != 0) {
-		ptr += ++n;
-		if (i++ == index) return ptr;
-		n = strlen(ptr);
-		ptr += ++n;
+    static BOOL initialized = 0;
+    
+    if (!initialized) {
+	if (!hFolder) hFolder = LoadBitmap(0, MAKEINTRESOURCE(OBM_FOLDER));
+	if (!hFolder2) hFolder2 = LoadBitmap(0, MAKEINTRESOURCE(OBM_FOLDER2));
+	if (!hFloppy) hFloppy = LoadBitmap(0, MAKEINTRESOURCE(OBM_FLOPPY));
+	if (!hHDisk) hHDisk = LoadBitmap(0, MAKEINTRESOURCE(OBM_HDISK));
+	if (!hCDRom) hCDRom = LoadBitmap(0, MAKEINTRESOURCE(OBM_CDROM));
+	if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 
+	    hHDisk == 0 || hCDRom == 0)
+	{	
+	    fprintf(stderr, "FileDlg_Init // Error loading bitmaps !");
+	    return FALSE;
 	}
-	return NULL;
+	initialized = TRUE;
+    }
+    return TRUE;
 }
 
 /***********************************************************************
@@ -162,6 +64,8 @@
   BOOL 	    bRet;
   LPCSTR    dlgTemplate;
   
+  if (!FileDlg_Init()) return FALSE;
+    
   if (lpofn == NULL) return FALSE;
   if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
     dlgTemplate = GlobalLock(lpofn->hInstance);
@@ -190,7 +94,7 @@
   hInst = GetWindowWord(lpofn->hwndOwner, GWW_HINSTANCE);
   bRet = DialogBoxIndirectParamPtr(hInst, dlgTemplate, lpofn->hwndOwner,
 				   GetWndProcEntry16("FileOpenDlgProc"),
-				   (DWORD)lpofn); 
+				   (DWORD)lpofn);
   
   printf("GetOpenFileName // return lpstrFile='%s' !\n", 
 	 (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
@@ -209,6 +113,8 @@
   BOOL	    bRet;
   LPCSTR    dlgTemplate;
   
+  if (!FileDlg_Init()) return FALSE;
+
   if (lpofn == NULL) return FALSE;
   if (lpofn->Flags & OFN_ENABLETEMPLATEHANDLE) {
     dlgTemplate = GlobalLock(lpofn->hInstance);
@@ -243,100 +149,210 @@
   return bRet;
 }
 
-
 /***********************************************************************
- * 				ChooseColor				[COMMDLG.5]
+ *                              FILEDLG_StripEditControl        [internal]
+ * Strip pathnames off the contents of the edit control.
  */
-BOOL ChooseColor(LPCHOOSECOLOR lpChCol)
+static void FILEDLG_StripEditControl(HWND hwnd)
 {
-        WND     *wndPtr;
-	BOOL	bRet;
-        wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
-	bRet = DialogBoxIndirectParamPtr(wndPtr->hInstance, sysres_DIALOG_8,
-		lpChCol->hwndOwner, GetWndProcEntry16("ColorDlgProc"), 
-		(DWORD)lpChCol);
-	return bRet;
+    char temp[512], *cp;
+
+    SendDlgItemMessage(hwnd, edt1, WM_GETTEXT, 511, MAKE_SEGPTR(temp));
+    cp = strrchr(temp, '\\');
+    if (cp != NULL) {
+	strcpy(temp, cp+1);
+    }
+    cp = strrchr(temp, ':');
+    if (cp != NULL) {
+	strcpy(temp, cp+1);
+    }
 }
 
+/***********************************************************************
+ * 				FILEDLG_ScanDir			[internal]
+ */
+static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath)
+{
+  char str[512],str2[512];
+
+  strcpy(str,newPath);
+  SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, MAKE_SEGPTR(str2));
+  strcat(str, str2);
+  if (!DlgDirList(hWnd, str, lst1, 0, 0x0000)) return FALSE;
+  DlgDirList(hWnd, "*.*", lst2, stc1, 0x8010);
+  
+  return TRUE;
+}
 
 /***********************************************************************
- * 				FileOpenDlgProc			[COMMDLG.6]
+ * 				FILEDLG_GetFileType		[internal]
  */
-BOOL FileOpenDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
+static LPSTR FILEDLG_GetFileType(LPSTR ptr, WORD index)
 {
-  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;
+    int n, i;
+    
+    if	(ptr == NULL) return NULL;
+    
+    for (i = 1;;i++) {
+	n = strlen(ptr);
+	if (n == 0) break;
+	ptr += n + 1;
+	if (i == index) return ptr;
+	n = strlen(ptr);
+	ptr += n + 1;
     }
+    return NULL;
+}
+
+/***********************************************************************
+ *                              FILEDLG_WMDrawItem              [internal]
+ */
+static LONG FILEDLG_WMDrawItem(HWND hWnd, WORD wParam, LONG lParam)
+{
+    LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    LPSTR str;
+    HBRUSH hBrush;
+    HBITMAP hBitmap, hPrevBitmap;
+    BITMAP bm;
+    HDC hMemDC;
+    
+    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);
+	str = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+	if (str != NULL)  {
+	    TextOut(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+		    str, strlen(str));
+	    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);
+	str = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+	if (str != NULL)  {
+	    hBitmap = hFolder;
+	    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
+	    TextOut(lpdis->hDC, lpdis->rcItem.left + bm.bmWidth, 
+		    lpdis->rcItem.top, str, strlen(str));
+	    hMemDC = CreateCompatibleDC(lpdis->hDC);
+	    hPrevBitmap = SelectObject(hMemDC, hBitmap);
+	    BitBlt(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+		   bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	    SelectObject(hMemDC, hPrevBitmap);
+	    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);
+	str = (LPSTR) PTR_SEG_TO_LIN(lpdis->itemData);
+	if (str != NULL) {
+	    switch(str[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, str, strlen(str));
+	    hMemDC = CreateCompatibleDC(lpdis->hDC);
+	    hPrevBitmap = SelectObject(hMemDC, hBitmap);
+	    BitBlt(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
+		   bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	    SelectObject(hMemDC, hPrevBitmap);
+	    DeleteDC(hMemDC);
+	    if (lpdis->itemState != 0) {
+		InvertRect(lpdis->hDC, &lpdis->rcItem);
+	    }
+	}
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/***********************************************************************
+ *                              FILEDLG_WMMeasureItem           [internal]
+ */
+static LONG FILEDLG_WMMeasureItem(HWND hWnd, WORD wParam, LONG lParam) 
+{
+    BITMAP bm;
+    LPMEASUREITEMSTRUCT lpmeasure;
+    
+    GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
+    lpmeasure = (LPMEASUREITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
+    lpmeasure->itemHeight = bm.bmHeight;
+    return TRUE;
+}
+
+/***********************************************************************
+ *                              FILEDLG_WMInitDialog            [internal]
+ */
+static LONG FILEDLG_WMInitDialog(HWND hWnd, WORD wParam, LONG lParam) 
+{
+    int n;
+    LPOPENFILENAME lpofn;
+    char tmpstr[512];
+    LPSTR pstr;
+    
+    SetWindowLong(hWnd, DWL_USER, lParam);
+    lpofn = (LPOPENFILENAME)lParam;
+    
+    /* read filter information */
+    pstr = (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFilter);
+    while(*pstr) {
+      n = strlen(pstr);
+      strcpy(tmpstr, pstr);
+      SendDlgItemMessage(hWnd, cmb1, CB_ADDSTRING, 0, MAKE_SEGPTR(tmpstr));
+      pstr += n + 1;
+      n = strlen(pstr);
+      pstr += 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,"");
+		       lpofn->nFilterIndex - 1, 0);
+    strcpy(tmpstr, FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), 
+				       lpofn->nFilterIndex));
+    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr));
+      
+    /* get drive list */
+    strcpy(tmpstr,"");
+    DlgDirListComboBox(hWnd, MAKE_SEGPTR(tmpstr), cmb2, 0, 0xC000);
+
+    /* read initial directory */
+    if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) {
+	strcpy(tmpstr, PTR_SEG_TO_LIN(lpofn->lpstrInitialDir));
+	if (strlen(tmpstr) > 0 && tmpstr[strlen(tmpstr)-1] != '\\' 
+	    && tmpstr[strlen(tmpstr)-1] != ':')
+	{
+	    strcat(tmpstr,"\\");
+	}
+    } else {
+	strcpy(tmpstr,"");
     }
-    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 (!FILEDLG_ScanDir(hWnd, tmpstr)) {
+	fprintf(stderr, "FileDlg: couldn't read initial directory!\n");
+    } 
+
+    /* select current drive in combo 2 */
+    n = DOS_GetDefaultDrive();
+    SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, n, 0);
     
-    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);
     }
@@ -344,162 +360,157 @@
       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;
+/***********************************************************************
+ *                              FILEDLG_WMCommand               [internal]
+ */
+static LONG FILEDLG_WMCommand(HWND hWnd, WORD wParam, LONG lParam) 
+{
+    LONG lRet;
+    LPOPENFILENAME lpofn;
+    char tmpstr[512], tmpstr2[512];
+    LPSTR pstr, pstr2;
     
-   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:
+    lpofn = (LPOPENFILENAME)GetWindowLong(hWnd, DWL_USER);
     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);
+	FILEDLG_StripEditControl(hWnd);
+	if (HIWORD(lParam) == LBN_DBLCLK) {
+	    lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0);
+	    if (lRet == LB_ERR) return TRUE;
+	    SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, lRet, MAKE_SEGPTR(tmpstr));
+	    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr));
+	    return SendMessage(hWnd, WM_COMMAND, IDOK, 0);
 	}
-	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;
+	return TRUE;
+     case lst2:
+	FILEDLG_StripEditControl(hWnd);
+	if (HIWORD(lParam) == LBN_DBLCLK) {
+	    lRet = SendDlgItemMessage(hWnd, lst2, LB_GETCURSEL, 0, 0);
+	    if (lRet == LB_ERR) return TRUE;
+	    SendDlgItemMessage(hWnd, lst2, LB_GETTEXT, lRet, MAKE_SEGPTR(tmpstr));
+	    
+	    if (tmpstr[0] == '[') {
+		tmpstr[strlen(tmpstr) - 1] = 0;
+		strcpy(tmpstr,tmpstr+1);
+	    }
+	    strcat(tmpstr, "\\");
+	    FILEDLG_ScanDir(hWnd, tmpstr);
+	}
+	return TRUE;
+	
      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;
+	if (HIWORD(lParam) == CBN_SELCHANGE) {
+	    lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+	    if (lRet == LB_ERR) return TRUE;
+	    strcpy(tmpstr, FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter), 
+					       lRet + 1));
+	    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr));
+	    FILEDLG_ScanDir(hWnd, "");
+	}
+	return TRUE;
+	
      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;
+	FILEDLG_StripEditControl(hWnd);
+	lRet = SendDlgItemMessage(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
+	if (lRet == LB_ERR) return 0;
+	SendDlgItemMessage(hWnd, cmb2, CB_GETLBTEXT, lRet, MAKE_SEGPTR(tmpstr));
+	sprintf(tmpstr, "%c:", tmpstr[2]);
+	FILEDLG_ScanDir(hWnd, tmpstr);
+	return TRUE;
+	
      case chx1:
-#ifdef DEBUG_OPENDLG
-      printf("FileOpenDlgProc // read-only toggled !\n");
-#endif
-      break;
+	return TRUE;
+	
      case pshHelp:
-#ifdef DEBUG_OPENDLG
-      printf("FileOpenDlgProc // pshHelp pressed !\n");
-#endif
-      break;
+	return TRUE;
+
      case IDOK:
-      SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, str16);
-      if (COMMDLG_IsPathName(str)) {
-	OpenDlg_ScanDir(hWnd, str);
-      } else  {	
-	ShowWindow(hWnd, SW_HIDE); 
-	strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFile), str);
+	SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, MAKE_SEGPTR(tmpstr));
+
+	pstr = strrchr(tmpstr, '\\');
+	if (pstr == NULL) pstr = strrchr(tmpstr, ':');
+	
+	if (strchr(tmpstr,'*') != NULL || strchr(tmpstr,'?') != NULL) {
+	    /* edit control contains wildcards */
+	    if (pstr != NULL) {
+		strcpy(tmpstr2, pstr+1);
+		*(pstr+1) = 0;
+	    } else {
+		strcpy(tmpstr2, tmpstr);
+		strcpy(tmpstr, "");
+	    }
+	    printf("commdlg: %s, %s\n", tmpstr, tmpstr2);
+	    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr2));
+	    FILEDLG_ScanDir(hWnd, tmpstr);
+	    return TRUE;
+	}
+
+	/* no wildcards, we might have a directory or a filename */
+	/* try appending a wildcard and reading the directory */
+	pstr2 = tmpstr + strlen(tmpstr);
+	if (pstr == NULL || *(pstr+1) != 0) {
+	    strcat(tmpstr, "\\");
+	}
+	lRet = SendDlgItemMessage(hWnd, cmb1, CB_GETCURSEL, 0, 0);
+	if (lRet == LB_ERR) return TRUE;
+	strcpy(tmpstr2, FILEDLG_GetFileType(PTR_SEG_TO_LIN(lpofn->lpstrFilter),
+					    lRet + 1));
+	SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr2));
+	/* if ScanDir succeeds, we have changed the directory */
+	if (FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
+	
+	/* if not, this must be a filename */
+	*pstr2 = 0;
+	
+	if (pstr != NULL) {
+	    /* strip off the pathname */
+	    *pstr = 0;
+	    strcpy(tmpstr2, pstr+1);
+	    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr2));
+	    /* Should we MessageBox() if this fails? */
+	    if (!FILEDLG_ScanDir(hWnd, tmpstr)) return TRUE;
+	    strcpy(tmpstr, tmpstr2);
+	} else {
+	    SendDlgItemMessage(hWnd, edt1, WM_SETTEXT, 0, MAKE_SEGPTR(tmpstr));
+	}
+	
+	ShowWindow(hWnd, SW_HIDE);
+	strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFile), tmpstr);
 	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);
+	    lRet = SendDlgItemMessage(hWnd, lst1, LB_GETCURSEL, 0, 0);
+	    SendDlgItemMessage(hWnd, lst1, LB_GETTEXT, lRet, MAKE_SEGPTR(tmpstr));
+	    strcpy(PTR_SEG_TO_LIN(lpofn->lpstrFileTitle), tmpstr);
 	}
 	EndDialog(hWnd, TRUE);
-      }
-      return TRUE;
+	return TRUE;
      case IDCANCEL:
-      EndDialog(hWnd, FALSE);
-      return TRUE;
+	EndDialog(hWnd, FALSE);
+	return TRUE;
     }
-/*    return FALSE;*/
+    return FALSE;
+}
+
+/***********************************************************************
+ * 				FileOpenDlgProc			[COMMDLG.6]
+ */
+BOOL FileOpenDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
+{  
+  switch (wMsg) {
+   case WM_INITDIALOG:
+      return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
+      
+   case WM_MEASUREITEM:
+      return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
+    
+   case WM_DRAWITEM:
+      return FILEDLG_WMDrawItem(hWnd, wParam, lParam);
+
+   case WM_COMMAND:
+      return FILEDLG_WMCommand(hWnd, wParam, lParam);
   }
   
   /*
@@ -526,245 +537,20 @@
  */
 BOOL FileSaveDlgProc(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("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;
-
+      return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
+      
    case WM_MEASUREITEM:
-    GetObject(hFolder2, sizeof(BITMAP), (LPSTR)&bm);
-    lpmeasure = (LPMEASUREITEMSTRUCT)PTR_SEG_TO_LIN(lParam);
-    lpmeasure->itemHeight = bm.bmHeight;
-    return TRUE;
+      return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
     
    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);
+      return FILEDLG_WMDrawItem(hWnd, wParam, lParam);
 
-	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 // read-only toggled !\n");
-#endif
-      break;
-     case pshHelp:
-#ifdef DEBUG_OPENDLG
-      printf("FileSaveDlgProc // pshHelp pressed !\n");
-#endif
-      break;
-     case IDOK:
-      SendDlgItemMessage(hWnd, edt1, WM_GETTEXT, 511, 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_COMMAND:
+      return FILEDLG_WMCommand(hWnd, wParam, lParam);
   }
   
-  
   /*
   case WM_CTLCOLOR:
    SetBkColor((HDC)wParam, 0x00C0C0C0);
@@ -785,6 +571,21 @@
 
 
 /***********************************************************************
+ * 				ChooseColor				[COMMDLG.5]
+ */
+BOOL ChooseColor(LPCHOOSECOLOR lpChCol)
+{
+        WND     *wndPtr;
+	BOOL	bRet;
+        wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
+	bRet = DialogBoxIndirectParamPtr(wndPtr->hInstance, sysres_DIALOG_8,
+		lpChCol->hwndOwner, GetWndProcEntry16("ColorDlgProc"), 
+		(DWORD)lpChCol);
+	return bRet;
+}
+
+
+/***********************************************************************
  * 				ColorDlgProc			[COMMDLG.8]
  */
 BOOL ColorDlgProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
diff --git a/misc/compobj.c b/misc/compobj.c
index c527b0f..690cfa4 100644
--- a/misc/compobj.c
+++ b/misc/compobj.c
@@ -20,6 +20,6 @@
 	LPUNKNOWN lpUnk,
 	DWORD reserved)
 {
-    dprintf_ole(stdnimp,"CoDisconnectObject:%x %x\n",lpUnk,reserved);
+    dprintf_ole(stdnimp,"CoDisconnectObject:%p %lx\n",lpUnk,reserved);
     return OLE_OK;
 }
diff --git a/misc/shell.c b/misc/shell.c
index bab7b02..f300710 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -458,13 +458,10 @@
 
 /*************************************************************************
  *              DoEnvironmentSubst      [SHELL.37]
- * I couldn't find any reference, so even the number of bytes on the
- * stack might be wrong
  */
-WORD DoEnvironmentSubst(LPSTR a,WORD b,WORD c)
+DWORD DoEnvironmentSubst(LPSTR str,WORD len)
 {
-    printf(stderr, "DoEnvironmentSubst: Unknown argument count\n");
-    dprintf_reg(stdnimp, "DoEnvironmentSubst %x %x %x\n",a,b,c);
+    dprintf_reg(stdnimp, "DoEnvironmentSubst(%s,%x): Empyt Stub !!!\n",str,len);
     return 0;
 }
 
diff --git a/misc/user.c b/misc/user.c
index d9bf1d8..9e0333f 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -92,24 +92,8 @@
  */
 int USER_InitApp(int hInstance)
 {
-    extern BOOL WIDGETS_Init(void);
-
-    static int firstTask = 1;
     int queueSize;
 
-    if (firstTask)
-    {
-        /* Perform global initialisations that need a task context */
-
-          /* Initialize built-in window classes */
-        if (!WIDGETS_Init()) return 0;
-
-          /* Create desktop window */
-        if (!WIN_CreateDesktopWindow()) return 0;
-
-        firstTask = 0;
-    }
-
       /* Create task message queue */
     queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
     if (!SetMessageQueue( queueSize )) return 0;
diff --git a/miscemu/Imakefile b/miscemu/Imakefile
index 11e3840..70a5b6a 100644
--- a/miscemu/Imakefile
+++ b/miscemu/Imakefile
@@ -15,6 +15,8 @@
 	int2a.c \
 	int2f.c \
 	int31.c \
+	int5c.c \
+	interrupts.c \
 	ioports.c
 
 OBJS = $(SRCS:.c=.o)
diff --git a/miscemu/int21.c b/miscemu/int21.c
index e4bb91f..f0af67b 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -1324,10 +1324,7 @@
 	    break;
 		
 	  case 0x25: /* SET INTERRUPT VECTOR */
-	    /* Ignore any attempt to set a segment vector */
- 		dprintf_int(stddeb,
-			"int21: set interrupt vector %2x (%04x:%04x)\n",
-			AL, DS, DX);
+            INT_SetHandler( AL, MAKELONG( DX, DS ) );
             break;
 
 	  case 0x2a: /* GET SYSTEM DATE */
@@ -1396,12 +1393,11 @@
 	    break;
 
 	  case 0x35: /* GET INTERRUPT VECTOR */
-	    /* Return a NULL segment selector - this will bomb, 
-	    		if anyone ever tries to use it */
-	    dprintf_int(stddeb, "int21: get interrupt vector %2x\n",
-		AX & 0xff);
-	    ES = 0;
-	    BX = 0;
+            {
+                SEGPTR addr = INT_GetHandler( AL );
+                ES = SELECTOROF(addr);
+                BX = OFFSETOF(addr);
+            }
 	    break;
 
 	  case 0x36: /* GET FREE DISK SPACE */
@@ -1734,8 +1730,9 @@
     return 1;
 }
 
-/**********************************************************************
- *			DOS3Call
+
+/***********************************************************************
+ *           DOS3Call  (KERNEL.102)
  */
 void DOS3Call( struct sigcontext_struct context )
 {
diff --git a/miscemu/int5c.c b/miscemu/int5c.c
new file mode 100644
index 0000000..060da76
--- /dev/null
+++ b/miscemu/int5c.c
@@ -0,0 +1,33 @@
+/*
+ * NetBIOS interrupt handling
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include "miscemu.h"
+#include "registers.h"
+#include "wine.h"
+#include "stddebug.h"
+/* #define DEBUG_INT */
+#include "debug.h"
+
+
+/***********************************************************************
+ *           do_int5c
+ */
+int do_int5c(struct sigcontext_struct * context)
+{
+    dprintf_int(stddeb,"NetBiosCall: 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);
+    return 0;
+}
+
+
+/***********************************************************************
+ *           NetBIOSCall  (KERNEL.103)
+ */
+void NetBIOSCall( struct sigcontext_struct context )
+{
+    do_int5c( &context );
+}
diff --git a/miscemu/interrupts.c b/miscemu/interrupts.c
new file mode 100644
index 0000000..01f957e
--- /dev/null
+++ b/miscemu/interrupts.c
@@ -0,0 +1,190 @@
+/*
+ * Interrupt vectors emulation
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#include "windows.h"
+#include "miscemu.h"
+#include "module.h"
+#include "stddebug.h"
+#include "debug.h"
+
+static SEGPTR INT_Vectors[256];
+
+  /* Ordinal number for interrupt 0 handler in WINPROCS.DLL */
+#define FIRST_INTERRUPT_ORDINAL 100
+
+
+/**********************************************************************
+ *	    INT_Init
+ */
+BOOL INT_Init(void)
+{
+    SEGPTR addr, dummyHandler;
+    WORD vector;
+    HMODULE hModule = GetModuleHandle( "WINPROCS" );
+
+    dummyHandler = MODULE_GetEntryPoint( hModule, FIRST_INTERRUPT_ORDINAL+256);
+    for (vector = 0; vector < 256; vector++)
+    {
+        addr = MODULE_GetEntryPoint( hModule, FIRST_INTERRUPT_ORDINAL+vector );
+        INT_Vectors[vector] = addr ? addr : dummyHandler;
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    INT_GetHandler
+ *
+ * Return the interrupt vector for a given interrupt.
+ */
+SEGPTR INT_GetHandler( BYTE intnum )
+{
+    dprintf_int( stddeb, "Get interrupt vector %02x -> %04x:%04x\n",
+                 intnum, HIWORD(INT_Vectors[intnum]),
+                 LOWORD(INT_Vectors[intnum]) );
+    return INT_Vectors[intnum];
+}
+
+
+/**********************************************************************
+ *	    INT_SetHandler
+ *
+ * Set the interrupt handler for a given interrupt.
+ */
+void INT_SetHandler( BYTE intnum, SEGPTR handler )
+{
+    dprintf_int( stddeb, "Set interrupt vector %02x <- %04x:%04x\n",
+                 intnum, HIWORD(handler), LOWORD(handler) );
+    INT_Vectors[intnum] = handler;
+}
+
+
+/**********************************************************************
+ *	    INT_DummyHandler
+ */
+void INT_DummyHandler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "Dummy handler called!\n" );
+}
+
+/**********************************************************************
+ *	    INT_Int10Handler
+ */
+void INT_Int10Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 10 called indirectly through handler!\n" );
+    do_int10( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int13Handler
+ */
+void INT_Int13Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 13 called indirectly through handler!\n" );
+    do_int13( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int15Handler
+ */
+void INT_Int15Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 15 called indirectly through handler!\n" );
+    do_int15( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int16Handler
+ */
+void INT_Int16Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 16 called indirectly through handler!\n" );
+    do_int16( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int1aHandler
+ */
+void INT_Int1aHandler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 1a called indirectly through handler!\n" );
+    do_int1a( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int21Handler
+ */
+void INT_Int21Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 21 called indirectly through handler!\n" );
+    do_int21( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int25Handler
+ */
+void INT_Int25Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 25 called indirectly through handler!\n" );
+    do_int25( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int26Handler
+ */
+void INT_Int26Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 26 called indirectly through handler!\n" );
+    do_int26( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int2aHandler
+ */
+void INT_Int2aHandler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 2a called indirectly through handler!\n" );
+    do_int2a( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int2fHandler
+ */
+void INT_Int2fHandler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 2f called indirectly through handler!\n" );
+    do_int2f( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int31Handler
+ */
+void INT_Int31Handler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 31 called indirectly through handler!\n" );
+    do_int31( &context );
+}
+
+
+/**********************************************************************
+ *	    INT_Int5cHandler
+ */
+void INT_Int5cHandler( struct sigcontext_struct context )
+{
+    dprintf_int( stddeb, "int 5c called indirectly through handler!\n" );
+    do_int5c( &context );
+}
diff --git a/objects/bitblt.c b/objects/bitblt.c
index 6822f53..f5037b0 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -9,6 +9,7 @@
 #include <X11/Xlib.h>
 #include <X11/Intrinsic.h>
 #include "bitmap.h"
+#include "callback.h"
 #include "color.h"
 #include "dc.h"
 #include "metafile.h"
@@ -581,7 +582,7 @@
     register short i;
 
     pdata += swap ? start+width-1 : start;
-    if (image->depth == depthDst)
+    if (image->depth == depthDst)  /* color -> color */
     {
         if (COLOR_PixelToPalette && (depthDst != 1))
             if (swap) for (i = 0; i < width; i++)
@@ -596,16 +597,25 @@
     }
     else
     {
-        if (image->depth == 1)
+        if (image->depth == 1)  /* monochrome -> color */
+        {
+            if (COLOR_PixelToPalette)
+            {
+                fg = COLOR_PixelToPalette[fg];
+                bg = COLOR_PixelToPalette[bg];
+            }
             if (swap) for (i = 0; i < width; i++)
                 *pdata-- = XGetPixel( image, i, row ) ? bg : fg;
             else for (i = 0; i < width; i++)
                 *pdata++ = XGetPixel( image, i, row ) ? bg : fg;
-        else
+        }
+        else  /* color -> monochrome */
+        {
             if (swap) for (i = 0; i < width; i++)
                 *pdata-- = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
             else for (i = 0; i < width; i++)
                 *pdata++ = (XGetPixel( image, i, row ) == bg) ? 1 : 0;
+        }
     }
 }
 
@@ -1203,8 +1213,9 @@
     dprintf_bitblt(stddeb, "PatBlt: %d %d,%d %dx%d %06lx\n",
 	    hdc, left, top, width, height, rop );
 
-    return BITBLT_InternalStretchBlt( dc, left, top, width, height,
-                                      NULL, 0, 0, 0, 0, rop );
+    return CallTo32_LargeStack( (int(*)())BITBLT_InternalStretchBlt, 11,
+                                 dc, left, top, width, height,
+                                 NULL, 0, 0, 0, 0, rop );
 }
 
 
@@ -1231,8 +1242,9 @@
                 hdcDst, xDst, yDst, width, height, dcDst->w.bitsPerPixel, rop);
     dprintf_bitblt(stddeb,"        src org=%d,%d  dst org=%d,%d\n",
                 dcSrc->w.DCOrgX, dcSrc->w.DCOrgY, dcDst->w.DCOrgX, dcDst->w.DCOrgY );
-    return BITBLT_InternalStretchBlt( dcDst, xDst, yDst, width, height,
-                                      dcSrc, xSrc, ySrc, width, height, rop );
+    return CallTo32_LargeStack( (int(*)())BITBLT_InternalStretchBlt, 11,
+                                dcDst, xDst, yDst, width, height,
+                                dcSrc, xSrc, ySrc, width, height, rop );
 }
 
 
@@ -1261,7 +1273,7 @@
                    dcSrc ? dcSrc->w.bitsPerPixel : 0, hdcDst, xDst, yDst,
                    widthDst, heightDst, dcDst->w.bitsPerPixel, rop );
 
-    return BITBLT_InternalStretchBlt( dcDst, xDst, yDst, widthDst, heightDst,
-                                      dcSrc, xSrc, ySrc, widthSrc, heightSrc,
-                                      rop );
+    return CallTo32_LargeStack( (int(*)())BITBLT_InternalStretchBlt, 11,
+                                dcDst, xDst, yDst, widthDst, heightDst,
+                                dcSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
 }
diff --git a/objects/bitmap.c b/objects/bitmap.c
index e394ccb..e0f15c4 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -2,15 +2,14 @@
  * GDI bitmap objects
  *
  * Copyright 1993 Alexandre Julliard
- *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
-*/
+ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include "gdi.h"
 #include "arch.h"
+#include "callback.h"
 #include "dc.h"
 #include "bitmap.h"
 #include "prototypes.h"
@@ -81,10 +80,43 @@
 HBITMAP CreateBitmap( short width, short height, 
 		      BYTE planes, BYTE bpp, LPSTR bits )
 {
-    BITMAP bitmap = { 0, width, height, 0, planes, bpp, bits };
-    dprintf_gdi(stddeb, "CreateBitmap: %dx%d, %d colors\n", 
-	     width, height, 1 << (planes*bpp) );
-    return CreateBitmapIndirect( &bitmap );
+    BITMAPOBJ * bmpObjPtr;
+    HBITMAP hbitmap;
+
+    dprintf_gdi( stddeb, "CreateBitmap: %dx%d, %d colors\n", 
+                 width, height, 1 << (planes*bpp) );
+
+      /* Check parameters */
+    if (!height || !width || planes != 1) return 0;
+    if ((bpp != 1) && (bpp != screenDepth)) return 0;
+    if (height < 0) height = -height;
+    if (width < 0) width = -width;
+
+      /* Create the BITMAPOBJ */
+    hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
+    if (!hbitmap) return 0;
+    bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LIN_ADDR( hbitmap );
+
+    bmpObjPtr->size.cx = 0;
+    bmpObjPtr->size.cy = 0;
+    bmpObjPtr->bitmap.bmType = 0;
+    bmpObjPtr->bitmap.bmWidth = width;
+    bmpObjPtr->bitmap.bmHeight = height;
+    bmpObjPtr->bitmap.bmPlanes = planes;
+    bmpObjPtr->bitmap.bmBitsPixel = bpp;
+    bmpObjPtr->bitmap.bmWidthBytes = (width * bpp + 15) / 16 * 2;
+    bmpObjPtr->bitmap.bmBits = NULL;
+
+      /* Create the pixmap */
+    bmpObjPtr->pixmap = XCreatePixmap(display, rootWindow, width, height, bpp);
+    if (!bmpObjPtr->pixmap)
+    {
+	GDI_HEAP_FREE( hbitmap );
+	hbitmap = 0;
+    }
+    else if (bits)  /* Set bitmap bits */
+	SetBitmapBits( hbitmap, height * bmpObjPtr->bitmap.bmWidthBytes, bits);
+    return hbitmap;
 }
 
 
@@ -106,43 +138,8 @@
  */
 HBITMAP CreateBitmapIndirect( BITMAP * bmp )
 {
-    BITMAPOBJ * bmpObjPtr;
-    HBITMAP hbitmap;
-
-      /* Check parameters */
-    if (!bmp->bmHeight || !bmp->bmWidth) return 0;
-    if (bmp->bmPlanes != 1) return 0;
-    if ((bmp->bmBitsPixel != 1) && (bmp->bmBitsPixel != screenDepth)) return 0;
-
-    if (bmp->bmHeight < 0)
-	bmp->bmHeight = -bmp->bmHeight;
-    
-    if (bmp->bmWidth < 0)
-	bmp->bmWidth = -bmp->bmWidth;
-    
-
-      /* Create the BITMAPOBJ */
-    hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
-    if (!hbitmap) return 0;
-    bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LIN_ADDR( hbitmap );
-
-    bmpObjPtr->size.cx = 0;
-    bmpObjPtr->size.cy = 0;
-    bmpObjPtr->bitmap  = *bmp;
-    bmpObjPtr->bitmap.bmBits = NULL;
-    bmpObjPtr->bitmap.bmWidthBytes = (bmp->bmWidth*bmp->bmBitsPixel+15)/16 * 2;
-
-      /* Create the pixmap */
-    bmpObjPtr->pixmap = XCreatePixmap( display, rootWindow, bmp->bmWidth,
-				       bmp->bmHeight, bmp->bmBitsPixel );
-    if (!bmpObjPtr->pixmap)
-    {
-	GDI_HEAP_FREE( hbitmap );
-	hbitmap = 0;
-    }
-    else if (bmp->bmBits)  /* Set bitmap bits */
-	SetBitmapBits( hbitmap, bmpObjPtr->bitmap.bmHeight*bmpObjPtr->bitmap.bmWidthBytes, bmp->bmBits );
-    return hbitmap;
+    return CreateBitmap( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
+                         bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
 }
 
 
@@ -167,8 +164,9 @@
     if (!height) return 0;
     
     if (!(image = BITMAP_BmpToImage( &bmp->bitmap, buffer ))) return 0;
-    XGetSubImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth, height,
-		  AllPlanes, ZPixmap, image, 0, 0 );
+    CallTo32_LargeStack( (int(*)())XGetSubImage, 11,
+                         display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
+                         height, AllPlanes, ZPixmap, image, 0, 0 );
     image->data = NULL;
     XDestroyImage( image );
     return height * bmp->bitmap.bmWidthBytes;
@@ -197,8 +195,9 @@
     if (!height) return 0;
     	
     if (!(image = BITMAP_BmpToImage( &bmp->bitmap, buffer ))) return 0;
-    XPutImage( display, bmp->pixmap, BITMAP_GC(bmp), image, 0, 0,
-	       0, 0, bmp->bitmap.bmWidth, height );
+    CallTo32_LargeStack( XPutImage, 10,
+                         display, bmp->pixmap, BITMAP_GC(bmp), image, 0, 0,
+                         0, 0, bmp->bitmap.bmWidth, height );
     image->data = NULL;
     XDestroyImage( image );
     return height * bmp->bitmap.bmWidthBytes;
diff --git a/objects/dib.c b/objects/dib.c
index b8d7313..f55c44f 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -10,6 +10,7 @@
 #include <X11/Xutil.h>
 #include "dc.h"
 #include "bitmap.h"
+#include "callback.h"
 #include "palette.h"
 #include "icon.h"
 #include "stackframe.h"
@@ -172,9 +173,10 @@
 {
 	int x = 0, c, length;
 	BYTE *begin = bits;
-	
-	lines--;
-	while (1) {
+
+        lines--;
+	while ((INT)lines >= 0)
+        {
 		length = *bits++;
 		if (length) {	/* encoded */
 			c = *bits++;
@@ -562,9 +564,11 @@
     if (startscan+lines > info->bmiHeader.biHeight)
 	lines = info->bmiHeader.biHeight - startscan;
 
-    return DIB_SetImageBits( dc, lines, bmp->bitmap.bmBitsPixel,
-			     bits, info, coloruse, bmp->pixmap, BITMAP_GC(bmp),
-			     0, 0, 0, startscan, bmp->bitmap.bmWidth, lines );
+    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 14,
+                                dc, lines, bmp->bitmap.bmBitsPixel,
+                                bits, info, coloruse, bmp->pixmap,
+                                BITMAP_GC(bmp), 0, 0, 0, startscan,
+                                bmp->bitmap.bmWidth, lines );
 }
 
 
@@ -592,13 +596,13 @@
 
     DC_SetupGCForText( dc );  /* To have the correct colors */
     XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
-    return DIB_SetImageBits( dc, lines, dc->w.bitsPerPixel,
-			     bits, info, coloruse,
-			     dc->u.x.drawable, dc->u.x.gc,
-			     xSrc, ySrc - startscan,
-			     dc->w.DCOrgX + XLPTODP( dc, xDest ),
-			     dc->w.DCOrgY + YLPTODP( dc, yDest ),
-			     cx, cy );
+    return CallTo32_LargeStack( (int(*)())DIB_SetImageBits, 14,
+                                dc, lines, dc->w.bitsPerPixel, bits, info,
+                                coloruse, dc->u.x.drawable, dc->u.x.gc,
+                                xSrc, ySrc - startscan,
+                                dc->w.DCOrgX + XLPTODP( dc, xDest ),
+                                dc->w.DCOrgY + YLPTODP( dc, yDest ),
+                                cx, cy );
 }
 
 
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index c34a379..2cfcd75 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -2,9 +2,7 @@
  * GDI functions
  *
  * Copyright 1993 Alexandre Julliard
- *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
-*/
+ */
 
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/objects/palette.c b/objects/palette.c
index 80b64c4..dd925ce 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -21,6 +21,8 @@
 /* #define DEBUG_PALETTE */
 #include "debug.h"
 
+static WORD SystemPaletteUse = SYSPAL_STATIC;	/* currently not considered */
+
 /***********************************************************************
  *           CreatePalette    (GDI.360)
  */
@@ -80,13 +82,26 @@
 
 
 /***********************************************************************
+ *           SetSystemPaletteUse    (GDI.373)
+ *	Should this be per DC rather than system wide?
+ *  Currently, it does not matter as the use is only set and returned,
+ *  but not taken into account
+ */
+WORD SetSystemPaletteUse( HDC hdc, WORD use)
+{
+	 WORD old=SystemPaletteUse;
+	 printf("SetSystemPaletteUse(%04X,%04X) // empty stub !!!\n", hdc, use);
+	 SystemPaletteUse=use;
+	 return old;
+}
+
+/***********************************************************************
  *           GetSystemPaletteUse    (GDI.374)
  */
 WORD GetSystemPaletteUse( HDC hdc )
 {
 	printf("GetSystemPaletteUse(%04X) // empty stub !!!\n", hdc);
-	/* Assuming there is remaining system colors ... */
-	return SYSPAL_STATIC;
+	return SystemPaletteUse;
 }
 
 
diff --git a/objects/text.c b/objects/text.c
index 9e3347c..52673fe 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -302,9 +302,12 @@
     if (!DC_SetupGCForText( dc )) return TRUE;
     font = dc->u.x.font.fstruct;
 
-    dprintf_text(stddeb,"ExtTextOut: %d,%d '%*.*s', %d  flags=%d rect=%d,%d,%d,%d\n",
-            x, y, count, count, str, count, flags,
-            lprect->left, lprect->top, lprect->right, lprect->bottom );
+    dprintf_text(stddeb,"ExtTextOut: %d,%d '%*.*s', %d  flags=%d\n",
+            x, y, count, count, str, count, flags);
+    if (lprect != NULL) {
+      dprintf_text(stddeb, "rect %d %d %d %d\n",
+		   lprect->left, lprect->top, lprect->right, lprect->bottom );
+    }
 
       /* Setup coordinates */
 
diff --git a/rc/sysres.rc b/rc/sysres.rc
index 2ca57c8..44e217f 100644
--- a/rc/sysres.rc
+++ b/rc/sysres.rc
@@ -29,14 +29,14 @@
         PUSHBUTTON "&No", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
 END
 
-SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 149
+SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
 STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 CAPTION "About X"
 FONT 10, "System"
 {
- DEFPUSHBUTTON "OK", 1, 86, 130, 40, 14
- CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 90
- LTEXT "Text", 100, 11, 40, 190, 80, SS_NOPREFIX | WS_GROUP
+ DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
+ CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 120
+ LTEXT "Text", 100, 11, 40, 190, 110, SS_NOPREFIX | WS_GROUP
  ICON "", 1088, 185, 10, 18, 20
 }
 
diff --git a/rc/sysres_De.rc b/rc/sysres_De.rc
index 00bb498..4f74ac2 100644
--- a/rc/sysres_De.rc
+++ b/rc/sysres_De.rc
@@ -27,14 +27,14 @@
         PUSHBUTTON "&Nein", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
 END
 
-SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 149
+SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
 STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 CAPTION ""
 FONT 10, "System"
 {
- DEFPUSHBUTTON "OK", 1, 86, 130, 40, 14
- CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 90
- LTEXT "Text", 100, 11, 40, 190, 80, SS_NOPREFIX | WS_GROUP
+ DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
+ CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 120
+ LTEXT "Text", 100, 11, 40, 190, 110, SS_NOPREFIX | WS_GROUP
  ICON "", 1088, 185, 10, 18, 20
 }
 
diff --git a/rc/sysres_No.rc b/rc/sysres_No.rc
index ee189b2..2a86058 100644
--- a/rc/sysres_No.rc
+++ b/rc/sysres_No.rc
@@ -27,14 +27,14 @@
         PUSHBUTTON "&Nei", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP
 END
 
-SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 149
+SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 213, 179
 STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 CAPTION "Om X"
 FONT 10, "System"
 {
- DEFPUSHBUTTON "OK", 1, 86, 130, 40, 14
- CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 90
- LTEXT "Tekst", 100, 11, 40, 190, 80, SS_NOPREFIX | WS_GROUP
+ DEFPUSHBUTTON "OK", 1, 86, 160, 40, 14
+ CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 205, 120
+ LTEXT "Tekst", 100, 11, 40, 190, 110, SS_NOPREFIX | WS_GROUP
  ICON "", 1088, 185, 10, 18, 20
 }
 
diff --git a/tools/build.c b/tools/build.c
index b79dc51..045de3c 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -295,12 +295,6 @@
     }
     fdp->arg_types[i] = '\0';
 
-    if ((type == TYPE_REGISTER) && (i > 0))
-    {
-        fprintf( stderr, "%d: Register function can't have arguments\n", Line);
-        exit(1);
-    }
-
     strcpy(fdp->internal_name, GetToken());
     return 0;
 }
@@ -946,6 +940,110 @@
 
 
 /*******************************************************************
+ *         BuildCall32LargeStack
+ *
+ * Build the function used to switch to the original 32-bit stack
+ * before calling a 32-bit function from 32-bit code. This is used for
+ * functions that need a large stack, like X bitmaps functions.
+ *
+ * The generated function has the following prototype:
+ *   int CallTo32_LargeStack( int (*func)(), int nbargs, ... )
+ *
+ * Stack layout:
+ *   ...     ...
+ * (ebp+20)  arg2
+ * (ebp+16)  arg1
+ * (ebp+12)  nbargs
+ * (ebp+8)   func
+ * (ebp+4)   ret addr
+ * (ebp)     ebp
+ */
+static void BuildCall32LargeStack(void)
+{
+    /* Function header */
+
+    printf( "/**********\n" );
+    printf( " * " PREFIX "CallTo32_LargeStack\n" );
+    printf( " **********/\n" );
+    printf( "\t.align 4\n" );
+    printf( "\t.globl " PREFIX "CallTo32_LargeStack\n\n" );
+    printf( PREFIX "CallTo32_LargeStack:\n" );
+    
+    /* Entry code */
+
+    printf( "\tpushl %%ebp\n" );
+    printf( "\tmovl %%esp,%%ebp\n" );
+
+    /* Save registers */
+
+    printf( "\tpushl %%ecx\n" );
+    printf( "\tpushl %%esi\n" );
+    printf( "\tpushl %%edi\n" );
+
+    /* Switch to the new stack (if any) */
+
+    printf( "\tleal 16(%%ebp),%%esi\n" );
+    printf( "\tmovl " PREFIX "IF1632_Original32_esp, %%ecx\n" );
+    printf( "\tjcxz 0f\n" );
+    printf( "\tmovl %%ecx,%%esp\n" );
+
+    /* Transfer the arguments */
+
+    printf( "\tmovl 12(%%ebp),%%ecx\n" );
+    printf( "\tjcxz 1f\n" );
+    printf( "\tshl $2,%%ecx\n" );
+    printf( "\tsubl %%ecx,%%esp\n" );
+    printf( "\tmovl %%esp,%%edi\n" );
+    printf( "\tshr $2,%%ecx\n" );
+    printf( "\trep; movsl\n" );
+    printf( "1:\n" );
+
+    /* Call the function */
+
+    printf( "\tcall 8(%%ebp)\n" );
+
+    /* Switch back to the normal stack */
+
+    printf( "\tleal -12(%%ebp),%%esp\n" );
+
+    /* Restore registers and return */
+
+    printf( "\tpopl %%edi\n" );
+    printf( "\tpopl %%esi\n" );
+    printf( "\tpopl %%ecx\n" );
+
+    printf( "\tpopl %%ebp\n" );
+    printf( "\tret\n" );
+
+    /* We get here if IF1632_Original32_esp is 0, i.e. we have not */
+    /* switched to another 32-bit stack yet. */
+
+    printf( "0:\n" );
+
+    /* Restore the registers */
+
+    printf( "\tpopl %%edi\n" );
+    printf( "\tpopl %%esi\n" );
+    printf( "\tpopl %%ecx\n" );
+
+    /* Move the return address up the stack */
+
+    printf( "\tmovl 4(%%ebp),%%eax\n" );
+    printf( "\tmovl %%eax,12(%%ebp)\n" );
+
+    /* Restore ebp and remove old return address */
+
+    printf( "\tpopl %%ebp\n" );
+    printf( "\taddl $4,%%esp\n" );
+
+    /* Now jump to the routine, leaving the original return address and */
+    /* the arguments on the stack. */
+
+    printf( "\tret\n" );
+}
+
+
+/*******************************************************************
  *         TransferArgs16To32
  *
  * Get the arguments from the 16-bit stack and push them on the 32-bit stack.
@@ -1100,6 +1198,8 @@
  * profile is: type_xxxxx, where 'type' is one of 'regs', 'word' or
  * 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
  * 'l'=long, 'p'=pointer).
+ * For register functions, the arguments are ignored, but they are still
+ * removed from the stack upon return.
  *
  * Stack layout upon entry to the callback function:
  *  ...      ...
@@ -1174,20 +1274,16 @@
 
     /* Switch to the 32-bit stack */
 
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebp\n" );
     printf( "\tpushw %%ds\n" );
     printf( "\tpopw %%ss\n" );
-    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
+    printf( "\tleal -%d(%%ebp),%%esp\n",
+            reg_func ? sizeof(struct sigcontext_struct) : 4 * strlen(args) );
 
     /* 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)
-        printf( "\tsubl $%d,%%esp\n", 4 * strlen(args) );
-
     /* Call the entry point */
 
     if (debugging)
@@ -1226,6 +1322,25 @@
     {
         /* Restore registers from the context structure */
         RestoreContext();
+        
+        /* Calc the arguments size */
+        while (*args)
+        {
+            switch(*args)
+            {
+            case 'w':
+            case 's':
+                argsize += 2;
+                break;
+            case 'p':
+            case 'l':
+                argsize += 4;
+                break;
+            default:
+                fprintf( stderr, "Unknown arg type '%c'\n", *args );
+            }
+            args++;
+        }
     }
     else  /* Store the return value in dx:ax if needed */
     {
@@ -1502,6 +1617,10 @@
         printf( "/* File generated automatically. Do no edit! */\n\n" );
         printf( "\t.text\n" );
 
+        /* Build the 32-bit large stack callback */
+
+        BuildCall32LargeStack();
+
         /* Build the callback functions */
 
         for (i = 2; i < argc; i++) BuildCall32Func( argv[i] );
diff --git a/windows/graphics.c b/windows/graphics.c
index 2531ed3..26ba7b3 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -14,6 +14,7 @@
 #endif
 #include "dc.h"
 #include "bitmap.h"
+#include "callback.h"
 #include "metafile.h"
 #include "syscolor.h"
 #include "stddebug.h"
@@ -883,13 +884,45 @@
 
 
 /**********************************************************************
+ *          GRAPH_DoFloodFill
+ *
+ * Main flood-fill routine.
+ */
+static BOOL GRAPH_DoFloodFill( DC *dc, RECT *rect, INT x, INT y,
+                               COLORREF color, WORD fillType )
+{
+    XImage *image;
+
+    if (!(image = XGetImage( display, dc->u.x.drawable,
+                             dc->w.DCOrgX + rect->left,
+                             dc->w.DCOrgY + rect->top,
+                             rect->right - rect->left,
+                             rect->bottom - rect->top,
+                             AllPlanes, ZPixmap ))) return FALSE;
+
+    if (DC_SetupGCForBrush( dc ))
+    {
+          /* ROP mode is always GXcopy for flood-fill */
+        XSetFunction( display, dc->u.x.gc, GXcopy );
+        GRAPH_InternalFloodFill( image, dc,
+                                 XLPTODP(dc,x) - rect->left,
+                                 YLPTODP(dc,y) - rect->top,
+                                 dc->w.DCOrgX + rect->left,
+                                 dc->w.DCOrgY + rect->top,
+                                 COLOR_ToPhysical( dc, color ), fillType );
+    }
+
+    XDestroyImage( image );
+    return TRUE;
+}
+
+
+/**********************************************************************
  *          ExtFloodFill  (GDI.372)
  */
 BOOL ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, WORD fillType )
 {
     RECT rect;
-    Pixel pixel;
-    XImage *image;
     DC *dc;
 
     dprintf_graphics( stddeb, "ExtFloodFill %x %d,%d %06lx %d\n",
@@ -906,28 +939,9 @@
 
     if (!PtVisible( hdc, x, y )) return FALSE;
     if (GetRgnBox( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
-    pixel = COLOR_ToPhysical( dc, color );
 
-    if (!(image = XGetImage( display, dc->u.x.drawable,
-                             dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
-                             rect.right - rect.left, rect.bottom - rect.top,
-                             AllPlanes, ZPixmap ))) return FALSE;
-
-    if (DC_SetupGCForBrush( dc ))
-    {
-          /* ROP mode is always GXcopy for flood-fill */
-        XSetFunction( display, dc->u.x.gc, GXcopy );
-          /* We can pass anything except 0 as a region */
-        GRAPH_InternalFloodFill( image, dc,
-                                 XLPTODP(dc,x) - rect.left,
-                                 YLPTODP(dc,y) - rect.top,
-                                 dc->w.DCOrgX + rect.left,
-                                 dc->w.DCOrgY + rect.top,
-                                 pixel, fillType );
-    }
-
-    XDestroyImage( image );
-    return TRUE;
+    return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill, 6,
+                                dc, &rect, x, y, color, fillType );
 }
 
 
diff --git a/windows/keyboard.c b/windows/keyboard.c
index e02ebd7..7610ae9 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -43,6 +43,18 @@
 }
 
 /**********************************************************************
+ *      SetKeyboardState            [USER.223]
+ */
+void SetKeyboardState(BYTE FAR *lpKeyState)
+{
+	if (lpKeyState != NULL) {
+	memcpy(KeyStateTable, lpKeyState, 256);
+	MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON];
+	MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON];
+	MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON];
+	}
+}
+/**********************************************************************
  *            GetAsyncKeyState        (USER.249)
  *
  *	Determine if a key is or was pressed.  retval has high-order 
diff --git a/windows/win.c b/windows/win.c
index 29dc18a..be12941 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -210,7 +210,7 @@
  *
  * Create the desktop window.
  */
-BOOL WIN_CreateDesktopWindow()
+BOOL WIN_CreateDesktopWindow(void)
 {
     WND *wndPtr;
     HCLASS hclass;