Moved most of the 16-bit task support and NE module loader to
dlls/kernel.

diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index 4a8ca0a..f5b0e96 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -34,6 +34,8 @@
 	lcformat.c \
 	local16.c \
 	locale.c \
+	ne_module.c \
+	ne_segment.c \
 	powermgnt.c \
 	process.c \
 	resource.c \
@@ -42,6 +44,7 @@
 	string.c \
 	sync.c \
 	tape.c \
+	task.c \
 	thread.c \
 	thunk.c \
 	time.c \
diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c
index b01f4d1..c756968 100644
--- a/dlls/kernel/kernel_main.c
+++ b/dlls/kernel/kernel_main.c
@@ -97,6 +97,7 @@
     /* free the 16-bit stack */
     K32WOWGlobalFree16( NtCurrentTeb()->stack_sel );
     NtCurrentTeb()->cur_stack = 0;
+    if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask();
 }
 
 
diff --git a/dlls/kernel/ne_module.c b/dlls/kernel/ne_module.c
new file mode 100644
index 0000000..1a28a42
--- /dev/null
+++ b/dlls/kernel/ne_module.c
@@ -0,0 +1,1716 @@
+/*
+ * NE modules
+ *
+ * Copyright 1995 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <ctype.h>
+
+#include "winbase.h"
+#include "wine/winbase16.h"
+#include "winerror.h"
+#include "wownt32.h"
+#include "wine/library.h"
+#include "module.h"
+#include "toolhelp.h"
+#include "file.h"
+#include "task.h"
+#include "snoop.h"
+#include "builtin16.h"
+#include "stackframe.h"
+#include "excpt.h"
+#include "wine/exception.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(module);
+WINE_DECLARE_DEBUG_CHANNEL(loaddll);
+
+#include "pshpack1.h"
+typedef struct _GPHANDLERDEF
+{
+    WORD selector;
+    WORD rangeStart;
+    WORD rangeEnd;
+    WORD handler;
+} GPHANDLERDEF;
+#include "poppack.h"
+
+/*
+ * Segment table entry
+ */
+struct ne_segment_table_entry_s
+{
+    WORD seg_data_offset;   /* Sector offset of segment data	*/
+    WORD seg_data_length;   /* Length of segment data		*/
+    WORD seg_flags;         /* Flags associated with this segment	*/
+    WORD min_alloc;         /* Minimum allocation size for this	*/
+};
+
+#define hFirstModule (pThhook->hExeHead)
+
+static NE_MODULE *pCachedModule = 0;  /* Module cached by NE_OpenFile */
+
+static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
+static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
+
+static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
+
+static HMODULE16 NE_GetModuleByFilename( LPCSTR name );
+
+
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
+        GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
+        return EXCEPTION_EXECUTE_HANDLER;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+
+/***********************************************************************
+ *           NE_DumpModule
+ */
+void NE_DumpModule( HMODULE16 hModule )
+{
+    int i, ordinal;
+    SEGTABLEENTRY *pSeg;
+    BYTE *pstr;
+    WORD *pword;
+    NE_MODULE *pModule;
+    ET_BUNDLE *bundle;
+    ET_ENTRY *entry;
+
+    if (!(pModule = NE_GetPtr( hModule )))
+    {
+        MESSAGE( "**** %04x is not a module handle\n", hModule );
+        return;
+    }
+
+      /* Dump the module info */
+    DPRINTF( "---\n" );
+    DPRINTF( "Module %04x:\n", hModule );
+    DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
+             pModule->count, pModule->flags,
+             pModule->heap_size, pModule->stack_size );
+    DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
+             pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
+             pModule->seg_count, pModule->modref_count );
+    DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
+             pModule->os_flags, pModule->min_swap_area,
+             pModule->expected_version );
+    if (pModule->flags & NE_FFLAGS_WIN32)
+        DPRINTF( "PE module=%p\n", pModule->module32 );
+
+      /* Dump the file info */
+    DPRINTF( "---\n" );
+    DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
+
+      /* Dump the segment table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Segment table:\n" );
+    pSeg = NE_SEG_TABLE( pModule );
+    for (i = 0; i < pModule->seg_count; i++, pSeg++)
+        DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
+                 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
+                 pSeg->minsize, pSeg->hSeg );
+
+      /* Dump the resource table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Resource table:\n" );
+    if (pModule->res_table)
+    {
+        pword = (WORD *)((BYTE *)pModule + pModule->res_table);
+        DPRINTF( "Alignment: %d\n", *pword++ );
+        while (*pword)
+        {
+            NE_TYPEINFO *ptr = (NE_TYPEINFO *)pword;
+            NE_NAMEINFO *pname = (NE_NAMEINFO *)(ptr + 1);
+            DPRINTF( "id=%04x count=%d\n", ptr->type_id, ptr->count );
+            for (i = 0; i < ptr->count; i++, pname++)
+                DPRINTF( "offset=%d len=%d id=%04x\n",
+		      pname->offset, pname->length, pname->id );
+            pword = (WORD *)pname;
+        }
+    }
+    else DPRINTF( "None\n" );
+
+      /* Dump the resident name table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Resident-name table:\n" );
+    pstr = (char *)pModule + pModule->name_table;
+    while (*pstr)
+    {
+        DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+                 *(WORD *)(pstr + *pstr + 1) );
+        pstr += *pstr + 1 + sizeof(WORD);
+    }
+
+      /* Dump the module reference table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Module ref table:\n" );
+    if (pModule->modref_table)
+    {
+        pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
+        for (i = 0; i < pModule->modref_count; i++, pword++)
+        {
+            char name[10];
+            GetModuleName16( *pword, name, sizeof(name) );
+            DPRINTF( "%d: %04x -> '%s'\n", i, *pword, name );
+        }
+    }
+    else DPRINTF( "None\n" );
+
+      /* Dump the entry table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Entry table:\n" );
+    bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
+    do {
+        entry = (ET_ENTRY *)((BYTE *)bundle+6);
+        DPRINTF( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
+        ordinal = bundle->first;
+        while (ordinal < bundle->last)
+        {
+            if (entry->type == 0xff)
+                DPRINTF("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
+            else
+                DPRINTF("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
+            entry++;
+        }
+    } while ( (bundle->next) && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
+
+    /* Dump the non-resident names table */
+    DPRINTF( "---\n" );
+    DPRINTF( "Non-resident names table:\n" );
+    if (pModule->nrname_handle)
+    {
+        pstr = (char *)GlobalLock16( pModule->nrname_handle );
+        while (*pstr)
+        {
+            DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
+                   *(WORD *)(pstr + *pstr + 1) );
+            pstr += *pstr + 1 + sizeof(WORD);
+        }
+    }
+    DPRINTF( "\n" );
+}
+
+
+/***********************************************************************
+ *           NE_WalkModules
+ *
+ * Walk the module list and print the modules.
+ */
+void NE_WalkModules(void)
+{
+    HMODULE16 hModule = hFirstModule;
+    MESSAGE( "Module Flags Name\n" );
+    while (hModule)
+    {
+        NE_MODULE *pModule = NE_GetPtr( hModule );
+        if (!pModule)
+        {
+            MESSAGE( "Bad module %04x in list\n", hModule );
+            return;
+        }
+        MESSAGE( " %04x  %04x  %.*s\n", hModule, pModule->flags,
+                 *((char *)pModule + pModule->name_table),
+                 (char *)pModule + pModule->name_table + 1 );
+        hModule = pModule->next;
+    }
+}
+
+
+/***********************************************************************
+ *		EntryAddrProc (KERNEL.667) Wine-specific export
+ *
+ * Return the entry point for a given ordinal.
+ */
+FARPROC16 WINAPI EntryAddrProc16( HMODULE16 hModule, WORD ordinal )
+{
+    FARPROC16 ret = NE_GetEntryPointEx( hModule, ordinal, TRUE );
+    CURRENT_STACK16->ecx = hModule; /* FIXME: might be incorrect value */
+    return ret;
+}
+
+/***********************************************************************
+ *           NE_SetEntryPoint
+ *
+ * Change the value of an entry point. Use with caution!
+ * It can only change the offset value, not the selector.
+ */
+BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
+{
+    NE_MODULE *pModule;
+    ET_ENTRY *entry;
+    ET_BUNDLE *bundle;
+    int i;
+
+    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
+    assert( !(pModule->flags & NE_FFLAGS_WIN32) );
+
+    bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
+    while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
+    {
+        bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
+        if (!(bundle->next)) return 0;
+    }
+
+    entry = (ET_ENTRY *)((BYTE *)bundle+6);
+    for (i=0; i < (ordinal - bundle->first - 1); i++)
+        entry++;
+
+    memcpy( &entry->offs, &offset, sizeof(WORD) );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           NE_OpenFile
+ */
+HANDLE NE_OpenFile( NE_MODULE *pModule )
+{
+    HANDLE handle;
+    char *name;
+
+    TRACE("(%p)\n", pModule );
+    /* mjm - removed module caching because it keeps open file handles
+             thus preventing CDROMs from being ejected */
+    name = NE_MODULE_NAME( pModule );
+    if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
+                                   NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
+        MESSAGE( "Can't open file '%s' for module %04x\n", name, pModule->self );
+    TRACE("opened '%s' -> %p\n", name, handle);
+    return handle;
+}
+
+
+/* wrapper for SetFilePointer and ReadFile */
+static BOOL read_data( HANDLE handle, LONG offset, void *buffer, DWORD size )
+{
+    DWORD result;
+
+    if (SetFilePointer( handle, offset, NULL, SEEK_SET ) == INVALID_SET_FILE_POINTER) return FALSE;
+    if (!ReadFile( handle, buffer, size, &result, NULL )) return FALSE;
+    return (result == size);
+}
+
+/***********************************************************************
+ *           NE_LoadExeHeader
+ */
+static HMODULE16 NE_LoadExeHeader( HANDLE handle, LPCSTR path )
+{
+    IMAGE_DOS_HEADER mz_header;
+    IMAGE_OS2_HEADER ne_header;
+    int size;
+    HMODULE16 hModule;
+    NE_MODULE *pModule;
+    BYTE *pData, *pTempEntryTable;
+    char *buffer, *fastload = NULL;
+    int fastload_offset = 0, fastload_length = 0;
+    ET_ENTRY *entry;
+    ET_BUNDLE *bundle, *oldbundle;
+    OFSTRUCT *ofs;
+
+  /* Read a block from either the file or the fast-load area. */
+#define READ(offset,size,buffer) \
+       ((fastload && ((offset) >= fastload_offset) && \
+         ((offset)+(size) <= fastload_offset+fastload_length)) ? \
+        (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
+         read_data( handle, (offset), (buffer), (size)))
+
+    if (!read_data( handle, 0, &mz_header, sizeof(mz_header)) ||
+        (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
+        return (HMODULE16)11;  /* invalid exe */
+
+    if (!read_data( handle, mz_header.e_lfanew, &ne_header, sizeof(ne_header) ))
+        return (HMODULE16)11;  /* invalid exe */
+
+    if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
+    if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
+        MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
+        return (HMODULE16)12;
+    }
+    if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
+
+    /* We now have a valid NE header */
+
+    size = sizeof(NE_MODULE) +
+             /* segment table */
+           ne_header.ne_cseg * sizeof(SEGTABLEENTRY) +
+             /* resource table */
+           ne_header.ne_restab - ne_header.ne_rsrctab +
+             /* resident names table */
+           ne_header.ne_modtab - ne_header.ne_restab +
+             /* module ref table */
+           ne_header.ne_cmod * sizeof(WORD) +
+             /* imported names table */
+           ne_header.ne_enttab - ne_header.ne_imptab +
+             /* entry table length */
+           ne_header.ne_cbenttab +
+             /* entry table extra conversion space */
+           sizeof(ET_BUNDLE) +
+           2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6) +
+             /* loaded file info */
+           sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
+
+    hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
+    if (!hModule) return (HMODULE16)11;  /* invalid exe */
+
+    FarSetOwner16( hModule, hModule );
+    pModule = (NE_MODULE *)GlobalLock16( hModule );
+    memcpy( pModule, &ne_header, sizeof(ne_header) );
+    pModule->count = 0;
+    /* check *programs* for default minimal stack size */
+    if ( (!(pModule->flags & NE_FFLAGS_LIBMODULE))
+         && (pModule->stack_size < 0x1400) )
+        pModule->stack_size = 0x1400;
+    pModule->module32 = 0;
+    pModule->self = hModule;
+    pModule->self_loading_sel = 0;
+    pData = (BYTE *)(pModule + 1);
+
+    /* Clear internal Wine flags in case they are set in the EXE file */
+
+    pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
+
+    /* Read the fast-load area */
+
+    if (ne_header.ne_flagsothers & NE_AFLAGS_FASTLOAD)
+    {
+        fastload_offset=ne_header.ne_pretthunks << ne_header.ne_align;
+        fastload_length=ne_header.ne_psegrefbytes << ne_header.ne_align;
+        TRACE("Using fast-load area offset=%x len=%d\n",
+                        fastload_offset, fastload_length );
+        if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL)
+        {
+            if (!read_data( handle, fastload_offset, fastload, fastload_length))
+            {
+                HeapFree( GetProcessHeap(), 0, fastload );
+                WARN("Error reading fast-load area!\n");
+                fastload = NULL;
+            }
+        }
+    }
+
+    /* Get the segment table */
+
+    pModule->seg_table = pData - (BYTE *)pModule;
+    buffer = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cseg *
+                                      sizeof(struct ne_segment_table_entry_s));
+    if (buffer)
+    {
+        int i;
+        struct ne_segment_table_entry_s *pSeg;
+
+        if (!READ( mz_header.e_lfanew + ne_header.ne_segtab,
+             ne_header.ne_cseg * sizeof(struct ne_segment_table_entry_s),
+             buffer ))
+        {
+            HeapFree( GetProcessHeap(), 0, buffer );
+            if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+        pSeg = (struct ne_segment_table_entry_s *)buffer;
+        for (i = ne_header.ne_cseg; i > 0; i--, pSeg++)
+        {
+            memcpy( pData, pSeg, sizeof(*pSeg) );
+            pData += sizeof(SEGTABLEENTRY);
+        }
+        HeapFree( GetProcessHeap(), 0, buffer );
+    }
+    else
+    {
+        if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+        GlobalFree16( hModule );
+        return (HMODULE16)11;  /* invalid exe */
+    }
+
+    /* Get the resource table */
+
+    if (ne_header.ne_rsrctab < ne_header.ne_restab)
+    {
+        pModule->res_table = pData - (BYTE *)pModule;
+        if (!READ(mz_header.e_lfanew + ne_header.ne_rsrctab,
+                  ne_header.ne_restab - ne_header.ne_rsrctab,
+                  pData ))
+            return (HMODULE16)11;  /* invalid exe */
+        pData += ne_header.ne_restab - ne_header.ne_rsrctab;
+        NE_InitResourceHandler( pModule );
+    }
+    else pModule->res_table = 0;  /* No resource table */
+
+    /* Get the resident names table */
+
+    pModule->name_table = pData - (BYTE *)pModule;
+    if (!READ( mz_header.e_lfanew + ne_header.ne_restab,
+               ne_header.ne_modtab - ne_header.ne_restab,
+               pData ))
+    {
+        if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+        GlobalFree16( hModule );
+        return (HMODULE16)11;  /* invalid exe */
+    }
+    pData += ne_header.ne_modtab - ne_header.ne_restab;
+
+    /* Get the module references table */
+
+    if (ne_header.ne_cmod > 0)
+    {
+        pModule->modref_table = pData - (BYTE *)pModule;
+        if (!READ( mz_header.e_lfanew + ne_header.ne_modtab,
+                  ne_header.ne_cmod * sizeof(WORD),
+                  pData ))
+        {
+            if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+        pData += ne_header.ne_cmod * sizeof(WORD);
+    }
+    else pModule->modref_table = 0;  /* No module references */
+
+    /* Get the imported names table */
+
+    pModule->import_table = pData - (BYTE *)pModule;
+    if (!READ( mz_header.e_lfanew + ne_header.ne_imptab,
+               ne_header.ne_enttab - ne_header.ne_imptab,
+               pData ))
+    {
+        if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+        GlobalFree16( hModule );
+        return (HMODULE16)11;  /* invalid exe */
+    }
+    pData += ne_header.ne_enttab - ne_header.ne_imptab;
+
+    /* Load entry table, convert it to the optimized version used by Windows */
+
+    if ((pTempEntryTable = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cbenttab)) != NULL)
+    {
+        BYTE nr_entries, type, *s;
+
+        TRACE("Converting entry table.\n");
+        pModule->entry_table = pData - (BYTE *)pModule;
+        if (!READ( mz_header.e_lfanew + ne_header.ne_enttab,
+                   ne_header.ne_cbenttab, pTempEntryTable ))
+        {
+            HeapFree( GetProcessHeap(), 0, pTempEntryTable );
+            if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+
+        s = pTempEntryTable;
+        TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header.ne_enttab, ne_header.ne_cbenttab, *s);
+
+        bundle = (ET_BUNDLE *)pData;
+        TRACE("first bundle: %p\n", bundle);
+        memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
+        entry = (ET_ENTRY *)((BYTE *)bundle+6);
+
+        while ((nr_entries = *s++))
+        {
+            if ((type = *s++))
+            {
+                bundle->last += nr_entries;
+                if (type == 0xff)
+                while (nr_entries--)
+                {
+                    entry->type   = type;
+                    entry->flags  = *s++;
+                    s += 2;
+                    entry->segnum = *s++;
+                    entry->offs   = *(WORD *)s; s += 2;
+                    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
+                    entry++;
+                }
+                else
+                while (nr_entries--)
+                {
+                    entry->type   = type;
+                    entry->flags  = *s++;
+                    entry->segnum = type;
+                    entry->offs   = *(WORD *)s; s += 2;
+                    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
+                    entry++;
+                }
+            }
+            else
+            {
+                if (bundle->first == bundle->last)
+                {
+                    bundle->first += nr_entries;
+                    bundle->last += nr_entries;
+                }
+                else
+                {
+                    oldbundle = bundle;
+                    oldbundle->next = ((int)entry - (int)pModule);
+                    bundle = (ET_BUNDLE *)entry;
+                    TRACE("new bundle: %p\n", bundle);
+                    bundle->first = bundle->last =
+                        oldbundle->last + nr_entries;
+                    bundle->next = 0;
+                    (BYTE *)entry += sizeof(ET_BUNDLE);
+                }
+            }
+        }
+        HeapFree( GetProcessHeap(), 0, pTempEntryTable );
+    }
+    else
+    {
+        if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+        GlobalFree16( hModule );
+        return (HMODULE16)11;  /* invalid exe */
+    }
+
+    pData += ne_header.ne_cbenttab + sizeof(ET_BUNDLE) +
+        2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6);
+
+    if ((DWORD)entry > (DWORD)pData)
+       ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
+
+    /* Store the filename information */
+
+    pModule->fileinfo = pData - (BYTE *)pModule;
+    size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
+    ofs = (OFSTRUCT *)pData;
+    ofs->cBytes = size - 1;
+    ofs->fFixedDisk = 1;
+    strcpy( ofs->szPathName, path );
+    pData += size;
+
+    /* Free the fast-load area */
+
+#undef READ
+    if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
+
+    /* Get the non-resident names table */
+
+    if (ne_header.ne_cbnrestab)
+    {
+        pModule->nrname_handle = GlobalAlloc16( 0, ne_header.ne_cbnrestab );
+        if (!pModule->nrname_handle)
+        {
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+        FarSetOwner16( pModule->nrname_handle, hModule );
+        buffer = GlobalLock16( pModule->nrname_handle );
+        if (!read_data( handle, ne_header.ne_nrestab, buffer, ne_header.ne_cbnrestab ))
+        {
+            GlobalFree16( pModule->nrname_handle );
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+    }
+    else pModule->nrname_handle = 0;
+
+    /* Allocate a segment for the implicitly-loaded DLLs */
+
+    if (pModule->modref_count)
+    {
+        pModule->dlls_to_init = GlobalAlloc16( GMEM_ZEROINIT,
+                                               (pModule->modref_count+1)*sizeof(HMODULE16) );
+        if (!pModule->dlls_to_init)
+        {
+            if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
+            GlobalFree16( hModule );
+            return (HMODULE16)11;  /* invalid exe */
+        }
+        FarSetOwner16( pModule->dlls_to_init, hModule );
+    }
+    else pModule->dlls_to_init = 0;
+
+    NE_RegisterModule( pModule );
+    SNOOP16_RegisterDLL(pModule,path);
+    return hModule;
+}
+
+
+/***********************************************************************
+ *           NE_LoadDLLs
+ *
+ * Load all DLLs implicitly linked to a module.
+ */
+static BOOL NE_LoadDLLs( NE_MODULE *pModule )
+{
+    int i;
+    WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
+    WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
+
+    for (i = 0; i < pModule->modref_count; i++, pModRef++)
+    {
+        char buffer[260], *p;
+        BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
+        memcpy( buffer, pstr + 1, *pstr );
+        *(buffer + *pstr) = 0; /* terminate it */
+
+        TRACE("Loading '%s'\n", buffer );
+        if (!(*pModRef = GetModuleHandle16( buffer )))
+        {
+            /* If the DLL is not loaded yet, load it and store */
+            /* its handle in the list of DLLs to initialize.   */
+            HMODULE16 hDLL;
+
+            /* Append .DLL to name if no extension present */
+            if (!(p = strrchr( buffer, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
+                    strcat( buffer, ".DLL" );
+
+            if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
+            {
+                /* FIXME: cleanup what was done */
+
+                MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
+                     buffer, *((BYTE*)pModule + pModule->name_table),
+                     (char *)pModule + pModule->name_table + 1, hDLL );
+                return FALSE;
+            }
+            *pModRef = GetExePtr( hDLL );
+            *pDLLs++ = *pModRef;
+        }
+        else  /* Increment the reference count of the DLL */
+        {
+            NE_MODULE *pOldDLL = NE_GetPtr( *pModRef );
+            if (pOldDLL) pOldDLL->count++;
+        }
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    NE_DoLoadModule
+ *
+ * Load first instance of NE module from file.
+ *
+ * pModule must point to a module structure prepared by NE_LoadExeHeader.
+ * This routine must never be called twice on a module.
+ *
+ */
+static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
+{
+    /* Allocate the segments for this module */
+
+    if (!NE_CreateAllSegments( pModule ))
+        return ERROR_NOT_ENOUGH_MEMORY; /* 8 */
+
+    /* Load the referenced DLLs */
+
+    if (!NE_LoadDLLs( pModule ))
+        return ERROR_FILE_NOT_FOUND; /* 2 */
+
+    /* Load the segments */
+
+    NE_LoadAllSegments( pModule );
+
+    /* Make sure the usage count is 1 on the first loading of  */
+    /* the module, even if it contains circular DLL references */
+
+    pModule->count = 1;
+
+    return NE_GetInstance( pModule );
+}
+
+/**********************************************************************
+ *	    NE_LoadModule
+ *
+ * Load first instance of NE module. (Note: caller is responsible for
+ * ensuring the module isn't already loaded!)
+ *
+ * If the module turns out to be an executable module, only a
+ * handle to a module stub is returned; this needs to be initialized
+ * by calling NE_DoLoadModule later, in the context of the newly
+ * created process.
+ *
+ * If lib_only is TRUE, however, the module is perforce treated
+ * like a DLL module, even if it is an executable module.
+ *
+ */
+static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
+{
+    NE_MODULE *pModule;
+    HMODULE16 hModule;
+    HINSTANCE16 hInstance;
+    HFILE16 hFile;
+    OFSTRUCT ofs;
+
+    /* Open file */
+    if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
+        return (HMODULE16)2;  /* File not found */
+
+    hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName );
+    _lclose16( hFile );
+    if (hModule < 32) return hModule;
+
+    pModule = NE_GetPtr( hModule );
+    if ( !pModule ) return hModule;
+
+    if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
+        return hModule;
+
+    hInstance = NE_DoLoadModule( pModule );
+    if ( hInstance < 32 )
+    {
+        /* cleanup ... */
+        NE_FreeModule( hModule, 0 );
+    }
+
+    return hInstance;
+}
+
+
+/**********************************************************************
+ *	    MODULE_LoadModule16
+ *
+ * Load a NE module in the order of the loadorder specification.
+ * The caller is responsible that the module is not loaded already.
+ *
+ */
+static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
+{
+    HINSTANCE16 hinst = 2;
+    enum loadorder_type loadorder[LOADORDER_NTYPES];
+    int i;
+    const char *filetype = "";
+
+    MODULE_GetLoadOrder(loadorder, libname, FALSE);
+
+    for(i = 0; i < LOADORDER_NTYPES; i++)
+    {
+        if (loadorder[i] == LOADORDER_INVALID) break;
+
+        switch(loadorder[i])
+        {
+        case LOADORDER_DLL:
+            TRACE("Trying native dll '%s'\n", libname);
+            hinst = NE_LoadModule(libname, lib_only);
+            filetype = "native";
+            break;
+
+        case LOADORDER_BI:
+            TRACE("Trying built-in '%s'\n", libname);
+            hinst = BUILTIN_LoadModule(libname);
+            filetype = "builtin";
+            break;
+
+        default:
+            hinst = 2;
+            break;
+        }
+
+        if(hinst >= 32)
+        {
+            TRACE_(loaddll)("Loaded module '%s' : %s\n", libname, filetype);
+            if(!implicit)
+            {
+                HMODULE16 hModule;
+                NE_MODULE *pModule;
+
+                hModule = GetModuleHandle16(libname);
+                if(!hModule)
+                {
+                    ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle. Filename too long ?\n",
+                        libname, hinst);
+                    return 6;   /* ERROR_INVALID_HANDLE seems most appropriate */
+                }
+
+                pModule = NE_GetPtr(hModule);
+                if(!pModule)
+                {
+                    ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
+                        libname, hinst);
+                    return 6;   /* ERROR_INVALID_HANDLE seems most appropriate */
+                }
+
+                TRACE("Loaded module '%s' at 0x%04x.\n", libname, hinst);
+
+                /*
+                 * Call initialization routines for all loaded DLLs. Note that
+                 * when we load implicitly linked DLLs this will be done by InitTask().
+                 */
+                if(pModule->flags & NE_FFLAGS_LIBMODULE)
+                {
+                    NE_InitializeDLLs(hModule);
+                    NE_DllProcessAttach(hModule);
+                }
+            }
+            return hinst;
+        }
+
+        if(hinst != 2)
+        {
+            /* We quit searching when we get another error than 'File not found' */
+            break;
+        }
+    }
+    return hinst;       /* The last error that occurred */
+}
+
+
+/**********************************************************************
+ *          NE_CreateThread
+ *
+ * Create the thread for a 16-bit module.
+ */
+static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
+{
+    HANDLE hThread;
+    TDB *pTask;
+    HTASK16 hTask;
+    HINSTANCE16 instance = 0;
+
+    if (!(hTask = TASK_SpawnTask( pModule, cmdShow, cmdline + 1, *cmdline, &hThread )))
+        return 0;
+
+    /* Post event to start the task */
+    PostEvent16( hTask );
+
+    /* Wait until we get the instance handle */
+    do
+    {
+        DirectedYield16( hTask );
+        if (!IsTask16( hTask ))  /* thread has died */
+        {
+            DWORD exit_code;
+            WaitForSingleObject( hThread, INFINITE );
+            GetExitCodeThread( hThread, &exit_code );
+            CloseHandle( hThread );
+            return exit_code;
+        }
+        if (!(pTask = GlobalLock16( hTask ))) break;
+        instance = pTask->hInstance;
+        GlobalUnlock16( hTask );
+    } while (!instance);
+
+    CloseHandle( hThread );
+    return instance;
+}
+
+
+/**********************************************************************
+ *          LoadModule      (KERNEL.45)
+ */
+HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
+{
+    BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
+    LOADPARAMS16 *params;
+    HMODULE16 hModule;
+    NE_MODULE *pModule;
+    LPSTR cmdline;
+    WORD cmdShow;
+
+    /* Load module */
+
+    if ( (hModule = NE_GetModuleByFilename(name) ) != 0 )
+    {
+        /* Special case: second instance of an already loaded NE module */
+
+        if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
+        if ( pModule->module32 ) return (HINSTANCE16)21;
+
+        /* Increment refcount */
+
+        pModule->count++;
+    }
+    else
+    {
+        /* Main case: load first instance of NE module */
+
+        if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
+            return hModule;
+
+        if ( !(pModule = NE_GetPtr( hModule )) )
+            return (HINSTANCE16)11;
+    }
+
+    /* If library module, we just retrieve the instance handle */
+
+    if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
+        return NE_GetInstance( pModule );
+
+    /*
+     *  At this point, we need to create a new process.
+     *
+     *  pModule points either to an already loaded module, whose refcount
+     *  has already been incremented (to avoid having the module vanish
+     *  in the meantime), or else to a stub module which contains only header
+     *  information.
+     */
+    params = (LOADPARAMS16 *)paramBlock;
+    cmdShow = ((WORD *)MapSL(params->showCmd))[1];
+    cmdline = MapSL( params->cmdLine );
+    return NE_CreateThread( pModule, cmdShow, cmdline );
+}
+
+
+/**********************************************************************
+ *          NE_StartTask
+ *
+ * Startup code for a new 16-bit task.
+ */
+DWORD NE_StartTask(void)
+{
+    TDB *pTask = TASK_GetCurrent();
+    NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
+    HINSTANCE16 hInstance, hPrevInstance;
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+    WORD sp;
+
+    if ( pModule->count > 0 )
+    {
+        /* Second instance of an already loaded NE module */
+        /* Note that the refcount was already incremented by the parent */
+
+        hPrevInstance = NE_GetInstance( pModule );
+
+        if ( pModule->dgroup )
+            if ( NE_CreateSegment( pModule, pModule->dgroup ) )
+                NE_LoadSegment( pModule, pModule->dgroup );
+
+        hInstance = NE_GetInstance( pModule );
+        TRACE("created second instance %04x[%d] of instance %04x.\n", hInstance, pModule->dgroup, hPrevInstance);
+
+    }
+    else
+    {
+        /* Load first instance of NE module */
+
+        pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
+
+        hInstance = NE_DoLoadModule( pModule );
+        hPrevInstance = 0;
+    }
+
+    if ( hInstance >= 32 )
+    {
+        CONTEXT86 context;
+
+        /* Enter instance handles into task struct */
+
+        pTask->hInstance = hInstance;
+        pTask->hPrevInstance = hPrevInstance;
+
+        /* Use DGROUP for 16-bit stack */
+
+        if (!(sp = pModule->sp))
+            sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
+        sp &= ~1;
+        sp -= sizeof(STACK16FRAME);
+        pTask->teb->cur_stack = MAKESEGPTR( GlobalHandleToSel16(hInstance), sp );
+
+        /* Registers at initialization must be:
+         * ax   zero
+         * bx   stack size in bytes
+         * cx   heap size in bytes
+         * si   previous app instance
+         * di   current app instance
+         * bp   zero
+         * es   selector to the PSP
+         * ds   dgroup of the application
+         * ss   stack selector
+         * sp   top of the stack
+         */
+        memset( &context, 0, sizeof(context) );
+        context.SegCs  = GlobalHandleToSel16(pSegTable[pModule->cs - 1].hSeg);
+        context.SegDs  = GlobalHandleToSel16(pTask->hInstance);
+        context.SegEs  = pTask->hPDB;
+        context.Eip    = pModule->ip;
+        context.Ebx    = pModule->stack_size;
+        context.Ecx    = pModule->heap_size;
+        context.Edi    = pTask->hInstance;
+        context.Esi    = pTask->hPrevInstance;
+
+        /* Now call 16-bit entry point */
+
+        TRACE("Starting main program: cs:ip=%04lx:%04lx ds=%04lx ss:sp=%04x:%04x\n",
+              context.SegCs, context.Eip, context.SegDs,
+              SELECTOROF(pTask->teb->cur_stack),
+              OFFSETOF(pTask->teb->cur_stack) );
+
+        wine_call_to_16_regs_short( &context, 0 );
+        ExitThread( LOWORD(context.Eax) );
+    }
+    return hInstance;  /* error code */
+}
+
+/***********************************************************************
+ *           LoadLibrary     (KERNEL.95)
+ *           LoadLibrary16   (KERNEL32.35)
+ */
+HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
+{
+    return LoadModule16(libname, (LPVOID)-1 );
+}
+
+
+/**********************************************************************
+ *	    MODULE_CallWEP
+ *
+ * Call a DLL's WEP, allowing it to shut down.
+ * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
+ */
+static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
+{
+    BOOL16 ret;
+    FARPROC16 WEP = GetProcAddress16( hModule, "WEP" );
+    if (!WEP) return FALSE;
+
+    __TRY
+    {
+        WORD args[1];
+        DWORD dwRet;
+
+        args[0] = WEP_FREE_DLL;
+        WOWCallback16Ex( (DWORD)WEP, WCB16_PASCAL, sizeof(args), args, &dwRet );
+        ret = LOWORD(dwRet);
+    }
+    __EXCEPT(page_fault)
+    {
+        WARN("Page fault\n");
+        ret = 0;
+    }
+    __ENDTRY
+
+    return ret;
+}
+
+
+/**********************************************************************
+ *	    NE_FreeModule
+ *
+ * Implementation of FreeModule16().
+ */
+static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
+{
+    HMODULE16 *hPrevModule;
+    NE_MODULE *pModule;
+    HMODULE16 *pModRef;
+    int i;
+
+    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
+    hModule = pModule->self;
+
+    TRACE("%04x count %d\n", hModule, pModule->count );
+
+    if (((INT16)(--pModule->count)) > 0 ) return TRUE;
+    else pModule->count = 0;
+
+    if (pModule->flags & NE_FFLAGS_BUILTIN)
+        return FALSE;  /* Can't free built-in module */
+
+    if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32))
+    {
+        /* Free the objects owned by the DLL module */
+        NE_CallUserSignalProc( hModule, USIG16_DLL_UNLOAD );
+
+        if (pModule->flags & NE_FFLAGS_LIBMODULE)
+            MODULE_CallWEP( hModule );
+        else
+            call_wep = FALSE;  /* We are freeing a task -> no more WEPs */
+    }
+
+
+    /* Clear magic number just in case */
+
+    pModule->magic = pModule->self = 0;
+
+      /* Remove it from the linked list */
+
+    hPrevModule = &hFirstModule;
+    while (*hPrevModule && (*hPrevModule != hModule))
+    {
+        hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
+    }
+    if (*hPrevModule) *hPrevModule = pModule->next;
+
+    /* Free the referenced modules */
+
+    pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
+    for (i = 0; i < pModule->modref_count; i++, pModRef++)
+    {
+        NE_FreeModule( *pModRef, call_wep );
+    }
+
+    /* Free the module storage */
+
+    GlobalFreeAll16( hModule );
+
+    /* Remove module from cache */
+
+    if (pCachedModule == pModule) pCachedModule = NULL;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    FreeModule    (KERNEL.46)
+ */
+BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
+{
+    return NE_FreeModule( hModule, TRUE );
+}
+
+
+/***********************************************************************
+ *           FreeLibrary     (KERNEL.96)
+ *           FreeLibrary16   (KERNEL32.36)
+ */
+void WINAPI FreeLibrary16( HINSTANCE16 handle )
+{
+    TRACE("%04x\n", handle );
+    FreeModule16( handle );
+}
+
+
+/**********************************************************************
+ *	    GetModuleName    (KERNEL.27)
+ */
+BOOL16 WINAPI GetModuleName16( HINSTANCE16 hinst, LPSTR buf, INT16 count )
+{
+    NE_MODULE *pModule;
+    BYTE *p;
+
+    if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
+    p = (BYTE *)pModule + pModule->name_table;
+    if (count > *p) count = *p + 1;
+    if (count > 0)
+    {
+        memcpy( buf, p + 1, count - 1 );
+        buf[count-1] = '\0';
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    GetModuleUsage    (KERNEL.48)
+ */
+INT16 WINAPI GetModuleUsage16( HINSTANCE16 hModule )
+{
+    NE_MODULE *pModule = NE_GetPtr( hModule );
+    return pModule ? pModule->count : 0;
+}
+
+
+/**********************************************************************
+ *	    GetExpWinVer    (KERNEL.167)
+ */
+WORD WINAPI GetExpWinVer16( HMODULE16 hModule )
+{
+    NE_MODULE *pModule = NE_GetPtr( hModule );
+    if ( !pModule ) return 0;
+
+    /*
+     * For built-in modules, fake the expected version the module should
+     * have according to the Windows version emulated by Wine
+     */
+    if ( !pModule->expected_version )
+    {
+        OSVERSIONINFOA versionInfo;
+        versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+
+        if ( GetVersionExA( &versionInfo ) )
+            pModule->expected_version =
+                     (versionInfo.dwMajorVersion & 0xff) << 8
+                   | (versionInfo.dwMinorVersion & 0xff);
+    }
+
+    return pModule->expected_version;
+}
+
+
+/***********************************************************************
+ *           WinExec     (KERNEL.166)
+ */
+HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
+{
+    LPCSTR p, args = NULL;
+    LPCSTR name_beg, name_end;
+    LPSTR name, cmdline;
+    int arglen;
+    HINSTANCE16 ret;
+    char buffer[MAX_PATH];
+
+    if (*lpCmdLine == '"') /* has to be only one and only at beginning ! */
+    {
+        name_beg = lpCmdLine+1;
+        p = strchr ( lpCmdLine+1, '"' );
+        if (p)
+        {
+            name_end = p;
+            args = strchr ( p, ' ' );
+        }
+        else /* yes, even valid with trailing '"' missing */
+            name_end = lpCmdLine+strlen(lpCmdLine);
+    }
+    else
+    {
+        name_beg = lpCmdLine;
+        args = strchr( lpCmdLine, ' ' );
+        name_end = args ? args : lpCmdLine+strlen(lpCmdLine);
+    }
+
+    if ((name_beg == lpCmdLine) && (!args))
+    { /* just use the original cmdline string as file name */
+        name = (LPSTR)lpCmdLine;
+    }
+    else
+    {
+        if (!(name = HeapAlloc( GetProcessHeap(), 0, name_end - name_beg + 1 )))
+            return ERROR_NOT_ENOUGH_MEMORY;
+        memcpy( name, name_beg, name_end - name_beg );
+        name[name_end - name_beg] = '\0';
+    }
+
+    if (args)
+    {
+        args++;
+        arglen = strlen(args);
+        cmdline = HeapAlloc( GetProcessHeap(), 0, 2 + arglen );
+        cmdline[0] = (BYTE)arglen;
+        strcpy( cmdline + 1, args );
+    }
+    else
+    {
+        cmdline = HeapAlloc( GetProcessHeap(), 0, 2 );
+        cmdline[0] = cmdline[1] = 0;
+    }
+
+    TRACE("name: '%s', cmdline: '%.*s'\n", name, cmdline[0], &cmdline[1]);
+
+    if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
+    {
+        LOADPARAMS16 params;
+        WORD showCmd[2];
+        showCmd[0] = 2;
+        showCmd[1] = nCmdShow;
+
+        params.hEnvironment = 0;
+        params.cmdLine = MapLS( cmdline );
+        params.showCmd = MapLS( showCmd );
+        params.reserved = 0;
+
+        ret = LoadModule16( buffer, &params );
+        UnMapLS( params.cmdLine );
+        UnMapLS( params.showCmd );
+    }
+    else ret = GetLastError();
+
+    HeapFree( GetProcessHeap(), 0, cmdline );
+    if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
+
+    if (ret == 21)  /* 32-bit module */
+    {
+        DWORD count;
+        ReleaseThunkLock( &count );
+        ret = LOWORD( WinExec( lpCmdLine, nCmdShow ) );
+        RestoreThunkLock( count );
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    GetModuleHandle    (KERNEL.47)
+ *
+ * Find a module from a module name.
+ *
+ * NOTE: The current implementation works the same way the Windows 95 one
+ *	 does. Do not try to 'fix' it, fix the callers.
+ *	 + It does not do ANY extension handling (except that strange .EXE bit)!
+ *	 + It does not care about paths, just about basenames. (same as Windows)
+ *
+ * RETURNS
+ *   LOWORD:
+ *	the win16 module handle if found
+ * 	0 if not
+ *   HIWORD (undocumented, see "Undocumented Windows", chapter 5):
+ *	Always hFirstModule
+ */
+DWORD WINAPI WIN16_GetModuleHandle( SEGPTR name )
+{
+    if (HIWORD(name) == 0)
+        return MAKELONG(GetExePtr( (HINSTANCE16)name), hFirstModule );
+    return MAKELONG(GetModuleHandle16( MapSL(name)), hFirstModule );
+}
+
+/**********************************************************************
+ *	    NE_GetModuleByFilename
+ */
+static HMODULE16 NE_GetModuleByFilename( LPCSTR name )
+{
+    HMODULE16   hModule;
+    LPSTR       s, p;
+    BYTE        len, *name_table;
+    char        tmpstr[MAX_PATH];
+    NE_MODULE *pModule;
+
+    lstrcpynA(tmpstr, name, sizeof(tmpstr));
+
+    /* If the base filename of 'name' matches the base filename of the module
+     * filename of some module (case-insensitive compare):
+     * Return its handle.
+     */
+
+    /* basename: search backwards in passed name to \ / or : */
+    s = tmpstr + strlen(tmpstr);
+    while (s > tmpstr)
+    {
+        if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
+                break;
+        s--;
+    }
+
+    /* search this in loaded filename list */
+    for (hModule = hFirstModule; hModule ; hModule = pModule->next)
+    {
+        char            *loadedfn;
+        OFSTRUCT        *ofs;
+
+        pModule = NE_GetPtr( hModule );
+        if (!pModule) break;
+        if (!pModule->fileinfo) continue;
+        if (pModule->flags & NE_FFLAGS_WIN32) continue;
+
+        ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
+        loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
+        /* basename: search backwards in pathname to \ / or : */
+        while (loadedfn > (char*)ofs->szPathName)
+        {
+            if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
+                    break;
+            loadedfn--;
+        }
+        /* case insensitive compare ... */
+        if (!FILE_strcasecmp(loadedfn, s))
+            return hModule;
+    }
+    /* If basename (without ext) matches the module name of a module:
+     * Return its handle.
+     */
+
+    if ( (p = strrchr( s, '.' )) != NULL ) *p = '\0';
+    len = strlen(s);
+
+    for (hModule = hFirstModule; hModule ; hModule = pModule->next)
+    {
+        pModule = NE_GetPtr( hModule );
+        if (!pModule) break;
+        if (pModule->flags & NE_FFLAGS_WIN32) continue;
+
+        name_table = (BYTE *)pModule + pModule->name_table;
+        if ((*name_table == len) && !FILE_strncasecmp(s, name_table+1, len))
+            return hModule;
+    }
+
+    return 0;
+}
+
+/***********************************************************************
+ *           GetProcAddress16   (KERNEL32.37)
+ * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
+ */
+FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
+{
+    if (!hModule) return 0;
+    if (HIWORD(hModule))
+    {
+        WARN("hModule is Win32 handle (%p)\n", hModule );
+        return 0;
+    }
+    return GetProcAddress16( LOWORD(hModule), name );
+}
+
+/**********************************************************************
+ *	    ModuleFirst    (TOOLHELP.59)
+ */
+BOOL16 WINAPI ModuleFirst16( MODULEENTRY *lpme )
+{
+    lpme->wNext = hFirstModule;
+    return ModuleNext16( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleNext    (TOOLHELP.60)
+ */
+BOOL16 WINAPI ModuleNext16( MODULEENTRY *lpme )
+{
+    NE_MODULE *pModule;
+    char *name;
+
+    if (!lpme->wNext) return FALSE;
+    if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
+    name = (char *)pModule + pModule->name_table;
+    memcpy( lpme->szModule, name + 1, min(*name, MAX_MODULE_NAME) );
+    lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
+    lpme->hModule = lpme->wNext;
+    lpme->wcUsage = pModule->count;
+    lstrcpynA( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
+    lpme->wNext = pModule->next;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	    ModuleFindName    (TOOLHELP.61)
+ */
+BOOL16 WINAPI ModuleFindName16( MODULEENTRY *lpme, LPCSTR name )
+{
+    lpme->wNext = GetModuleHandle16( name );
+    return ModuleNext16( lpme );
+}
+
+
+/**********************************************************************
+ *	    ModuleFindHandle    (TOOLHELP.62)
+ */
+BOOL16 WINAPI ModuleFindHandle16( MODULEENTRY *lpme, HMODULE16 hModule )
+{
+    hModule = GetExePtr( hModule );
+    lpme->wNext = hModule;
+    return ModuleNext16( lpme );
+}
+
+
+/***************************************************************************
+ *          IsRomModule    (KERNEL.323)
+ */
+BOOL16 WINAPI IsRomModule16( HMODULE16 unused )
+{
+    return FALSE;
+}
+
+/***************************************************************************
+ *          IsRomFile    (KERNEL.326)
+ */
+BOOL16 WINAPI IsRomFile16( HFILE16 unused )
+{
+    return FALSE;
+}
+
+/***********************************************************************
+ *           create_dummy_module
+ *
+ * Create a dummy NE module for Win32 or Winelib.
+ */
+static HMODULE16 create_dummy_module( HMODULE module32 )
+{
+    HMODULE16 hModule;
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSegment;
+    char *pStr,*s;
+    unsigned int len;
+    const char* basename;
+    OFSTRUCT *ofs;
+    int of_size, size;
+    char filename[MAX_PATH];
+    IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module32 );
+
+    if (!nt) return (HMODULE16)11;  /* invalid exe */
+
+    /* Extract base filename */
+    GetModuleFileNameA( module32, filename, sizeof(filename) );
+    basename = strrchr(filename, '\\');
+    if (!basename) basename = filename;
+    else basename++;
+    len = strlen(basename);
+    if ((s = strchr(basename, '.'))) len = s - basename;
+
+    /* Allocate module */
+    of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
+                    + strlen(filename) + 1;
+    size = sizeof(NE_MODULE) +
+                 /* loaded file info */
+                 ((of_size + 3) & ~3) +
+                 /* segment table: DS,CS */
+                 2 * sizeof(SEGTABLEENTRY) +
+                 /* name table */
+                 len + 2 +
+                 /* several empty tables */
+                 8;
+
+    hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
+    if (!hModule) return (HMODULE16)11;  /* invalid exe */
+
+    FarSetOwner16( hModule, hModule );
+    pModule = (NE_MODULE *)GlobalLock16( hModule );
+
+    /* Set all used entries */
+    pModule->magic            = IMAGE_OS2_SIGNATURE;
+    pModule->count            = 1;
+    pModule->next             = 0;
+    pModule->flags            = NE_FFLAGS_WIN32;
+    pModule->dgroup           = 0;
+    pModule->ss               = 1;
+    pModule->cs               = 2;
+    pModule->heap_size        = 0;
+    pModule->stack_size       = 0;
+    pModule->seg_count        = 2;
+    pModule->modref_count     = 0;
+    pModule->nrname_size      = 0;
+    pModule->fileinfo         = sizeof(NE_MODULE);
+    pModule->os_flags         = NE_OSFLAGS_WINDOWS;
+    pModule->self             = hModule;
+    pModule->module32         = module32;
+
+    /* Set version and flags */
+    pModule->expected_version = ((nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
+                                (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
+    if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
+        pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
+
+    /* Set loaded file information */
+    ofs = (OFSTRUCT *)(pModule + 1);
+    memset( ofs, 0, of_size );
+    ofs->cBytes = of_size < 256 ? of_size : 255;   /* FIXME */
+    strcpy( ofs->szPathName, filename );
+
+    pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + ((of_size + 3) & ~3));
+    pModule->seg_table = (int)pSegment - (int)pModule;
+    /* Data segment */
+    pSegment->size    = 0;
+    pSegment->flags   = NE_SEGFLAGS_DATA;
+    pSegment->minsize = 0x1000;
+    pSegment++;
+    /* Code segment */
+    pSegment->flags   = 0;
+    pSegment++;
+
+    /* Module name */
+    pStr = (char *)pSegment;
+    pModule->name_table = (int)pStr - (int)pModule;
+    assert(len<256);
+    *pStr = len;
+    lstrcpynA( pStr+1, basename, len+1 );
+    pStr += len+2;
+
+    /* All tables zero terminated */
+    pModule->res_table = pModule->import_table = pModule->entry_table = (int)pStr - (int)pModule;
+
+    NE_RegisterModule( pModule );
+    LoadLibraryA( filename );  /* increment the ref count of the 32-bit module */
+    return hModule;
+}
+
+/***********************************************************************
+ *           PrivateLoadLibrary       (KERNEL32.@)
+ *
+ * FIXME: rough guesswork, don't know what "Private" means
+ */
+HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
+{
+    return LoadLibrary16(libname);
+}
+
+/***********************************************************************
+ *           PrivateFreeLibrary       (KERNEL32.@)
+ *
+ * FIXME: rough guesswork, don't know what "Private" means
+ */
+void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
+{
+    FreeLibrary16(handle);
+}
+
+/***************************************************************************
+ *		MapHModuleLS			(KERNEL32.@)
+ */
+HMODULE16 WINAPI MapHModuleLS(HMODULE hmod)
+{
+    HMODULE16 ret;
+    NE_MODULE *pModule;
+
+    if (!hmod)
+        return TASK_GetCurrent()->hInstance;
+    if (!HIWORD(hmod))
+        return LOWORD(hmod); /* we already have a 16 bit module handle */
+    pModule = (NE_MODULE*)GlobalLock16(hFirstModule);
+    while (pModule)  {
+        if (pModule->module32 == hmod)
+            return pModule->self;
+        pModule = (NE_MODULE*)GlobalLock16(pModule->next);
+    }
+    if ((ret = create_dummy_module( hmod )) < 32)
+    {
+        SetLastError(ret);
+        ret = 0;
+    }
+    return ret;
+}
+
+/***************************************************************************
+ *		MapHModuleSL			(KERNEL32.@)
+ */
+HMODULE WINAPI MapHModuleSL(HMODULE16 hmod)
+{
+    NE_MODULE *pModule;
+
+    if (!hmod) {
+        TDB *pTask = TASK_GetCurrent();
+        hmod = pTask->hModule;
+    }
+    pModule = (NE_MODULE*)GlobalLock16(hmod);
+    if ((pModule->magic!=IMAGE_OS2_SIGNATURE) || !(pModule->flags & NE_FFLAGS_WIN32))
+        return 0;
+    return pModule->module32;
+}
+
+/***************************************************************************
+ *		MapHInstLS			(KERNEL32.@)
+ *		MapHInstLS			(KERNEL.472)
+ */
+void WINAPI MapHInstLS( CONTEXT86 *context )
+{
+    context->Eax = MapHModuleLS( (HMODULE)context->Eax );
+}
+
+/***************************************************************************
+ *		MapHInstSL			(KERNEL32.@)
+ *		MapHInstSL			(KERNEL.473)
+ */
+void WINAPI MapHInstSL( CONTEXT86 *context )
+{
+    context->Eax = (DWORD)MapHModuleSL( context->Eax );
+}
+
+/***************************************************************************
+ *		MapHInstLS_PN			(KERNEL32.@)
+ */
+void WINAPI MapHInstLS_PN( CONTEXT86 *context )
+{
+    if (context->Eax) context->Eax = MapHModuleLS( (HMODULE)context->Eax );
+}
+
+/***************************************************************************
+ *		MapHInstSL_PN			(KERNEL32.@)
+ */
+void WINAPI MapHInstSL_PN( CONTEXT86 *context )
+{
+    if (context->Eax) context->Eax = (DWORD)MapHModuleSL( context->Eax );
+}
diff --git a/loader/ne/segment.c b/dlls/kernel/ne_segment.c
similarity index 97%
rename from loader/ne/segment.c
rename to dlls/kernel/ne_segment.c
index 83fce73..061f4a6 100644
--- a/loader/ne/segment.c
+++ b/dlls/kernel/ne_segment.c
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include "wine/winbase16.h"
+#include "wownt32.h"
 #include "wine/library.h"
 #include "global.h"
 #include "task.h"
@@ -82,10 +83,6 @@
 
 static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum);
 
-/* ### start build ### */
-extern WORD CALLBACK NE_CallTo16_word_ww(FARPROC16,WORD,WORD);
-extern WORD CALLBACK NE_CallTo16_word_www(FARPROC16,WORD,WORD,WORD);
-/* ### stop build ### */
 
 /***********************************************************************
  *           NE_GetRelocAddrName
@@ -158,6 +155,8 @@
         DWORD oldstack;
         HANDLE hFile32;
         HFILE16 hFile16;
+        WORD args[3];
+        DWORD ret;
 
  	selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) );
  	oldstack = NtCurrentTeb()->cur_stack;
@@ -169,8 +168,11 @@
         DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32,
                          0, FALSE, DUPLICATE_SAME_ACCESS );
         hFile16 = Win32HandleToDosFileHandle( hFile32 );
- 	pSeg->hSeg = NE_CallTo16_word_www( selfloadheader->LoadAppSeg,
-                                           pModule->self, hFile16, segnum );
+        args[2] = pModule->self;
+        args[1] = hFile16;
+        args[0] = segnum;
+        WOWCallback16Ex( (DWORD)selfloadheader->LoadAppSeg, WCB16_PASCAL, sizeof(args), args, &ret );
+        pSeg->hSeg = LOWORD(ret);
 	TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg);
         _lclose16( hFile16 );
  	NtCurrentTeb()->cur_stack = oldstack;
@@ -450,6 +452,7 @@
         SELFLOADHEADER *selfloadheader;
         HMODULE16 mod = GetModuleHandle16("KERNEL");
         DWORD oldstack;
+        WORD args[2];
 
         TRACE_(module)("%.*s is a self-loading module!\n",
 		     *((BYTE*)pModule + pModule->name_table),
@@ -470,7 +473,9 @@
         hFile16 = Win32HandleToDosFileHandle( hf );
         TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n",
               pModule->self,hFile16);
-        NE_CallTo16_word_ww(selfloadheader->BootApp, pModule->self,hFile16);
+        args[1] = pModule->self;
+        args[0] = hFile16;
+        WOWCallback16Ex( (DWORD)selfloadheader->BootApp, WCB16_PASCAL, sizeof(args), args, NULL );
 	TRACE_(dll)("Return from CallBootAppProc\n");
         _lclose16(hFile16);
         NtCurrentTeb()->cur_stack = oldstack;
diff --git a/dlls/kernel/task.c b/dlls/kernel/task.c
new file mode 100644
index 0000000..44b4ebc
--- /dev/null
+++ b/dlls/kernel/task.c
@@ -0,0 +1,1556 @@
+/*
+ * Task functions
+ *
+ * Copyright 1995 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "winbase.h"
+#include "wingdi.h"
+#include "winnt.h"
+#include "wownt32.h"
+#include "winuser.h"
+
+#include "wine/winbase16.h"
+#include "drive.h"
+#include "file.h"
+#include "global.h"
+#include "instance.h"
+#include "module.h"
+#include "winternl.h"
+#include "selectors.h"
+#include "wine/server.h"
+#include "syslevel.h"
+#include "stackframe.h"
+#include "task.h"
+#include "thread.h"
+#include "toolhelp.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(task);
+WINE_DECLARE_DEBUG_CHANNEL(relay);
+WINE_DECLARE_DEBUG_CHANNEL(toolhelp);
+
+  /* Min. number of thunks allocated when creating a new segment */
+#define MIN_THUNKS  32
+
+static THHOOK DefaultThhook;
+
+#define hFirstTask   (pThhook->HeadTDB)
+#define hLockedTask  (pThhook->LockTDB)
+
+static UINT16 nTaskCount = 0;
+
+static HTASK16 initial_task;
+
+/***********************************************************************
+ *	     TASK_InstallTHHook
+ */
+void TASK_InstallTHHook( THHOOK *pNewThhook )
+{
+     THHOOK *pOldThhook = pThhook;
+
+     pThhook = pNewThhook? pNewThhook : &DefaultThhook;
+
+     *pThhook = *pOldThhook;
+}
+
+/***********************************************************************
+ *	     TASK_GetPtr
+ */
+static TDB *TASK_GetPtr( HTASK16 hTask )
+{
+    return GlobalLock16( hTask );
+}
+
+
+/***********************************************************************
+ *	     TASK_GetCurrent
+ */
+TDB *TASK_GetCurrent(void)
+{
+    return TASK_GetPtr( GetCurrentTask() );
+}
+
+
+/***********************************************************************
+ *           TASK_LinkTask
+ */
+static void TASK_LinkTask( HTASK16 hTask )
+{
+    HTASK16 *prevTask;
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetPtr( hTask ))) return;
+    prevTask = &hFirstTask;
+    while (*prevTask)
+    {
+        TDB *prevTaskPtr = TASK_GetPtr( *prevTask );
+        if (prevTaskPtr->priority >= pTask->priority) break;
+        prevTask = &prevTaskPtr->hNext;
+    }
+    pTask->hNext = *prevTask;
+    *prevTask = hTask;
+    nTaskCount++;
+}
+
+
+/***********************************************************************
+ *           TASK_UnlinkTask
+ */
+static void TASK_UnlinkTask( HTASK16 hTask )
+{
+    HTASK16 *prevTask;
+    TDB *pTask;
+
+    prevTask = &hFirstTask;
+    while (*prevTask && (*prevTask != hTask))
+    {
+        pTask = TASK_GetPtr( *prevTask );
+        prevTask = &pTask->hNext;
+    }
+    if (*prevTask)
+    {
+        pTask = TASK_GetPtr( *prevTask );
+        *prevTask = pTask->hNext;
+        pTask->hNext = 0;
+        nTaskCount--;
+    }
+}
+
+
+/***********************************************************************
+ *           TASK_CreateThunks
+ *
+ * Create a thunk free-list in segment 'handle', starting from offset 'offset'
+ * and containing 'count' entries.
+ */
+static void TASK_CreateThunks( HGLOBAL16 handle, WORD offset, WORD count )
+{
+    int i;
+    WORD free;
+    THUNKS *pThunk;
+
+    pThunk = (THUNKS *)((BYTE *)GlobalLock16( handle ) + offset);
+    pThunk->next = 0;
+    pThunk->magic = THUNK_MAGIC;
+    pThunk->free = (int)&pThunk->thunks - (int)pThunk;
+    free = pThunk->free;
+    for (i = 0; i < count-1; i++)
+    {
+        free += 8;  /* Offset of next thunk */
+        pThunk->thunks[4*i] = free;
+    }
+    pThunk->thunks[4*i] = 0;  /* Last thunk */
+}
+
+
+/***********************************************************************
+ *           TASK_AllocThunk
+ *
+ * Allocate a thunk for MakeProcInstance().
+ */
+static SEGPTR TASK_AllocThunk(void)
+{
+    TDB *pTask;
+    THUNKS *pThunk;
+    WORD sel, base;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    sel = pTask->hCSAlias;
+    pThunk = &pTask->thunks;
+    base = (int)pThunk - (int)pTask;
+    while (!pThunk->free)
+    {
+        sel = pThunk->next;
+        if (!sel)  /* Allocate a new segment */
+        {
+            sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
+                                pTask->hPDB, WINE_LDT_FLAGS_CODE );
+            if (!sel) return (SEGPTR)0;
+            TASK_CreateThunks( sel, 0, MIN_THUNKS );
+            pThunk->next = sel;
+        }
+        pThunk = (THUNKS *)GlobalLock16( sel );
+        base = 0;
+    }
+    base += pThunk->free;
+    pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
+    return MAKESEGPTR( sel, base );
+}
+
+
+/***********************************************************************
+ *           TASK_FreeThunk
+ *
+ * Free a MakeProcInstance() thunk.
+ */
+static BOOL TASK_FreeThunk( SEGPTR thunk )
+{
+    TDB *pTask;
+    THUNKS *pThunk;
+    WORD sel, base;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    sel = pTask->hCSAlias;
+    pThunk = &pTask->thunks;
+    base = (int)pThunk - (int)pTask;
+    while (sel && (sel != HIWORD(thunk)))
+    {
+        sel = pThunk->next;
+        pThunk = (THUNKS *)GlobalLock16( sel );
+        base = 0;
+    }
+    if (!sel) return FALSE;
+    *(WORD *)((BYTE *)pThunk + LOWORD(thunk) - base) = pThunk->free;
+    pThunk->free = LOWORD(thunk) - base;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           TASK_Create
+ *
+ * NOTE: This routine might be called by a Win32 thread. Thus, we need
+ *       to be careful to protect global data structures. We do this
+ *       by entering the Win16Lock while linking the task into the
+ *       global task list.
+ */
+static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, BYTE len )
+{
+    HTASK16 hTask;
+    TDB *pTask;
+    FARPROC16 proc;
+    HMODULE16 hModule = pModule ? pModule->self : 0;
+
+      /* Allocate the task structure */
+
+    hTask = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB) );
+    if (!hTask) return NULL;
+    pTask = TASK_GetPtr( hTask );
+    FarSetOwner16( hTask, hModule );
+
+    /* Fill the task structure */
+
+    pTask->hSelf = hTask;
+
+    if (teb && teb->tibflags & TEBF_WIN32)
+    {
+        pTask->flags        |= TDBF_WIN32;
+        pTask->hInstance     = hModule;
+        pTask->hPrevInstance = 0;
+        /* NOTE: for 16-bit tasks, the instance handles are updated later on
+           in NE_InitProcess */
+    }
+
+    pTask->version       = pModule ? pModule->expected_version : 0x0400;
+    pTask->hModule       = hModule;
+    pTask->hParent       = GetCurrentTask();
+    pTask->magic         = TDB_MAGIC;
+    pTask->nCmdShow      = cmdShow;
+    pTask->teb           = teb;
+    pTask->curdrive      = DRIVE_GetCurrentDrive() | 0x80;
+    strcpy( pTask->curdir, "\\" );
+    WideCharToMultiByte(CP_ACP, 0, DRIVE_GetDosCwd(DRIVE_GetCurrentDrive()), -1,
+                        pTask->curdir + 1, sizeof(pTask->curdir) - 1, NULL, NULL);
+    pTask->curdir[sizeof(pTask->curdir) - 1] = 0; /* ensure 0 termination */
+
+      /* Create the thunks block */
+
+    TASK_CreateThunks( hTask, (int)&pTask->thunks - (int)pTask, 7 );
+
+      /* Copy the module name */
+
+    if (hModule)
+    {
+        char name[10];
+        GetModuleName16( hModule, name, sizeof(name) );
+        strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
+        pTask->compat_flags = GetProfileIntA( "Compatibility", name, 0 );
+    }
+
+      /* Allocate a selector for the PDB */
+
+    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB16),
+                                      hModule, WINE_LDT_FLAGS_DATA );
+
+      /* Fill the PDB */
+
+    pTask->pdb.int20 = 0x20cd;
+    pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
+    proc = GetProcAddress16( GetModuleHandle16("KERNEL"), "DOS3Call" );
+    memcpy( &pTask->pdb.dispatcher[1], &proc, sizeof(proc) );
+    pTask->pdb.savedint22 = 0;
+    pTask->pdb.savedint23 = 0;
+    pTask->pdb.savedint24 = 0;
+    pTask->pdb.fileHandlesPtr =
+        MAKESEGPTR( GlobalHandleToSel16(pTask->hPDB), (int)&((PDB16 *)0)->fileHandles );
+    pTask->pdb.hFileHandles = 0;
+    memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
+    /* FIXME: should we make a copy of the environment? */
+    pTask->pdb.environment    = SELECTOROF(GetDOSEnvironment16());
+    pTask->pdb.nbFiles        = 20;
+
+    /* Fill the command line */
+
+    if (!cmdline)
+    {
+        cmdline = GetCommandLineA();
+        /* remove the first word (program name) */
+        if (*cmdline == '"')
+            if (!(cmdline = strchr( cmdline+1, '"' ))) cmdline = GetCommandLineA();
+        while (*cmdline && (*cmdline != ' ') && (*cmdline != '\t')) cmdline++;
+        while ((*cmdline == ' ') || (*cmdline == '\t')) cmdline++;
+        len = strlen(cmdline);
+    }
+    if (len >= sizeof(pTask->pdb.cmdLine)) len = sizeof(pTask->pdb.cmdLine)-1;
+    pTask->pdb.cmdLine[0] = len;
+    memcpy( pTask->pdb.cmdLine + 1, cmdline, len );
+    /* pTask->pdb.cmdLine[len+1] = 0; */
+
+    TRACE("cmdline='%.*s' task=%04x\n", len, cmdline, hTask );
+
+      /* Allocate a code segment alias for the TDB */
+
+    pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
+                                          sizeof(TDB), pTask->hPDB, WINE_LDT_FLAGS_CODE );
+
+      /* Default DTA overwrites command line */
+
+    pTask->dta = MAKESEGPTR( pTask->hPDB, (int)&pTask->pdb.cmdLine - (int)&pTask->pdb );
+
+    /* Create scheduler event for 16-bit tasks */
+
+    if ( !(pTask->flags & TDBF_WIN32) )
+        NtCreateEvent( &pTask->hEvent, EVENT_ALL_ACCESS, NULL, TRUE, FALSE );
+
+    /* Enter task handle into thread */
+
+    if (teb) teb->htask16 = hTask;
+    if (!initial_task) initial_task = hTask;
+
+    return pTask;
+}
+
+
+/***********************************************************************
+ *           TASK_DeleteTask
+ */
+static void TASK_DeleteTask( HTASK16 hTask )
+{
+    TDB *pTask;
+    HGLOBAL16 hPDB;
+
+    if (!(pTask = TASK_GetPtr( hTask ))) return;
+    hPDB = pTask->hPDB;
+
+    pTask->magic = 0xdead; /* invalidate signature */
+
+    /* Free the selector aliases */
+
+    GLOBAL_FreeBlock( pTask->hCSAlias );
+    GLOBAL_FreeBlock( pTask->hPDB );
+
+    /* Free the task module */
+
+    FreeModule16( pTask->hModule );
+
+    /* Free the task structure itself */
+
+    GlobalFree16( hTask );
+
+    /* Free all memory used by this task (including the 32-bit stack, */
+    /* the environment block and the thunk segments). */
+
+    GlobalFreeAll16( hPDB );
+}
+
+
+/***********************************************************************
+ *           TASK_CreateMainTask
+ *
+ * Create a task for the main (32-bit) process.
+ */
+void TASK_CreateMainTask(void)
+{
+    TDB *pTask;
+    STARTUPINFOA startup_info;
+    UINT cmdShow = 1; /* SW_SHOWNORMAL but we don't want to include winuser.h here */
+
+    GetStartupInfoA( &startup_info );
+    if (startup_info.dwFlags & STARTF_USESHOWWINDOW) cmdShow = startup_info.wShowWindow;
+    pTask = TASK_Create( NULL, cmdShow, NtCurrentTeb(), NULL, 0 );
+    if (!pTask)
+    {
+        ERR("could not create task for main process\n");
+        ExitProcess(1);
+    }
+
+    /* Add the task to the linked list */
+    /* (no need to get the win16 lock, we are the only thread at this point) */
+    TASK_LinkTask( pTask->hSelf );
+}
+
+
+/* startup routine for a new 16-bit thread */
+static DWORD CALLBACK task_start( TDB *pTask )
+{
+    DWORD ret;
+
+    NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
+    NtCurrentTeb()->htask16 = pTask->hSelf;
+
+    _EnterWin16Lock();
+    TASK_LinkTask( pTask->hSelf );
+    pTask->teb = NtCurrentTeb();
+    ret = NE_StartTask();
+    _LeaveWin16Lock();
+    return ret;
+}
+
+
+/***********************************************************************
+ *           TASK_SpawnTask
+ *
+ * Spawn a new 16-bit task.
+ */
+HTASK16 TASK_SpawnTask( NE_MODULE *pModule, WORD cmdShow,
+                        LPCSTR cmdline, BYTE len, HANDLE *hThread )
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_Create( pModule, cmdShow, NULL, cmdline, len ))) return 0;
+    if (!(*hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)task_start, pTask, 0, NULL )))
+    {
+        TASK_DeleteTask( pTask->hSelf );
+        return 0;
+    }
+    return pTask->hSelf;
+}
+
+
+/***********************************************************************
+ *           TASK_GetTaskFromThread
+ */
+HTASK16 TASK_GetTaskFromThread( DWORD thread )
+{
+    TDB *p = TASK_GetPtr( hFirstTask );
+    while (p)
+    {
+        if (p->teb->tid == thread) return p->hSelf;
+        p = TASK_GetPtr( p->hNext );
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           TASK_CallTaskSignalProc
+ */
+static void TASK_CallTaskSignalProc( UINT16 uCode, HANDLE16 hTaskOrModule )
+{
+    WORD args[5];
+    TDB *pTask = TASK_GetCurrent();
+
+    if ( !pTask || !pTask->userhandler ) return;
+
+    args[4] = hTaskOrModule;
+    args[3] = uCode;
+    args[2] = 0;
+    args[1] = pTask->hInstance;
+    args[0] = pTask->hQueue;
+    WOWCallback16Ex( (DWORD)pTask->userhandler, WCB16_PASCAL, sizeof(args), args, NULL );
+}
+
+
+/***********************************************************************
+ *           TASK_ExitTask
+ */
+void TASK_ExitTask(void)
+{
+    TDB *pTask;
+    DWORD lockCount;
+
+    /* Enter the Win16Lock to protect global data structures */
+    _EnterWin16Lock();
+
+    pTask = TASK_GetCurrent();
+    if ( !pTask )
+    {
+        _LeaveWin16Lock();
+        return;
+    }
+
+    TRACE("Killing task %04x\n", pTask->hSelf );
+
+    /* Perform USER cleanup */
+
+    TASK_CallTaskSignalProc( USIG16_TERMINATION, pTask->hSelf );
+
+    /* Remove the task from the list to be sure we never switch back to it */
+    TASK_UnlinkTask( pTask->hSelf );
+
+    if (!nTaskCount || (nTaskCount == 1 && hFirstTask == initial_task))
+    {
+        TRACE("this is the last task, exiting\n" );
+        ExitKernel16();
+    }
+
+    pTask->nEvents = 0;
+
+    if ( hLockedTask == pTask->hSelf )
+        hLockedTask = 0;
+
+    TASK_DeleteTask( pTask->hSelf );
+
+    /* ... and completely release the Win16Lock, just in case. */
+    ReleaseThunkLock( &lockCount );
+}
+
+
+/***********************************************************************
+ *           ExitKernel (KERNEL.2)
+ *
+ * Clean-up everything and exit the Wine process.
+ */
+void WINAPI ExitKernel16(void)
+{
+    WriteOutProfiles16();
+    TerminateProcess( GetCurrentProcess(), 0 );
+}
+
+
+/***********************************************************************
+ *           InitTask  (KERNEL.91)
+ *
+ * Called by the application startup code.
+ */
+void WINAPI InitTask16( CONTEXT86 *context )
+{
+    TDB *pTask;
+    INSTANCEDATA *pinstance;
+    SEGPTR ptr;
+
+    context->Eax = 0;
+    if (!(pTask = TASK_GetCurrent())) return;
+
+    /* Note: we need to trust that BX/CX contain the stack/heap sizes,
+       as some apps, notably Visual Basic apps, *modify* the heap/stack
+       size of the instance data segment before calling InitTask() */
+
+    /* Initialize the INSTANCEDATA structure */
+    pinstance = MapSL( MAKESEGPTR(CURRENT_DS, 0) );
+    pinstance->stackmin    = OFFSETOF( pTask->teb->cur_stack ) + sizeof( STACK16FRAME );
+    pinstance->stackbottom = pinstance->stackmin; /* yup, that's right. Confused me too. */
+    pinstance->stacktop    = ( pinstance->stackmin > LOWORD(context->Ebx) ?
+                               pinstance->stackmin - LOWORD(context->Ebx) : 0 ) + 150;
+
+    /* Initialize the local heap */
+    if (LOWORD(context->Ecx))
+        LocalInit16( GlobalHandleToSel16(pTask->hInstance), 0, LOWORD(context->Ecx) );
+
+    /* Initialize implicitly loaded DLLs */
+    NE_InitializeDLLs( pTask->hModule );
+    NE_DllProcessAttach( pTask->hModule );
+
+    /* Registers on return are:
+     * ax     1 if OK, 0 on error
+     * cx     stack limit in bytes
+     * dx     cmdShow parameter
+     * si     instance handle of the previous instance
+     * di     instance handle of the new task
+     * es:bx  pointer to command line inside PSP
+     *
+     * 0 (=%bp) is pushed on the stack
+     */
+    ptr = stack16_push( sizeof(WORD) );
+    *(WORD *)MapSL(ptr) = 0;
+    context->Esp -= 2;
+
+    context->Eax = 1;
+
+    if (!pTask->pdb.cmdLine[0]) context->Ebx = 0x80;
+    else
+    {
+        LPBYTE p = &pTask->pdb.cmdLine[1];
+        while ((*p == ' ') || (*p == '\t')) p++;
+        context->Ebx = 0x80 + (p - pTask->pdb.cmdLine);
+    }
+    context->Ecx   = pinstance->stacktop;
+    context->Edx   = pTask->nCmdShow;
+    context->Esi   = (DWORD)pTask->hPrevInstance;
+    context->Edi   = (DWORD)pTask->hInstance;
+    context->SegEs = (WORD)pTask->hPDB;
+}
+
+
+/***********************************************************************
+ *           WaitEvent  (KERNEL.30)
+ */
+BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = GetCurrentTask();
+    pTask = TASK_GetPtr( hTask );
+
+    if (pTask->flags & TDBF_WIN32)
+    {
+        FIXME("called for Win32 thread (%04x)!\n", NtCurrentTeb()->teb_sel);
+        return TRUE;
+    }
+
+    if (pTask->nEvents > 0)
+    {
+        pTask->nEvents--;
+        return FALSE;
+    }
+
+    if (pTask->teb == NtCurrentTeb())
+    {
+        DWORD lockCount;
+
+        NtResetEvent( pTask->hEvent, NULL );
+        ReleaseThunkLock( &lockCount );
+        SYSLEVEL_CheckNotLevel( 1 );
+        WaitForSingleObject( pTask->hEvent, INFINITE );
+        RestoreThunkLock( lockCount );
+        if (pTask->nEvents > 0) pTask->nEvents--;
+    }
+    else FIXME("for other task %04x cur=%04x\n",pTask->hSelf,GetCurrentTask());
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           PostEvent  (KERNEL.31)
+ */
+void WINAPI PostEvent16( HTASK16 hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask = TASK_GetPtr( hTask ))) return;
+
+    if (pTask->flags & TDBF_WIN32)
+    {
+        FIXME("called for Win32 thread (%04x)!\n", pTask->teb->teb_sel );
+        return;
+    }
+
+    pTask->nEvents++;
+
+    if (pTask->nEvents == 1) NtSetEvent( pTask->hEvent, NULL );
+}
+
+
+/***********************************************************************
+ *           SetPriority  (KERNEL.32)
+ */
+void WINAPI SetPriority16( HTASK16 hTask, INT16 delta )
+{
+    TDB *pTask;
+    INT16 newpriority;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask = TASK_GetPtr( hTask ))) return;
+    newpriority = pTask->priority + delta;
+    if (newpriority < -32) newpriority = -32;
+    else if (newpriority > 15) newpriority = 15;
+
+    pTask->priority = newpriority + 1;
+    TASK_UnlinkTask( pTask->hSelf );
+    TASK_LinkTask( pTask->hSelf );
+    pTask->priority--;
+}
+
+
+/***********************************************************************
+ *           LockCurrentTask  (KERNEL.33)
+ */
+HTASK16 WINAPI LockCurrentTask16( BOOL16 bLock )
+{
+    if (bLock) hLockedTask = GetCurrentTask();
+    else hLockedTask = 0;
+    return hLockedTask;
+}
+
+
+/***********************************************************************
+ *           IsTaskLocked  (KERNEL.122)
+ */
+HTASK16 WINAPI IsTaskLocked16(void)
+{
+    return hLockedTask;
+}
+
+
+/***********************************************************************
+ *           OldYield  (KERNEL.117)
+ */
+void WINAPI OldYield16(void)
+{
+   DWORD count;
+
+   ReleaseThunkLock(&count);
+   RestoreThunkLock(count);
+}
+
+/***********************************************************************
+ *           WIN32_OldYield  (KERNEL.447)
+ */
+void WINAPI WIN32_OldYield16(void)
+{
+   DWORD count;
+
+   ReleaseThunkLock(&count);
+   RestoreThunkLock(count);
+}
+
+/***********************************************************************
+ *           DirectedYield  (KERNEL.150)
+ */
+void WINAPI DirectedYield16( HTASK16 hTask )
+{
+    OldYield16();
+}
+
+/***********************************************************************
+ *           Yield  (KERNEL.29)
+ */
+void WINAPI Yield16(void)
+{
+    TDB *pCurTask = TASK_GetCurrent();
+
+    if (pCurTask && pCurTask->hQueue)
+    {
+        HMODULE mod = GetModuleHandleA( "user32.dll" );
+        if (mod)
+        {
+            FARPROC proc = GetProcAddress( mod, "UserYield16" );
+            if (proc)
+            {
+                proc();
+                return;
+            }
+        }
+    }
+    OldYield16();
+}
+
+/***********************************************************************
+ *           KERNEL_490  (KERNEL.490)
+ */
+HTASK16 WINAPI KERNEL_490( HTASK16 someTask )
+{
+    if ( !someTask ) return 0;
+
+    FIXME("(%04x): stub\n", someTask );
+    return 0;
+}
+
+/***********************************************************************
+ *           MakeProcInstance  (KERNEL.51)
+ */
+FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
+{
+    BYTE *thunk,*lfunc;
+    SEGPTR thunkaddr;
+    WORD hInstanceSelector;
+
+    hInstanceSelector = GlobalHandleToSel16(hInstance);
+
+    TRACE("(%08lx, %04x);\n", (DWORD)func, hInstance);
+
+    if (!HIWORD(func)) {
+      /* Win95 actually protects via SEH, but this is better for debugging */
+      WARN("Ouch ! Called with invalid func 0x%08lx !\n", (DWORD)func);
+      return (FARPROC16)0;
+    }
+
+    if ( (GlobalHandleToSel16(CURRENT_DS) != hInstanceSelector)
+      && (hInstance != 0)
+      && (hInstance != 0xffff) )
+    {
+	/* calling MPI with a foreign DSEG is invalid ! */
+        WARN("Problem with hInstance? Got %04x, using %04x instead\n",
+                   hInstance,CURRENT_DS);
+    }
+
+    /* Always use the DSEG that MPI was entered with.
+     * We used to set hInstance to GetTaskDS16(), but this should be wrong
+     * as CURRENT_DS provides the DSEG value we need.
+     * ("calling" DS, *not* "task" DS !) */
+    hInstanceSelector = CURRENT_DS;
+    hInstance = GlobalHandle16(hInstanceSelector);
+
+    /* no thunking for DLLs */
+    if (NE_GetPtr(FarGetOwner16(hInstance))->flags & NE_FFLAGS_LIBMODULE)
+	return func;
+
+    thunkaddr = TASK_AllocThunk();
+    if (!thunkaddr) return (FARPROC16)0;
+    thunk = MapSL( thunkaddr );
+    lfunc = MapSL( (SEGPTR)func );
+
+    TRACE("(%08lx,%04x): got thunk %08lx\n",
+          (DWORD)func, hInstance, (DWORD)thunkaddr );
+    if (((lfunc[0]==0x8c) && (lfunc[1]==0xd8)) || /* movw %ds, %ax */
+    	((lfunc[0]==0x1e) && (lfunc[1]==0x58))    /* pushw %ds, popw %ax */
+    ) {
+    	WARN("This was the (in)famous \"thunk useless\" warning. We thought we have to overwrite with nop;nop;, but this isn't true.\n");
+    }
+
+    *thunk++ = 0xb8;    /* movw instance, %ax */
+    *thunk++ = (BYTE)(hInstanceSelector & 0xff);
+    *thunk++ = (BYTE)(hInstanceSelector >> 8);
+    *thunk++ = 0xea;    /* ljmp func */
+    *(DWORD *)thunk = (DWORD)func;
+    return (FARPROC16)thunkaddr;
+    /* CX reg indicates if thunkaddr != NULL, implement if needed */
+}
+
+
+/***********************************************************************
+ *           FreeProcInstance  (KERNEL.52)
+ */
+void WINAPI FreeProcInstance16( FARPROC16 func )
+{
+    TRACE("(%08lx)\n", (DWORD)func );
+    TASK_FreeThunk( (SEGPTR)func );
+}
+
+/**********************************************************************
+ *	    TASK_GetCodeSegment
+ *
+ * Helper function for GetCodeHandle/GetCodeInfo: Retrieve the module
+ * and logical segment number of a given code segment.
+ *
+ * 'proc' either *is* already a pair of module handle and segment number,
+ * in which case there's nothing to do.  Otherwise, it is a pointer to
+ * a function, and we need to retrieve the code segment.  If the pointer
+ * happens to point to a thunk, we'll retrieve info about the code segment
+ * where the function pointed to by the thunk resides, not the thunk itself.
+ *
+ * FIXME: if 'proc' is a SNOOP16 return stub, we should retrieve info about
+ *        the function the snoop code will return to ...
+ *
+ */
+static BOOL TASK_GetCodeSegment( FARPROC16 proc, NE_MODULE **ppModule,
+                                 SEGTABLEENTRY **ppSeg, int *pSegNr )
+{
+    NE_MODULE *pModule = NULL;
+    SEGTABLEENTRY *pSeg = NULL;
+    int segNr=0;
+
+    /* Try pair of module handle / segment number */
+    pModule = (NE_MODULE *) GlobalLock16( HIWORD( proc ) );
+    if ( pModule && pModule->magic == IMAGE_OS2_SIGNATURE )
+    {
+        segNr = LOWORD( proc );
+        if ( segNr && segNr <= pModule->seg_count )
+            pSeg = NE_SEG_TABLE( pModule ) + segNr-1;
+    }
+
+    /* Try thunk or function */
+    else
+    {
+        BYTE *thunk = MapSL( (SEGPTR)proc );
+        WORD selector;
+
+        if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
+            selector = thunk[6] + (thunk[7] << 8);
+        else
+            selector = HIWORD( proc );
+
+        pModule = NE_GetPtr( GlobalHandle16( selector ) );
+        pSeg = pModule? NE_SEG_TABLE( pModule ) : NULL;
+
+        if ( pModule )
+            for ( segNr = 1; segNr <= pModule->seg_count; segNr++, pSeg++ )
+                if ( GlobalHandleToSel16(pSeg->hSeg) == selector )
+                    break;
+
+        if ( pModule && segNr > pModule->seg_count )
+            pSeg = NULL;
+    }
+
+    /* Abort if segment not found */
+
+    if ( !pModule || !pSeg )
+        return FALSE;
+
+    /* Return segment data */
+
+    if ( ppModule ) *ppModule = pModule;
+    if ( ppSeg    ) *ppSeg    = pSeg;
+    if ( pSegNr   ) *pSegNr   = segNr;
+
+    return TRUE;
+}
+
+/**********************************************************************
+ *	    GetCodeHandle    (KERNEL.93)
+ */
+HANDLE16 WINAPI GetCodeHandle16( FARPROC16 proc )
+{
+    SEGTABLEENTRY *pSeg;
+
+    if ( !TASK_GetCodeSegment( proc, NULL, &pSeg, NULL ) )
+        return (HANDLE16)0;
+
+    return pSeg->hSeg;
+}
+
+/**********************************************************************
+ *	    GetCodeInfo    (KERNEL.104)
+ */
+BOOL16 WINAPI GetCodeInfo16( FARPROC16 proc, SEGINFO *segInfo )
+{
+    NE_MODULE *pModule;
+    SEGTABLEENTRY *pSeg;
+    int segNr;
+
+    if ( !TASK_GetCodeSegment( proc, &pModule, &pSeg, &segNr ) )
+        return FALSE;
+
+    /* Fill in segment information */
+
+    segInfo->offSegment = pSeg->filepos;
+    segInfo->cbSegment  = pSeg->size;
+    segInfo->flags      = pSeg->flags;
+    segInfo->cbAlloc    = pSeg->minsize;
+    segInfo->h          = pSeg->hSeg;
+    segInfo->alignShift = pModule->alignment;
+
+    if ( segNr == pModule->dgroup )
+        segInfo->cbAlloc += pModule->heap_size + pModule->stack_size;
+
+    /* Return module handle in %es */
+
+    CURRENT_STACK16->es = GlobalHandleToSel16( pModule->self );
+
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          DefineHandleTable    (KERNEL.94)
+ */
+BOOL16 WINAPI DefineHandleTable16( WORD wOffset )
+{
+    FIXME("(%04x): stub ?\n", wOffset);
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           SetTaskQueue  (KERNEL.34)
+ */
+HQUEUE16 WINAPI SetTaskQueue16( HTASK16 hTask, HQUEUE16 hQueue )
+{
+    HQUEUE16 hPrev;
+    TDB *pTask;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
+
+    hPrev = pTask->hQueue;
+    pTask->hQueue = hQueue;
+
+    return hPrev;
+}
+
+
+/***********************************************************************
+ *           GetTaskQueue  (KERNEL.35)
+ */
+HQUEUE16 WINAPI GetTaskQueue16( HTASK16 hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
+    return pTask->hQueue;
+}
+
+/***********************************************************************
+ *           SetThreadQueue  (KERNEL.463)
+ */
+HQUEUE16 WINAPI SetThreadQueue16( DWORD thread, HQUEUE16 hQueue )
+{
+    HQUEUE16 oldQueue = NtCurrentTeb()->queue;
+
+    if (thread && thread != GetCurrentThreadId())
+    {
+        FIXME( "not supported on other thread %04lx\n", thread );
+        return 0;
+    }
+    NtCurrentTeb()->queue = hQueue;
+    if ( GetTaskQueue16( NtCurrentTeb()->htask16 ) == oldQueue )
+        SetTaskQueue16( NtCurrentTeb()->htask16, hQueue );
+    return oldQueue;
+}
+
+/***********************************************************************
+ *           GetThreadQueue  (KERNEL.464)
+ */
+HQUEUE16 WINAPI GetThreadQueue16( DWORD thread )
+{
+    if (thread && thread != GetCurrentThreadId())
+    {
+        FIXME( "not supported on other thread %04lx\n", thread );
+        return 0;
+    }
+    return NtCurrentTeb()->queue;
+}
+
+/***********************************************************************
+ *           SetFastQueue  (KERNEL.624)
+ */
+VOID WINAPI SetFastQueue16( DWORD thread, HQUEUE16 hQueue )
+{
+    if (!thread || thread == GetCurrentThreadId())
+        NtCurrentTeb()->queue = hQueue;
+    else
+        FIXME( "not supported on other thread %04lx\n", thread );
+}
+
+/***********************************************************************
+ *           GetFastQueue  (KERNEL.625)
+ */
+HQUEUE16 WINAPI GetFastQueue16( void )
+{
+    HQUEUE16 ret = NtCurrentTeb()->queue;
+
+    if (!ret) FIXME("(): should initialize thread-local queue, expect failure!\n" );
+    return ret;
+}
+
+/***********************************************************************
+ *           SwitchStackTo   (KERNEL.108)
+ */
+void WINAPI SwitchStackTo16( WORD seg, WORD ptr, WORD top )
+{
+    TDB *pTask;
+    STACK16FRAME *oldFrame, *newFrame;
+    INSTANCEDATA *pData;
+    UINT16 copySize;
+
+    if (!(pTask = TASK_GetCurrent())) return;
+    if (!(pData = (INSTANCEDATA *)GlobalLock16( seg ))) return;
+    TRACE("old=%04x:%04x new=%04x:%04x\n",
+          SELECTOROF( pTask->teb->cur_stack ),
+          OFFSETOF( pTask->teb->cur_stack ), seg, ptr );
+
+    /* Save the old stack */
+
+    oldFrame = THREAD_STACK16( pTask->teb );
+    /* pop frame + args and push bp */
+    pData->old_ss_sp   = pTask->teb->cur_stack + sizeof(STACK16FRAME)
+                           + 2 * sizeof(WORD);
+    *(WORD *)MapSL(pData->old_ss_sp) = oldFrame->bp;
+    pData->stacktop    = top;
+    pData->stackmin    = ptr;
+    pData->stackbottom = ptr;
+
+    /* Switch to the new stack */
+
+    /* Note: we need to take the 3 arguments into account; otherwise,
+     * the stack will underflow upon return from this function.
+     */
+    copySize = oldFrame->bp - OFFSETOF(pData->old_ss_sp);
+    copySize += 3 * sizeof(WORD) + sizeof(STACK16FRAME);
+    pTask->teb->cur_stack = MAKESEGPTR( seg, ptr - copySize );
+    newFrame = THREAD_STACK16( pTask->teb );
+
+    /* Copy the stack frame and the local variables to the new stack */
+
+    memmove( newFrame, oldFrame, copySize );
+    newFrame->bp = ptr;
+    *(WORD *)MapSL( MAKESEGPTR( seg, ptr ) ) = 0;  /* clear previous bp */
+}
+
+
+/***********************************************************************
+ *           SwitchStackBack   (KERNEL.109)
+ */
+void WINAPI SwitchStackBack16( CONTEXT86 *context )
+{
+    STACK16FRAME *oldFrame, *newFrame;
+    INSTANCEDATA *pData;
+
+    if (!(pData = (INSTANCEDATA *)GlobalLock16(SELECTOROF(NtCurrentTeb()->cur_stack))))
+        return;
+    if (!pData->old_ss_sp)
+    {
+        WARN("No previous SwitchStackTo\n" );
+        return;
+    }
+    TRACE("restoring stack %04x:%04x\n",
+          SELECTOROF(pData->old_ss_sp), OFFSETOF(pData->old_ss_sp) );
+
+    oldFrame = CURRENT_STACK16;
+
+    /* Pop bp from the previous stack */
+
+    context->Ebp = (context->Ebp & ~0xffff) | *(WORD *)MapSL(pData->old_ss_sp);
+    pData->old_ss_sp += sizeof(WORD);
+
+    /* Switch back to the old stack */
+
+    NtCurrentTeb()->cur_stack = pData->old_ss_sp - sizeof(STACK16FRAME);
+    context->SegSs = SELECTOROF(pData->old_ss_sp);
+    context->Esp   = OFFSETOF(pData->old_ss_sp) - sizeof(DWORD); /*ret addr*/
+    pData->old_ss_sp = 0;
+
+    /* Build a stack frame for the return */
+
+    newFrame = CURRENT_STACK16;
+    newFrame->frame32     = oldFrame->frame32;
+    newFrame->module_cs   = oldFrame->module_cs;
+    newFrame->callfrom_ip = oldFrame->callfrom_ip;
+    newFrame->entry_ip    = oldFrame->entry_ip;
+}
+
+
+/***********************************************************************
+ *           GetTaskQueueDS  (KERNEL.118)
+ */
+void WINAPI GetTaskQueueDS16(void)
+{
+    CURRENT_STACK16->ds = GlobalHandleToSel16( GetTaskQueue16(0) );
+}
+
+
+/***********************************************************************
+ *           GetTaskQueueES  (KERNEL.119)
+ */
+void WINAPI GetTaskQueueES16(void)
+{
+    CURRENT_STACK16->es = GlobalHandleToSel16( GetTaskQueue16(0) );
+}
+
+
+/***********************************************************************
+ *           GetCurrentTask   (KERNEL32.@)
+ */
+HTASK16 WINAPI GetCurrentTask(void)
+{
+    return NtCurrentTeb()->htask16;
+}
+
+/***********************************************************************
+ *           GetCurrentTask   (KERNEL.36)
+ */
+DWORD WINAPI WIN16_GetCurrentTask(void)
+{
+    /* This is the version used by relay code; the first task is */
+    /* returned in the high word of the result */
+    return MAKELONG( GetCurrentTask(), hFirstTask );
+}
+
+
+/***********************************************************************
+ *           GetCurrentPDB   (KERNEL.37)
+ *
+ * UNDOC: returns PSP of KERNEL in high word
+ */
+DWORD WINAPI GetCurrentPDB16(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    return MAKELONG(pTask->hPDB, 0); /* FIXME */
+}
+
+
+/***********************************************************************
+ *           GetCurPID   (KERNEL.157)
+ */
+DWORD WINAPI GetCurPID16( DWORD unused )
+{
+    return 0;
+}
+
+
+/***********************************************************************
+ *           GetInstanceData   (KERNEL.54)
+ */
+INT16 WINAPI GetInstanceData16( HINSTANCE16 instance, WORD buffer, INT16 len )
+{
+    char *ptr = (char *)GlobalLock16( instance );
+    if (!ptr || !len) return 0;
+    if ((int)buffer + len >= 0x10000) len = 0x10000 - buffer;
+    memcpy( (char *)GlobalLock16(CURRENT_DS) + buffer, ptr + buffer, len );
+    return len;
+}
+
+
+/***********************************************************************
+ *           GetExeVersion   (KERNEL.105)
+ */
+WORD WINAPI GetExeVersion16(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    return pTask->version;
+}
+
+
+/***********************************************************************
+ *           SetErrorMode   (KERNEL.107)
+ */
+UINT16 WINAPI SetErrorMode16( UINT16 mode )
+{
+    TDB *pTask;
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    pTask->error_mode = mode;
+    return SetErrorMode( mode );
+}
+
+
+/***********************************************************************
+ *           GetNumTasks   (KERNEL.152)
+ */
+UINT16 WINAPI GetNumTasks16(void)
+{
+    return nTaskCount;
+}
+
+
+/***********************************************************************
+ *           GetTaskDS   (KERNEL.155)
+ *
+ * Note: this function apparently returns a DWORD with LOWORD == HIWORD.
+ * I don't think we need to bother with this.
+ */
+HINSTANCE16 WINAPI GetTaskDS16(void)
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    return GlobalHandleToSel16(pTask->hInstance);
+}
+
+/***********************************************************************
+ *           GetDummyModuleHandleDS   (KERNEL.602)
+ */
+WORD WINAPI GetDummyModuleHandleDS16(void)
+{
+    TDB *pTask;
+    WORD selector;
+
+    if (!(pTask = TASK_GetCurrent())) return 0;
+    if (!(pTask->flags & TDBF_WIN32)) return 0;
+    selector = GlobalHandleToSel16( pTask->hModule );
+    CURRENT_DS = selector;
+    return selector;
+}
+
+/***********************************************************************
+ *           IsTask   (KERNEL.320)
+ */
+BOOL16 WINAPI IsTask16( HTASK16 hTask )
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetPtr( hTask ))) return FALSE;
+    if (GlobalSize16( hTask ) < sizeof(TDB)) return FALSE;
+    return (pTask->magic == TDB_MAGIC);
+}
+
+
+/***********************************************************************
+ *           IsWinOldApTask   (KERNEL.158)
+ */
+BOOL16 WINAPI IsWinOldApTask16( HTASK16 hTask )
+{
+    /* should return bit 0 of byte 0x48 in PSP */
+    return FALSE;
+}
+
+/***********************************************************************
+ *           SetTaskSignalProc   (KERNEL.38)
+ */
+FARPROC16 WINAPI SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
+{
+    TDB *pTask;
+    FARPROC16 oldProc;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask = TASK_GetPtr( hTask ))) return NULL;
+    oldProc = pTask->userhandler;
+    pTask->userhandler = proc;
+    return oldProc;
+}
+
+/***********************************************************************
+ *           SetSigHandler   (KERNEL.140)
+ */
+WORD WINAPI SetSigHandler16( FARPROC16 newhandler, FARPROC16* oldhandler,
+                           UINT16 *oldmode, UINT16 newmode, UINT16 flag )
+{
+    FIXME("(%p,%p,%p,%d,%d), unimplemented.\n",
+	  newhandler,oldhandler,oldmode,newmode,flag );
+
+    if (flag != 1) return 0;
+    if (!newmode) newhandler = NULL;  /* Default handler */
+    if (newmode != 4)
+    {
+        TDB *pTask;
+
+        if (!(pTask = TASK_GetCurrent())) return 0;
+        if (oldmode) *oldmode = pTask->signal_flags;
+        pTask->signal_flags = newmode;
+        if (oldhandler) *oldhandler = pTask->sighandler;
+        pTask->sighandler = newhandler;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           GlobalNotify   (KERNEL.154)
+ *
+ * Note that GlobalNotify does _not_ return the old NotifyProc
+ * -- contrary to LocalNotify !!
+ */
+VOID WINAPI GlobalNotify16( FARPROC16 proc )
+{
+    TDB *pTask;
+
+    if (!(pTask = TASK_GetCurrent())) return;
+    pTask->discardhandler = proc;
+}
+
+
+/***********************************************************************
+ *           GetExePtrHelper
+ */
+static inline HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask )
+{
+    char *ptr;
+    HANDLE16 owner;
+
+      /* Check for module handle */
+
+    if (!(ptr = GlobalLock16( handle ))) return 0;
+    if (((NE_MODULE *)ptr)->magic == IMAGE_OS2_SIGNATURE) return handle;
+
+      /* Search for this handle inside all tasks */
+
+    *hTask = hFirstTask;
+    while (*hTask)
+    {
+        TDB *pTask = TASK_GetPtr( *hTask );
+        if ((*hTask == handle) ||
+            (pTask->hInstance == handle) ||
+            (pTask->hQueue == handle) ||
+            (pTask->hPDB == handle)) return pTask->hModule;
+        *hTask = pTask->hNext;
+    }
+
+      /* Check the owner for module handle */
+
+    owner = FarGetOwner16( handle );
+    if (!(ptr = GlobalLock16( owner ))) return 0;
+    if (((NE_MODULE *)ptr)->magic == IMAGE_OS2_SIGNATURE) return owner;
+
+      /* Search for the owner inside all tasks */
+
+    *hTask = hFirstTask;
+    while (*hTask)
+    {
+        TDB *pTask = TASK_GetPtr( *hTask );
+        if ((*hTask == owner) ||
+            (pTask->hInstance == owner) ||
+            (pTask->hQueue == owner) ||
+            (pTask->hPDB == owner)) return pTask->hModule;
+        *hTask = pTask->hNext;
+    }
+
+    return 0;
+}
+
+/***********************************************************************
+ *           GetExePtr   (KERNEL.133)
+ */
+HMODULE16 WINAPI WIN16_GetExePtr( HANDLE16 handle )
+{
+    HTASK16 hTask = 0;
+    HMODULE16 hModule = GetExePtrHelper( handle, &hTask );
+    STACK16FRAME *frame = CURRENT_STACK16;
+    frame->ecx = hModule;
+    if (hTask) frame->es = hTask;
+    return hModule;
+}
+
+
+/***********************************************************************
+ *           K228   (KERNEL.228)
+ */
+HMODULE16 WINAPI GetExePtr( HANDLE16 handle )
+{
+    HTASK16 hTask = 0;
+    return GetExePtrHelper( handle, &hTask );
+}
+
+
+/***********************************************************************
+ *           TaskFirst   (TOOLHELP.63)
+ */
+BOOL16 WINAPI TaskFirst16( TASKENTRY *lpte )
+{
+    lpte->hNext = hFirstTask;
+    return TaskNext16( lpte );
+}
+
+
+/***********************************************************************
+ *           TaskNext   (TOOLHELP.64)
+ */
+BOOL16 WINAPI TaskNext16( TASKENTRY *lpte )
+{
+    TDB *pTask;
+    INSTANCEDATA *pInstData;
+
+    TRACE_(toolhelp)("(%p): task=%04x\n", lpte, lpte->hNext );
+    if (!lpte->hNext) return FALSE;
+
+    /* make sure that task and hInstance are valid (skip initial Wine task !) */
+    while (1) {
+        pTask = TASK_GetPtr( lpte->hNext );
+        if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
+        if (pTask->hInstance)
+            break;
+        lpte->hNext = pTask->hNext;
+    }
+    pInstData = MapSL( MAKESEGPTR( GlobalHandleToSel16(pTask->hInstance), 0 ) );
+    lpte->hTask         = lpte->hNext;
+    lpte->hTaskParent   = pTask->hParent;
+    lpte->hInst         = pTask->hInstance;
+    lpte->hModule       = pTask->hModule;
+    lpte->wSS           = SELECTOROF( pTask->teb->cur_stack );
+    lpte->wSP           = OFFSETOF( pTask->teb->cur_stack );
+    lpte->wStackTop     = pInstData->stacktop;
+    lpte->wStackMinimum = pInstData->stackmin;
+    lpte->wStackBottom  = pInstData->stackbottom;
+    lpte->wcEvents      = pTask->nEvents;
+    lpte->hQueue        = pTask->hQueue;
+    lstrcpynA( lpte->szModule, pTask->module_name, sizeof(lpte->szModule) );
+    lpte->wPSPOffset    = 0x100;  /*??*/
+    lpte->hNext         = pTask->hNext;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           TaskFindHandle   (TOOLHELP.65)
+ */
+BOOL16 WINAPI TaskFindHandle16( TASKENTRY *lpte, HTASK16 hTask )
+{
+    lpte->hNext = hTask;
+    return TaskNext16( lpte );
+}
+
+
+typedef INT (WINAPI *MessageBoxA_funcptr)(HWND hWnd, LPCSTR text, LPCSTR title, UINT type);
+
+/**************************************************************************
+ *           FatalAppExit   (KERNEL.137)
+ */
+void WINAPI FatalAppExit16( UINT16 action, LPCSTR str )
+{
+    TDB *pTask = TASK_GetCurrent();
+
+    if (!pTask || !(pTask->error_mode & SEM_NOGPFAULTERRORBOX))
+    {
+        HMODULE mod = GetModuleHandleA( "user32.dll" );
+        if (mod)
+        {
+            MessageBoxA_funcptr pMessageBoxA = (MessageBoxA_funcptr)GetProcAddress( mod, "MessageBoxA" );
+            if (pMessageBoxA)
+            {
+                pMessageBoxA( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
+                goto done;
+            }
+        }
+        ERR( "%s\n", debugstr_a(str) );
+    }
+ done:
+    ExitThread(0xff);
+}
+
+
+/***********************************************************************
+ *           TerminateApp   (TOOLHELP.77)
+ *
+ * See "Undocumented Windows".
+ */
+void WINAPI TerminateApp16(HTASK16 hTask, WORD wFlags)
+{
+    if (hTask && hTask != GetCurrentTask())
+    {
+        FIXME("cannot terminate task %x\n", hTask);
+        return;
+    }
+
+    if (wFlags & NO_UAE_BOX)
+    {
+        UINT16 old_mode;
+        old_mode = SetErrorMode16(0);
+        SetErrorMode16(old_mode|SEM_NOGPFAULTERRORBOX);
+    }
+    FatalAppExit16( 0, NULL );
+
+    /* hmm, we're still alive ?? */
+
+    /* check undocumented flag */
+    if (!(wFlags & 0x8000))
+        TASK_CallTaskSignalProc( USIG16_TERMINATION, hTask );
+
+    /* UndocWin says to call int 0x21/0x4c exit=0xff here,
+       but let's just call ExitThread */
+    ExitThread(0xff);
+}
+
+
+/***********************************************************************
+ *           GetAppCompatFlags   (KERNEL.354)
+ */
+DWORD WINAPI GetAppCompatFlags16( HTASK16 hTask )
+{
+    TDB *pTask;
+
+    if (!hTask) hTask = GetCurrentTask();
+    if (!(pTask=TASK_GetPtr( hTask ))) return 0;
+    if (GlobalSize16(hTask) < sizeof(TDB)) return 0;
+    return pTask->compat_flags;
+}
diff --git a/dlls/kernel/thunk.c b/dlls/kernel/thunk.c
index 7dcb8f8..019dc9f 100644
--- a/dlls/kernel/thunk.c
+++ b/dlls/kernel/thunk.c
@@ -1589,7 +1589,7 @@
                                           THUNKLET_TYPE_LS );
     if (!thunk)
     {
-        TDB *pTask = TASK_GetPtr( owner );
+        TDB *pTask = GlobalLock16( owner );
 
         if (!ThunkletHeap) THUNK_Init();
         if ( !(thunk = HeapAlloc( ThunkletHeap, 0, sizeof(THUNKLET) )) )
@@ -1623,7 +1623,7 @@
                                           THUNKLET_TYPE_SL );
     if (!thunk)
     {
-        TDB *pTask = TASK_GetPtr( owner );
+        TDB *pTask = GlobalLock16( owner );
 
         if (!ThunkletHeap) THUNK_Init();
         if ( !(thunk = HeapAlloc( ThunkletHeap, 0, sizeof(THUNKLET) )) )
diff --git a/dlls/kernel/wowthunk.c b/dlls/kernel/wowthunk.c
index 8207386..30029b1 100644
--- a/dlls/kernel/wowthunk.c
+++ b/dlls/kernel/wowthunk.c
@@ -235,7 +235,7 @@
         return (HANDLE)(ULONG_PTR)handle;
 
     case WOW_TYPE_HTASK:
-        return (HANDLE)TASK_GetPtr(handle)->teb->tid;
+        return (HANDLE)((TDB *)GlobalLock16(handle))->teb->tid;
 
     case WOW_TYPE_FULLHWND:
         FIXME( "conversion of full window handles not supported yet\n" );
@@ -276,7 +276,7 @@
         return LOWORD(handle);
 
     case WOW_TYPE_HTASK:
-        return THREAD_IdToTEB((DWORD)handle)->htask16;
+        return TASK_GetTaskFromThread( (DWORD)handle );
 
     default:
         ERR( "handle %p of unknown type %d\n", handle, type );
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 7890956..fe92065 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -21,7 +21,6 @@
 	$(TOPOBJDIR)/loader/pe_image.c \
 	$(TOPOBJDIR)/loader/task.c \
 	$(TOPOBJDIR)/loader/ne/module.c \
-	$(TOPOBJDIR)/loader/ne/segment.c \
 	$(TOPOBJDIR)/memory/codepage.c \
 	$(TOPOBJDIR)/memory/environ.c \
 	$(TOPOBJDIR)/memory/global.c \
@@ -89,7 +88,7 @@
 	relay16.s \
 	relay32.s
 
-EXTRA_OBJS = $(ASM_SRCS:.s=.o) $(MODULE).glue.o
+EXTRA_OBJS = $(ASM_SRCS:.s=.o)
 
 SUBDIRS = tests
 
diff --git a/files/drive.c b/files/drive.c
index bf29d75..4cdf385 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -428,7 +428,7 @@
  */
 int DRIVE_GetCurrentDrive(void)
 {
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
     if (pTask && (pTask->curdrive & 0x80)) return pTask->curdrive & ~0x80;
     return DRIVE_CurDrive;
 }
@@ -439,7 +439,7 @@
  */
 int DRIVE_SetCurrentDrive( int drive )
 {
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
     if (!DRIVE_IsValid( drive ))
     {
         SetLastError( ERROR_INVALID_DRIVE );
@@ -619,7 +619,7 @@
  */
 LPCWSTR DRIVE_GetDosCwd( int drive )
 {
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
     if (!DRIVE_IsValid( drive )) return NULL;
 
     /* Check if we need to change the directory to the new task. */
@@ -643,7 +643,7 @@
  */
 const char * DRIVE_GetUnixCwd( int drive )
 {
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
     if (!DRIVE_IsValid( drive )) return NULL;
 
     /* Check if we need to change the directory to the new task. */
@@ -1234,7 +1234,7 @@
     WCHAR buffer[MAX_PATHNAME_LEN];
     LPSTR unix_cwd;
     BY_HANDLE_FILE_INFORMATION info;
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
 
     buffer[0] = 'A' + drive;
     buffer[1] = ':';
diff --git a/include/task.h b/include/task.h
index a4fc200..b4cdf2d 100644
--- a/include/task.h
+++ b/include/task.h
@@ -163,10 +163,8 @@
 extern HTASK16 TASK_SpawnTask( struct _NE_MODULE *pModule, WORD cmdShow,
                                LPCSTR cmdline, BYTE len, HANDLE *hThread );
 extern void TASK_ExitTask(void);
-extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
-extern TDB *TASK_GetPtr( HTASK16 hTask );
+extern HTASK16 TASK_GetTaskFromThread( DWORD thread );
 extern TDB *TASK_GetCurrent(void);
 extern void TASK_InstallTHHook( THHOOK *pNewThook );
-extern void TASK_CallTaskSignalProc( UINT16 uCode, HANDLE16 hTaskOrModule );
 
 #endif /* __WINE_TASK_H */
diff --git a/include/thread.h b/include/thread.h
index 79665cb..bd9a9cc 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -149,7 +149,6 @@
 /* scheduler/thread.c */
 extern void THREAD_Init(void);
 extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
-extern TEB *THREAD_IdToTEB( DWORD id );
 
 /* scheduler/sysdeps.c */
 extern int SYSDEPS_SpawnThread( void (*func)(TEB *), TEB *teb );
diff --git a/loader/module.c b/loader/module.c
index f75ce9f..e18db67 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -782,27 +782,6 @@
 }
 
 /***********************************************************************
- *           PrivateLoadLibrary       (KERNEL32.@)
- *
- * FIXME: rough guesswork, don't know what "Private" means
- */
-HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
-{
-    return LoadLibrary16(libname);
-}
-
-/***********************************************************************
- *           PrivateFreeLibrary       (KERNEL32.@)
- *
- * FIXME: rough guesswork, don't know what "Private" means
- */
-void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
-{
-    FreeLibrary16(handle);
-}
-
-
-/***********************************************************************
  *           GetProcAddress   		(KERNEL32.@)
  */
 FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function )
diff --git a/loader/ne/module.c b/loader/ne/module.c
index 0e65b94..4713bf4 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -59,41 +59,8 @@
 } GPHANDLERDEF;
 #include "poppack.h"
 
-/*
- * Segment table entry
- */
-struct ne_segment_table_entry_s
-{
-    WORD seg_data_offset;   /* Sector offset of segment data	*/
-    WORD seg_data_length;   /* Length of segment data		*/
-    WORD seg_flags;         /* Flags associated with this segment	*/
-    WORD min_alloc;         /* Minimum allocation size for this	*/
-};
-
 #define hFirstModule (pThhook->hExeHead)
 
-static NE_MODULE *pCachedModule = 0;  /* Module cached by NE_OpenFile */
-
-static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
-static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
-
-static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
-
-static HMODULE16 NE_GetModuleByFilename( LPCSTR name );
-
-/* ### start build ### */
-extern WORD CALLBACK NE_CallTo16_word_w(FARPROC16,WORD);
-/* ### stop build ### */
-
-
-static WINE_EXCEPTION_FILTER(page_fault)
-{
-    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
-        GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
-        return EXCEPTION_EXECUTE_HANDLER;
-    return EXCEPTION_CONTINUE_SEARCH;
-}
-
 
 /***********************************************************************
  *           NE_GetPtr
@@ -104,160 +71,6 @@
 }
 
 
-/***********************************************************************
- *           NE_DumpModule
- */
-void NE_DumpModule( HMODULE16 hModule )
-{
-    int i, ordinal;
-    SEGTABLEENTRY *pSeg;
-    BYTE *pstr;
-    WORD *pword;
-    NE_MODULE *pModule;
-    ET_BUNDLE *bundle;
-    ET_ENTRY *entry;
-
-    if (!(pModule = NE_GetPtr( hModule )))
-    {
-        MESSAGE( "**** %04x is not a module handle\n", hModule );
-        return;
-    }
-
-      /* Dump the module info */
-    DPRINTF( "---\n" );
-    DPRINTF( "Module %04x:\n", hModule );
-    DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
-	  pModule->count, pModule->flags,
-	  pModule->heap_size, pModule->stack_size );
-    DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
-	  pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
-	  pModule->seg_count, pModule->modref_count );
-    DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
-	  pModule->os_flags, pModule->min_swap_area,
-	  pModule->expected_version );
-    if (pModule->flags & NE_FFLAGS_WIN32)
-        DPRINTF( "PE module=%p\n", pModule->module32 );
-
-      /* Dump the file info */
-    DPRINTF( "---\n" );
-    DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
-
-      /* Dump the segment table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Segment table:\n" );
-    pSeg = NE_SEG_TABLE( pModule );
-    for (i = 0; i < pModule->seg_count; i++, pSeg++)
-        DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
-	      i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
-	      pSeg->minsize, pSeg->hSeg );
-
-      /* Dump the resource table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Resource table:\n" );
-    if (pModule->res_table)
-    {
-        pword = (WORD *)((BYTE *)pModule + pModule->res_table);
-        DPRINTF( "Alignment: %d\n", *pword++ );
-        while (*pword)
-        {
-            NE_TYPEINFO *ptr = (NE_TYPEINFO *)pword;
-            NE_NAMEINFO *pname = (NE_NAMEINFO *)(ptr + 1);
-            DPRINTF( "id=%04x count=%d\n", ptr->type_id, ptr->count );
-            for (i = 0; i < ptr->count; i++, pname++)
-                DPRINTF( "offset=%d len=%d id=%04x\n",
-		      pname->offset, pname->length, pname->id );
-            pword = (WORD *)pname;
-        }
-    }
-    else DPRINTF( "None\n" );
-
-      /* Dump the resident name table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Resident-name table:\n" );
-    pstr = (char *)pModule + pModule->name_table;
-    while (*pstr)
-    {
-        DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
-	      *(WORD *)(pstr + *pstr + 1) );
-        pstr += *pstr + 1 + sizeof(WORD);
-    }
-
-      /* Dump the module reference table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Module ref table:\n" );
-    if (pModule->modref_table)
-    {
-        pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
-        for (i = 0; i < pModule->modref_count; i++, pword++)
-        {
-            char name[10];
-            GetModuleName16( *pword, name, sizeof(name) );
-	    DPRINTF( "%d: %04x -> '%s'\n", i, *pword, name );
-        }
-    }
-    else DPRINTF( "None\n" );
-
-      /* Dump the entry table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Entry table:\n" );
-    bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
-    do {
-	entry = (ET_ENTRY *)((BYTE *)bundle+6);
-	DPRINTF( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
-	ordinal = bundle->first;
-	while (ordinal < bundle->last)
-        {
-	    if (entry->type == 0xff)
-		DPRINTF("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
-	    else
-		DPRINTF("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
-	    entry++;
-    }
-    } while ( (bundle->next)
-	   && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
-
-    /* Dump the non-resident names table */
-    DPRINTF( "---\n" );
-    DPRINTF( "Non-resident names table:\n" );
-    if (pModule->nrname_handle)
-    {
-        pstr = (char *)GlobalLock16( pModule->nrname_handle );
-        while (*pstr)
-        {
-            DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
-                   *(WORD *)(pstr + *pstr + 1) );
-            pstr += *pstr + 1 + sizeof(WORD);
-        }
-    }
-    DPRINTF( "\n" );
-}
-
-
-/***********************************************************************
- *           NE_WalkModules
- *
- * Walk the module list and print the modules.
- */
-void NE_WalkModules(void)
-{
-    HMODULE16 hModule = hFirstModule;
-    MESSAGE( "Module Flags Name\n" );
-    while (hModule)
-    {
-        NE_MODULE *pModule = NE_GetPtr( hModule );
-        if (!pModule)
-        {
-            MESSAGE( "Bad module %04x in list\n", hModule );
-            return;
-        }
-        MESSAGE( " %04x  %04x  %.*s\n", hModule, pModule->flags,
-                 *((char *)pModule + pModule->name_table),
-                 (char *)pModule + pModule->name_table + 1 );
-        hModule = pModule->next;
-    }
-}
-
-
 /**********************************************************************
  *           NE_RegisterModule
  */
