Commit 909eff99 authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for Unicode applications in winebuild.

Removed cuiexe_no_main hack. Avoid stdcall function declarations inside functions because of gcc bug.
parent 57f8eb71
......@@ -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
......
......@@ -9,6 +9,7 @@
#include <stdlib.h>
#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;
}
......@@ -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 */
{
......
name wine
mode cuiexe_no_main
mode guiexe
type win32
init wine_initial_task
......
......@@ -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).
......
......@@ -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
......
......@@ -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] );
......
......@@ -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)
{
......
......@@ -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, "static void __wine_unimplemented( const char *func )\n{\n" );
fprintf( outfile, " struct exc_record {\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, " } rec;\n" );
fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n\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 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 <winbase.h>\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)
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case SPEC_MODE_GUIEXE_UNICODE:
if (!init_func) init_func = "WinMain";
fprintf( outfile,
"int main( int argc, char *argv[] )\n"
"\n#include <winbase.h>\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 void PROCESS_InitWinelib( int, char ** );\n"
" PROCESS_InitWinelib( argc, argv );\n"
" return 1;\n"
"}\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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment