Changed the Win32 dll descriptor to be in IMAGE_NT_HEADERS format.
Generate the import table directly in PE format.
Added gui/cuiexe_no_main modes in EXE spec files, and use this for the
main wine binary.
diff --git a/tools/winebuild/Makefile.in b/tools/winebuild/Makefile.in
index 031dd8f..d73e5e5 100644
--- a/tools/winebuild/Makefile.in
+++ b/tools/winebuild/Makefile.in
@@ -8,6 +8,7 @@
MODULE = none
C_SRCS = \
+ import.c \
main.c \
parser.c \
relay.c \
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index ac62ec4..622fb24 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -61,7 +61,9 @@
{
SPEC_MODE_DLL,
SPEC_MODE_GUIEXE,
- SPEC_MODE_CUIEXE
+ SPEC_MODE_CUIEXE,
+ SPEC_MODE_GUIEXE_NO_MAIN,
+ SPEC_MODE_CUIEXE_NO_MAIN
} SPEC_MODE;
typedef struct
@@ -126,7 +128,6 @@
#define MAX_ORDINALS 2048
-#define MAX_IMPORTS 16
/* global functions */
@@ -135,7 +136,11 @@
extern char *xstrdup( const char *str );
extern char *strupper(char *s);
extern void fatal_error( const char *msg, ... );
+extern void warning( const char *msg, ... );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label );
+extern void add_import_dll( const char *name );
+extern void resolve_imports( FILE *outfile );
+extern int output_imports( FILE *outfile );
extern void BuildGlue( FILE *outfile, FILE *infile );
extern void BuildRelays( FILE *outfile );
@@ -148,7 +153,6 @@
extern int current_line;
extern int nb_entry_points;
extern int nb_names;
-extern int nb_imports;
extern int Base;
extern int Limit;
extern int DLLHeapSize;
@@ -163,7 +167,6 @@
extern char DLLInitFunc[80];
extern char rsrc_name[80];
extern char owner_name[80];
-extern char *DLLImports[MAX_IMPORTS];
extern const char *input_file_name;
extern const char *output_file_name;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
new file mode 100644
index 0000000..e27fe47
--- /dev/null
+++ b/tools/winebuild/import.c
@@ -0,0 +1,114 @@
+/*
+ * DLL imports support
+ *
+ * Copyright 2000 Alexandre Julliard
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "winnt.h"
+#include "build.h"
+
+struct import
+{
+ char *dll; /* dll name */
+ char **imports; /* functions we want to import from this dll */
+ int nb_imports; /* number of imported functions */
+};
+
+
+static struct import **dll_imports = NULL;
+static int nb_imports = 0; /* number of imported dlls */
+static int total_imports = 0; /* total number of imported functions */
+
+
+/* add a dll to the list of imports */
+void add_import_dll( const char *name )
+{
+ struct import *imp = xmalloc( sizeof(*imp) );
+ imp->dll = xstrdup( name );
+ imp->imports = NULL;
+ imp->nb_imports = 0;
+
+ dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) );
+ dll_imports[nb_imports++] = imp;
+}
+
+#ifdef notyet
+/* add a function to the list of imports from a given dll */
+static void add_import_func( struct import *imp, const char *name )
+{
+ imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
+ imp->imports[imp->nb_imports++] = xstrdup( name );
+ total_imports++;
+}
+#endif
+
+/* output the import table of a Win32 module */
+int output_imports( FILE *outfile )
+{
+ int i, j, pos;
+
+ if (!nb_imports) goto done;
+
+ /* main import header */
+
+ fprintf( outfile, "\n\n/* imports */\n\n" );
+ fprintf( outfile, "static struct {\n" );
+ fprintf( outfile, " struct {\n" );
+ fprintf( outfile, " void *OriginalFirstThunk;\n" );
+ fprintf( outfile, " unsigned int TimeDateStamp;\n" );
+ fprintf( outfile, " unsigned int ForwarderChain;\n" );
+ fprintf( outfile, " const char *Name;\n" );
+ fprintf( outfile, " void *FirstThunk;\n" );
+ fprintf( outfile, " } imp[%d];\n", nb_imports+1 );
+ fprintf( outfile, " const char *data[%d];\n", total_imports + nb_imports );
+ fprintf( outfile, "} imports = {\n {\n" );
+
+ /* list of dlls */
+
+ for (i = j = 0; i < nb_imports; i++)
+ {
+ fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
+ dll_imports[i]->dll, j );
+ j += dll_imports[i]->nb_imports + 1;
+ }
+ fprintf( outfile, " { 0, 0, 0, 0, 0 },\n" );
+ fprintf( outfile, " },\n {\n" );
+
+ /* list of imported functions */
+
+ for (i = 0; i < nb_imports; i++)
+ {
+ fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
+ for (j = 0; j < dll_imports[i]->nb_imports; j++)
+ fprintf( outfile, " \"\\0\\0%s\",\n", dll_imports[i]->imports[j] );
+ fprintf( outfile, " 0,\n" );
+ }
+ fprintf( outfile, " }\n};\n\n" );
+
+ /* thunks for imported functions */
+
+ fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
+ pos = 20 * (nb_imports + 1); /* offset of imports.data from start of imports */
+ fprintf( outfile, "asm(\".align 4\");\n" );
+ for (i = 0; i < nb_imports; i++, pos += 4)
+ {
+ for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
+ {
+ fprintf( outfile,
+ "asm(\".type " PREFIX "%s,@function\\n\\t"
+ ".globl " PREFIX "%s\\n"
+ PREFIX "%s:\\tjmp *(imports+%d)\\n\\t"
+ "movl %%esi,%%esi\");\n",
+ dll_imports[i]->imports[j], dll_imports[i]->imports[j],
+ dll_imports[i]->imports[j], pos );
+ }
+ }
+ fprintf( outfile, "#ifndef __GNUC__\n}\n#endif\n\n" );
+
+ done:
+ return nb_imports;
+}
diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c
index 1cb5776..8564036 100644
--- a/tools/winebuild/main.c
+++ b/tools/winebuild/main.c
@@ -38,13 +38,11 @@
int UsePIC = 0;
int nb_entry_points = 0;
int nb_names = 0;
-int nb_imports = 0;
int debugging = 1;
char DLLName[80];
char DLLFileName[80];
char DLLInitFunc[80];
-char *DLLImports[MAX_IMPORTS];
char rsrc_name[80];
char owner_name[80];
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 12a5c93..93332f9 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -311,6 +311,20 @@
/*******************************************************************
+ * fix_export_name
+ *
+ * Fix an exported function name by removing a possible @xx suffix
+ */
+static void fix_export_name( char *name )
+{
+ char *p, *end = strrchr( name, '@' );
+ if (!end || !end[1] || end == name) return;
+ /* make sure all the rest is digits */
+ for (p = end + 1; *p; p++) if (!isdigit(*p)) return;
+ *end = 0;
+}
+
+/*******************************************************************
* ParseOrdinal
*
* Parse an ordinal definition.
@@ -333,6 +347,7 @@
if (!(token = GetToken())) fatal_error( "Expected name after type\n" );
strcpy( odp->name, token );
+ fix_export_name( odp->name );
odp->lineno = current_line;
odp->ordinal = ordinal;
@@ -436,7 +451,9 @@
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 fatal_error( "Mode must be 'dll', 'guiexe' or 'cuiexe'\n" );
+ 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, "heap") == 0)
{
@@ -456,11 +473,9 @@
}
else if (strcmp(token, "import") == 0)
{
- if (nb_imports >= MAX_IMPORTS)
- fatal_error( "Too many imports (limit %d)\n", MAX_IMPORTS );
if (SpecType != SPEC_WIN32)
fatal_error( "Imports not supported for Win16\n" );
- DLLImports[nb_imports++] = xstrdup(GetToken());
+ add_import_dll( GetToken() );
}
else if (strcmp(token, "rsrc") == 0)
{
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index e01d174..413c141 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -269,7 +269,8 @@
{
ORDDEF *odp;
int i, fwd_size = 0, have_regs = FALSE;
- int nr_exports;
+ int nr_exports, nr_imports;
+ int characteristics, subsystem;
const char *init_func;
DWORD page_size;
@@ -370,24 +371,17 @@
/* Output the DLL imports */
- if (nb_imports)
- {
- fprintf( outfile, "static const char * const Imports[%d] =\n{\n", nb_imports );
- for (i = 0; i < nb_imports; i++)
- {
- fprintf( outfile, " \"%s\"", DLLImports[i] );
- if (i < nb_imports-1) fprintf( outfile, ",\n" );
- }
- fprintf( outfile, "\n};\n\n" );
- }
+ nr_imports = output_imports( outfile );
/* Output LibMain function */
init_func = DLLInitFunc[0] ? DLLInitFunc : NULL;
+ characteristics = subsystem = 0;
switch(SpecMode)
{
case SPEC_MODE_DLL:
if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
+ characteristics = IMAGE_FILE_DLL;
break;
case SPEC_MODE_GUIEXE:
if (!init_func) init_func = "WinMain";
@@ -412,6 +406,7 @@
" return 1;\n"
"}\n\n" );
init_func = "exe_main";
+ subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case SPEC_MODE_CUIEXE:
if (!init_func) init_func = "wine_main";
@@ -432,6 +427,15 @@
" return 1;\n"
"}\n\n" );
init_func = "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 );
+ subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break;
}
@@ -439,28 +443,87 @@
if (rsrc_name[0]) fprintf( outfile, "extern char %s[];\n\n", rsrc_name );
- /* Warning: this must match the definition in builtin32.h */
- fprintf( outfile, "static const struct dll_descriptor\n{\n" );
- fprintf( outfile, " const char* filename;\n" );
- fprintf( outfile, " int nb_imports;\n" );
- fprintf( outfile, " void *pe_header;\n" );
- fprintf( outfile, " void *exports;\n" );
- fprintf( outfile, " unsigned int exports_size;\n" );
- fprintf( outfile, " const char * const *imports;\n" );
- fprintf( outfile, " void (*dllentrypoint)();\n" );
- fprintf( outfile, " int characteristics;\n" );
- fprintf( outfile, " void *rsrc;\n" );
- fprintf( outfile, "} descriptor = {\n" );
- fprintf( outfile, " \"%s\",\n", DLLFileName );
- fprintf( outfile, " %d,\n", nb_imports );
- fprintf( outfile, " pe_header,\n" );
- fprintf( outfile, " %s,\n", nr_exports ? "&exports" : "0" );
- fprintf( outfile, " %s,\n", nr_exports ? "sizeof(exports.exp)" : "0" );
- fprintf( outfile, " %s,\n", nb_imports ? "Imports" : "0" );
- fprintf( outfile, " %s,\n", init_func ? init_func : "0" );
- fprintf( outfile, " %d,\n", SpecMode == SPEC_MODE_DLL ? IMAGE_FILE_DLL : 0 );
- fprintf( outfile, " %s\n", rsrc_name[0] ? rsrc_name : "0" );
- fprintf( outfile, "};\n" );
+ /* Output the NT header */
+
+ /* this is the IMAGE_NT_HEADERS structure, but we cannot include winnt.h here */
+ fprintf( outfile, "static const struct image_nt_headers\n{\n" );
+ fprintf( outfile, " int Signature;\n" );
+ fprintf( outfile, " struct file_header {\n" );
+ fprintf( outfile, " short Machine;\n" );
+ fprintf( outfile, " short NumberOfSections;\n" );
+ fprintf( outfile, " int TimeDateStamp;\n" );
+ fprintf( outfile, " void *PointerToSymbolTable;\n" );
+ fprintf( outfile, " int NumberOfSymbols;\n" );
+ fprintf( outfile, " short SizeOfOptionalHeader;\n" );
+ fprintf( outfile, " short Characteristics;\n" );
+ fprintf( outfile, " } FileHeader;\n" );
+ fprintf( outfile, " struct opt_header {\n" );
+ fprintf( outfile, " short Magic;\n" );
+ fprintf( outfile, " char MajorLinkerVersion, MinorLinkerVersion;\n" );
+ fprintf( outfile, " int SizeOfCode;\n" );
+ fprintf( outfile, " int SizeOfInitializedData;\n" );
+ fprintf( outfile, " int SizeOfUninitializedData;\n" );
+ fprintf( outfile, " void *AddressOfEntryPoint;\n" );
+ fprintf( outfile, " void *BaseOfCode;\n" );
+ fprintf( outfile, " void *BaseOfData;\n" );
+ fprintf( outfile, " void *ImageBase;\n" );
+ fprintf( outfile, " int SectionAlignment;\n" );
+ fprintf( outfile, " int FileAlignment;\n" );
+ fprintf( outfile, " short MajorOperatingSystemVersion;\n" );
+ fprintf( outfile, " short MinorOperatingSystemVersion;\n" );
+ fprintf( outfile, " short MajorImageVersion;\n" );
+ fprintf( outfile, " short MinorImageVersion;\n" );
+ fprintf( outfile, " short MajorSubsystemVersion;\n" );
+ fprintf( outfile, " short MinorSubsystemVersion;\n" );
+ fprintf( outfile, " int Win32VersionValue;\n" );
+ fprintf( outfile, " int SizeOfImage;\n" );
+ fprintf( outfile, " int SizeOfHeaders;\n" );
+ fprintf( outfile, " int CheckSum;\n" );
+ fprintf( outfile, " short Subsystem;\n" );
+ fprintf( outfile, " short DllCharacteristics;\n" );
+ fprintf( outfile, " int SizeOfStackReserve;\n" );
+ fprintf( outfile, " int SizeOfStackCommit;\n" );
+ fprintf( outfile, " int SizeOfHeapReserve;\n" );
+ fprintf( outfile, " int SizeOfHeapCommit;\n" );
+ fprintf( outfile, " int LoaderFlags;\n" );
+ fprintf( outfile, " int NumberOfRvaAndSizes;\n" );
+ fprintf( outfile, " struct { void *VirtualAddress; int Size; } DataDirectory[%d];\n",
+ IMAGE_NUMBEROF_DIRECTORY_ENTRIES );
+ fprintf( outfile, " } OptionalHeader;\n" );
+ fprintf( outfile, "} nt_header = {\n" );
+ fprintf( outfile, " 0x%04x,\n", IMAGE_NT_SIGNATURE ); /* Signature */
+
+ fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 ); /* Machine */
+ fprintf( outfile, " 0, 0, 0, 0,\n" );
+ fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
+ fprintf( outfile, " 0x%04x },\n", characteristics ); /* Characteristics */
+
+ fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */
+ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
+ fprintf( outfile, " 0, 0, 0,\n" ); /* SizeOfCode/Data */
+ fprintf( outfile, " %s,\n", init_func ? init_func : "0" ); /* AddressOfEntryPoint */
+ fprintf( outfile, " 0, 0,\n" ); /* BaseOfCode/Data */
+ fprintf( outfile, " pe_header,\n" ); /* ImageBase */
+ fprintf( outfile, " %ld,\n", page_size ); /* SectionAlignment */
+ fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */
+ fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
+ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */
+ fprintf( outfile, " 4, 0,\n" ); /* Major/MinorSubsystemVersion */
+ fprintf( outfile, " 0,\n" ); /* Win32VersionValue */
+ fprintf( outfile, " %ld,\n", page_size ); /* SizeOfImage */
+ fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */
+ fprintf( outfile, " 0,\n" ); /* CheckSum */
+ fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */
+ fprintf( outfile, " 0, 0, 0, 0, 0, 0,\n" );
+ fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
+ fprintf( outfile, " {\n" );
+ fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_EXPORT */
+ nr_exports ? "&exports" : "0", nr_exports ? "sizeof(exports.exp)" : "0" );
+ fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
+ nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
+ fprintf( outfile, " { %s, 0 },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
+ rsrc_name[0] ? rsrc_name : "0" );
+ fprintf( outfile, " }\n }\n};\n\n" );
/* Output the DLL constructor */
@@ -474,6 +537,6 @@
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void %s_init(void)\n{\n", DLLName );
- fprintf( outfile, " extern void BUILTIN32_RegisterDLL( const struct dll_descriptor * );\n" );
- fprintf( outfile, " BUILTIN32_RegisterDLL( &descriptor );\n}\n" );
+ fprintf( outfile, " extern void BUILTIN32_RegisterDLL( const struct image_nt_headers *, const char * );\n" );
+ fprintf( outfile, " BUILTIN32_RegisterDLL( &nt_header, \"%s\" );\n}\n", DLLFileName );
}
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 19b50ba..f859408 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -55,13 +55,34 @@
{
va_list valist;
va_start( valist, msg );
- if (input_file_name && current_line)
- fprintf( stderr, "%s:%d: ", input_file_name, current_line );
+ if (input_file_name)
+ {
+ fprintf( stderr, "%s:", input_file_name );
+ if (current_line)
+ fprintf( stderr, "%d:", current_line );
+ fputc( ' ', stderr );
+ }
vfprintf( stderr, msg, valist );
va_end( valist );
exit(1);
}
+void warning( const char *msg, ... )
+{
+ va_list valist;
+ va_start( valist, msg );
+ if (input_file_name)
+ {
+ fprintf( stderr, "%s:", input_file_name );
+ if (current_line)
+ fprintf( stderr, "%d:", current_line );
+ fputc( ' ', stderr );
+ }
+ fprintf( stderr, "warning: " );
+ vfprintf( stderr, msg, valist );
+ va_end( valist );
+}
+
/* dump a byte stream into the assembly code */
void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label )
{