@@ -358,18 +171,6 @@
 
 
 /***********************************************************************
- *		EntryAddrProc (KERNEL.667) Wine-specific export
- *
- * Return the entry point for a given ordinal.
- */
-FARPROC16 WINAPI EntryAddrProc16( HMODULE16 hModule, WORD ordinal )
-{
-    FARPROC16 ret = NE_GetEntryPointEx( hModule, ordinal, TRUE );
-    CURRENT_STACK16->ecx = hModule; /* FIXME: might be incorrect value */
-    return ret;
-}
-
-/***********************************************************************
  *		NE_GetEntryPoint
  */
 FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
@@ -417,1000 +218,6 @@
 }
 
 
-/***********************************************************************
- *           NE_SetEntryPoint
- *
- * Change the value of an entry point. Use with caution!
- * It can only change the offset value, not the selector.
- */
-BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
-{
-    NE_MODULE *pModule;
-    ET_ENTRY *entry;
-    ET_BUNDLE *bundle;
-    int i;
-
-    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
-    assert( !(pModule->flags & NE_FFLAGS_WIN32) );
-
-    bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
-    while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
-        {
-	bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
-	if (!(bundle->next))
-	    return 0;
-    }
-
-    entry = (ET_ENTRY *)((BYTE *)bundle+6);
-    for (i=0; i < (ordinal - bundle->first - 1); i++)
-	entry++;
-
-    memcpy( &entry->offs, &offset, sizeof(WORD) );
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           NE_OpenFile
- */
-HANDLE NE_OpenFile( NE_MODULE *pModule )
-{
-    HANDLE handle;
-    char *name;
-
-    TRACE("(%p)\n", pModule );
-    /* mjm - removed module caching because it keeps open file handles
-             thus preventing CDROMs from being ejected */
-    name = NE_MODULE_NAME( pModule );
-    if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
-                                   NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
-        MESSAGE( "Can't open file '%s' for module %04x\n", name, pModule->self );
-    TRACE("opened '%s' -> %p\n", name, handle);
-    return handle;
-}
-
-
-/* wrapper for SetFilePointer and ReadFile */
-static BOOL read_data( HANDLE handle, LONG offset, void *buffer, DWORD size )
-{
-    DWORD result;
-
-    if (SetFilePointer( handle, offset, NULL, SEEK_SET ) == INVALID_SET_FILE_POINTER) return FALSE;
-    if (!ReadFile( handle, buffer, size, &result, NULL )) return FALSE;
-    return (result == size);
-}
-
-/***********************************************************************
- *           NE_LoadExeHeader
- */
-static HMODULE16 NE_LoadExeHeader( HANDLE handle, LPCSTR path )
-{
-    IMAGE_DOS_HEADER mz_header;
-    IMAGE_OS2_HEADER ne_header;
-    int size;
-    HMODULE16 hModule;
-    NE_MODULE *pModule;
-    BYTE *pData, *pTempEntryTable;
-    char *buffer, *fastload = NULL;
-    int fastload_offset = 0, fastload_length = 0;
-    ET_ENTRY *entry;
-    ET_BUNDLE *bundle, *oldbundle;
-    OFSTRUCT *ofs;
-
-  /* Read a block from either the file or the fast-load area. */
-#define READ(offset,size,buffer) \
-       ((fastload && ((offset) >= fastload_offset) && \
-         ((offset)+(size) <= fastload_offset+fastload_length)) ? \
-        (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
-         read_data( handle, (offset), (buffer), (size)))
-
-    if (!read_data( handle, 0, &mz_header, sizeof(mz_header)) ||
-        (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
-        return (HMODULE16)11;  /* invalid exe */
-
-    if (!read_data( handle, mz_header.e_lfanew, &ne_header, sizeof(ne_header) ))
-        return (HMODULE16)11;  /* invalid exe */
-
-    if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
-    if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
-        MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
-        return (HMODULE16)12;
-    }
-    if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
-
-    /* We now have a valid NE header */
-
-    size = sizeof(NE_MODULE) +
-             /* segment table */
-           ne_header.ne_cseg * sizeof(SEGTABLEENTRY) +
-             /* resource table */
-           ne_header.ne_restab - ne_header.ne_rsrctab +
-             /* resident names table */
-           ne_header.ne_modtab - ne_header.ne_restab +
-             /* module ref table */
-           ne_header.ne_cmod * sizeof(WORD) +
-             /* imported names table */
-           ne_header.ne_enttab - ne_header.ne_imptab +
-             /* entry table length */
-           ne_header.ne_cbenttab +
-	     /* entry table extra conversion space */
-	   sizeof(ET_BUNDLE) +
-	   2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6) +
-             /* loaded file info */
-           sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
-
-    hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
-    if (!hModule) return (HMODULE16)11;  /* invalid exe */
-
-    FarSetOwner16( hModule, hModule );
-    pModule = (NE_MODULE *)GlobalLock16( hModule );
-    memcpy( pModule, &ne_header, sizeof(ne_header) );
-    pModule->count = 0;
-    /* check *programs* for default minimal stack size */
-    if ( (!(pModule->flags & NE_FFLAGS_LIBMODULE))
-		&& (pModule->stack_size < 0x1400) )
-		pModule->stack_size = 0x1400;
-    pModule->module32 = 0;
-    pModule->self = hModule;
-    pModule->self_loading_sel = 0;
-    pData = (BYTE *)(pModule + 1);
-
-    /* Clear internal Wine flags in case they are set in the EXE file */
-
-    pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
-
-    /* Read the fast-load area */
-
-    if (ne_header.ne_flagsothers & NE_AFLAGS_FASTLOAD)
-    {
-        fastload_offset=ne_header.ne_pretthunks << ne_header.ne_align;
-        fastload_length=ne_header.ne_psegrefbytes << ne_header.ne_align;
-        TRACE("Using fast-load area offset=%x len=%d\n",
-                        fastload_offset, fastload_length );
-        if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL)
-        {
-            if (!read_data( handle, fastload_offset, fastload, fastload_length))
-            {
-                HeapFree( GetProcessHeap(), 0, fastload );
-                WARN("Error reading fast-load area!\n");
-                fastload = NULL;
-            }
-        }
-    }
-
-    /* Get the segment table */
-
-    pModule->seg_table = pData - (BYTE *)pModule;
-    buffer = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cseg *
-                                      sizeof(struct ne_segment_table_entry_s));
-    if (buffer)
-    {
-        int i;
-        struct ne_segment_table_entry_s *pSeg;
-
-        if (!READ( mz_header.e_lfanew + ne_header.ne_segtab,
-             ne_header.ne_cseg * sizeof(struct ne_segment_table_entry_s),
-             buffer ))
-        {
-            HeapFree( GetProcessHeap(), 0, buffer );
-            if (fastload)
-		HeapFree( GetProcessHeap(), 0, fastload );
-            GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
-        }
-        pSeg = (struct ne_segment_table_entry_s *)buffer;
-        for (i = ne_header.ne_cseg; i > 0; i--, pSeg++)
-        {
-            memcpy( pData, pSeg, sizeof(*pSeg) );
-            pData += sizeof(SEGTABLEENTRY);
-        }
-        HeapFree( GetProcessHeap(), 0, buffer );
-    }
-    else
-    {
-        if (fastload)
-	    HeapFree( GetProcessHeap(), 0, fastload );
-        GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
-    }
-
-    /* Get the resource table */
-
-    if (ne_header.ne_rsrctab < ne_header.ne_restab)
-    {
-        pModule->res_table = pData - (BYTE *)pModule;
-        if (!READ(mz_header.e_lfanew + ne_header.ne_rsrctab,
-                  ne_header.ne_restab - ne_header.ne_rsrctab,
-                  pData ))
-            return (HMODULE16)11;  /* invalid exe */
-        pData += ne_header.ne_restab - ne_header.ne_rsrctab;
-        NE_InitResourceHandler( pModule );
-    }
-    else pModule->res_table = 0;  /* No resource table */
-
-    /* Get the resident names table */
-
-    pModule->name_table = pData - (BYTE *)pModule;
-    if (!READ( mz_header.e_lfanew + ne_header.ne_restab,
-               ne_header.ne_modtab - ne_header.ne_restab,
-               pData ))
-    {
-        if (fastload)
-	    HeapFree( GetProcessHeap(), 0, fastload );
-        GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
-    }
-    pData += ne_header.ne_modtab - ne_header.ne_restab;
-
-    /* Get the module references table */
-
-    if (ne_header.ne_cmod > 0)
-    {
-        pModule->modref_table = pData - (BYTE *)pModule;
-        if (!READ( mz_header.e_lfanew + ne_header.ne_modtab,
-                  ne_header.ne_cmod * sizeof(WORD),
-                  pData ))
-        {
-            if (fastload)
-		HeapFree( GetProcessHeap(), 0, fastload );
-            GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
-        }
-        pData += ne_header.ne_cmod * sizeof(WORD);
-    }
-    else pModule->modref_table = 0;  /* No module references */
-
-    /* Get the imported names table */
-
-    pModule->import_table = pData - (BYTE *)pModule;
-    if (!READ( mz_header.e_lfanew + ne_header.ne_imptab,
-               ne_header.ne_enttab - ne_header.ne_imptab,
-               pData ))
-    {
-        if (fastload)
-	    HeapFree( GetProcessHeap(), 0, fastload );
-        GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
-    }
-    pData += ne_header.ne_enttab - ne_header.ne_imptab;
-
-    /* Load entry table, convert it to the optimized version used by Windows */
-
-    if ((pTempEntryTable = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cbenttab)) != NULL)
-    {
-        BYTE nr_entries, type, *s;
-
-	TRACE("Converting entry table.\n");
-    pModule->entry_table = pData - (BYTE *)pModule;
-    if (!READ( mz_header.e_lfanew + ne_header.ne_enttab,
-                ne_header.ne_cbenttab, pTempEntryTable ))
-    {
-            HeapFree( GetProcessHeap(), 0, pTempEntryTable );
-            if (fastload)
-		HeapFree( GetProcessHeap(), 0, fastload );
-        GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
-    }
-
-        s = pTempEntryTable;
-        TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header.ne_enttab, ne_header.ne_cbenttab, *s);
-
-	bundle = (ET_BUNDLE *)pData;
-        TRACE("first bundle: %p\n", bundle);
-	memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
-	entry = (ET_ENTRY *)((BYTE *)bundle+6);
-
-	while ((nr_entries = *s++))
-        {
-	    if ((type = *s++))
-            {
-		bundle->last += nr_entries;
-                if (type == 0xff)
-                while (nr_entries--)
-                {
-                    entry->type   = type;
-                    entry->flags  = *s++;
-                    s += 2;
-                    entry->segnum = *s++;
-                    entry->offs   = *(WORD *)s; s += 2;
-		    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
-		    entry++;
-		}
-                else
-                while (nr_entries--)
-                {
-                    entry->type   = type;
-                    entry->flags  = *s++;
-                    entry->segnum = type;
-                    entry->offs   = *(WORD *)s; s += 2;
-		    /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
-		    entry++;
-		}
-	    }
-            else
-            {
-                if (bundle->first == bundle->last)
-                {
-                    bundle->first += nr_entries;
-                    bundle->last += nr_entries;
-                }
-                else
-                {
-		    oldbundle = bundle;
-		    oldbundle->next = ((int)entry - (int)pModule);
-                    bundle = (ET_BUNDLE *)entry;
-                    TRACE("new bundle: %p\n", bundle);
-                    bundle->first = bundle->last =
-                        oldbundle->last + nr_entries;
-                    bundle->next = 0;
-                    (BYTE *)entry += sizeof(ET_BUNDLE);
-                }
-            }
-        }
-	HeapFree( GetProcessHeap(), 0, pTempEntryTable );
-    }
-    else
-    {
-        if (fastload)
-	    HeapFree( GetProcessHeap(), 0, fastload );
-        GlobalFree16( hModule );
-        return (HMODULE16)11;  /* invalid exe */
-    }
-
-    pData += ne_header.ne_cbenttab + sizeof(ET_BUNDLE) +
-	     2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6);
-
-    if ((DWORD)entry > (DWORD)pData)
-       ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
-
-    /* Store the filename information */
-
-    pModule->fileinfo = pData - (BYTE *)pModule;
-    size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
-    ofs = (OFSTRUCT *)pData;
-    ofs->cBytes = size - 1;
-    ofs->fFixedDisk = 1;
-    strcpy( ofs->szPathName, path );
-    pData += size;
-
-    /* Free the fast-load area */
-
-#undef READ
-    if (fastload)
-	HeapFree( GetProcessHeap(), 0, fastload );
-
-    /* Get the non-resident names table */
-
-    if (ne_header.ne_cbnrestab)
-    {
-        pModule->nrname_handle = GlobalAlloc16( 0, ne_header.ne_cbnrestab );
-        if (!pModule->nrname_handle)
-        {
-            GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
-        }
-        FarSetOwner16( pModule->nrname_handle, hModule );
-        buffer = GlobalLock16( pModule->nrname_handle );
-        if (!read_data( handle, ne_header.ne_nrestab, buffer, ne_header.ne_cbnrestab ))
-        {
-            GlobalFree16( pModule->nrname_handle );
-            GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
-        }
-    }
-    else pModule->nrname_handle = 0;
-
-    /* Allocate a segment for the implicitly-loaded DLLs */
-
-    if (pModule->modref_count)
-    {
-        pModule->dlls_to_init = GlobalAlloc16( GMEM_ZEROINIT,
-                                               (pModule->modref_count+1)*sizeof(HMODULE16) );
-        if (!pModule->dlls_to_init)
-        {
-            if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
-            GlobalFree16( hModule );
-            return (HMODULE16)11;  /* invalid exe */
-        }
-        FarSetOwner16( pModule->dlls_to_init, hModule );
-    }
-    else pModule->dlls_to_init = 0;
-
-    NE_RegisterModule( pModule );
-    SNOOP16_RegisterDLL(pModule,path);
-    return hModule;
-}
-
-
-/***********************************************************************
- *           NE_LoadDLLs
- *
- * Load all DLLs implicitly linked to a module.
- */
-static BOOL NE_LoadDLLs( NE_MODULE *pModule )
-{
-    int i;
-    WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
-    WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
-
-    for (i = 0; i < pModule->modref_count; i++, pModRef++)
-    {
-        char buffer[260], *p;
-        BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
-        memcpy( buffer, pstr + 1, *pstr );
-        *(buffer + *pstr) = 0; /* terminate it */
-
-        TRACE("Loading '%s'\n", buffer );
-        if (!(*pModRef = GetModuleHandle16( buffer )))
-        {
-            /* If the DLL is not loaded yet, load it and store */
-            /* its handle in the list of DLLs to initialize.   */
-            HMODULE16 hDLL;
-
-            /* Append .DLL to name if no extension present */
-            if (!(p = strrchr( buffer, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
-                    strcat( buffer, ".DLL" );
-
-            if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
-            {
-                /* FIXME: cleanup what was done */
-
-                MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
-                     buffer, *((BYTE*)pModule + pModule->name_table),
-                     (char *)pModule + pModule->name_table + 1, hDLL );
-                return FALSE;
-            }
-            *pModRef = GetExePtr( hDLL );
-            *pDLLs++ = *pModRef;
-        }
-        else  /* Increment the reference count of the DLL */
-        {
-            NE_MODULE *pOldDLL;
-
-	    pOldDLL = NE_GetPtr( *pModRef );
-            if (pOldDLL) pOldDLL->count++;
-        }
-    }
-    return TRUE;
-}
-
-
-/**********************************************************************
- *	    NE_DoLoadModule
- *
- * Load first instance of NE module from file.
- *
- * pModule must point to a module structure prepared by NE_LoadExeHeader.
- * This routine must never be called twice on a module.
- *
- */
-static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
-{
-    /* Allocate the segments for this module */
-
-    if (!NE_CreateAllSegments( pModule ))
-        return ERROR_NOT_ENOUGH_MEMORY; /* 8 */
-
-    /* Load the referenced DLLs */
-
-    if (!NE_LoadDLLs( pModule ))
-        return ERROR_FILE_NOT_FOUND; /* 2 */
-
-    /* Load the segments */
-
-    NE_LoadAllSegments( pModule );
-
-    /* Make sure the usage count is 1 on the first loading of  */
-    /* the module, even if it contains circular DLL references */
-
-    pModule->count = 1;
-
-    return NE_GetInstance( pModule );
-}
-
-/**********************************************************************
- *	    NE_LoadModule
- *
- * Load first instance of NE module. (Note: caller is responsible for
- * ensuring the module isn't already loaded!)
- *
- * If the module turns out to be an executable module, only a
- * handle to a module stub is returned; this needs to be initialized
- * by calling NE_DoLoadModule later, in the context of the newly
- * created process.
- *
- * If lib_only is TRUE, however, the module is perforce treated
- * like a DLL module, even if it is an executable module.
- *
- */
-static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
-{
-    NE_MODULE *pModule;
-    HMODULE16 hModule;
-    HINSTANCE16 hInstance;
-    HFILE16 hFile;
-    OFSTRUCT ofs;
-
-    /* Open file */
-    if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
-        return (HMODULE16)2;  /* File not found */
-
-    hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName );
-    _lclose16( hFile );
-    if (hModule < 32) return hModule;
-
-    pModule = NE_GetPtr( hModule );
-    if ( !pModule ) return hModule;
-
-    if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
-        return hModule;
-
-    hInstance = NE_DoLoadModule( pModule );
-    if ( hInstance < 32 )
-    {
-        /* cleanup ... */
-        NE_FreeModule( hModule, 0 );
-    }
-
-    return hInstance;
-}
-
-
-/**********************************************************************
- *	    MODULE_LoadModule16
- *
- * Load a NE module in the order of the loadorder specification.
- * The caller is responsible that the module is not loaded already.
- *
- */
-static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
-{
-	HINSTANCE16 hinst = 2;
-	enum loadorder_type loadorder[LOADORDER_NTYPES];
-	int i;
-        const char *filetype = "";
-
-	MODULE_GetLoadOrder(loadorder, libname, FALSE);
-
-	for(i = 0; i < LOADORDER_NTYPES; i++)
-	{
-            if (loadorder[i] == LOADORDER_INVALID) break;
-
-		switch(loadorder[i])
-		{
-		case LOADORDER_DLL:
-			TRACE("Trying native dll '%s'\n", libname);
-			hinst = NE_LoadModule(libname, lib_only);
-                        filetype = "native";
-			break;
-
-		case LOADORDER_BI:
-			TRACE("Trying built-in '%s'\n", libname);
-			hinst = BUILTIN_LoadModule(libname);
-                        filetype = "builtin";
-			break;
-
-                default:
-			hinst = 2;
-			break;
-		}
-
-		if(hinst >= 32)
-		{
-                        TRACE_(loaddll)("Loaded module '%s' : %s\n", libname, filetype);
-			if(!implicit)
-			{
-				HMODULE16 hModule;
-				NE_MODULE *pModule;
-
-				hModule = GetModuleHandle16(libname);
-				if(!hModule)
-				{
-					ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle. Filename too long ?\n",
-						libname, hinst);
-					return 6;	/* ERROR_INVALID_HANDLE seems most appropriate */
-				}
-
-				pModule = NE_GetPtr(hModule);
-				if(!pModule)
-				{
-					ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
-						libname, hinst);
-					return 6;	/* ERROR_INVALID_HANDLE seems most appropriate */
-				}
-
-				TRACE("Loaded module '%s' at 0x%04x.\n", libname, hinst);
-
-				/*
-				 * Call initialization routines for all loaded DLLs. Note that
-				 * when we load implicitly linked DLLs this will be done by InitTask().
-				 */
-				if(pModule->flags & NE_FFLAGS_LIBMODULE)
-				{
-					NE_InitializeDLLs(hModule);
-					NE_DllProcessAttach(hModule);
-				}
-			}
-			return hinst;
-		}
-
-		if(hinst != 2)
-		{
-			/* We quit searching when we get another error than 'File not found' */
-			break;
-		}
-	}
-	return hinst;	/* The last error that occurred */
-}
-
-
-/**********************************************************************
- *          NE_CreateThread
- *
- * Create the thread for a 16-bit module.
- */
-static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
-{
-    HANDLE hThread;
-    TDB *pTask;
-    HTASK16 hTask;
-    HINSTANCE16 instance = 0;
-
-    if (!(hTask = TASK_SpawnTask( pModule, cmdShow, cmdline + 1, *cmdline, &hThread )))
-        return 0;
-
-    /* Post event to start the task */
-    PostEvent16( hTask );
-
-    /* Wait until we get the instance handle */
-    do
-    {
-        DirectedYield16( hTask );
-        if (!IsTask16( hTask ))  /* thread has died */
-        {
-            DWORD exit_code;
-            WaitForSingleObject( hThread, INFINITE );
-            GetExitCodeThread( hThread, &exit_code );
-            CloseHandle( hThread );
-            return exit_code;
-        }
-        if (!(pTask = TASK_GetPtr( hTask ))) break;
-        instance = pTask->hInstance;
-        GlobalUnlock16( hTask );
-    } while (!instance);
-
-    CloseHandle( hThread );
-    return instance;
-}
-
-
-/**********************************************************************
- *          LoadModule      (KERNEL.45)
- */
-HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
-{
-    BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
-    LOADPARAMS16 *params;
-    HMODULE16 hModule;
-    NE_MODULE *pModule;
-    LPSTR cmdline;
-    WORD cmdShow;
-
-    /* Load module */
-
-    if ( (hModule = NE_GetModuleByFilename(name) ) != 0 )
-    {
-        /* Special case: second instance of an already loaded NE module */
-
-        if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
-        if ( pModule->module32 ) return (HINSTANCE16)21;
-
-        /* Increment refcount */
-
-        pModule->count++;
-    }
-    else
-    {
-        /* Main case: load first instance of NE module */
-
-        if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
-            return hModule;
-
-        if ( !(pModule = NE_GetPtr( hModule )) )
-            return (HINSTANCE16)11;
-    }
-
-    /* If library module, we just retrieve the instance handle */
-
-    if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
-        return NE_GetInstance( pModule );
-
-    /*
-     *  At this point, we need to create a new process.
-     *
-     *  pModule points either to an already loaded module, whose refcount
-     *  has already been incremented (to avoid having the module vanish
-     *  in the meantime), or else to a stub module which contains only header
-     *  information.
-     */
-    params = (LOADPARAMS16 *)paramBlock;
-    cmdShow = ((WORD *)MapSL(params->showCmd))[1];
-    cmdline = MapSL( params->cmdLine );
-    return NE_CreateThread( pModule, cmdShow, cmdline );
-}
-
-
-/**********************************************************************
- *          NE_StartTask
- *
- * Startup code for a new 16-bit task.
- */
-DWORD NE_StartTask(void)
-{
-    TDB *pTask = TASK_GetCurrent();
-    NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
-    HINSTANCE16 hInstance, hPrevInstance;
-    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
-    WORD sp;
-
-    if ( pModule->count > 0 )
-    {
-        /* Second instance of an already loaded NE module */
-        /* Note that the refcount was already incremented by the parent */
-
-        hPrevInstance = NE_GetInstance( pModule );
-
-        if ( pModule->dgroup )
-            if ( NE_CreateSegment( pModule, pModule->dgroup ) )
-                NE_LoadSegment( pModule, pModule->dgroup );
-
-        hInstance = NE_GetInstance( pModule );
-	TRACE("created second instance %04x[%d] of instance %04x.\n", hInstance, pModule->dgroup, hPrevInstance);
-
-    }
-    else
-    {
-        /* Load first instance of NE module */
-
-        pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
-
-        hInstance = NE_DoLoadModule( pModule );
-        hPrevInstance = 0;
-    }
-
-    if ( hInstance >= 32 )
-    {
-        CONTEXT86 context;
-
-        /* Enter instance handles into task struct */
-
-        pTask->hInstance = hInstance;
-        pTask->hPrevInstance = hPrevInstance;
-
-        /* Use DGROUP for 16-bit stack */
-
-        if (!(sp = pModule->sp))
-            sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
-        sp &= ~1;
-        sp -= sizeof(STACK16FRAME);
-        pTask->teb->cur_stack = MAKESEGPTR( GlobalHandleToSel16(hInstance), sp );
-
-        /* Registers at initialization must be:
-         * ax   zero
-         * bx   stack size in bytes
-         * cx   heap size in bytes
-         * si   previous app instance
-         * di   current app instance
-         * bp   zero
-         * es   selector to the PSP
-         * ds   dgroup of the application
-         * ss   stack selector
-         * sp   top of the stack
-         */
-        memset( &context, 0, sizeof(context) );
-        context.SegCs  = GlobalHandleToSel16(pSegTable[pModule->cs - 1].hSeg);
-        context.SegDs  = GlobalHandleToSel16(pTask->hInstance);
-        context.SegEs  = pTask->hPDB;
-        context.Eip    = pModule->ip;
-        context.Ebx    = pModule->stack_size;
-        context.Ecx    = pModule->heap_size;
-        context.Edi    = pTask->hInstance;
-        context.Esi    = pTask->hPrevInstance;
-
-        /* Now call 16-bit entry point */
-
-        TRACE("Starting main program: cs:ip=%04lx:%04lx ds=%04lx ss:sp=%04x:%04x\n",
-              context.SegCs, context.Eip, context.SegDs,
-              SELECTOROF(pTask->teb->cur_stack),
-              OFFSETOF(pTask->teb->cur_stack) );
-
-        wine_call_to_16_regs_short( &context, 0 );
-        ExitThread( LOWORD(context.Eax) );
-    }
-    return hInstance;  /* error code */
-}
-
-/***********************************************************************
- *           LoadLibrary     (KERNEL.95)
- *           LoadLibrary16   (KERNEL32.35)
- */
-HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
-{
-    return LoadModule16(libname, (LPVOID)-1 );
-}
-
-
-/**********************************************************************
- *	    MODULE_CallWEP
- *
- * Call a DLL's WEP, allowing it to shut down.
- * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
- */
-static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
-{
-    BOOL16 ret;
-    FARPROC16 WEP = GetProcAddress16( hModule, "WEP" );
-    if (!WEP) return FALSE;
-
-    __TRY
-    {
-        ret = NE_CallTo16_word_w( WEP, WEP_FREE_DLL );
-    }
-    __EXCEPT(page_fault)
-    {
-        WARN("Page fault\n");
-        ret = 0;
-    }
-    __ENDTRY
-
-    return ret;
-}
-
-
-/**********************************************************************
- *	    NE_FreeModule
- *
- * Implementation of FreeModule16().
- */
-static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
-{
-    HMODULE16 *hPrevModule;
-    NE_MODULE *pModule;
-    HMODULE16 *pModRef;
-    int i;
-
-    if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
-    hModule = pModule->self;
-
-    TRACE("%04x count %d\n", hModule, pModule->count );
-
-    if (((INT16)(--pModule->count)) > 0 ) return TRUE;
-    else pModule->count = 0;
-
-    if (pModule->flags & NE_FFLAGS_BUILTIN)
-        return FALSE;  /* Can't free built-in module */
-
-    if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32))
-    {
-        /* Free the objects owned by the DLL module */
-        NE_CallUserSignalProc( hModule, USIG16_DLL_UNLOAD );
-
-        if (pModule->flags & NE_FFLAGS_LIBMODULE)
-            MODULE_CallWEP( hModule );
-        else
-            call_wep = FALSE;  /* We are freeing a task -> no more WEPs */
-    }
-
-
-    /* Clear magic number just in case */
-
-    pModule->magic = pModule->self = 0;
-
-      /* Remove it from the linked list */
-
-    hPrevModule = &hFirstModule;
-    while (*hPrevModule && (*hPrevModule != hModule))
-    {
-        hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
-    }
-    if (*hPrevModule) *hPrevModule = pModule->next;
-
-    /* Free the referenced modules */
-
-    pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
-    for (i = 0; i < pModule->modref_count; i++, pModRef++)
-    {
-        NE_FreeModule( *pModRef, call_wep );
-    }
-
-    /* Free the module storage */
-
-    GlobalFreeAll16( hModule );
-
-    /* Remove module from cache */
-
-    if (pCachedModule == pModule) pCachedModule = NULL;
-    return TRUE;
-}
-
-
-/**********************************************************************
- *	    FreeModule    (KERNEL.46)
- */
-BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
-{
-    return NE_FreeModule( hModule, TRUE );
-}
-
-
-/***********************************************************************
- *           FreeLibrary     (KERNEL.96)
- *           FreeLibrary16   (KERNEL32.36)
- */
-void WINAPI FreeLibrary16( HINSTANCE16 handle )
-{
-    TRACE("%04x\n", handle );
-    FreeModule16( handle );
-}
-
-
-/**********************************************************************
- *	    GetModuleName    (KERNEL.27)
- */
-BOOL16 WINAPI GetModuleName16( HINSTANCE16 hinst, LPSTR buf, INT16 count )
-{
-    NE_MODULE *pModule;
-    BYTE *p;
-
-    if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
-    p = (BYTE *)pModule + pModule->name_table;
-    if (count > *p) count = *p + 1;
-    if (count > 0)
-    {
-        memcpy( buf, p + 1, count - 1 );
-        buf[count-1] = '\0';
-    }
-    return TRUE;
-}
-
-
-/**********************************************************************
- *	    GetModuleUsage    (KERNEL.48)
- */
-INT16 WINAPI GetModuleUsage16( HINSTANCE16 hModule )
-{
-    NE_MODULE *pModule = NE_GetPtr( hModule );
-    return pModule ? pModule->count : 0;
-}
-
-
-/**********************************************************************
- *	    GetExpWinVer    (KERNEL.167)
- */
-WORD WINAPI GetExpWinVer16( HMODULE16 hModule )
-{
-    NE_MODULE *pModule = NE_GetPtr( hModule );
-    if ( !pModule ) return 0;
-
-    /*
-     * For built-in modules, fake the expected version the module should
-     * have according to the Windows version emulated by Wine
-     */
-    if ( !pModule->expected_version )
-    {
-        OSVERSIONINFOA versionInfo;
-        versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
-
-        if ( GetVersionExA( &versionInfo ) )
-            pModule->expected_version =
-                     (versionInfo.dwMajorVersion & 0xff) << 8
-                   | (versionInfo.dwMinorVersion & 0xff);
-    }
-
-    return pModule->expected_version;
-}
-
-
 /**********************************************************************
  *	    GetModuleFileName      (KERNEL.49)
  *
@@ -1438,120 +245,6 @@
 
 
 /***********************************************************************
- *           WinExec     (KERNEL.166)
- */
-HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
-{
-    LPCSTR p, args = NULL;
-    LPCSTR name_beg, name_end;
-    LPSTR name, cmdline;
-    int arglen;
-    HINSTANCE16 ret;
-    char buffer[MAX_PATH];
-
-    if (*lpCmdLine == '"') /* has to be only one and only at beginning ! */
-    {
-        name_beg = lpCmdLine+1;
-        p = strchr ( lpCmdLine+1, '"' );
-        if (p)
-        {
-            name_end = p;
-            args = strchr ( p, ' ' );
-        }
-        else /* yes, even valid with trailing '"' missing */
-            name_end = lpCmdLine+strlen(lpCmdLine);
-    }
-    else
-    {
-        name_beg = lpCmdLine;
-        args = strchr( lpCmdLine, ' ' );
-        name_end = args ? args : lpCmdLine+strlen(lpCmdLine);
-    }
-
-    if ((name_beg == lpCmdLine) && (!args))
-    { /* just use the original cmdline string as file name */
-        name = (LPSTR)lpCmdLine;
-    }
-    else
-    {
-        if (!(name = HeapAlloc( GetProcessHeap(), 0, name_end - name_beg + 1 )))
-            return ERROR_NOT_ENOUGH_MEMORY;
-        memcpy( name, name_beg, name_end - name_beg );
-        name[name_end - name_beg] = '\0';
-    }
-
-    if (args)
-    {
-        args++;
-        arglen = strlen(args);
-        cmdline = HeapAlloc( GetProcessHeap(), 0, 2 + arglen );
-        cmdline[0] = (BYTE)arglen;
-        strcpy( cmdline + 1, args );
-    }
-    else
-    {
-        cmdline = HeapAlloc( GetProcessHeap(), 0, 2 );
-        cmdline[0] = cmdline[1] = 0;
-    }
-
-    TRACE("name: '%s', cmdline: '%.*s'\n", name, cmdline[0], &cmdline[1]);
-
-    if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
-    {
-        LOADPARAMS16 params;
-        WORD showCmd[2];
-        showCmd[0] = 2;
-        showCmd[1] = nCmdShow;
-
-        params.hEnvironment = 0;
-        params.cmdLine = MapLS( cmdline );
-        params.showCmd = MapLS( showCmd );
-        params.reserved = 0;
-
-        ret = LoadModule16( buffer, &params );
-        UnMapLS( params.cmdLine );
-        UnMapLS( params.showCmd );
-    }
-    else ret = GetLastError();
-
-    HeapFree( GetProcessHeap(), 0, cmdline );
-    if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
-
-    if (ret == 21)  /* 32-bit module */
-    {
-        DWORD count;
-        ReleaseThunkLock( &count );
-        ret = LOWORD( WinExec( lpCmdLine, nCmdShow ) );
-        RestoreThunkLock( count );
-    }
-    return ret;
-}
-
-/**********************************************************************
- *	    GetModuleHandle    (KERNEL.47)
- *
- * Find a module from a module name.
- *
- * NOTE: The current implementation works the same way the Windows 95 one
- *	 does. Do not try to 'fix' it, fix the callers.
- *	 + It does not do ANY extension handling (except that strange .EXE bit)!
- *	 + It does not care about paths, just about basenames. (same as Windows)
- *
- * RETURNS
- *   LOWORD:
- *	the win16 module handle if found
- * 	0 if not
- *   HIWORD (undocumented, see "Undocumented Windows", chapter 5):
- *	Always hFirstModule
- */
-DWORD WINAPI WIN16_GetModuleHandle( SEGPTR name )
-{
-    if (HIWORD(name) == 0)
-	return MAKELONG(GetExePtr( (HINSTANCE16)name), hFirstModule );
-    return MAKELONG(GetModuleHandle16( MapSL(name)), hFirstModule );
-}
-
-/***********************************************************************
  *          GetModuleHandle16 (KERNEL32.@)
  */
 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
