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/Make.rules.in b/Make.rules.in
index 7ebc172..519b1ec 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -289,9 +289,9 @@
 
 # Misc. rules
 
-$(SPEC_SRCS:.spec=.spec.c): $(BUILD) $(TOPSRCDIR)/include/builtin16.h $(TOPSRCDIR)/include/builtin32.h
+$(SPEC_SRCS:.spec=.spec.c): $(BUILD) $(TOPSRCDIR)/include/builtin16.h
 
-$(GLUE:.c=.glue.c): $(BUILD) $(TOPSRCDIR)/include/builtin16.h $(TOPSRCDIR)/include/builtin32.h
+$(GLUE:.c=.glue.c): $(BUILD) $(TOPSRCDIR)/include/builtin16.h
 
 $(RC_SRCS:.rc=.s): $(WRC)
 
diff --git a/include/builtin32.h b/include/builtin32.h
deleted file mode 100644
index 7df2111..0000000
--- a/include/builtin32.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Win32 built-in DLLs definitions
- *
- * Copyright 1997 Alexandre Julliard
- */
-
-#ifndef __WINE_BUILTIN32_H
-#define __WINE_BUILTIN32_H
-
-/* Warning: this must match the definition in tools/winebuild/spec32.c */
-typedef struct
-{
-    const char*           filename;     /* DLL file name */
-    int                   nb_imports;   /* Number of imported DLLs */
-    void                 *pe_header;    /* Buffer for PE header */
-    void                 *exports;      /* Pointer to export directory */
-    unsigned int          exports_size; /* Total size of export directory */
-    const char * const   *imports;      /* Pointer to imports */
-    void                (*dllentrypoint)(); /* Pointer to entry point function */
-    int                   characteristics;
-    void                 *rsrc;         /* Resource descriptor */
-} BUILTIN32_DESCRIPTOR;
-
-extern void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr );
-extern void RELAY_SetupDLL( const char *module );
-
-#endif /* __WINE_BUILTIN32_H */
diff --git a/miscemu/.cvsignore b/miscemu/.cvsignore
index f3c7a7c..25613a4 100644
--- a/miscemu/.cvsignore
+++ b/miscemu/.cvsignore
@@ -1 +1,2 @@
 Makefile
+wine.spec.c
diff --git a/miscemu/Makefile.in b/miscemu/Makefile.in
index 1030b0c..cf1e072 100644
--- a/miscemu/Makefile.in
+++ b/miscemu/Makefile.in
@@ -5,6 +5,8 @@
 VPATH     = @srcdir@
 MODULE    = miscemu
 
+SPEC_SRCS = wine.spec
+
 C_SRCS = \
 	main.c
 
diff --git a/miscemu/main.c b/miscemu/main.c
index b35d94d..764c5d2 100644
--- a/miscemu/main.c
+++ b/miscemu/main.c
@@ -8,7 +8,6 @@
 #include "wingdi.h"
 #include "winuser.h"
 
-#include "builtin32.h"
 #include "callback.h"
 #include "options.h"
 #include "process.h"
@@ -17,7 +16,7 @@
 /***********************************************************************
  *           Main loop of initial task
  */
-static void initial_task(void)
+void wine_initial_task(void)
 {
     MSG msg;
     HINSTANCE16 instance;
@@ -55,13 +54,6 @@
  */
 int main( int argc, char *argv[] )
 {
-    BUILTIN32_DESCRIPTOR descriptor;
-
-    memset( &descriptor, 0, sizeof(descriptor) );
-    descriptor.filename = argv[0];
-    descriptor.dllentrypoint = initial_task;
-    BUILTIN32_RegisterDLL( &descriptor );
-
     PROCESS_InitWine( argc, argv );
     return 1;  /* not reached */
 }
diff --git a/miscemu/wine.spec b/miscemu/wine.spec
new file mode 100644
index 0000000..02ced94
--- /dev/null
+++ b/miscemu/wine.spec
@@ -0,0 +1,4 @@
+name	wine
+mode	cuiexe_no_main
+type	win32
+init	wine_initial_task
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index afbb77b..233eafd 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -20,7 +20,6 @@
 
 #include "windef.h"
 #include "wine/winbase16.h"
-#include "builtin32.h"
 #include "elfdll.h"
 #include "global.h"
 #include "neexe.h"
@@ -43,7 +42,15 @@
 
 #define MAX_DLLS 100
 
-static const BUILTIN32_DESCRIPTOR *builtin_dlls[MAX_DLLS];
+typedef struct
+{
+    const IMAGE_NT_HEADERS *nt;           /* NT header */
+    const char             *filename;     /* DLL file name */
+} BUILTIN32_DESCRIPTOR;
+
+extern void RELAY_SetupDLL( const char *module );
+
+static BUILTIN32_DESCRIPTOR builtin_dlls[MAX_DLLS];
 static int nb_dlls;
 
 
@@ -119,8 +126,6 @@
     IMAGE_DOS_HEADER *dos;
     IMAGE_NT_HEADERS *nt;
     IMAGE_SECTION_HEADER *sec;
-    IMAGE_IMPORT_DESCRIPTOR *imp;
-    IMAGE_EXPORT_DIRECTORY *exports = descr->exports;
     INT i, size, nb_sections;
     BYTE *addr, *code_start, *data_start;
     int page_size = VIRTUAL_GetPageSize();
@@ -131,17 +136,17 @@
 
     size = (sizeof(IMAGE_DOS_HEADER)
             + sizeof(IMAGE_NT_HEADERS)
-            + nb_sections * sizeof(IMAGE_SECTION_HEADER)
-            + (descr->nb_imports+1) * sizeof(IMAGE_IMPORT_DESCRIPTOR));
+            + nb_sections * sizeof(IMAGE_SECTION_HEADER));
 
     assert( size <= page_size );
 
