Sync to Wine-20050830:
Alexandre Julliard <julliard@winehq.org>
- Beginnings of a crt0 library.
- Added a warning for DllGetVersion and DllInstall not being declared
  private. Also warn when one of the Dll* functions is using a different
  internal name.
- Added a --undefined option to allow forcing some symbols to be
  resolved by the linker.
- Byteswap the resources if we detect that the header is in the wrong
  endianness.
- Moved more of the spec initialization code to the winecrt0 library,
  and get rid of implicit kernel32 imports.
- Use __wine_unimplemented_stub from crt0 for 16-bit spec files too.
- Moved the delay loading support code to the winecrt0 library.
- Avoid using common symbols, they are broken on Mac OS.
- Moved the implementation of spec file stubs to the winecrt0 library.
- The exported name strings should be inside the export directory (found
  by Vitaliy Margolen).
- Added some general purpose routines for managing list of symbol
  names.
- Print a warning when a generated import library doesn't export
  anything useful.
- Implemented DelayLoadFailureHook and use it in the winebuild-generated
  delay load code.
- Compute the ordinal base and limit in assign_ordinals instead of doing
  it while parsing.
- Get rid of the unused owner_name field.
Ge van Geldorp <gvg@reactos.org>
- Adapt changes to ReactOS
Modified: trunk/reactos/tools/winebuild/build.h
Modified: trunk/reactos/tools/winebuild/import.c
Modified: trunk/reactos/tools/winebuild/main.c
Modified: trunk/reactos/tools/winebuild/parser.c
Modified: trunk/reactos/tools/winebuild/res32.c
Modified: trunk/reactos/tools/winebuild/spec16.c
Modified: trunk/reactos/tools/winebuild/spec32.c
Modified: trunk/reactos/tools/winebuild/utils.c
Modified: trunk/reactos/tools/winebuild/winebuild.man.in

Modified: trunk/reactos/tools/winebuild/build.h
--- trunk/reactos/tools/winebuild/build.h	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/build.h	2005-09-05 17:35:31 UTC (rev 17659)
@@ -88,7 +88,6 @@
 {
     char            *file_name;          /* file name of the dll */
     char            *dll_name;           /* internal name of the dll */
-    char            *owner_name;         /* name of the 32-bit dll owning this one */
     char            *init_func;          /* initialization routine */
     SPEC_TYPE        type;               /* type of dll (Win16/Win32) */
     int              base;               /* ordinal base */
@@ -190,7 +189,8 @@
 extern void add_import_dll( const char *name, const char *filename );
 extern void add_delayed_import( const char *name );
 extern void add_ignore_symbol( const char *name );
-extern void read_undef_symbols( char **argv );
+extern void add_extra_ld_symbol( const char *name );
+extern void read_undef_symbols( DLLSPEC *spec, char **argv );
 extern int resolve_imports( DLLSPEC *spec );
 extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
 extern void output_import_thunks( FILE *outfile, DLLSPEC *spec );

Modified: trunk/reactos/tools/winebuild/import.c
--- trunk/reactos/tools/winebuild/import.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/import.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -21,6 +21,7 @@
 
 #include "config.h"
 
+#include <assert.h>
 #include <ctype.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -34,7 +35,6 @@
 #endif
 
 #include "winglue.h"
-//#include "wine/exception.h"
 #include "build.h"
 
 #ifndef EXCEPTION_NONCONTINUABLE
@@ -56,13 +56,16 @@
     int          nb_imports;  /* number of imported functions */
 };
 
-static char **undef_symbols;  /* list of undefined symbols */
-static int nb_undef_symbols = -1;
-static int undef_size;
+struct name_table
+{
+    char **names;
+    unsigned int count, size;
+};
 
-static char **ignore_symbols; /* list of symbols to ignore */
-static int nb_ignore_symbols;
-static int ignore_size;
+static struct name_table undef_symbols;    /* list of undefined symbols */
+static struct name_table ignore_symbols;   /* list of symbols to ignore */
+static struct name_table extra_ld_symbols; /* list of extra symbols that ld should resolve */
+static struct name_table delayed_imports;  /* list of delayed import dlls */
 
 static char *ld_tmp_file;  /* ld temp file name */
 
@@ -71,8 +74,6 @@
 static int nb_delayed = 0;      /* number of delayed dlls */
 static int total_imports = 0;   /* total number of imported functions */
 static int total_delayed = 0;   /* total number of imported functions in delayed DLLs */
-static char **delayed_imports;  /* names of delayed import dlls */
-static int nb_delayed_imports;  /* size of the delayed_imports array */
 
 /* list of symbols that are ignored by default */
 static const char * const default_ignored_symbols[] =
@@ -151,18 +152,52 @@
                    odp2->name ? odp2->name : odp2->export_name );
 }
 
