Use the standard CreateThread routine to create 16-bit tasks instead
of duplicating the code.

diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c
index 36f6f8c..1cbd814 100644
--- a/dlls/kernel/kernel_main.c
+++ b/dlls/kernel/kernel_main.c
@@ -26,8 +26,6 @@
 static BOOL process_attach(void)
 {
     HMODULE16 hModule;
-    STARTUPINFOA startup_info;
-    UINT cmdShow = 1; /* SW_SHOWNORMAL but we don't want to include winuser.h here */
 
     /* Setup codepage info */
     CODEPAGE_Init();
@@ -83,11 +81,7 @@
     if (!DOSCONF_ReadConfig()) return FALSE;
 
     /* Create 16-bit task */
-    GetStartupInfoA( &startup_info );
-    if (startup_info.dwFlags & STARTF_USESHOWWINDOW) cmdShow = startup_info.wShowWindow;
-    if (!TASK_Create( (NE_MODULE *)GlobalLock16( MapHModuleLS(GetModuleHandleA(0)) ),
-                      cmdShow, NtCurrentTeb(), NULL, 0 ))
-        return FALSE;
+    TASK_CreateMainTask();
 
     return TRUE;
 }
diff --git a/include/module.h b/include/module.h
index 72683da..ed89987 100644
--- a/include/module.h
+++ b/include/module.h
@@ -186,6 +186,7 @@
 extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop );
 extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
 extern HANDLE NE_OpenFile( NE_MODULE *pModule );
+extern DWORD NE_StartTask(void);
 
 /* loader/ne/resource.c */
 extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16);
diff --git a/include/task.h b/include/task.h
index 7a6b725..5530947 100644
--- a/include/task.h
+++ b/include/task.h
@@ -145,8 +145,9 @@
 
 extern THHOOK *pThhook;
 
-extern BOOL TASK_Create( struct _NE_MODULE *pModule, UINT16 cmdShow,
-                         struct _TEB *teb, LPCSTR cmdline, BYTE len );
+extern void TASK_CreateMainTask(void);
+extern HTASK 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 void TASK_Reschedule(void);
diff --git a/include/thread.h b/include/thread.h
index faf7ba8..7d84170 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -125,8 +125,7 @@
 
 /* scheduler/thread.c */
 extern void THREAD_Init(void);
-extern TEB *THREAD_Create( int fd, DWORD stack_size, BOOL alloc_stack16 );
-extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 );
+extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
 extern BOOL THREAD_IsWin16( TEB *thdb );
 extern TEB *THREAD_IdToTEB( DWORD id );
 
diff --git a/loader/ne/module.c b/loader/ne/module.c
index 7985ec5..3914ca2 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -24,7 +24,6 @@
 #include "stackframe.h"
 #include "debugtools.h"
 #include "loadorder.h"
-#include "server.h"
 
 DEFAULT_DEBUG_CHANNEL(module);
 DECLARE_DEBUG_CHANNEL(loaddll);
@@ -46,7 +45,6 @@
 
 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
-static void NE_InitProcess(void) WINE_NORETURN;
 
 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
 
@@ -983,35 +981,13 @@
  */
 static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
 {
-    TEB *teb = NULL;
-    HANDLE hThread = 0;
-    int socket = -1;
-    HTASK hTask;
+    HANDLE hThread;
     TDB *pTask;
+    HTASK hTask;
     HINSTANCE16 instance = 0;
 
-    SERVER_START_REQ( new_thread )
-    {
-        req->suspend = 0;
-        req->inherit = 0;
-        if (!SERVER_CALL_ERR())
-        {
-            hThread = req->handle;
-            socket = wine_server_recv_fd( hThread, 0 );
-        }
-    }
-    SERVER_END_REQ;
-    if (!hThread) return 0;
-
-    if (!(teb = THREAD_Create( socket, 0, FALSE ))) goto error;
-    teb->tibflags &= ~TEBF_WIN32;
-    teb->startup = NE_InitProcess;
-
-    /* Create a task for this process */
-
-    if (!TASK_Create( pModule, cmdShow, teb, cmdline + 1, *cmdline )) goto error;
-    hTask = teb->htask16;
-    if (SYSDEPS_SpawnThread( teb ) == -1) goto error;
+    if (!(hTask = TASK_SpawnTask( pModule, cmdShow, cmdline + 1, *cmdline, &hThread )))
+        return 0;
 
     /* Post event to start the task */
     PostEvent16( hTask );
@@ -1033,13 +1009,8 @@
         GlobalUnlock16( hTask );
     } while (!instance);
 
