Unicode support for CRT startup

Jan Hlavatý <[email protected]> Mon, 12 May 2003 05:21:33 +0200
Newsgroups gmane.comp.gnu.mingw.patches
Organization Bohemia Interactive Studio
Message-ID <[email protected]>
Hi,

I've been playing tonight with Unicode support in mingw32.
Found that there were no unicode startup objects, so I patched together 
these.

To use Unicode entrypoints, in addition to defining UNICODE and _UNICODE
you must set executable's entrypoint to _wWinMainCRTStartup (or 
_wmainCRTStartup) using -Wl,--entry=_wWinMainCRTStartup

I'd like to see something like this integrated into runtime
so we can build dual unicode/ansi builds as intended with tchar.h and 
company...

diff1 - diff of changes against runtime 3.0 and w32api 2.3

diff2 - how to make wmain.c out of main.c

Jan
diff1.txt (text/plain, 5.9 KB)
diff -r -c mingworig/runtime/Makefile.in mingwr/runtime/Makefile.in
*** mingworig/runtime/Makefile.in	Tue May  6 16:01:52 2003
--- mingwr/runtime/Makefile.in	Mon May 12 02:24:46 2003
***************
*** 151,157 ****
  CRT0S = crt1.o dllcrt1.o crt2.o dllcrt2.o CRT_noglob.o crtmt.o crtst.o \
  	CRT_fp8.o CRT_fp10.o txtmode.o binmode.o
  MINGW_OBJS = CRTglob.o CRTfmode.o CRTinit.o  dllmain.o gccmain.o \
! 	     main.o crtst.o mthr_stub.o CRT_fp10.o txtmode.o \
  	     pseudo-reloc.o pseudo-reloc-list.o
  MOLD_OBJS = ctype_old.o string_old.o
  
--- 151,157 ----
  CRT0S = crt1.o dllcrt1.o crt2.o dllcrt2.o CRT_noglob.o crtmt.o crtst.o \
  	CRT_fp8.o CRT_fp10.o txtmode.o binmode.o
  MINGW_OBJS = CRTglob.o CRTfmode.o CRTinit.o  dllmain.o gccmain.o \
! 	     main.o wmain.o crtst.o mthr_stub.o CRT_fp10.o txtmode.o \
  	     pseudo-reloc.o pseudo-reloc-list.o
  MOLD_OBJS = ctype_old.o string_old.o
  
***************
*** 163,169 ****
  SRCDIST_FILES = CRT_noglob.c CRTfmode.c CRTglob.c CRTinit.c ChangeLog \
  Makefile.in README TODO config.guess config.sub configure configure.in \
  crt1.c crtdll.def crtmt.c crtst.c ctype_old.c  dllcrt1.c dllmain.c \
! gccmain.c init.c install-sh jamfile main.c mkinstalldirs \
  moldname.def.in msvcrt.def.in \
  mthr.c mthr_init.c mthr_stub.c readme.txt string_old.c \
  CRT_fp8.c CRT_fp10.c test_headers.c txtmode.c binmode.c pseudo-reloc.c \
--- 163,169 ----
  SRCDIST_FILES = CRT_noglob.c CRTfmode.c CRTglob.c CRTinit.c ChangeLog \
  Makefile.in README TODO config.guess config.sub configure configure.in \
  crt1.c crtdll.def crtmt.c crtst.c ctype_old.c  dllcrt1.c dllmain.c \
! gccmain.c init.c install-sh jamfile main.c wmain.c mkinstalldirs \
  moldname.def.in msvcrt.def.in \
  mthr.c mthr_init.c mthr_stub.c readme.txt string_old.c \
  CRT_fp8.c CRT_fp10.c test_headers.c txtmode.c binmode.c pseudo-reloc.c \
***************
*** 428,433 ****
--- 428,434 ----
  dllcrt2.o: dllcrt1.c 
  dllmain.o: dllmain.c
  main.o: main.c
+ wmain.o: wmain.c
  oldnames.o: oldnames.c
  string_old.o: string_old.c
  CRT_fp8.o: CRT_fp8.c
