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/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/ldt.c b/loader/ldt.c
deleted file mode 100644
index 73e1260..0000000
--- a/loader/ldt.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * LDT manipulation functions
- *
- * Copyright 1993 Robert J. Amstadt
- * Copyright 1995 Alexandre Julliard
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <errno.h>
-#include "ldt.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#ifndef WINELIB
-
-#ifdef linux
-#include <linux/unistd.h>
-#include <linux/head.h>
-#include <linux/ldt.h>
-
-_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
-#endif  /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#include <machine/segments.h>
-
-extern int i386_get_ldt(int, union descriptor *, int);
-extern int i386_set_ldt(int, union descriptor *, int);
-#endif  /* __NetBSD__ || __FreeBSD__ */
-
-#endif  /* ifndef WINELIB */
-
-        
-/***********************************************************************
- *           LDT_BytesToEntry
- *
- * Convert the raw bytes of the descriptor to an ldt_entry structure.
- */
-static void LDT_BytesToEntry( unsigned long *buffer, ldt_entry *content )
-{
-    content->base  = (*buffer >> 16) & 0x0000ffff;
-    content->limit = *buffer & 0x0000ffff;
-    buffer++;
-    content->base  |= (*buffer & 0xff000000) | ((*buffer << 16) & 0x00ff0000);
-    content->limit |= (*buffer & 0x000f0000);
-    content->type           = (*buffer >> 10) & 3;
-    content->seg_32bit      = (*buffer & 0x00400000) != 0;
-    content->read_only      = (*buffer & 0x00000200) == 0;
-    content->limit_in_pages = (*buffer & 0x00800000) != 0;
-}
-
-
-/***********************************************************************
- *           LDT_GetEntry
- *
- * Retrieve an LDT entry.
- */
-int LDT_GetEntry( int entry, ldt_entry *content )
-{
-    int ret = 0;
-
-#ifdef WINELIB
-    content->base           = ldt_copy[entry].base;
-    content->limit          = ldt_copy[entry].limit;
-    content->type           = SEGMENT_DATA;
-    content->seg_32bit      = 0;
-    content->read_only      = 0;
-    content->limit_in_pages = 0;
-#else  /* WINELIB */
-
-#ifdef linux
-    int size = (entry + 1) * 2 * sizeof(long);
-    long *buffer = (long *) malloc( size );
-    ret = modify_ldt( 0, buffer, size );
-    LDT_BytesToEntry( &buffer[entry*2], content );
-    free( buffer );
-#endif  /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-    long buffer[2];
-    ret = i386_get_ldt( entry, (union descriptor *)buffer, 1 );
-    LDT_BytesToEntry( buffer, content );
-#endif  /* __NetBSD__ || __FreeBSD__ */
-
-#endif  /* WINELIB */
-
-    return ret;
-}
-
-
-/***********************************************************************
- *           LDT_SetEntry
- *
- * Set an LDT entry.
- */
-int LDT_SetEntry( int entry, ldt_entry *content )
-{
-    int ret = 0;
-
-    dprintf_ldt(stddeb,
-	  "LDT_SetEntry: entry=%04x base=%08lx limit=%05lx %s %d-bit flags=%c%c%c\n",
-          entry, content->base, content->limit,
-          content->limit_in_pages ? "pages" : "bytes",
-          content->seg_32bit ? 32 : 16,
-          content->read_only && (content->type & SEGMENT_CODE) ? '-' : 'r',
-          content->read_only || (content->type & SEGMENT_CODE) ? '-' : 'w',
-          (content->type & SEGMENT_CODE) ? 'x' : '-' );
-
-#ifndef WINELIB
-#ifdef linux
-    {
-        struct modify_ldt_ldt_s ldt_info;
-
-        memset( &ldt_info, 0, sizeof(ldt_info) );
-        ldt_info.entry_number   = entry;
-        ldt_info.base_addr      = content->base;
-        ldt_info.limit          = content->limit;
-        ldt_info.seg_32bit      = content->seg_32bit != 0;
-        ldt_info.contents       = content->type;
-        ldt_info.read_exec_only = content->read_only != 0;
-        ldt_info.limit_in_pages = content->limit_in_pages != 0;
-        ret = modify_ldt(1, &ldt_info, sizeof(ldt_info));
-    }
-#endif  /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-    {
-        long d[2];
-
-        d[0] = ((content->base & 0x0000ffff) << 16) |
-                (content->limit & 0x0ffff);
-        d[1] = (content->base & 0xff000000) |
-               ((content->base & 0x00ff0000)>>16) |
-               (content->limit & 0xf0000) |
-               (content->type << 10) |
-               ((content->read_only == 0) << 9) |
-               ((content->seg_32bit != 0) << 22) |
-               ((content->limit_in_pages != 0) << 23) |
-               0xf000;
-        ret = i386_set_ldt(entry, (union descriptor *)d, 1);
-        if (ret < 0)
-        {
-            perror("i386_set_ldt");
-            fprintf(stderr,
-		"Did you reconfigure the kernel with \"options USER_LDT\"?\n");
-    	    exit(1);
-        }
-    }
-#endif  /* __NetBSD__ || __FreeBSD__ */
-#endif  /* ifndef WINELIB */
-
-    if (ret < 0) return ret;
-    ldt_copy[entry].base = content->base;
-    if (!content->limit_in_pages) ldt_copy[entry].limit = content->limit;
-    else ldt_copy[entry].limit = (content->limit << 12) | 0x0fff;
-    return ret;
-}
-
-
-/***********************************************************************
- *           LDT_Print
- *
- * Print the content of the LDT on stdout.
- */
-void LDT_Print()
-{
-    int i;
-
-#ifdef WINELIB
-    for (i = 0; i < LDT_SIZE; i++)
-    {
-        if (ldt_copy[i].base || ldt_copy[i].limit)
-        {
-            fprintf( stderr, "%04x: sel=%04x base=%08x limit=%05x\n",
-                     i, ENTRY_TO_SELECTOR(i),
-                     ldt_copy[i].base, ldt_copy[i].limit );
-        }
-    }
-#else  /* WINELIB */
-
-    long buffer[2*LDT_SIZE];
-    ldt_entry content;
-    int n;
-
-#ifdef linux
-    n = modify_ldt( 0, buffer, sizeof(buffer) ) / 8;
-#endif  /* linux */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-    n = i386_get_ldt( 0, (union descriptor *)buffer, LDT_SIZE );
-#endif  /* __NetBSD__ || __FreeBSD__ */
-    for (i = 0; i < n; i++)
-    {
-        LDT_BytesToEntry( &buffer[2*i], &content );
-        if (content.base || content.limit)
-        {
-            fprintf( stderr, "%04x: sel=%04x base=%08lx limit=%05lx %s type=%d\n",
-                    i, ENTRY_TO_SELECTOR(i),
-                    content.base, content.limit,
-                    content.limit_in_pages ? "(pages)" : "(bytes)",
-                    content.type );
-        }
-    }
-#endif  /* WINELIB */
-}
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)