On NE process creation, move major part of NE EXE module loading and
NE instance creation into the child process.

diff --git a/include/module.h b/include/module.h
index dcfffc4..10e302e 100644
--- a/include/module.h
+++ b/include/module.h
@@ -202,11 +202,12 @@
 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 HINSTANCE16 MODULE_LoadModule16( LPCSTR name, BOOL implicit );
 extern BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env, 
                               LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
                               BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
                               LPPROCESS_INFORMATION info );
+extern BOOL NE_InitProcess( NE_MODULE *pModule );
+
 
 /* loader/ne/resource.c */
 extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16);
diff --git a/include/process.h b/include/process.h
index 85f0643..f628294 100644
--- a/include/process.h
+++ b/include/process.h
@@ -95,8 +95,6 @@
     HANDLE          *dos_handles;      /*    Handles mapping DOS -> Win32 */
     struct _PDB     *next;             /*    List reference - list of PDB's */
     WORD            winver;            /*    Windows version figured out by VERSION_GetVersion */
-    WORD            hInstance;         /*    hInstance on startup */
-    WORD            hPrevInstance;     /*    hPrevInstance on startup */
     struct _SERVICETABLE *service_table; /*  Service table for service thread */
 } PDB;
 
@@ -161,7 +159,6 @@
 extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule );
 extern PDB *PROCESS_Create( struct _NE_MODULE *pModule, 
                             LPCSTR cmd_line, LPCSTR env, 
-                            HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance, 
                             LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
                             BOOL inherit, DWORD flags,
                             STARTUPINFOA *startup, PROCESS_INFORMATION *info );
diff --git a/include/task.h b/include/task.h
index 0a82ebd..8f2fdf0 100644
--- a/include/task.h
+++ b/include/task.h
@@ -146,9 +146,7 @@
 extern THHOOK *pThhook;
 extern void (*TASK_AddTaskEntryBreakpoint)( HTASK16 hTask );
 
-extern BOOL TASK_Create( struct _NE_MODULE *pModule,
-                         HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
-                         UINT16 cmdShow );
+extern BOOL TASK_Create( struct _NE_MODULE *pModule, UINT16 cmdShow );
 extern void TASK_KillTask( HTASK16 hTask );
 extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
 extern void TASK_Reschedule(void);
diff --git a/loader/dos/module.c b/loader/dos/module.c
index 56ebf9d..630d67d 100644
--- a/loader/dos/module.c
+++ b/loader/dos/module.c
@@ -498,7 +498,7 @@
    return FALSE;
   }
   inherit = TRUE; /* bad hack for inheriting the CreatePipe... */
-  if (!PROCESS_Create( pModule, cmdline, env, 0, 0, 
+  if (!PROCESS_Create( pModule, cmdline, env, 
                        psa, tsa, inherit, flags, startup, info ))
    return FALSE;
  }
diff --git a/loader/main.c b/loader/main.c
index 8a1c1aa..a813f24 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -309,7 +309,7 @@
     pModule->flags = NE_FFLAGS_WIN32;
     pModule->module32 = wm->module;
 
-    if (!TASK_Create( pModule, 0, 0, FALSE )) return 0;
+    if (!TASK_Create( pModule, FALSE )) return 0;
 
     /* Initialize GDI and USER */
     if (!LoadLibraryA( "GDI32.DLL" )) return 0;
diff --git a/loader/ne/module.c b/loader/ne/module.c
index 827251a..675ea6c 100644
--- a/loader/ne/module.c
+++ b/loader/ne/module.c
@@ -45,6 +45,8 @@
 HMODULE16 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL force) = NE_LoadBuiltin;
 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
 
+static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
+
 /***********************************************************************
  *           NE_GetPtr
  */
@@ -758,7 +760,7 @@
             /* its handle in the list of DLLs to initialize.   */
             HMODULE16 hDLL;
 
