Added support for Unicode applications in winebuild.

Removed cuiexe_no_main hack.
Avoid stdcall function declarations inside functions because of gcc bug.
This commit is contained in:
Alexandre Julliard 2000-12-15 03:38:11 +00:00
parent 57f8eb71da
commit 909eff9932
9 changed files with 114 additions and 52 deletions

View File

@ -1027,6 +1027,7 @@ debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem
# Command-line # Command-line
@ cdecl __wine_get_main_args(ptr) __wine_get_main_args @ cdecl __wine_get_main_args(ptr) __wine_get_main_args
@ cdecl __wine_get_wmain_args(ptr) __wine_get_wmain_args
# Server interface # Server interface
@ cdecl -norelay wine_server_call(long) wine_server_call @ cdecl -norelay wine_server_call(long) wine_server_call

View File

@ -9,6 +9,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "winbase.h" #include "winbase.h"
#include "winnls.h"
#include "wine/library.h" #include "wine/library.h"
#include "options.h" #include "options.h"
#include "version.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 int app_argc; /* argc/argv to pass to application */
static char **app_argv; static char **app_argv;
static WCHAR **app_wargv;
static void out_of_memory(void) WINE_NORETURN; static void out_of_memory(void) WINE_NORETURN;
static void out_of_memory(void) static void out_of_memory(void)
@ -358,3 +360,35 @@ int __wine_get_main_args( char ***argv )
return app_argc; 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;
}

View File

@ -18,11 +18,10 @@ extern void PROCESS_InitWine( int argc, char *argv[] ) WINE_NORETURN;
/*********************************************************************** /***********************************************************************
* Main loop of initial task * 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; MSG msg;
HINSTANCE16 instance; HINSTANCE16 instance;
STARTUPINFOA info;
if (!LoadLibraryA( "user32.dll" )) if (!LoadLibraryA( "user32.dll" ))
{ {
@ -31,10 +30,7 @@ void wine_initial_task(void)
} }
THUNK_InitCallout(); THUNK_InitCallout();
GetStartupInfoA( &info ); if ((instance = WinExec16( GetCommandLineA(), show )) < 32)
if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL;
if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32)
{ {
if (instance == 11) /* try DOS format */ if (instance == 11) /* try DOS format */
{ {

View File

@ -1,5 +1,5 @@
name wine name wine
mode cuiexe_no_main mode guiexe
type win32 type win32
init wine_initial_task init wine_initial_task

View File

@ -4,11 +4,13 @@
name NAME name NAME
type win16|win32 type win16|win32
[file WINFILENAME] [file WINFILENAME]
[mode dll|cuiexe|guiexe] [mode dll|cuiexe|guiexe|cuiexe_unicode|guiexe_unicode]
[heap SIZE] [heap SIZE]
[init FUNCTION] [init FUNCTION]
[import DLL] [import DLL]
[rsrc RESFILE] [rsrc RESFILE]
[debug_channels ([CHANNEL [CHANNEL...]])]
[ignore ([SYMBOL [SYMBOL...]])]
ORDINAL FUNCTYPE [FLAGS] EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME ORDINAL FUNCTYPE [FLAGS] EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME
@ -51,6 +53,11 @@ times.
"rsrc" specifies the path of the compiled resource file. "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 "ORDINAL" specified the ordinal number corresponding to the entry
point, or "@" for automatic ordinal allocation (Win32 only). point, or "@" for automatic ordinal allocation (Win32 only).

View File

@ -60,8 +60,8 @@ typedef enum
SPEC_MODE_DLL, SPEC_MODE_DLL,
SPEC_MODE_GUIEXE, SPEC_MODE_GUIEXE,
SPEC_MODE_CUIEXE, SPEC_MODE_CUIEXE,
SPEC_MODE_GUIEXE_NO_MAIN, SPEC_MODE_GUIEXE_UNICODE,
SPEC_MODE_CUIEXE_NO_MAIN SPEC_MODE_CUIEXE_UNICODE
} SPEC_MODE; } SPEC_MODE;
typedef struct typedef struct

View File