-/* locate a symbol in a (sorted) list */
-inline static const char *find_symbol( const char *name, char **table, int size )
+/* add a name to a name table */
+inline static void add_name( struct name_table *table, const char *name )
 {
-    char **res = NULL;
-
-    if (table) {
-        res = bsearch( &name, table, size, sizeof(*table), name_cmp );
+    if (table->count == table->size)
+    {
+        table->size += (table->size / 2);
+        if (table->size < 32) table->size = 32;
+        table->names = xrealloc( table->names, table->size * sizeof(*table->names) );
     }
+    table->names[table->count++] = xstrdup( name );
+}
 
+/* remove a name from a name table */
+inline static void remove_name( struct name_table *table, unsigned int idx )
+{
+    assert( idx < table->count );
+    free( table->names[idx] );
+    memmove( table->names + idx, table->names + idx + 1,
+             (table->count - idx - 1) * sizeof(*table->names) );
+    table->count--;
+}
+
+/* make a name table empty */
+inline static void empty_name_table( struct name_table *table )
+{
+    unsigned int i;
+
+    for (i = 0; i < table->count; i++) free( table->names[i] );
+    table->count = 0;
+}
+
+/* locate a name in a (sorted) list */
+inline static const char *find_name( const char *name, const struct name_table *table )
+{
+    char **res = NULL;
+
+    if (table->count) res = bsearch( &name, table->names, table->count, sizeof(*table->names), name_cmp );
     return res ? *res : NULL;
 }
 
+/* sort a name table */
+inline static void sort_names( struct name_table *table )
+{
+    if (table->count) qsort( table->names, table->count, sizeof(*table->names), name_cmp );
+}
+
 /* locate an export in a (sorted) export list */
 inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
 {
@@ -175,13 +210,6 @@
     return res ? *res : NULL;
 }
 
-/* sort a symbol table */
-inline static void sort_symbols( char **table, int size )
-{
-    if (table )
-        qsort( table, size, sizeof(*table), name_cmp );
-}
-
 inline static void output_function_size( FILE *outfile, const char *name )
 {
     const char *size = func_size( name );
@@ -209,9 +237,9 @@
 {
     int i;
 
-    for (i = 0; i < nb_delayed_imports; i++)
+    for (i = 0; i < delayed_imports.count; i++)
     {
-        if (!strcmp( delayed_imports[i], name )) return 1;
+        if (!strcmp( delayed_imports.names[i], name )) return 1;
     }
     return 0;
 }
@@ -367,13 +395,13 @@
     struct import *imp;
     char *fullname = get_dll_name( name, NULL );
 
-    delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) );
-    delayed_imports[nb_delayed_imports++] = fullname;
+    add_name( &delayed_imports, fullname );
     if ((imp = is_already_imported( fullname )) && !imp->delay)
     {
         imp->delay = 1;
         nb_delayed++;
     }
+    free( fullname );
 }
 
 /* remove an imported dll, based on its index in the dll_imports array */
@@ -390,54 +418,37 @@
 /* initialize the list of ignored symbols */
 static void init_ignored_symbols(void)
 {
-    int i;
+    unsigned int i;
 
-    nb_ignore_symbols = sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]);
-    ignore_size = nb_ignore_symbols + 32;
-    ignore_symbols = xmalloc( ignore_size * sizeof(*ignore_symbols) );
-    for (i = 0; i < nb_ignore_symbols; i++)
-        ignore_symbols[i] = xstrdup( default_ignored_symbols[i] );
+    for (i = 0; i < sizeof(default_ignored_symbols)/sizeof(default_ignored_symbols[0]); i++)
+        add_name( &ignore_symbols, default_ignored_symbols[i] );
 }
 
 /* add a symbol to the ignored symbol list */
 /* if the name starts with '-' the symbol is removed instead */
 void add_ignore_symbol( const char *name )
 {
-    int i;
+    unsigned int i;
 
-    if (!ignore_symbols) init_ignored_symbols();  /* first time around, fill list with defaults */
+    if (!ignore_symbols.size) init_ignored_symbols();  /* first time around, fill list with defaults */
 
     if (name[0] == '-')  /* remove it */
     {
-        if (!name[1])  /* remove everything */
+        if (!name[1]) empty_name_table( &ignore_symbols );  /* remove everything */
+        else for (i = 0; i < ignore_symbols.count; i++)
         {
-            for (i = 0; i < nb_ignore_symbols; i++) free( ignore_symbols[i] );
-            nb_ignore_symbols = 0;
+            if (!strcmp( ignore_symbols.names[i], name+1 )) remove_name( &ignore_symbols, i-- );
         }
-        else
-        {
-            for (i = 0; i < nb_ignore_symbols; i++)
-            {
-                if (!strcmp( ignore_symbols[i], name+1 ))
-                {
-                    free( ignore_symbols[i] );
-                    memmove( &ignore_symbols[i], &ignore_symbols[i+1], nb_ignore_symbols - i - 1 );
-                    nb_ignore_symbols--;
-                }
-            }
-        }
     }
-    else
-    {
-        if (nb_ignore_symbols == ignore_size)
-        {
-            ignore_size += 32;
-            ignore_symbols = xrealloc( ignore_symbols, ignore_size * sizeof(*ignore_symbols) );
-        }
-        ignore_symbols[nb_ignore_symbols++] = xstrdup( name );
-    }
+    else add_name( &ignore_symbols, name );
 }
 
+/* add a symbol to the list of extra symbols that ld must resolve */
+void add_extra_ld_symbol( const char *name )
+{
+    add_name( &extra_ld_symbols, name );
+}
+
 /* add a function to the list of imports from a given dll */
 static void add_import_func( struct import *imp, ORDDEF *func )
 {
@@ -447,103 +458,33 @@
     if (imp->delay) total_delayed++;
 }
 
-/* add a symbol to the undef list */
-inline static void add_undef_symbol( const char *name )
+/* check if the spec file exports any stubs */
+static int has_stubs( const DLLSPEC *spec )
 {
-    if (nb_undef_symbols == undef_size)
+    int i;
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        undef_size += 128;
-        undef_symbols = xrealloc( undef_symbols, undef_size * sizeof(*undef_symbols) );
+        ORDDEF *odp = &spec->entry_points[i];
+        if (odp->type == TYPE_STUB) return 1;
     }
-    undef_symbols[nb_undef_symbols++] = xstrdup( name );
+    return 0;
 }
 
-/* remove all the holes in the undefined symbol list; return the number of removed symbols */
-static int remove_symbol_holes(void)
+/* get the default entry point for a given spec file */
+static const char *get_default_entry_point( const DLLSPEC *spec )
 {
-    int i, off;
-    for (i = off = 0; i < nb_undef_symbols; i++)
-    {
-        if (!undef_symbols[i]) off++;
-        else undef_symbols[i - off] = undef_symbols[i];
-    }
-    nb_undef_symbols -= off;
-    return off;
+    if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
+    if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
+    return "__wine_spec_exe_entry";
 }
 
-/* add a symbol to the extra list, but only if needed */
-static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec )
-{
-    int i;
-
-    if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
-    {
-        /* check if the symbol is being exported by this dll */
-        for (i = 0; i < spec->nb_entry_points; i++)
-        {
-            ORDDEF *odp = &spec->entry_points[i];
-            if (odp->type == TYPE_STDCALL ||
-                odp->type == TYPE_CDECL ||
-                odp->type == TYPE_VARARGS ||
-                odp->type == TYPE_EXTERN)
-            {
-                if (odp->name && !strcmp( odp->name, name )) return 0;
-            }
-        }
-        extras[*count] = name;
-        (*count)++;
-    }
-    return 1;
-}
-
 /* add the extra undefined symbols that will be contained in the generated spec file itself */
-static void add_extra_undef_symbols( const DLLSPEC *spec )
+static void add_extra_undef_symbols( DLLSPEC *spec )
 {
-    const char *extras[10];
-    int i, count = 0, nb_stubs = 0;
-    int kernel_imports = 0, ntdll_imports = 0;
-
-    sort_symbols( undef_symbols, nb_undef_symbols );
-
-    for (i = 0; i < spec->nb_entry_points; i++)
-    {
-        ORDDEF *odp = &spec->entry_points[i];
-        if (odp->type == TYPE_STUB) nb_stubs++;
-    }
-
-    /* add symbols that will be contained in the spec file itself */
-    if (!(spec->characteristics & IMAGE_FILE_DLL))
-    {
-        switch (spec->subsystem)
-        {
-        case IMAGE_SUBSYSTEM_WINDOWS_GUI:
-        case IMAGE_SUBSYSTEM_WINDOWS_CUI:
-            kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
-            kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
-            kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
-            kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
-            break;
-        }
-    }
-    if (nb_delayed)
-    {
-        kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
-        kernel_imports += add_extra_symbol( extras, &count, "FreeLibrary", spec );
-        kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
-        kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec );
-    }
-    if (nb_stubs)
-        ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
-
-    /* make sure we import the dlls that contain these functions */
-    if (kernel_imports) add_import_dll( "kernel32", NULL );
-    if (ntdll_imports) add_import_dll( "ntdll", NULL );
-
-    if (count)
-    {
-        for (i = 0; i < count; i++) add_undef_symbol( extras[i] );
-        sort_symbols( undef_symbols, nb_undef_symbols );
-    }
+    if (!spec->init_func) spec->init_func = xstrdup( get_default_entry_point(spec) );
+    add_extra_ld_symbol( spec->init_func );
+    if (has_stubs( spec )) add_extra_ld_symbol( "__wine_spec_unimplemented_stub" );
+    if (nb_delayed) add_extra_ld_symbol( "__wine_spec_delay_load" );
 }
 
 /* check if a given imported dll is not needed, taking forwards into account */
