Hi,
This patch addresses most of the existing issues building Wines dlls
as native win32 dlls using msvc, namely:
- We need to export forwards from the .def file.
- We need to export any implemented ordinal functions and mark them
as NONAME.
- Functions exported by name only should not be given ordinal numbers
in the .def output, so that link.exe can fill up empy ordinal slots
and create a valid export table. Not doing this leads to an incorrect
export table without any warnings or errors during the build.
- This means that parsing the .def files has to treat ordinal numbers
as optional for named functions (just as link.exe/lib.exe do). This
concurs with the MSDN documentation for the .def file syntax.
- We need the stub functions to be present in the final dll file, or
our ordinal functions cannot be accessed. This is because link.exe
requires that all ordinals be present in order to generate a correct
ordinal export table.
This in turn requires that the .spec.c files compile correctly under
msvc, in order to get the stub functions included in the link.
However, we obviously don't need the pe header or export tables that
winebuild generates, since link.exe (and any other PE linker, for
that matter) does this work for us.
- Fixing the .spec.c file requires that we use RaiseException from
kernel32 instead of RtlRaiseException from ntdll, since no import
library is provided for ntdll by default. This can be fixed later but
requires large changes to the build environment to get dependencies
correct (we should generate our .def files from our .spec files when
building with msvc, just as we do under unix; we would then use our
own ntdll.def to link to ntdll functions).
- Several symbols are expected to be exported as private and by name
only, or they generate warnings when creating the .lib and .exp files
for the dll. This requires identifying said symbols, and correctly
generating and parsing the PRIVATE flag in .def files.
- Debug channels should be registered, this is accomplished using the
CRT static constructor data segment. This allows linking to proceed
by finding the debug channels, and (with upcoming patches) will allow
debug msgs to be printed.
- The added #ifdefs required for msvc made the output look more crufy
than it was, so I reduced the number of these with some macros at the
start of the generated output files.
Using this patch I can build a correctly functioning native
shlwapi.dll which will load and run under Windows, and as a native
dll under Wine. This includes being able to GetProcAddress() the
ordinal functions and call them. It should now be possible to create
distributable native trace dlls that can be installed under windows,
giving us non-instrusive monitoring of the internals of calls between
applications and native dlls.
Two remaining issues are what to do with register functions and 16
bit dlls.
Please comment if there are any issues with respect to cygwin that
occur after applying this patch. I imagine the ReactOS folks might be
interested as well; does anyone know how they build their dlls at
present?
License: X11
Cheers,
Jon
ChangeLog:
Jon Griffiths <jon_p_griffiths@yahoo.com>
+tools/winebuild/build.h tools/winebuild/import.c
tools/winebuild/parser.ctools/winebuild/spec16.c
tools/winebuild/spec32.c
Export '@'-functions and forwards
Support PRIVATE and optional ordinal numbers in .def files
Allow generated files to build correct dlls under msvc
Clean up the generated output
=====
"Don't wait for the seas to part, or messiahs to come;
Don't you sit around and waste this chance..." - Live
jon_p_griffiths@yahoo.com
__________________________________
Do you Yahoo!?
SBC Yahoo! DSL - Now only $29.95 per month!
http://sbc.yahoo.com
diff -u wine/tools/winebuild/build.h wine-develop/tools/winebuild/build.h
--- wine/tools/winebuild/build.h Sat Apr 26 19:33:24 2003
+++ wine-develop/tools/winebuild/build.h Sun Jul 6 03:13:23 2003
@@ -103,6 +103,7 @@
#define FLAG_REGISTER 0x10 /* use register calling convention */
#define FLAG_INTERRUPT 0x20 /* function is an interrupt handler */
#define FLAG_FORWARD 0x100 /* function is a forwarded name */
+#define FLAG_NAMEONLY 0x200 /* function can be assigned to any ordinal - '@' */
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
diff -u wine/tools/winebuild/import.c wine-develop/tools/winebuild/import.c
--- wine/tools/winebuild/import.c Sat May 31 12:38:16 2003
+++ wine-develop/tools/winebuild/import.c Sun Jul 6 09:39:20 2003
@@ -21,6 +21,7 @@
#include "config.h"
#include "wine/port.h"
+#include "wine/exception.h"
#include <ctype.h>
#include <fcntl.h>
@@ -304,22 +305,20 @@
}
if (!strcmp( name, "EXPORTS" )) goto next;
- /* check for ordinal */
- if (!p)
+ /* check for optional ordinal */
+ if (p && *p == '@')
{
- error( "Expected ordinal after function name\n" );
- goto next;
- }
- if (*p != '@' || !isdigit(p[1]))
- {
- error( "Expected ordinal after function name '%s'\n", name );
- goto next;
- }
- ordinal = strtol( p+1, &p, 10 );
- if (ordinal >= MAX_ORDINALS)
- {
- error( "Invalid ordinal number %d\n", ordinal );
- goto next;
+ if (!isdigit(p[1]))
+ {
+ error( "Expected ordinal after function name '%s'\n", name );
+ goto next;
+ }
+ ordinal = strtol( p+1, &p, 10 );
+ if (ordinal >= MAX_ORDINALS)
+ {
+ error( "Invalid ordinal number %d\n", ordinal );
+ goto next;
+ }
}
/* check for optional flags */
@@ -341,6 +340,11 @@
/* we don't support importing non-function entry points */
goto next;
}
+ else if (!strcmp( flags, "PRIVATE" ))
+ {
+ /* this symbol can only be imported through GetProcAddress() */
+ goto next;
+ }
else
{
error( "Garbage after ordinal declaration\n" );
@@ -781,7 +785,7 @@
/* thunks for imported functions */
- fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
+ fprintf( outfile, "ASM_DUMMY(import)\n" );
pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
for (i = 0; i < nb_imports; i++)
@@ -845,7 +849,8 @@
}
pos += 4;
}
- fprintf( outfile, "\".section\\t\\\".text\\\"\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
+ fprintf( outfile, "\".section\\t\\\".text\\\"\");\n"
+ "ASM_DUMMY_END\n\n" );
done:
return nb_imm;
@@ -929,7 +934,8 @@
fprintf( outfile, " unsigned int params;\n" );
fprintf( outfile, " const void *info[15];\n" );
fprintf( outfile, "};\n\n" );
- fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" );
+ fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n"
+ "extern void __stdcall RaiseException( unsigned long, unsigned long, unsigned long, const void* );\n" );
}
fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n");
@@ -948,26 +954,27 @@
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, " else {\n"
+ "#ifdef _MSC_VER\n"
+ " const void *rec[2];\n"
+ " rec[0] = imd->szName;\n"
+ " rec[1] = *pINT + 2;\n"
+ " for (;;) RaiseException(0x%08x, %d, 2, rec);\n", EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
+ fprintf( outfile, "#else\n" );
fprintf( outfile, " struct exc_record rec;\n" );
- fprintf( outfile, " rec.code = 0x80000100;\n" );
- fprintf( outfile, " rec.flags = 1;\n" );
+ fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
+ fprintf( outfile, " rec.flags = %d;\n" , EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\n" );
fprintf( outfile, " rec.info[0] = imd->szName;\n" );
fprintf( outfile, " rec.info[1] = *pINT + 2;\n" );
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, " rec.addr = 0;\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" );
- fprintf( outfile, " return 0; /* shouldn't go here */\n" );
- fprintf( outfile, " }\n}\n\n" );
-
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
- fprintf( outfile, "#endif\n" );
+ fprintf( outfile, " rec.addr = CALLER_ADDRESS;\n" );
+ fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n"
+ "#endif\n"
+ " return (void*)0; /* shouldn't get here */\n"
+ " }\n}\n\n" );
+
+ fprintf( outfile, "ASM_DUMMY(delay_import)\n" );
fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
@@ -1122,11 +1129,8 @@
fprintf( outfile, "\n" );
}
}
- fprintf( outfile, "\".section \\\".text\\\"\");\n" );
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "}\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, "\n" );
+ fprintf( outfile, "\".section \\\".text\\\"\");\n"
+ "ASM_DUMMY_END\n\n" );
done:
return nb_delayed;
diff -u wine/tools/winebuild/parser.c wine-develop/tools/winebuild/parser.c
--- wine/tools/winebuild/parser.c Sat Apr 26 19:33:25 2003
+++ wine-develop/tools/winebuild/parser.c Sun Jul 6 04:10:28 2003
@@ -466,6 +466,8 @@
fix_export_name( odp->name );
odp->lineno = current_line;
odp->ordinal = ordinal;
+ if (ordinal == -1)
+ odp->flags |= FLAG_NAMEONLY;
switch(odp->type)
{
diff -u wine/tools/winebuild/spec16.c wine-develop/tools/winebuild/spec16.c
--- wine/tools/winebuild/spec16.c Sat Apr 26 19:33:26 2003
+++ wine-develop/tools/winebuild/spec16.c Sun Jul 6 09:14:22 2003
@@ -63,16 +63,29 @@
static void output_file_header( FILE *outfile )
{
output_standard_file_header( outfile );
- fprintf( outfile, "extern struct\n{\n" );
- fprintf( outfile, " void *base[8192];\n" );
- fprintf( outfile, " unsigned long limit[8192];\n" );
- fprintf( outfile, " unsigned char flags[8192];\n" );
- fprintf( outfile, "} wine_ldt_copy;\n\n" );
-#ifdef __i386__
- fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
-#else
- fprintf( outfile, "#define __stdcall\n\n" );
-#endif
+ fprintf( outfile, "extern struct\n{\n"
+ " void *base[8192];\n"
+ " unsigned long limit[8192];\n"
+ " unsigned char flags[8192];\n"
+ "} wine_ldt_copy;\n\n"
+ "#ifdef __GNUC__\n"
+ "#define ASM_DUMMY(name)\n"
+ "#define ASM_DUMMY_END\n"
+ "#define CALLER_ADDRESS __builtin_return_address(1)\n"
+ "# ifdef __i386__\n"
+ "# define __stdcall __attribute__((__stdcall__))\n"
+ "# else\n"
+ "# define __stdcall\n"
+ "#endif\n"
+ "#else /* !__GNUC__ */\n"
+ "#define ASM_DUMMY(name) static void __asm__dummy_##name(void) {\n"
+ "#define ASM_DUMMY_END }\n"
+ "#define CALLER_ADDRESS 0\n"
+ "#define __attribute__(x)\n"
+ "# ifndef _MSC_VER\n"
+ "# define __stdcall\n"
+ "# endif\n"
+ "#endif\n\n" );
}
@@ -595,9 +608,7 @@
{
ORDDEF *odp = 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 *) __attribute__((noreturn));\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
fprintf( outfile, " struct exc_record {\n" );
fprintf( outfile, " unsigned int code, flags;\n" );
@@ -605,19 +616,23 @@
fprintf( outfile, " unsigned int params;\n" );
fprintf( outfile, " const void *info[15];\n" );
fprintf( outfile, " } rec;\n\n" );
- fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
+ fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n"
+ " extern void __stdcall RaiseException( unsigned long, unsigned long, unsigned long, const void* );\n\n"
+ "#ifdef _MSC_VER\n"
+ " const void *rec[2];\n"
+ " rec[0] = \"%s\";\n"
+ " rec[1] = func;\n"
+ " for (;;) RaiseException(0x%08x, %d, 2, rec);\n", dll_file_name, EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
+ fprintf( outfile, "#else\n" );
fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
- fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
+ fprintf( outfile, " rec.flags = %d;\n" , EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\n" );
fprintf( outfile, " rec.info[0] = \"%s\";\n", dll_file_name );
fprintf( outfile, " rec.info[1] = func;\n" );
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, " rec.addr = 0;\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
+ fprintf( outfile, " rec.addr = CALLER_ADDRESS;\n" );
+ fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n"
+ "#endif\n}\n\n" );
break;
}
for (i = 0; i <= Limit; i++)
diff -u wine/tools/winebuild/spec32.c wine-develop/tools/winebuild/spec32.c
--- wine/tools/winebuild/spec32.c Sat Apr 26 19:33:26 2003
+++ wine-develop/tools/winebuild/spec32.c Tue Jul 8 21:01:32 2003
@@ -104,6 +104,16 @@
if (!nb_debug_channels) return 0;
qsort( debug_channels, nb_debug_channels, sizeof(debug_channels[0]), string_compare );
+ fprintf( outfile,
+ "#if defined (__GNUC__) || defined(_MSC_VER)\n"
+ "#define LOCAL static\n"
+ "#else\n"
+ "#define LOCAL\n"
+ "#endif\n\n"
+ "#ifndef __GNUC__\n"
+ "#define __attribute__(x)\n"
+ "#endif\n\n" );
+
for (i = 0; i < nb_debug_channels; i++)
fprintf( outfile, "char __wine_dbch_%s[] = \"\\003%s\";\n",
debug_channels[i], debug_channels[i] );
@@ -296,7 +306,7 @@
fprintf( outfile, " \"\\t.text\\n\"\n" );
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
- fprintf( outfile, ");\n\n" );
+ fprintf( outfile, ");\n" );
return total_size;
}
@@ -315,30 +325,31 @@
{
ORDDEF *odp = EntryPoints[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" );
- fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
- fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
- fprintf( outfile, " struct exc_record rec;\n" );
+ fprintf( outfile, " struct exc_record {\n"
+ " unsigned int code, flags;\n"
+ " void *rec, *addr;\n"
+ " unsigned int params;\n"
+ " const void *info[15];\n"
+ " } rec;\n\n"
+ "extern void __stdcall RtlRaiseException( struct exc_record * );\n"
+ "extern void __stdcall RaiseException( unsigned long, unsigned long, unsigned long, const void* );\n\n"
+ "static void __wine_unimplemented( const char *) __attribute__((noreturn));\n"
+ "static void __wine_unimplemented( const char *func )\n{\n"
+ "#ifdef _MSC_VER\n"
+ " const void *rec[2];\n"
+ " rec[0] = dllname;\n"
+ " rec[1] = func;\n"
+ " for (;;) RaiseException(0x%08x, %d, 2, rec);\n", EXCEPTION_WINE_STUB, EH_NONCONTINUABLE );
+ fprintf( outfile, "#else\n" );
fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\n" );
fprintf( outfile, " rec.info[0] = dllname;\n" );
fprintf( outfile, " rec.info[1] = func;\n" );
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, " rec.addr = 0;\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
+ fprintf( outfile, " rec.addr = CALLER_ADDRESS;\n" );
+ fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n"
+ "#endif\n}\n\n" );
break;
}
@@ -354,6 +365,7 @@
else
fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
}
+ fprintf( outfile, "\n\n" );
}
@@ -396,9 +408,7 @@
*/
void output_dll_init( FILE *outfile, const char *constructor, const char *destructor )
{
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
- fprintf( outfile, "#endif\n" );
+ fprintf( outfile, "ASM_DUMMY(dll_init)\n" );
#if defined(__i386__)
if (constructor)
@@ -444,9 +454,7 @@
#else
#error You need to define the DLL constructor for your architecture
#endif
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "}\n" );
- fprintf( outfile, "#endif\n" );
+ fprintf( outfile, "ASM_DUMMY_END\n" );
}
@@ -485,25 +493,35 @@
/* Reserve some space for the PE header */
+ fprintf( outfile, "#ifdef __GNUC__\n"
+ "#define ASM_DUMMY(name)\n"
+ "#define ASM_DUMMY_END\n"
+ "#define CALLER_ADDRESS __builtin_return_address(1)\n"
+ "# ifdef __i386__\n"
+ "# define __stdcall __attribute__((__stdcall__))\n"
+ "# else\n"
+ "# define __stdcall\n"
+ "# endif\n"
+ "#else\n"
+ "#define ASM_DUMMY(name) static void __asm__dummy_##name(void) {\n"
+ "#define ASM_DUMMY_END }\n"
+ "#define CALLER_ADDRESS 0\n"
+ "#define __attribute__(x)\n"
+ "# ifndef _MSC_VER\n"
+ "# define __stdcall\n"
+ "# endif\n"
+ "#endif\n\n" );
+
+ fprintf( outfile, "static const char dllname[] = \"%s\";\n\n", dll_file_name );
fprintf( outfile, "extern char pe_header[];\n" );
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "static void __asm__dummy_header(void) {\n" );
- fprintf( outfile, "#endif\n" );
- fprintf( outfile, "asm(\".section \\\".text\\\"\\n\\t\"\n" );
+ fprintf( outfile, "extern int __wine_spec_exports[];\n\n"
+ "#ifndef _MSC_VER\n"
+ "ASM_DUMMY(header)\n"
+ "asm(\".section \\\".text\\\"\\n\\t\"\n" );
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(page_size) );
fprintf( outfile, " \"" __ASM_NAME("pe_header") ":\\t.skip 65536\\n\\t\");\n" );
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "}\n" );
- fprintf( outfile, "#endif\n" );
-
- fprintf( outfile, "static const char dllname[] = \"%s\";\n\n", dll_file_name );
- fprintf( outfile, "extern int __wine_spec_exports[];\n\n" );
-
-#ifdef __i386__
- fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
-#else
- fprintf( outfile, "#define __stdcall\n\n" );
-#endif
+ fprintf( outfile, "ASM_DUMMY_END\n"
+ "#endif\n\n" );
if (nr_exports)
{
@@ -511,9 +529,8 @@
output_stub_funcs( outfile );
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "static void __asm__dummy(void) {\n" );
- fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
+ fprintf( outfile, "#ifndef _MSC_VER\n"
+ "ASM_DUMMY(exports)\n" );
/* Output code for all register functions */
@@ -523,10 +540,10 @@
exports_size = output_exports( outfile, nr_exports );
- fprintf( outfile, "#ifndef __GNUC__\n" );
- fprintf( outfile, "}\n" );
- fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
+ fprintf( outfile, "ASM_DUMMY_END\n\n" );
}
+ else
+ fprintf( outfile, "#ifndef _MSC_VER\n" );
/* Output the DLL imports */
@@ -545,13 +562,12 @@
if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
else
{
- fprintf( outfile, "#ifdef __GNUC__\n" );
- fprintf( outfile, "extern void DllMain() __attribute__((weak));\n" );
- fprintf( outfile, "#else\n" );
- fprintf( outfile, "extern void DllMain();\n" );
- fprintf( outfile, "static void __asm__dummy_dllmain(void)" );
- fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" );
- fprintf( outfile, "#endif\n" );
+ fprintf( outfile, "extern void DllMain() __attribute__((weak));\n"
+ "#ifndef __GNUC__\n"
+ "ASM_DUMMY(dllmain)\n" );
+ fprintf( outfile, "asm(\".weak " __ASM_NAME("DllMain") "\");\n"
+ "ASM_DUMMY_END\n"
+ "#endif\n\n" );
}
characteristics = IMAGE_FILE_DLL;
break;
@@ -781,12 +797,26 @@
"void %s(void)\n"
"{\n"
" extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
- " extern void *__wine_dbg_register( char * const *, int );\n"
- " __wine_dll_register( &nt_header, \"%s\" );\n"
- "}\n",
- constructor, dll_file_name );
+ " __wine_dll_register( &nt_header, dllname );\n"
+ "}\n"
+ "#endif /* defined(_MSC_VER) */\n",
+ constructor );
}
+/* These symbols are expected to be private by default */
+static const char *private_exports[] = {
+ "DllRegisterServer",
+ "DllRegisterServerEx",
+ "DllUnregisterServer",
+ "DllGetClassObject",
+ "DllCanUnloadNow"
+};
+
+/* In addition to private_exports, these should not be exported by ordinal */
+static const char *no_ordinal_exports[] = {
+ "DllGetClassFactoryFromClassString",
+ "DllInstall"
+};
/*******************************************************************
* BuildDef32File
@@ -811,15 +841,32 @@
for(i = 0; i < nb_entry_points; i++)
{
+ char name_buff[256];
ORDDEF *odp = EntryPoints[i];
- int is_data = 0;
+ int is_data = 0, is_private = 0, no_ordinal = 0;
+ unsigned int j;
if (!odp) continue;
if (odp->flags & FLAG_REGISTER) continue;
- if (odp->type == TYPE_STUB) continue;
-
- if (odp->name) name = odp->name;
+ if (odp->flags & FLAG_FORWARD)
+ {
+ if (!odp->name)
+ {
+ /* We may fwd to this fn more than once, so make name unique */
+ sprintf(name_buff, make_internal_name( odp, "fwd" ));
+ name = name_buff;
+ }
+ else
+ name = odp->name;
+ }
+ else if (odp->type == TYPE_STUB)
+ {
+ sprintf(name_buff, make_internal_name( odp, "stub" ));
+ name = name_buff;
+ }
+ else if (odp->name) name = odp->name;
else if (odp->export_name) name = odp->export_name;
+ else if (odp->link_name) name = odp->link_name;
else continue;
fprintf(outfile, " %s", name);
@@ -850,11 +897,43 @@
}
break;
}
+ case TYPE_STUB:
+ break;
default:
assert(0);
}
- fprintf(outfile, " @%d%s%s\n", odp->ordinal,
- odp->name ? "" : " NONAME", is_data ? " DATA" : "" );
+ /* Determine which components to write out */
+ if (!(odp->flags & FLAG_FORWARD))
+ {
+ for(j = 0; j < sizeof(private_exports)/sizeof(private_exports[0]); j++)
+ {
+ if (!strcmp( name, private_exports[j]))
+ {
+ is_private = 1;
+ no_ordinal = 1;
+ }
+ }
+ }
+
+ if (odp->flags & FLAG_NAMEONLY)
+ no_ordinal = 1;
+ else
+ {
+ for(j = 0; j < sizeof(no_ordinal_exports)/sizeof(no_ordinal_exports[0]); j++)
+ {
+ if (!strcmp( name, no_ordinal_exports[j]))
+ {
+ no_ordinal = 1;
+ }
+ }
+ }
+
+ if (!no_ordinal)
+ fprintf(outfile, " @%d", odp->ordinal);
+
+ fprintf( outfile, "%s%s%s\n",
+ odp->name ? "" : " NONAME", is_data ? " DATA" : "",
+ is_private ? " PRIVATE" : "" );
}
}
@@ -891,15 +970,17 @@
}
else prefix = xstrdup( "_" );
- /* Output the DLL constructor */
+ /* Output the debug channel constructor */
fprintf( outfile,
- "#ifdef __GNUC__\n"
- "static void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
- "static void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
- "#else\n"
+ "LOCAL void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
+ "LOCAL void __wine_dbg_%s_fini(void) __attribute__((destructor));\n\n"
+ "#ifdef _MSC_VER\n\n"
+ "#pragma data_seg(\".CRT$XCU\") /* static ctors */\n"
+ "void (*__wine_dbg_%s_init_ptr)() = __wine_dbg_%s_init;\n\n"
+ "#elif !defined(__GNUC__)\n\n"
"static void __asm__dummy_dll_init(void) {\n",
- prefix, prefix );
+ prefix, prefix, prefix, prefix );
#if defined(__i386__)
fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
@@ -922,24 +1003,18 @@
fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" );
#else
-#error You need to define the DLL constructor for your architecture
+#error You need to define the debug constructor for your architecture
#endif
- fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n" );
+ fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
fprintf( outfile,
- "\n#ifdef __GNUC__\n"
- "static\n"
- "#endif\n"
- "void __wine_dbg_%s_init(void)\n"
+ "LOCAL void __wine_dbg_%s_init(void)\n"
"{\n"
" extern void *__wine_dbg_register( char * const *, int );\n"
" debug_registration = __wine_dbg_register( debug_channels, %d );\n"
- "}\n", prefix, nr_debug );
+ "}\n\n", prefix, nr_debug );
fprintf( outfile,
- "\n#ifdef __GNUC__\n"
- "static\n"
- "#endif\n"
- "void __wine_dbg_%s_fini(void)\n"
+ "LOCAL void __wine_dbg_%s_fini(void)\n"
"{\n"
" extern void __wine_dbg_unregister( void* );\n"
" __wine_dbg_unregister( debug_registration );\n"