diff -r -c mingworig/runtime/crt1.c mingwr/runtime/crt1.c
*** mingworig/runtime/crt1.c	Mon Jan  6 21:14:18 2003
--- mingwr/runtime/crt1.c	Mon May 12 02:31:40 2003
***************
*** 229,234 ****
--- 229,290 ----
    return 0;
  }
  
+ 
+ static int
+ __mingw_wCRTStartup ()
+ {
+   int nRet;
+ 
+   /*
+    * Set up the top-level exception handler so that signal handling
+    * works as expected. The mapping between ANSI/POSIX signals and
+    * Win32 SE is not 1-to-1, so caveat emptore.
+    * 
+    */
+   SetUnhandledExceptionFilter (_gnu_exception_handler);
+ 
+   /*
+    * Initialize floating point unit.
+    */
+   _fpreset ();			/* Supplied by the runtime library. */
+ 
+   /*
+    * Set up __argc, __argv and _environ.
+    */
+   _mingw32_init_wmainargs ();
+ 
+   /*
+    * Sets the default file mode.
+    * If _CRT_fmode is set, also set mode for stdin, stdout
+    * and stderr, as well
+    * NOTE: DLLs don't do this because that would be rude!
+    */
+   _mingw32_init_fmode ();
+ 
+   
+    /* Adust references to dllimported data that have non-zero offsets.  */
+   _pei386_runtime_relocator ();
+ 
+   /*
+    * Call the main function. If the user does not supply one
+    * the one in the 'libmingw32.a' library will be linked in, and
+    * that one calls WinMain. See main.c in the 'lib' dir
+    * for more details.
+    */
+   nRet = wmain (_argc, _argv, environ);
+ 
+   /*
+    * Perform exit processing for the C library. This means
+    * flushing output and calling 'atexit' registered functions.
+    */
+   _cexit ();
+ 
+   ExitProcess (nRet);
+ 
+   return 0;
+ }
+ 
+ 
  /*
   * The function mainCRTStartup is the entry point for all console programs.
   */
***************
*** 242,247 ****
--- 298,313 ----
    return 0;
  }
  
+ int
+ wmainCRTStartup ()
+ {
+ #ifdef __MSVCRT__
+   __set_app_type (__CONSOLE_APP);
+ #endif
+   __mingw_wCRTStartup ();
+   return 0;
+ }
+ 
  /*
   * For now the GUI startup function is the same as the console one.
   * This simply gets rid of the annoying warning about not being able
***************
*** 256,261 ****
--- 322,340 ----
    __mingw_CRTStartup ();
  return 0;
  }
+ 
+ int
+ wWinMainCRTStartup ()
+ {
+ #ifdef __MSVCRT__
+   __set_app_type (__GUI_APP);
+ #endif
+   __mingw_wCRTStartup ();
+ return 0;
+ }	
+ 	
+ 
+ 
  
  /*
   *  We force use of library version of atexit, which is only
diff -r -c mingworig/runtime/include/tchar.h mingwr/runtime/include/tchar.h
*** mingworig/runtime/include/tchar.h	Wed May  7 02:36:14 2003
--- mingwr/runtime/include/tchar.h	Mon May 12 02:27:40 2003
***************
*** 70,76 ****
  #define	__TEXT(q)	L##q
  
  /*  for porting from other Windows compilers */
! #if 0  /* no  wide startup module */
  #define _tmain      wmain
  #define _tWinMain   wWinMain
  #define _tenviron   _wenviron
--- 70,76 ----
  #define	__TEXT(q)	L##q
  
  /*  for porting from other Windows compilers */
! #if 1  /* no  wide startup module */
  #define _tmain      wmain
  #define _tWinMain   wWinMain
  #define _tenviron   _wenviron
diff -r -c mingworig/runtime/init.c mingwr/runtime/init.c
*** mingworig/runtime/init.c	Tue Jun  5 00:26:30 2001
--- mingwr/runtime/init.c	Mon May 12 02:33:12 2003
***************
*** 82,84 ****
--- 82,106 ----
  #endif
  }
  