@@ -570,8 +511,8 @@
 /* returns the name of the combined file */
 static const char *ldcombine_files( char **argv )
 {
-    int i, len = 0;
-    char *cmd;
+    unsigned int i, len = 0;
+    char *cmd, *p;
     int fd, err;
 
     if (output_file_name && output_file_name[0])
@@ -587,10 +528,14 @@
     atexit( remove_ld_tmp_file );
 
     if (!ld_command) ld_command = xstrdup("ld");
+    for (i = 0; i < extra_ld_symbols.count; i++) len += strlen(extra_ld_symbols.names[i]) + 5;
     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
-    cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command)  );
-    sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
-    for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
+    cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command)  );
+    p += sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
+    for (i = 0; i < extra_ld_symbols.count; i++)
+        p += sprintf( p, " -u %s", asm_name(extra_ld_symbols.names[i]) );
+    for (i = 0; argv[i]; i++)
+        p += sprintf( p, " %s", argv[i] );
     err = system( cmd );
     if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
     free( cmd );
@@ -598,7 +543,7 @@
 }
 
 /* read in the list of undefined symbols */
-void read_undef_symbols( char **argv )
+void read_undef_symbols( DLLSPEC *spec, char **argv )
 {
     size_t prefix_len;
     FILE *f;
@@ -608,15 +553,13 @@
 
     if (!argv[0]) return;
 
+    add_extra_undef_symbols( spec );
+
     strcpy( name_prefix, asm_name("") );
     prefix_len = strlen( name_prefix );
 
-    undef_size = nb_undef_symbols = 0;
+    name = ldcombine_files( argv );
 
-    /* if we have multiple object files, link them together */
-    if (argv[1]) name = ldcombine_files( argv );
-    else name = argv[0];
-
     if (!nm_command) nm_command = xstrdup("nm");
     cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
     sprintf( cmd, "%s -u %s", nm_command, name );
@@ -632,7 +575,7 @@
         while (*p == ' ') p++;
         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
         if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
-        add_undef_symbol( p );
+        add_name( &undef_symbols, p );
     }
     if ((err = pclose( f ))) warning( "%s failed with status %d\n", cmd, err );
     free( cmd );
@@ -640,47 +583,39 @@
 
 static void remove_ignored_symbols(void)
 {
-    int i;
+    unsigned int i;
 
-    if (!ignore_symbols) init_ignored_symbols();
-    sort_symbols( ignore_symbols, nb_ignore_symbols );
-    for (i = 0; i < nb_undef_symbols; i++)
+    if (!ignore_symbols.size) init_ignored_symbols();
+    sort_names( &ignore_symbols );
+    for (i = 0; i < undef_symbols.count; i++)
     {
-        if (find_symbol( undef_symbols[i], ignore_symbols, nb_ignore_symbols ))
-        {
-            free( undef_symbols[i] );
-            undef_symbols[i] = NULL;
-        }
+        if (find_name( undef_symbols.names[i], &ignore_symbols ))
+            remove_name( &undef_symbols, i-- );
     }
-    remove_symbol_holes();
 }
 
 /* resolve the imports for a Win32 module */
 int resolve_imports( DLLSPEC *spec )
 {
-    int i, j;
+    unsigned int i, j, removed;
 
-    if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
-
-    add_extra_undef_symbols( spec );
     remove_ignored_symbols();
 
     for (i = 0; i < nb_imports; i++)
     {
         struct import *imp = dll_imports[i];
 
-        for (j = 0; j < nb_undef_symbols; j++)
+        for (j = removed = 0; j < undef_symbols.count; j++)
         {
-            ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
+            ORDDEF *odp = find_export( undef_symbols.names[j], imp->exports, imp->nb_exports );
             if (odp)
             {
                 add_import_func( imp, odp );
-                free( undef_symbols[j] );
-                undef_symbols[j] = NULL;
+                remove_name( &undef_symbols, j-- );
+                removed++;
             }
         }
-        /* remove all the holes in the undef symbols list */
-        if (!remove_symbol_holes() && check_unused( imp, spec ))
+        if (!removed && check_unused( imp, spec ))
         {
             /* the dll is not used, get rid of it */
             warning( "%s imported but no symbols used\n", imp->spec->file_name );
@@ -919,7 +854,7 @@
         }
     }
     fprintf( outfile, "\n" );
-    fprintf( outfile, "static struct {\n" );
+    fprintf( outfile, "struct {\n" );
     fprintf( outfile, "  struct ImgDelayDescr {\n" );
     fprintf( outfile, "    unsigned int  grAttrs;\n" );
     fprintf( outfile, "    const char   *szName;\n" );
@@ -929,15 +864,15 @@
     fprintf( outfile, "    void*         pBoundIAT;\n" );
     fprintf( outfile, "    void*         pUnloadIAT;\n" );
     fprintf( outfile, "    unsigned long dwTimeStamp;\n" );
-    fprintf( outfile, "  } imp[%d];\n", nb_delayed );
+    fprintf( outfile, "  } imp[%d];\n", nb_delayed + 1 );
     fprintf( outfile, "  void         *IAT[%d];\n", total_delayed );
     fprintf( outfile, "  const char   *INT[%d];\n", total_delayed );
-    fprintf( outfile, "} delay_imports = {\n" );
+    fprintf( outfile, "} __wine_spec_delay_imports = {\n" );
     fprintf( outfile, "  {\n" );
     for (i = j = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
-        fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_hmod[%d], &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
+        fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_hmod[%d], &__wine_spec_delay_imports.IAT[%d], &__wine_spec_delay_imports.INT[%d], 0, 0, 0 },\n",
                  dll_imports[i]->spec->file_name, i, j, j );
         j += dll_imports[i]->nb_imports;
     }