-            if ((hDLL = MODULE_LoadModule16( buffer, TRUE )) < 32)
+            if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
             {
                 /* FIXME: cleanup what was done */
 
@@ -783,41 +785,34 @@
 
 
 /**********************************************************************
- *	    NE_LoadFileModule
+ *	    NE_DoLoadModule
  *
  * Load first instance of NE module from file.
- * (Note: caller is responsible for ensuring the module isn't
- *        already loaded!)
+ *
+ * pModule must point to a module structure prepared by NE_LoadExeHeader.
+ * This routine must never be called twice on a module.
+ *
  */
-static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs, 
-                                      BOOL implicit )
+static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
 {
     HINSTANCE16 hInstance;
-    HMODULE16 hModule;
-    NE_MODULE *pModule;
-
-    /* Create the module structure */
-
-    hModule = NE_LoadExeHeader( hFile, ofs );
-    if (hModule < 32) return hModule;
-    pModule = NE_GetPtr( hModule );
 
     /* Allocate the segments for this module */
 
     if (!NE_CreateSegments( pModule ) ||
         !(hInstance = NE_CreateInstance( pModule, NULL, FALSE )))
     {
-        GlobalFreeAll16( hModule );
+        GlobalFreeAll16( pModule->self );
         return 8;  /* Insufficient memory */
     }
 
     /* Load the referenced DLLs */
 
     if (!NE_LoadDLLs( pModule ))
-      {
-       NE_FreeModule(hModule,0);
+    {
+        NE_FreeModule( pModule->self, 0 );
         return 2;
-      }
+    }
 
     /* Load the segments */
 
@@ -838,14 +833,22 @@
 /**********************************************************************
  *	    NE_LoadModule
  *
- * Load first instance of NE module, deciding whether to use
- * built-in module or load module from file.
- * (Note: caller is responsible for ensuring the module isn't
- *        already loaded!)
+ * 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.
+ * 
  */
-HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit )
+HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit, BOOL lib_only )
 {
-    HINSTANCE16 hInstance;
+    NE_MODULE *pModule;
+    HMODULE16 hModule;
     HFILE16 hFile;
     OFSTRUCT ofs;
 
@@ -863,10 +866,17 @@
 	}
     }
 
-    hInstance = NE_LoadFileModule( hFile, &ofs, implicit );
+    hModule = NE_LoadExeHeader( hFile, &ofs );
     _lclose16( hFile );
 
-    return hInstance;
+    if (hModule < 32) return hModule;
+    pModule = NE_GetPtr( hModule );
+    if ( !pModule ) return hModule;
+
+    if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
+        return hModule;
+
+    return NE_DoLoadModule( pModule );
 }
 
 
@@ -877,7 +887,7 @@
  * The caller is responsible that the module is not loaded already.
  *
  */
-HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit )
+static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
 {
 	HINSTANCE16 hinst;
 	int i;
@@ -891,7 +901,7 @@
 		{
 		case MODULE_LOADORDER_DLL:
 			TRACE("Trying native dll '%s'\n", libname);
-			hinst = NE_LoadModule(libname, implicit);
+			hinst = NE_LoadModule(libname, implicit, lib_only);
 			break;
 
 		case MODULE_LOADORDER_ELFDLL:
@@ -970,7 +980,6 @@
     LPCVOID env = NULL;
     STARTUPINFOA startup;
     PROCESS_INFORMATION info;
-    HINSTANCE16 hInstance, hPrevInstance = 0;
     HMODULE16 hModule;
     NE_MODULE *pModule;
     PDB *pdb;
@@ -984,31 +993,46 @@
         if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
         if ( pModule->module32 ) return (HINSTANCE16)21;
 
-        hInstance = NE_CreateInstance( pModule, &hPrevInstance, lib_only );
-        if ( hInstance != hPrevInstance )  /* not a library */
-            NE_LoadSegment( pModule, pModule->dgroup );
+        /* Increment refcount */
 
         pModule->count++;
+
+        /* If library module, we just retrieve the instance handle */
+
+        if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
+            return NE_CreateInstance( pModule, NULL, TRUE );
     }
     else
     {
         /* Main case: load first instance of NE module */
 
-        if ( (hInstance = MODULE_LoadModule16( name, FALSE )) < 32 )
-            return hInstance;
+        if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
+            return hModule;
 
-        if ( !(pModule = NE_GetPtr( hInstance )) )
+        if ( !(pModule = NE_GetPtr( hModule )) )
             return (HINSTANCE16)11;
+
+        /* If library module, we're finished */
+
+        if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
+            return hModule;
     }
 
-    /* If library module, we're finished */
 
-    if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
-        return hInstance;
+    /*
+     *  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.
+     *
+     *  All remaining initialization (really loading the module in the second
+     *  case, and creating the new instance in both cases) are to be done in
+     *  the context of the new process. This happens in the NE_InitProcess
+     *  routine, which will be called from the 32-bit process initialization.
+     */
 
-    /* Create a task for this instance */
-
-    pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
 
     params = (LOADPARAMS16 *)paramBlock;
     cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
@@ -1035,7 +1059,6 @@
 
     SYSLEVEL_ReleaseWin16Lock();
     pdb = PROCESS_Create( pModule, new_cmd_line, env,
-                          hInstance, hPrevInstance, 
                           NULL, NULL, TRUE, 0, &startup, &info );
     SYSLEVEL_RestoreWin16Lock();
 
@@ -1044,22 +1067,24 @@
 
     if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
     HeapFree( GetProcessHeap(), 0, new_cmd_line );
-    return hInstance;
+
+    return GetProcessDword( info.dwProcessId, GPD_HINSTANCE16 );
 }
 
 /**********************************************************************
  *          NE_CreateProcess
  */
-BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env, 
+BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env,
                        LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
                        BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
                        LPPROCESS_INFORMATION info )
 {
-    HINSTANCE16 hInstance, hPrevInstance = 0;
     HMODULE16 hModule;
     NE_MODULE *pModule;
     HFILE16 hFile16;
 
+    SYSLEVEL_EnterWin16Lock();
+
     /* Special case: second instance of an already loaded NE module */
 
     if ( ( hModule = GetModuleHandle16( ofs->szPathName ) ) != 0 )
@@ -1069,13 +1094,9 @@
             ||  pModule->module32 )
         {
             SetLastError( ERROR_BAD_FORMAT );
-            return FALSE;
+            goto error;
         }
 
-        hInstance = NE_CreateInstance( pModule, &hPrevInstance, FALSE );
-        if ( hInstance != hPrevInstance )  /* not a library */
-            NE_LoadSegment( pModule, pModule->dgroup );
-
         pModule->count++;
     }
 
@@ -1085,7 +1106,7 @@
         /* If we didn't get a file handle, return */
 
         if ( hFile == HFILE_ERROR )
-            return FALSE;
+            goto error;
 
         /* Allocate temporary HFILE16 for NE_LoadFileModule */
 
@@ -1094,40 +1115,98 @@
                               0, FALSE, DUPLICATE_SAME_ACCESS ))
         {
             SetLastError( ERROR_INVALID_HANDLE );
-            return FALSE;
+            goto error;
         }
         hFile16 = FILE_AllocDosHandle( hFile );
 
         /* Load module */
 
-        hInstance = NE_LoadFileModule( hFile16, ofs, TRUE );
+        hModule = NE_LoadExeHeader( hFile16, ofs );
         _lclose16( hFile16 );
 
-        if ( hInstance < 32 )
+        if ( hModule < 32 )
         {
-            SetLastError( hInstance );
-            return FALSE;
+            SetLastError( hModule );
+            goto error;
         }
 