-    if (descr->pe_header)
+    if (descr->nt->OptionalHeader.ImageBase)
     {
-        if ((addr = VIRTUAL_mmap( -1, descr->pe_header, page_size, 0,
-                                  PROT_READ|PROT_WRITE, MAP_FIXED )) != descr->pe_header)
+        void *base = (void *)descr->nt->OptionalHeader.ImageBase;
+        if ((addr = VIRTUAL_mmap( -1, base, page_size, 0,
+                                  PROT_READ|PROT_WRITE, MAP_FIXED )) != base)
         {
-            ERR("failed to map over PE header for %s at %p\n", descr->filename, descr->pe_header );
+            ERR("failed to map over PE header for %s at %p\n", descr->filename, base );
             return 0;
         }
     }
@@ -153,7 +158,6 @@
     dos    = (IMAGE_DOS_HEADER *)addr;
     nt     = (IMAGE_NT_HEADERS *)(dos + 1);
     sec    = (IMAGE_SECTION_HEADER *)(nt + 1);
-    imp    = (IMAGE_IMPORT_DESCRIPTOR *)(sec + nb_sections);
     code_start = addr + page_size;
 
     /* HACK! */
@@ -164,29 +168,16 @@
     dos->e_magic  = IMAGE_DOS_SIGNATURE;
     dos->e_lfanew = sizeof(*dos);
 
-    nt->Signature                       = IMAGE_NT_SIGNATURE;
-    nt->FileHeader.Machine              = IMAGE_FILE_MACHINE_I386;
-    nt->FileHeader.NumberOfSections     = nb_sections;
-    nt->FileHeader.SizeOfOptionalHeader = sizeof(nt->OptionalHeader);
-    nt->FileHeader.Characteristics      = descr->characteristics;
+    *nt = *descr->nt;
 
-    nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+    nt->FileHeader.NumberOfSections                = nb_sections;
     nt->OptionalHeader.SizeOfCode                  = data_start - code_start;
     nt->OptionalHeader.SizeOfInitializedData       = 0;
     nt->OptionalHeader.SizeOfUninitializedData     = 0;
     nt->OptionalHeader.ImageBase                   = (DWORD)addr;
-    nt->OptionalHeader.SectionAlignment            = page_size;
-    nt->OptionalHeader.FileAlignment               = page_size;
-    nt->OptionalHeader.MajorOperatingSystemVersion = 1;
-    nt->OptionalHeader.MinorOperatingSystemVersion = 0;
-    nt->OptionalHeader.MajorSubsystemVersion       = 4;
-    nt->OptionalHeader.MinorSubsystemVersion       = 0;
-    nt->OptionalHeader.SizeOfImage                 = page_size;
-    nt->OptionalHeader.SizeOfHeaders               = page_size;
-    nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
-    if (descr->dllentrypoint) 
-        nt->OptionalHeader.AddressOfEntryPoint = (DWORD)descr->dllentrypoint - (DWORD)addr;
-    
+
+    fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
+
     /* Build the code section */
 
     strcpy( sec->Name, ".text" );
@@ -210,44 +201,34 @@
 
     /* Build the import directory */
 