@@ -969,32 +904,6 @@
     }
     fprintf( outfile, "  }\n};\n\n" );
 
-    fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" );
-    fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
-    fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n");
-    fprintf( outfile, "\n" );
-
-    fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" );
-    fprintf( outfile, "{\n" );
-    fprintf( outfile, "  int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" );
-    fprintf( outfile, "  struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" );
-    fprintf( outfile, "  void **pIAT = imd->pIAT + nr;\n" );
-    fprintf( outfile, "  const char** pINT = imd->pINT + nr;\n" );
-    fprintf( outfile, "  void *fn;\n\n" );
-
-    fprintf( outfile, "  if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" );
-    fprintf( outfile, "  if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT)))\n");
-    fprintf( outfile, "    /* patch IAT with final value */\n" );
-    fprintf( outfile, "    return *pIAT = fn;\n" );
-    fprintf( outfile, "  else {\n");
-    fprintf( outfile, "    const void *args[2];\n" );
-    fprintf( outfile, "    args[0] = imd->szName;\n" );
-    fprintf( outfile, "    args[1] = *pINT;\n" );
-    fprintf( outfile, "    RaiseException( 0x%08x, %d, 2, args );\n",
-             EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE );
-    fprintf( outfile, "    return 0;\n" );
-    fprintf( outfile, "  }\n}\n" );
-
     return nb_delayed;
 }
 
@@ -1017,17 +926,17 @@
     {
     case CPU_x86:
         fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_delay_load") );
+        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
         fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
         break;
     case CPU_SPARC:
         fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_delay_load") );
+        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
         fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
         fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
         break;
     case CPU_ALPHA:
-        fprintf( outfile, "    \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_delay_load") );
+        fprintf( outfile, "    \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_spec_delay_load") );
         fprintf( outfile, "    \"\\tjmp $31,($0)\\n\"\n" );
         break;
     case CPU_POWERPC:
@@ -1054,7 +963,7 @@
         fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
 
         /* Call the __wine_delay_load function, arg1 is arg1. */
-        fprintf( outfile, "    \"\\tbl %s\\n\"\n", asm_name("__wine_delay_load") );
+        fprintf( outfile, "    \"\\tbl %s\\n\"\n", asm_name("__wine_spec_delay_load") );
 
         /* Load return value from call into ctr register */
         fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg(3));
@@ -1145,7 +1054,7 @@
 
     fprintf( outfile, "\n    \".align %d\\n\"\n", get_alignment(8) );
     fprintf( outfile, "    \"%s:\\n\"\n", asm_name(delayed_import_thunks));
-    pos = nb_delayed * 32;
+    pos = (nb_delayed + 1) * 32;
     for (i = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
@@ -1153,7 +1062,7 @@
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
-                                 "delay_imports", pos );
+                                 "__wine_spec_delay_imports", pos );
         }
     }
     output_function_size( outfile, delayed_import_thunks );

Modified: trunk/reactos/tools/winebuild/main.c
--- trunk/reactos/tools/winebuild/main.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/main.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -233,31 +233,32 @@
 static const char usage_str[] =
 "Usage: winebuild [OPTIONS] [FILES]\n\n"
 "Options:\n"
-"    -C --source-dir=DIR     Look for source files in DIR\n"
-"    -d --delay-lib=LIB      Import the specified library in delayed mode\n"
-"    -D SYM                  Ignored for C flags compatibility\n"
-"    -E --export=FILE        Export the symbols defined in the .spec or .def file\n"
-"    -e --entry=FUNC         Set the DLL entry point function (default: DllMain)\n"
-"    -f FLAGS                Compiler flags (only -fPIC is supported)\n"
-"    -F --filename=DLLFILE   Set the DLL filename (default: from input file name)\n"
-"    -h --help               Display this help message\n"
-"    -H --heap=SIZE          Set the heap size for a Win16 dll\n"
-"    -i --ignore=SYM[,SYM]   Ignore specified symbols when resolving imports\n"
-"    -I DIR                  Ignored for C flags compatibility\n"
-"    -k --kill-at            Kill stdcall decorations in generated .def files\n"
-"    -K FLAGS                Compiler flags (only -KPIC is supported)\n"
+"   -C, --source-dir=DIR     Look for source files in DIR\n"
+"   -d, --delay-lib=LIB      Import the specified library in delayed mode\n"
+"   -D SYM                   Ignored for C flags compatibility\n"
+"   -E, --export=FILE        Export the symbols defined in the .spec or .def file\n"
+"   -e, --entry=FUNC         Set the DLL entry point function (default: DllMain)\n"
+"   -f FLAGS                 Compiler flags (only -fPIC is supported)\n"
+"   -F, --filename=DLLFILE   Set the DLL filename (default: from input file name)\n"
+"   -h, --help               Display this help message\n"
+"   -H, --heap=SIZE          Set the heap size for a Win16 dll\n"
+"   -i, --ignore=SYM[,SYM]   Ignore specified symbols when resolving imports\n"
+"   -I DIR                   Ignored for C flags compatibility\n"
+"   -k, --kill-at            Kill stdcall decorations in generated .def files\n"
+"   -K, FLAGS                Compiler flags (only -KPIC is supported)\n"
 "       --ld-cmd=LD          Command to use for linking (default: ld)\n"
