Rewrote Unix process launching to allow passing startup information to
[wine] / miscemu / main.c
1 /*
2  * Emulator initialisation code
3  *
4  */
5
6 #include <stdlib.h>
7 #include <assert.h>
8 #include "wine/winbase16.h"
9 #include "callback.h"
10 #include "main.h"
11 #include "miscemu.h"
12 #include "module.h"
13 #include "options.h"
14 #include "process.h"
15 #include "thread.h"
16 #include "task.h"
17 #include "stackframe.h"
18 #include "wine/exception.h"
19 #include "debugtools.h"
20
21 static BOOL exec_program( LPCSTR cmdline )
22 {
23     HINSTANCE handle = WinExec( cmdline, SW_SHOWNORMAL );
24     if (handle < 32) 
25     {
26         MESSAGE( "%s: can't exec '%s': ", argv0, cmdline );
27         switch (handle) 
28         {
29         case  2: MESSAGE("file not found\n" ); break;
30         case 11: MESSAGE("invalid exe file\n" ); break;
31         default: MESSAGE("error=%d\n", handle ); break;
32         }
33     }
34     return (handle >= 32);
35 }
36
37 /***********************************************************************
38  *           Main loop of initial task
39  */
40 void MAIN_EmulatorRun( void )
41 {
42     char startProg[256], defProg[256];
43     int i, tasks = 0;
44     MSG msg;
45     char szGraphicsDriver[MAX_PATH];
46
47     if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver", 
48         "x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
49     {
50         if (!LoadLibraryA( szGraphicsDriver )) return FALSE;
51     }
52
53     /* Load system DLLs into the initial process (and initialize them) */
54     if (   !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
55         || !LoadLibrary16("USER.EXE") || !LoadLibraryA("USER32.DLL"))
56         ExitProcess( 1 );
57
58     /* Get pointers to USER routines called by KERNEL */
59     THUNK_InitCallout();
60
61     /* Call FinalUserInit routine */
62     Callout.FinalUserInit16();
63
64     /* Call InitApp for initial task */
65     Callout.InitApp16( MapHModuleLS( 0 ) );
66
67     /* Add the Startup Program to the run list */
68     PROFILE_GetWineIniString( "programs", "Startup", "", 
69                                startProg, sizeof(startProg) );
70     if (startProg[0]) tasks += exec_program( startProg );
71
72     /* Add the Default Program if no program on the command line */
73     if (!Options.argv[1])
74     {
75         PROFILE_GetWineIniString( "programs", "Default", "",
76                                   defProg, sizeof(defProg) );
77         if (defProg[0]) tasks += exec_program( defProg );
78         else if (!tasks && !startProg[0]) OPTIONS_Usage();
79     }
80     else
81     {
82         /* Load and run executables given on command line */
83         for (i = 1; Options.argv[i]; i++)
84         {
85             tasks += exec_program( Options.argv[i] );
86         }
87     }
88     if (!tasks) ExitProcess( 0 );
89
90     /* Start message loop for desktop window */
91
92     while ( GetNumTasks16() > 1  && Callout.GetMessageA( &msg, 0, 0, 0 ) )
93     {
94         Callout.TranslateMessage( &msg );
95         Callout.DispatchMessageA( &msg );
96     }
97
98     ExitProcess( 0 );
99 }
100
101
102 /**********************************************************************
103  *           main
104  */
105 int main( int argc, char *argv[] )
106 {
107     NE_MODULE *pModule;
108
109     /* Initialize everything */
110     if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
111
112     if (!THREAD_InitStack( NtCurrentTeb(), PROCESS_Current(), 0, TRUE )) return 1;
113     SIGNAL_Init();  /* reinitialize signal stack */
114
115     /* Initialize KERNEL */
116     if (!LoadLibraryA( "KERNEL32" )) return FALSE;
117
118     /* Create initial task */
119     if ( !(pModule = NE_GetPtr( GetModuleHandle16( "KERNEL" ) )) ) return 1;
120     if ( !TASK_Create( pModule, FALSE ) ) return 1;
121
122     /* Switch to initial task */
123     PostEvent16( PROCESS_Current()->task );
124     TASK_Reschedule();
125
126     /* Switch stacks and jump to MAIN_EmulatorRun */
127     CALL32_Init( &IF1632_CallLargeStack, MAIN_EmulatorRun, NtCurrentTeb()->stack_top );
128
129     MESSAGE( "main: Should never happen: returned from CALL32_Init()\n" );
130     return 0;
131 }