-    return instance;
-
- error:
-    /* FIXME: free TEB and task */
-    close( socket );
     CloseHandle( hThread );
-    return 0;  /* FIXME */
+    return instance;
 }
 
 
@@ -1138,9 +1109,11 @@
 
 
 /**********************************************************************
- *          NE_InitProcess
+ *          NE_StartTask
+ *
+ * Startup code for a new 16-bit task.
  */
-static void NE_InitProcess(void)
+DWORD NE_StartTask(void)
 {
     TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
     NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
@@ -1148,8 +1121,6 @@
     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
     WORD sp;
 
-    _EnterWin16Lock();
-
     if ( pModule->count > 0 )
     {
         /* Second instance of an already loaded NE module */
@@ -1184,8 +1155,11 @@
         pTask->hInstance = hInstance;
         pTask->hPrevInstance = hPrevInstance;
 
+        /* Free the previous stack selector */
+        FreeSelector16( SELECTOROF(pTask->teb->cur_stack) );
+
         /* Use DGROUP for 16-bit stack */
- 
+
         if (!(sp = pModule->sp))
             sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
         sp &= ~1;
@@ -1224,9 +1198,7 @@
         wine_call_to_16_regs_short( &context, 0 );
         ExitThread( LOWORD(context.Eax) );
     }
-
-    _LeaveWin16Lock();
-    ExitThread( hInstance );
+    return hInstance;  /* error code */
 }
 
 /***********************************************************************
diff --git a/loader/task.c b/loader/task.c
index a9661c4..ac86874 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -218,7 +218,7 @@
  *       by entering the Win16Lock while linking the task into the
  *       global task list.
  */
-BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, BYTE len )
+static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, BYTE len )
 {
     HTASK16 hTask;
     TDB *pTask;
@@ -227,7 +227,7 @@
       /* Allocate the task structure */
 
     hTask = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB) );
-    if (!hTask) return FALSE;
+    if (!hTask) return NULL;
     pTask = (TDB *)GlobalLock16( hTask );
     FarSetOwner16( hTask, pModule->self );
 
@@ -235,7 +235,7 @@
 
     pTask->hSelf = hTask;
 
-    if (teb->tibflags & TEBF_WIN32)
+    if (teb && teb->tibflags & TEBF_WIN32)
     {
         pTask->flags        |= TDBF_WIN32;
         pTask->hInstance     = pModule->self;
@@ -323,20 +323,15 @@
     if ( !(pTask->flags & TDBF_WIN32) )
         NtCreateEvent( &pTask->hEvent, EVENT_ALL_ACCESS, NULL, TRUE, FALSE );
 
-    /* Enter task handle into thread and process */
+    /* Enter task handle into thread */
 
-    teb->htask16 = hTask;
+    if (teb) teb->htask16 = hTask;
     if (!initial_task) initial_task = hTask;
 
-    /* Add the task to the linked list */
-
-    _EnterWin16Lock();
-    TASK_LinkTask( hTask );
-    _LeaveWin16Lock();
-
-    return TRUE;
+    return pTask;
 }
 
+
 /***********************************************************************
  *           TASK_DeleteTask
  */