-"    -l --library=LIB        Import the specified library\n"
-"    -L --library-path=DIR   Look for imports libraries in DIR\n"
-"    -M --main-module=MODULE Set the name of the main module for a Win16 dll\n"
+"   -l, --library=LIB        Import the specified library\n"
+"   -L, --library-path=DIR   Look for imports libraries in DIR\n"
+"   -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n"
 "       --nm-cmd=NM          Command to use to get undefined symbols (default: nm)\n"
-"    -N --dll-name=DLLNAME   Set the DLL name (default: from input file name)\n"
-"    -o --output=NAME        Set the output file name (default: stdout)\n"
-"    -r --res=RSRC.RES       Load resources from RSRC.RES\n"
+"   -N, --dll-name=DLLNAME   Set the DLL name (default: from input file name)\n"
+"   -o, --output=NAME        Set the output file name (default: stdout)\n"
+"   -r, --res=RSRC.RES       Load resources from RSRC.RES\n"
 "       --subsystem=SUBSYS   Set the subsystem (one of native, windows, console)\n"
 "       --target=TARGET      Specify target CPU and platform for cross-compiling\n"
+"   -u, --undefined=SYMBOL   Add an undefined reference to SYMBOL when linking\n"
 "       --version            Print the version and exit\n"
-"    -w --warnings           Turn on warnings\n"
+"   -w, --warnings           Turn on warnings\n"
 "\nMode options:\n"
 "       --dll                Build a .c file from a .spec or .def file\n"
 "       --def                Build a .def file from a .spec file\n"
@@ -284,7 +285,7 @@
     LONG_OPT_PEDLL
 };
 
-static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w";
+static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:u:w";
 
 static const struct option long_options[] =
 {
@@ -316,6 +317,7 @@
     { "dll-name",      1, 0, 'N' },
     { "output",        1, 0, 'o' },
     { "res",           1, 0, 'r' },
+    { "undefined",     1, 0, 'u' },
     { "warnings",      0, 0, 'w' },
     { NULL,            0, 0, 0 }
 };
@@ -373,7 +375,6 @@
             lib_path[nb_lib_paths++] = xstrdup( optarg );
             break;
         case 'M':
-            spec->owner_name = xstrdup( optarg );
             spec->type = SPEC_WIN16;
             break;
         case 'N':
@@ -423,6 +424,9 @@
             res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
             res_files[nb_res_files++] = xstrdup( optarg );
             break;
+        case 'u':
+            add_extra_ld_symbol( optarg );
+            break;
         case 'w':
             display_warnings = 1;
             break;
@@ -568,7 +572,7 @@
                 fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
                 break;
             case SPEC_WIN32:
-                read_undef_symbols( argv );
+                read_undef_symbols( spec, argv );
                 BuildSpec32File( output_file, spec );
                 break;
             default: assert(0);
@@ -580,7 +584,7 @@
         load_resources( argv, spec );
         load_import_libs( argv );
         if (spec_file_name && !parse_input_file( spec )) break;
-        read_undef_symbols( argv );
+        read_undef_symbols( spec, argv );
         BuildSpec32File( output_file, spec );
         break;
     case MODE_DEF:

Modified: trunk/reactos/tools/winebuild/parser.c
--- trunk/reactos/tools/winebuild/parser.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/parser.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -520,9 +520,14 @@
         if (!strcmp( odp->name, "DllRegisterServer" ) ||
             !strcmp( odp->name, "DllUnregisterServer" ) ||
             !strcmp( odp->name, "DllGetClassObject" ) ||
+            !strcmp( odp->name, "DllGetVersion" ) ||
+            !strcmp( odp->name, "DllInstall" ) ||
             !strcmp( odp->name, "DllCanUnloadNow" ))
         {
             warning( "Function %s should be marked private\n", odp->name );
+            if (strcmp( odp->name, odp->link_name ))
+                warning( "Function %s should not use a different internal name (%s)\n",
+                         odp->name, odp->link_name );
         }
     }
 
