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) */