-    if (descr->nb_imports)
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
+    if (dir->Size)
     {
-        dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY];
-        dir->VirtualAddress = (BYTE *)imp - addr;
-        dir->Size = sizeof(*imp) * (descr->nb_imports + 1);
-
-        /* Build the imports */
-        for (i = 0; i < descr->nb_imports; i++)
-        {
-            imp[i].u.Characteristics = 0;
-            imp[i].ForwarderChain = -1;
-            imp[i].Name = (BYTE *)descr->imports[i] - addr;
-            /* hack: make first thunk point to some zero value */
-            imp[i].FirstThunk = (PIMAGE_THUNK_DATA)((BYTE *)&imp[i].u.Characteristics - addr);
-        }
+        IMAGE_IMPORT_DESCRIPTOR *imports = (void *)dir->VirtualAddress;
+        fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
+        /* we can fixup everything at once since we only have pointers and 0 values */
+        fixup_rva_ptrs( imports, addr, dir->Size / sizeof(void*) );
     }
 
     /* Build the resource directory */
 
-    if (descr->rsrc)
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
+    if (dir->VirtualAddress)
     {
-        BUILTIN32_RESOURCE *rsrc = descr->rsrc;
-	IMAGE_RESOURCE_DATA_ENTRY *rdep;
-	dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY];
-	dir->VirtualAddress = (BYTE *)rsrc->restab - addr;
-	dir->Size = rsrc->restabsize;
-	rdep = rsrc->entries;
-	for (i = 0; i < rsrc->nresources; i++) rdep[i].OffsetToData += dir->VirtualAddress;
+        BUILTIN32_RESOURCE *rsrc = (BUILTIN32_RESOURCE *)dir->VirtualAddress;
+        IMAGE_RESOURCE_DATA_ENTRY *rdep = rsrc->entries;
+        dir->VirtualAddress = (BYTE *)rsrc->restab - addr;
+        dir->Size = rsrc->restabsize;
+        for (i = 0; i < rsrc->nresources; i++) rdep[i].OffsetToData += dir->VirtualAddress;
     }
 
     /* Build the export directory */
 
-    if (exports)
+    dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
+    if (dir->Size)
     {
-        dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY];
-        dir->VirtualAddress = (BYTE *)exports - addr;
-        dir->Size = descr->exports_size;
-
+        IMAGE_EXPORT_DIRECTORY *exports = (void *)dir->VirtualAddress;
+        fixup_rva_ptrs( &dir->VirtualAddress, addr, 1 );
         fixup_rva_ptrs( (void *)exports->AddressOfFunctions, addr, exports->NumberOfFunctions );
         fixup_rva_ptrs( (void *)exports->AddressOfNames, addr, exports->NumberOfNames );
         fixup_rva_ptrs( &exports->Name, addr, 1 );
@@ -290,12 +271,12 @@
 
     /* Search built-in descriptor */
     for (i = 0; i < nb_dlls; i++)
-        if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found;
+        if (!strcasecmp( builtin_dlls[i].filename, dllname )) goto found;
 
     if ((handle = BUILTIN32_dlopen( dllname )))
     {
         for (i = 0; i < nb_dlls; i++)
-            if (!strcasecmp( builtin_dlls[i]->filename, dllname )) goto found;
+            if (!strcasecmp( builtin_dlls[i].filename, dllname )) goto found;
         ERR( "loaded .so but dll %s still not found\n", dllname );
         BUILTIN32_dlclose( handle );
     }
@@ -306,7 +287,7 @@
 
  found:
     /* Load built-in module */
-    if (!(module = BUILTIN32_DoLoadImage( builtin_dlls[i] ))) return NULL;
+    if (!(module = BUILTIN32_DoLoadImage( &builtin_dlls[i] ))) return NULL;
 
     /* Create 32-bit MODREF */
     if ( !(wm = PE_CreateModule( module, path, flags, -1, TRUE )) )
@@ -329,7 +310,7 @@
 
     /* Search built-in EXE descriptor */
     for ( i = 0; i < nb_dlls; i++ )
-        if ( !(builtin_dlls[i]->characteristics & IMAGE_FILE_DLL) ) 
+        if ( !(builtin_dlls[i].nt->FileHeader.Characteristics & IMAGE_FILE_DLL) )
         {
             if ( exe != -1 )
             {
@@ -347,7 +328,7 @@
     }
 
     /* Load built-in module */
-    return BUILTIN32_DoLoadImage( builtin_dlls[exe] );
+    return BUILTIN32_DoLoadImage( &builtin_dlls[exe] );
 }
 
 
@@ -356,10 +337,12 @@
  *
  * Register a built-in DLL descriptor.
  */
-void BUILTIN32_RegisterDLL( const BUILTIN32_DESCRIPTOR *descr )
+void BUILTIN32_RegisterDLL( const IMAGE_NT_HEADERS *header, const char *filename )
 {
     assert( nb_dlls < MAX_DLLS );
-    builtin_dlls[nb_dlls++] = descr;
+    builtin_dlls[nb_dlls].nt = header;
+    builtin_dlls[nb_dlls].filename = filename;
+    nb_dlls++;
 }
 
 /***********************************************************************
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 )
 {