winebuild: Add support for creating 16-bit fake dlls.

This commit is contained in:
Alexandre Julliard 2009-08-15 11:21:38 +02:00
parent 8024718c78
commit 5d3e134b17
3 changed files with 221 additions and 16 deletions

View File

@ -251,7 +251,9 @@ extern void output_bin_resources( DLLSPEC *spec, unsigned int start_rva );
extern void output_fake_module( DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec );
extern void output_res16_data( DLLSPEC *spec );
extern void output_bin_res16_data( DLLSPEC *spec );
extern void output_res16_directory( DLLSPEC *spec );
extern void output_bin_res16_directory( DLLSPEC *spec, unsigned int data_offset );
extern void output_spec16_file( DLLSPEC *spec );
extern void output_fake_module16( DLLSPEC *spec16 );
extern void output_res_o_file( DLLSPEC *spec );

View File

@ -215,6 +215,13 @@ static void output_string( const char *str )
output( " /* %s */\n", str );
}
/* output a string preceded by its length in binary format*/
static void output_bin_string( const char *str )
{
put_byte( strlen(str) );
while (*str) put_byte( *str++ );
}
/* output the resource data */
void output_res16_data( DLLSPEC *spec )
{
@ -268,3 +275,60 @@ void output_res16_directory( DLLSPEC *spec )
free_resource_tree( tree );
}
/* output the resource data in binary format */
void output_bin_res16_data( DLLSPEC *spec )
{
const struct resource *res;
unsigned int i;
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
put_data( res->data, res->data_size );
}
/* output the resource definitions in binary format */
void output_bin_res16_directory( DLLSPEC *spec, unsigned int data_offset )
{
unsigned int i, j;
struct res_tree *tree;
const struct res_type *type;
const struct resource *res;
tree = build_resource_tree( spec );
put_word( 0 ); /* alignment */
/* type and name structures */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
put_word( type->name_offset );
put_word( type->nb_names );
put_word( 0 );
put_word( 0 );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
put_word( data_offset );
put_word( res->data_size );
put_word( res->memopt );
put_word( res->name_offset );
put_word( 0 );
put_word( 0 );
data_offset += res->data_size;
}
}
put_word( 0 ); /* terminator */
/* name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str) output_bin_string( type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
if (res->name.str) output_bin_string( res->name.str );
}
put_byte( 0 ); /* names terminator */
free_resource_tree( tree );
}

View File

