From 909eff9932a8f365eb9b5b5a257423b12ea1ad51 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 15 Dec 2000 03:38:11 +0000 Subject: [PATCH] Added support for Unicode applications in winebuild. Removed cuiexe_no_main hack. Avoid stdcall function declarations inside functions because of gcc bug. --- dlls/ntdll/ntdll.spec | 1 + misc/options.c | 34 ++++++++++++++++ miscemu/main.c | 8 +--- miscemu/wine.spec | 2 +- tools/winebuild/README | 9 ++++- tools/winebuild/build.h | 4 +- tools/winebuild/import.c | 16 ++++++-- tools/winebuild/parser.c | 6 +-- tools/winebuild/spec32.c | 86 ++++++++++++++++++++++++---------------- 9 files changed, 114 insertions(+), 52 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index e025ebfb477..ee0afade9c2 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1027,6 +1027,7 @@ debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem # Command-line @ cdecl __wine_get_main_args(ptr) __wine_get_main_args +@ cdecl __wine_get_wmain_args(ptr) __wine_get_wmain_args # Server interface @ cdecl -norelay wine_server_call(long) wine_server_call diff --git a/misc/options.c b/misc/options.c index 22b9fb4cf1f..64add27c937 100644 --- a/misc/options.c +++ b/misc/options.c @@ -9,6 +9,7 @@ #include #include "winbase.h" +#include "winnls.h" #include "wine/library.h" #include "options.h" #include "version.h" @@ -42,6 +43,7 @@ static char *inherit_str; /* options to pass to child processes */ static int app_argc; /* argc/argv to pass to application */ static char **app_argv; +static WCHAR **app_wargv; static void out_of_memory(void) WINE_NORETURN; static void out_of_memory(void) @@ -358,3 +360,35 @@ int __wine_get_main_args( char ***argv ) return app_argc; } + +/*********************************************************************** + * __wine_get_wmain_args + * + * Same as __wine_get_main_args but for Unicode. + */ +int __wine_get_wmain_args( WCHAR ***argv ) +{ + if (!app_wargv) + { + int i; + WCHAR *p; + DWORD total = 0; + + for (i = 0; i < app_argc; i++) + total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 ); + + app_wargv = HeapAlloc( GetProcessHeap(), 0, + total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) ); + p = (WCHAR *)(app_wargv + app_argc + 1); + for (i = 0; i < app_argc; i++) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total ); + app_wargv[i] = p; + p += len; + total -= len; + } + app_wargv[app_argc] = NULL; + } + *argv = app_wargv; + return app_argc; +} diff --git a/miscemu/main.c b/miscemu/main.c index 666b8f8eb59..5bcb2d66b2b 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -18,11 +18,10 @@ extern void PROCESS_InitWine( int argc, char *argv[] ) WINE_NORETURN; /*********************************************************************** * Main loop of initial task */ -void wine_initial_task(void) +int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT show ) { MSG msg; HINSTANCE16 instance; - STARTUPINFOA info; if (!LoadLibraryA( "user32.dll" )) { @@ -31,10 +30,7 @@ void wine_initial_task(void) } THUNK_InitCallout(); - GetStartupInfoA( &info ); - if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL; - - if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32) + if ((instance = WinExec16( GetCommandLineA(), show )) < 32) { if (instance == 11) /* try DOS format */ { diff --git a/miscemu/wine.spec b/miscemu/wine.spec index 9917659b4ab..a6ded8576eb 100644 --- a/miscemu/wine.spec +++ b/miscemu/wine.spec @@ -1,5 +1,5 @@ name wine -mode cuiexe_no_main +mode guiexe type win32 init wine_initial_task diff --git a/tools/winebuild/README b/tools/winebuild/README index e82939c2548..dfdde443008 100644 --- a/tools/winebuild/README +++ b/tools/winebuild/README @@ -4,11 +4,13 @@ name NAME type win16|win32 [file WINFILENAME] -[mode dll|cuiexe|guiexe] +[mode dll|cuiexe|guiexe|cuiexe_unicode|guiexe_unicode] [heap SIZE] [init FUNCTION] [import DLL] [rsrc RESFILE] +[debug_channels ([CHANNEL [CHANNEL...]])] +[ignore ([SYMBOL [SYMBOL...]])] ORDINAL FUNCTYPE [FLAGS] EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME @@ -51,6 +53,11 @@ times. "rsrc" specifies the path of the compiled resource file. +"debug_channels" specifies the list of debug channels used by the dll. + +"ignore" specifies a list of symbols that should be ignored when +resolving undefined symbols against the imported libraries. + "ORDINAL" specified the ordinal number corresponding to the entry point, or "@" for automatic ordinal allocation (Win32 only). diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index dc0cff2d77f..e182674cd51 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -60,8 +60,8 @@ typedef enum SPEC_MODE_DLL, SPEC_MODE_GUIEXE, SPEC_MODE_CUIEXE, - SPEC_MODE_GUIEXE_NO_MAIN, - SPEC_MODE_CUIEXE_NO_MAIN + SPEC_MODE_GUIEXE_UNICODE, + SPEC_MODE_CUIEXE_UNICODE } SPEC_MODE; typedef struct diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 839290aa728..b050b8fe400 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -205,6 +205,8 @@ static void add_extra_undef_symbols(void) /* add symbols that will be contained in the spec file itself */ switch (SpecMode) { + case SPEC_MODE_DLL: + break; case SPEC_MODE_GUIEXE: ADD_SYM( "GetCommandLineA" ); ADD_SYM( "GetStartupInfoA" ); @@ -213,13 +215,19 @@ static void add_extra_undef_symbols(void) case SPEC_MODE_CUIEXE: ADD_SYM( "__wine_get_main_args" ); ADD_SYM( "ExitProcess" ); + break; + case SPEC_MODE_GUIEXE_UNICODE: + ADD_SYM( "GetCommandLineA" ); + ADD_SYM( "GetStartupInfoA" ); + ADD_SYM( "GetModuleHandleA" ); /* fall through */ - case SPEC_MODE_DLL: - case SPEC_MODE_GUIEXE_NO_MAIN: - case SPEC_MODE_CUIEXE_NO_MAIN: - ADD_SYM( "RtlRaiseException" ); + case SPEC_MODE_CUIEXE_UNICODE: + ADD_SYM( "__wine_get_wmain_args" ); + ADD_SYM( "ExitProcess" ); break; } + ADD_SYM( "RtlRaiseException" ); + if (count) { for (i = 0; i < count; i++) add_undef_symbol( extras[i] ); diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 3dc99f3d70c..e08165d0ed2 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -560,9 +560,9 @@ SPEC_TYPE ParseTopLevel( FILE *file ) if (!strcmp(token, "dll" )) SpecMode = SPEC_MODE_DLL; else if (!strcmp(token, "guiexe" )) SpecMode = SPEC_MODE_GUIEXE; else if (!strcmp(token, "cuiexe" )) SpecMode = SPEC_MODE_CUIEXE; - else if (!strcmp(token, "guiexe_no_main" )) SpecMode = SPEC_MODE_GUIEXE_NO_MAIN; - else if (!strcmp(token, "cuiexe_no_main" )) SpecMode = SPEC_MODE_CUIEXE_NO_MAIN; - else fatal_error( "Mode must be 'dll', 'guiexe', 'cuiexe', 'guiexe_no_main' or 'cuiexe_no_main'\n" ); + else if (!strcmp(token, "guiexe_unicode" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE; + else if (!strcmp(token, "cuiexe_unicode" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE; + else fatal_error( "Mode must be 'dll', 'guiexe', 'cuiexe', 'guiexe_unicode' or 'cuiexe_unicode'\n" ); } else if (strcmp(token, "heap") == 0) { diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index c82df025fcc..9400e15899a 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -341,15 +341,16 @@ static void output_stub_funcs( FILE *outfile ) if (odp->type != TYPE_STUB) continue; fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); - fprintf( outfile, "#endif\n" ); + fprintf( outfile, "#endif\n\n" ); + fprintf( outfile, "struct exc_record {\n" ); + fprintf( outfile, " unsigned int code, flags;\n" ); + fprintf( outfile, " void *rec, *addr;\n" ); + fprintf( outfile, " unsigned int params;\n" ); + fprintf( outfile, " const void *info[15];\n" ); + fprintf( outfile, "};\n\n" ); + fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" ); - fprintf( outfile, " struct exc_record {\n" ); - fprintf( outfile, " unsigned int code, flags;\n" ); - fprintf( outfile, " void *rec, *addr;\n" ); - fprintf( outfile, " unsigned int params;\n" ); - fprintf( outfile, " const void *info[15];\n" ); - fprintf( outfile, " } rec;\n" ); - fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" ); + fprintf( outfile, " struct exc_record rec;\n" ); fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB ); fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.rec = 0;\n" ); @@ -414,7 +415,7 @@ void BuildSpec32File( FILE *outfile ) { int exports_size = 0; int nr_exports, nr_imports, nr_resources, nr_debug; - int characteristics, subsystem, has_imports; + int characteristics, subsystem; const char *init_func; DWORD page_size; @@ -431,7 +432,7 @@ void BuildSpec32File( FILE *outfile ) AssignOrdinals(); nr_exports = Base <= Limit ? Limit - Base + 1 : 0; - has_imports = resolve_imports( outfile ); + resolve_imports( outfile ); fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n", input_file_name ); @@ -503,9 +504,9 @@ void BuildSpec32File( FILE *outfile ) "\n#include \n" "int _ARGC;\n" "char **_ARGV;\n" + "extern int __stdcall %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n" "static void __wine_exe_main(void)\n" "{\n" - " extern int PASCAL %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n" " extern int __wine_get_main_args( char ***argv );\n" " STARTUPINFOA info;\n" " LPSTR cmdline = GetCommandLineA();\n" @@ -516,47 +517,62 @@ void BuildSpec32File( FILE *outfile ) " _ARGC = __wine_get_main_args( &_ARGV );\n" " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n" "}\n\n", init_func, init_func ); - if (!has_imports) - fprintf( outfile, - "int main( int argc, char *argv[] )\n" - "{\n" - " extern void PROCESS_InitWinelib( int, char ** );\n" - " PROCESS_InitWinelib( argc, argv );\n" - " return 1;\n" - "}\n\n" ); + init_func = "__wine_exe_main"; + subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; + break; + case SPEC_MODE_GUIEXE_UNICODE: + if (!init_func) init_func = "WinMain"; + fprintf( outfile, + "\n#include \n" + "int _ARGC;\n" + "WCHAR **_ARGV;\n" + "extern int __stdcall %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n" + "static void __wine_exe_main(void)\n" + "{\n" + " extern int __wine_get_wmain_args( WCHAR ***argv );\n" + " STARTUPINFOA info;\n" + " LPSTR cmdline = GetCommandLineA();\n" + " while (*cmdline && *cmdline != ' ') cmdline++;\n" + " if (*cmdline) cmdline++;\n" + " GetStartupInfoA( &info );\n" + " if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;\n" + " _ARGC = __wine_get_wmain_args( &_ARGV );\n" + " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n" + "}\n\n", init_func, init_func ); init_func = "__wine_exe_main"; subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; break; case SPEC_MODE_CUIEXE: - if (!init_func) init_func = has_imports ? "main" : "wine_main"; + if (!init_func) init_func = "main"; fprintf( outfile, "\nint _ARGC;\n" "char **_ARGV;\n" + "extern void __stdcall ExitProcess(int);\n" "static void __wine_exe_main(void)\n" "{\n" " extern int %s( int argc, char *argv[] );\n" " extern int __wine_get_main_args( char ***argv );\n" - " extern void __stdcall ExitProcess(int);\n" " _ARGC = __wine_get_main_args( &_ARGV );\n" " ExitProcess( %s( _ARGC, _ARGV ) );\n" "}\n\n", init_func, init_func ); - if (!has_imports) - fprintf( outfile, - "int main( int argc, char *argv[] )\n" - "{\n" - " extern void PROCESS_InitWinelib( int, char ** );\n" - " PROCESS_InitWinelib( argc, argv );\n" - " return 1;\n" - "}\n\n" ); init_func = "__wine_exe_main"; subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; break; - case SPEC_MODE_GUIEXE_NO_MAIN: - if (init_func) fprintf( outfile, "extern void %s();\n", init_func ); - subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; - break; - case SPEC_MODE_CUIEXE_NO_MAIN: - if (init_func) fprintf( outfile, "extern void %s();\n", init_func ); + case SPEC_MODE_CUIEXE_UNICODE: + if (!init_func) init_func = "wmain"; + fprintf( outfile, + "\ntypedef unsigned short WCHAR;\n" + "int _ARGC;\n" + "WCHAR **_ARGV;\n" + "extern void __stdcall ExitProcess(int);\n" + "static void __wine_exe_main(void)\n" + "{\n" + " extern int %s( int argc, WCHAR *argv[] );\n" + " extern int __wine_get_wmain_args( WCHAR ***argv );\n" + " _ARGC = __wine_get_wmain_args( &_ARGV );\n" + " ExitProcess( %s( _ARGC, _ARGV ) );\n" + "}\n\n", init_func, init_func ); + init_func = "__wine_exe_main"; subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; break; }