@@ -1647,117 +340,9 @@
 	if (!FILE_strcasecmp(loadedfn, s))
 	    return hModule;
     }
-
-    /* If the extension of 'name' is '.EXE' and the base filename of 'name'
-     * matches the base filename of the module filename of some 32-bit module:
-     * Return the corresponding 16-bit dummy module handle.
-     */
-    if (len >= 4 && !FILE_strcasecmp(name+len-4, ".EXE"))
-    {
-        HMODULE hModule = GetModuleHandleA( name );
-        if ( hModule )
-            return MapHModuleLS( hModule );
-    }
-
-    if (!strcmp(tmpstr,"MSDOS"))
-	return 1;
-
-    if (!strcmp(tmpstr,"TIMER"))
-    {
-	FIXME("Eh... Should return caller's code segment, expect crash\n");
-	return 0;
-    }
-
     return 0;
 }
 
-/**********************************************************************
- *	    NE_GetModuleByFilename
- */
-static HMODULE16 NE_GetModuleByFilename( LPCSTR name )
-{
-    HMODULE16	hModule;
-    LPSTR	s, p;
-    BYTE	len, *name_table;
-    char	tmpstr[MAX_PATH];
-    NE_MODULE *pModule;
-
-    lstrcpynA(tmpstr, name, sizeof(tmpstr));
-
-    /* If the base filename of 'name' matches the base filename of the module
-     * filename of some module (case-insensitive compare):
-     * Return its handle.
-     */
-
-    /* basename: search backwards in passed name to \ / or : */
-    s = tmpstr + strlen(tmpstr);
-    while (s > tmpstr)
-    {
-    	if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
-		break;
-	s--;
-    }
-
-    /* search this in loaded filename list */
-    for (hModule = hFirstModule; hModule ; hModule = pModule->next)
-    {
-    	char		*loadedfn;
-	OFSTRUCT	*ofs;
-
-	pModule = NE_GetPtr( hModule );
-        if (!pModule) break;
-	if (!pModule->fileinfo) continue;
-        if (pModule->flags & NE_FFLAGS_WIN32) continue;
-
-        ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
-	loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
-	/* basename: search backwards in pathname to \ / or : */
-	while (loadedfn > (char*)ofs->szPathName)
-	{
-	    if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
-		    break;
-	    loadedfn--;
-	}
-	/* case insensitive compare ... */
-	if (!FILE_strcasecmp(loadedfn, s))
-	    return hModule;
-    }
-    /* If basename (without ext) matches the module name of a module:
-     * Return its handle.
-     */
-
-    if ( (p = strrchr( s, '.' )) != NULL ) *p = '\0';
-    len = strlen(s);
-
-    for (hModule = hFirstModule; hModule ; hModule = pModule->next)
-    {
-	pModule = NE_GetPtr( hModule );
-        if (!pModule) break;
-        if (pModule->flags & NE_FFLAGS_WIN32) continue;
-
-        name_table = (BYTE *)pModule + pModule->name_table;
-        if ((*name_table == len) && !FILE_strncasecmp(s, name_table+1, len))
-            return hModule;
-    }
-
-    return 0;
-}
-
-/***********************************************************************
- *           GetProcAddress16   (KERNEL32.37)
- * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
- */
-FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
-{
-    if (!hModule) return 0;
-    if (HIWORD(hModule))
-    {
-        WARN("hModule is Win32 handle (%p)\n", hModule );
-        return 0;
-    }
-    return GetProcAddress16( LOWORD(hModule), name );
-}
-
 /***********************************************************************
  *           GetProcAddress   (KERNEL.50)
  */