@@ -602,6 +607,16 @@
     int i, count, ordinal;
 
     /* start assigning from base, or from 1 if no ordinal defined yet */
+
+    spec->base = MAX_ORDINALS;
+    spec->limit = 0;
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ordinal = spec->entry_points[i].ordinal;
+        if (ordinal == -1) continue;
+        if (ordinal > spec->limit) spec->limit = ordinal;
+        if (ordinal < spec->base) spec->base = ordinal;
+    }
     if (spec->base == MAX_ORDINALS) spec->base = 1;
     if (spec->limit < spec->base) spec->limit = spec->base;
 
@@ -819,8 +834,6 @@
             error( "Ordinal number %d too large\n", ordinal );
             goto error;
         }
-        if (ordinal > spec->limit) spec->limit = ordinal;
-        if (ordinal < spec->base) spec->base = ordinal;
         odp->ordinal = ordinal;
         token = GetToken(1);
     }

Modified: trunk/reactos/tools/winebuild/res32.c
--- trunk/reactos/tools/winebuild/res32.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/res32.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -82,6 +82,7 @@
     unsigned int     nb_types;             /* total number of types */
 };
 
+static int byte_swapped;  /* whether the current resource file is byte-swapped */
 static const unsigned char *file_pos;   /* current position in resource file */
 static const unsigned char *file_end;   /* end of resource file */
 static const char *file_name;  /* current resource file name */
@@ -137,6 +138,7 @@
 static WORD get_word(void)
 {
     WORD ret = *(const WORD *)file_pos;
+    if (byte_swapped) ret = (ret << 8) | (ret >> 8);
     file_pos += sizeof(WORD);
     if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
     return ret;
@@ -146,6 +148,8 @@
 static DWORD get_dword(void)
 {
     DWORD ret = *(const DWORD *)file_pos;
+    if (byte_swapped)
+        ret = ((ret << 24) | ((ret << 8) & 0x00ff0000) | ((ret >> 8) & 0x0000ff00) | (ret >> 24));
     file_pos += sizeof(DWORD);
     if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
     return ret;
@@ -173,8 +177,12 @@
 /* all values must be zero except header size */
 static int check_header(void)
 {
+    DWORD size;
+
     if (get_dword()) return 0;        /* data size */
-    if (get_dword() != 32) return 0;  /* header size */
+    size = get_dword();               /* header size */
+    if (size == 0x20000000) byte_swapped = 1;
+    else if (size != 0x20) return 0;
     if (get_word() != 0xffff || get_word()) return 0;  /* type, must be id 0 */
     if (get_word() != 0xffff || get_word()) return 0;  /* name, must be id 0 */
     if (get_dword()) return 0;        /* data version */
@@ -228,6 +236,7 @@
             fatal_error( "Cannot read %s\n", name );
     }
 
+    byte_swapped = 0;
     file_name = name;
     file_pos  = base;
     file_end  = file_pos + st.st_size;

Modified: trunk/reactos/tools/winebuild/spec16.c
--- trunk/reactos/tools/winebuild/spec16.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/spec16.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -362,15 +362,10 @@
         ORDDEF *odp = spec->ordinals[i];
         if (!odp || 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, "  extern void __stdcall RaiseException( unsigned int, unsigned int, unsigned int, const void ** );\n" );
-        fprintf( outfile, "  const void *args[2];\n" );
-        fprintf( outfile, "  args[0] = \"%s\";\n", spec->file_name );
-        fprintf( outfile, "  args[1] = func;\n" );
-        fprintf( outfile, "  for (;;) RaiseException( 0x%08x, %d, 2, args );\n}\n\n",
-                 EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
+        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
+        fprintf( outfile, "#else\n" );
+        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
+        fprintf( outfile, "#endif\n\n" );
         break;
     }
     for (i = 0; i <= spec->limit; i++)
@@ -381,7 +376,7 @@
         strcpy( odp->link_name, "__wine_stub_" );
         strcat( odp->link_name, odp->name );
         for (p = odp->link_name; *p; p++) if (!isalnum(*p)) *p = '_';
-        fprintf( outfile, "static void %s(void) { __wine_unimplemented(\"%s\"); }\n",
+        fprintf( outfile, "static void %s(void) { __wine_spec_unimplemented_stub(__wine_spec16_file_name, \"%s\"); }\n",
                  odp->link_name, odp->name );
     }
 }
@@ -413,6 +408,7 @@
     /* File header */
 
     output_file_header( outfile );
+    fprintf( outfile, "static const char __wine_spec16_file_name[] = \"%s\";\n", spec->file_name );
     fprintf( outfile, "extern unsigned short __wine_call_from_16_word();\n" );
     fprintf( outfile, "extern unsigned int __wine_call_from_16_long();\n" );
     fprintf( outfile, "extern void __wine_call_from_16_regs();\n" );

Modified: trunk/reactos/tools/winebuild/spec32.c
--- trunk/reactos/tools/winebuild/spec32.c	2005-09-05 10:18:07 UTC (rev 17658)
+++ trunk/reactos/tools/winebuild/spec32.c	2005-09-05 17:35:31 UTC (rev 17659)
@@ -66,31 +66,7 @@
     return buffer;
 }
 
