Sync to Wine-20050524: Alexandre Julliard julliard@winehq.org - Free delayed import modules on PROCESS_DETACH. - Removed no longer used support for 32-bit register entry points. - Added support in winebuild for specifying import libraries directly on the command line without the -l option. - Changed the -d option to only mark the library as delayed, the actual loading is now done separately. - Generate 16-bit resources in the proper format inside the module data, and get rid of the special case for builtins in NE_DefResourceHandler. - Generate the 16-bit module header in the standard on-disk format, so that winebuild doesn't need to know about kernel internal structures. - 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. - Use RaiseException instead of RtlRaiseException in 16-bit spec files since they already depend on kernel32. - Renamed __wine_(un)register_dll_16 to __wine_dll_(un)register_16 for consistency with the 32-bit version, and also make the register function use the same prototype as the 32-bit one. - Use the exported IMAGE_OS2_HEADER to generate the module header in the spec file, and moved the NE_MODULE structure definition to kernel16_private.h. - Avoid referencing stackframe.h from outside kernel32. - Moved data structures for 16-bit relay calls to winbase16.h and removed builtin16.h. - Store the 16-bit stack pointer in the WOW32Reserved TEB field. - Use RaiseException instead of RtlRaiseException for delayed entry points load failure to avoid creating a dependency on ntdll. Modified: trunk/reactos/include/wine/exception.h Modified: trunk/reactos/tools/winebuild/Makefile Modified: trunk/reactos/tools/winebuild/build.h Modified: trunk/reactos/tools/winebuild/import.c Modified: trunk/reactos/tools/winebuild/main.c Modified: trunk/reactos/tools/winebuild/parser.c Modified: trunk/reactos/tools/winebuild/relay.c Modified: trunk/reactos/tools/winebuild/res16.c Modified: trunk/reactos/tools/winebuild/spec16.c Modified: trunk/reactos/tools/winebuild/spec32.c Modified: trunk/reactos/tools/winebuild/utils.c Modified: trunk/reactos/tools/winebuild/winebuild.man.in _____
Modified: trunk/reactos/include/wine/exception.h --- trunk/reactos/include/wine/exception.h 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/include/wine/exception.h 2005-05-26 09:44:59 UTC (rev 15499) @@ -24,6 +24,7 @@
#include <setjmp.h> #include <windef.h> #include <excpt.h> +#include <wine/port.h>
/* The following definitions allow using exceptions in Wine and Winelib code * @@ -75,6 +76,10 @@
#else /* USE_COMPILER_EXCEPTIONS */
+#ifndef __GNUC__ +#define __attribute__(x) /* nothing */ +#endif + #define __TRY \ do { __WINE_FRAME __f; \ int __first = 1; \ @@ -91,7 +96,7 @@ __f.u.filter = (func); \ __wine_push_frame( &__f.frame ); \ if (sigsetjmp( __f.jmp, 1 )) { \ - const __WINE_FRAME * const __eptr WINE_UNUSED = &__f; \ + const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \ do {
#define __ENDTRY \ @@ -125,10 +130,7 @@ #define GetExceptionInformation() (__eptr) #define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode)
-#if defined(AbnormalTermination) && defined(__REACTOS__) #undef AbnormalTermination -#endif - #define AbnormalTermination() (!__normal)
typedef struct __tagWINE_FRAME @@ -175,8 +177,6 @@ { #if defined(__GNUC__) && defined(__i386__) __asm__ __volatile__(".byte 0x64\n\tmovl %0,(0)" - //: : "r" (frame->Prev) : "memory" ); - //return frame->Prev; : : "r" (frame->prev) : "memory" ); return frame->prev;
_____
Modified: trunk/reactos/tools/winebuild/Makefile --- trunk/reactos/tools/winebuild/Makefile 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/Makefile 2005-05-26 09:44:59 UTC (rev 15499) @@ -22,7 +22,7 @@
CLEAN_FILES = *.o $(TARGET)
-HOST_CFLAGS = $(HOSTARCH) -D__USE_W32API -I$(PATH_TO_TOP)/include/wine +HOST_CFLAGS = $(HOSTARCH) -D__USE_W32API -I$(PATH_TO_TOP)/include/wine -I$(PATH_TO_TOP)/include
%.o: %.c $(HOST_CC) $(HOST_CFLAGS) -c $< -o $@ _____
Modified: trunk/reactos/tools/winebuild/build.h --- trunk/reactos/tools/winebuild/build.h 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/build.h 2005-05-26 09:44:59 UTC (rev 15499) @@ -133,7 +133,7 @@
#define STACK32OFFSET(reg) STRUCTOFFSET(STACK32FRAME,reg)
/* Offset of the stack pointer relative to %fs:(0) */ -#define STACKOFFSET (STRUCTOFFSET(TEB,cur_stack)) +#define STACKOFFSET (STRUCTOFFSET(TEB,WOW32Reserved))
#define MAX_ORDINALS 65535 @@ -148,6 +148,7 @@ extern void *xrealloc (void *ptr, size_t size); extern char *xstrdup( const char *str ); extern char *strupper(char *s); +extern int strendswith(const char* str, const char* end); extern void fatal_error( const char *msg, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); extern void fatal_perror( const char *msg, ... ) @@ -167,16 +168,22 @@ extern const char *make_c_identifier( const char *str ); extern int get_alignment(int alignBoundary);
-extern void add_import_dll( const char *name, int delay ); +extern void add_import_dll( const char *name, const char *filename ); +extern void add_delayed_import( const char *name ); extern void add_ignore_symbol( const char *name ); extern void read_undef_symbols( char **argv ); extern int resolve_imports( DLLSPEC *spec ); -extern int output_imports( FILE *outfile, DLLSPEC *spec ); +extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed ); extern int load_res32_file( const char *name, DLLSPEC *spec ); extern void output_resources( FILE *outfile, DLLSPEC *spec ); extern void load_res16_file( const char *name, DLLSPEC *spec ); -extern int output_res16_data( FILE *outfile, DLLSPEC *spec ); -extern int output_res16_directory( unsigned char *buffer, DLLSPEC *spec ); +extern unsigned int get_res16_data_size( DLLSPEC *spec, unsigned int res_offset, + unsigned int alignment ); +extern unsigned int output_res16_data( unsigned char **ret_buf, DLLSPEC *spec, + unsigned int res_offset, unsigned int alignment ); +extern unsigned int get_res16_directory_size( DLLSPEC *spec ); +extern unsigned int output_res16_directory( unsigned char **ret_buf, DLLSPEC *spec, + unsigned int res_offset, unsigned int alignment ); extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor );
extern void BuildRelays16( FILE *outfile ); _____
Modified: trunk/reactos/tools/winebuild/import.c --- trunk/reactos/tools/winebuild/import.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/import.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -26,16 +26,23 @@
#include <stdio.h> #include <string.h> #include <stdarg.h> +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif
#include "winglue.h" +#include "wine/exception.h" #include "build.h"
struct import { - DLLSPEC *spec; /* description of the imported dll */ + DLLSPEC *spec; /* description of the imported dll */ + char *full_name; /* full name of the input file */ + dev_t dev; /* device/inode of the input file */ + ino_t ino; int delay; /* delay or not dll loading ? */ ORDDEF **exports; /* functions exported from this dll */ int nb_exports; /* number of exported functions */ @@ -58,6 +65,8 @@ static int nb_delayed = 0; /* number of delayed dlls */ static int total_imports = 0; /* total number of imported functions */ static int total_delayed = 0; /* total number of imported functions in delayed DLLs */ +static char **delayed_imports; /* names of delayed import dlls */ +static int nb_delayed_imports; /* size of the delayed_imports array */
/* list of symbols that are ignored by default */ static const char * const default_ignored_symbols[] = @@ -187,6 +196,7 @@ free( imp->exports ); free( imp->imports ); free_dll_spec( imp->spec ); + free( imp->full_name ); free( imp ); }
@@ -196,16 +206,28 @@ if (ld_tmp_file) unlink( ld_tmp_file ); }
+/* check whether a given dll is imported in delayed mode */ +static int is_delayed_import( const char *name ) +{ + int i; + + for (i = 0; i < nb_delayed_imports; i++) + { + if (!strcmp( delayed_imports[i], name )) return 1; + } + return 0; +} + /* check whether a given dll has already been imported */ -static int is_already_imported( const char *name ) +static struct import *is_already_imported( const char *name ) { int i;
for (i = 0; i < nb_imports; i++) { - if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1; + if (!strcmp( dll_imports[i]->spec->file_name, name )) return dll_imports[i]; } - return 0; + return NULL; }
/* open the .so library for a given dll in a specified path */ @@ -227,8 +249,8 @@ return NULL; }
-/* open the .so library for a given dll */ -static char *open_library( const char *name ) +/* find the .def import library for a given dll */ +static char *find_library( const char *name ) { char *fullname; int i; @@ -242,25 +264,37 @@ }
/* read in the list of exported symbols of an import library */ -static int read_import_lib( const char *name, struct import *imp ) +static int read_import_lib( struct import *imp ) { FILE *f; - char *fullname; int i, ret; + struct stat stat; + struct import *prev_imp; DLLSPEC *spec = imp->spec;
- imp->exports = NULL; - imp->nb_exports = 0; - - fullname = open_library( name ); - f = open_input_file( NULL, fullname ); - free( fullname ); - + f = open_input_file( NULL, imp->full_name ); + fstat( fileno(f), &stat ); + imp->dev = stat.st_dev; + imp->ino = stat.st_ino; ret = parse_def_file( f, spec ); close_input_file( f ); if (!ret) return 0; - if (is_already_imported( spec->file_name )) return 0;
+ /* check if we already imported that library from a different file */ + if ((prev_imp = is_already_imported( spec->file_name ))) + { + if (prev_imp->dev != imp->dev || prev_imp->ino != imp->ino) + fatal_error( "%s and %s have the same export name '%s'\n", + prev_imp->full_name, imp->full_name, spec->file_name ); + return 0; /* the same file was already loaded, ignore this one */ + } + + if (is_delayed_import( spec->file_name )) + { + imp->delay = 1; + nb_delayed++; + } + imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
for (i = 0; i < spec->nb_entry_points; i++) @@ -277,32 +311,47 @@ return 1; }
-/* add a dll to the list of imports */ -void add_import_dll( const char *name, int delay ) +/* build the dll exported name from the import lib name or path */ +static char *get_dll_name( const char *name, const char *filename ) { - struct import *imp; - char *fullname; + char *ret;
- fullname = xmalloc( strlen(name) + 5 ); - strcpy( fullname, name ); - if (!strchr( fullname, '.' )) strcat( fullname, ".dll" ); - - /* check if we already imported it */ - if (is_already_imported( fullname )) + if (filename) { - free( fullname ); - return; + const char *basename = strrchr( filename, '/' ); + if (!basename) basename = filename; + else basename++; + if (!strncmp( basename, "lib", 3 )) basename += 3; + ret = xmalloc( strlen(basename) + 5 ); + strcpy( ret, basename ); + if (strendswith( ret, ".def" )) ret[strlen(ret)-4] = 0; } + else + { + ret = xmalloc( strlen(name) + 5 ); + strcpy( ret, name ); + } + if (!strchr( ret, '.' )) strcat( ret, ".dll" ); + return ret; +}
- imp = xmalloc( sizeof(*imp) ); +/* add a dll to the list of imports */ +void add_import_dll( const char *name, const char *filename ) +{ + struct import *imp = xmalloc( sizeof(*imp) ); + imp->spec = alloc_dll_spec(); - imp->spec->file_name = fullname; - imp->delay = delay; + imp->spec->file_name = get_dll_name( name, filename ); + imp->delay = 0; imp->imports = NULL; imp->nb_imports = 0; - if (delay) nb_delayed++; + imp->exports = NULL; + imp->nb_exports = 0;
- if (read_import_lib( name, imp )) + if (filename) imp->full_name = xstrdup( filename ); + else imp->full_name = find_library( name ); + + if (read_import_lib( imp )) { dll_imports = xrealloc( dll_imports, (nb_imports+1) * sizeof(*dll_imports) ); dll_imports[nb_imports++] = imp; @@ -314,6 +363,21 @@ } }
+/* add a library to the list of delayed imports */ +void add_delayed_import( const char *name ) +{ + struct import *imp; + char *fullname = get_dll_name( name, NULL ); + + delayed_imports = xrealloc( delayed_imports, (nb_delayed_imports+1) * sizeof(*delayed_imports) ); + delayed_imports[nb_delayed_imports++] = fullname; + if ((imp = is_already_imported( fullname )) && !imp->delay) + { + imp->delay = 1; + nb_delayed++; + } +} + /* remove an imported dll, based on its index in the dll_imports array */ static void remove_import_dll( int index ) { @@ -438,7 +502,7 @@ static void add_extra_undef_symbols( const DLLSPEC *spec ) { const char *extras[10]; - int i, count = 0, nb_stubs = 0, nb_regs = 0; + int i, count = 0, nb_stubs = 0; int kernel_imports = 0, ntdll_imports = 0;
sort_symbols( undef_symbols, nb_undef_symbols ); @@ -447,7 +511,6 @@ { ORDDEF *odp = &spec->entry_points[i]; if (odp->type == TYPE_STUB) nb_stubs++; - if (odp->flags & FLAG_REGISTER) nb_regs++; }
/* add symbols that will be contained in the spec file itself */ @@ -467,16 +530,16 @@ if (nb_delayed) { kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec ); + kernel_imports += add_extra_symbol( extras, &count, "FreeLibrary", spec ); kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec ); + kernel_imports += add_extra_symbol( extras, &count, "RaiseException", spec ); } - if (nb_regs) - ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec ); - if (nb_delayed || nb_stubs) + if (nb_stubs) ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
/* make sure we import the dlls that contain these functions */ - if (kernel_imports) add_import_dll( "kernel32", 0 ); - if (ntdll_imports) add_import_dll( "ntdll", 0 ); + if (kernel_imports) add_import_dll( "kernel32", NULL ); + if (ntdll_imports) add_import_dll( "ntdll", NULL );
if (count) { @@ -777,10 +840,10 @@
if (!nb_delayed) goto done;
+ fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed ); for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; - fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i); for (j = 0; j < dll_imports[i]->nb_imports; j++) { ORDDEF *odp = dll_imports[i]->imports[j]; @@ -807,7 +870,7 @@ for (i = j = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; - fprintf( outfile, " { 0, "%s", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n", + fprintf( outfile, " { 0, "%s", &__wine_delay_imp_hmod[%d], &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n", dll_imports[i]->spec->file_name, i, j, j ); j += dll_imports[i]->nb_imports; } @@ -839,21 +902,7 @@ } fprintf( outfile, " }\n};\n\n" );
- /* check if there's some stub defined. if so, exception struct - * is already defined, so don't emit it twice - */ - for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break; - - if (i == spec->nb_entry_points) { - fprintf( outfile, "struct exc_record {\n" ); - fprintf( outfile, " unsigned int code, flags;\n" ); - fprintf( outfile, " void *rec, *addr;\n" ); - fprintf( outfile, " unsigned int params;\n" ); - fprintf( outfile, " const void *info[15];\n" ); - fprintf( outfile, "};\n\n" ); - fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" ); - } - + fprintf( outfile, "extern void __stdcall RaiseException(unsigned int, unsigned int, unsigned int, const void *args[]);\n" ); fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n"); fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n"); fprintf( outfile, "\n" ); @@ -871,20 +920,12 @@ fprintf( outfile, " /* patch IAT with final value */\n" ); fprintf( outfile, " return *pIAT = fn;\n" ); fprintf( outfile, " else {\n"); - fprintf( outfile, " struct exc_record rec;\n" ); - fprintf( outfile, " rec.code = 0x80000100;\n" ); - fprintf( outfile, " rec.flags = 1;\n" ); - fprintf( outfile, " rec.rec = 0;\n" ); - fprintf( outfile, " rec.params = 2;\n" ); - fprintf( outfile, " rec.info[0] = imd->szName;\n" ); - fprintf( outfile, " rec.info[1] = *pINT;\n" ); - fprintf( outfile, "#ifdef __GNUC__\n" ); - fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); - fprintf( outfile, "#else\n" ); - fprintf( outfile, " rec.addr = 0;\n" ); - fprintf( outfile, "#endif\n" ); - fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" ); - fprintf( outfile, " return 0; /* shouldn't go here */\n" ); + fprintf( outfile, " const void *args[2];\n" ); + fprintf( outfile, " args[0] = imd->szName;\n" ); + fprintf( outfile, " args[1] = *pINT;\n" ); + fprintf( outfile, " RaiseException( 0x%08x, %d, 2, args );\n", + EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE ); + fprintf( outfile, " return 0;\n" ); fprintf( outfile, " }\n}\n\n" );
fprintf( outfile, "#ifndef __GNUC__\n" ); @@ -1100,8 +1141,8 @@ /* output the import and delayed import tables of a Win32 module * returns number of DLLs exported in 'immediate' mode */ -int output_imports( FILE *outfile, DLLSPEC *spec ) +int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed ) { - output_delayed_imports( outfile, spec ); - return output_immediate_imports( outfile ); + *nb_delayed = output_delayed_imports( outfile, spec ); + return output_immediate_imports( outfile ); } _____
Modified: trunk/reactos/tools/winebuild/main.c --- trunk/reactos/tools/winebuild/main.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/main.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -283,7 +283,7 @@
spec->dll_name = xstrdup( optarg ); break; case 'd': - add_import_dll( optarg, 1 ); + add_delayed_import( optarg ); break; case 'e': spec->init_func = xstrdup( optarg ); @@ -312,7 +312,7 @@ kill_at = 1; break; case 'l': - add_import_dll( optarg, 0 ); + add_import_dll( optarg, NULL ); break; case 'o': if (unlink( optarg ) == -1 && errno != ENOENT) @@ -408,6 +408,21 @@ } }
+/* add input files that look like import libs to the import list */ +static void load_import_libs( char *argv[] ) +{ + char **ptr, **last; + + for (ptr = last = argv; *ptr; ptr++) + { + if (strendswith( *ptr, ".def" )) + add_import_dll( NULL, *ptr ); + else + *last++ = *ptr; /* not an import dll, keep it in the list */ + } + *last = NULL; +} + static int parse_input_file( DLLSPEC *spec ) { FILE *input_file = open_input_file( NULL, spec_file_name ); @@ -444,6 +459,7 @@ case MODE_DLL: spec->characteristics |= IMAGE_FILE_DLL; load_resources( argv, spec ); + load_import_libs( argv ); if (!spec_file_name) fatal_error( "missing .spec file\n" ); if (!parse_input_file( spec )) break; switch (spec->type) @@ -462,6 +478,7 @@ if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); if (!spec->file_name) fatal_error( "executable must be named via the -F option\n" ); load_resources( argv, spec ); + load_import_libs( argv ); if (spec_file_name && !parse_input_file( spec )) break; read_undef_symbols( argv ); BuildSpec32File( output_file, spec ); _____
Modified: trunk/reactos/tools/winebuild/parser.c --- trunk/reactos/tools/winebuild/parser.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/parser.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -511,6 +511,12 @@
odp->ordinal = ordinal; }
+ if (spec->type == SPEC_WIN32 && odp->flags & FLAG_REGISTER) + { + error( "-register flag not supported for Win32 entry points\n" ); + goto error; + } + if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE)) { if (!strcmp( odp->name, "DllRegisterServer" ) || _____
Modified: trunk/reactos/tools/winebuild/relay.c --- trunk/reactos/tools/winebuild/relay.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/relay.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -27,7 +27,7 @@
#include <ctype.h>
#include "thread.h" -#include "stackframe.h" +#include "wine/winbase16.h"
#include "build.h"
_____
Modified: trunk/reactos/tools/winebuild/res16.c --- trunk/reactos/tools/winebuild/res16.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/res16.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -20,6 +20,7 @@
#include "config.h"
+#include <assert.h> #include <ctype.h> #include <stdlib.h> #include <string.h> @@ -39,9 +40,6 @@ #include "winglue.h" #include "build.h"
-#define ALIGNMENT 2 /* alignment for resource data */ -#define ALIGN_MASK ((1 << ALIGNMENT) - 1) - /* Unicode string or integer id */ struct string_id { @@ -265,49 +263,116 @@ while (len--) put_byte( buffer, *str++ ); }
+/* get the resource data total size */ +unsigned int get_res16_data_size( DLLSPEC *spec, unsigned int res_offset, unsigned int alignment ) +{ + const struct resource *res; + unsigned int i, total; + unsigned int align_mask = (1 << alignment) - 1; + + if (!spec->nb_resources) return 0; + + /* add padding at the beginning if needed so that resources are properly aligned */ + total = ((res_offset + align_mask) & ~align_mask) - res_offset; + + for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) + total += (res->data_size + align_mask) & ~align_mask; + + return total; +} + /* output the resource data */ -int output_res16_data( FILE *outfile, DLLSPEC *spec ) +unsigned int output_res16_data( unsigned char **ret_buf, DLLSPEC *spec, + unsigned int res_offset, unsigned int alignment ) { const struct resource *res; - unsigned char *buffer, *p; - unsigned int i; - int total; + unsigned char *p; + unsigned int i, total, padding; + unsigned int align_mask = (1 << alignment) - 1;
if (!spec->nb_resources) return 0;
+ /* add padding at the beginning if needed so that resources are properly aligned */ + padding = ((res_offset + align_mask) & ~align_mask) - res_offset; + for (i = total = 0, res = spec->resources; i < spec->nb_resources; i++, res++) - total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK; + total += (res->data_size + align_mask) & ~align_mask;
- buffer = p = xmalloc( total ); + *ret_buf = p = xmalloc( total + padding ); + memset( p, 0, padding ); + p += padding; for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) { + unsigned int size = (res->data_size + align_mask) & ~align_mask; memcpy( p, res->data, res->data_size ); - p += res->data_size; - while ((int)p & ALIGN_MASK) *p++ = 0; + memset( p + res->data_size, 0, size - res->data_size ); + p += size; } - dump_bytes( outfile, buffer, total, "resource_data", 1 ); - free( buffer ); return total; }
+/* get the resource definitions total size */ +unsigned int get_res16_directory_size( DLLSPEC *spec ) +{ + unsigned int i, j, total_size; + struct res_tree *tree; + const struct res_type *type; + const struct resource *res; + + tree = build_resource_tree( spec ); + + total_size = 4; /* alignment + terminator */ + total_size += tree->nb_types * 8; /* typeinfo structures */ + total_size += spec->nb_resources * 12; /* nameinfo structures */ + + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) + { + if (type->type->str) total_size += strlen(type->type->str) + 1; + for (j = 0, res = type->res; j < type->nb_names; j++, res++) + if (res->name.str) total_size += strlen(res->name.str) + 1; + } + total_size++; /* final terminator */ + if (total_size & 1) total_size++; + return total_size; +} + /* output the resource definitions */ -int output_res16_directory( unsigned char *buffer, DLLSPEC *spec ) +unsigned int output_res16_directory( unsigned char **ret_buf, DLLSPEC *spec, + unsigned int res_offset, unsigned int alignment ) { - int offset, res_offset = 0; - unsigned int i, j; + int offset; + unsigned int i, j, total_size; + unsigned int align_mask = (1 << alignment) - 1; struct res_tree *tree; const struct res_type *type; const struct resource *res; - unsigned char *start = buffer; + unsigned char *buffer;
tree = build_resource_tree( spec );
+ /* make sure data offset is properly aligned */ + res_offset = (res_offset + align_mask) & ~align_mask; + + /* first compute total size */ + offset = 4; /* alignment + terminator */ offset += tree->nb_types * 8; /* typeinfo structures */ offset += spec->nb_resources * 12; /* nameinfo structures */
- put_word( &buffer, ALIGNMENT ); + total_size = offset;
+ for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) + { + if (type->type->str) total_size += strlen(type->type->str) + 1; + for (j = 0, res = type->res; j < type->nb_names; j++, res++) + if (res->name.str) total_size += strlen(res->name.str) + 1; + } + total_size++; /* final terminator */ + if (total_size & 1) total_size++; + *ret_buf = buffer = xmalloc( total_size ); + + put_word( &buffer, alignment ); + /* type and name structures */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) @@ -326,8 +391,8 @@
for (j = 0, res = type->res; j < type->nb_names; j++, res++) { - put_word( &buffer, res_offset >> ALIGNMENT ); - put_word( &buffer, (res->data_size + ALIGN_MASK) >> ALIGNMENT ); + put_word( &buffer, res_offset >> alignment ); + put_word( &buffer, (res->data_size + align_mask) >> alignment ); put_word( &buffer, res->memopt ); if (res->name.str) { @@ -338,7 +403,7 @@ put_word( &buffer, res->name.id | 0x8000 ); put_word( &buffer, 0 ); put_word( &buffer, 0 ); - res_offset += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK; + res_offset += (res->data_size + align_mask) & ~align_mask; } } put_word( &buffer, 0 ); /* terminator */ @@ -354,8 +419,9 @@ } } put_byte( &buffer, 0 ); /* names terminator */ - if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */ + if ((buffer - *ret_buf) & 1) put_byte( &buffer, 0 ); /* align on word boundary */ + assert( buffer - *ret_buf == total_size );
free_resource_tree( tree ); - return buffer - start; + return total_size; } _____
Modified: trunk/reactos/tools/winebuild/spec16.c --- trunk/reactos/tools/winebuild/spec16.c 2005-05-26 06:30:47 UTC (rev 15498) +++ trunk/reactos/tools/winebuild/spec16.c 2005-05-26 09:44:59 UTC (rev 15499) @@ -28,9 +28,7 @@
#include <ctype.h>
#include "wine/exception.h" -#include "stackframe.h" -#include "builtin16.h" -#include "module.h" +#include "wine/winbase16.h"
#include "build.h"
@@ -76,230 +74,95 @@
/******************************************************************* - * StoreVariableCode - * - * Store a list of ints into a byte array. + * output_entry_table */ -static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp ) +static int output_entry_table( unsigned char **ret_buff, DLLSPEC *spec ) { - int i; + int i, prev = 0, prev_sel = -1; + unsigned char *pstr, *buffer; + unsigned char *bundle = NULL;
- 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; -} + buffer = xmalloc( spec->limit * 5 ); /* we use at most 5 bytes per entry-point */ + pstr = buffer;
- -/******************************************************************* - * BuildModule16 - * - * Build the in-memory representation of a 16-bit NE module, and dump it - * as a byte stream into the assembly code. - */ -static int BuildModule16( FILE *outfile, int max_code_offset, - int max_data_offset, DLLSPEC *spec ) -{ - int i; - char *buffer; - NE_MODULE *pModule; - SEGTABLEENTRY *pSegment; - OFSTRUCT *pFileInfo; - BYTE *pstr; - ET_BUNDLE *bundle = 0; - ET_ENTRY entry; - - /* Module layout: - * NE_MODULE Module - * OFSTRUCT File information - * SEGTABLEENTRY Segment 1 (code) - * SEGTABLEENTRY Segment 2 (data) - * WORD[2] Resource table (empty) - * BYTE[2] Imported names (empty) - * BYTE[n] Resident names table - * BYTE[n] Entry table - */ - - buffer = xmalloc( 0x10000 ); - memset( buffer, 0, 0x10000 ); - - pModule = (NE_MODULE *)buffer; - pModule->magic = IMAGE_OS2_SIGNATURE; - pModule->count = 1; - pModule->next = 0; - pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE; - pModule->dgroup = 2; - pModule->heap_size = spec->heap_size; - pModule->stack_size = 0; - pModule->ip = 0; - pModule->cs = 0; - pModule->sp = 0; - pModule->ss = 0; - pModule->seg_count = 2; - pModule->modref_count = 0; - pModule->nrname_size = 0; - pModule->modref_table = 0; - pModule->nrname_fpos = 0; - pModule->moveable_entries = 0; - pModule->alignment = 0; - pModule->truetype = 0; - pModule->os_flags = NE_OSFLAGS_WINDOWS; - pModule->misc_flags = 0; - pModule->dlls_to_init = 0; - pModule->nrname_handle = 0; - pModule->min_swap_area = 0; - pModule->expected_version = 0; - pModule->module32 = 0; - pModule->self = 0; - pModule->self_loading_sel = 0; - - /* File information */ - - pFileInfo = (OFSTRUCT *)(pModule + 1); - pModule->fileinfo = (int)pFileInfo - (int)pModule; - memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); - pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) - + strlen(spec->file_name); - strcpy( pFileInfo->szPathName, spec->file_name ); - pstr = (char *)pFileInfo + pFileInfo->cBytes + 1; - - /* Segment table */ - - pstr = (char *)(((long)pstr + 3) & ~3); - pSegment = (SEGTABLEENTRY *)pstr; - pModule->seg_table = (int)pSegment - (int)pModule; - pSegment->filepos = 0; - pSegment->size = max_code_offset; - pSegment->flags = 0; - pSegment->minsize = max_code_offset; - pSegment->hSeg = 0; - pSegment++; - - pModule->dgroup_entry = (int)pSegment - (int)pModule; - pSegment->filepos = 0; - pSegment->size = max_data_offset; - pSegment->flags = NE_SEGFLAGS_DATA; - pSegment->minsize = max_data_offset; - pSegment->hSeg = 0; - pSegment++; - - /* Resource table */ - - pstr = (char *)pSegment; - pstr = (char *)(((long)pstr + 3) & ~3); - pModule->res_table = (int)pstr - (int)pModule; - pstr += output_res16_directory( pstr, spec ); - - /* Imported names table */ - - pstr = (char *)(((long)pstr + 3) & ~3); - pModule->import_table = (int)pstr - (int)pModule; - *pstr++ = 0; - *pstr++ = 0; - - /* Resident names table */ - - pstr = (char *)(((long)pstr + 3) & ~3); - pModule->name_table = (int)pstr - (int)pModule; - /* First entry is module name */ - *pstr = strlen( spec->dll_name ); - strcpy( pstr + 1, spec->dll_name ); - strupper( pstr + 1 ); - pstr += *pstr + 1; - *pstr++ = 0; - *pstr++ = 0; - /* Store all ordinals */ for (i = 1; i <= spec->limit; i++) { - ORDDEF *odp = spec->ordinals[i]; - WORD ord = i; - if (!odp || !odp->name[0]) continue; - *pstr = strlen( odp->name ); - strcpy( pstr + 1, odp->name ); - strupper( pstr + 1 ); - pstr += *pstr + 1; - memcpy( pstr, &ord, sizeof(WORD) ); - pstr += sizeof(WORD); - } - *pstr++ = 0; - - /* Entry table */ - - pstr = (char *)(((long)pstr + 3) & ~3); - pModule->entry_table = (int)pstr - (int)pModule; - for (i = 1; i <= spec->limit; i++) - { int selector = 0; + WORD offset; ORDDEF *odp = spec->ordinals[i]; if (!odp) continue;
- switch (odp->type) - { + switch (odp->type) + { case TYPE_CDECL: case TYPE_PASCAL: case TYPE_VARARGS: case TYPE_STUB: selector = 1; /* Code selector */ break; - case TYPE_VARIABLE: selector = 2; /* Data selector */ break; - case TYPE_ABS: selector = 0xfe; /* Constant selector */ break; - default: - selector = 0; /* Invalid selector */ - break; + continue; }
- if ( !selector ) - continue; - - if ( bundle && bundle->last+1 == i ) - bundle->last++; - else + if (!bundle || prev + 1 != i || prev_sel != selector || *bundle == 255) { - pstr = (char *)(((long)pstr + 1) & ~1); - if ( bundle ) - bundle->next = (char *)pstr - (char *)pModule; + /* need to start a new bundle */
- bundle = (ET_BUNDLE *)pstr; - bundle->first = i-1; - bundle->last = i; - bundle->next = 0; - pstr += sizeof(ET_BUNDLE); + if (prev + 1 != i) + { + int skip = i - (prev + 1); + while (skip > 255) + { + *pstr++ = 255; + *pstr++ = 0; + skip -= 255; + } + *pstr++ = skip; + *pstr++ = 0; + } + + bundle = pstr; + *pstr++ = 0; + *pstr++ = selector; + prev_sel = selector; } - - /* FIXME: is this really correct ?? */ - entry.type = 0xff; /* movable */ - entry.flags = 3; /* exported & public data */ - entry.segnum = selector; - entry.offs = odp->offset; - memcpy( pstr, &entry, sizeof(ET_ENTRY) ); - pstr += sizeof(ET_ENTRY); [truncated at 1000 lines; 698 more skipped]