/*********************************************************************** * 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); }
/*********************************************************************** * TASK_ExitTask */ void TASK_ExitTask(void) { WIN16_SUBSYSTEM_TIB *tib; 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 ); if ((tib = NtCurrentTeb()->Tib.SubSystemTib)) { free_win16_tib( tib ); NtCurrentTeb()->Tib.SubSystemTib = NULL; } /* ... and completely release the Win16Lock, just in case. */ ReleaseThunkLock( &lockCount ); }
/*********************************************************************** * NE_InitDLL * * Call the DLL initialization code */ static BOOL NE_InitDLL( NE_MODULE *pModule ) { SEGTABLEENTRY *pSegTable; WORD hInst, ds, heap; CONTEXT86 context; pSegTable = NE_SEG_TABLE( pModule ); if (!(pModule->flags & NE_FFLAGS_LIBMODULE) || (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/ /* Call USER signal handler for Win3.1 compatibility. */ TASK_CallTaskSignalProc( USIG16_DLL_LOAD, pModule->self ); if (!pModule->cs) return TRUE; /* no initialization code */ /* Registers at initialization must be: * cx heap size * di library instance * ds data segment if any * es:si command line (always 0) */ memset( &context, 0, sizeof(context) ); NE_GetDLLInitParams( pModule, &hInst, &ds, &heap ); context.Ecx = heap; context.Edi = hInst; context.SegDs = ds; context.SegEs = ds; /* who knows ... */ context.SegCs = SEL(pSegTable[pModule->cs-1].hSeg); context.Eip = pModule->ip; context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp; pModule->cs = 0; /* Don't initialize it twice */ TRACE_(dll)("Calling LibMain, cs:ip=%04lx:%04lx ds=%04lx di=%04x cx=%04x\n", context.SegCs, context.Eip, context.SegDs, LOWORD(context.Edi), LOWORD(context.Ecx) ); wine_call_to_16_regs_short( &context, 0 ); return TRUE; }