Use libwine and libwine_unicode directly from their build directory
[wine] / tools / winebuild / spec32.c
1 /*
2  * 32-bit spec files
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Martin von Loewis
6  * Copyright 1995, 1996, 1997 Alexandre Julliard
7  * Copyright 1997 Eric Youngdale
8  * Copyright 1999 Ulrich Weigand
9  */
10
11 #include <assert.h>
12 #include <ctype.h>
13 #include <unistd.h>
14
15 #include "config.h"
16 #include "winbase.h"
17 #include "wine/exception.h"
18 #include "build.h"
19
20
21 static int string_compare( const void *ptr1, const void *ptr2 )
22 {
23     const char * const *str1 = ptr1;
24     const char * const *str2 = ptr2;
25     return strcmp( *str1, *str2 );
26 }
27
28
29 /*******************************************************************
30  *         make_internal_name
31  *
32  * Generate an internal name for an entry point. Used for stubs etc.
33  */
34 static const char *make_internal_name( const ORDDEF *odp, const char *prefix )
35 {
36     static char buffer[256];
37     if (odp->name[0]) sprintf( buffer, "__wine_%s_%s", prefix, odp->name );
38     else sprintf( buffer, "__wine_%s_%d", prefix, odp->ordinal );
39     return buffer;
40 }
41
42 /*******************************************************************
43  *         AssignOrdinals
44  *
45  * Assign ordinals to all entry points.
46  */
47 static void AssignOrdinals(void)
48 {
49     int i, ordinal;
50
51     if ( !nb_names ) return;
52
53     /* start assigning from Base, or from 1 if no ordinal defined yet */
54     if (Base == MAX_ORDINALS) Base = 1;
55     for (i = 0, ordinal = Base; i < nb_names; i++)
56     {
57         if (Names[i]->ordinal != -1) continue;  /* already has an ordinal */
58         while (Ordinals[ordinal]) ordinal++;
59         if (ordinal >= MAX_ORDINALS)
60         {
61             current_line = Names[i]->lineno;
62             fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
63         }
64         Names[i]->ordinal = ordinal;
65         Ordinals[ordinal] = Names[i];
66     }
67     if (ordinal > Limit) Limit = ordinal;
68 }
69
70
71 /*******************************************************************
72  *         output_debug
73  *
74  * Output the debug channels.
75  */
76 static int output_debug( FILE *outfile )
77 {
78     int i;
79
80     if (!nb_debug_channels) return 0;
81     qsort( debug_channels, nb_debug_channels, sizeof(debug_channels[0]), string_compare );
82
83     for (i = 0; i < nb_debug_channels; i++)
84         fprintf( outfile, "char __wine_dbch_%s[] = \"\\003%s\";\n",
85                  debug_channels[i], debug_channels[i] );
86
87     fprintf( outfile, "\nstatic char * const debug_channels[%d] =\n{\n", nb_debug_channels );
88     for (i = 0; i < nb_debug_channels; i++)
89     {
90         fprintf( outfile, "    __wine_dbch_%s", debug_channels[i] );
91         if (i < nb_debug_channels - 1) fprintf( outfile, ",\n" );
92     }
93     fprintf( outfile, "\n};\n\n" );
94     fprintf( outfile, "static void *debug_registration;\n\n" );
95
96     return nb_debug_channels;
97 }
98
99
100 /*******************************************************************
101  *         output_exports
102  *
103  * Output the export table for a Win32 module.
104  */
105 static void output_exports( FILE *outfile, int nr_exports, int fwd_size )
106 {
107     int i, fwd_pos = 0;
108
109     if (!nr_exports) return;
110
111     fprintf( outfile, "\n\n/* exports */\n\n" );
112     fprintf( outfile, "typedef void (*func_ptr)();\n" );
113     fprintf( outfile, "static struct {\n" );
114     fprintf( outfile, "  struct {\n" );
115     fprintf( outfile, "    unsigned int    Characteristics;\n" );
116     fprintf( outfile, "    unsigned int    TimeDateStamp;\n" );
117     fprintf( outfile, "    unsigned short  MajorVersion;\n" );
118     fprintf( outfile, "    unsigned short  MinorVersion;\n" );
119     fprintf( outfile, "    const char     *Name;\n" );
120     fprintf( outfile, "    unsigned int    Base;\n" );
121     fprintf( outfile, "    unsigned int    NumberOfFunctions;\n" );
122     fprintf( outfile, "    unsigned int    NumberOfNames;\n" );
123     fprintf( outfile, "    func_ptr       *AddressOfFunctions;\n" );
124     fprintf( outfile, "    const char    **AddressOfNames;\n" );
125     fprintf( outfile, "    unsigned short *AddressOfNameOrdinals;\n" );
126     fprintf( outfile, "    func_ptr        functions[%d];\n", nr_exports );
127     if (nb_names)
128     {
129         fprintf( outfile, "    const char     *names[%d];\n", nb_names );
130         fprintf( outfile, "    unsigned short  ordinals[%d];\n", nb_names );
131         if (nb_names % 2) fprintf( outfile, "    unsigned short  pad1;\n" );
132     }
133     if (fwd_size)
134     {
135         fprintf( outfile, "    char            forwards[%d];\n", (fwd_size + 3) & ~3 );
136     }
137     fprintf( outfile, "  } exp;\n" );
138
139     if (debugging)
140     {
141         fprintf( outfile, "  struct {\n" );
142         fprintf( outfile, "    unsigned char  jmp;\n" );
143         fprintf( outfile, "    unsigned char  addr[4];\n" );
144         fprintf( outfile, "    unsigned char  ret;\n" );
145         fprintf( outfile, "    unsigned short args;\n" );
146         fprintf( outfile, "    func_ptr       orig;\n" );
147         fprintf( outfile, "    unsigned int   argtypes;\n" );
148         fprintf( outfile, "  } relay[%d];\n", nr_exports );
149     }
150
151     fprintf( outfile, "} exports = {\n  {\n" );
152     fprintf( outfile, "    0,\n" );                 /* Characteristics */
153     fprintf( outfile, "    0,\n" );                 /* TimeDateStamp */
154     fprintf( outfile, "    0,\n" );                 /* MajorVersion */
155     fprintf( outfile, "    0,\n" );                 /* MinorVersion */
156     fprintf( outfile, "    dllname,\n" );           /* Name */
157     fprintf( outfile, "    %d,\n", Base );          /* Base */
158     fprintf( outfile, "    %d,\n", nr_exports );    /* NumberOfFunctions */
159     fprintf( outfile, "    %d,\n", nb_names );      /* NumberOfNames */
160     fprintf( outfile, "    exports.exp.functions,\n" ); /* AddressOfFunctions */
161     if (nb_names)
162     {
163         fprintf( outfile, "    exports.exp.names,\n" );     /* AddressOfNames */
164         fprintf( outfile, "    exports.exp.ordinals,\n" );  /* AddressOfNameOrdinals */
165     }
166     else
167     {
168         fprintf( outfile, "    0,\n" );  /* AddressOfNames */
169         fprintf( outfile, "    0,\n" );  /* AddressOfNameOrdinals */
170     }
171
172     /* output the function addresses */
173
174     fprintf( outfile, "    {\n      " );
175     for (i = Base; i <= Limit; i++)
176     {
177         ORDDEF *odp = Ordinals[i];
178         if (!odp) fprintf( outfile, "0" );
179         else switch(odp->type)
180         {
181         case TYPE_EXTERN:
182             fprintf( outfile, "%s", odp->u.ext.link_name );
183             break;
184         case TYPE_STDCALL:
185         case TYPE_VARARGS:
186         case TYPE_CDECL:
187             fprintf( outfile, "%s", odp->u.func.link_name);
188             break;
189         case TYPE_STUB:
190             fprintf( outfile, "%s", make_internal_name( odp, "stub" ) );
191             break;
192         case TYPE_REGISTER:
193             fprintf( outfile, "%s", make_internal_name( odp, "regs" ) );
194             break;
195         case TYPE_VARIABLE:
196             fprintf( outfile, "(func_ptr)%s", make_internal_name( odp, "var" ) );
197             break;
198         case TYPE_FORWARD:
199             fprintf( outfile, "(func_ptr)&exports.exp.forwards[%d] /* %s */",
200                      fwd_pos, odp->u.fwd.link_name );
201             fwd_pos += strlen(odp->u.fwd.link_name) + 1;
202             break;
203         default:
204             assert(0);
205         }
206         if (i < Limit) fprintf( outfile, ",\n      " );
207         else fprintf( outfile, "\n    },\n" );
208     }
209
210     if (nb_names)
211     {
212         /* output the function names */
213
214         fprintf( outfile, "    {\n" );
215         for (i = 0; i < nb_names; i++)
216         {
217             if (i) fprintf( outfile, ",\n" );
218             fprintf( outfile, "      \"%s\"", Names[i]->name );
219         }
220         fprintf( outfile, "\n    },\n" );
221
222         /* output the function ordinals */
223
224         fprintf( outfile, "    {\n     " );
225         for (i = 0; i < nb_names; i++)
226         {
227             fprintf( outfile, "%4d", Names[i]->ordinal - Base );
228             if (i < nb_names-1)
229             {
230                 fputc( ',', outfile );
231                 if ((i % 8) == 7) fprintf( outfile, "\n     " );
232             }
233         }
234         fprintf( outfile, "\n    },\n" );
235         if (nb_names % 2) fprintf( outfile, "    0,\n" );
236     }
237
238     /* output forwards */
239
240     if (fwd_size)
241     {
242         for (i = Base; i <= Limit; i++)
243         {
244             ORDDEF *odp = Ordinals[i];
245             if (odp && odp->type == TYPE_FORWARD)
246                 fprintf( outfile, "    \"%s\\0\"\n", odp->u.fwd.link_name );
247         }
248     }
249
250     /* output relays */
251
252     if (debugging)
253     {
254         fprintf( outfile, "  },\n  {\n" );
255         for (i = Base; i <= Limit; i++)
256         {
257             ORDDEF *odp = Ordinals[i];
258             unsigned int j, mask = 0;
259
260             /* skip non-existent entry points */
261             if (!odp) goto ignore;
262             /* skip non-functions */
263             if ((odp->type != TYPE_STDCALL) &&
264                 (odp->type != TYPE_CDECL) &&
265                 (odp->type != TYPE_REGISTER)) goto ignore;
266             /* skip norelay entry points */
267             if (odp->flags & FLAG_NORELAY) goto ignore;
268
269             for (j = 0; odp->u.func.arg_types[j]; j++)
270             {
271                 if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
272                 if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
273             }
274             if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
275
276             switch(odp->type)
277             {
278             case TYPE_STDCALL:
279                 fprintf( outfile, "    { 0xe9, { 0,0,0,0 }, 0xc2, 0x%04x, %s, 0x%08x }",
280                          strlen(odp->u.func.arg_types) * sizeof(int),
281                          odp->u.func.link_name, mask );
282                 break;
283             case TYPE_CDECL:
284                 fprintf( outfile, "    { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, %s, 0x%08x }",
285                          strlen(odp->u.func.arg_types) * sizeof(int),
286                          odp->u.func.link_name, mask );
287                 break;
288             case TYPE_REGISTER:
289                 fprintf( outfile, "    { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, %s, 0x%08x }",
290                          0x8000 | (strlen(odp->u.func.arg_types) * sizeof(int)),
291                          make_internal_name( odp, "regs" ), mask );
292                 break;
293             default:
294                 assert(0);
295             }
296             goto done;
297
298         ignore:
299             fprintf( outfile, "    { 0, { 0,0,0,0 }, 0, 0, 0, 0 }" );
300         done:
301             if (i < Limit) fprintf( outfile, ",\n" );
302         }
303     }
304
305     fprintf( outfile, "  }\n};\n\n" );
306
307     /* output __wine_dllexport symbols */
308
309     for (i = 0; i < nb_names; i++)
310     {
311         char *p;
312         if (Names[i]->flags & FLAG_NOIMPORT) continue;
313         /* check for invalid characters in the name */
314         for (p = Names[i]->name; *p; p++) if (!isalnum(*p) && *p != '_') break;
315         if (!*p) fprintf( outfile, "const char __wine_dllexport_%s_%s = 0;\n",
316                           DLLName, Names[i]->name );
317     }
318 }
319
320
321 /*******************************************************************
322  *         output_stub_funcs
323  *
324  * Output the functions for stub entry points
325 */
326 static void output_stub_funcs( FILE *outfile )
327 {
328     int i;
329     ORDDEF *odp;
330
331     for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
332     {
333         if (odp->type != TYPE_STUB) continue;
334         fprintf( outfile, "#ifdef __GNUC__\n" );
335         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
336         fprintf( outfile, "#endif\n" );
337         fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
338         fprintf( outfile, "  struct exc_record {\n" );
339         fprintf( outfile, "    unsigned int code, flags;\n" );
340         fprintf( outfile, "    void *rec, *addr;\n" );
341         fprintf( outfile, "    unsigned int params;\n" );
342         fprintf( outfile, "    const void *info[15];\n" );
343         fprintf( outfile, "  } rec;\n" );
344         fprintf( outfile, "  extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
345         fprintf( outfile, "  rec.code    = 0x%08x;\n", EXCEPTION_WINE_STUB );
346         fprintf( outfile, "  rec.flags   = %d;\n", EH_NONCONTINUABLE );
347         fprintf( outfile, "  rec.rec     = 0;\n" );
348         fprintf( outfile, "  rec.params  = 2;\n" );
349         fprintf( outfile, "  rec.info[0] = dllname;\n" );
350         fprintf( outfile, "  rec.info[1] = func;\n" );
351         fprintf( outfile, "#ifdef __GNUC__\n" );
352         fprintf( outfile, "  rec.addr = __builtin_return_address(1);\n" );
353         fprintf( outfile, "#else\n" );
354         fprintf( outfile, "  rec.addr = 0;\n" );
355         fprintf( outfile, "#endif\n" );
356         fprintf( outfile, "  for (;;) RtlRaiseException( &rec );\n}\n\n" );
357         break;
358     }
359
360     for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
361     {
362         if (odp->type != TYPE_STUB) continue;
363         fprintf( outfile, "static void %s(void) ", make_internal_name( odp, "stub" ) );
364         if (odp->name[0])
365             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
366         else
367             fprintf( outfile, "{ __wine_unimplemented(\"%d\"); }\n", odp->ordinal );
368     }
369 }
370
371
372 /*******************************************************************
373  *         output_register_funcs
374  *
375  * Output the functions for register entry points
376  */
377 static void output_register_funcs( FILE *outfile )
378 {
379     ORDDEF *odp;
380     const char *name;
381     int i;
382
383     fprintf( outfile, "#ifndef __GNUC__\n" );
384     fprintf( outfile, "static void __asm__dummy(void) {\n" );
385     fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
386     for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
387     {
388         if (odp->type != TYPE_REGISTER) continue;
389         name = make_internal_name( odp, "regs" );
390         fprintf( outfile,
391                  "asm(\".align 4\\n\\t\"\n"
392                  "    \"" __ASM_FUNC("%s") "\\n\\t\"\n"
393                  "    \"" PREFIX "%s:\\n\\t\"\n"
394                  "    \"call " PREFIX "CALL32_Regs\\n\\t\"\n"
395                  "    \".long " PREFIX "%s\\n\\t\"\n"
396                  "    \".byte %d,%d\");\n",
397                  name, name, odp->u.func.link_name,
398                  4 * strlen(odp->u.func.arg_types), 4 * strlen(odp->u.func.arg_types) );
399     }
400     fprintf( outfile, "#ifndef __GNUC__\n" );
401     fprintf( outfile, "}\n" );
402     fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
403 }
404
405
406 /*******************************************************************
407  *         BuildSpec32File
408  *
409  * Build a Win32 C file from a spec file.
410  */
411 void BuildSpec32File( FILE *outfile )
412 {
413     ORDDEF *odp;
414     int i, j, fwd_size = 0, have_regs = FALSE;
415     int nr_exports, nr_imports, nr_resources, nr_debug;
416     int characteristics, subsystem, has_imports;
417     const char *init_func;
418     DWORD page_size;
419
420 #ifdef HAVE_GETPAGESIZE
421     page_size = getpagesize();
422 #else
423 # ifdef __svr4__
424     page_size = sysconf(_SC_PAGESIZE);
425 # else
426 #   error Cannot get the page size on this platform
427 # endif
428 #endif
429
430     AssignOrdinals();
431     nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
432
433     has_imports = resolve_imports( outfile );
434
435     fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
436              input_file_name );
437
438     /* Reserve some space for the PE header */
439
440     fprintf( outfile, "extern char pe_header[];\n" );
441     fprintf( outfile, "asm(\".section .text\\n\\t\"\n" );
442     fprintf( outfile, "    \".align %ld\\n\"\n", page_size );
443     fprintf( outfile, "    \"pe_header:\\t.fill %ld,1,0\\n\\t\");\n", page_size );
444
445     fprintf( outfile, "static const char dllname[] = \"%s\";\n\n", DLLName );
446
447 #ifdef __i386__
448     fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
449 #else
450     fprintf( outfile, "#define __stdcall\n\n" );
451 #endif
452
453     /* Output the stub functions */
454
455     output_stub_funcs( outfile );
456
457     /* Output the DLL functions prototypes */
458
459     for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
460     {
461         switch(odp->type)
462         {
463         case TYPE_EXTERN:
464             fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name );
465             break;
466         case TYPE_STDCALL:
467         case TYPE_VARARGS:
468         case TYPE_CDECL:
469             fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
470             break;
471         case TYPE_FORWARD:
472             fwd_size += strlen(odp->u.fwd.link_name) + 1;
473             break;
474         case TYPE_REGISTER:
475             fprintf( outfile, "extern void %s();\n", make_internal_name( odp, "regs" ) );
476             have_regs = TRUE;
477             break;
478         case TYPE_STUB:
479             break;
480         case TYPE_VARIABLE:
481             fprintf( outfile, "unsigned int %s[%d] = {",
482                      make_internal_name( odp, "var" ), odp->u.var.n_values );
483             for (j = 0; j < odp->u.var.n_values; j++)
484             {
485                 fprintf( outfile, " 0x%08x", odp->u.var.values[j] );
486                 if (j < odp->u.var.n_values-1) fputc( ',', outfile );
487             }
488             fprintf( outfile, " };\n" );
489             break;
490         default:
491             fatal_error("function type %d not available for Win32\n", odp->type);
492         }
493     }
494
495     /* Output code for all register functions */
496
497     if (have_regs) output_register_funcs( outfile );
498
499     /* Output the exports and relay entry points */
500
501     output_exports( outfile, nr_exports, fwd_size );
502
503     /* Output the DLL imports */
504
505     nr_imports = output_imports( outfile );
506
507     /* Output the resources */
508
509     nr_resources = output_resources( outfile );
510
511     /* Output the debug channels */
512
513     nr_debug = output_debug( outfile );
514
515     /* Output LibMain function */
516
517     init_func = DLLInitFunc[0] ? DLLInitFunc : NULL;
518     characteristics = subsystem = 0;
519     switch(SpecMode)
520     {
521     case SPEC_MODE_DLL:
522         if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
523         characteristics = IMAGE_FILE_DLL;
524         break;
525     case SPEC_MODE_GUIEXE:
526         if (!init_func) init_func = "WinMain";
527         fprintf( outfile,
528                  "\n#include <winbase.h>\n"
529                  "int _ARGC;\n"
530                  "char **_ARGV;\n"
531                  "static void __wine_exe_main(void)\n"
532                  "{\n"
533                  "    extern int PASCAL %s(HINSTANCE,HINSTANCE,LPSTR,INT);\n"
534                  "    extern int __wine_get_main_args( char ***argv );\n"
535                  "    STARTUPINFOA info;\n"
536                  "    LPSTR cmdline = GetCommandLineA();\n"
537                  "    while (*cmdline && *cmdline != ' ') cmdline++;\n"
538                  "    if (*cmdline) cmdline++;\n"
539                  "    GetStartupInfoA( &info );\n"
540                  "    if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;\n"
541                  "    _ARGC = __wine_get_main_args( &_ARGV );\n"
542                  "    ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
543                  "}\n\n", init_func, init_func );
544         if (!has_imports)
545             fprintf( outfile,
546                      "int main( int argc, char *argv[] )\n"
547                      "{\n"
548                      "    extern void PROCESS_InitWinelib( int, char ** );\n"
549                      "    PROCESS_InitWinelib( argc, argv );\n"
550                      "    return 1;\n"
551                      "}\n\n" );
552         init_func = "__wine_exe_main";
553         subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
554         break;
555     case SPEC_MODE_CUIEXE:
556         if (!init_func) init_func = has_imports ? "main" : "wine_main";
557         fprintf( outfile,
558                  "\nint _ARGC;\n"
559                  "char **_ARGV;\n"
560                  "static void __wine_exe_main(void)\n"
561                  "{\n"
562                  "    extern int %s( int argc, char *argv[] );\n"
563                  "    extern int __wine_get_main_args( char ***argv );\n"
564                  "    extern void __stdcall ExitProcess(int);\n"
565                  "    _ARGC = __wine_get_main_args( &_ARGV );\n"
566                  "    ExitProcess( %s( _ARGC, _ARGV ) );\n"
567                  "}\n\n", init_func, init_func );
568         if (!has_imports)
569             fprintf( outfile,
570                      "int main( int argc, char *argv[] )\n"
571                      "{\n"
572                      "    extern void PROCESS_InitWinelib( int, char ** );\n"
573                      "    PROCESS_InitWinelib( argc, argv );\n"
574                      "    return 1;\n"
575                      "}\n\n" );
576         init_func = "__wine_exe_main";
577         subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
578         break;
579     case SPEC_MODE_GUIEXE_NO_MAIN:
580         if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
581         subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
582         break;
583     case SPEC_MODE_CUIEXE_NO_MAIN:
584         if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
585         subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
586         break;
587     }
588
589     /* Output the NT header */
590
591     /* this is the IMAGE_NT_HEADERS structure, but we cannot include winnt.h here */
592     fprintf( outfile, "static const struct image_nt_headers\n{\n" );
593     fprintf( outfile, "  int Signature;\n" );
594     fprintf( outfile, "  struct file_header {\n" );
595     fprintf( outfile, "    short Machine;\n" );
596     fprintf( outfile, "    short NumberOfSections;\n" );
597     fprintf( outfile, "    int   TimeDateStamp;\n" );
598     fprintf( outfile, "    void *PointerToSymbolTable;\n" );
599     fprintf( outfile, "    int   NumberOfSymbols;\n" );
600     fprintf( outfile, "    short SizeOfOptionalHeader;\n" );
601     fprintf( outfile, "    short Characteristics;\n" );
602     fprintf( outfile, "  } FileHeader;\n" );
603     fprintf( outfile, "  struct opt_header {\n" );
604     fprintf( outfile, "    short Magic;\n" );
605     fprintf( outfile, "    char  MajorLinkerVersion, MinorLinkerVersion;\n" );
606     fprintf( outfile, "    int   SizeOfCode;\n" );
607     fprintf( outfile, "    int   SizeOfInitializedData;\n" );
608     fprintf( outfile, "    int   SizeOfUninitializedData;\n" );
609     fprintf( outfile, "    void *AddressOfEntryPoint;\n" );
610     fprintf( outfile, "    void *BaseOfCode;\n" );
611     fprintf( outfile, "    void *BaseOfData;\n" );
612     fprintf( outfile, "    void *ImageBase;\n" );
613     fprintf( outfile, "    int   SectionAlignment;\n" );
614     fprintf( outfile, "    int   FileAlignment;\n" );
615     fprintf( outfile, "    short MajorOperatingSystemVersion;\n" );
616     fprintf( outfile, "    short MinorOperatingSystemVersion;\n" );
617     fprintf( outfile, "    short MajorImageVersion;\n" );
618     fprintf( outfile, "    short MinorImageVersion;\n" );
619     fprintf( outfile, "    short MajorSubsystemVersion;\n" );
620     fprintf( outfile, "    short MinorSubsystemVersion;\n" );
621     fprintf( outfile, "    int   Win32VersionValue;\n" );
622     fprintf( outfile, "    int   SizeOfImage;\n" );
623     fprintf( outfile, "    int   SizeOfHeaders;\n" );
624     fprintf( outfile, "    int   CheckSum;\n" );
625     fprintf( outfile, "    short Subsystem;\n" );
626     fprintf( outfile, "    short DllCharacteristics;\n" );
627     fprintf( outfile, "    int   SizeOfStackReserve;\n" );
628     fprintf( outfile, "    int   SizeOfStackCommit;\n" );
629     fprintf( outfile, "    int   SizeOfHeapReserve;\n" );
630     fprintf( outfile, "    int   SizeOfHeapCommit;\n" );
631     fprintf( outfile, "    int   LoaderFlags;\n" );
632     fprintf( outfile, "    int   NumberOfRvaAndSizes;\n" );
633     fprintf( outfile, "    struct { const void *VirtualAddress; int Size; } DataDirectory[%d];\n",
634              IMAGE_NUMBEROF_DIRECTORY_ENTRIES );
635     fprintf( outfile, "  } OptionalHeader;\n" );
636     fprintf( outfile, "} nt_header = {\n" );
637     fprintf( outfile, "  0x%04x,\n", IMAGE_NT_SIGNATURE );   /* Signature */
638
639     fprintf( outfile, "  { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 );  /* Machine */
640     fprintf( outfile, "    0, 0, 0, 0,\n" );
641     fprintf( outfile, "    sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
642     fprintf( outfile, "    0x%04x },\n", characteristics );        /* Characteristics */
643
644     fprintf( outfile, "  { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC );  /* Magic */
645     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorLinkerVersion */
646     fprintf( outfile, "    0, 0, 0,\n" );                /* SizeOfCode/Data */
647     fprintf( outfile, "    %s,\n", init_func ? init_func : "0" );  /* AddressOfEntryPoint */
648     fprintf( outfile, "    0, 0,\n" );                   /* BaseOfCode/Data */
649     fprintf( outfile, "    pe_header,\n" );              /* ImageBase */
650     fprintf( outfile, "    %ld,\n", page_size );         /* SectionAlignment */
651     fprintf( outfile, "    %ld,\n", page_size );         /* FileAlignment */
652     fprintf( outfile, "    1, 0,\n" );                   /* Major/MinorOperatingSystemVersion */
653     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorImageVersion */
654     fprintf( outfile, "    4, 0,\n" );                   /* Major/MinorSubsystemVersion */
655     fprintf( outfile, "    0,\n" );                      /* Win32VersionValue */
656     fprintf( outfile, "    %ld,\n", page_size );         /* SizeOfImage */
657     fprintf( outfile, "    %ld,\n", page_size );         /* SizeOfHeaders */
658     fprintf( outfile, "    0,\n" );                      /* CheckSum */
659     fprintf( outfile, "    0x%04x,\n", subsystem );      /* Subsystem */
660     fprintf( outfile, "    0, 0, 0, 0, 0, 0,\n" );
661     fprintf( outfile, "    %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES );  /* NumberOfRvaAndSizes */
662     fprintf( outfile, "    {\n" );
663     fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_EXPORT */
664              nr_exports ? "&exports" : "0", nr_exports ? "sizeof(exports.exp)" : "0" );
665     fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
666              nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
667     fprintf( outfile, "      { %s, %s },\n",   /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
668              nr_resources ? "&resources" : "0", nr_resources ? "sizeof(resources)" : "0" );
669     fprintf( outfile, "    }\n  }\n};\n\n" );
670
671     /* Output the DLL constructor */
672
673     fprintf( outfile, "#ifdef __GNUC__\n" );
674     fprintf( outfile, "static void init(void) __attribute__((unused));\n" );
675     if (nr_debug)
676         fprintf( outfile, "static void fini(void) __attribute__((unused));\n" );
677     fprintf( outfile, "#else /* defined(__GNUC__) */\n" );
678     fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
679     fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
680     fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
681     fprintf( outfile, "    \"\\tcall init\\n\"\n" );
682     fprintf( outfile, "    \"\\t.previous\\n\");\n" );
683     if (nr_debug)
684     {
685         fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
686         fprintf( outfile, "    \"\\tcall fini\\n\"\n" );
687         fprintf( outfile, "    \"\\t.previous\\n\");\n" );
688     }
689     fprintf( outfile, "#ifndef __GNUC__\n" );
690     fprintf( outfile, "}\n" );
691     fprintf( outfile, "#endif /* defined(__GNUC__) */\n\n" );
692     fprintf( outfile, "static void init(void)\n{\n" );
693     fprintf( outfile, "    extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n" );
694     fprintf( outfile, "    extern void *__wine_dbg_register( char * const *, int );\n");
695     fprintf( outfile, "    __wine_dll_register( &nt_header, \"%s\" );\n", DLLFileName );
696     if (nr_debug)
697         fprintf( outfile, "    debug_registration = __wine_dbg_register( debug_channels, %d );\n",
698                  nr_debug );
699     fprintf( outfile, "}\n" );
700     if (nr_debug)
701     {
702         fprintf( outfile, "\nstatic void fini(void)\n{\n" );
703         fprintf( outfile, "    extern void __wine_dbg_unregister( void * );\n");
704         fprintf( outfile, "    __wine_dbg_unregister( debug_registration );\n" );
705         fprintf( outfile, "}\n" );
706     }
707 }