@ -63,6 +63,22 @@ static inline int is_function( const ORDDEF *odp )
odp->type == TYPE_STUB);
}
static void init_dll_name( DLLSPEC *spec )
{
if (!spec->file_name)
{
char *p;
spec->file_name = xstrdup( output_file_name );
if ((p = strrchr( spec->file_name, '.' ))) *p = 0;
}
if (!spec->dll_name) /* set default name from file name */
{
char *p;
spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
}
}
/*******************************************************************
* output_entries
*
@ -546,19 +562,6 @@ static void output_module16( DLLSPEC *spec )
ORDDEF *entry_point = NULL;
int i, j, nb_funcs;
if (!spec->file_name)
{
char *p;
spec->file_name = xstrdup( output_file_name );
if ((p = strrchr( spec->file_name, '.' ))) *p = 0;
}
if (!spec->dll_name) /* set default name from file name */
{
char *p;
spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
}
/* store the main entry point as ordinal 0 */
if (!spec->ordinals)
@ -657,7 +660,7 @@ static void output_module16( DLLSPEC *spec )
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
output( "\t.byte 0x04\n" ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */
output( "\t.byte 0x02\n" ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */
output( "\t.byte 0x08\n" ); /* ne_flagsothers = NE_AFLAGS_FASTLOAD */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
@ -847,6 +850,7 @@ static void output_module16( DLLSPEC *spec )
*/
void BuildSpec16File( DLLSPEC *spec )
{
init_dll_name( spec );
output_standard_file_header();
output_module16( spec );
output_init_code( spec );
@ -870,6 +874,7 @@ void output_spec16_file( DLLSPEC *spec16 )
{
DLLSPEC *spec32 = alloc_dll_spec();
init_dll_name( spec16 );
spec32->file_name = xstrdup( spec16->file_name );
if (spec16->characteristics & IMAGE_FILE_DLL)
@ -902,7 +907,141 @@ void output_spec16_file( DLLSPEC *spec16 )
*
* Create a fake 16-bit binary module.
*/
void output_fake_module16( DLLSPEC *spec16 )
void output_fake_module16( DLLSPEC *spec )
{
warning( "not implemented yet\n" );
static const unsigned char code_segment[] = { 0x90, 0xc3 };
static const unsigned char data_segment[16] = { 0 };
static const char fakedll_signature[] = "Wine placeholder DLL";
const unsigned int cseg = 2;
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;
init_dll_name( spec );
init_output_buffer();
rsrctab = lfanew;
restab = segtab + 8 * cseg;
if (spec->nb_resources)
{
output_bin_res16_directory( spec, 0 );
align_output( 2 );
rsrctab = restab;
restab += output_buffer_pos;
free( output_buffer );
init_output_buffer();
}
namelen = strlen( spec->dll_name );
modtab = restab + ((namelen + 3) & ~1);
imptab = modtab;
enttab = modtab + 2;
cbenttab = 1;
codeseg = (enttab + cbenttab + 1) & ~1;
dataseg = codeseg + sizeof(code_segment);
rsrcdata = dataseg + sizeof(data_segment);
init_output_buffer();
put_word( 0x5a4d ); /* e_magic */
put_word( 0x40 ); /* e_cblp */
put_word( 0x01 ); /* e_cp */
put_word( 0 ); /* e_crlc */
put_word( lfanew / 16 ); /* e_cparhdr */
put_word( 0x0000 ); /* e_minalloc */
put_word( 0xffff ); /* e_maxalloc */
put_word( 0x0000 ); /* e_ss */
put_word( 0x00b8 ); /* e_sp */
put_word( 0 ); /* e_csum */
put_word( 0 ); /* e_ip */
put_word( 0 ); /* e_cs */
put_word( lfanew ); /* e_lfarlc */
put_word( 0 ); /* e_ovno */
put_dword( 0 ); /* e_res */
put_dword( 0 );
put_word( 0 ); /* e_oemid */
put_word( 0 ); /* e_oeminfo */
put_dword( 0 ); /* e_res2 */
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( 0 );
put_dword( lfanew );
put_data( fakedll_signature, sizeof(fakedll_signature) );
align_output( 16 );
put_word( 0x454e ); /* ne_magic */
put_byte( 0 ); /* ne_ver */
put_byte( 0 ); /* ne_rev */
put_word( enttab - lfanew ); /* ne_enttab */
put_word( cbenttab ); /* ne_cbenttab */
put_dword( 0 ); /* ne_crc */
put_word( NE_FFLAGS_SINGLEDATA | /* ne_flags */
((spec->characteristics & IMAGE_FILE_DLL) ? NE_FFLAGS_LIBMODULE : 0) );
put_word( 2 ); /* ne_autodata */
put_word( spec->heap_size ); /* ne_heap */
put_word( 0 ); /* ne_stack */
put_word( 0 ); put_word( 0 ); /* ne_csip */
put_word( 0 ); put_word( 2 ); /* ne_sssp */
put_word( cseg ); /* ne_cseg */
put_word( 0 ); /* ne_cmod */
put_word( 0 ); /* ne_cbnrestab */
put_word( segtab - lfanew ); /* ne_segtab */
put_word( rsrctab - lfanew ); /* ne_rsrctab */
put_word( restab - lfanew ); /* ne_restab */
put_word( modtab - lfanew ); /* ne_modtab */
put_word( imptab - lfanew ); /* ne_imptab */
put_dword( 0 ); /* ne_nrestab */
put_word( 0 ); /* ne_cmovent */
put_word( 0 ); /* ne_align */
put_word( 0 ); /* ne_cres */
put_byte( 2 /*NE_OSFLAGS_WINDOWS*/ ); /* ne_exetyp */
put_byte( 8 /*NE_AFLAGS_FASTLOAD*/ ); /* ne_flagsothers */
put_word( 0 ); /* ne_pretthunks */
put_word( 0 ); /* ne_psegrefbytes */
put_word( 0 ); /* ne_swaparea */
put_word( 0 ); /* ne_expver */
/* segment table */
put_word( codeseg );
put_word( sizeof(code_segment) );
put_word( 0x2000 /* NE_SEGFLAGS_32BIT */ );
put_word( sizeof(code_segment) );
put_word( dataseg );
put_word( sizeof(data_segment) );
put_word( 0x0001 /* NE_SEGFLAGS_DATA */ );
put_word( sizeof(data_segment) );
/* resource directory */
if (spec->nb_resources)
{
output_bin_res16_directory( spec, rsrcdata );
align_output( 2 );
}
/* resident names table */
put_byte( namelen );
for (i = 0; i < namelen; i++) put_byte( toupper(spec->dll_name[i]) );
put_byte( 0 );
align_output( 2 );
/* imported names table */
put_word( 0 );
/* entry table */
put_byte( 0 );
align_output( 2 );
/* code segment */
put_data( code_segment, sizeof(code_segment) );
/* data segment */
put_data( data_segment, sizeof(data_segment) );
/* resource data */
output_bin_res16_data( spec );
flush_output_buffer();
}