Some fixes to Wine startup/termination sequence with native USER.
Do not call built-in USER signal handler when using native USER.
diff --git a/loader/main.c b/loader/main.c
index 1c76b07..68c0a78 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -233,11 +233,11 @@
SetDoubleClickTime32( GetProfileInt32A("windows","DoubleClickSpeed",452) );
/* Create task message queue for the initial task */
- if ( GetCurrentTask() )
- {
- queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
- if (!SetMessageQueue32( queueSize )) return FALSE;
- }
+ queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
+ if (!SetMessageQueue32( queueSize )) return FALSE;
+
+ /* Install default USER Signal Handler */
+ SetTaskSignalProc( 0, (FARPROC16)USER_SignalProc );
/* Initialize keyboard driver */
KEYBOARD_Enable( keybd_event, InputKeyStateTable );
@@ -272,12 +272,6 @@
/* Initialize KERNEL */
if (!MAIN_KernelInit(0, 0, NULL)) return 0;
- /* Initialize GDI */
- if (!MAIN_GdiInit(0, 0, NULL)) return 0;
-
- /* Initialize USER */
- if (!MAIN_UserInit(0, 0, NULL)) return 0;
-
/* Create and switch to initial task */
if (!(wm = ELF_CreateDummyModule( argv[0], argv[0], PROCESS_Current() )))
return 0;
@@ -294,7 +288,9 @@
TASK_StartTask( PROCESS_Current()->task );
- InitApp( hInstance );
+ /* Initialize GDI and USER */
+ if (!MAIN_GdiInit(0, 0, NULL)) return 0;
+ if (!MAIN_UserInit(0, 0, NULL)) return 0;
return wm->module;
}
diff --git a/loader/task.c b/loader/task.c
index 20b430e..4ad4309 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
#include "windows.h"
#include "user.h"
@@ -43,6 +44,8 @@
/* Pointer to function to switch to a larger stack */
int (*IF1632_CallLargeStack)( int (*func)(), void *arg ) = NULL;
+ /* Pointer to debugger callback routine */
+void (*TASK_AddTaskEntryBreakpoint)( HTASK16 hTask ) = NULL;
static THHOOK DefaultThhook = { 0 };
THHOOK *pThhook = &DefaultThhook;
@@ -241,11 +244,7 @@
LPTHREAD_START_ROUTINE entry = (LPTHREAD_START_ROUTINE)
RVA_PTR(pModule->module32, OptionalHeader.AddressOfEntryPoint);
- DWORD size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
- DWORD id;
- THDB *thdb;
- pTask->userhandler = (USERSIGNALPROC)&USER_SignalProc;
if (pModule->heap_size)
LocalInit( pTask->hInstance, 0, pModule->heap_size );
@@ -256,6 +255,11 @@
#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_ID_TO_THDB( id );
@@ -266,6 +270,7 @@
}
ExitProcess( thdb->exit_code );
+}
#endif
}
else if (pModule->dos_image)
@@ -322,7 +327,7 @@
HINSTANCE16 hPrevInstance, UINT16 cmdShow)
{
HTASK16 hTask;
- TDB *pTask;
+ TDB *pTask, *pInitialTask;
LPSTR cmd_line;
WORD sp;
char *stack32Top;
@@ -421,6 +426,12 @@
pTask->dta = PTR_SEG_OFF_TO_SEGPTR( pTask->hPDB,
(int)&pTask->pdb.cmdLine - (int)&pTask->pdb );
+ /* Inherit default UserSignalHandler from initial process */
+
+ pInitialTask = (TDB *)GlobalLock16( PROCESS_Initial()->task );
+ if ( pInitialTask )
+ pTask->userhandler = pInitialTask->userhandler;
+
/* Create the 16-bit stack frame */
if (!(sp = pModule->sp))
@@ -475,6 +486,11 @@
TRACE(task, "linked task %04x\n", hTask );
+ /* If requested, add entry point breakpoint */
+
+ if ( TASK_AddTaskEntryBreakpoint )
+ TASK_AddTaskEntryBreakpoint( hTask );
+
/* Get the task up and running. If we ourselves are a 16-bit task,
we simply Yield(). If we are 32-bit however, we need to signal
the main process somehow (NOT YET IMPLEMENTED!) */
@@ -504,15 +520,15 @@
K32OBJ_DecCount( &pTask->thdb->process->header );
K32OBJ_DecCount( &pTask->thdb->header );
- /* Free the task module */
-
- FreeModule16( pTask->hModule );
-
/* Free the selector aliases */
GLOBAL_FreeBlock( pTask->hCSAlias );
GLOBAL_FreeBlock( pTask->hPDB );
+ /* Free the task module */
+
+ FreeModule16( pTask->hModule );
+
/* Free the task structure itself */
GlobalFree16( hTask );
@@ -579,12 +595,27 @@
TASK_DeleteTask( hTaskToKill );
}
- if (nTaskCount <= 2) /* FIXME */
+ if (nTaskCount <= 1)
{
TRACE(task, "this is the last task, exiting\n" );
USER_ExitWindows();
}
+ if (!__winelib)
+ {
+ /* 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 :-/
+ */
+ HTASK16 hTask = PROCESS_Initial()->task;
+ HMODULE16 hModule = GetModuleHandle16( "USER" );
+ FARPROC16 postFunc = WIN32_GetProcAddress16( hModule, "PostAppMessage" );
+ if (postFunc)
+ Callbacks->CallPostAppMessageProc( postFunc, hTask, WM_NULL, 0, 0 );
+ }
+
/* Remove the task from the list to be sure we never switch back to it */
TASK_UnlinkTask( hCurrentTask );
if( nTaskCount )
@@ -814,11 +845,6 @@
if (!(pTask = (TDB *)GlobalLock16( GetCurrentTask() ))) return;
if (!(pModule = NE_GetPtr( pTask->hModule ))) return;
- /* This is a hack to install task USER signal handler before
- * implicitly loaded DLLs are initialized (see windows/user.c) */
-
- pTask->userhandler = (USERSIGNALPROC)&USER_SignalProc;
-
/* Initialize implicitly loaded DLLs */
NE_InitializeDLLs( pTask->hModule );