@ -205,6 +205,8 @@ static void add_extra_undef_symbols(void)
/* add symbols that will be contained in the spec file itself */ /* add symbols that will be contained in the spec file itself */
switch (SpecMode) switch (SpecMode)
{ {
case SPEC_MODE_DLL:
break;
case SPEC_MODE_GUIEXE: case SPEC_MODE_GUIEXE:
ADD_SYM( "GetCommandLineA" ); ADD_SYM( "GetCommandLineA" );
ADD_SYM( "GetStartupInfoA" ); ADD_SYM( "GetStartupInfoA" );
@ -213,13 +215,19 @@ static void add_extra_undef_symbols(void)
case SPEC_MODE_CUIEXE: case SPEC_MODE_CUIEXE:
ADD_SYM( "__wine_get_main_args" ); ADD_SYM( "__wine_get_main_args" );
ADD_SYM( "ExitProcess" ); ADD_SYM( "ExitProcess" );
break;
case SPEC_MODE_GUIEXE_UNICODE:
ADD_SYM( "GetCommandLineA" );
ADD_SYM( "GetStartupInfoA" );
ADD_SYM( "GetModuleHandleA" );
/* fall through */ /* fall through */
case SPEC_MODE_DLL: case SPEC_MODE_CUIEXE_UNICODE:
case SPEC_MODE_GUIEXE_NO_MAIN: ADD_SYM( "__wine_get_wmain_args" );
case SPEC_MODE_CUIEXE_NO_MAIN: ADD_SYM( "ExitProcess" );
ADD_SYM( "RtlRaiseException" );
break; break;
} }
ADD_SYM( "RtlRaiseException" );
if (count) if (count)
{ {
for (i = 0; i < count; i++) add_undef_symbol( extras[i] ); for (i = 0; i < count; i++) add_undef_symbol( extras[i] );

View File

@ -560,9 +560,9 @@ SPEC_TYPE ParseTopLevel( FILE *file )
if (!strcmp(token, "dll" )) SpecMode = SPEC_MODE_DLL; if (!strcmp(token, "dll" )) SpecMode = SPEC_MODE_DLL;
else if (!strcmp(token, "guiexe" )) SpecMode = SPEC_MODE_GUIEXE; else if (!strcmp(token, "guiexe" )) SpecMode = SPEC_MODE_GUIEXE;
else if (!strcmp(token, "cuiexe" )) SpecMode = SPEC_MODE_CUIEXE; 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, "guiexe_unicode" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE;
else if (!strcmp(token, "cuiexe_no_main" )) SpecMode = SPEC_MODE_CUIEXE_NO_MAIN; else if (!strcmp(token, "cuiexe_unicode" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE;
else fatal_error( "Mode must be 'dll', 'guiexe', 'cuiexe', 'guiexe_no_main' or 'cuiexe_no_main'\n" ); else fatal_error( "Mode must be 'dll', 'guiexe', 'cuiexe', 'guiexe_unicode' or 'cuiexe_unicode'\n" );
} }
else if (strcmp(token, "heap") == 0) else if (strcmp(token, "heap") == 0)
{ {

View File

@ -341,15 +341,16 @@ static void output_stub_funcs( FILE *outfile )
if (odp->type != TYPE_STUB) continue; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\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, "static void __wine_unimplemented( const char *func )\n{\n" );
fprintf( outfile, " struct exc_record {\n" ); fprintf( outfile, " struct exc_record rec;\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, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB ); fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.rec = 0;\n" );
@ -414,7 +415,7 @@ void BuildSpec32File( FILE *outfile )
{ {
int exports_size = 0; int exports_size = 0;
int nr_exports, nr_imports, nr_resources, nr_debug; int nr_exports, nr_imports, nr_resources, nr_debug;
int characteristics, subsystem, has_imports; int characteristics, subsystem;
const char *init_func; const char *init_func;
DWORD page_size; DWORD page_size;
@ -431,7 +432,7 @@ void BuildSpec32File( FILE *outfile )
AssignOrdinals(); AssignOrdinals();
nr_exports = Base <= Limit ? Limit - Base + 1 : 0; 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", fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
input_file_name ); input_file_name );
@ -503,9 +504,9 @@ void BuildSpec32File( FILE *outfile )
"\n#include <winbase.h>\n" "\n#include <winbase.h>\n"
"int _ARGC;\n" "int _ARGC;\n"
"char **_ARGV;\n" "char **_ARGV;\n"
"extern int __stdcall %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n"
"static void __wine_exe_main(void)\n" "static void __wine_exe_main(void)\n"
"{\n" "{\n"
" extern int PASCAL %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n"
" extern int __wine_get_main_args( char ***argv );\n" " extern int __wine_get_main_args( char ***argv );\n"
" STARTUPINFOA info;\n" " STARTUPINFOA info;\n"
" LPSTR cmdline = GetCommandLineA();\n" " LPSTR cmdline = GetCommandLineA();\n"
@ -516,47 +517,62 @@ void BuildSpec32File( FILE *outfile )
" _ARGC = __wine_get_main_args( &_ARGV );\n" " _ARGC = __wine_get_main_args( &_ARGV );\n"
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n" " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
"}\n\n", init_func, init_func ); "}\n\n", init_func, init_func );
if (!has_imports) init_func = "__wine_exe_main";
fprintf( outfile, subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
"int main( int argc, char *argv[] )\n" break;
"{\n" case SPEC_MODE_GUIEXE_UNICODE:
" extern void PROCESS_InitWinelib( int, char ** );\n" if (!init_func) init_func = "WinMain";
" PROCESS_InitWinelib( argc, argv );\n" fprintf( outfile,
" return 1;\n" "\n#include <winbase.h>\n"
"}\n\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"; init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break; break;
case SPEC_MODE_CUIEXE: case SPEC_MODE_CUIEXE:
if (!init_func) init_func = has_imports ? "main" : "wine_main"; if (!init_func) init_func = "main";
fprintf( outfile, fprintf( outfile,
"\nint _ARGC;\n" "\nint _ARGC;\n"
"char **_ARGV;\n" "char **_ARGV;\n"
"extern void __stdcall ExitProcess(int);\n"
"static void __wine_exe_main(void)\n" "static void __wine_exe_main(void)\n"
"{\n" "{\n"
" extern int %s( int argc, char *argv[] );\n" " extern int %s( int argc, char *argv[] );\n"
" extern int __wine_get_main_args( 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" " _ARGC = __wine_get_main_args( &_ARGV );\n"
" ExitProcess( %s( _ARGC, _ARGV ) );\n" " ExitProcess( %s( _ARGC, _ARGV ) );\n"
"}\n\n", init_func, init_func ); "}\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"; init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break; break;
case SPEC_MODE_GUIEXE_NO_MAIN: case SPEC_MODE_CUIEXE_UNICODE:
if (init_func) fprintf( outfile, "extern void %s();\n", init_func ); if (!init_func) init_func = "wmain";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; fprintf( outfile,
break; "\ntypedef unsigned short WCHAR;\n"
case SPEC_MODE_CUIEXE_NO_MAIN: "int _ARGC;\n"
if (init_func) fprintf( outfile, "extern void %s();\n", init_func ); "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; subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break; break;
} }