diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 45e21f8c462..1a9be3c7ae7 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -727,8 +727,7 @@ int main(int argc, char **argv) if (fake_module) { - if (spec->type == SPEC_WIN16) output_fake_module16( spec ); - else output_fake_module( spec ); + output_fake_module( spec ); break; } if (!is_pe()) diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index e82f5f81d9a..8d4f96ea323 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -829,7 +829,8 @@ void output_fake_module16( DLLSPEC *spec ) const unsigned int lfanew = (0x40 + sizeof(fakedll_signature) + 15) & ~15; const unsigned int segtab = lfanew + 0x40; - unsigned int i, rsrctab, restab, namelen, modtab, imptab, enttab, cbenttab, codeseg, dataseg, rsrcdata; + unsigned int i, rsrctab, restab, namelen, modtab, imptab, enttab, cbenttab, codeseg, dataseg, rsrcdata, rsrc_size = 0; + void *rsrc_ptr = NULL; init_output_buffer(); @@ -843,6 +844,10 @@ void output_fake_module16( DLLSPEC *spec ) restab += output_buffer_pos; free( output_buffer ); init_output_buffer(); + output_bin_res16_data( spec ); + rsrc_ptr = output_buffer; + rsrc_size = output_buffer_pos; + init_output_buffer(); } namelen = strlen( spec->dll_name ); @@ -874,7 +879,7 @@ void output_fake_module16( DLLSPEC *spec ) put_dword( 0 ); put_word( 0 ); /* e_oemid */ put_word( 0 ); /* e_oeminfo */ - put_dword( 0 ); /* e_res2 */ + put_dword( rsrcdata + rsrc_size ); /* e_res2 */ put_dword( 0 ); put_dword( 0 ); put_dword( 0 ); @@ -953,7 +958,5 @@ void output_fake_module16( DLLSPEC *spec ) put_data( data_segment, sizeof(data_segment) ); /* resource data */ - output_bin_res16_data( spec ); - - flush_output_buffer(); + put_data( rsrc_ptr, rsrc_size ); } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 7a28777fb77..513778ad10c 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -790,13 +790,21 @@ struct dir_data unsigned int size; }; +struct exp_data +{ + unsigned int rva; + const char *name; +}; + static struct { unsigned int section_align; unsigned int file_align; unsigned int sec_count; + unsigned int exp_count; struct dir_data dir[16]; struct sec_data sec[8]; + struct exp_data exp[8]; } pe; static void set_dir( unsigned int idx, unsigned int rva, unsigned int size ) @@ -805,6 +813,13 @@ static void set_dir( unsigned int idx, unsigned int rva, unsigned int size ) pe.dir[idx].size = size; } +static void add_export( unsigned int rva, const char *name ) +{ + pe.exp[pe.exp_count].rva = rva; + pe.exp[pe.exp_count].name = name; + pe.exp_count++; +} + static unsigned int current_rva(void) { if (!pe.sec_count) return pe.section_align; @@ -864,16 +879,68 @@ void output_fake_module( DLLSPEC *spec ) else put_data( exe_code_section, sizeof(exe_code_section) ); flush_output_to_section( ".text", -1, 0x60000020 /* CNT_CODE|MEM_EXECUTE|MEM_READ */ ); + if (spec->type == SPEC_WIN16) + { + add_export( current_rva(), "__wine_spec_dos_header" ); + + /* .rodata section */ + output_fake_module16( spec ); + if (spec->main_module) + { + add_export( current_rva() + output_buffer_pos, "__wine_spec_main_module" ); + put_data( spec->main_module, strlen(spec->main_module) + 1 ); + } + flush_output_to_section( ".rodata", -1, 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); + } + + if (pe.exp_count) + { + /* .edata section */ + unsigned int exp_rva = current_rva() + 40; /* sizeof(IMAGE_EXPORT_DIRECTORY) */ + unsigned int pos, str_rva = exp_rva + 10 * pe.exp_count; + + put_dword( 0 ); /* Characteristics */ + put_dword( hash_filename(spec->file_name) ); /* TimeDateStamp */ + put_word( 0 ); /* MajorVersion */ + put_word( 0 ); /* MinorVersion */ + put_dword( str_rva ); /* Name */ + put_dword( 1 ); /* Base */ + put_dword( pe.exp_count ); /* NumberOfFunctions */ + put_dword( pe.exp_count ); /* NumberOfNames */ + put_dword( exp_rva ); /* AddressOfFunctions */ + put_dword( exp_rva + 4 * pe.exp_count ); /* AddressOfNames */ + put_dword( exp_rva + 8 * pe.exp_count ); /* AddressOfNameOrdinals */ + + /* functions */ + for (i = 0; i < pe.exp_count; i++) put_dword( pe.exp[i].rva ); + /* names */ + for (i = 0, pos = str_rva + strlen(spec->file_name) + 1; i < pe.exp_count; i++) + { + put_dword( pos ); + pos += strlen( pe.exp[i].name ) + 1; + } + /* ordinals */ + for (i = 0; i < pe.exp_count; i++) put_word( i ); + /* strings */ + put_data( spec->file_name, strlen(spec->file_name) + 1 ); + for (i = 0; i < pe.exp_count; i++) put_data( pe.exp[i].name, strlen(pe.exp[i].name) + 1 ); + flush_output_to_section( ".edata", 0 /* IMAGE_DIRECTORY_ENTRY_EXPORT */, + 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); + } + /* .reloc section */ put_dword( 0 ); /* VirtualAddress */ put_dword( 0 ); /* Size */ flush_output_to_section( ".reloc", 5 /* IMAGE_DIRECTORY_ENTRY_BASERELOC */, 0x42000040 /* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */ ); - /* .rsrc section */ - output_bin_resources( spec, current_rva() ); - flush_output_to_section( ".rsrc", 2 /* IMAGE_DIRECTORY_ENTRY_RESOURCE */, - 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); + if (spec->type == SPEC_WIN32) + { + /* .rsrc section */ + output_bin_resources( spec, current_rva() ); + flush_output_to_section( ".rsrc", 2 /* IMAGE_DIRECTORY_ENTRY_RESOURCE */, + 0x40000040 /* CNT_INITIALIZED_DATA|MEM_READ */ ); + } put_word( 0x5a4d ); /* e_magic */ put_word( 0x40 ); /* e_cblp */