@@ -1816,254 +401,3 @@
 
     return 0;
 }
-
-
-/**********************************************************************
- *	    ModuleFirst    (TOOLHELP.59)
- */
-BOOL16 WINAPI ModuleFirst16( MODULEENTRY *lpme )
-{
-    lpme->wNext = hFirstModule;
-    return ModuleNext16( lpme );
-}
-
-
-/**********************************************************************
- *	    ModuleNext    (TOOLHELP.60)
- */
-BOOL16 WINAPI ModuleNext16( MODULEENTRY *lpme )
-{
-    NE_MODULE *pModule;
-    char *name;
-
-    if (!lpme->wNext) return FALSE;
-    if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
-    name = (char *)pModule + pModule->name_table;
-    memcpy( lpme->szModule, name + 1, min(*name, MAX_MODULE_NAME) );
-    lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
-    lpme->hModule = lpme->wNext;
-    lpme->wcUsage = pModule->count;
-    lstrcpynA( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
-    lpme->wNext = pModule->next;
-    return TRUE;
-}
-
-
-/**********************************************************************
- *	    ModuleFindName    (TOOLHELP.61)
- */
-BOOL16 WINAPI ModuleFindName16( MODULEENTRY *lpme, LPCSTR name )
-{
-    lpme->wNext = GetModuleHandle16( name );
-    return ModuleNext16( lpme );
-}
-
-
-/**********************************************************************
- *	    ModuleFindHandle    (TOOLHELP.62)
- */
-BOOL16 WINAPI ModuleFindHandle16( MODULEENTRY *lpme, HMODULE16 hModule )
-{
-    hModule = GetExePtr( hModule );
-    lpme->wNext = hModule;
-    return ModuleNext16( lpme );
-}
-
-
-/***************************************************************************
- *          IsRomModule    (KERNEL.323)
- */
-BOOL16 WINAPI IsRomModule16( HMODULE16 unused )
-{
-    return FALSE;
-}
-
-/***************************************************************************
- *          IsRomFile    (KERNEL.326)
- */
-BOOL16 WINAPI IsRomFile16( HFILE16 unused )
-{
-    return FALSE;
-}
-
-/***********************************************************************
- *           create_dummy_module
- *
- * Create a dummy NE module for Win32 or Winelib.
- */
-static HMODULE16 create_dummy_module( HMODULE module32 )
-{
-    HMODULE16 hModule;
-    NE_MODULE *pModule;
-    SEGTABLEENTRY *pSegment;
-    char *pStr,*s;
-    unsigned int len;
-    const char* basename;
-    OFSTRUCT *ofs;
-    int of_size, size;
-    char filename[MAX_PATH];
-    IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module32 );
-
-    if (!nt) return (HMODULE16)11;  /* invalid exe */
-
-    /* Extract base filename */
-    GetModuleFileNameA( module32, filename, sizeof(filename) );
-    basename = strrchr(filename, '\\');
-    if (!basename) basename = filename;
-    else basename++;
-    len = strlen(basename);
-    if ((s = strchr(basename, '.'))) len = s - basename;
-
-    /* Allocate module */
-    of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
-                    + strlen(filename) + 1;
-    size = sizeof(NE_MODULE) +
-                 /* loaded file info */
-                 ((of_size + 3) & ~3) +
-                 /* segment table: DS,CS */
-                 2 * sizeof(SEGTABLEENTRY) +
-                 /* name table */
-                 len + 2 +
-                 /* several empty tables */
-                 8;
-
-    hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
-    if (!hModule) return (HMODULE16)11;  /* invalid exe */
-
-    FarSetOwner16( hModule, hModule );
-    pModule = (NE_MODULE *)GlobalLock16( hModule );
-
-    /* Set all used entries */
-    pModule->magic            = IMAGE_OS2_SIGNATURE;
-    pModule->count            = 1;
-    pModule->next             = 0;
-    pModule->flags            = NE_FFLAGS_WIN32;
-    pModule->dgroup           = 0;
-    pModule->ss               = 1;
-    pModule->cs               = 2;
-    pModule->heap_size        = 0;
-    pModule->stack_size       = 0;
-    pModule->seg_count        = 2;
-    pModule->modref_count     = 0;
-    pModule->nrname_size      = 0;
-    pModule->fileinfo         = sizeof(NE_MODULE);
-    pModule->os_flags         = NE_OSFLAGS_WINDOWS;
-    pModule->self             = hModule;
-    pModule->module32         = module32;
-
-    /* Set version and flags */
-    pModule->expected_version = ((nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
-                                (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
-    if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
-        pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
-
-    /* Set loaded file information */
-    ofs = (OFSTRUCT *)(pModule + 1);
-    memset( ofs, 0, of_size );
-    ofs->cBytes = of_size < 256 ? of_size : 255;   /* FIXME */
-    strcpy( ofs->szPathName, filename );
-
-    pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + ((of_size + 3) & ~3));
-    pModule->seg_table = (int)pSegment - (int)pModule;
-    /* Data segment */
-    pSegment->size    = 0;
-    pSegment->flags   = NE_SEGFLAGS_DATA;
-    pSegment->minsize = 0x1000;
-    pSegment++;
-    /* Code segment */
-    pSegment->flags   = 0;
-    pSegment++;
-
-    /* Module name */
-    pStr = (char *)pSegment;
-    pModule->name_table = (int)pStr - (int)pModule;
-    assert(len<256);
-    *pStr = len;
-    lstrcpynA( pStr+1, basename, len+1 );
-    pStr += len+2;
-
-    /* All tables zero terminated */
-    pModule->res_table = pModule->import_table = pModule->entry_table = (int)pStr - (int)pModule;
-
-    NE_RegisterModule( pModule );
-    LoadLibraryA( filename );  /* increment the ref count of the 32-bit module */
-    return hModule;
-}
-
-/***************************************************************************
- *		MapHModuleLS			(KERNEL32.@)
- */
-HMODULE16 WINAPI MapHModuleLS(HMODULE hmod)
-{
-	HMODULE16 ret;
-	NE_MODULE	*pModule;
-
-	if (!hmod)
-		return TASK_GetCurrent()->hInstance;
-	if (!HIWORD(hmod))
-		return LOWORD(hmod); /* we already have a 16 bit module handle */
-	pModule = (NE_MODULE*)GlobalLock16(hFirstModule);
-	while (pModule)  {
-		if (pModule->module32 == hmod)
-			return pModule->self;
-		pModule = (NE_MODULE*)GlobalLock16(pModule->next);
-	}
-        if ((ret = create_dummy_module( hmod )) < 32)
-        {
-            SetLastError(ret);
-            ret = 0;
-        }
-        return ret;
-}
-
-/***************************************************************************
- *		MapHModuleSL			(KERNEL32.@)
- */
-HMODULE WINAPI MapHModuleSL(HMODULE16 hmod) {
-	NE_MODULE	*pModule;
-
-	if (!hmod) {
-		TDB *pTask = TASK_GetCurrent();
-		hmod = pTask->hModule;
-	}
-	pModule = (NE_MODULE*)GlobalLock16(hmod);
-	if (	(pModule->magic!=IMAGE_OS2_SIGNATURE)	||
-		!(pModule->flags & NE_FFLAGS_WIN32)
-	)
-		return 0;
-	return pModule->module32;
-}
-
-/***************************************************************************
- *		MapHInstLS			(KERNEL32.@)
- *		MapHInstLS			(KERNEL.472)
- */
-void WINAPI MapHInstLS( CONTEXT86 *context )
-{
-    context->Eax = MapHModuleLS( (HMODULE)context->Eax );
-}
-
-/***************************************************************************
- *		MapHInstSL			(KERNEL32.@)
- *		MapHInstSL			(KERNEL.473)
- */
-void WINAPI MapHInstSL( CONTEXT86 *context )
-{
-    context->Eax = (DWORD)MapHModuleSL( context->Eax );
-}
-
-/***************************************************************************
- *		MapHInstLS_PN			(KERNEL32.@)
- */
-void WINAPI MapHInstLS_PN( CONTEXT86 *context )
-{
-    if (context->Eax) context->Eax = MapHModuleLS( (HMODULE)context->Eax );
-}
-
-/***************************************************************************
- *		MapHInstSL_PN			(KERNEL32.@)
- */
-void WINAPI MapHInstSL_PN( CONTEXT86 *context )
-{
-    if (context->Eax) context->Eax = (DWORD)MapHModuleSL( context->Eax );
-}
diff --git a/loader/task.c b/loader/task.c
index f836008..e954081 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -42,7 +42,6 @@
 #include "winternl.h"
 #include "selectors.h"
 #include "wine/server.h"
-#include "syslevel.h"
 #include "stackframe.h"
 #include "task.h"
 #include "thread.h"
@@ -51,8 +50,6 @@
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(task);
-WINE_DECLARE_DEBUG_CHANNEL(relay);
-WINE_DECLARE_DEBUG_CHANNEL(toolhelp);
 
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
@@ -61,42 +58,12 @@
 static THHOOK DefaultThhook;
 THHOOK *pThhook = &DefaultThhook;
 
-#define hCurrentTask (pThhook->CurTDB)
 #define hFirstTask   (pThhook->HeadTDB)
-#define hLockedTask  (pThhook->LockTDB)
-
-static UINT16 nTaskCount = 0;
-
-static HTASK16 initial_task;
-
-/***********************************************************************
- *	     TASK_InstallTHHook
- */
-void TASK_InstallTHHook( THHOOK *pNewThhook )
-{
-     THHOOK *pOldThhook = pThhook;
-
-     pThhook = pNewThhook? pNewThhook : &DefaultThhook;
-
-     *pThhook = *pOldThhook;
-}
-
-/***********************************************************************
- *	     TASK_GetNextTask
- */
-HTASK16 TASK_GetNextTask( HTASK16 hTask )
-{
-    TDB* pTask = TASK_GetPtr( hTask );
-
-    if (pTask->hNext) return pTask->hNext;
-    return (hFirstTask != hTask) ? hFirstTask : 0;
-}
-
 
 /***********************************************************************
  *	     TASK_GetPtr
  */
-TDB *TASK_GetPtr( HTASK16 hTask )
+static TDB *TASK_GetPtr( HTASK16 hTask )
 {
     return GlobalLock16( hTask );
 }
@@ -112,532 +79,6 @@
 
 
 /***********************************************************************
- *           TASK_LinkTask
- */
-static void TASK_LinkTask( HTASK16 hTask )
-{
-    HTASK16 *prevTask;
-    TDB *pTask;
-
-    if (!(pTask = TASK_GetPtr( hTask ))) return;
-    prevTask = &hFirstTask;
-    while (*prevTask)
-    {
-        TDB *prevTaskPtr = TASK_GetPtr( *prevTask );
-        if (prevTaskPtr->priority >= pTask->priority) break;
-        prevTask = &prevTaskPtr->hNext;
-    }
-    pTask->hNext = *prevTask;
-    *prevTask = hTask;
-    nTaskCount++;
-}
-
-
-/***********************************************************************
- *           TASK_UnlinkTask
- */
-static void TASK_UnlinkTask( HTASK16 hTask )
-{
-    HTASK16 *prevTask;
-    TDB *pTask;
-
-    prevTask = &hFirstTask;
-    while (*prevTask && (*prevTask != hTask))
-    {
-        pTask = TASK_GetPtr( *prevTask );
-        prevTask = &pTask->hNext;
-    }
-    if (*prevTask)
-    {
-        pTask = TASK_GetPtr( *prevTask );
-        *prevTask = pTask->hNext;
-        pTask->hNext = 0;
-        nTaskCount--;
-    }
-}
-
-
-/***********************************************************************
- *           TASK_CreateThunks
- *
- * Create a thunk free-list in segment 'handle', starting from offset 'offset'
- * and containing 'count' entries.
- */
-static void TASK_CreateThunks( HGLOBAL16 handle, WORD offset, WORD count )
-{
-    int i;
-    WORD free;
-    THUNKS *pThunk;
-
-    pThunk = (THUNKS *)((BYTE *)GlobalLock16( handle ) + offset);
-    pThunk->next = 0;
-    pThunk->magic = THUNK_MAGIC;
-    pThunk->free = (int)&pThunk->thunks - (int)pThunk;
-    free = pThunk->free;
-    for (i = 0; i < count-1; i++)
-    {
-        free += 8;  /* Offset of next thunk */
-        pThunk->thunks[4*i] = free;
-    }
-    pThunk->thunks[4*i] = 0;  /* Last thunk */
-}
-
-
-/***********************************************************************
- *           TASK_AllocThunk
- *
- * Allocate a thunk for MakeProcInstance().
- */
-static SEGPTR TASK_AllocThunk(void)
-{
-    TDB *pTask;
-    THUNKS *pThunk;
-    WORD sel, base;
-
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    sel = pTask->hCSAlias;
-    pThunk = &pTask->thunks;
-    base = (int)pThunk - (int)pTask;
-    while (!pThunk->free)
-    {
-        sel = pThunk->next;
-        if (!sel)  /* Allocate a new segment */
-        {
-            sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
-                                pTask->hPDB, WINE_LDT_FLAGS_CODE );
-            if (!sel) return (SEGPTR)0;
-            TASK_CreateThunks( sel, 0, MIN_THUNKS );
-            pThunk->next = sel;
-        }
-        pThunk = (THUNKS *)GlobalLock16( sel );
-        base = 0;
-    }
-    base += pThunk->free;
-    pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
-    return MAKESEGPTR( sel, base );
-}
-
-
-/***********************************************************************
- *           TASK_FreeThunk
- *
- * Free a MakeProcInstance() thunk.
- */
-static BOOL TASK_FreeThunk( SEGPTR thunk )
-{
-    TDB *pTask;
-    THUNKS *pThunk;
-    WORD sel, base;
-
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    sel = pTask->hCSAlias;
-    pThunk = &pTask->thunks;
-    base = (int)pThunk - (int)pTask;
-    while (sel && (sel != HIWORD(thunk)))
-    {
-        sel = pThunk->next;
-        pThunk = (THUNKS *)GlobalLock16( sel );
-        base = 0;
-    }
-    if (!sel) return FALSE;
-    *(WORD *)((BYTE *)pThunk + LOWORD(thunk) - base) = pThunk->free;
-    pThunk->free = LOWORD(thunk) - base;
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           TASK_Create
- *
- * NOTE: This routine might be called by a Win32 thread. Thus, we need
- *       to be careful to protect global data structures. We do this
- *       by entering the Win16Lock while linking the task into the
- *       global task list.
- */
-static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, BYTE len )
-{
-    HTASK16 hTask;
-    TDB *pTask;
-    FARPROC16 proc;
-    HMODULE16 hModule = pModule ? pModule->self : 0;
-
-      /* Allocate the task structure */
-
-    hTask = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB) );
-    if (!hTask) return NULL;
-    pTask = TASK_GetPtr( hTask );
-    FarSetOwner16( hTask, hModule );
-
-    /* Fill the task structure */
-
-    pTask->hSelf = hTask;
-
-    if (teb && teb->tibflags & TEBF_WIN32)
-    {
-        pTask->flags        |= TDBF_WIN32;
-        pTask->hInstance     = hModule;
-        pTask->hPrevInstance = 0;
-        /* NOTE: for 16-bit tasks, the instance handles are updated later on
-           in NE_InitProcess */
-    }
-
-    pTask->version       = pModule ? pModule->expected_version : 0x0400;
-    pTask->hModule       = hModule;
-    pTask->hParent       = GetCurrentTask();
-    pTask->magic         = TDB_MAGIC;
-    pTask->nCmdShow      = cmdShow;
-    pTask->teb           = teb;
-    pTask->curdrive      = DRIVE_GetCurrentDrive() | 0x80;
-    strcpy( pTask->curdir, "\\" );
-    WideCharToMultiByte(CP_ACP, 0, DRIVE_GetDosCwd(DRIVE_GetCurrentDrive()), -1,
-                        pTask->curdir + 1, sizeof(pTask->curdir) - 1, NULL, NULL);
-    pTask->curdir[sizeof(pTask->curdir) - 1] = 0; /* ensure 0 termination */
-
-      /* Create the thunks block */
-
-    TASK_CreateThunks( hTask, (int)&pTask->thunks - (int)pTask, 7 );
-
-      /* Copy the module name */
-
-    if (hModule)
-    {
-        char name[10];
-        GetModuleName16( hModule, name, sizeof(name) );
-        strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
-        pTask->compat_flags = GetProfileIntA( "Compatibility", name, 0 );
-    }
-
-      /* Allocate a selector for the PDB */
-
-    pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB16),
-                                      hModule, WINE_LDT_FLAGS_DATA );
-
-      /* Fill the PDB */
-
-    pTask->pdb.int20 = 0x20cd;
-    pTask->pdb.dispatcher[0] = 0x9a;  /* ljmp */
-    proc = GetProcAddress16( GetModuleHandle16("KERNEL"), "DOS3Call" );
-    memcpy( &pTask->pdb.dispatcher[1], &proc, sizeof(proc) );
-    pTask->pdb.savedint22 = 0;
-    pTask->pdb.savedint23 = 0;
-    pTask->pdb.savedint24 = 0;
-    pTask->pdb.fileHandlesPtr =
-        MAKESEGPTR( GlobalHandleToSel16(pTask->hPDB), (int)&((PDB16 *)0)->fileHandles );
-    pTask->pdb.hFileHandles = 0;
-    memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
-    /* FIXME: should we make a copy of the environment? */
-    pTask->pdb.environment    = SELECTOROF(GetDOSEnvironment16());
-    pTask->pdb.nbFiles        = 20;
-
-    /* Fill the command line */
-
-    if (!cmdline)
-    {
-        cmdline = GetCommandLineA();
-        /* remove the first word (program name) */
-        if (*cmdline == '"')
-            if (!(cmdline = strchr( cmdline+1, '"' ))) cmdline = GetCommandLineA();
-        while (*cmdline && (*cmdline != ' ') && (*cmdline != '\t')) cmdline++;
-        while ((*cmdline == ' ') || (*cmdline == '\t')) cmdline++;
-        len = strlen(cmdline);
-    }
-    if (len >= sizeof(pTask->pdb.cmdLine)) len = sizeof(pTask->pdb.cmdLine)-1;
-    pTask->pdb.cmdLine[0] = len;
-    memcpy( pTask->pdb.cmdLine + 1, cmdline, len );
-    /* pTask->pdb.cmdLine[len+1] = 0; */
-
-    TRACE("cmdline='%.*s' task=%04x\n", len, cmdline, hTask );
-
-      /* Allocate a code segment alias for the TDB */
-
-    pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
-                                          sizeof(TDB), pTask->hPDB, WINE_LDT_FLAGS_CODE );
-
-      /* Default DTA overwrites command line */
-
-    pTask->dta = MAKESEGPTR( pTask->hPDB, (int)&pTask->pdb.cmdLine - (int)&pTask->pdb );
-
-    /* Create scheduler event for 16-bit tasks */
-
-    if ( !(pTask->flags & TDBF_WIN32) )
-        NtCreateEvent( &pTask->hEvent, EVENT_ALL_ACCESS, NULL, TRUE, FALSE );
-
-    /* Enter task handle into thread */
-
-    if (teb) teb->htask16 = hTask;
-    if (!initial_task) initial_task = hTask;
-
-    return pTask;
-}
-
-
-/***********************************************************************
- *           TASK_DeleteTask
- */
-static void TASK_DeleteTask( HTASK16 hTask )
-{
-    TDB *pTask;
-    HGLOBAL16 hPDB;
-
-    if (!(pTask = TASK_GetPtr( hTask ))) return;
-    hPDB = pTask->hPDB;
-
-    pTask->magic = 0xdead; /* invalidate signature */
-
-    /* Free the selector aliases */
-
-    GLOBAL_FreeBlock( pTask->hCSAlias );
-    GLOBAL_FreeBlock( pTask->hPDB );
-
-    /* Free the task module */
-
-    FreeModule16( pTask->hModule );
-
-    /* Free the task structure itself */
-
-    GlobalFree16( hTask );
-
-    /* Free all memory used by this task (including the 32-bit stack, */
-    /* the environment block and the thunk segments). */
-
-    GlobalFreeAll16( hPDB );
-}
-
-
-/***********************************************************************
- *           TASK_CreateMainTask
- *
- * Create a task for the main (32-bit) process.
- */
-void TASK_CreateMainTask(void)
-{
-    TDB *pTask;
-    STARTUPINFOA startup_info;
-    UINT cmdShow = 1; /* SW_SHOWNORMAL but we don't want to include winuser.h here */
-
-    GetStartupInfoA( &startup_info );
-    if (startup_info.dwFlags & STARTF_USESHOWWINDOW) cmdShow = startup_info.wShowWindow;
-    pTask = TASK_Create( NULL, cmdShow, NtCurrentTeb(), NULL, 0 );
-    if (!pTask)
-    {
-        ERR("could not create task for main process\n");
-        ExitProcess(1);
-    }
-
-    /* Add the task to the linked list */
-    /* (no need to get the win16 lock, we are the only thread at this point) */
-    TASK_LinkTask( pTask->hSelf );
-}
-
-
-/* startup routine for a new 16-bit thread */
-static DWORD CALLBACK task_start( TDB *pTask )
-{
-    DWORD ret;
-
-    NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
-    NtCurrentTeb()->htask16 = pTask->hSelf;
-
-    _EnterWin16Lock();
-    TASK_LinkTask( pTask->hSelf );
-    pTask->teb = NtCurrentTeb();
-    ret = NE_StartTask();
-    _LeaveWin16Lock();
-    return ret;
-}
-
-
-/***********************************************************************
- *           TASK_SpawnTask
- *
- * Spawn a new 16-bit task.
- */
-HTASK16 TASK_SpawnTask( NE_MODULE *pModule, WORD cmdShow,
-                        LPCSTR cmdline, BYTE len, HANDLE *hThread )
-{
-    TDB *pTask;
-
-    if (!(pTask = TASK_Create( pModule, cmdShow, NULL, cmdline, len ))) return 0;
-    if (!(*hThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)task_start, pTask, 0, NULL )))
-    {
-        TASK_DeleteTask( pTask->hSelf );
-        return 0;
-    }
-    return pTask->hSelf;
-}
-
-
-/***********************************************************************
- *           TASK_ExitTask
- */
-void TASK_ExitTask(void)
-{
-    TDB *pTask;
-    DWORD lockCount;
-
-    /* Enter the Win16Lock to protect global data structures */
-    _EnterWin16Lock();
-
-    pTask = TASK_GetCurrent();
-    if ( !pTask )
-    {
-        _LeaveWin16Lock();
-        return;
-    }
-
-    TRACE("Killing task %04x\n", pTask->hSelf );
-
-    /* Perform USER cleanup */
-
-    TASK_CallTaskSignalProc( USIG16_TERMINATION, pTask->hSelf );
-
-    /* Remove the task from the list to be sure we never switch back to it */
-    TASK_UnlinkTask( pTask->hSelf );
-
-    if (!nTaskCount || (nTaskCount == 1 && hFirstTask == initial_task))
-    {
-        TRACE("this is the last task, exiting\n" );
-        ExitKernel16();
-    }
-
-    if( nTaskCount )
-    {
-        TDB* p = TASK_GetPtr( hFirstTask );
-        while( p )
-        {
-            if( p->hYieldTo == pTask->hSelf ) p->hYieldTo = 0;
-            p = TASK_GetPtr( p->hNext );
-        }
-    }
-
-    pTask->nEvents = 0;
-
-    if ( hLockedTask == pTask->hSelf )
-        hLockedTask = 0;
-
-    TASK_DeleteTask( pTask->hSelf );
-
-    /* ... and completely release the Win16Lock, just in case. */
-    ReleaseThunkLock( &lockCount );
-}
-
-
-/***********************************************************************
- *           ExitKernel (KERNEL.2)
- *
- * Clean-up everything and exit the Wine process.
- */
-void WINAPI ExitKernel16(void)
-{
-    WriteOutProfiles16();
-    TerminateProcess( GetCurrentProcess(), 0 );
-}
-
-
-/***********************************************************************
- *           InitTask  (KERNEL.91)
- *
- * Called by the application startup code.
- */
-void WINAPI InitTask16( CONTEXT86 *context )
-{
-    TDB *pTask;
-    INSTANCEDATA *pinstance;
-    SEGPTR ptr;
-
-    context->Eax = 0;
-    if (!(pTask = TASK_GetCurrent())) return;
-
-    /* Note: we need to trust that BX/CX contain the stack/heap sizes,
-       as some apps, notably Visual Basic apps, *modify* the heap/stack
-       size of the instance data segment before calling InitTask() */
-
-    /* Initialize the INSTANCEDATA structure */
-    pinstance = MapSL( MAKESEGPTR(CURRENT_DS, 0) );
-    pinstance->stackmin    = OFFSETOF( pTask->teb->cur_stack ) + sizeof( STACK16FRAME );
-    pinstance->stackbottom = pinstance->stackmin; /* yup, that's right. Confused me too. */
-    pinstance->stacktop    = ( pinstance->stackmin > LOWORD(context->Ebx) ?
-                               pinstance->stackmin - LOWORD(context->Ebx) : 0 ) + 150;
-
-    /* Initialize the local heap */
-    if (LOWORD(context->Ecx))
-        LocalInit16( GlobalHandleToSel16(pTask->hInstance), 0, LOWORD(context->Ecx) );
-
-    /* Initialize implicitly loaded DLLs */
-    NE_InitializeDLLs( pTask->hModule );
-    NE_DllProcessAttach( pTask->hModule );
-
-    /* Registers on return are:
-     * ax     1 if OK, 0 on error
-     * cx     stack limit in bytes
-     * dx     cmdShow parameter
-     * si     instance handle of the previous instance
-     * di     instance handle of the new task
-     * es:bx  pointer to command line inside PSP
-     *
-     * 0 (=%bp) is pushed on the stack
-     */
-    ptr = stack16_push( sizeof(WORD) );
-    *(WORD *)MapSL(ptr) = 0;
-    context->Esp -= 2;
-
-    context->Eax = 1;
-
-    if (!pTask->pdb.cmdLine[0]) context->Ebx = 0x80;
-    else
-    {
-        LPBYTE p = &pTask->pdb.cmdLine[1];
-        while ((*p == ' ') || (*p == '\t')) p++;
-        context->Ebx = 0x80 + (p - pTask->pdb.cmdLine);
-    }
-    context->Ecx   = pinstance->stacktop;
-    context->Edx   = pTask->nCmdShow;
-    context->Esi   = (DWORD)pTask->hPrevInstance;
-    context->Edi   = (DWORD)pTask->hInstance;
-    context->SegEs = (WORD)pTask->hPDB;
-}
-
-
-/***********************************************************************
- *           WaitEvent  (KERNEL.30)
- */
-BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
-{
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    pTask = TASK_GetPtr( hTask );
-
-    if (pTask->flags & TDBF_WIN32)
-    {
-        FIXME("called for Win32 thread (%04x)!\n", NtCurrentTeb()->teb_sel);
-        return TRUE;
-    }
-
-    if (pTask->nEvents > 0)
-    {
-        pTask->nEvents--;
-        return FALSE;
-    }
-
-    if (pTask->teb == NtCurrentTeb())
-    {
-        DWORD lockCount;
-
-        NtResetEvent( pTask->hEvent, NULL );
-        ReleaseThunkLock( &lockCount );
-        SYSLEVEL_CheckNotLevel( 1 );
-        WaitForSingleObject( pTask->hEvent, INFINITE );
-        RestoreThunkLock( lockCount );
-        if (pTask->nEvents > 0) pTask->nEvents--;
-    }
-    else FIXME("for other task %04x cur=%04x\n",pTask->hSelf,GetCurrentTask());
-
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           PostEvent  (KERNEL.31)
  */
 void WINAPI PostEvent16( HTASK16 hTask )
@@ -660,47 +101,6 @@
 
 
 /***********************************************************************
- *           SetPriority  (KERNEL.32)
- */
-void WINAPI SetPriority16( HTASK16 hTask, INT16 delta )
-{
-    TDB *pTask;
-    INT16 newpriority;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return;
-    newpriority = pTask->priority + delta;
-    if (newpriority < -32) newpriority = -32;
-    else if (newpriority > 15) newpriority = 15;
-
-    pTask->priority = newpriority + 1;
-    TASK_UnlinkTask( pTask->hSelf );
-    TASK_LinkTask( pTask->hSelf );
-    pTask->priority--;
-}
-
-
-/***********************************************************************
- *           LockCurrentTask  (KERNEL.33)
- */
-HTASK16 WINAPI LockCurrentTask16( BOOL16 bLock )
-{
-    if (bLock) hLockedTask = GetCurrentTask();
-    else hLockedTask = 0;
-    return hLockedTask;
-}
-
-
-/***********************************************************************
- *           IsTaskLocked  (KERNEL.122)
- */
-HTASK16 WINAPI IsTaskLocked16(void)
-{
-    return hLockedTask;
-}
-
-
-/***********************************************************************
  *           OldYield  (KERNEL.117)
  */
 void WINAPI OldYield16(void)
@@ -712,461 +112,14 @@
 }
 
 /***********************************************************************
- *           WIN32_OldYield  (KERNEL.447)
- */
-void WINAPI WIN32_OldYield16(void)
-{
-   DWORD count;
-
-   ReleaseThunkLock(&count);
-   RestoreThunkLock(count);
-}
-
-/***********************************************************************
  *           DirectedYield  (KERNEL.150)
  */
 void WINAPI DirectedYield16( HTASK16 hTask )
 {
-    TDB *pCurTask = TASK_GetCurrent();
-
-    if (!pCurTask || (pCurTask->flags & TDBF_WIN32)) OldYield16();
-    else
-    {
-        TRACE("%04x: DirectedYield(%04x)\n", pCurTask->hSelf, hTask );
-        pCurTask->hYieldTo = hTask;
-        OldYield16();
-        TRACE("%04x: back from DirectedYield(%04x)\n", pCurTask->hSelf, hTask );
-    }
-}
-
-/***********************************************************************
- *           Yield  (KERNEL.29)
- */
-void WINAPI Yield16(void)
-{
-    TDB *pCurTask = TASK_GetCurrent();
-
-    if (pCurTask) pCurTask->hYieldTo = 0;
-    if (pCurTask && pCurTask->hQueue)
-    {
-        HMODULE mod = GetModuleHandleA( "user32.dll" );
-        if (mod)
-        {
-            FARPROC proc = GetProcAddress( mod, "UserYield16" );
-            if (proc)
-            {
-                proc();
-                return;
-            }
-        }
-    }
     OldYield16();
 }
 
 /***********************************************************************
- *           KERNEL_490  (KERNEL.490)
- */
-HTASK16 WINAPI KERNEL_490( HTASK16 someTask )
-{
-    if ( !someTask ) return 0;
-
-    FIXME("(%04x): stub\n", someTask );
-    return 0;
-}
-
-/***********************************************************************
- *           MakeProcInstance  (KERNEL.51)
- */
-FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
-{
-    BYTE *thunk,*lfunc;
-    SEGPTR thunkaddr;
-    WORD hInstanceSelector;
-
-    hInstanceSelector = GlobalHandleToSel16(hInstance);
-
-    TRACE("(%08lx, %04x);\n", (DWORD)func, hInstance);
-
-    if (!HIWORD(func)) {
-      /* Win95 actually protects via SEH, but this is better for debugging */
-      WARN("Ouch ! Called with invalid func 0x%08lx !\n", (DWORD)func);
-      return (FARPROC16)0;
-    }
-
-    if ( (GlobalHandleToSel16(CURRENT_DS) != hInstanceSelector)
-      && (hInstance != 0)
-      && (hInstance != 0xffff) )
-    {
-	/* calling MPI with a foreign DSEG is invalid ! */
-        WARN("Problem with hInstance? Got %04x, using %04x instead\n",
-                   hInstance,CURRENT_DS);
-    }
-
-    /* Always use the DSEG that MPI was entered with.
-     * We used to set hInstance to GetTaskDS16(), but this should be wrong
-     * as CURRENT_DS provides the DSEG value we need.
-     * ("calling" DS, *not* "task" DS !) */
-    hInstanceSelector = CURRENT_DS;
-    hInstance = GlobalHandle16(hInstanceSelector);
-
-    /* no thunking for DLLs */
-    if (NE_GetPtr(FarGetOwner16(hInstance))->flags & NE_FFLAGS_LIBMODULE)
-	return func;
-
-    thunkaddr = TASK_AllocThunk();
-    if (!thunkaddr) return (FARPROC16)0;
-    thunk = MapSL( thunkaddr );
-    lfunc = MapSL( (SEGPTR)func );
-
-    TRACE("(%08lx,%04x): got thunk %08lx\n",
-          (DWORD)func, hInstance, (DWORD)thunkaddr );
-    if (((lfunc[0]==0x8c) && (lfunc[1]==0xd8)) || /* movw %ds, %ax */
-    	((lfunc[0]==0x1e) && (lfunc[1]==0x58))    /* pushw %ds, popw %ax */
-    ) {
-    	WARN("This was the (in)famous \"thunk useless\" warning. We thought we have to overwrite with nop;nop;, but this isn't true.\n");
-    }
-
-    *thunk++ = 0xb8;    /* movw instance, %ax */
-    *thunk++ = (BYTE)(hInstanceSelector & 0xff);
-    *thunk++ = (BYTE)(hInstanceSelector >> 8);
-    *thunk++ = 0xea;    /* ljmp func */
-    *(DWORD *)thunk = (DWORD)func;
-    return (FARPROC16)thunkaddr;
-    /* CX reg indicates if thunkaddr != NULL, implement if needed */
-}
-
-
-/***********************************************************************
- *           FreeProcInstance  (KERNEL.52)
- */
-void WINAPI FreeProcInstance16( FARPROC16 func )
-{
-    TRACE("(%08lx)\n", (DWORD)func );
-    TASK_FreeThunk( (SEGPTR)func );
-}
-
-/**********************************************************************
- *	    TASK_GetCodeSegment
- *
- * Helper function for GetCodeHandle/GetCodeInfo: Retrieve the module
- * and logical segment number of a given code segment.
- *
- * 'proc' either *is* already a pair of module handle and segment number,
- * in which case there's nothing to do.  Otherwise, it is a pointer to
- * a function, and we need to retrieve the code segment.  If the pointer
- * happens to point to a thunk, we'll retrieve info about the code segment
- * where the function pointed to by the thunk resides, not the thunk itself.
- *
- * FIXME: if 'proc' is a SNOOP16 return stub, we should retrieve info about
- *        the function the snoop code will return to ...
- *
- */
-static BOOL TASK_GetCodeSegment( FARPROC16 proc, NE_MODULE **ppModule,
-                                 SEGTABLEENTRY **ppSeg, int *pSegNr )
-{
-    NE_MODULE *pModule = NULL;
-    SEGTABLEENTRY *pSeg = NULL;
-    int segNr=0;
-
-    /* Try pair of module handle / segment number */
-    pModule = (NE_MODULE *) GlobalLock16( HIWORD( proc ) );
-    if ( pModule && pModule->magic == IMAGE_OS2_SIGNATURE )
-    {
-        segNr = LOWORD( proc );
-        if ( segNr && segNr <= pModule->seg_count )
-            pSeg = NE_SEG_TABLE( pModule ) + segNr-1;
-    }
-
-    /* Try thunk or function */
-    else
-    {
-        BYTE *thunk = MapSL( (SEGPTR)proc );
-        WORD selector;
-
-        if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
-            selector = thunk[6] + (thunk[7] << 8);
-        else
-            selector = HIWORD( proc );
-
-        pModule = NE_GetPtr( GlobalHandle16( selector ) );
-        pSeg = pModule? NE_SEG_TABLE( pModule ) : NULL;
-
-        if ( pModule )
-            for ( segNr = 1; segNr <= pModule->seg_count; segNr++, pSeg++ )
-                if ( GlobalHandleToSel16(pSeg->hSeg) == selector )
-                    break;
-
-        if ( pModule && segNr > pModule->seg_count )
-            pSeg = NULL;
-    }
-
-    /* Abort if segment not found */
-
-    if ( !pModule || !pSeg )
-        return FALSE;
-
-    /* Return segment data */
-
-    if ( ppModule ) *ppModule = pModule;
-    if ( ppSeg    ) *ppSeg    = pSeg;
-    if ( pSegNr   ) *pSegNr   = segNr;
-
-    return TRUE;
-}
-
-/**********************************************************************
- *	    GetCodeHandle    (KERNEL.93)
- */
-HANDLE16 WINAPI GetCodeHandle16( FARPROC16 proc )
-{
-    SEGTABLEENTRY *pSeg;
-
-    if ( !TASK_GetCodeSegment( proc, NULL, &pSeg, NULL ) )
-        return (HANDLE16)0;
-
-    return pSeg->hSeg;
-}
-
-/**********************************************************************
- *	    GetCodeInfo    (KERNEL.104)
- */
-BOOL16 WINAPI GetCodeInfo16( FARPROC16 proc, SEGINFO *segInfo )
-{
-    NE_MODULE *pModule;
-    SEGTABLEENTRY *pSeg;
-    int segNr;
-
-    if ( !TASK_GetCodeSegment( proc, &pModule, &pSeg, &segNr ) )
-        return FALSE;
-
-    /* Fill in segment information */
-
-    segInfo->offSegment = pSeg->filepos;
-    segInfo->cbSegment  = pSeg->size;
-    segInfo->flags      = pSeg->flags;
-    segInfo->cbAlloc    = pSeg->minsize;
-    segInfo->h          = pSeg->hSeg;
-    segInfo->alignShift = pModule->alignment;
-
-    if ( segNr == pModule->dgroup )
-        segInfo->cbAlloc += pModule->heap_size + pModule->stack_size;
-
-    /* Return module handle in %es */
-
-    CURRENT_STACK16->es = GlobalHandleToSel16( pModule->self );
-
-    return TRUE;
-}
-
-
-/**********************************************************************
- *          DefineHandleTable    (KERNEL.94)
- */
-BOOL16 WINAPI DefineHandleTable16( WORD wOffset )
-{
-    FIXME("(%04x): stub ?\n", wOffset);
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           SetTaskQueue  (KERNEL.34)
- */
-HQUEUE16 WINAPI SetTaskQueue16( HTASK16 hTask, HQUEUE16 hQueue )
-{
-    HQUEUE16 hPrev;
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
-
-    hPrev = pTask->hQueue;
-    pTask->hQueue = hQueue;
-
-    return hPrev;
-}
-
-
-/***********************************************************************
- *           GetTaskQueue  (KERNEL.35)
- */
-HQUEUE16 WINAPI GetTaskQueue16( HTASK16 hTask )
-{
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
-    return pTask->hQueue;
-}
-
-/***********************************************************************
- *           SetThreadQueue  (KERNEL.463)
- */
-HQUEUE16 WINAPI SetThreadQueue16( DWORD thread, HQUEUE16 hQueue )
-{
-    TEB *teb = thread? THREAD_IdToTEB( thread ) : NtCurrentTeb();
-    HQUEUE16 oldQueue = teb? teb->queue : 0;
-
-    if ( teb )
-    {
-        teb->queue = hQueue;
-
-        if ( GetTaskQueue16( teb->htask16 ) == oldQueue )
-            SetTaskQueue16( teb->htask16, hQueue );
-    }
-
-    return oldQueue;
-}
-
-/***********************************************************************
- *           GetThreadQueue  (KERNEL.464)
- */
-HQUEUE16 WINAPI GetThreadQueue16( DWORD thread )
-{
-    TEB *teb = NULL;
-    if ( !thread )
-        teb = NtCurrentTeb();
-    else if ( HIWORD(thread) )
-        teb = THREAD_IdToTEB( thread );
-    else if ( IsTask16( (HTASK16)thread ) )
-        teb = (TASK_GetPtr( (HANDLE16)thread ))->teb;
-
-    return (HQUEUE16)(teb? teb->queue : 0);
-}
-
-/***********************************************************************
- *           SetFastQueue  (KERNEL.624)
- */
-VOID WINAPI SetFastQueue16( DWORD thread, HQUEUE16 hQueue )
-{
-    TEB *teb = NULL;
-    if ( !thread )
-        teb = NtCurrentTeb();
-    else if ( HIWORD(thread) )
-        teb = THREAD_IdToTEB( thread );
-    else if ( IsTask16( (HTASK16)thread ) )
-        teb = (TASK_GetPtr( (HANDLE16)thread ))->teb;
-
-    if ( teb ) teb->queue = hQueue;
-}
-
-/***********************************************************************
- *           GetFastQueue  (KERNEL.625)
- */
-HQUEUE16 WINAPI GetFastQueue16( void )
-{
-    HQUEUE16 ret = NtCurrentTeb()->queue;
-
-    if (!ret) FIXME("(): should initialize thread-local queue, expect failure!\n" );
-    return ret;
-}
-
-/***********************************************************************
- *           SwitchStackTo   (KERNEL.108)
- */
-void WINAPI SwitchStackTo16( WORD seg, WORD ptr, WORD top )
-{
-    TDB *pTask;
-    STACK16FRAME *oldFrame, *newFrame;
-    INSTANCEDATA *pData;
-    UINT16 copySize;
-
-    if (!(pTask = TASK_GetCurrent())) return;
-    if (!(pData = (INSTANCEDATA *)GlobalLock16( seg ))) return;
-    TRACE("old=%04x:%04x new=%04x:%04x\n",
-          SELECTOROF( pTask->teb->cur_stack ),
-          OFFSETOF( pTask->teb->cur_stack ), seg, ptr );
-
-    /* Save the old stack */
-
-    oldFrame = THREAD_STACK16( pTask->teb );
-    /* pop frame + args and push bp */
-    pData->old_ss_sp   = pTask->teb->cur_stack + sizeof(STACK16FRAME)
-                           + 2 * sizeof(WORD);
-    *(WORD *)MapSL(pData->old_ss_sp) = oldFrame->bp;
-    pData->stacktop    = top;
-    pData->stackmin    = ptr;
-    pData->stackbottom = ptr;
-
-    /* Switch to the new stack */
-
-    /* Note: we need to take the 3 arguments into account; otherwise,
-     * the stack will underflow upon return from this function.
-     */
-    copySize = oldFrame->bp - OFFSETOF(pData->old_ss_sp);
-    copySize += 3 * sizeof(WORD) + sizeof(STACK16FRAME);
-    pTask->teb->cur_stack = MAKESEGPTR( seg, ptr - copySize );
-    newFrame = THREAD_STACK16( pTask->teb );
-
-    /* Copy the stack frame and the local variables to the new stack */
-
-    memmove( newFrame, oldFrame, copySize );
-    newFrame->bp = ptr;
-    *(WORD *)MapSL( MAKESEGPTR( seg, ptr ) ) = 0;  /* clear previous bp */
-}
-
-
-/***********************************************************************
- *           SwitchStackBack   (KERNEL.109)
- */
-void WINAPI SwitchStackBack16( CONTEXT86 *context )
-{
-    STACK16FRAME *oldFrame, *newFrame;
-    INSTANCEDATA *pData;
-
-    if (!(pData = (INSTANCEDATA *)GlobalLock16(SELECTOROF(NtCurrentTeb()->cur_stack))))
-        return;
-    if (!pData->old_ss_sp)
-    {
-        WARN("No previous SwitchStackTo\n" );
-        return;
-    }
-    TRACE("restoring stack %04x:%04x\n",
-          SELECTOROF(pData->old_ss_sp), OFFSETOF(pData->old_ss_sp) );
-
-    oldFrame = CURRENT_STACK16;
-
-    /* Pop bp from the previous stack */
-
-    context->Ebp = (context->Ebp & ~0xffff) | *(WORD *)MapSL(pData->old_ss_sp);
-    pData->old_ss_sp += sizeof(WORD);
-
-    /* Switch back to the old stack */
-
-    NtCurrentTeb()->cur_stack = pData->old_ss_sp - sizeof(STACK16FRAME);
-    context->SegSs = SELECTOROF(pData->old_ss_sp);
-    context->Esp   = OFFSETOF(pData->old_ss_sp) - sizeof(DWORD); /*ret addr*/
-    pData->old_ss_sp = 0;
-
-    /* Build a stack frame for the return */
-
-    newFrame = CURRENT_STACK16;
-    newFrame->frame32     = oldFrame->frame32;
-    newFrame->module_cs   = oldFrame->module_cs;
-    newFrame->callfrom_ip = oldFrame->callfrom_ip;
-    newFrame->entry_ip    = oldFrame->entry_ip;
-}
-
-
-/***********************************************************************
- *           GetTaskQueueDS  (KERNEL.118)
- */
-void WINAPI GetTaskQueueDS16(void)
-{
-    CURRENT_STACK16->ds = GlobalHandleToSel16( GetTaskQueue16(0) );
-}
-
-
-/***********************************************************************
- *           GetTaskQueueES  (KERNEL.119)
- */
-void WINAPI GetTaskQueueES16(void)
-{
-    CURRENT_STACK16->es = GlobalHandleToSel16( GetTaskQueue16(0) );
-}
-
-
-/***********************************************************************
  *           GetCurrentTask   (KERNEL32.@)
  */
 HTASK16 WINAPI GetCurrentTask(void)
@@ -1175,17 +128,6 @@
 }
 
 /***********************************************************************
- *           GetCurrentTask   (KERNEL.36)
- */
-DWORD WINAPI WIN16_GetCurrentTask(void)
-{
-    /* This is the version used by relay code; the first task is */
-    /* returned in the high word of the result */
-    return MAKELONG( GetCurrentTask(), hFirstTask );
-}
-
-
-/***********************************************************************
  *           GetCurrentPDB   (KERNEL.37)
  *
  * UNDOC: returns PSP of KERNEL in high word
@@ -1200,183 +142,6 @@
 
 
 /***********************************************************************
- *           GetCurPID   (KERNEL.157)
- */
-DWORD WINAPI GetCurPID16( DWORD unused )
-{
-    return 0;
-}
-
-
-/***********************************************************************
- *           GetInstanceData   (KERNEL.54)
- */
-INT16 WINAPI GetInstanceData16( HINSTANCE16 instance, WORD buffer, INT16 len )
-{
-    char *ptr = (char *)GlobalLock16( instance );
-    if (!ptr || !len) return 0;
-    if ((int)buffer + len >= 0x10000) len = 0x10000 - buffer;
-    memcpy( (char *)GlobalLock16(CURRENT_DS) + buffer, ptr + buffer, len );
-    return len;
-}
-
-
-/***********************************************************************
- *           GetExeVersion   (KERNEL.105)
- */
-WORD WINAPI GetExeVersion16(void)
-{
-    TDB *pTask;
-
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    return pTask->version;
-}
-
-
-/***********************************************************************
- *           SetErrorMode   (KERNEL.107)
- */
-UINT16 WINAPI SetErrorMode16( UINT16 mode )
-{
-    TDB *pTask;
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    pTask->error_mode = mode;
-    return SetErrorMode( mode );
-}
-
-
-/***********************************************************************
- *           GetNumTasks   (KERNEL.152)
- */
-UINT16 WINAPI GetNumTasks16(void)
-{
-    return nTaskCount;
-}
-
-
-/***********************************************************************
- *           GetTaskDS   (KERNEL.155)
- *
- * Note: this function apparently returns a DWORD with LOWORD == HIWORD.
- * I don't think we need to bother with this.
- */
-HINSTANCE16 WINAPI GetTaskDS16(void)
-{
-    TDB *pTask;
-
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    return GlobalHandleToSel16(pTask->hInstance);
-}
-
-/***********************************************************************
- *           GetDummyModuleHandleDS   (KERNEL.602)
- */
-WORD WINAPI GetDummyModuleHandleDS16(void)
-{
-    TDB *pTask;
-    WORD selector;
-
-    if (!(pTask = TASK_GetCurrent())) return 0;
-    if (!(pTask->flags & TDBF_WIN32)) return 0;
-    selector = GlobalHandleToSel16( pTask->hModule );
-    CURRENT_DS = selector;
-    return selector;
-}
-
-/***********************************************************************
- *           IsTask   (KERNEL.320)
- */
-BOOL16 WINAPI IsTask16( HTASK16 hTask )
-{
-    TDB *pTask;
-
-    if (!(pTask = TASK_GetPtr( hTask ))) return FALSE;
-    if (GlobalSize16( hTask ) < sizeof(TDB)) return FALSE;
-    return (pTask->magic == TDB_MAGIC);
-}
-
-
-/***********************************************************************
- *           IsWinOldApTask   (KERNEL.158)
- */
-BOOL16 WINAPI IsWinOldApTask16( HTASK16 hTask )
-{
-    /* should return bit 0 of byte 0x48 in PSP */
-    return FALSE;
-}
-
-/***********************************************************************
- *           SetTaskSignalProc   (KERNEL.38)
- */
-FARPROC16 WINAPI SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
-{
-    TDB *pTask;
-    FARPROC16 oldProc;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return NULL;
-    oldProc = pTask->userhandler;
-    pTask->userhandler = proc;
-    return oldProc;
-}
-
-/***********************************************************************
- *           TASK_CallTaskSignalProc
- */
-/* ### start build ### */
-extern WORD CALLBACK TASK_CallTo16_word_wwwww(FARPROC16,WORD,WORD,WORD,WORD,WORD);
-/* ### stop build ### */
-void TASK_CallTaskSignalProc( UINT16 uCode, HANDLE16 hTaskOrModule )
-{
-    TDB *pTask = TASK_GetCurrent();
-    if ( !pTask || !pTask->userhandler ) return;
-
-    TASK_CallTo16_word_wwwww( pTask->userhandler,
-                              hTaskOrModule, uCode, 0,
-                              pTask->hInstance, pTask->hQueue );
-}
-
-/***********************************************************************
- *           SetSigHandler   (KERNEL.140)
- */
-WORD WINAPI SetSigHandler16( FARPROC16 newhandler, FARPROC16* oldhandler,
-                           UINT16 *oldmode, UINT16 newmode, UINT16 flag )
-{
-    FIXME("(%p,%p,%p,%d,%d), unimplemented.\n",
-	  newhandler,oldhandler,oldmode,newmode,flag );
-
-    if (flag != 1) return 0;
-    if (!newmode) newhandler = NULL;  /* Default handler */
-    if (newmode != 4)
-    {
-        TDB *pTask;
-
-        if (!(pTask = TASK_GetCurrent())) return 0;
-        if (oldmode) *oldmode = pTask->signal_flags;
-        pTask->signal_flags = newmode;
-        if (oldhandler) *oldhandler = pTask->sighandler;
-        pTask->sighandler = newhandler;
-    }
-    return 0;
-}
-
-
-/***********************************************************************
- *           GlobalNotify   (KERNEL.154)
- *
- * Note that GlobalNotify does _not_ return the old NotifyProc
- * -- contrary to LocalNotify !!
- */
-VOID WINAPI GlobalNotify16( FARPROC16 proc )
-{
-    TDB *pTask;
-
-    if (!(pTask = TASK_GetCurrent())) return;
-    pTask->discardhandler = proc;
-}
-
-
-/***********************************************************************
  *           GetExePtrHelper
  */
 static inline HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask )
@@ -1446,136 +211,3 @@
     HTASK16 hTask = 0;
     return GetExePtrHelper( handle, &hTask );
 }
-
-
-/***********************************************************************
- *           TaskFirst   (TOOLHELP.63)
- */
-BOOL16 WINAPI TaskFirst16( TASKENTRY *lpte )
-{
-    lpte->hNext = hFirstTask;
-    return TaskNext16( lpte );
-}
-
-
-/***********************************************************************
- *           TaskNext   (TOOLHELP.64)
- */
-BOOL16 WINAPI TaskNext16( TASKENTRY *lpte )
-{
-    TDB *pTask;
-    INSTANCEDATA *pInstData;
-
-    TRACE_(toolhelp)("(%p): task=%04x\n", lpte, lpte->hNext );
-    if (!lpte->hNext) return FALSE;
-
-    /* make sure that task and hInstance are valid (skip initial Wine task !) */
-    while (1) {
-        pTask = TASK_GetPtr( lpte->hNext );
-        if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
-        if (pTask->hInstance)
-            break;
-        lpte->hNext = pTask->hNext;
-    }
-    pInstData = MapSL( MAKESEGPTR( GlobalHandleToSel16(pTask->hInstance), 0 ) );
-    lpte->hTask         = lpte->hNext;
-    lpte->hTaskParent   = pTask->hParent;
-    lpte->hInst         = pTask->hInstance;
-    lpte->hModule       = pTask->hModule;
-    lpte->wSS           = SELECTOROF( pTask->teb->cur_stack );
-    lpte->wSP           = OFFSETOF( pTask->teb->cur_stack );
-    lpte->wStackTop     = pInstData->stacktop;
-    lpte->wStackMinimum = pInstData->stackmin;
-    lpte->wStackBottom  = pInstData->stackbottom;
-    lpte->wcEvents      = pTask->nEvents;
-    lpte->hQueue        = pTask->hQueue;
-    lstrcpynA( lpte->szModule, pTask->module_name, sizeof(lpte->szModule) );
-    lpte->wPSPOffset    = 0x100;  /*??*/
-    lpte->hNext         = pTask->hNext;
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           TaskFindHandle   (TOOLHELP.65)
- */
-BOOL16 WINAPI TaskFindHandle16( TASKENTRY *lpte, HTASK16 hTask )
-{
-    lpte->hNext = hTask;
-    return TaskNext16( lpte );
-}
-
-
-typedef INT (WINAPI *MessageBoxA_funcptr)(HWND hWnd, LPCSTR text, LPCSTR title, UINT type);
-
-/**************************************************************************
- *           FatalAppExit   (KERNEL.137)
- */
-void WINAPI FatalAppExit16( UINT16 action, LPCSTR str )
-{
-    TDB *pTask = TASK_GetCurrent();
-
-    if (!pTask || !(pTask->error_mode & SEM_NOGPFAULTERRORBOX))
-    {
-        HMODULE mod = GetModuleHandleA( "user32.dll" );
-        if (mod)
-        {
-            MessageBoxA_funcptr pMessageBoxA = (MessageBoxA_funcptr)GetProcAddress( mod, "MessageBoxA" );
-            if (pMessageBoxA)
-            {
-                pMessageBoxA( 0, str, NULL, MB_SYSTEMMODAL | MB_OK );
-                goto done;
-            }
-        }
-        ERR( "%s\n", debugstr_a(str) );
-    }
- done:
-    ExitThread(0xff);
-}
-
-
-/***********************************************************************
- *           TerminateApp   (TOOLHELP.77)
- *
- * See "Undocumented Windows".
- */
-void WINAPI TerminateApp16(HTASK16 hTask, WORD wFlags)
-{
-    if (hTask && hTask != GetCurrentTask())
-    {
-        FIXME("cannot terminate task %x\n", hTask);
-        return;
-    }
-
-    if (wFlags & NO_UAE_BOX)
-    {
-        UINT16 old_mode;
-        old_mode = SetErrorMode16(0);
-        SetErrorMode16(old_mode|SEM_NOGPFAULTERRORBOX);
-    }
-    FatalAppExit16( 0, NULL );
-
-    /* hmm, we're still alive ?? */
-
-    /* check undocumented flag */
-    if (!(wFlags & 0x8000))
-        TASK_CallTaskSignalProc( USIG16_TERMINATION, hTask );
-
-    /* UndocWin says to call int 0x21/0x4c exit=0xff here,
-       but let's just call ExitThread */
-    ExitThread(0xff);
-}
-
-
-/***********************************************************************
- *           GetAppCompatFlags   (KERNEL.354)
- */
-DWORD WINAPI GetAppCompatFlags16( HTASK16 hTask )
-{
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask=TASK_GetPtr( hTask ))) return 0;
-    if (GlobalSize16(hTask) < sizeof(TDB)) return 0;
-    return pTask->compat_flags;
-}
diff --git a/msdos/int21.c b/msdos/int21.c
index 4ca3beb..f05b88c 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -148,7 +148,7 @@
 
 static BYTE *GetCurrentDTA( CONTEXT86 *context )
 {
-    TDB *pTask = TASK_GetCurrent();
+    TDB *pTask = GlobalLock16(GetCurrentTask());
 
     /* FIXME: This assumes DTA was set correctly! */
     return (BYTE *)CTX_SEG_OFF_TO_LIN( context, SELECTOROF(pTask->dta),
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 414a52d..81b2d6d 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -35,7 +35,6 @@
 #endif
 #include "wine/winbase16.h"
 #include "thread.h"
-#include "task.h"
 #include "module.h"
 #include "winerror.h"
 #include "selectors.h"
@@ -54,39 +53,6 @@
 extern struct _PDB current_process;
 
 /***********************************************************************
- *           THREAD_IdToTEB
- *
- * Convert a thread id to a TEB, making sure it is valid.
- */
-TEB *THREAD_IdToTEB( DWORD id )
-{
-    TEB *ret = NULL;
-
-    if (!id || id == GetCurrentThreadId()) return NtCurrentTeb();
-
-    SERVER_START_REQ( get_thread_info )
-    {
-        req->handle = 0;
-        req->tid_in = id;
-        if (!wine_server_call( req )) ret = reply->teb;
-    }
-    SERVER_END_REQ;
-
-    if (!ret)
-    {
-        /* Allow task handles to be used; convert to main thread */
-        if ( IsTask16( id ) )
-        {
-            TDB *pTask = TASK_GetPtr( id );
-            if (pTask) return pTask->teb;
-        }
-        SetLastError( ERROR_INVALID_PARAMETER );
-    }
-    return ret;
-}
-
-
-/***********************************************************************
  *           THREAD_InitTEB
  *
  * Initialization of a newly created TEB.
@@ -341,7 +307,6 @@
     else
     {
         LdrShutdownThread();
-        if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask();
         SYSDEPS_ExitThread( code );
     }
 }