+ static void
+ _mingw32_init_wmainargs ()
+ {
+   /* The environ variable is provided directly in stdlib.h through
+    * a dll function call. */
+   char **dummy_environ;
+ #ifdef __MSVCRT__
+   _startupinfo start_info;
+   start_info.newmode = 0;
+ #endif
+ 
+   /*
+    * Microsoft's runtime provides a function for doing just that.
+    */
+ #ifdef __MSVCRT__
+   (void) __wgetmainargs (&_argc, &_argv, &dummy_environ, _CRT_glob, 
+                         &start_info);
+ #else
+   /* CRTDLL version */
+   (void) __GetMainArgs (&_argc, &_argv, &dummy_environ, _CRT_glob);
+ #endif
+ }
Only in mingwr/runtime: msvcrt.def
Only in mingwr/runtime: msvcrtd.def
Only in mingwr/runtime: wmain.c
diff2.txt (text/plain, 2.6 KB)
*** main.c	Tue Jun  5 00:26:30 2001
--- wmain.c	Mon May 12 02:35:56 2003
***************
*** 1,30 ****
  /*
!  * main.c
!  *
!  * Extra startup code for applications which do not have a main function
!  * of their own (but do have a WinMain). Generally these are GUI
!  * applications, but they don't *have* to be.
!  *
!  * This file is part of the Mingw32 package.
!  *
!  * Contributors:
!  *  Created by Colin Peters <[email protected]>
!  *  Maintained by Mumit Khan <[email protected]>
!  *
!  *  THIS SOFTWARE IS NOT COPYRIGHTED
!  *
!  *  This source code is offered for use in the public domain. You may
!  *  use, modify or distribute it freely.
!  *
!  *  This code is distributed in the hope that it will be useful but
!  *  WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
!  *  DISCLAMED. This includes but is not limited to warrenties of
!  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
!  *
!  * $Revision: 1.2 $
!  * $Author: earnie $
!  * $Date: 2001/06/05 00:26:30 $
   *
   */
  
  #include <stdlib.h>
--- 1,7 ----
  /*
!  * wmain.c
   *
+  * clone of main.c with Unicode support
   */
  
  #include <stdlib.h>
***************
*** 33,51 ****
  
  #define ISSPACE(a)	(a == ' ' || a == '\t')
  
! extern int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, 
!                            LPSTR szCmdLine, int nShow);
  
  int
! main (int argc, char *argv[], char *environ[])
  {
!   char *szCmd;
    STARTUPINFO startinfo;
    int nRet;
  
    /* Get the command line passed to the process. */
!   szCmd = GetCommandLineA ();
!   GetStartupInfoA (&startinfo);
  
    /* Strip off the name of the application and any leading
     * whitespace. */
--- 10,28 ----
  
  #define ISSPACE(a)	(a == ' ' || a == '\t')
  
! extern int PASCAL wWinMain (HINSTANCE hInst, HINSTANCE hPrevInst, 
!                            LPWSTR szCmdLine, int nShow);
  
  int
! wmain (int argc, wchar_t *argv[], wchar_t *environ[])
  {
!   wchar_t *szCmd;
    STARTUPINFO startinfo;
    int nRet;
  
    /* Get the command line passed to the process. */
!   szCmd = GetCommandLineW ();
!   GetStartupInfoW (&startinfo);
  
    /* Strip off the name of the application and any leading
     * whitespace. */
***************
*** 87,93 ****
  	}
      }
  
!   nRet = WinMain (GetModuleHandle (NULL), NULL, szCmd,
  		  (startinfo.dwFlags & STARTF_USESHOWWINDOW) ?
  		  startinfo.wShowWindow : SW_SHOWDEFAULT);
  
--- 64,70 ----
  	}
      }
  
!   nRet = wWinMain (GetModuleHandle (NULL), NULL, szCmd,
  		  (startinfo.dwFlags & STARTF_USESHOWWINDOW) ?
  		  startinfo.wShowWindow : SW_SHOWDEFAULT);