-        if (   !( pModule = NE_GetPtr( hInstance ) )
+        if (   !( pModule = NE_GetPtr( hModule ) )
             ||  ( pModule->flags & NE_FFLAGS_LIBMODULE) )
         {
-            /* FIXME: cleanup */
+            GlobalFreeAll16( hModule );
             SetLastError( ERROR_BAD_FORMAT );
-            return FALSE;
+            goto error;
         }
     }
 
-    /* Create a task for this instance */
-
-    pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
+    SYSLEVEL_LeaveWin16Lock();
 
     if ( !PROCESS_Create( pModule, cmd_line, env,
-                          hInstance, hPrevInstance, 
                           psa, tsa, inherit, flags, startup, info ) )
         return FALSE;
 
     return TRUE;
+
+ error:
+    SYSLEVEL_LeaveWin16Lock();
+    return FALSE;
+}
+
+/**********************************************************************
+ *          NE_InitProcess
+ */
+BOOL NE_InitProcess( NE_MODULE *pModule  )
+{
+    HINSTANCE16 hInstance, hPrevInstance;
+    BOOL retv = TRUE;
+
+    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
+    WORD sp;
+    TDB *pTask;
+
+    SYSLEVEL_EnterWin16Lock();
+
+    if ( pModule->count > 0 )
+    {
+        /* Second instance of an already loaded NE module */
+        /* Note that the refcount was already incremented by the parent */
+
+        hInstance = NE_CreateInstance( pModule, &hPrevInstance, FALSE );
+        if ( hInstance != hPrevInstance )  /* not a library */
+            NE_LoadSegment( pModule, pModule->dgroup );
+    }
+    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 )
+        {
+            SetLastError( hInstance );
+            retv = FALSE;
+        }
+    }
+
+    /* Enter instance handles into task struct */
+
+    pTask = (TDB *)GlobalLock16( GetCurrentTask() );
+    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 = PTR_SEG_OFF_TO_SEGPTR( hInstance, sp );
+ 
+    SYSLEVEL_LeaveWin16Lock();
+
+    return retv;
 }
 
 /***********************************************************************
diff --git a/loader/pe_image.c b/loader/pe_image.c
index c6f8907..36d16b4 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -984,7 +984,7 @@
 
     /* Create new process */
     if ( !PROCESS_Create( pModule, cmd_line, env,
-                          0, 0, psa, tsa, inherit, flags, startup, info ) )
+                          psa, tsa, inherit, flags, startup, info ) )
         return FALSE;
 
     /* Note: PE_CreateModule and the remaining process initialization will
diff --git a/loader/task.c b/loader/task.c
index 9ff7fed..c176e3e 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -275,16 +275,13 @@
  *       by entering the Win16Lock while linking the task into the
  *       global task list.
  */
