Run Win32 processes in their own threads.
Process exit sequence adapted.
This commit is contained in:
parent
f016752b45
commit
93b23d746d
|
@ -150,6 +150,7 @@ extern BOOL TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
|
||||||
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
|
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
|
||||||
UINT16 cmdShow );
|
UINT16 cmdShow );
|
||||||
extern void TASK_StartTask( HTASK16 hTask );
|
extern void TASK_StartTask( HTASK16 hTask );
|
||||||
|
extern void TASK_KillTask( HTASK16 hTask );
|
||||||
extern void TASK_KillCurrentTask( INT16 exitCode );
|
extern void TASK_KillCurrentTask( INT16 exitCode );
|
||||||
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
|
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
|
||||||
extern BOOL TASK_Reschedule(void);
|
extern BOOL TASK_Reschedule(void);
|
||||||
|
|
183
loader/task.c
183
loader/task.c
|
@ -57,7 +57,7 @@ THHOOK *pThhook = &DefaultThhook;
|
||||||
static HTASK16 hTaskToKill = 0;
|
static HTASK16 hTaskToKill = 0;
|
||||||
static UINT16 nTaskCount = 0;
|
static UINT16 nTaskCount = 0;
|
||||||
|
|
||||||
static void TASK_YieldToSystem(TDB*);
|
static void TASK_YieldToSystem( void );
|
||||||
|
|
||||||
extern BOOL THREAD_InitDone;
|
extern BOOL THREAD_InitDone;
|
||||||
|
|
||||||
|
@ -240,49 +240,9 @@ static void TASK_CallToStart(void)
|
||||||
|
|
||||||
if (pModule->flags & NE_FFLAGS_WIN32)
|
if (pModule->flags & NE_FFLAGS_WIN32)
|
||||||
{
|
{
|
||||||
/* FIXME: all this is an ugly hack */
|
ERR( task, "Called for Win32 task!\n" );
|
||||||
|
|
||||||
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
|
|
||||||
LPTHREAD_START_ROUTINE entry = (LPTHREAD_START_ROUTINE)
|
|
||||||
RVA_PTR(pModule->module32, OptionalHeader.AddressOfEntryPoint);
|
|
||||||
|
|
||||||
/* Create 32-bit MODREF */
|
|
||||||
if ( !PE_CreateModule( pModule->module32, ofs, 0, FALSE ) )
|
|
||||||
{
|
|
||||||
ERR( task, "Could not initialize process\n" );
|
|
||||||
ExitProcess( 1 );
|
ExitProcess( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Thread-Local Storage */
|
|
||||||
PE_InitTls( pTask->thdb );
|
|
||||||
|
|
||||||
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
|
||||||
AllocConsole();
|
|
||||||
|
|
||||||
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
|
|
||||||
TRACE(relay, "(entryproc=%p)\n", entry );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
ExitProcess( entry(NULL) );
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
DWORD size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
|
|
||||||
DWORD id;
|
|
||||||
THDB *thdb;
|
|
||||||
|
|
||||||
CreateThread( NULL, size, entry, NULL, 0, &id );
|
|
||||||
thdb = THREAD_IdToTHDB( id );
|
|
||||||
|
|
||||||
while ( thdb->exit_code == 0x103 )
|
|
||||||
{
|
|
||||||
WaitEvent16( 0 );
|
|
||||||
QUEUE_Signal( pTask->hSelf );
|
|
||||||
}
|
|
||||||
|
|
||||||
ExitProcess( thdb->exit_code );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (pModule->dos_image)
|
else if (pModule->dos_image)
|
||||||
{
|
{
|
||||||
DOSVM_Enter( NULL );
|
DOSVM_Enter( NULL );
|
||||||
|
@ -356,7 +316,7 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
||||||
|
|
||||||
/* Fill the task structure */
|
/* Fill the task structure */
|
||||||
|
|
||||||
pTask->nEvents = 1; /* So the task can be started */
|
pTask->nEvents = 0;
|
||||||
pTask->hSelf = hTask;
|
pTask->hSelf = hTask;
|
||||||
pTask->flags = 0;
|
pTask->flags = 0;
|
||||||
|
|
||||||
|
@ -498,6 +458,9 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
||||||
*/
|
*/
|
||||||
void TASK_StartTask( HTASK16 hTask )
|
void TASK_StartTask( HTASK16 hTask )
|
||||||
{
|
{
|
||||||
|
TDB *pTask = (TDB *)GlobalLock16( hTask );
|
||||||
|
if ( !pTask ) return;
|
||||||
|
|
||||||
/* Add the task to the linked list */
|
/* Add the task to the linked list */
|
||||||
|
|
||||||
SYSLEVEL_EnterWin16Lock();
|
SYSLEVEL_EnterWin16Lock();
|
||||||
|
@ -511,16 +474,27 @@ void TASK_StartTask( HTASK16 hTask )
|
||||||
if ( TASK_AddTaskEntryBreakpoint )
|
if ( TASK_AddTaskEntryBreakpoint )
|
||||||
TASK_AddTaskEntryBreakpoint( hTask );
|
TASK_AddTaskEntryBreakpoint( hTask );
|
||||||
|
|
||||||
/* Get the task up and running. If we ourselves are a 16-bit task,
|
/* Get the task up and running. */
|
||||||
we simply Yield(). If we are 32-bit however, we need to signal
|
|
||||||
the main process somehow (NOT YET IMPLEMENTED!) */
|
if ( THREAD_IsWin16( pTask->thdb ) )
|
||||||
|
{
|
||||||
|
pTask->nEvents++;
|
||||||
|
|
||||||
|
/* If we ourselves are a 16-bit task, we simply Yield().
|
||||||
|
If we are 32-bit however, we need to signal the scheduler. */
|
||||||
|
|
||||||
if ( THREAD_IsWin16( THREAD_Current() ) )
|
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||||
OldYield16();
|
OldYield16();
|
||||||
else
|
else
|
||||||
/* wake-up the scheduler waiting in EVENT_WaitNetEvent */
|
|
||||||
EVENT_WakeUp();
|
EVENT_WakeUp();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* To start a 32-bit task, we spawn its initial thread. */
|
||||||
|
|
||||||
|
SYSDEPS_SpawnThread( pTask->thdb );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -560,37 +534,25 @@ static void TASK_DeleteTask( HTASK16 hTask )
|
||||||
GlobalFreeAll16( hPDB );
|
GlobalFreeAll16( hPDB );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* TASK_KillCurrentTask
|
* TASK_KillTask
|
||||||
*
|
|
||||||
* Kill the currently running task. As it's not possible to kill the
|
|
||||||
* current task like this, it is simply marked for destruction, and will
|
|
||||||
* be killed when either TASK_Reschedule or this function is called again
|
|
||||||
* in the context of another task.
|
|
||||||
*/
|
*/
|
||||||
void TASK_KillCurrentTask( INT16 exitCode )
|
void TASK_KillTask( HTASK16 hTask )
|
||||||
{
|
{
|
||||||
TDB* pTask = (TDB*) GlobalLock16( GetCurrentTask() );
|
TDB *pTask;
|
||||||
NE_MODULE* pModule = NE_GetPtr( pTask->hModule );
|
|
||||||
if (!pTask) USER_ExitWindows(); /* No current task yet */
|
|
||||||
|
|
||||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
/* Enter the Win16Lock to protect global data structures */
|
||||||
|
SYSLEVEL_EnterWin16Lock();
|
||||||
|
|
||||||
|
if ( !hTask ) hTask = GetCurrentTask();
|
||||||
|
pTask = (TDB *)GlobalLock16( hTask );
|
||||||
|
if ( !pTask )
|
||||||
{
|
{
|
||||||
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
|
SYSLEVEL_LeaveWin16Lock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter the Win16Lock to protect global data structures
|
TRACE(task, "Killing task %04x\n", hTask );
|
||||||
NOTE: We never explicitly leave it again. This shouldn't matter
|
|
||||||
though, as it will be released in TASK_Reschedule and this
|
|
||||||
task won't ever get scheduled again ... */
|
|
||||||
|
|
||||||
SYSLEVEL_EnterWin16Lock();
|
|
||||||
|
|
||||||
assert(hCurrentTask == GetCurrentTask());
|
|
||||||
|
|
||||||
TRACE(task, "Killing task %04x\n", hCurrentTask );
|
|
||||||
|
|
||||||
/* Delete active sockets */
|
/* Delete active sockets */
|
||||||
|
|
||||||
|
@ -598,9 +560,12 @@ void TASK_KillCurrentTask( INT16 exitCode )
|
||||||
WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
|
WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
|
||||||
|
|
||||||
#ifdef MZ_SUPPORTED
|
#ifdef MZ_SUPPORTED
|
||||||
|
{
|
||||||
/* Kill DOS VM task */
|
/* Kill DOS VM task */
|
||||||
|
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
|
||||||
if ( pModule->lpDosTask )
|
if ( pModule->lpDosTask )
|
||||||
MZ_KillModule( pModule->lpDosTask );
|
MZ_KillModule( pModule->lpDosTask );
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Perform USER cleanup */
|
/* Perform USER cleanup */
|
||||||
|
@ -609,13 +574,6 @@ void TASK_KillCurrentTask( INT16 exitCode )
|
||||||
pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
|
pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
|
||||||
pTask->hInstance, pTask->hQueue );
|
pTask->hInstance, pTask->hQueue );
|
||||||
|
|
||||||
if (hTaskToKill && (hTaskToKill != hCurrentTask))
|
|
||||||
{
|
|
||||||
/* If another task is already marked for destruction, */
|
|
||||||
/* we can kill it now, as we are in another context. */
|
|
||||||
TASK_DeleteTask( hTaskToKill );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nTaskCount <= 1)
|
if (nTaskCount <= 1)
|
||||||
{
|
{
|
||||||
TRACE(task, "this is the last task, exiting\n" );
|
TRACE(task, "this is the last task, exiting\n" );
|
||||||
|
@ -631,22 +589,71 @@ void TASK_KillCurrentTask( INT16 exitCode )
|
||||||
Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 );
|
Callout.PostAppMessage16( PROCESS_Initial()->task, WM_NULL, 0, 0 );
|
||||||
|
|
||||||
/* Remove the task from the list to be sure we never switch back to it */
|
/* Remove the task from the list to be sure we never switch back to it */
|
||||||
TASK_UnlinkTask( hCurrentTask );
|
TASK_UnlinkTask( hTask );
|
||||||
if( nTaskCount )
|
if( nTaskCount )
|
||||||
{
|
{
|
||||||
TDB* p = (TDB *)GlobalLock16( hFirstTask );
|
TDB* p = (TDB *)GlobalLock16( hFirstTask );
|
||||||
while( p )
|
while( p )
|
||||||
{
|
{
|
||||||
if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0;
|
if( p->hYieldTo == hTask ) p->hYieldTo = 0;
|
||||||
p = (TDB *)GlobalLock16( p->hNext );
|
p = (TDB *)GlobalLock16( p->hNext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hTaskToKill = hCurrentTask;
|
pTask->nEvents = 0;
|
||||||
|
|
||||||
|
if ( hLockedTask == hTask )
|
||||||
hLockedTask = 0;
|
hLockedTask = 0;
|
||||||
|
|
||||||
pTask->nEvents = 0;
|
if ( hTaskToKill && ( hTaskToKill != hCurrentTask ) )
|
||||||
TASK_YieldToSystem(pTask);
|
{
|
||||||
|
/* If another task is already marked for destruction, */
|
||||||
|
/* we can kill it now, as we are in another context. */
|
||||||
|
TASK_DeleteTask( hTaskToKill );
|
||||||
|
hTaskToKill = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If hTask is not the task currently scheduled by the Win16
|
||||||
|
* scheduler, we simply delete it; otherwise we mark it for
|
||||||
|
* destruction. Note that if the current task is a 32-bit
|
||||||
|
* one, hCurrentTask is *different* from GetCurrentTask()!
|
||||||
|
*/
|
||||||
|
if ( hTask == hCurrentTask )
|
||||||
|
{
|
||||||
|
assert( hTaskToKill == 0 || hTaskToKill == hCurrentTask );
|
||||||
|
hTaskToKill = hCurrentTask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TASK_DeleteTask( hTask );
|
||||||
|
|
||||||
|
SYSLEVEL_LeaveWin16Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* TASK_KillCurrentTask
|
||||||
|
*
|
||||||
|
* Kill the currently running task. As it's not possible to kill the
|
||||||
|
* current task like this, it is simply marked for destruction, and will
|
||||||
|
* be killed when either TASK_Reschedule or this function is called again
|
||||||
|
* in the context of another task.
|
||||||
|
*/
|
||||||
|
void TASK_KillCurrentTask( INT16 exitCode )
|
||||||
|
{
|
||||||
|
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
||||||
|
{
|
||||||
|
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(hCurrentTask == GetCurrentTask());
|
||||||
|
|
||||||
|
TRACE(task, "Killing current task %04x\n", hCurrentTask );
|
||||||
|
|
||||||
|
TASK_KillTask( 0 );
|
||||||
|
|
||||||
|
TASK_YieldToSystem();
|
||||||
|
|
||||||
/* We should never return from this Yield() */
|
/* We should never return from this Yield() */
|
||||||
|
|
||||||
|
@ -824,7 +831,7 @@ BOOL TASK_Reschedule(void)
|
||||||
* Scheduler interface, this way we ensure that all "unsafe" events are
|
* Scheduler interface, this way we ensure that all "unsafe" events are
|
||||||
* processed outside the scheduler.
|
* processed outside the scheduler.
|
||||||
*/
|
*/
|
||||||
void TASK_YieldToSystem(TDB* pTask)
|
static void TASK_YieldToSystem( void )
|
||||||
{
|
{
|
||||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
||||||
{
|
{
|
||||||
|
@ -944,7 +951,7 @@ BOOL16 WINAPI WaitEvent16( HTASK16 hTask )
|
||||||
pTask->nEvents--;
|
pTask->nEvents--;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
TASK_YieldToSystem(pTask);
|
TASK_YieldToSystem();
|
||||||
|
|
||||||
/* When we get back here, we have an event */
|
/* When we get back here, we have an event */
|
||||||
|
|
||||||
|
@ -963,6 +970,12 @@ void WINAPI PostEvent16( HTASK16 hTask )
|
||||||
if (!hTask) hTask = GetCurrentTask();
|
if (!hTask) hTask = GetCurrentTask();
|
||||||
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
|
if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
|
||||||
|
|
||||||
|
if ( !THREAD_IsWin16( pTask->thdb ) )
|
||||||
|
{
|
||||||
|
FIXME( task, "called for Win32 thread (%04x)!\n", pTask->thdb->teb_sel );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pTask->nEvents++;
|
pTask->nEvents++;
|
||||||
|
|
||||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
||||||
|
@ -1028,7 +1041,7 @@ void WINAPI OldYield16(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
|
if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
|
||||||
TASK_YieldToSystem(pCurTask);
|
TASK_YieldToSystem();
|
||||||
if (pCurTask) pCurTask->nEvents--;
|
if (pCurTask) pCurTask->nEvents--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,7 @@ BOOL PROCESS_Init(void)
|
||||||
initial_pdb.ring0_threads = 1;
|
initial_pdb.ring0_threads = 1;
|
||||||
initial_pdb.group = &initial_pdb;
|
initial_pdb.group = &initial_pdb;
|
||||||
initial_pdb.priority = 8; /* Normal */
|
initial_pdb.priority = 8; /* Normal */
|
||||||
|
initial_pdb.flags = PDB32_WIN16_PROC;
|
||||||
|
|
||||||
/* Initialize virtual memory management */
|
/* Initialize virtual memory management */
|
||||||
if (!VIRTUAL_Init()) return FALSE;
|
if (!VIRTUAL_Init()) return FALSE;
|
||||||
|
@ -330,8 +331,11 @@ void PROCESS_Start(void)
|
||||||
LPTHREAD_START_ROUTINE entry;
|
LPTHREAD_START_ROUTINE entry;
|
||||||
THDB *thdb = THREAD_Current();
|
THDB *thdb = THREAD_Current();
|
||||||
PDB *pdb = thdb->process;
|
PDB *pdb = thdb->process;
|
||||||
NE_MODULE *pModule = (NE_MODULE *)thdb->entry_arg; /* hack */
|
TDB *pTask = (TDB *)GlobalLock16( pdb->task );
|
||||||
|
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
|
||||||
|
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Initialize the critical section */
|
/* Initialize the critical section */
|
||||||
|
|
||||||
InitializeCriticalSection( &pdb->crit_section );
|
InitializeCriticalSection( &pdb->crit_section );
|
||||||
|
@ -347,10 +351,10 @@ void PROCESS_Start(void)
|
||||||
|
|
||||||
if (!PROCESS_CreateEnvDB()) goto error;
|
if (!PROCESS_CreateEnvDB()) goto error;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
|
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
|
||||||
cmdShow = pdb->env_db->startup_info->wShowWindow;
|
cmdShow = pdb->env_db->startup_info->wShowWindow;
|
||||||
if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
|
if (!TASK_Create( thdb, pModule, 0, 0, cmdShow )) goto error;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Map system DLLs into this process (from initial process) */
|
/* Map system DLLs into this process (from initial process) */
|
||||||
|
@ -358,10 +362,7 @@ void PROCESS_Start(void)
|
||||||
pdb->modref_list = PROCESS_Initial()->modref_list;
|
pdb->modref_list = PROCESS_Initial()->modref_list;
|
||||||
|
|
||||||
/* Create 32-bit MODREF */
|
/* Create 32-bit MODREF */
|
||||||
{
|
|
||||||
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
|
|
||||||
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
|
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize thread-local storage */
|
/* Initialize thread-local storage */
|
||||||
|
|
||||||
|
@ -463,6 +464,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
|
||||||
goto error;
|
goto error;
|
||||||
info->hThread = server_thandle;
|
info->hThread = server_thandle;
|
||||||
info->dwThreadId = (DWORD)thdb->server_tid;
|
info->dwThreadId = (DWORD)thdb->server_tid;
|
||||||
|
thdb->startup = PROCESS_Start;
|
||||||
|
|
||||||
/* Duplicate the standard handles */
|
/* Duplicate the standard handles */
|
||||||
|
|
||||||
|
@ -509,20 +511,13 @@ error:
|
||||||
*/
|
*/
|
||||||
void WINAPI ExitProcess( DWORD status )
|
void WINAPI ExitProcess( DWORD status )
|
||||||
{
|
{
|
||||||
PDB *pdb = PROCESS_Current();
|
|
||||||
TDB *pTask = (TDB *)GlobalLock16( pdb->task );
|
|
||||||
if ( pTask ) pTask->nEvents++;
|
|
||||||
|
|
||||||
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL );
|
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL );
|
||||||
|
|
||||||
if ( pTask && pTask->thdb != THREAD_Current() )
|
if ( THREAD_IsWin16( THREAD_Current() ) )
|
||||||
TerminateProcess( GetCurrentProcess(), status );
|
|
||||||
|
|
||||||
/* FIXME: should kill all running threads of this process */
|
|
||||||
pdb->exit_code = status;
|
|
||||||
|
|
||||||
__RESTORE_ES; /* Necessary for Pietrek's showseh example program */
|
|
||||||
TASK_KillCurrentTask( status );
|
TASK_KillCurrentTask( status );
|
||||||
|
|
||||||
|
TASK_KillTask( 0 );
|
||||||
|
TerminateProcess( GetCurrentProcess(), status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,13 +54,7 @@ THDB *THREAD_Current(void)
|
||||||
*/
|
*/
|
||||||
BOOL THREAD_IsWin16( THDB *thdb )
|
BOOL THREAD_IsWin16( THDB *thdb )
|
||||||
{
|
{
|
||||||
if (!thdb || !thdb->process)
|
return !thdb || !(thdb->teb.flags & TEBF_WIN32);
|
||||||
return TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TDB* pTask = (TDB*)GlobalLock16( thdb->process->task );
|
|
||||||
return !pTask || pTask->thdb == thdb;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -188,7 +182,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
|
||||||
initial_thdb.process = pdb;
|
initial_thdb.process = pdb;
|
||||||
initial_thdb.teb.except = (void *)-1;
|
initial_thdb.teb.except = (void *)-1;
|
||||||
initial_thdb.teb.self = &initial_thdb.teb;
|
initial_thdb.teb.self = &initial_thdb.teb;
|
||||||
initial_thdb.teb.flags = TEBF_WIN32;
|
initial_thdb.teb.flags = /* TEBF_WIN32 */ 0;
|
||||||
initial_thdb.teb.tls_ptr = initial_thdb.tls_array;
|
initial_thdb.teb.tls_ptr = initial_thdb.tls_array;
|
||||||
initial_thdb.teb.process = pdb;
|
initial_thdb.teb.process = pdb;
|
||||||
initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */
|
initial_thdb.exit_code = 0x103; /* STILL_ACTIVE */
|
||||||
|
|
Loading…
Reference in New Issue