Check all Callouts function pointers for NULL before using them.
Don't load USER dll if not needed by the application.
diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c
index ba52f4a..0097f14 100644
--- a/loader/dos/dosvm.c
+++ b/loader/dos/dosvm.c
@@ -420,12 +420,15 @@
objc=hObject?2:1;
do {
/* check for messages (waste time before the response check below) */
- while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
- /* got a message */
- DOSVM_ProcessMessage(&msg);
- /* we don't need a TranslateMessage here */
- Callout.DispatchMessageA(&msg);
- got_msg = TRUE;
+ if (Callout.PeekMessageA)
+ {
+ while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
+ /* got a message */
+ DOSVM_ProcessMessage(&msg);
+ /* we don't need a TranslateMessage here */
+ Callout.DispatchMessageA(&msg);
+ got_msg = TRUE;
+ }
}
if (!got_msg) {
/* check for console input */
@@ -448,7 +451,11 @@
break;
}
/* nothing yet, block while waiting for something to do */
- waitret=Callout.MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT);
+ if (Callout.MsgWaitForMultipleObjects)
+ waitret = Callout.MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT);
+ else
+ waitret = WaitForMultipleObjects(objc,objs,FALSE,INFINITE);
+
if (waitret==(DWORD)-1) {
ERR_(module)("dosvm wait error=%ld\n",GetLastError());
}
diff --git a/loader/module.c b/loader/module.c
index e1978cf..ae2d298 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -827,7 +827,8 @@
0, NULL, NULL, &startup, &info ))
{
/* Give 30 seconds to the app to come up */
- if (Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF)
+ if (Callout.WaitForInputIdle &&
+ Callout.WaitForInputIdle( info.hProcess, 30000 ) == 0xFFFFFFFF)
WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
hInstance = 33;
/* Close off the handles */
@@ -884,7 +885,8 @@
params->lpEnvAddress, NULL, &startup, &info ))
{
/* Give 30 seconds to the app to come up */
- if ( Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF )
+ if (Callout.WaitForInputIdle &&
+ Callout.WaitForInputIdle( info.hProcess, 30000 ) == 0xFFFFFFFF )
WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
hInstance = 33;
/* Close off the handles */
diff --git a/loader/task.c b/loader/task.c
index 4db25a2..e6bafa0 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -379,78 +379,62 @@
/***********************************************************************
* TASK_KillTask
*/
-void TASK_KillTask( HTASK16 hTask )
+void TASK_ExitTask(void)
{
TDB *pTask;
+ DWORD lockCount;
/* Enter the Win16Lock to protect global data structures */
SYSLEVEL_EnterWin16Lock();
- if ( !hTask ) hTask = GetCurrentTask();
- pTask = (TDB *)GlobalLock16( hTask );
+ pTask = (TDB *)GlobalLock16( GetCurrentTask() );
if ( !pTask )
{
SYSLEVEL_LeaveWin16Lock();
return;
}
- TRACE("Killing task %04x\n", hTask );
+ TRACE("Killing task %04x\n", pTask->hSelf );
/* Perform USER cleanup */
- TASK_CallTaskSignalProc( USIG16_TERMINATION, hTask );
+ TASK_CallTaskSignalProc( USIG16_TERMINATION, pTask->hSelf );
PROCESS_CallUserSignalProc( USIG_PROCESS_EXIT, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_DESTROY, 0 );
- if (nTaskCount <= 1)
+ /* 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" );
+ ERR("done\n");
ExitKernel16();
}
- /* FIXME: Hack! Send a message to the initial task so that
- * the GetMessage wakes up and the initial task can check whether
- * it is the only remaining one and terminate itself ...
- * The initial task should probably install hooks or something
- * to get informed about task termination :-/
- */
- Callout.PostAppMessage16( initial_task, WM_NULL, 0, 0 );
-
- /* Remove the task from the list to be sure we never switch back to it */
- TASK_UnlinkTask( hTask );
if( nTaskCount )
{
TDB* p = (TDB *)GlobalLock16( hFirstTask );
while( p )
{
- if( p->hYieldTo == hTask ) p->hYieldTo = 0;
+ if( p->hYieldTo == pTask->hSelf ) p->hYieldTo = 0;
p = (TDB *)GlobalLock16( p->hNext );
}
}
pTask->nEvents = 0;
- if ( hLockedTask == hTask )
+ if ( hLockedTask == pTask->hSelf )
hLockedTask = 0;
- TASK_DeleteTask( hTask );
+ TASK_DeleteTask( pTask->hSelf );
- /* When deleting the current task ... */
- if ( hTask == hCurrentTask )
- {
- DWORD lockCount;
+ /* ... schedule another one ... */
+ TASK_Reschedule();
- /* ... schedule another one ... */
- TASK_Reschedule();
-
- /* ... and completely release the Win16Lock, just in case. */
- ReleaseThunkLock( &lockCount );
-
- return;
- }
-
- SYSLEVEL_LeaveWin16Lock();
+ /* ... and completely release the Win16Lock, just in case. */
+ ReleaseThunkLock( &lockCount );
}
/***********************************************************************
@@ -838,7 +822,7 @@
TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() );
if (pCurTask) pCurTask->hYieldTo = 0;
- if (pCurTask && pCurTask->hQueue) Callout.UserYield16();
+ if (pCurTask && pCurTask->hQueue && Callout.UserYield16) Callout.UserYield16();
else OldYield16();
}
@@ -1148,7 +1132,7 @@
TEB *teb = NtCurrentTeb();
if (!teb) return 0;
- if (!teb->queue)
+ if (!teb->queue && Callout.InitThreadInput16)
Callout.InitThreadInput16( 0, THREAD_IsWin16(teb)? 4 : 5 );
if (!teb->queue)