-BOOL TASK_Create( NE_MODULE *pModule, HINSTANCE16 hInstance,
-                  HINSTANCE16 hPrevInstance, UINT16 cmdShow)
+BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow)
 {
     HTASK16 hTask;
     TDB *pTask;
     LPSTR cmd_line;
-    WORD sp;
     char name[10];
     PDB *pdb32 = PROCESS_Current();
-    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
 
       /* Allocate the task structure */
 
@@ -304,9 +301,12 @@
     if (pModule->lpDosTask)
     	pTask->flags 	|= TDBF_WINOLDAP;
 
+    pTask->hInstance     = pModule->self;
+    pTask->hPrevInstance = 0;
+    /* NOTE: for 16-bit tasks, the instance handles are updated later on
+             in NE_InitProcess */
+
     pTask->version       = pModule->expected_version;
-    pTask->hInstance     = hInstance? hInstance : pModule->self;
-    pTask->hPrevInstance = hPrevInstance;
     pTask->hModule       = pModule->self;
     pTask->hParent       = GetCurrentTask();
     pTask->magic         = TDB_MAGIC;
@@ -388,16 +388,6 @@
     pTask->teb->htask16 = pTask->teb->process->task = hTask;
     TRACE_(task)("module='%s' cmdline='%s' task=%04x\n", name, cmd_line, hTask );
 
-    /* If we have a DGROUP/hInstance, use it for 16-bit stack */
- 
-    if ( hInstance )
-    {
-        if (!(sp = pModule->sp))
-            sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
-        sp &= ~1;  sp -= sizeof(STACK16FRAME);
-        pTask->teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( hInstance, sp );
-    }
-
     /* If requested, add entry point breakpoint */
 
     if ( TASK_AddTaskEntryBreakpoint )
diff --git a/miscemu/main.c b/miscemu/main.c
index a4ce545..38953d2 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -168,7 +168,7 @@
 
     /* Create initial task */
     if ( !(pModule = NE_GetPtr( GetModuleHandle16( "KERNEL" ) )) ) return 1;
-    if ( !TASK_Create( pModule, 0, 0, FALSE ) ) return 1;
+    if ( !TASK_Create( pModule, FALSE ) ) return 1;
 
     /* Switch to initial task */
     PostEvent16( PROCESS_Current()->task );
diff --git a/scheduler/process.c b/scheduler/process.c
index 70cc709..f4c69e8 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -411,9 +411,14 @@
     /* Create a task for this process */
     if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
         cmdShow = pdb->env_db->startup_info->wShowWindow;
-    if (!TASK_Create( pModule, pdb->hInstance, pdb->hPrevInstance, cmdShow ))
+    if (!TASK_Create( pModule, cmdShow ))
         goto error;
 
+    /* Perform Win16 specific process initialization */
+    if ( type == PROC_WIN16 )
+        if ( !NE_InitProcess( pModule ) )
+            goto error;
+
     /* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the
      *       context of the parent process.  Actually, the USER signal proc
      *       doesn't really care about that, but it *does* require that the
@@ -502,13 +507,13 @@
  * Create a new process database and associated info.
  */
 PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
-                     HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
                      LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
                      BOOL inherit, DWORD flags, STARTUPINFOA *startup,
                      PROCESS_INFORMATION *info )
 {
     HANDLE handles[2], load_done_evt = INVALID_HANDLE_VALUE;
     DWORD exitcode, size;
+    BOOL alloc_stack16;
     int server_thandle;
     struct new_process_request *req = get_req_buffer();
     TEB *teb = NULL;
@@ -554,21 +559,24 @@
         size = header->SizeOfStackReserve;
         if (header->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) 
             pdb->flags |= PDB32_CONSOLE_PROC;
+        alloc_stack16 = TRUE;
     }
     else if (!pModule->dos_image) /* Win16 process */
     {
+        alloc_stack16 = FALSE;
         size = 0;
         pdb->flags |= PDB32_WIN16_PROC;
     }
     else  /* DOS process */
     {
+        alloc_stack16 = FALSE;
         size = 0;
         pdb->flags |= PDB32_DOS_PROC;
     }
 
     /* Create the main thread */
 
-    if (!(teb = THREAD_Create( pdb, 0L, size, hInstance == 0, tsa, &server_thandle ))) 
+    if (!(teb = THREAD_Create( pdb, 0L, size, alloc_stack16, tsa, &server_thandle ))) 
         goto error;
     info->hThread     = server_thandle;
     info->dwThreadId  = (DWORD)teb->tid;
@@ -579,10 +587,8 @@
     DuplicateHandle( GetCurrentProcess(), load_done_evt,
                      info->hProcess, &pdb->load_done_evt, 0, TRUE, DUPLICATE_SAME_ACCESS );
 
-    /* Pass module/instance to new process (FIXME: hack) */
+    /* Pass module to new process (FIXME: hack) */
     pdb->module = pModule->self;
-    pdb->hInstance = hInstance;
-    pdb->hPrevInstance = hPrevInstance;
     SYSDEPS_SpawnThread( teb );
 
     /* Wait until process is initialized (or initialization failed) */