From 70d04399057846a7165807201a01a0427b84edec Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 23 May 2005 12:07:15 +0000 Subject: [PATCH] Moved the generated code segment for 16-bit builtins inside the module structure. Get rid of the BUILTIN16_DESCRIPTOR structure and directly register the MZ header instead. --- dlls/kernel/kernel16_private.h | 43 +++ dlls/kernel/ne_module.c | 124 +++---- include/wine/winbase16.h | 41 --- tools/winebuild/spec16.c | 588 +++++++++++++++------------------ 4 files changed, 366 insertions(+), 430 deletions(-) diff --git a/dlls/kernel/kernel16_private.h b/dlls/kernel/kernel16_private.h index 9b2ba6428d4..7f00b7ee1b0 100644 --- a/dlls/kernel/kernel16_private.h +++ b/dlls/kernel/kernel16_private.h @@ -107,6 +107,49 @@ typedef struct WORD stackbottom; /* Bottom of the stack */ } INSTANCEDATA; +/* relay entry points */ + +#ifdef __i386__ + +typedef struct +{ + WORD pushw_bp; /* pushw %bp */ + BYTE pushl; /* pushl $target */ + void (*target)(); + WORD call; /* call CALLFROM16 */ + short callfrom16; +} ENTRYPOINT16; + +typedef struct +{ + BYTE pushl; /* pushl $relay */ + void *relay; + BYTE lcall; /* lcall __FLATCS__:glue */ + void *glue; + WORD flatcs; + WORD lret; /* lret $nArgs */ + WORD nArgs; + DWORD arg_types[2]; /* type of each argument */ +} CALLFROM16; + +#else /* __i386__ */ + +typedef struct +{ + void (*target)(); + WORD call; /* call CALLFROM16 */ + short callfrom16; +} ENTRYPOINT16; + +typedef struct +{ + WORD lret; /* lret $nArgs */ + WORD nArgs; + DWORD arg_types[2]; /* type of each argument */ +} CALLFROM16; + +#endif /* __i386__ */ + /* THHOOK Kernel Data Structure */ typedef struct _THHOOK { diff --git a/dlls/kernel/ne_module.c b/dlls/kernel/ne_module.c index 4dc2a652c6f..0ea38ab3da9 100644 --- a/dlls/kernel/ne_module.c +++ b/dlls/kernel/ne_module.c @@ -68,16 +68,10 @@ struct ne_segment_table_entry_s #define hFirstModule (pThhook->hExeHead) -typedef struct -{ - const void *module; /* module header */ - void *code_start; /* 32-bit address of DLL code */ -} BUILTIN16_DESCRIPTOR; - struct builtin_dll { - const BUILTIN16_DESCRIPTOR *descr; /* module descriptor */ - const char *file_name; /* module file name */ + const IMAGE_DOS_HEADER *header; /* module headers */ + const char *file_name; /* module file name */ }; /* Table of all built-in DLLs */ @@ -104,15 +98,24 @@ static WINE_EXCEPTION_FILTER(page_fault) /* patch all the flat cs references of the code segment if necessary */ -inline static void patch_code_segment( void *code_segment ) +inline static void patch_code_segment( NE_MODULE *pModule ) { #ifdef __i386__ - CALLFROM16 *call = code_segment; - if (call->flatcs == wine_get_cs()) return; /* nothing to patch */ - while (call->pushl == 0x68) + int i; + SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ); + + for (i = 0; i < pModule->ne_cseg; i++, pSeg++) { - call->flatcs = wine_get_cs(); - call++; + if (!(pSeg->flags & NE_SEGFLAGS_DATA)) /* found the code segment */ + { + CALLFROM16 *call = GlobalLock16( pSeg->hSeg ); + if (call->flatcs == wine_get_cs()) return; /* nothing to patch */ + while (call->pushl == 0x68) + { + call->flatcs = wine_get_cs(); + call++; + } + } } #endif } @@ -151,7 +154,7 @@ static int NE_strncasecmp( const char *str1, const char *str2, int len ) * * Find a descriptor in the list */ -static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname, const char **file_name ) +static const IMAGE_DOS_HEADER *find_dll_descr( const char *dllname, const char **file_name ) { int i; const IMAGE_DOS_HEADER *mz_header; @@ -160,10 +163,9 @@ static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname, const ch for (i = 0; i < MAX_DLLS; i++) { - const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i].descr; - if (descr) + mz_header = builtin_dlls[i].header; + if (mz_header) { - mz_header = descr->module; ne_header = (const IMAGE_OS2_HEADER *)((const char *)mz_header + mz_header->e_lfanew); name_table = (BYTE *)ne_header + ne_header->ne_restab; @@ -174,7 +176,7 @@ static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname, const ch !strcmp( dllname + *name_table, ".dll" ))) { *file_name = builtin_dlls[i].file_name; - return builtin_dlls[i].descr; + return builtin_dlls[i].header; } } } @@ -187,14 +189,14 @@ static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname, const ch * * Register a built-in DLL descriptor. */ -void __wine_dll_register_16( const BUILTIN16_DESCRIPTOR *descr, const char *file_name ) +void __wine_dll_register_16( const IMAGE_DOS_HEADER *header, const char *file_name ) { int i; for (i = 0; i < MAX_DLLS; i++) { - if (builtin_dlls[i].descr) continue; - builtin_dlls[i].descr = descr; + if (builtin_dlls[i].header) continue; + builtin_dlls[i].header = header; builtin_dlls[i].file_name = file_name; break; } @@ -207,14 +209,14 @@ void __wine_dll_register_16( const BUILTIN16_DESCRIPTOR *descr, const char *file * * Unregister a built-in DLL descriptor. */ -void __wine_dll_unregister_16( const BUILTIN16_DESCRIPTOR *descr ) +void __wine_dll_unregister_16( const IMAGE_DOS_HEADER *header ) { int i; for (i = 0; i < MAX_DLLS; i++) { - if (builtin_dlls[i].descr != descr) continue; - builtin_dlls[i].descr = NULL; + if (builtin_dlls[i].header != header) continue; + builtin_dlls[i].header = NULL; break; } } @@ -893,9 +895,8 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule ) * * Load first instance of NE module from file. * - * pModule must point to a module structure prepared by build_module_data. + * pModule must point to a module structure prepared by build_module. * This routine must never be called twice on a module. - * */ static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule ) { @@ -992,53 +993,42 @@ static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only ) * * Load a built-in Win16 module. Helper function for NE_LoadBuiltinModule. */ -static HMODULE16 NE_DoLoadBuiltinModule( const BUILTIN16_DESCRIPTOR *descr, const char *file_name ) +static HMODULE16 NE_DoLoadBuiltinModule( const IMAGE_DOS_HEADER *mz_header, const char *file_name ) { NE_MODULE *pModule; HMODULE16 hModule; - SEGTABLEENTRY *pSegTable; - const IMAGE_DOS_HEADER *mz_header; + HINSTANCE16 hInstance; + OSVERSIONINFOW versionInfo; const IMAGE_OS2_HEADER *ne_header; - SIZE_T mapping_size; + SIZE_T mapping_size = ~0UL; /* assume builtins don't contain invalid offsets... */ - mz_header = descr->module; ne_header = (const IMAGE_OS2_HEADER *)((const BYTE *)mz_header + mz_header->e_lfanew); - mapping_size = ne_header->ne_psegrefbytes << ne_header->ne_align; - hModule = build_module( descr->module, mapping_size, file_name ); + hModule = build_module( mz_header, mapping_size, file_name ); if (hModule < 32) return hModule; pModule = GlobalLock16( hModule ); pModule->ne_flags |= NE_FFLAGS_BUILTIN; - pModule->count = 1; - /* Allocate the code segment */ + /* fake the expected version the module should have according to the current Windows version */ + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (GetVersionExW( &versionInfo )) + pModule->ne_expver = MAKEWORD( versionInfo.dwMinorVersion, versionInfo.dwMajorVersion ); - pSegTable = NE_SEG_TABLE( pModule ); - pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start, - pSegTable->minsize, hModule, - WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT ); - if (!pSegTable->hSeg) return ERROR_NOT_ENOUGH_MEMORY; - patch_code_segment( descr->code_start ); - pSegTable->flags |= NE_SEGFLAGS_ALLOCATED | NE_SEGFLAGS_LOADED; - pSegTable++; + hInstance = NE_DoLoadModule( pModule ); + if (hInstance < 32) NE_FreeModule( hModule, 0 ); - /* Allocate the data segment */ - - if (!NE_CreateSegment( pModule, 2 )) return ERROR_NOT_ENOUGH_MEMORY; - pModule->dgroup_entry = (char *)pSegTable - (char *)pModule; - memcpy( GlobalLock16( pSegTable->hSeg ), - (const char *)descr->module + (pSegTable->filepos << pModule->ne_align), - pSegTable->minsize); - pSegTable->flags |= NE_SEGFLAGS_LOADED; + NE_InitResourceHandler( hModule ); if (pModule->ne_heap) { - unsigned int size = pSegTable->minsize + pModule->ne_heap; + SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + pModule->ne_autodata - 1; + unsigned int size = pSeg->minsize + pModule->ne_heap; if (size > 0xfffe) size = 0xfffe; - LocalInit16( GlobalHandleToSel16(pSegTable->hSeg), pSegTable->minsize, size ); + LocalInit16( GlobalHandleToSel16(pSeg->hSeg), pSeg->minsize, size ); } - NE_InitResourceHandler( hModule ); - return hModule; + patch_code_segment( pModule ); + + return hInstance; } @@ -1053,8 +1043,9 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ { HINSTANCE16 hinst = 2; HMODULE16 hModule; + HMODULE mod32 = 0; NE_MODULE *pModule; - const BUILTIN16_DESCRIPTOR *descr = NULL; + const IMAGE_DOS_HEADER *descr = NULL; const char *file_name = NULL; char dllname[20], owner[20], *p; const char *basename; @@ -1076,7 +1067,7 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ if (wine_dll_get_owner( dllname, owner, sizeof(owner), &owner_exists ) != -1) { - HMODULE mod32 = LoadLibraryA( owner ); + mod32 = LoadLibraryA( owner ); if (mod32) { if (!(descr = find_dll_descr( dllname, &file_name ))) @@ -1091,6 +1082,7 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_ TRACE( "module %s already loaded by owner\n", libname ); pModule = NE_GetPtr( hModule ); if (pModule) pModule->count++; + FreeLibrary( mod32 ); return hModule; } } @@ -1626,22 +1618,6 @@ WORD WINAPI GetExpWinVer16( HMODULE16 hModule ) { NE_MODULE *pModule = NE_GetPtr( hModule ); if ( !pModule ) return 0; - - /* - * For built-in modules, fake the expected version the module should - * have according to the Windows version emulated by Wine - */ - if ( !pModule->ne_expver ) - { - OSVERSIONINFOA versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); - - if ( GetVersionExA( &versionInfo ) ) - pModule->ne_expver = - (versionInfo.dwMajorVersion & 0xff) << 8 - | (versionInfo.dwMinorVersion & 0xff); - } - return pModule->ne_expver; } diff --git a/include/wine/winbase16.h b/include/wine/winbase16.h index 9c48d7ddd1e..6ed5b3682e4 100644 --- a/include/wine/winbase16.h +++ b/include/wine/winbase16.h @@ -204,47 +204,6 @@ typedef struct _STACK16FRAME WORD cs; /* 2e */ } STACK16FRAME; -#ifdef __i386__ - -typedef struct -{ - WORD pushw_bp; /* pushw %bp */ - BYTE pushl; /* pushl $target */ - void (*target)(); - WORD call; /* call CALLFROM16 */ - short callfrom16; -} ENTRYPOINT16; - -typedef struct -{ - BYTE pushl; /* pushl $relay */ - void *relay; - BYTE lcall; /* lcall __FLATCS__:glue */ - void *glue; - WORD flatcs; - WORD lret; /* lret $nArgs */ - WORD nArgs; - DWORD arg_types[2]; /* type of each argument */ -} CALLFROM16; - -#else /* __i386__ */ - -typedef struct -{ - void (*target)(); - WORD call; /* call CALLFROM16 */ - short callfrom16; -} ENTRYPOINT16; - -typedef struct -{ - WORD lret; /* lret $nArgs */ - WORD nArgs; - DWORD arg_types[2]; /* type of each argument */ -} CALLFROM16; - -#endif - /* argument type flags for relay debugging */ enum arg_types { diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 6266327452f..2b0a07d4826 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -74,34 +74,6 @@ static void output_file_header( FILE *outfile ) } -/******************************************************************* - * StoreVariableCode - * - * Store a list of ints into a byte array. - */ -static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp ) -{ - int i; - - switch(size) - { - case 1: - for (i = 0; i < odp->u.var.n_values; i++) - buffer[i] = odp->u.var.values[i]; - break; - case 2: - for (i = 0; i < odp->u.var.n_values; i++) - ((unsigned short *)buffer)[i] = odp->u.var.values[i]; - break; - case 4: - for (i = 0; i < odp->u.var.n_values; i++) - ((unsigned int *)buffer)[i] = odp->u.var.values[i]; - break; - } - return odp->u.var.n_values * size; -} - - /******************************************************************* * output_entry_table */ @@ -195,244 +167,6 @@ static void output_bytes( FILE *outfile, const void *buffer, unsigned int size ) } -/******************************************************************* - * output_module_data - * - * Output the 16-bit NE module structure. - */ -static void output_module_data( FILE *outfile, int max_code_offset, const void *data_segment, - unsigned int data_size, DLLSPEC *spec ) -{ - unsigned char *resdir_buffer, *resdata_buffer, *et_buffer; - unsigned char string[256]; - int i; - unsigned int ne_offset, segtable_offset, impnames_offset, data_offset; - unsigned int resnames_offset, resnames_size; - unsigned int resdir_size, resdir_offset; - unsigned int resdata_size, resdata_offset, resdata_align; - unsigned int et_size, et_offset; - - /* DOS header */ - - fprintf( outfile, "static const struct module_data\n{\n" ); - fprintf( outfile, " struct\n {\n" ); - fprintf( outfile, " unsigned short e_magic;\n" ); - fprintf( outfile, " unsigned short e_cblp;\n" ); - fprintf( outfile, " unsigned short e_cp;\n" ); - fprintf( outfile, " unsigned short e_crlc;\n" ); - fprintf( outfile, " unsigned short e_cparhdr;\n" ); - fprintf( outfile, " unsigned short e_minalloc;\n" ); - fprintf( outfile, " unsigned short e_maxalloc;\n" ); - fprintf( outfile, " unsigned short e_ss;\n" ); - fprintf( outfile, " unsigned short e_sp;\n" ); - fprintf( outfile, " unsigned short e_csum;\n" ); - fprintf( outfile, " unsigned short e_ip;\n" ); - fprintf( outfile, " unsigned short e_cs;\n" ); - fprintf( outfile, " unsigned short e_lfarlc;\n" ); - fprintf( outfile, " unsigned short e_ovno;\n" ); - fprintf( outfile, " unsigned short e_res[4];\n" ); - fprintf( outfile, " unsigned short e_oemid;\n" ); - fprintf( outfile, " unsigned short e_oeminfo;\n" ); - fprintf( outfile, " unsigned short e_res2[10];\n" ); - fprintf( outfile, " unsigned int e_lfanew;\n" ); - fprintf( outfile, " } dos_header;\n" ); - - /* NE header */ - - ne_offset = 64; - fprintf( outfile, " struct\n {\n" ); - fprintf( outfile, " unsigned short ne_magic;\n" ); - fprintf( outfile, " unsigned char ne_ver;\n" ); - fprintf( outfile, " unsigned char ne_rev;\n" ); - fprintf( outfile, " unsigned short ne_enttab;\n" ); - fprintf( outfile, " unsigned short ne_cbenttab;\n" ); - fprintf( outfile, " int ne_crc;\n" ); - fprintf( outfile, " unsigned short ne_flags;\n" ); - fprintf( outfile, " unsigned short ne_autodata;\n" ); - fprintf( outfile, " unsigned short ne_heap;\n" ); - fprintf( outfile, " unsigned short ne_stack;\n" ); - fprintf( outfile, " unsigned int ne_csip;\n" ); - fprintf( outfile, " unsigned int ne_sssp;\n" ); - fprintf( outfile, " unsigned short ne_cseg;\n" ); - fprintf( outfile, " unsigned short ne_cmod;\n" ); - fprintf( outfile, " unsigned short ne_cbnrestab;\n" ); - fprintf( outfile, " unsigned short ne_segtab;\n" ); - fprintf( outfile, " unsigned short ne_rsrctab;\n" ); - fprintf( outfile, " unsigned short ne_restab;\n" ); - fprintf( outfile, " unsigned short ne_modtab;\n" ); - fprintf( outfile, " unsigned short ne_imptab;\n" ); - fprintf( outfile, " unsigned int ne_nrestab;\n" ); - fprintf( outfile, " unsigned short ne_cmovent;\n" ); - fprintf( outfile, " unsigned short ne_align;\n" ); - fprintf( outfile, " unsigned short ne_cres;\n" ); - fprintf( outfile, " unsigned char ne_exetyp;\n" ); - fprintf( outfile, " unsigned char ne_flagsothers;\n" ); - fprintf( outfile, " unsigned short ne_pretthunks;\n" ); - fprintf( outfile, " unsigned short ne_psegrefbytes;\n" ); - fprintf( outfile, " unsigned short ne_swaparea;\n" ); - fprintf( outfile, " unsigned short ne_expver;\n" ); - fprintf( outfile, " } os2_header;\n" ); - - /* segment table */ - - segtable_offset = 64; - fprintf( outfile, " struct\n {\n" ); - fprintf( outfile, " unsigned short filepos;\n" ); - fprintf( outfile, " unsigned short size;\n" ); - fprintf( outfile, " unsigned short flags;\n" ); - fprintf( outfile, " unsigned short minsize;\n" ); - fprintf( outfile, " } segtable[2];\n" ); - - /* resource directory */ - - resdir_offset = segtable_offset + 2 * 8; - resdir_size = get_res16_directory_size( spec ); - fprintf( outfile, " unsigned char resdir[%d];\n", resdir_size ); - - /* resident names table */ - - resnames_offset = resdir_offset + resdir_size; - fprintf( outfile, " struct\n {\n" ); - fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_0;\n", - strlen( spec->dll_name ) ); - resnames_size = 3 + strlen( spec->dll_name ); - for (i = 1; i <= spec->limit; i++) - { - ORDDEF *odp = spec->ordinals[i]; - if (!odp || !odp->name[0]) continue; - fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_%d;\n", - strlen(odp->name), i ); - resnames_size += 3 + strlen( odp->name ); - } - fprintf( outfile, " unsigned char name_last[%d];\n", 2 - (resnames_size & 1) ); - resnames_size = (resnames_size + 2) & ~1; - fprintf( outfile, " } resnames;\n" ); - - /* imported names table */ - - impnames_offset = resnames_offset + resnames_size; - fprintf( outfile, " unsigned char impnames[2];\n" ); - - /* entry table */ - - et_offset = impnames_offset + 2; - et_size = output_entry_table( &et_buffer, spec ); - fprintf( outfile, " unsigned char entry_table[%d];\n", et_size ); - - /* data segment */ - - data_offset = et_offset + et_size; - fprintf( outfile, " unsigned char data_segment[%d];\n", data_size ); - if (data_offset + data_size >= 0x10000) - fatal_error( "Not supported yet: 16-bit module data larger than 64K\n" ); - - /* resource data */ - - resdata_offset = ne_offset + data_offset + data_size; - for (resdata_align = 0; resdata_align < 16; resdata_align++) - { - unsigned int size = get_res16_data_size( spec, resdata_offset, resdata_align ); - if ((resdata_offset + size) >> resdata_align <= 0xffff) break; - } - output_res16_directory( &resdir_buffer, spec, resdata_offset, resdata_align ); - resdata_size = output_res16_data( &resdata_buffer, spec, resdata_offset, resdata_align ); - if (resdata_size) fprintf( outfile, " unsigned char resources[%d];\n", resdata_size ); - - /* DOS header */ - - fprintf( outfile, "} module =\n{\n {\n" ); - fprintf( outfile, " 0x%04x,\n", IMAGE_DOS_SIGNATURE ); /* e_magic */ - fprintf( outfile, " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n" ); - fprintf( outfile, " { 0, 0, 0, 0, }, 0, 0,\n" ); - fprintf( outfile, " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n" ); - fprintf( outfile, " sizeof(module.dos_header)\n" ); /* e_lfanew */ - - /* NE header */ - - fprintf( outfile, " },\n {\n" ); - fprintf( outfile, " 0x%04x,\n", IMAGE_OS2_SIGNATURE ); /* ne_magic */ - fprintf( outfile, " 0, 0,\n" ); - fprintf( outfile, " %d,\n", et_offset ); /* ne_enttab */ - fprintf( outfile, " sizeof(module.entry_table),\n" ); /* ne_cbenttab */ - fprintf( outfile, " 0,\n" ); /* ne_crc */ - fprintf( outfile, " 0x%04x,\n", /* ne_flags */ - NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE ); - fprintf( outfile, " 2,\n" ); /* ne_autodata */ - fprintf( outfile, " %d,\n", spec->heap_size ); /* ne_heap */ - fprintf( outfile, " 0, 0, 0,\n" ); - fprintf( outfile, " 2,\n" ); /* ne_cseg */ - fprintf( outfile, " 0,\n" ); /* ne_cmod */ - fprintf( outfile, " 0,\n" ); /* ne_cbnrestab */ - fprintf( outfile, " %d,\n", segtable_offset ); /* ne_segtab */ - fprintf( outfile, " %d,\n", resdir_offset ); /* ne_rsrctab */ - fprintf( outfile, " %d,\n", resnames_offset ); /* ne_restab */ - fprintf( outfile, " %d,\n", impnames_offset ); /* ne_modtab */ - fprintf( outfile, " %d,\n", impnames_offset ); /* ne_imptab */ - fprintf( outfile, " 0,\n" ); /* ne_nrestab */ - fprintf( outfile, " 0,\n" ); /* ne_cmovent */ - fprintf( outfile, " 0,\n" ); /* ne_align */ - fprintf( outfile, " 0,\n" ); /* ne_cres */ - fprintf( outfile, " 0x%04x,\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */ - fprintf( outfile, " 0x%04x,\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */ - fprintf( outfile, " 0,\n" ); /* ne_pretthunks */ - fprintf( outfile, " sizeof(module),\n" ); /* ne_psegrefbytes */ - fprintf( outfile, " 0,\n" ); /* ne_swaparea */ - fprintf( outfile, " 0\n" ); /* ne_expver */ - fprintf( outfile, " },\n" ); - - /* segment table */ - - fprintf( outfile, " {\n" ); - fprintf( outfile, " { 0, %d, 0x%04x, %d },\n", - max_code_offset, NE_SEGFLAGS_32BIT, max_code_offset ); - fprintf( outfile, " { %d, %d, 0x%04x, %d },\n", - data_offset, data_size, NE_SEGFLAGS_DATA, data_size ); - fprintf( outfile, " },\n" ); - - /* resource directory */ - - output_bytes( outfile, resdir_buffer, resdir_size ); - free( resdir_buffer ); - - /* resident names table */ - - fprintf( outfile, " {\n" ); - strcpy( string, spec->dll_name ); - fprintf( outfile, " { %d, \"%s\", 0 },\n", strlen(string), strupper(string) ); - for (i = 1; i <= spec->limit; i++) - { - ORDDEF *odp = spec->ordinals[i]; - if (!odp || !odp->name[0]) continue; - strcpy( string, odp->name ); - fprintf( outfile, " { %d, \"%s\", %d },\n", strlen(string), strupper(string), i ); - } - fprintf( outfile, " { 0 }\n },\n" ); - - /* imported names table */ - - fprintf( outfile, " { 0, 0 },\n" ); - - /* entry table */ - - output_bytes( outfile, et_buffer, et_size ); - free( et_buffer ); - - /* data_segment */ - - output_bytes( outfile, data_segment, data_size ); - - /* resource data */ - - if (resdata_size) - { - output_bytes( outfile, resdata_buffer, resdata_size ); - free( resdata_buffer ); - } - - fprintf( outfile, "};\n" ); -} - - #ifdef __i386__ /******************************************************************* * BuildCallFrom16Func @@ -671,8 +405,17 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) { ORDDEF **type, **typelist; int i, nFuncs, nTypes; - int code_offset, data_offset; - unsigned char *data; + unsigned char *resdir_buffer, *resdata_buffer, *et_buffer, *data_buffer; + unsigned char string[256]; + unsigned int ne_offset, segtable_offset, impnames_offset; + unsigned int entrypoint_size, callfrom_size; + unsigned int code_size, code_offset; + unsigned int data_size, data_offset; + unsigned int resnames_size, resnames_offset; + unsigned int resdir_size, resdir_offset; + unsigned int resdata_size, resdata_offset, resdata_align; + unsigned int et_size, et_offset; + char constructor[100], destructor[100]; #ifdef __i386__ unsigned short code_selector = get_cs(); @@ -686,9 +429,9 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, "extern void __wine_call_from_16_regs();\n" ); fprintf( outfile, "extern void __wine_call_from_16_thunk();\n" ); - data = (unsigned char *)xmalloc( 0x10000 ); - memset( data, 0, 16 ); - data_offset = 16; + data_buffer = xmalloc( 0x10000 ); + memset( data_buffer, 0, 16 ); + data_size = 16; if (!spec->dll_name) /* set default name from file name */ { @@ -741,28 +484,160 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) } #endif - /* Output the DLL functions prototypes */ + /* compute code and data sizes, set offsets, and output prototypes */ + +#ifdef __i386__ + entrypoint_size = 2 + 5 + 4; /* pushw bp + pushl target + call */ + callfrom_size = 5 + 7 + 4 + 8; /* pushl relay + lcall cs:glue + lret n + args */ +#else + entrypoint_size = 4 + 4; /* target + call */ + callfrom_size = 4 + 8; /* lret n + args */ +#endif + code_size = nTypes * callfrom_size; for (i = 0; i <= spec->limit; i++) { ORDDEF *odp = spec->ordinals[i]; if (!odp) continue; - switch(odp->type) + switch (odp->type) { + case TYPE_ABS: + odp->offset = LOWORD(odp->u.abs.value); + break; + case TYPE_VARIABLE: + odp->offset = data_size; + memcpy( data_buffer + data_size, odp->u.var.values, odp->u.var.n_values * sizeof(int) ); + data_size += odp->u.var.n_values * sizeof(int); + break; case TYPE_CDECL: case TYPE_PASCAL: case TYPE_VARARGS: fprintf( outfile, "extern void %s();\n", odp->link_name ); + /* fall through */ + case TYPE_STUB: + odp->offset = code_size; + code_size += entrypoint_size; break; default: + assert(0); break; } } + data_buffer = xrealloc( data_buffer, data_size ); /* free unneeded data */ - /* Output code segment */ + /* Output the module structure */ + + /* DOS header */ fprintf( outfile, "\n#include \"pshpack1.h\"\n" ); - fprintf( outfile, "\nstatic struct code_segment\n{\n" ); + fprintf( outfile, "static const struct module_data\n{\n" ); + fprintf( outfile, " struct\n {\n" ); + fprintf( outfile, " unsigned short e_magic;\n" ); + fprintf( outfile, " unsigned short e_cblp;\n" ); + fprintf( outfile, " unsigned short e_cp;\n" ); + fprintf( outfile, " unsigned short e_crlc;\n" ); + fprintf( outfile, " unsigned short e_cparhdr;\n" ); + fprintf( outfile, " unsigned short e_minalloc;\n" ); + fprintf( outfile, " unsigned short e_maxalloc;\n" ); + fprintf( outfile, " unsigned short e_ss;\n" ); + fprintf( outfile, " unsigned short e_sp;\n" ); + fprintf( outfile, " unsigned short e_csum;\n" ); + fprintf( outfile, " unsigned short e_ip;\n" ); + fprintf( outfile, " unsigned short e_cs;\n" ); + fprintf( outfile, " unsigned short e_lfarlc;\n" ); + fprintf( outfile, " unsigned short e_ovno;\n" ); + fprintf( outfile, " unsigned short e_res[4];\n" ); + fprintf( outfile, " unsigned short e_oemid;\n" ); + fprintf( outfile, " unsigned short e_oeminfo;\n" ); + fprintf( outfile, " unsigned short e_res2[10];\n" ); + fprintf( outfile, " unsigned int e_lfanew;\n" ); + fprintf( outfile, " } dos_header;\n" ); + + /* NE header */ + + ne_offset = 64; + fprintf( outfile, " struct\n {\n" ); + fprintf( outfile, " unsigned short ne_magic;\n" ); + fprintf( outfile, " unsigned char ne_ver;\n" ); + fprintf( outfile, " unsigned char ne_rev;\n" ); + fprintf( outfile, " unsigned short ne_enttab;\n" ); + fprintf( outfile, " unsigned short ne_cbenttab;\n" ); + fprintf( outfile, " int ne_crc;\n" ); + fprintf( outfile, " unsigned short ne_flags;\n" ); + fprintf( outfile, " unsigned short ne_autodata;\n" ); + fprintf( outfile, " unsigned short ne_heap;\n" ); + fprintf( outfile, " unsigned short ne_stack;\n" ); + fprintf( outfile, " unsigned int ne_csip;\n" ); + fprintf( outfile, " unsigned int ne_sssp;\n" ); + fprintf( outfile, " unsigned short ne_cseg;\n" ); + fprintf( outfile, " unsigned short ne_cmod;\n" ); + fprintf( outfile, " unsigned short ne_cbnrestab;\n" ); + fprintf( outfile, " unsigned short ne_segtab;\n" ); + fprintf( outfile, " unsigned short ne_rsrctab;\n" ); + fprintf( outfile, " unsigned short ne_restab;\n" ); + fprintf( outfile, " unsigned short ne_modtab;\n" ); + fprintf( outfile, " unsigned short ne_imptab;\n" ); + fprintf( outfile, " unsigned int ne_nrestab;\n" ); + fprintf( outfile, " unsigned short ne_cmovent;\n" ); + fprintf( outfile, " unsigned short ne_align;\n" ); + fprintf( outfile, " unsigned short ne_cres;\n" ); + fprintf( outfile, " unsigned char ne_exetyp;\n" ); + fprintf( outfile, " unsigned char ne_flagsothers;\n" ); + fprintf( outfile, " unsigned short ne_pretthunks;\n" ); + fprintf( outfile, " unsigned short ne_psegrefbytes;\n" ); + fprintf( outfile, " unsigned short ne_swaparea;\n" ); + fprintf( outfile, " unsigned short ne_expver;\n" ); + fprintf( outfile, " } os2_header;\n" ); + + /* segment table */ + + segtable_offset = 64; + fprintf( outfile, " struct\n {\n" ); + fprintf( outfile, " unsigned short filepos;\n" ); + fprintf( outfile, " unsigned short size;\n" ); + fprintf( outfile, " unsigned short flags;\n" ); + fprintf( outfile, " unsigned short minsize;\n" ); + fprintf( outfile, " } segtable[2];\n" ); + + /* resource directory */ + + resdir_offset = segtable_offset + 2 * 8; + resdir_size = get_res16_directory_size( spec ); + fprintf( outfile, " unsigned char resdir[%d];\n", resdir_size ); + + /* resident names table */ + + resnames_offset = resdir_offset + resdir_size; + fprintf( outfile, " struct\n {\n" ); + fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_0;\n", + strlen( spec->dll_name ) ); + resnames_size = 3 + strlen( spec->dll_name ); + for (i = 1; i <= spec->limit; i++) + { + ORDDEF *odp = spec->ordinals[i]; + if (!odp || !odp->name[0]) continue; + fprintf( outfile, " struct { unsigned char len; char name[%d]; unsigned short ord; } name_%d;\n", + strlen(odp->name), i ); + resnames_size += 3 + strlen( odp->name ); + } + fprintf( outfile, " unsigned char name_last[%d];\n", 2 - (resnames_size & 1) ); + resnames_size = (resnames_size + 2) & ~1; + fprintf( outfile, " } resnames;\n" ); + + /* imported names table */ + + impnames_offset = resnames_offset + resnames_size; + fprintf( outfile, " unsigned char impnames[2];\n" ); + + /* entry table */ + + et_offset = impnames_offset + 2; + et_size = output_entry_table( &et_buffer, spec ); + fprintf( outfile, " unsigned char entry_table[%d];\n", et_size ); + + /* code segment */ + + code_offset = et_offset + et_size; fprintf( outfile, " struct {\n" ); #ifdef __i386__ fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $relay */ @@ -784,10 +659,110 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, " unsigned short call;\n" ); /* call CALLFROM16 */ fprintf( outfile, " short callfrom16;\n" ); fprintf( outfile, " } entry[%d];\n", nFuncs ); - fprintf( outfile, "} code_segment =\n{\n {\n" ); - code_offset = 0; + /* data segment */ + data_offset = code_offset + code_size; + fprintf( outfile, " unsigned char data_segment[%d];\n", data_size ); + if (data_offset + data_size >= 0x10000) + fatal_error( "Not supported yet: 16-bit module data larger than 64K\n" ); + + /* resource data */ + + resdata_offset = ne_offset + data_offset + data_size; + for (resdata_align = 0; resdata_align < 16; resdata_align++) + { + unsigned int size = get_res16_data_size( spec, resdata_offset, resdata_align ); + if ((resdata_offset + size) >> resdata_align <= 0xffff) break; + } + output_res16_directory( &resdir_buffer, spec, resdata_offset, resdata_align ); + resdata_size = output_res16_data( &resdata_buffer, spec, resdata_offset, resdata_align ); + if (resdata_size) fprintf( outfile, " unsigned char resources[%d];\n", resdata_size ); + + /* Output the module data */ + + /* DOS header */ + + fprintf( outfile, "} module =\n{\n {\n" ); + fprintf( outfile, " 0x%04x,\n", IMAGE_DOS_SIGNATURE ); /* e_magic */ + fprintf( outfile, " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n" ); + fprintf( outfile, " { 0, 0, 0, 0, }, 0, 0,\n" ); + fprintf( outfile, " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },\n" ); + fprintf( outfile, " sizeof(module.dos_header)\n" ); /* e_lfanew */ + + /* NE header */ + + fprintf( outfile, " },\n {\n" ); + fprintf( outfile, " 0x%04x,\n", IMAGE_OS2_SIGNATURE ); /* ne_magic */ + fprintf( outfile, " 0, 0,\n" ); + fprintf( outfile, " %d,\n", et_offset ); /* ne_enttab */ + fprintf( outfile, " sizeof(module.entry_table),\n" ); /* ne_cbenttab */ + fprintf( outfile, " 0,\n" ); /* ne_crc */ + fprintf( outfile, " 0x%04x,\n", /* ne_flags */ + NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE ); + fprintf( outfile, " 2,\n" ); /* ne_autodata */ + fprintf( outfile, " %d,\n", spec->heap_size ); /* ne_heap */ + fprintf( outfile, " 0, 0, 0,\n" ); + fprintf( outfile, " 2,\n" ); /* ne_cseg */ + fprintf( outfile, " 0,\n" ); /* ne_cmod */ + fprintf( outfile, " 0,\n" ); /* ne_cbnrestab */ + fprintf( outfile, " %d,\n", segtable_offset ); /* ne_segtab */ + fprintf( outfile, " %d,\n", resdir_offset ); /* ne_rsrctab */ + fprintf( outfile, " %d,\n", resnames_offset ); /* ne_restab */ + fprintf( outfile, " %d,\n", impnames_offset ); /* ne_modtab */ + fprintf( outfile, " %d,\n", impnames_offset ); /* ne_imptab */ + fprintf( outfile, " 0,\n" ); /* ne_nrestab */ + fprintf( outfile, " 0,\n" ); /* ne_cmovent */ + fprintf( outfile, " 0,\n" ); /* ne_align */ + fprintf( outfile, " 0,\n" ); /* ne_cres */ + fprintf( outfile, " 0x%04x,\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */ + fprintf( outfile, " 0x%04x,\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */ + fprintf( outfile, " 0,\n" ); /* ne_pretthunks */ + fprintf( outfile, " 0,\n" ); /* ne_psegrefbytes */ + fprintf( outfile, " 0,\n" ); /* ne_swaparea */ + fprintf( outfile, " 0\n" ); /* ne_expver */ + fprintf( outfile, " },\n" ); + + /* segment table */ + + fprintf( outfile, " {\n" ); + fprintf( outfile, " { %d, %d, 0x%04x, %d },\n", + ne_offset + code_offset, code_size, NE_SEGFLAGS_32BIT, code_size ); + fprintf( outfile, " { %d, %d, 0x%04x, %d },\n", + ne_offset + data_offset, data_size, NE_SEGFLAGS_DATA, data_size ); + fprintf( outfile, " },\n" ); + + /* resource directory */ + + output_bytes( outfile, resdir_buffer, resdir_size ); + free( resdir_buffer ); + + /* resident names table */ + + fprintf( outfile, " {\n" ); + strcpy( string, spec->dll_name ); + fprintf( outfile, " { %d, \"%s\", 0 },\n", strlen(string), strupper(string) ); + for (i = 1; i <= spec->limit; i++) + { + ORDDEF *odp = spec->ordinals[i]; + if (!odp || !odp->name[0]) continue; + strcpy( string, odp->name ); + fprintf( outfile, " { %d, \"%s\", %d },\n", strlen(string), strupper(string), i ); + } + fprintf( outfile, " { 0 }\n },\n" ); + + /* imported names table */ + + fprintf( outfile, " { 0, 0 },\n" ); + + /* entry table */ + + output_bytes( outfile, et_buffer, et_size ); + free( et_buffer ); + + /* code segment */ + + fprintf( outfile, " {\n" ); for ( i = 0; i < nTypes; i++ ) { char profile[101], *arg; @@ -849,7 +824,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, " { 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n", arg_types[0], arg_types[1] ); #endif - code_offset += sizeof(CALLFROM16); } fprintf( outfile, " },\n {\n" ); @@ -859,15 +833,6 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) if (!odp) continue; switch (odp->type) { - case TYPE_ABS: - odp->offset = LOWORD(odp->u.abs.value); - break; - - case TYPE_VARIABLE: - odp->offset = data_offset; - data_offset += StoreVariableCode( data + data_offset, 4, odp); - break; - case TYPE_CDECL: case TYPE_PASCAL: case TYPE_VARARGS: @@ -876,45 +841,38 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) assert( type ); fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i ); + fprintf( outfile, #ifdef __i386__ - fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n", + "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n", #else - fprintf( outfile, "{ %s, 0xe866, %d, /* %s */ },\n", + "{ %s, 0xe866, %d, /* %s */ },\n", #endif odp->link_name, - (type-typelist)*sizeof(CALLFROM16) - - (code_offset + sizeof(ENTRYPOINT16)), + (type - typelist) * callfrom_size - (odp->offset + entrypoint_size), get_function_name( odp ) ); - - odp->offset = code_offset; - code_offset += sizeof(ENTRYPOINT16); break; - - default: - fprintf(stderr,"build: function type %d not available for Win16\n", - odp->type); - exit(1); + default: + break; } } + fprintf( outfile, " },\n" ); - fprintf( outfile, " }\n};\n" ); - /* Build the module */ + /* data_segment */ - output_module_data( outfile, code_offset, data, data_offset, spec ); + output_bytes( outfile, data_buffer, data_size ); + free( data_buffer ); - /* Output the DLL descriptor */ + /* resource data */ - fprintf( outfile, "#include \"poppack.h\"\n\n" ); + if (resdata_size) + { + output_bytes( outfile, resdata_buffer, resdata_size ); + free( resdata_buffer ); + } - fprintf( outfile, "static const struct dll_descriptor\n{\n" ); - fprintf( outfile, " const struct module_data *module;\n" ); - fprintf( outfile, " struct code_segment *code_start;\n" ); - fprintf( outfile, " const unsigned char *rsrc;\n" ); - fprintf( outfile, "} descriptor =\n{\n" ); - fprintf( outfile, " &module,\n" ); - fprintf( outfile, " &code_segment\n" ); fprintf( outfile, "};\n" ); + fprintf( outfile, "#include \"poppack.h\"\n\n" ); /* Output the DLL constructor */ @@ -925,13 +883,13 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, "void %s(void)\n" "{\n" - " extern void __wine_dll_register_16( const struct dll_descriptor *descr, const char *file_name );\n" - " __wine_dll_register_16( &descriptor, \"%s\" );\n" + " extern void __wine_dll_register_16( const struct module_data *, const char * );\n" + " __wine_dll_register_16( &module, \"%s\" );\n" "}\n", constructor, spec->file_name ); fprintf( outfile, "void %s(void)\n" "{\n" - " extern void __wine_dll_unregister_16( const struct dll_descriptor *descr );\n" - " __wine_dll_unregister_16( &descriptor );\n" + " extern void __wine_dll_unregister_16( const struct module_data * );\n" + " __wine_dll_unregister_16( &module );\n" "}\n", destructor ); }