-/*******************************************************************
- *         declare_weak_function
- *
- * Output a prototype for a weak function.
- */
-static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
-{
-    fprintf( outfile, "#ifdef __GNUC__\n" );
-    if (target_platform == PLATFORM_APPLE)
-    {
-        fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params );
-        fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name );
-        fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name );
-        fprintf( outfile, "asm(\".weak_reference %s\");\n", asm_name(name) );
-    }
-    else fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
 
-    fprintf( outfile, "#else\n" );
-    fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
-    fprintf( outfile, "static void __asm__dummy_%s(void)", name );
-    fprintf( outfile, " { asm(\".weak %s\"); }\n", asm_name(name) );
-    fprintf( outfile, "#endif\n\n" );
-}
-
-
 /*******************************************************************
  *         output_debug
  *
@@ -128,7 +104,7 @@
 static int get_exports_size( DLLSPEC *spec )
 {
     int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
-    int i, fwd_size = 0, total_size;
+    int i, strings_size, total_size;
 
     if (!nr_exports) return 0;
 
@@ -145,38 +121,24 @@
     total_size += spec->nb_names * sizeof(short);
     if (spec->nb_names % 2) total_size += sizeof(short);
 
+    /* export name strings */
+    strings_size = strlen(spec->file_name) + 1;
+    for (i = 0; i < spec->nb_names; i++)
+        strings_size += strlen(spec->names[i]->name) + 1;
+
     /* forward strings */
     for (i = spec->base; i <= spec->limit; i++)
     {
         ORDDEF *odp = spec->ordinals[i];
-        if (odp && odp->flags & FLAG_FORWARD) fwd_size += strlen(odp->link_name) + 1;
+        if (odp && odp->flags & FLAG_FORWARD) strings_size += strlen(odp->link_name) + 1;
     }
-    total_size += (fwd_size + 3) & ~3;
+    total_size += (strings_size + 3) & ~3;
 
     return total_size;
 }
 
 
 /*******************************************************************
- *         output_export_names
- *
- * Output all the exported names for a Win32 module.
- */
-static void output_export_names( FILE *outfile, DLLSPEC *spec )
-{
-    int i, nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
-
-    if (!nr_exports) return;
-
-    fprintf( outfile, "\nconst char __wine_spec_exp_names[] =" );
-    fprintf( outfile, "\n    \"%s\\0\"", spec->file_name );
-    for (i = 0; i < spec->nb_names; i++)
-        fprintf( outfile, "\n    \"%s\\0\"", spec->names[i]->name );
-    fprintf( outfile, ";\n" );
-}
-
-
-/*******************************************************************
  *         output_exports
  *
  * Output the export table for a Win32 module.
@@ -198,7 +160,7 @@
     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* Characteristics */
     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* TimeDateStamp */
     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* MajorVersion/MinorVersion */
-    fprintf( outfile, "    \"\\t.long %s\\n\"\n", asm_name("__wine_spec_exp_names") ); /* Name */
+    fprintf( outfile, "    \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->base );        /* Base */
     fprintf( outfile, "    \"\\t.long %d\\n\"\n", nr_exports );        /* NumberOfFunctions */
     fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->nb_names );    /* NumberOfNames */
@@ -255,13 +217,10 @@
         fprintf( outfile, "    \"__wine_spec_exp_name_ptrs:\\n\"\n" );
         for (i = 0; i < spec->nb_names; i++)
         {
-            fprintf( outfile, "    \"\\t.long %s+%d\\n\"\n", asm_name("__wine_spec_exp_names"), namepos );
+            fprintf( outfile, "    \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
             namepos += strlen(spec->names[i]->name) + 1;
         }
-    }
 
-    if (spec->nb_names)
-    {
         /* output the function ordinals */
 
         fprintf( outfile, "    \"__wine_spec_exp_ordinals:\\n\"\n" );
@@ -276,6 +235,14 @@
         }
     }
 
+    /* output the export name strings */
+
+    fprintf( outfile, "    \"__wine_spec_exp_names:\\n\"\n" );
+    fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), spec->file_name );
+    for (i = 0; i < spec->nb_names; i++)
+        fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n",
+                 get_asm_string_keyword(), spec->names[i]->name );
+
     /* output forward strings */
 
     if (fwd_size)
@@ -287,8 +254,8 @@
             if (odp && (odp->flags & FLAG_FORWARD))
                 fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), odp->link_name );
         }
-        fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
     }
+    fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
 
     /* output relays */
 
@@ -356,29 +323,10 @@
         ORDDEF *odp = &spec->entry_points[i];
         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\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" );
[truncated at 1000 lines; 337 more skipped]