diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index afb6fd19cf7..c7da34df17f 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -53,6 +53,7 @@ typedef enum typedef enum { SPEC_MODE_DLL, + SPEC_MODE_NATIVE, SPEC_MODE_GUIEXE, SPEC_MODE_CUIEXE, SPEC_MODE_GUIEXE_UNICODE, diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 023f45c75ed..a8f367ced65 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -569,6 +569,7 @@ static void add_extra_undef_symbols( const DLLSPEC *spec ) switch (spec->mode) { case SPEC_MODE_DLL: + case SPEC_MODE_NATIVE: break; case SPEC_MODE_GUIEXE: kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec ); diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index ce7ff312c8c..615089c3f66 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -268,6 +268,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) else if (!strcmp( optarg, "cui" )) spec->mode = SPEC_MODE_CUIEXE; else if (!strcmp( optarg, "guiw" )) spec->mode = SPEC_MODE_GUIEXE_UNICODE; else if (!strcmp( optarg, "cuiw" )) spec->mode = SPEC_MODE_CUIEXE_UNICODE; + else if (!strcmp( optarg, "native" )) spec->mode = SPEC_MODE_NATIVE; else usage(1); break; case 'o': diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 8588e720676..994a9b2372a 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -71,6 +71,27 @@ static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const c return buffer; } +/******************************************************************* + * declare_weak_function + * + * Output a prototype for a weak function. + */ +static void declare_weak_function( FILE *outfile, const char *name, const char *prototype ) +{ + fprintf( outfile, "#ifdef __GNUC__\n" ); + fprintf( outfile, "# ifdef __APPLE__\n" ); + fprintf( outfile, "extern %s __attribute__((weak_import));\n", prototype ); + fprintf( outfile, "# else\n" ); + fprintf( outfile, "extern %s __attribute__((weak));\n", prototype ); + fprintf( outfile, "# endif\n" ); + fprintf( outfile, "#else\n" ); + fprintf( outfile, "extern %s;\n", prototype ); + fprintf( outfile, "static void __asm__dummy_%s(void)", name ); + fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name ); + fprintf( outfile, "#endif\n\n" ); +} + + /******************************************************************* * output_debug * @@ -559,17 +580,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func ); else { - fprintf( outfile, "#ifdef __GNUC__\n" ); - fprintf( outfile, "# ifdef __APPLE__\n" ); - fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak_import));\n" ); - fprintf( outfile, "# else\n" ); - fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* ) __attribute__((weak));\n" ); - fprintf( outfile, "# endif\n" ); - fprintf( outfile, "#else\n" ); - fprintf( outfile, "extern int __stdcall DllMain( void*, unsigned int, void* );\n" ); - fprintf( outfile, "static void __asm__dummy_dllmain(void)" ); - fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" ); - fprintf( outfile, "#endif\n\n" ); + declare_weak_function( outfile, "DllMain", + "int __stdcall DllMain( void*, unsigned int, void* )" ); init_func = "DllMain"; } fprintf( outfile, @@ -586,6 +598,29 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) init_func = "__wine_dll_main"; characteristics = IMAGE_FILE_DLL; break; + case SPEC_MODE_NATIVE: + if (init_func) + fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func ); + else + { + declare_weak_function( outfile, "DriverEntry", + "int __stdcall DriverEntry( void*, void* )" ); + init_func = "DriverEntry"; + } + fprintf( outfile, + "static int __stdcall __wine_driver_entry( void *obj, void *path )\n" + "{\n" + " int ret;\n" + " if (reason == %d && __wine_spec_init_state == 1)\n" + " _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" + " ret = %s ? %s( obj, path ) : 0;\n" + " if (reason == %d && __wine_spec_init_state == 1) _fini();\n" + " return ret;\n" + "}\n", + DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH ); + init_func = "__wine_driver_entry"; + subsystem = IMAGE_SUBSYSTEM_NATIVE; + break; case SPEC_MODE_GUIEXE: case SPEC_MODE_GUIEXE_UNICODE: if (!init_func) init_func = "WinMain"; diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index ffd80cdc5e4..2e8a203d4cb 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -145,7 +145,10 @@ for a graphical ASCII executable, for a command line Unicode executable, .br .B guiw -for a graphical Unicode executable. +for a graphical Unicode executable, +.br +.B native +for a native-mode dll. .br A command line executable entry point is a normal C \fBmain\fR function. A graphical executable has a \fBWinMain\fR entry point