@@ -369,6 +364,70 @@
     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( (NE_MODULE *)GlobalLock16( MapHModuleLS(GetModuleHandleA(0)) ),
+                         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.
+ */
+HTASK 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_KillTask
  */
@@ -525,7 +584,7 @@
     {
         hNewTask = pOldTask->hYieldTo;
         pNewTask = (TDB *)GlobalLock16( hNewTask );
-        if( !pNewTask || !pNewTask->nEvents) hNewTask = 0;
+        if( !pNewTask || !pNewTask->nEvents || !pNewTask->teb) hNewTask = 0;
         pOldTask->hYieldTo = 0;
     }
 
diff --git a/scheduler/process.c b/scheduler/process.c
index e7e7428..482cedb 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -520,7 +520,7 @@
 
  found:
     /* allocate main thread stack */
-    if (!THREAD_InitStack( NtCurrentTeb(), stack_size, TRUE )) goto error;
+    if (!THREAD_InitStack( NtCurrentTeb(), stack_size )) goto error;
 
     /* switch to the new stack */
     SYSDEPS_SwitchToThreadStack( start_process );
@@ -540,7 +540,7 @@
     if (!process_init( argv )) exit(1);
 
     /* allocate main thread stack */
-    if (!THREAD_InitStack( NtCurrentTeb(), 0, TRUE )) ExitProcess( GetLastError() );
+    if (!THREAD_InitStack( NtCurrentTeb(), 0 )) ExitProcess( GetLastError() );
 
     /* switch to the new stack */
     SYSDEPS_SwitchToThreadStack( start_process );
diff --git a/scheduler/thread.c b/scheduler/thread.c
index f8424a2..77daaac 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -131,7 +131,7 @@
  *
  * Allocate the stack of a thread.
  */
-TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 )
+TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
 {
     DWORD old_prot, total_size;
     DWORD page_size = getpagesize();
@@ -169,7 +169,7 @@
 
     stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
     total_size = stack_size + SIGNAL_STACK_SIZE + 3 * page_size;
-    if (alloc_stack16) total_size += 0x10000;
+    total_size += 0x10000; /* 16-bit stack */
     if (!teb) total_size += page_size;
 
     if (!(base = VirtualAlloc( NULL, total_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
@@ -199,12 +199,10 @@
 
     /* Allocate the 16-bit stack selector */
 
-    if (alloc_stack16)
-    {
-        teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, WINE_LDT_FLAGS_DATA );
-        if (!teb->stack_sel) goto error;
-        teb->cur_stack = MAKESEGPTR( teb->stack_sel, 0x10000 - sizeof(STACK16FRAME) );
-    }
+    teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, WINE_LDT_FLAGS_DATA );
+    if (!teb->stack_sel) goto error;
+    teb->cur_stack = MAKESEGPTR( teb->stack_sel, 0x10000 - sizeof(STACK16FRAME) );
+
     return teb;
 
 error:
@@ -255,25 +253,6 @@
 
 DECL_GLOBAL_CONSTRUCTOR(thread_init) { THREAD_Init(); }
 
-/***********************************************************************
- *           THREAD_Create
- *
- */
-TEB *THREAD_Create( int fd, DWORD stack_size, BOOL alloc_stack16 )
-{
-    TEB *teb;
-
-    if ((teb = THREAD_InitStack( NULL, stack_size, alloc_stack16 )))
-    {
-        teb->tibflags = TEBF_WIN32;
-        teb->process  = NtCurrentTeb()->process;
-        teb->socket   = fd;
-        fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
-        TRACE("(%p) succeeded\n", teb);
-    }
-    return teb;
-}
-
 
 /***********************************************************************
  *           THREAD_Start
@@ -325,15 +304,20 @@
     SERVER_END_REQ;
     if (!handle) return 0;
 
-    if (!(teb = THREAD_Create( socket, stack, TRUE )))
+    if (!(teb = THREAD_InitStack( NULL, stack )))
     {
         close( socket );
         return 0;
     }
+
+    teb->process     = NtCurrentTeb()->process;
+    teb->socket      = socket;
     teb->entry_point = start;
     teb->entry_arg   = param;
     teb->startup     = THREAD_Start;
     teb->htask16     = GetCurrentTask();
+    fcntl( socket, F_SETFD, 1 ); /* set close on exec flag */
+
     if (id) *id = (DWORD)tid;
     if (SYSDEPS_SpawnThread( teb ) == -1)
     {