winebuild: Wrap 16-bit fake dlls in a PE module.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51564
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-10-21 12:50:13 +02:00
parent 2f0401c783
commit 5a8f7d1f74
3 changed files with 80 additions and 11 deletions

View File

@ -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())

View File

@ -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 );
}

View File

@ -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 */