Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 82518 | Differences between
and this patch

Collapse All | Expand All

(-)eclipse.c (-432 / +127 lines)
Lines 12-111 Link Here
12
12
13
/* Eclipse Program Launcher
13
/* Eclipse Program Launcher
14
 *
14
 *
15
 * This program performs the launching of the eclipse program along
15
 * This program performs the launching of the eclipse program.
16
 * with the splash window. If the splash window is to be displayed,
17
 * the java application will receive two extra arguments:
18
 *     -showsplash  <splashCommand>
19
 *
20
 * When the Java program starts, it should determine if a different
21
 * version of the splash bitmaps are to be used (uses the feature mechanism).
22
 * If feature specific bitmaps are to be used, the root directory where
23
 * those bitmaps reside (e.g., <rootDir>/splash/<bitmapFile>) should be
24
 * appended (in double quotes) to the splash command. If a directory is
25
 * not appended, the Eclipse install directory is used. 
26
 * 
27
 * The Java program initiates the displaying of the splash window
28
 * by executing the splash command as follows:
29
 *
30
 *     String command = splashCommand;
31
 *     String directory = getFeatureRootDirectory();
32
 *     if (directory != null)
33
 *         command += " \"" + directory + "\"";
34
 *     Process splashProcess = Runtime.getRuntime().exec( command );
35
 *
36
 * When the Java program initialization is complete, the splash window
37
 * is brought down by destroying the splash process as follows:
38
 *
39
 *     splashProcess.destroy();
40
 *
41
 * Therefore, when the splash window is visible, there are actually three
42
 * processes running: 
43
 * 1) the main launcher process 
44
 * 2) the Java VM process (Eclipse) 
45
 * 3) the splash window process.
46
 *
47
 * The Java application does not need to know the format of the
48
 * <splashCommand> argument but the command format is:
49
 *   <fullPathOfLauncherProgram> -showsplash <timeout>
50
 *
51
 * In other words, another eclipse launcher program is run with
52
 * the arguments "-showsplash" and a timeout value for bringing
53
 * the splash window down.
54
 *
55
 * Similarly, the Java application will receive two other arguments:
56
 *    -exitdata <exitDataCommand>
57
 *
58
 * The <exitDataCommand> argument can be used by the Java application
59
 * to provide specific exit data to the main launcher process. It accomplishes
60
 * this by executing the exit data command with an extra argument, which is
61
 * the exit data.
62
 *
63
 *     String command = exitDataCommand;
64
 *     String data = "Some data";
65
 *     if (data != null)
66
 *         command += " \"" + data + "\"";
67
 *     Process exitDataProcess = Runtime.getRuntime().exec( command );
68
 *     exitDataProcess.waitFor();
69
 *
70
 * The exit data size must not exceed MAX_SHARED_LENGTH which is
71
 * 16Kb. The exit data process will exit with an exit code
72
 * different than 0 if that happens.
73
 *
74
 * The Java application does not need to know the format of the
75
 * <exitDataCommand> argument either, but the command format is:
76
 *   <fullPathOfLauncherProgram> -exitdata <id>
77
 *
78
 *   where id is a process independent identifier for the shared
79
 * memory segment that stores the exit data.
80
 *
81
 * The main launcher recognizes the following exit codes from the
82
 * Java application:
83
 *
84
 *    0
85
 *       - Exit normally.
86
 *    RESTART_LAST_EC = 23
87
 *       - restart the java VM again with the same arguments as the previous one.
88
 *    RESTART_NEW_EC  = 24
89
 *       - restart the java VM again with the arguments taken from the exit data.
90
 *       The exit data format is a list of arguments separated by '\n'. The Java
91
 *       application should build this list using the arguments passed to it on
92
 *       startup. See below.
93
 *
94
 * Additionally, if the Java application exits with an exit code other than the
95
 * ones above, the main launcher will display an error message with the contents
96
 * of the exit data. If the exit data is empty, a generic error message is
97
 * displayed. The generic error message shows the exit code and the arguments
98
 * passed to the Java application.
99
 *
16
 *
100
 * The options that can be specified by the user to the launcher are:
17
 * The options that can be specified by the user to the launcher are:
101
 *  -vm <javaVM>               the Java VM to be used
18
 *  -vm <javaVM>               the Java VM to be used
102
 *  -os <opSys>                the operating system being run on
19
 *  -os <opSys>                the operating system being run on
103
 *  -arch <osArch>             the hardware architecture of the OS: x86, sparc, hp9000
20
 *  -arch <osArch>             the hardware architecture of the OS: x86, sparc, hp9000
104
 *  -ws <gui>                  the window system to be used: win32, motif, gtk, ...
21
 *  -ws <gui>                  the window system to be used: win32, motif, gtk, ...
105
 *  -nosplash                  do not display the splash screen
22
 *  -name <name>               application name displayed in error message dialogs.
106
 *  -name <name>               application name displayed in error message dialogs and
23
 *                             Default value is computed from the name of
107
 *                             splash screen window. Default value is computed from the
24
 *                             the executable - with the first letter capitalized
108
 *                             name of the executable - with the first letter capitalized
109
 *                             if possible. e.g. eclipse.exe defaults to the name Eclipse.
25
 *                             if possible. e.g. eclipse.exe defaults to the name Eclipse.
110
 *  <userArgs>                 arguments that are passed along to the Java application
26
 *  <userArgs>                 arguments that are passed along to the Java application
111
 *                             (i.e, -data <path>, -debug, -console, -consoleLog, etc) 
27
 *                             (i.e, -data <path>, -debug, -console, -consoleLog, etc) 
Lines 121-128 Link Here
121
 *     -os <user or default OS value>
37
 *     -os <user or default OS value>
122
 *     -ws <user or default WS value>
38
 *     -ws <user or default WS value>
123
 *     -arch <user or default ARCH value>
39
 *     -arch <user or default ARCH value>
124
 *     [-showsplash <splashCommand>]
125
 *     [-exitdata <exitDataCommand>]
126
 *     <userArgs>
40
 *     <userArgs>
127
 *     -vm <javaVM>
41
 *     -vm <javaVM>
128
 *     -vmargs <all VM args>
42
 *     -vmargs <all VM args>
Lines 133-142 Link Here
133
 *     -cp
47
 *     -cp
134
 *     <startup jar full path>
48
 *     <startup jar full path>
135
 *     org.eclipse.core.launcher.Main
49
 *     org.eclipse.core.launcher.Main
136
 * 
137
 * If the -nosplash option is given to the launcher, the java
138
 * application will not receive the "-showsplash" option or its
139
 * associated command.
140
 *
50
 *
141
 * See "Main.java" for a simple implementation of the Java
51
 * See "Main.java" for a simple implementation of the Java
142
 * application.
52
 * application.
Lines 185-209 Link Here
185
static _TCHAR*  program     = NULL;       /* full pathname of the program */
95
static _TCHAR*  program     = NULL;       /* full pathname of the program */
186
static _TCHAR*  homeDir     = NULL;       /* directory where program resides */
96
static _TCHAR*  homeDir     = NULL;       /* directory where program resides */
187
static _TCHAR*  javaVM      = NULL;       /* full pathname of the Java VM to run */
97
static _TCHAR*  javaVM      = NULL;       /* full pathname of the Java VM to run */
188
static _TCHAR*  sharedID    = NULL;       /* ID for the shared memory */
189
190
/* Define the special exit codes returned from Eclipse. */
191
#define RESTART_LAST_EC    23
192
#define RESTART_NEW_EC     24
193
194
/* Define the maximum time (in seconds) for the splash window to remain visible. */
195
static _TCHAR*  splashTimeout = _T("600");   /* 10 minutes */
196
98
197
/* Define the required VM arguments (all platforms). */
99
/* Define the required VM arguments (all platforms). */
198
#define        startupJarName _T("startup.jar")
100
static _TCHAR*  startupJarName = _T("startup.jar");
199
static _TCHAR*  reqVMarg[] = { _T("-cp"), startupJarName, _T("org.eclipse.core.launcher.Main"), NULL };
101
static _TCHAR*  startupClassName = _T("org/eclipse/core/launcher/Main");
200
102
201
/* Define error messages. (non-NLS) */
103
/* Define error messages. (non-NLS) */
202
static _TCHAR* exitMsg = _T("JVM terminated. Exit code=%d\n%s");
104
static _TCHAR* exitMsg = _T("JVM terminated. Exit code=%d\n%s");
203
static _TCHAR* goVMMsg = _T("Start VM: %s\n");
105
static _TCHAR* goVMMsg = _T("Start VM: %s\n");
204
static _TCHAR* pathMsg = _T("%s\n'%s' in your current PATH");
106
static _TCHAR* pathMsg = _T("%s\n'%s' in your current PATH");
205
static _TCHAR* showMsg = _T("Could not load splash bitmap:\n%s");
206
static _TCHAR* shareMsg = _T("No shared data available.");
207
static _TCHAR* noVMMsg =
107
static _TCHAR* noVMMsg =
208
_T("A Java Runtime Environment (JRE) or Java Development Kit (JDK)\n\
108
_T("A Java Runtime Environment (JRE) or Java Development Kit (JDK)\n\
209
must be available in order to run %s. No Java virtual machine\n\
109
must be available in order to run %s. No Java virtual machine\n\
Lines 212-218 Link Here
212
112
213
static _TCHAR* homeMsg =
113
static _TCHAR* homeMsg =
214
_T("The %s executable launcher was unable to locate its \n\
114
_T("The %s executable launcher was unable to locate its \n\
215
companion startup.jar file (in the same directory as the executable).");
115
companion %s file (in the same directory as the executable).");
216
116
217
/* Define constants for the options recognized by the launcher. */
117
/* Define constants for the options recognized by the launcher. */
218
#define CONSOLE      _T("-console")
118
#define CONSOLE      _T("-console")
Lines 220-228 Link Here
220
#define DEBUG        _T("-debug")
120
#define DEBUG        _T("-debug")
221
#define OS           _T("-os")
121
#define OS           _T("-os")
222
#define OSARCH       _T("-arch")
122
#define OSARCH       _T("-arch")
223
#define NOSPLASH     _T("-nosplash")
224
#define SHOWSPLASH   _T("-showsplash")
225
#define EXITDATA     _T("-exitdata")
226
#define VM           _T("-vm")
123
#define VM           _T("-vm")
227
#define WS           _T("-ws")
124
#define WS           _T("-ws")
228
#define NAME         _T("-name")
125
#define NAME         _T("-name")
Lines 231-241 Link Here
231
/* Define the variables to receive the option values. */
128
/* Define the variables to receive the option values. */
232
static int     needConsole   = 0;				/* True: user wants a console	*/
129
static int     needConsole   = 0;				/* True: user wants a console	*/
233
static int     debug         = 0;				/* True: output debugging info	*/
130
static int     debug         = 0;				/* True: output debugging info	*/
234
static int     noSplash      = 0;				/* True: do not show splash win	*/
235
static _TCHAR*  osArg         = _T(DEFAULT_OS);
131
static _TCHAR*  osArg         = _T(DEFAULT_OS);
236
static _TCHAR*  osArchArg     = _T(DEFAULT_OS_ARCH);
132
static _TCHAR*  osArchArg     = _T(DEFAULT_OS_ARCH);
237
static _TCHAR*  showSplashArg = NULL;			/* showsplash data (main launcher window) */
238
static _TCHAR*  exitDataArg   = NULL;
239
static _TCHAR*  vmName        = NULL;     		/* Java VM that the user wants to run */
133
static _TCHAR*  vmName        = NULL;     		/* Java VM that the user wants to run */
240
static _TCHAR*  wsArg         = _T(DEFAULT_WS);	/* the SWT supported GUI to be used */
134
static _TCHAR*  wsArg         = _T(DEFAULT_WS);	/* the SWT supported GUI to be used */
241
static _TCHAR*  name          = NULL;			/* program name */		
135
static _TCHAR*  name          = NULL;			/* program name */		
Lines 254-264 Link Here
254
    { CONSOLE,		NULL,			&needConsole,	0 },
148
    { CONSOLE,		NULL,			&needConsole,	0 },
255
    { CONSOLELOG,	NULL,			&needConsole,	0 },
149
    { CONSOLELOG,	NULL,			&needConsole,	0 },
256
    { DEBUG,		NULL,			&debug,			0 },
150
    { DEBUG,		NULL,			&debug,			0 },
257
    { NOSPLASH,     NULL,           &noSplash,		1 },
258
    { OS,			&osArg,			NULL,			2 },
151
    { OS,			&osArg,			NULL,			2 },
259
    { OSARCH,		&osArchArg,		NULL,			2 },
152
    { OSARCH,		&osArchArg,		NULL,			2 },
260
    { SHOWSPLASH,   &showSplashArg,	NULL,			2 },
261
    { EXITDATA,		&exitDataArg,	NULL,			2 },
262
    { VM,           &vmName,		NULL,			2 },
153
    { VM,           &vmName,		NULL,			2 },
263
    { NAME,         &name,			NULL,			2 },
154
    { NAME,         &name,			NULL,			2 },
264
    { WS,			&wsArg,			NULL,			2 } };
155
    { WS,			&wsArg,			NULL,			2 } };
Lines 268-283 Link Here
268
static _TCHAR** configArgv = NULL;
159
static _TCHAR** configArgv = NULL;
269
160
270
/* Local methods */
161
/* Local methods */
271
static int createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv);
162
static int      createUserArgs(int configArgc, _TCHAR **configArgv, int *argc, _TCHAR ***argv);
272
static void   parseArgs( int* argc, _TCHAR* argv[] );
163
static void     parseArgs( int* argc, _TCHAR* argv[] );
273
static _TCHAR** parseArgList( _TCHAR *data );
164
static _TCHAR** getVMArguments( int argc, _TCHAR* argv[], int *dstArgc );
274
static void   freeArgList( _TCHAR** data );
275
static _TCHAR** getVMCommand( int argc, _TCHAR* argv[] );
276
       _TCHAR*  findCommand( _TCHAR* command );
165
       _TCHAR*  findCommand( _TCHAR* command );
277
static _TCHAR*  formatVmCommandMsg( _TCHAR* args[] );
166
static _TCHAR*  formatVmCommandMsg( int argc, _TCHAR* argv[] );
278
       _TCHAR*  getInstallDir();
167
static _TCHAR*  getInstallDir( void );
279
static _TCHAR* getDefaultOfficialName();
168
static _TCHAR*  getDefaultOfficialName( void );
280
static int isMainEclipse( int argc, _TCHAR **argv );
169
static _TCHAR*  getJarFile( void );
170
static _TCHAR*  getJavaVM( void );
281
171
282
#ifdef _WIN32
172
#ifdef _WIN32
283
#ifdef UNICODE
173
#ifdef UNICODE
Lines 317-331 Link Here
317
207
318
int main( int argc, _TCHAR* argv[] )
208
int main( int argc, _TCHAR* argv[] )
319
{
209
{
320
	_TCHAR*   splashBitmap;
321
    _TCHAR*   ch;
210
    _TCHAR*   ch;
322
    _TCHAR*   data;
211
    _TCHAR**  vmCommandArgv = NULL;
323
    _TCHAR*   shippedVM    = NULL;
324
    _TCHAR*   vmSearchPath = NULL;
325
    _TCHAR**  vmCommand = NULL;
326
    _TCHAR**  vmCommandList = NULL;
327
    _TCHAR**  vmCommandArgs = NULL;
328
    _TCHAR*   vmCommandMsg = NULL;
212
    _TCHAR*   vmCommandMsg = NULL;
213
    int       vmCommandArgc = 0;
214
    _TCHAR*   jarFile = NULL;
329
    _TCHAR*   errorMsg;
215
    _TCHAR*   errorMsg;
330
    int       exitCode;
216
    int       exitCode;
331
    
217
    
Lines 355-361 Link Here
355
    }
241
    }
356
	
242
	
357
	/* Parse configuration file arguments */
243
	/* Parse configuration file arguments */
358
	if (isMainEclipse(argc, argv) && readConfigFile(program, argv[0], &configArgc, &configArgv) == 0)
244
	if (readConfigFile(program, argv[0], &configArgc, &configArgv) == 0)
359
	{
245
	{
360
		parseArgs (&configArgc, configArgv);
246
		parseArgs (&configArgc, configArgv);
361
	}
247
	}
Lines 375-548 Link Here
375
	/* Initialize official program name */
261
	/* Initialize official program name */
376
	officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName();
262
	officialName = name != NULL ? _tcsdup( name ) : getDefaultOfficialName();
377
263
378
    /* Initialize the window system. */
379
    initWindowSystem( &argc, argv, (showSplashArg != NULL) );
380
381
    /* Find the home directory where the Eclipse is installed. */
264
    /* Find the home directory where the Eclipse is installed. */
382
    homeDir = getInstallDir();
265
    homeDir = getInstallDir();
266
    
267
    /* Initialize the window system. */
268
    initWindowSystem( &argc, argv, homeDir );
269
270
	/* Error if home dir could not be determined */
383
    if (homeDir == NULL)
271
    if (homeDir == NULL)
384
    {
272
    {
385
        errorMsg = malloc( (_tcslen(homeMsg) + _tcslen(officialName) + 10) * sizeof(_TCHAR) );
273
        errorMsg = malloc( (_tcslen(homeMsg) + _tcslen(officialName) + _tcslen(startupJarName) + 10) * sizeof(_TCHAR) );
386
        _stprintf( errorMsg, homeMsg, officialName );
274
        _stprintf( errorMsg, homeMsg, officialName, startupJarName );
387
        displayMessage( errorMsg );
275
        displayMessage( errorMsg );
388
        free( errorMsg );
276
        free( errorMsg );
389
    	exit( 1 );
277
    	exit( 1 );
390
    }
278
    }
279
    
280
	/* Determine the location of the startup jar file */
281
	jarFile = getJarFile();
391
282
392
    /* If the exit data option was given, set exit data */
283
    /* Determine the Java VM to be used */
393
    if (exitDataArg != NULL)
284
   	javaVM = getJavaVM();
394
    {
395
       	/* If an extra argument was given, use it as the exit data, otherwise clear exit data */
396
       	data = argc > 1 ? argv[1] : NULL;
397
       	if (data != NULL && _tcslen( data ) > MAX_SHARED_LENGTH - 1)
398
       	{
399
       		exitCode = EINVAL;       		
400
       	}
401
       	else {
402
	        exitCode = setSharedData( exitDataArg, data );
403
    	}
404
   	    if (exitCode != 0 && debug) displayMessage( shareMsg );
405
		exit( exitCode );
406
    }
407
408
    /* If the showsplash option was given */
409
    if (showSplashArg != NULL)
410
    {
411
    	/* If an extra argument was given, pass it as the image to display. */
412
    	splashBitmap = (argc > 1 ? argv[1] : NULL);
413
    	exitCode = showSplash( showSplashArg, homeDir, splashBitmap );
414
    	if (exitCode && debug)
415
    	{
416
    		if (splashBitmap == NULL)
417
    			splashBitmap = homeDir;
418
        	errorMsg = malloc( (_tcslen(showMsg) + _tcslen(splashBitmap) + 10) * sizeof(_TCHAR) );
419
        	_stprintf( errorMsg, showMsg, splashBitmap );
420
        	displayMessage( errorMsg );
421
        	free( errorMsg );
422
     	}
423
    	exit( exitCode );
424
    }
425
426
    /* If the user did not specify a VM to be used */
427
    if (vmName == NULL)
428
    {
429
    	/* Determine which type of VM should be used. */
430
    	vmName = ((debug || needConsole) ? consoleVM : defaultVM);
431
432
        /* Try to find the VM shipped with eclipse. */
433
        shippedVM = malloc( (_tcslen( homeDir ) + _tcslen( shippedVMDir ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
434
        _stprintf( shippedVM, _T("%s%s%s"), homeDir, shippedVMDir, vmName );
435
        javaVM = findCommand( shippedVM );
436
437
        /* Format a message to indicate the default VM search path. */
438
        vmSearchPath = malloc( (_tcslen( pathMsg ) + _tcslen( shippedVM ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
439
        _stprintf( vmSearchPath, pathMsg, shippedVM, vmName );
440
        free( shippedVM );
441
        shippedVM = NULL;
442
	}
443
444
	/* If a Java VM has not been found yet */
445
	if (javaVM == NULL)
446
	{
447
		/* Either verify the VM specified by the user or
448
		   attempt to find the VM in the user's PATH. */
449
		javaVM = findCommand( vmName );
450
451
		/* If the VM was not found, display a message and exit. */
452
		if (javaVM == NULL)
453
		{
454
			if (vmSearchPath != NULL) vmName = vmSearchPath; /* used default VM searching */
455
        	errorMsg = malloc( (_tcslen(noVMMsg) + _tcslen(officialName) + _tcslen(vmName) + 10) * sizeof(_TCHAR) );
456
        	_stprintf( errorMsg, noVMMsg, officialName, vmName );
457
        	displayMessage( errorMsg );
458
        	free( errorMsg );
459
        	exit(1);
460
		}
461
	}
462
463
    if (createSharedData( &sharedID, MAX_SHARED_LENGTH )) {
464
        if (debug) {
465
   			if (debug) displayMessage( shareMsg );
466
        }
467
    }
468
469
    /* Get the command to start the Java VM. */
470
    vmCommandArgs = getVMCommand( argc, argv );
471
285
472
    /* While the Java VM should be restarted */
286
    /* Get the arguments to pass to the Java VM. */
473
    vmCommand = vmCommandArgs;
287
    vmCommandArgv = getVMArguments( argc, argv, &vmCommandArgc );
474
    while (vmCommand != NULL)
288
   	vmCommandMsg = formatVmCommandMsg( vmCommandArgc, vmCommandArgv );
475
    {
289
   	if (debug) _tprintf( goVMMsg, vmCommandMsg );
476
    	vmCommandMsg = formatVmCommandMsg( vmCommand );
290
  	
477
    	if (debug) _tprintf( goVMMsg, vmCommandMsg );
291
    /* Let 'er rip */
478
    	exitCode = startJavaVM( vmCommand );
292
   	exitCode = startJavaVM( javaVM, jarFile, startupClassName, vmCommandArgc, vmCommandArgv );
479
        switch( exitCode ) {
293
   	if (exitCode != 0)
480
            case 0:
294
   	{
481
                vmCommand = NULL;
295
   		errorMsg = malloc( (_tcslen(exitMsg) + _tcslen(vmCommandMsg) + 10) * sizeof(_TCHAR) );
482
            	break;
296
	    _stprintf( errorMsg, exitMsg, exitCode, vmCommandMsg );
483
            case RESTART_LAST_EC:
297
        displayMessage( errorMsg );
484
            	break;
298
        free( errorMsg );
485
            case RESTART_NEW_EC:
299
   	}
486
                if (getSharedData( sharedID, &data ) == 0) {
487
			    	if (vmCommandList != NULL) freeArgList( vmCommandList );
488
                    vmCommand = vmCommandList = parseArgList( data );
489
                } else {
490
                	vmCommand = NULL;
491
                    if (debug) displayMessage( shareMsg );
492
                }
493
                break;
494
			default:
495
                vmCommand = NULL;
496
                errorMsg = NULL;
497
                if (getSharedData( sharedID, &errorMsg ) == 0) {
498
                    if (_tcslen( errorMsg ) == 0) {
499
                	    free( errorMsg );
500
                	    errorMsg = NULL;
501
                    }
502
                } else {
503
                    if (debug) displayMessage( shareMsg );
504
                }
505
                if (errorMsg == NULL) {
506
	                errorMsg = malloc( (_tcslen(exitMsg) + _tcslen(vmCommandMsg) + 10) * sizeof(_TCHAR) );
507
	                _stprintf( errorMsg, exitMsg, exitCode, vmCommandMsg );
508
                }
509
	            displayMessage( errorMsg );
510
	            free( errorMsg );
511
                break;
512
        }
513
        free( vmCommandMsg );
514
    }
515
300
516
    /* Cleanup time. */
301
    /* Cleanup time. */
517
    free( homeDir );
302
    free( homeDir );
518
    free( program );
303
    free( program );
519
    if ( vmSearchPath != NULL ) free( vmSearchPath );
304
    if ( jarFile != NULL ) free( jarFile );
520
    if ( vmCommandList != NULL ) freeArgList( vmCommandList );
305
    if ( vmCommandMsg != NULL ) free( vmCommandMsg );
521
    if ( configArgv != NULL ) freeConfig( configArgv );
306
    if ( configArgv != NULL ) freeConfig( configArgv );
522
    if (configArgc > 1) free( argv );
307
    if (configArgc > 1) free( argv );
523
    free( officialName );
308
    free( officialName );
524
    if ( sharedID != NULL ) {
525
        if (destroySharedData( sharedID ) != 0) {
526
           if (debug) displayMessage( shareMsg );
527
        }
528
        free( sharedID );
529
    }
530
309
531
    return 0;
310
    return 0;
532
}
311
}
533
312
534
/* Return 1 if the current Eclipse is the process that starts the java IDE
535
 * Return 0 if it is an Eclipse used to display a splash screen or to write
536
 * data to a shared memory segment.
537
 * The main Eclipse is the only one that reads the eclipse.ini file.
538
 */
539
static int isMainEclipse( int argc, _TCHAR **argv )
540
{
541
	/* It is the main eclipse if the argument 1 is neither SHOWSPLASH nor EXITDATA */
542
	if (argc < 2) return 1;
543
	return (_tcsicmp( argv[1], SHOWSPLASH ) != 0 && _tcsicmp( argv[1], EXITDATA ) != 0);
544
}
545
546
/*
313
/*
547
 * Parse arguments of the command.
314
 * Parse arguments of the command.
548
 */
315
 */
Lines 632-674 Link Here
632
}
399
}
633
400
634
/*
401
/*
635
 * Free the memory allocated by parseArgList().
636
 */
637
static void freeArgList( _TCHAR** data ) {
638
	if (data == NULL) return;
639
	free( data [0] );
640
	free( data );
641
}
642
643
/*
644
 * Parse the data into a list of arguments separarted by \n.
645
 *
646
 * The list of strings returned by this function must be freed with
647
 * freeArgList().
648
 */
649
static _TCHAR** parseArgList( _TCHAR* data ) {
650
    int totalArgs = 0, dst = 0, length;
651
    _TCHAR *ch1, *ch2, **execArg;
652
    length = _tcslen( data );
653
    ch1 = ch2 = data;
654
    while ((ch2 = _tcschr( ch1, _T('\n') )) != NULL) {
655
    	totalArgs++;
656
    	ch1 = ch2 + 1;
657
    }
658
    if (ch1 != data + length) totalArgs++;
659
    execArg = malloc( (totalArgs + 1) * sizeof( _TCHAR* ) );
660
    ch1 = ch2 = data;
661
    while ((ch2 = _tcschr( ch1, _T('\n') )) != NULL) {
662
    	execArg[ dst++ ] = ch1;
663
    	ch2[ 0 ] = _T('\0');
664
    	ch1 = ch2 + 1;
665
    }
666
    if (ch1 != data + length) execArg[ dst++ ] = ch1;
667
    execArg[ dst++ ] = NULL;
668
    return execArg;
669
}
670
671
/*
672
 * Find the absolute pathname to where a command resides.
402
 * Find the absolute pathname to where a command resides.
673
 *
403
 *
674
 * The string returned by the function must be freed.
404
 * The string returned by the function must be freed.
Lines 804-810 Link Here
804
}
534
}
805
535
806
/*
536
/*
807
 * Get the command and arguments to start the Java VM.
537
 * Get the arguments to pass to the Java VM.
808
 *
538
 *
809
 * Memory allocated by this function is assumed to be
539
 * Memory allocated by this function is assumed to be
810
 * deallocated when the program terminates.
540
 * deallocated when the program terminates.
Lines 813-829 Link Here
813
 * passed directly from the main( argv ) array so they
543
 * passed directly from the main( argv ) array so they
814
 * should not be deallocated.
544
 * should not be deallocated.
815
 */
545
 */
816
static _TCHAR** getVMCommand( int argc, _TCHAR* argv[] )
546
static _TCHAR** getVMArguments( int argc, _TCHAR* argv[], int *dstArgc )
817
{
547
{
818
	_TCHAR** defVMarg;
819
    int     nDefVMarg = 0;
820
    int     nReqVMarg = 0;
821
    int     nUserVMarg = 0;
548
    int     nUserVMarg = 0;
822
    int     totalArgs;
549
    int     totalArgs;
823
    _TCHAR** execArg;
550
    _TCHAR** execArg;
824
    _TCHAR*  jarFile = NULL;
825
    _TCHAR*  splashExec;
826
	_TCHAR*  exitDataExec;
827
    int     src;
551
    int     src;
828
    int     dst;
552
    int     dst;
829
553
Lines 834-888 Link Here
834
 			nUserVMarg++;
558
 			nUserVMarg++;
835
 	}
559
 	}
836
560
837
 	/* Calculate the number of default VM arguments. */
561
    /* Allocate the arg list for the JVM
838
 	defVMarg = getArgVM( javaVM );
562
     *  (userVMargs + defaultVMargs + OS <os> + WS <ws> + ARCH <arch>
839
 	while (defVMarg[ nDefVMarg ] != NULL)
563
     *      + argv[] + NULL)
840
 		nDefVMarg++;
841
842
 	/* Calculate the number of required VM arguments. */
843
 	while (reqVMarg[ nReqVMarg ] != NULL)
844
 		nReqVMarg++;
845
846
    /* Allocate the arg list for the exec call.
847
     *  (VM + userVMargs + defaultVMargs + requiredVMargs + OS <os> + WS <ws> + ARCH <arch>
848
     *      + SHOWSPLASH <cmd> + EXITDATA <cmd> + argv[] + VM + <vm> + VMARGS + userVMargs + defaultVMargs + requiredVMargs
849
     *      + NULL)
850
     */
564
     */
851
    totalArgs  = 1 + nUserVMarg + nDefVMarg + nReqVMarg + 2 + 2 + 2 + 2 + 2 + argc + 2 + 1 + nUserVMarg + nDefVMarg + nReqVMarg + 1;
565
    totalArgs  = nUserVMarg + 2 + 2 + 2 + 2 + 2 + argc + 2 + 1;
852
	execArg = malloc( totalArgs * sizeof( _TCHAR* ) );
566
	execArg = malloc( totalArgs * sizeof( _TCHAR* ) );
853
    dst = 0;
567
    dst = 0;
854
    execArg[ dst++ ] = javaVM;
855
568
856
    /* If the user specified "-vmargs", add them instead of the default VM args. */
569
    /* For each user VM arg */
857
    if (userVMarg != NULL)
570
   	for (src = 0; src < nUserVMarg; src++)
858
    {
571
    	execArg[ dst++ ] = userVMarg[ src ];
859
    	for (src = 0; src < nUserVMarg; src++)
860
	    	execArg[ dst++ ] = userVMarg[ src ];
861
	}
862
	else
863
	{
864
    	for (src = 0; src < nDefVMarg; src++)
865
	    	execArg[ dst++ ] = defVMarg[ src ];
866
	}
867
572
868
    /* For each required VM arg */
869
	jarFile = malloc( (_tcslen( homeDir ) + _tcslen( startupJarName ) + 1) * sizeof( _TCHAR ) );
870
    jarFile = _tcscpy( jarFile, homeDir );
871
  	jarFile = _tcscat( jarFile, startupJarName );
872
	for (src = 0; src < nReqVMarg; src++)
873
    {
874
    	/* If the argument is not the startup jar, use it as is. */
875
     	if (_tcscmp( reqVMarg[ src ], startupJarName ) != 0)
876
     	{
877
	        execArg[ dst++ ] = reqVMarg[ src ];
878
	    }
879
880
	    /* else use the absolute path of the jar file. */
881
	    else
882
	    {
883
	        execArg[ dst++ ] = jarFile;
884
	    }
885
    }
886
573
887
	/* Append the required options. */
574
	/* Append the required options. */
888
    execArg[ dst++ ] = OS;
575
    execArg[ dst++ ] = OS;
Lines 892-953 Link Here
892
    execArg[ dst++ ] = OSARCH;
579
    execArg[ dst++ ] = OSARCH;
893
    execArg[ dst++ ] = osArchArg;
580
    execArg[ dst++ ] = osArchArg;
894
581
895
	/* Append the show splash window command, if defined. */
896
    if (!noSplash)
897
    {
898
        execArg[ dst++ ] = SHOWSPLASH;
899
		splashExec = malloc( (_tcslen( program ) + _tcslen(SHOWSPLASH) + _tcslen( splashTimeout ) + 3) * sizeof(_TCHAR) );
900
		_stprintf( splashExec, _T("%s %s %s"), program, SHOWSPLASH, splashTimeout );
901
	    execArg[ dst++ ] = splashExec;
902
    }
903
904
	/* Append the exit data command. */
905
	if (sharedID) {
906
	    execArg[ dst++ ] = EXITDATA;
907
	    exitDataExec = malloc( (_tcslen( program ) + _tcslen( EXITDATA ) + _tcslen( sharedID ) + 3) * sizeof(_TCHAR) );
908
	    _stprintf( exitDataExec, _T("%s %s %s"), program, EXITDATA, sharedID );
909
	    execArg[ dst++ ] = exitDataExec;
910
	}
911
912
	/* Append the remaining user defined arguments. */
582
	/* Append the remaining user defined arguments. */
913
    for (src = 1; src < argc; src++)
583
    for (src = 1; src < argc; src++)
914
    {
915
        execArg[ dst++ ] = argv[ src ];
584
        execArg[ dst++ ] = argv[ src ];
916
    }
917
918
    /* Append VM and VMARGS to be able to relaunch using exit data. */
919
	execArg[ dst++ ] = VM;
920
	execArg[ dst++ ] = javaVM;
921
    execArg[ dst++ ] = VMARGS;
922
    /* If the user specified "-vmargs", add them instead of the default VM args. */
923
    if (userVMarg != NULL)
924
    {
925
    	for (src = 0; src < nUserVMarg; src++)
926
	    	execArg[ dst++ ] = userVMarg[ src ];
927
	}
928
	else
929
	{
930
    	for (src = 0; src < nDefVMarg; src++)
931
	    	execArg[ dst++ ] = defVMarg[ src ];
932
	}
933
    /* For each required VM arg */
934
    for (src = 0; src < nReqVMarg; src++)
935
    {
936
    	/* If the argument is not the startup jar, use it as is. */
937
     	if (_tcscmp( reqVMarg[ src ], startupJarName ) != 0)
938
     	{
939
	        execArg[ dst++ ] = reqVMarg[ src ];
940
	    }
941
942
	    /* else use the absolute path of the jar file. */
943
	    else
944
	    {
945
	        execArg[ dst++ ] = jarFile;
946
	    }
947
    }
948
949
    execArg[ dst++ ] = NULL;
950
585
586
	*dstArgc = dst;
951
	return execArg;
587
	return execArg;
952
 }
588
 }
953
589
Lines 957-963 Link Here
957
  * that can be used in displaying error messages. The string returned from this
593
  * that can be used in displaying error messages. The string returned from this
958
  * method is probably not NLS compliant and must be deallocated by the caller.
594
  * method is probably not NLS compliant and must be deallocated by the caller.
959
  */
595
  */
960
static _TCHAR* formatVmCommandMsg( _TCHAR* args[] )
596
static _TCHAR* formatVmCommandMsg( int argc, _TCHAR* argv[] )
961
{
597
{
962
	int   index;
598
	int   index;
963
    int   length;
599
    int   length;
Lines 966-974 Link Here
966
602
967
	/* Determine the length of the message buffer. */
603
	/* Determine the length of the message buffer. */
968
	length = 0;
604
	length = 0;
969
	for (index = 0; args[index] != NULL; index++)
605
	for (index = 0; index < argc; index++)
970
	{
606
	{
971
		length += _tcslen(args[index]) + 1;
607
		length += _tcslen(argv[index]) + 1;
972
	}
608
	}
973
	message = malloc( (length + 5) * sizeof(_TCHAR) );
609
	message = malloc( (length + 5) * sizeof(_TCHAR) );
974
	
610
	
Lines 976-987 Link Here
976
	   on a new line. Otherwise, the Motif MessageBox does not automatically wrap
612
	   on a new line. Otherwise, the Motif MessageBox does not automatically wrap
977
	   the messages and the message window can extend beyond both sides of the display. */
613
	   the messages and the message window can extend beyond both sides of the display. */
978
	ch = message;
614
	ch = message;
979
	for (index = 0; args[index] != NULL; index++)
615
	for (index = 0; index < argc; index++)
980
	{
616
	{
981
		if (args[index][0] == _T('-') && *(ch-1) == _T(' '))
617
		if (argv[index][0] == _T('-') && *(ch-1) == _T(' '))
982
			*(ch-1) = _T('\n');
618
			*(ch-1) = _T('\n');
983
		_tcscpy( ch, args[index] );
619
		_tcscpy( ch, argv[index] );
984
		ch += _tcslen( args[index] );
620
		ch += _tcslen( argv[index] );
985
		*ch++ = _T(' ');
621
		*ch++ = _T(' ');
986
	}
622
	}
987
	*ch = _T('\0');
623
	*ch = _T('\0');
Lines 993-1005 Link Here
993
 * Determine the default official application name
629
 * Determine the default official application name
994
 *
630
 *
995
 * This function provides the default application name that appears in a variety of
631
 * This function provides the default application name that appears in a variety of
996
 * places such as: title of message dialog, title of splash screen window
632
 * places such as: title of message dialog that shows up in Windows task bar.
997
 * that shows up in Windows task bar.
998
 * It is computed from the name of the launcher executable and
633
 * It is computed from the name of the launcher executable and
999
 * by capitalizing the first letter. e.g. "c:/ide/eclipse.exe" provides
634
 * by capitalizing the first letter. e.g. "c:/ide/eclipse.exe" provides
1000
 * a default name of "Eclipse".
635
 * a default name of "Eclipse".
1001
 */
636
 */
1002
static _TCHAR* getDefaultOfficialName()
637
static _TCHAR* getDefaultOfficialName( void )
1003
{
638
{
1004
	_TCHAR *ch = NULL;
639
	_TCHAR *ch = NULL;
1005
	
640
	
Lines 1031-1037 Link Here
1031
 * contain the startup JAR file and the executable must be either in the
666
 * contain the startup JAR file and the executable must be either in the
1032
 * install directory or in a subdirectory.
667
 * install directory or in a subdirectory.
1033
 */
668
 */
1034
_TCHAR* getInstallDir( )
669
static _TCHAR* getInstallDir( void )
1035
{
670
{
1036
	_TCHAR*  ch;
671
	_TCHAR*  ch;
1037
	_TCHAR*  installDir;
672
	_TCHAR*  installDir;
Lines 1067-1069 Link Here
1067
    return NULL;
702
    return NULL;
1068
}
703
}
1069
704
705
/* 
706
 * Determine the Jar file name. Caller must free pointer returned.
707
 */
708
static _TCHAR* getJarFile( void )
709
{
710
	_TCHAR* jarFile = malloc( (_tcslen( homeDir ) + _tcslen( startupJarName ) + 1) * sizeof( _TCHAR ) );
711
    jarFile = _tcscpy( jarFile, homeDir );
712
  	jarFile = _tcscat( jarFile, startupJarName );
713
  	return jarFile;
714
}
715
716
/*
717
 * Determine the Java VM
718
 */
719
static _TCHAR* getJavaVM( void )
720
{
721
	_TCHAR* shippedVM = NULL;
722
	_TCHAR* javaVM = NULL;
723
    _TCHAR* vmSearchPath = NULL;
724
    _TCHAR* errorMsg = NULL;
725
    	
726
    /* If the user did not specify a VM to be used */
727
    if (vmName == NULL)
728
    {
729
    	/* Determine which type of VM should be used. */
730
    	vmName = ((debug || needConsole) ? consoleVM : defaultVM);
731
732
        /* Try to find the VM shipped with eclipse. */
733
        shippedVM = malloc( (_tcslen( homeDir ) + _tcslen( shippedVMDir ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
734
        _stprintf( shippedVM, _T("%s%s%s"), homeDir, shippedVMDir, vmName );
735
        javaVM = findCommand( shippedVM );
736
737
        /* Format a message to indicate the default VM search path. */
738
        vmSearchPath = malloc( (_tcslen( pathMsg ) + _tcslen( shippedVM ) + _tcslen( vmName ) + 10) * sizeof(_TCHAR) );
739
        _stprintf( vmSearchPath, pathMsg, shippedVM, vmName );
740
        free( shippedVM );
741
        shippedVM = NULL;
742
	}
743
744
	/* If a Java VM has not been found yet */
745
	if (javaVM == NULL)
746
	{
747
		/* Either verify the VM specified by the user or
748
		   attempt to find the VM in the user's PATH. */
749
		javaVM = findCommand( vmName );
750
751
		/* If the VM was not found, display a message and exit. */
752
		if (javaVM == NULL)
753
		{
754
			if (vmSearchPath != NULL) vmName = vmSearchPath; /* used default VM searching */
755
        	errorMsg = malloc( (_tcslen(noVMMsg) + _tcslen(officialName) + _tcslen(vmName) + 10) * sizeof(_TCHAR) );
756
        	_stprintf( errorMsg, noVMMsg, officialName, vmName );
757
        	displayMessage( errorMsg );
758
        	free( errorMsg );
759
        	exit(1);
760
		}
761
	}
762
    if ( vmSearchPath != NULL ) free( vmSearchPath );
763
	return javaVM;
764
}
(-)eclipseOS.h (-38 / +3 lines)
Lines 60-111 Link Here
60
 *
60
 *
61
 * This method is called after the command line arguments have been
61
 * This method is called after the command line arguments have been
62
 * parsed. Its purpose is to initialize the corresponding window system.
62
 * parsed. Its purpose is to initialize the corresponding window system.
63
 *
64
 * The showSplash flag indicates the splash window will be displayed by
65
 * this process (e.g., value will be zero for the main launcher).
66
 */
67
extern void initWindowSystem( int* argc, _TCHAR* argv[], int showSplash );
68
69
70
/** Show the Splash Window
71
 *
72
 * This method is called to display the actual splash window. It will only
73
 * be called by the splash window process and not the main launcher process.
74
 * The splash ID passed corresponds to the string returned from initWindowSystem().
75
 * If possible, this ID should be used to communicate some piece of data back
76
 * to the main launcher program for two reasons:
77
 * 1) to detect when the splash window process terminates
78
 * 2) to terminate the splash window process should the JVM terminate before it
79
 *    completes its initialization.
80
 *
81
 * Two parameters are passed: the install home directory and a specific bitmap image
82
 * file for a feature. The feature's image file is tried first and if it cannot be
83
 * displayed, the images from the install directory are used.
84
 *
85
 * Return (exit code):
86
 * 0        - success
87
 * non-zero - could not find a splash image to display
88
 */
89
extern int showSplash( _TCHAR* splashId, _TCHAR* homeDir, _TCHAR* featureImage );
90
91
92
/** Get List of Java VM Arguments
93
 *
94
 * A given Java VM might require a special set of arguments in order to
95
 * optimize its performance. This method returns a NULL terminated array
96
 * of strings, where each string is a separate VM argument.
97
 */
63
 */
98
extern _TCHAR** getArgVM( _TCHAR *vm );
64
extern void initWindowSystem( int* argc, _TCHAR* argv[], _TCHAR *homeDir );
99
100
65
101
/* Start the Java VM and Wait For It to Terminate
66
/** Start the Java VM and Wait For It to Terminate
102
 *
67
 *
103
 * This method is responsible for starting the Java VM and for
68
 * This method is responsible for starting the Java VM and for
104
 * detecting its termination. The resulting JVM exit code should
69
 * detecting its termination. The resulting JVM exit code should
105
 * be returned to the main launcher, which will display a message if
70
 * be returned to the main launcher, which will display a message if
106
 * the termination was not normal.
71
 * the termination was not normal.
107
 */
72
 */
108
extern int startJavaVM( _TCHAR* args[] );
73
extern int startJavaVM( _TCHAR* javaVM, _TCHAR* jarFile, _TCHAR* className, int argc, _TCHAR* argv[] );
109
74
110
#endif /* ECLIPSE_OS_H */
75
#endif /* ECLIPSE_OS_H */
111
76
(-)win32/eclipse.rc (-2 / +4 lines)
Lines 8-20 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
10
 *******************************************************************************/
11
11
 
12
#define ECLIPSE_ICON  401
12
#define ECLIPSE_ICON  401
13
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
14
#define RT_MANIFEST 24
13
15
14
#include "windows.h"
16
#include "windows.h"
15
#include "winver.h"
17
#include "winver.h"
16
18
17
18
ECLIPSE_ICON            ICON    DISCARDABLE     "eclipse.ico"
19
ECLIPSE_ICON            ICON    DISCARDABLE     "eclipse.ico"
20
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "eclipse.exe.manifest"
19
21
20
22
(-)win32/eclipseWin.c (-268 / +149 lines)
Lines 25-64 Link Here
25
/* Global Variables */
25
/* Global Variables */
26
_TCHAR   dirSeparator  = _T('\\');
26
_TCHAR   dirSeparator  = _T('\\');
27
_TCHAR   pathSeparator = _T(';');
27
_TCHAR   pathSeparator = _T(';');
28
_TCHAR*  consoleVM     = _T("java.exe");
28
#include <jni.h>       /* java native interface */
29
_TCHAR*  defaultVM     = _T("javaw.exe");
29
_TCHAR*  consoleVM     = _T("jni.dll");
30
_TCHAR*  shippedVMDir  = _T("jre\\bin\\");
30
_TCHAR*  defaultVM     = _T("jni.dll");
31
31
_TCHAR*  shippedVMDir  = _T("jre\\bin\\client\\");
32
/* Define the window system arguments for the Java VM. */
33
static _TCHAR*  argVM[] = { NULL };
34
35
/* Define local variables for the main window. */
36
static HWND    topWindow  = 0;
37
static WNDPROC oldProc;
38
32
39
/* Define local variables for running the JVM and detecting its exit. */
33
/* Define local variables for running the JVM and detecting its exit. */
40
static int     jvmProcess     = 0;
41
static int     jvmExitCode    = 0;
34
static int     jvmExitCode    = 0;
42
static int     jvmExitTimeout = 100;
43
static int     jvmExitTimerId = 99;
44
45
/* Define local variables for handling the splash window and its image. */
46
static _TCHAR*   loResSplash = _T("splash_basic.bmp");
47
static _TCHAR*   hiResSplash = _T("splash_full.bmp");
48
static int      splashTimerId = 88;
49
#define LO_RES_DEPTH 8
50
51
/* Local functions */
52
static void CALLBACK  detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime );
53
static HBITMAP        loadSplashImage(_TCHAR *baseDir, _TCHAR *fileName);
54
static void CALLBACK  splashTimeout( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime );
55
static LRESULT WINAPI WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
56
57
35
58
/* Display a Message */
36
/* Display a Message */
59
void displayMessage( _TCHAR* message )
37
void displayMessage( _TCHAR* message )
60
{
38
{
61
	MessageBox( topWindow, message, officialName, MB_OK );
39
	MessageBox( NULL, message, officialName, MB_OK );
62
}
40
}
63
41
64
/* Initialize Window System
42
/* Initialize Window System
Lines 68-337 Link Here
68
 * Return the window handle as the data for the splash command.
46
 * Return the window handle as the data for the splash command.
69
 *
47
 *
70
 */
48
 */
71
void initWindowSystem( int* pArgc, _TCHAR* argv[], int showSplash )
49
void initWindowSystem( int* argc, _TCHAR* argv[], _TCHAR *homeDir )
72
{
73
    /* Create a window that has no decorations. */
74
    topWindow = CreateWindowEx (0,
75
		_T("STATIC"),
76
		officialName,
77
		SS_BITMAP | WS_POPUP,
78
		0,
79
		0,
80
		0,
81
		0,
82
		NULL,
83
		NULL,
84
		GetModuleHandle (NULL),
85
		NULL);
86
    oldProc = (WNDPROC) GetWindowLong (topWindow, GWL_WNDPROC);
87
    SetWindowLong (topWindow, GWL_WNDPROC, (LONG) WndProc);
88
}
89
90
91
/* Show the Splash Window
92
 *
93
 * Open the bitmap, insert into the splash window and display it.
94
 *
95
 */
96
int showSplash( _TCHAR* timeoutString, _TCHAR* homeDir, _TCHAR* featureImage )
97
{
50
{
98
	int     timeout = 0;
99
    RECT    rect;
100
    HBITMAP hBitmap = 0;
101
    HDC     hDC;
102
    int     depth;
103
    int     x, y;
104
    int     width, height;
105
    MSG     msg;
106
107
	/* Determine the splash timeout value (in seconds). */
108
	if (timeoutString != NULL && _tcslen( timeoutString ) > 0)
109
	{
110
	    _stscanf( timeoutString, _T("%d"), &timeout );
111
	}
112
113
    /* Load the bitmap for the feature. */
114
    hDC = GetDC( NULL);
115
    depth = GetDeviceCaps( hDC, BITSPIXEL ) * GetDeviceCaps( hDC, PLANES);
116
    ReleaseDC(NULL, hDC);
117
    if (featureImage != NULL)
118
    	hBitmap = LoadImage(NULL, featureImage, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
119
120
    /* If the bitmap could not be found, try again using the install directory. */
121
    if (hBitmap == 0)
122
    	hBitmap = loadSplashImage( homeDir, depth <= LO_RES_DEPTH ? loResSplash : hiResSplash );
123
124
    /* If the bitmap could not be found, return an error. */
125
    if (hBitmap == 0)
126
    	return ERROR_FILE_NOT_FOUND;
127
128
	/* Load the bitmap into the splash popup window. */
129
    SendMessage( topWindow, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBitmap );
130
131
    /* Centre the splash window and display it. */
132
    GetWindowRect (topWindow, &rect);
133
    width = GetSystemMetrics (SM_CXSCREEN);
134
    height = GetSystemMetrics (SM_CYSCREEN);
135
    x = (width - (rect.right - rect.left)) / 2;
136
    y = (height - (rect.bottom - rect.top)) / 2;
137
    SetWindowPos (topWindow, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
138
    ShowWindow( topWindow, SW_SHOW );
139
    BringWindowToTop( topWindow );
140
51
141
	/* If a timeout for the splash window was given */
142
	if (timeout != 0)
143
	{
144
		/* Add a timeout (in milliseconds) to bring down the splash screen. */
145
        SetTimer( topWindow, splashTimerId, (timeout * 1000), splashTimeout );
146
	}
147
148
    /* Process messages until the splash window is closed or process is terminated. */
149
   	while (GetMessage( &msg, NULL, 0, 0 ))
150
   	{
151
		TranslateMessage( &msg );
152
		DispatchMessage( &msg );
153
	}
154
155
	return 0;
156
}
52
}
157
53
54
static jstring newJavaString(JNIEnv *env, char *s)
55
{    
56
	int len;
57
	jclass cls;
58
	jmethodID mid;
59
	jbyteArray ary;
60
	jstring str = 0;
61
	
62
	if (s == NULL)
63
		return 0;
64
	len = strlen(s);
65
	ary = (*env)->NewByteArray(env, len);
66
	if (ary != 0)
67
	{
68
		(*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
69
		if (!(*env)->ExceptionOccurred(env)) {
70
			cls = (*env)->FindClass(env, "java/lang/String");
71
			mid = (*env)->GetMethodID(env, cls, "<init>",  "([B)V");
72
		    str = (*env)->NewObject(env, cls, mid, ary);
73
		}
74
		(*env)->DeleteLocalRef(env, ary);
75
	} 
76
	return str;
77
}
78
79
static jobjectArray newJavaStringArray(JNIEnv *env, char **argv, int argc)
80
{
81
    jarray cls;
82
    jarray ary;
83
    int i;
84
85
    cls = (*env)->FindClass(env, "java/lang/String");
86
    ary = (*env)->NewObjectArray(env, argc, cls, 0);
87
    for (i = 0; i < argc; i++) {
88
		jstring str = newJavaString(env, *argv++);
89
		(*env)->SetObjectArrayElement(env, ary, i, str);
90
		(*env)->DeleteLocalRef(env, str);
91
    }
92
    return ary;
93
}
158
94
159
/* Get the window system specific VM args */
95
/**
160
_TCHAR** getArgVM( _TCHAR *vm )
96
 * Convert a wide string to a narrow one suitable for use in JNI.
97
 * Caller must free the null terminated string returned.
98
 */
99
static char *toNarrow(_TCHAR* src)
161
{
100
{
162
	return argVM;
101
#ifdef UNICODE
102
	int byteCount = WideCharToMultiByte (CP_ACP, 0, (wchar_t *)src, -1, NULL, 0, NULL, NULL);
103
	char *dest = malloc(byteCount+1);
104
	dest[byteCount] = 0;
105
	WideCharToMultiByte (CP_ACP, 0, (wchar_t *)src, -1, dest, byteCount, NULL, NULL);
106
	return dest;
107
#else
108
	return _tcsdup(src);
109
#endif
163
}
110
}
164
111
165
166
/* Start the Java VM
112
/* Start the Java VM
167
 *
113
 *
168
 * This method is called to start the Java virtual machine and to wait until it
114
 * This method is called to start the Java virtual machine and to wait until it
169
 * terminates. The function returns the exit code from the JVM.
115
 * terminates. The function returns the exit code from the JVM.
170
 */
116
 */
171
int startJavaVM( _TCHAR* args[] )
117
int startJavaVM( _TCHAR* javaVM, _TCHAR* jarFile, _TCHAR* className, int argc, _TCHAR* argv[] )
172
{
118
{
173
    MSG   msg;
119
	HINSTANCE jvmLibrary; // Library handle
174
	int   index, length;
120
	
175
	_TCHAR *commandLine, *ch, *space;
121
	//displayMessage(_T("jni invoke\n"));
176
122
	jvmLibrary = LoadLibrary(javaVM);
177
	/*
123
	/* If the child library (JVM) would not start */
178
	* Build the command line. Any argument with spaces must be in
124
	if (jvmLibrary == 0)
179
	* double quotes in the command line. 
180
	*/
181
	length = 0;
182
	for (index = 0; args[index] != NULL; index++)
183
	{
184
		/* String length plus space character */
185
		length += _tcslen( args[ index ] ) + 1;
186
		/* Quotes */
187
		if (_tcschr( args[ index ], _T(' ') ) != NULL) length += 2;
188
	}
189
	commandLine = ch = malloc ( (length + 1) * sizeof(_TCHAR) );
190
	for (index = 0; args[index] != NULL; index++)
191
	{
192
		space = _tcschr( args[ index ], _T(' '));
193
		if (space != NULL) *ch++ = _T('\"');
194
		_tcscpy( ch, args[index] );
195
		ch += _tcslen( args[index] );
196
		if (space != NULL) *ch++ = _T('\"');
197
		*ch++ = _T(' ');
198
	}
199
	*ch = _T('\0');
200
201
	/*
202
	* Start the Java virtual machine. Use CreateProcess() instead of spawnv()
203
	* otherwise the arguments cannot be freed since spawnv() segments fault.
204
	*/
205
	{
206
	STARTUPINFO    si;
207
    PROCESS_INFORMATION  pi;
208
    GetStartupInfo(&si);
209
    if (CreateProcess(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
210
    	CloseHandle( pi.hThread );
211
    	jvmProcess = (int)pi.hProcess;
212
    }    
213
	}
214
215
	free( commandLine );
216
217
	/* If the child process (JVM) would not start */
218
	if (jvmProcess == -1)
219
	{
125
	{
220
		/* Return the error number. */
126
		/* Return the error number. */
127
		displayMessage(_T("child lib would not start\n"));
221
		jvmExitCode = errno;
128
		jvmExitCode = errno;
222
		jvmProcess  = 0;
223
	}
129
	}
224
225
	/* else */
226
	else
130
	else
227
	{
131
	{
228
        /* Set a timer to detect JVM process termination. */
132
		/* Get the function addresses */
229
        SetTimer( topWindow, jvmExitTimerId, jvmExitTimeout, detectJvmExit );
133
		//displayMessage(_T("get function address\n"));
230
134
		jint (JNICALL *createJavaVM)(JavaVM **pvm, JNIEnv **env, void *args);
231
    	/* Process messages until the JVM terminates.
135
	    createJavaVM = (void *)GetProcAddress(jvmLibrary, "JNI_CreateJavaVM");
232
    	   This launcher process must continue to process events until the JVM exits
136
	    if (createJavaVM == 0)
233
    	   or else Windows 2K will hang if the desktop properties (e.g., background) are
137
		{
234
    	   changed by the user. Windows does a SendMessage() to every top level window
138
			/* Return the error number. */
235
    	   process, which blocks the caller until the process responds. */
139
			displayMessage(_T("createJavaVM or getDefaultJavaVMInitArgs address not found\n"));
236
   		while (jvmProcess != 0)
140
			jvmExitCode = errno;
237
   		{
141
		}
238
   			GetMessage( &msg, NULL, 0, 0 );
142
		else
239
			TranslateMessage( &msg );
143
		{
240
			DispatchMessage( &msg );
144
			JavaVM *jvm;       /* denotes a Java VM */
145
			JNIEnv *env;       /* pointer to native method interface */
146
			int i;
147
			char *narrowJarFile = toNarrow(jarFile);
148
			//displayMessage(jarFile);
149
			char *narrowClassName = toNarrow(className);
150
			//displayMessage(className);
151
			
152
			// documented here: http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html#JNI_CreateJavaVM
153
			//displayMessage(_T("pack arguments\n"));
154
			JavaVMInitArgs  vm_args = {0};
155
			JavaVMOption *options = malloc((1 + argc) * sizeof(JavaVMOption));
156
			memset(options, 0, (1 + argc) * sizeof(JavaVMOption));
157
			static char* classPath = "-Djava.class.path=";
158
			options[0].optionString = malloc(strlen(classPath) + strlen(narrowJarFile) + 1);
159
			strcpy(options[0].optionString, classPath);
160
			strcat(options[0].optionString, narrowJarFile);
161
			for (i = 0; i < argc; i++) {
162
			   options[i+1].optionString = toNarrow(argv[i]);
163
			}
164
			vm_args.version = JNI_VERSION_1_4;
165
			vm_args.options = options;
166
			vm_args.nOptions = 1 + argc;
167
			vm_args.ignoreUnrecognized = JNI_TRUE;
168
			
169
			/* load and initialize a Java VM, return a JNI interface pointer in env */
170
			//displayMessage(_T("about to create vm\n"));
171
			(*createJavaVM)(&jvm, &env, &vm_args);
172
			if (jvm == NULL)
173
			{
174
				displayMessage(_T("createJavaVM failed\n"));
175
				jvmExitCode = errno;
176
			}
177
			else
178
			{
179
				/* invoke the Main.test method using the JNI */
180
				//displayMessage(_T("about to FindClass\n"));
181
				jclass cls = (*env)->FindClass(env, narrowClassName);
182
				if (cls == NULL)
183
				{
184
					displayMessage(_T("FindClass failed\n"));
185
					jvmExitCode = errno;
186
				}
187
				else
188
				{
189
					//displayMessage(_T("about to GetStaticMethodID\n"));
190
					jmethodID mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
191
					if (mid == NULL)
192
					{
193
						displayMessage(_T("GetStaticMethodID failed\n"));
194
						jvmExitCode = errno;
195
					}
196
					else
197
					{
198
						//displayMessage(_T("about to call main\n"));
199
						(*env)->CallStaticVoidMethod(env, cls, mid,
200
							newJavaStringArray(env, NULL, 0));
201
						// shouldn't get here, but just in case...
202
						//displayMessage(_T("main complete, destroying vm\n"));
203
						/* We are done. */
204
						(*jvm)->DestroyJavaVM(jvm);
205
					}
206
				}
207
			}
208
			for (i = 0; i < vm_args.nOptions; i++)
209
			   free(options[i].optionString);
210
			free(options);
211
			free(narrowJarFile);
212
			free(narrowClassName);
241
		}
213
		}
242
243
		/* Kill the timer. */
244
        KillTimer( topWindow, jvmExitTimerId );
245
	}
214
	}
246
215
247
	/* Return the exit code from the JVM. */
216
	/* Return the exit code from the JVM. */
248
	return jvmExitCode;
217
	return jvmExitCode;
249
}
218
}
250
251
/* Local functions */
252
253
/* Detect JVM Process Termination */
254
static void CALLBACK detectJvmExit( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime )
255
{
256
    DWORD   exitCode;
257
258
    /* If the JVM process has terminated */
259
    if (!GetExitCodeProcess( (HANDLE)jvmProcess, &exitCode ) ||
260
    		 exitCode != STILL_ACTIVE)
261
    {
262
    	/* Save the JVM exit code. This should cause the loop in startJavaVM() to exit. */
263
        jvmExitCode = exitCode;
264
        jvmProcess = 0;
265
    }
266
}
267
268
/* Splash Timeout */
269
static void CALLBACK splashTimeout( HWND hwnd, UINT uMsg, UINT id, DWORD dwTime )
270
{
271
	/* Kill the timer. */
272
    KillTimer( topWindow, id );
273
	PostMessage( topWindow, WM_QUIT, 0, 0 );
274
}
275
276
277
/* Load the splash image depending on the current locale.
278
 *
279
 * This is the search sequence for an USA english locale:
280
 *
281
 *     1 - <homeDir>splash\en_US\<fileName>
282
 *     2 - <homeDir>splash\en\<fileName>
283
 *     3 - <homeDir>splash\<fileName>
284
 *
285
 * Returns an HBITMAP or NULL if the file can not be found.
286
 */
287
static HBITMAP loadSplashImage(_TCHAR* baseDir, _TCHAR* fileName)
288
{
289
	HBITMAP hBitmap = NULL;
290
	LCID locale;
291
	_TCHAR lang[4] = {0};
292
	_TCHAR country[4] = {0};
293
	_TCHAR *splashFile;
294
295
	locale = GetThreadLocale ();
296
	GetLocaleInfo(locale, LOCALE_SISO639LANGNAME, lang, 4);
297
	GetLocaleInfo(locale, LOCALE_SISO3166CTRYNAME, country, 4);
298
299
	splashFile = malloc ( (_tcslen( baseDir ) + 256) * sizeof(_TCHAR) );
300
301
    _stprintf( splashFile, _T("%s\\splash\\%s_%s\\%s"), baseDir, lang, country, fileName );
302
	hBitmap = LoadImage (NULL, splashFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
303
304
	if (hBitmap == NULL)
305
	{
306
		_stprintf( splashFile, _T("%s\\splash\\%s\\%s"), baseDir, lang, fileName );
307
		hBitmap = LoadImage (NULL, splashFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
308
	}
309
310
	if (hBitmap == NULL)
311
	{
312
		_stprintf( splashFile, _T("%s\\splash\\%s"), baseDir, fileName );
313
		hBitmap = LoadImage (NULL, splashFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
314
	}
315
316
	free (splashFile);
317
	return hBitmap;
318
}
319
320
321
/* Window Procedure for the Spash window.
322
 *
323
 * A special WndProc is needed to return the proper vlaue for WM_NCHITTEST.
324
 * It must also detect the message from the splash window process.
325
 */
326
static LRESULT WINAPI WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
327
{
328
	switch (uMsg)
329
	{
330
		case WM_NCHITTEST: return HTCLIENT;
331
		case WM_CLOSE:
332
	    	PostQuitMessage(  0 );
333
	    	break;
334
	}
335
	return CallWindowProc (oldProc, hwnd, uMsg, wParam, lParam);
336
}
337
(-)win32/make_mingw.mak (-1 / +4 lines)
Lines 34-39 Link Here
34
RC      = $(TDIR)/i586-pc-cygwin-windres
34
RC      = $(TDIR)/i586-pc-cygwin-windres
35
SYSINC  = -isystem $(TDIR)/../include/mingw
35
SYSINC  = -isystem $(TDIR)/../include/mingw
36
endif
36
endif
37
JDK_HOME="C:\Program Files\Java\jdk1.5.0_01"
38
JNIINC  = -I$(JDK_HOME)/include/ -I$(JDK_HOME)/include/win32
39
#CDEBUG = -g
37
40
38
ifeq ($(CC),)
41
ifeq ($(CC),)
39
$(error Unable to find $(CCVER)-pc-cygwin-gcc)
42
$(error Unable to find $(CCVER)-pc-cygwin-gcc)
Lines 48-54 Link Here
48
EXEC	= $(PROGRAM_OUTPUT)
51
EXEC	= $(PROGRAM_OUTPUT)
49
DEBUG	= $(CDEBUG)
52
DEBUG	= $(CDEBUG)
50
CFLAGS	= -O -s -Wall \
53
CFLAGS	= -O -s -Wall \
51
	  -I. $(SYSINC) \
54
	  -I. $(JNIINC) $(SYSINC) \
52
	  -D_WIN32 \
55
	  -D_WIN32 \
53
	  -DWIN32_LEAN_AND_MEAN \
56
	  -DWIN32_LEAN_AND_MEAN \
54
	  -mno-cygwin
57
	  -mno-cygwin
(-)win32/eclipse.exe.manifest (+10 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
3
	<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="IBM.Eclipse.eclipse" type="win32"/>
4
	<description>Eclipse IDE</description>
5
	<dependency>
6
		<dependentAssembly>
7
			<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"/>
8
		</dependentAssembly>
9
	</dependency>
10
</assembly>

Return to bug 82518