Home | History | Annotate | Download | only in win32
      1 /*
      2     SDL_main.c, placed in the public domain by Sam Lantinga  4/13/98
      3 
      4     The WinMain function -- calls your program's main() function
      5 */
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #define WIN32_LEAN_AND_MEAN
     11 #include <windows.h>
     12 
     13 #ifdef _WIN32_WCE
     14 # define DIR_SEPERATOR TEXT("\\")
     15 # undef _getcwd
     16 # define _getcwd(str,len)	wcscpy(str,TEXT(""))
     17 # define setbuf(f,b)
     18 # define setvbuf(w,x,y,z)
     19 # define fopen		_wfopen
     20 # define freopen	_wfreopen
     21 # define remove(x)	DeleteFile(x)
     22 #else
     23 # define DIR_SEPERATOR TEXT("/")
     24 # include <direct.h>
     25 #endif
     26 
     27 /* Include the SDL main definition header */
     28 #include "SDL.h"
     29 #include "SDL_main.h"
     30 
     31 #ifdef main
     32 # ifndef _WIN32_WCE_EMULATION
     33 #  undef main
     34 # endif /* _WIN32_WCE_EMULATION */
     35 #endif /* main */
     36 
     37 /* The standard output files */
     38 #define STDOUT_FILE	TEXT("stdout.txt")
     39 #define STDERR_FILE	TEXT("stderr.txt")
     40 
     41 #ifndef NO_STDIO_REDIRECT
     42 # ifdef _WIN32_WCE
     43   static wchar_t stdoutPath[MAX_PATH];
     44   static wchar_t stderrPath[MAX_PATH];
     45 # else
     46   static char stdoutPath[MAX_PATH];
     47   static char stderrPath[MAX_PATH];
     48 # endif
     49 #endif
     50 
     51 #if defined(_WIN32_WCE) && _WIN32_WCE < 300
     52 /* seems to be undefined in Win CE although in online help */
     53 #define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t'))
     54 #endif /* _WIN32_WCE < 300 */
     55 
     56 /* Parse a command line buffer into arguments */
     57 static int ParseCommandLine(char *cmdline, char **argv)
     58 {
     59 	char *bufp;
     60 	int argc;
     61 
     62 	argc = 0;
     63 	for ( bufp = cmdline; *bufp; ) {
     64 		/* Skip leading whitespace */
     65 		while ( isspace(*bufp) ) {
     66 			++bufp;
     67 		}
     68 		/* Skip over argument */
     69 		if ( *bufp == '"' ) {
     70 			++bufp;
     71 			if ( *bufp ) {
     72 				if ( argv ) {
     73 					argv[argc] = bufp;
     74 				}
     75 				++argc;
     76 			}
     77 			/* Skip over word */
     78 			while ( *bufp && (*bufp != '"') ) {
     79 				++bufp;
     80 			}
     81 		} else {
     82 			if ( *bufp ) {
     83 				if ( argv ) {
     84 					argv[argc] = bufp;
     85 				}
     86 				++argc;
     87 			}
     88 			/* Skip over word */
     89 			while ( *bufp && ! isspace(*bufp) ) {
     90 				++bufp;
     91 			}
     92 		}
     93 		if ( *bufp ) {
     94 			if ( argv ) {
     95 				*bufp = '\0';
     96 			}
     97 			++bufp;
     98 		}
     99 	}
    100 	if ( argv ) {
    101 		argv[argc] = NULL;
    102 	}
    103 	return(argc);
    104 }
    105 
    106 /* Show an error message */
    107 static void ShowError(const char *title, const char *message)
    108 {
    109 /* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
    110 #ifdef USE_MESSAGEBOX
    111 	MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
    112 #else
    113 	fprintf(stderr, "%s: %s\n", title, message);
    114 #endif
    115 }
    116 
    117 /* Pop up an out of memory message, returns to Windows */
    118 static BOOL OutOfMemory(void)
    119 {
    120 	ShowError("Fatal Error", "Out of memory - aborting");
    121 	return FALSE;
    122 }
    123 
    124 /* SDL_Quit() shouldn't be used with atexit() directly because
    125    calling conventions may differ... */
    126 static void cleanup(void)
    127 {
    128 	SDL_Quit();
    129 }
    130 
    131 /* Remove the output files if there was no output written */
    132 static void cleanup_output(void)
    133 {
    134 #ifndef NO_STDIO_REDIRECT
    135 	FILE *file;
    136 	int empty;
    137 #endif
    138 
    139 	/* Flush the output in case anything is queued */
    140 	fclose(stdout);
    141 	fclose(stderr);
    142 
    143 #ifndef NO_STDIO_REDIRECT
    144 	/* See if the files have any output in them */
    145 	if ( stdoutPath[0] ) {
    146 		file = fopen(stdoutPath, TEXT("rb"));
    147 		if ( file ) {
    148 			empty = (fgetc(file) == EOF) ? 1 : 0;
    149 			fclose(file);
    150 			if ( empty ) {
    151 				remove(stdoutPath);
    152 			}
    153 		}
    154 	}
    155 	if ( stderrPath[0] ) {
    156 		file = fopen(stderrPath, TEXT("rb"));
    157 		if ( file ) {
    158 			empty = (fgetc(file) == EOF) ? 1 : 0;
    159 			fclose(file);
    160 			if ( empty ) {
    161 				remove(stderrPath);
    162 			}
    163 		}
    164 	}
    165 #endif
    166 }
    167 
    168 #if defined(_MSC_VER) && !defined(_WIN32_WCE)
    169 /* The VC++ compiler needs main defined */
    170 #define console_main main
    171 #endif
    172 
    173 /* This is where execution begins [console apps] */
    174 int console_main(int argc, char *argv[])
    175 {
    176 	size_t n;
    177 	char *bufp, *appname;
    178 	int status;
    179 
    180 	/* Get the class name from argv[0] */
    181 	appname = argv[0];
    182 	if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) {
    183 		appname = bufp+1;
    184 	} else
    185 	if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) {
    186 		appname = bufp+1;
    187 	}
    188 
    189 	if ( (bufp=SDL_strrchr(appname, '.')) == NULL )
    190 		n = SDL_strlen(appname);
    191 	else
    192 		n = (bufp-appname);
    193 
    194 	bufp = SDL_stack_alloc(char, n+1);
    195 	if ( bufp == NULL ) {
    196 		return OutOfMemory();
    197 	}
    198 	SDL_strlcpy(bufp, appname, n+1);
    199 	appname = bufp;
    200 
    201 	/* Load SDL dynamic link library */
    202 	if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
    203 		ShowError("WinMain() error", SDL_GetError());
    204 		return(FALSE);
    205 	}
    206 	atexit(cleanup_output);
    207 	atexit(cleanup);
    208 
    209 	/* Sam:
    210 	   We still need to pass in the application handle so that
    211 	   DirectInput will initialize properly when SDL_RegisterApp()
    212 	   is called later in the video initialization.
    213 	 */
    214 	SDL_SetModuleHandle(GetModuleHandle(NULL));
    215 
    216 	/* Run the application main() code */
    217 	status = SDL_main(argc, argv);
    218 
    219 	/* Exit cleanly, calling atexit() functions */
    220 	exit(status);
    221 
    222 	/* Hush little compiler, don't you cry... */
    223 	return 0;
    224 }
    225 
    226 /* This is where execution begins [windowed apps] */
    227 #ifdef _WIN32_WCE
    228 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw)
    229 #else
    230 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
    231 #endif
    232 {
    233 	HINSTANCE handle;
    234 	char **argv;
    235 	int argc;
    236 	char *cmdline;
    237 #ifdef _WIN32_WCE
    238 	wchar_t *bufp;
    239 	int nLen;
    240 #else
    241 	char *bufp;
    242 	size_t nLen;
    243 #endif
    244 #ifndef NO_STDIO_REDIRECT
    245 	DWORD pathlen;
    246 #ifdef _WIN32_WCE
    247 	wchar_t path[MAX_PATH];
    248 #else
    249 	char path[MAX_PATH];
    250 #endif
    251 	FILE *newfp;
    252 #endif
    253 
    254 	/* Start up DDHELP.EXE before opening any files, so DDHELP doesn't
    255 	   keep them open.  This is a hack.. hopefully it will be fixed
    256 	   someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
    257 	 */
    258 	handle = LoadLibrary(TEXT("DDRAW.DLL"));
    259 	if ( handle != NULL ) {
    260 		FreeLibrary(handle);
    261 	}
    262 
    263 #ifndef NO_STDIO_REDIRECT
    264 	pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path));
    265 	while ( pathlen > 0 && path[pathlen] != '\\' ) {
    266 		--pathlen;
    267 	}
    268 	path[pathlen] = '\0';
    269 
    270 #ifdef _WIN32_WCE
    271 	wcsncpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
    272 	wcsncat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
    273 #else
    274 	SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) );
    275 	SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
    276 #endif
    277 
    278 	/* Redirect standard input and standard output */
    279 	newfp = freopen(stdoutPath, TEXT("w"), stdout);
    280 
    281 #ifndef _WIN32_WCE
    282 	if ( newfp == NULL ) {	/* This happens on NT */
    283 #if !defined(stdout)
    284 		stdout = fopen(stdoutPath, TEXT("w"));
    285 #else
    286 		newfp = fopen(stdoutPath, TEXT("w"));
    287 		if ( newfp ) {
    288 			*stdout = *newfp;
    289 		}
    290 #endif
    291 	}
    292 #endif /* _WIN32_WCE */
    293 
    294 #ifdef _WIN32_WCE
    295 	wcsncpy( stderrPath, path, SDL_arraysize(stdoutPath) );
    296 	wcsncat( stderrPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) );
    297 #else
    298 	SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) );
    299 	SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) );
    300 #endif
    301 
    302 	newfp = freopen(stderrPath, TEXT("w"), stderr);
    303 #ifndef _WIN32_WCE
    304 	if ( newfp == NULL ) {	/* This happens on NT */
    305 #if !defined(stderr)
    306 		stderr = fopen(stderrPath, TEXT("w"));
    307 #else
    308 		newfp = fopen(stderrPath, TEXT("w"));
    309 		if ( newfp ) {
    310 			*stderr = *newfp;
    311 		}
    312 #endif
    313 	}
    314 #endif /* _WIN32_WCE */
    315 
    316 	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);	/* Line buffered */
    317 	setbuf(stderr, NULL);			/* No buffering */
    318 #endif /* !NO_STDIO_REDIRECT */
    319 
    320 #ifdef _WIN32_WCE
    321 	nLen = wcslen(szCmdLine)+128+1;
    322 	bufp = SDL_stack_alloc(wchar_t, nLen*2);
    323 	wcscpy (bufp, TEXT("\""));
    324 	GetModuleFileName(NULL, bufp+1, 128-3);
    325 	wcscpy (bufp+wcslen(bufp), TEXT("\" "));
    326 	wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
    327 	nLen = wcslen(bufp)+1;
    328 	cmdline = SDL_stack_alloc(char, nLen);
    329 	if ( cmdline == NULL ) {
    330 		return OutOfMemory();
    331 	}
    332 	WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
    333 #else
    334 	/* Grab the command line */
    335 	bufp = GetCommandLine();
    336 	nLen = SDL_strlen(bufp)+1;
    337 	cmdline = SDL_stack_alloc(char, nLen);
    338 	if ( cmdline == NULL ) {
    339 		return OutOfMemory();
    340 	}
    341 	SDL_strlcpy(cmdline, bufp, nLen);
    342 #endif
    343 
    344 	/* Parse it into argv and argc */
    345 	argc = ParseCommandLine(cmdline, NULL);
    346 	argv = SDL_stack_alloc(char*, argc+1);
    347 	if ( argv == NULL ) {
    348 		return OutOfMemory();
    349 	}
    350 	ParseCommandLine(cmdline, argv);
    351 
    352 	/* Run the main program (after a little SDL initialization) */
    353 	console_main(argc, argv);
    354 
    355 	/* Hush little compiler, don't you cry... */
    356 	return 0;
    357 }
    358