Commit cbeb644a authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for loading .res files for 16-bit resources.

parent cae289cb
......@@ -79,7 +79,7 @@ CLEAN_FILES = *.o *.a *.so *.ln \\\#*\\\# *~ *% .\\\#* *.bak *.orig *.rej \
*.flc *.spec.c *.glue.c y.tab.c y.tab.h lex.yy.c core
OBJS = $(SPEC_SRCS:.spec=.spec.o) $(C_SRCS:.c=.o) $(GEN_C_SRCS:.c=.o) $(GEN_ASM_SRCS:.s=.o) \
$(ASM_SRCS:.S=.o) $(RC16_SRCS:.rc16=.o) $(GLUE:.c=.glue.o) $(EXTRA_OBJS)
$(ASM_SRCS:.S=.o) $(GLUE:.c=.glue.o) $(EXTRA_OBJS)
LINTS = $(C_SRCS:.c=.ln)
......@@ -154,7 +154,7 @@ DLLS = \
# Implicit rules
.SUFFIXES: .mc .rc .rc16 .res .spec .spec.c .spec.o .glue.c
.SUFFIXES: .mc .rc .res .spec .spec.c .spec.o .glue.c
.c.o:
$(CC) -c $(ALLCFLAGS) -o $*.o $<
......@@ -171,9 +171,6 @@ DLLS = \
.mc.rc:
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WMC) -i -H /dev/null -o $@ $<
.rc16.s:
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(WRCFLAGS) $(DIVINCL) -o $@ -w16 -m -c -p `basename $*` -s $<
.rc.res:
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(WRCFLAGS) $(DIVINCL) -o $@ -r $<
......@@ -253,8 +250,8 @@ winapi_check::
$(SUBDIRS:%=%/__depend__): $(MAKEDEP) dummy
cd `dirname $@` && $(MAKE) depend
depend: $(MAKEDEP) $(C_SRCS) $(RC_SRCS) $(RC16_SRCS) $(EXTRA_SRCS) $(GEN_C_SRCS) $(SUBDIRS:%=%/__depend__)
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(RC16_SRCS) $(EXTRA_SRCS) -C. $(GEN_C_SRCS)
depend: $(MAKEDEP) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS) $(GEN_C_SRCS) $(SUBDIRS:%=%/__depend__)
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS) -C. $(GEN_C_SRCS)
# Rules for cleaning
......@@ -265,7 +262,7 @@ $(EXTRASUBDIRS:%=%/__clean__): dummy
-cd `dirname $@` && $(RM) $(CLEAN_FILES)
clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
$(RM) $(CLEAN_FILES) $(GEN_C_SRCS) $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.res) $(RC16_SRCS:.rc16=.s) $(MC_SRCS:.mc=.rc) $(PROGRAMS)
$(RM) $(CLEAN_FILES) $(GEN_C_SRCS) $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.res) $(MC_SRCS:.mc=.rc) $(PROGRAMS)
# Rules for installing
......@@ -281,7 +278,7 @@ $(SPEC_SRCS:.spec=.spec.c): $(WINEBUILD) $(TOPSRCDIR)/include/builtin16.h
$(GLUE:.c=.glue.c): $(WINEBUILD) $(TOPSRCDIR)/include/builtin16.h
$(RC_SRCS:.rc=.res) $(RC16_SRCS:.rc16=.s): $(WRC)
$(RC_SRCS:.rc=.res): $(WRC)
$(MC_SRCS:.mc=.rc): $(WMC)
......
......@@ -22,11 +22,10 @@ C_SRCS = \
thunk.c \
user_main.c
RC16_SRCS = \
resources/display.rc16 \
resources/mouse.rc16
RC_SRCS = resources/user32.rc
RC_SRCS = \
resources/display.rc \
resources/mouse.rc \
resources/user32.rc
GLUE = thunk.c
......@@ -46,4 +45,12 @@ EXTRASUBDIRS = \
$(EXTRA_OBJS): $(TOOLSUBDIRS) dummy
@cd `dirname $@` && $(MAKE) `basename $@`
# Special rules for 16-bit resource files
resources/display.res: resources/display.rc
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(DIVINCL) -o $@ -w16 -m -r resources/display.rc
resources/mouse.res: resources/mouse.rc
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(DIVINCL) -o $@ -w16 -m -r resources/mouse.rc
### Dependencies:
name display
type win16
owner user32
rsrc display
rsrc resources/display.res
1 stub BitBlt
2 stub ColorInfo
......
name mouse
type win16
owner user32
rsrc mouse
rsrc resources/mouse.res
1 pascal16 Inquire(ptr) MOUSE_Inquire
2 pascal16 Enable(segptr) WIN16_MOUSE_Enable
......
display.s
mouse.s
display.res
mouse.res
user32.res
......@@ -23,14 +23,6 @@
DEFAULT_DEBUG_CHANNEL(module);
typedef struct
{
LPVOID res_start; /* address of resource data */
DWORD nr_res;
DWORD res_size; /* size of resource data */
} BUILTIN16_RESOURCE;
/* Table of all built-in DLLs */
#define MAX_DLLS 50
......@@ -47,54 +39,20 @@ static int nb_dlls;
static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
{
NE_MODULE *pModule;
int minsize, res_off;
int minsize;
SEGTABLEENTRY *pSegTable;
HMODULE16 hModule;
const BUILTIN16_RESOURCE *rsrc = descr->rsrc;
if (!rsrc)
{
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
descr->module_size, 0,
FALSE, FALSE, FALSE );
if (!hModule) return 0;
FarSetOwner16( hModule, hModule );
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
descr->module_size, 0,
FALSE, FALSE, FALSE );
if (!hModule) return 0;
FarSetOwner16( hModule, hModule );
pModule = (NE_MODULE *)GlobalLock16( hModule );
}
else
{
ET_BUNDLE *bundle;
hModule = GLOBAL_Alloc( GMEM_MOVEABLE,
descr->module_size + rsrc->res_size,
0, FALSE, FALSE, FALSE );
if (!hModule) return 0;
FarSetOwner16( hModule, hModule );
pModule = (NE_MODULE *)GlobalLock16( hModule );
res_off = ((NE_MODULE *)descr->module_start)->res_table;
memcpy( (LPBYTE)pModule, descr->module_start, res_off );
memcpy( (LPBYTE)pModule + res_off, rsrc->res_start, rsrc->res_size );
memcpy( (LPBYTE)pModule + res_off + rsrc->res_size,
(LPBYTE)descr->module_start + res_off, descr->module_size - res_off );
/* Have to fix up various pModule-based near pointers. Ugh! */
pModule->name_table += rsrc->res_size;
pModule->modref_table += rsrc->res_size;
pModule->import_table += rsrc->res_size;
pModule->entry_table += rsrc->res_size;
for ( bundle = (ET_BUNDLE *)((LPBYTE)pModule + pModule->entry_table);
bundle->next;
bundle = (ET_BUNDLE *)((LPBYTE)pModule + bundle->next) )
bundle->next += rsrc->res_size;
/* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
pModule->hRsrcMap = rsrc->res_start;
}
pModule = (NE_MODULE *)GlobalLock16( hModule );
pModule->self = hModule;
/* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
pModule->hRsrcMap = (void *)descr->rsrc;
TRACE( "Built-in %s: hmodule=%04x\n", descr->name, hModule );
......@@ -120,8 +78,7 @@ static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
pSegTable->minsize, minsize );
if (rsrc)
NE_InitResourceHandler(hModule);
if (descr->rsrc) NE_InitResourceHandler(hModule);
NE_RegisterModule( pModule );
return hModule;
......
......@@ -13,6 +13,7 @@ C_SRCS = \
main.c \
parser.c \
relay.c \
res16.c \
res32.c \
spec16.c \
spec32.c \
......
......@@ -139,12 +139,16 @@ extern char *strupper(char *s);
extern void fatal_error( const char *msg, ... );
extern void fatal_perror( const char *msg, ... );
extern void warning( const char *msg, ... );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant );
extern void add_import_dll( const char *name );
extern void resolve_imports( FILE *outfile );
extern int output_imports( FILE *outfile );
extern void load_res32_file( const char *name );
extern int output_resources( FILE *outfile );
extern void load_res16_file( const char *name );
extern int output_res16_data( FILE *outfile );
extern int output_res16_directory( unsigned char *buffer );
extern void BuildGlue( FILE *outfile, FILE *infile );
extern void BuildRelays( FILE *outfile );
......@@ -169,7 +173,6 @@ extern unsigned short data_selector;
extern char DLLName[80];
extern char DLLFileName[80];
extern char DLLInitFunc[80];
extern char rsrc_name[80];
extern char owner_name[80];
extern const char *input_file_name;
extern const char *output_file_name;
......
......@@ -43,7 +43,6 @@ int debugging = 1;
char DLLName[80];
char DLLFileName[80];
char DLLInitFunc[80];
char rsrc_name[80];
char owner_name[80];
const char *input_file_name;
......
......@@ -482,11 +482,7 @@ SPEC_TYPE ParseTopLevel( FILE *file )
else if (strcmp(token, "rsrc") == 0)
{
if (SpecType != SPEC_WIN16) load_res32_file( GetToken() );
else
{
strcpy( rsrc_name, GetToken() );
strcat( rsrc_name, "_ResourceDescriptor" );
}
else load_res16_file( GetToken() );
}
else if (strcmp(token, "owner") == 0)
{
......
/*
* Builtin dlls resource support
*
* Copyright 2000 Alexandre Julliard
*/
#include "config.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "winbase.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
{
char *str; /* ptr to string */
WORD id; /* integer id if str is NULL */
};
/* descriptor for a resource */
struct resource
{
struct string_id type;
struct string_id name;
const void *data;
unsigned int data_size;
WORD memopt;
};
/* type level of the resource tree */
struct res_type
{
const struct string_id *type; /* type name */
const struct resource *res; /* first resource of this type */
unsigned int nb_names; /* total number of names */
};
static struct resource *resources;
static int nb_resources;
static struct res_type *res_types;
static int nb_types; /* total number of types */
static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */
inline static struct resource *add_resource(void)
{
resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) );
return &resources[nb_resources++];
}
static struct res_type *add_type( const struct resource *res )
{
struct res_type *type;
res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) );
type = &res_types[nb_types++];
type->type = &res->type;
type->res = res;
type->nb_names = 0;
return type;
}
/* get the next byte from the current resource file */
static WORD get_byte(void)
{
unsigned char ret = *file_pos++;
if (file_pos > file_end) fatal_error( "%s is a truncated/corrupted file\n", file_name );
return ret;
}
/* get the next word from the current resource file */
static WORD get_word(void)
{
/* might not be aligned */
/* FIXME: should we change this on big-endian machines? */
unsigned char low = get_byte();
unsigned char high = get_byte();
return low | (high << 8);
}
/* get the next dword from the current resource file */
static DWORD get_dword(void)
{
WORD low = get_word();
WORD high = get_word();
return low | (high << 16);
}
/* get a string from the current resource file */
static void get_string( struct string_id *str )
{
if (*file_pos == 0xff)
{
get_byte(); /* skip the 0xff */
str->str = NULL;
str->id = get_word();
}
else
{
char *p = xmalloc( (strlen(file_pos) + 1) );
str->str = p;
str->id = 0;
while ((*p++ = get_byte()));
}
}
/* load the next resource from the current file */
static void load_next_resource(void)
{
struct resource *res = add_resource();
get_string( &res->type );
get_string( &res->name );
res->memopt = get_word();
res->data_size = get_dword();
res->data = file_pos;
file_pos += res->data_size;
if (file_pos > file_end) fatal_error( "%s is a truncated/corrupted file\n", file_name );
}
/* load a Win16 .res file */
void load_res16_file( const char *name )
{
int fd;
void *base;
struct stat st;
if ((fd = open( name, O_RDONLY )) == -1) fatal_perror( "Cannot open %s", name );
if ((fstat( fd, &st ) == -1)) fatal_perror( "Cannot stat %s", name );
if (!st.st_size) fatal_error( "%s is an empty file\n" );
if ((base = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
{
base = xmalloc( st.st_size );
if (read( fd, base, st.st_size ) != st.st_size)
fatal_error( "Cannot read %s\n", name );
}
file_name = name;
file_pos = base;
file_end = file_pos + st.st_size;
while (file_pos < file_end) load_next_resource();
}
/* compare two strings/ids */
static int cmp_string( const struct string_id *str1, const struct string_id *str2 )
{
if (!str1->str)
{
if (!str2->str) return str1->id - str2->id;
return 1; /* an id compares larger than a string */
}
if (!str2->str) return -1;
return strcasecmp( str1->str, str2->str );
}
/* compare two resources for sorting the resource directory */
/* resources are stored first by type, then by name */
static int cmp_res( const void *ptr1, const void *ptr2 )
{
const struct resource *res1 = ptr1;
const struct resource *res2 = ptr2;
int ret;
if ((ret = cmp_string( &res1->type, &res2->type ))) return ret;
return cmp_string( &res1->name, &res2->name );
}
/* build the 2-level (type,name) resource tree */
static void build_resource_tree(void)
{
int i;
struct res_type *type = NULL;
qsort( resources, nb_resources, sizeof(*resources), cmp_res );
for (i = 0; i < nb_resources; i++)
{
if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */
type = add_type( &resources[i] );
type->nb_names++;
}
}
inline static void put_byte( unsigned char **buffer, unsigned char val )
{
*(*buffer)++ = val;
}
inline static void put_word( unsigned char **buffer, WORD val )
{
put_byte( buffer, LOBYTE(val) );
put_byte( buffer, HIBYTE(val) );
}
/* output a string preceded by its length */
static void output_string( unsigned char **buffer, const char *str )
{
int len = strlen(str);
put_byte( buffer, len );
while (len--) put_byte( buffer, *str++ );
}
/* output the resource data */
int output_res16_data( FILE *outfile )
{
const struct resource *res;
unsigned char *buffer, *p;
int i, total;
if (!nb_resources) return 0;
for (i = total = 0, res = resources; i < nb_resources; i++, res++)
total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
buffer = p = xmalloc( total );
for (i = 0, res = resources; i < nb_resources; i++, res++)
{
memcpy( p, res->data, res->data_size );
p += res->data_size;
while ((int)p & ALIGN_MASK) *p++ = 0;
}
dump_bytes( outfile, buffer, total, "resource_data", 1 );
free( buffer );
return total;
}
/* output the resource definitions */
int output_res16_directory( unsigned char *buffer )
{
int i, j, offset, res_offset = 0;
const struct res_type *type;
const struct resource *res;
unsigned char *start = buffer;
build_resource_tree();
offset = 4; /* alignment + terminator */
offset += nb_types * 8; /* typeinfo structures */
offset += nb_resources * 12; /* nameinfo structures */
put_word( &buffer, ALIGNMENT );
/* type and name structures */
for (i = 0, type = res_types; i < nb_types; i++, type++)
{
if (type->type->str)
{
put_word( &buffer, offset );
offset += strlen(type->type->str) + 1;
}
else
put_word( &buffer, type->type->id | 0x8000 );
put_word( &buffer, type->nb_names );
put_word( &buffer, 0 );
put_word( &buffer, 0 );
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->memopt );
if (res->name.str)
{
put_word( &buffer, offset );
offset += strlen(res->name.str) + 1;
}
else
put_word( &buffer, res->name.id | 0x8000 );
put_word( &buffer, 0 );
put_word( &buffer, 0 );
res_offset += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
}
}
put_word( &buffer, 0 ); /* terminator */
/* name strings */
for (i = 0, type = res_types; i < nb_types; i++, type++)
{
if (type->type->str) output_string( &buffer, type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
if (res->name.str) output_string( &buffer, res->name.str );
}
}
put_byte( &buffer, 0 ); /* names terminator */
if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */
return buffer - start;
}
......@@ -63,9 +63,8 @@ static struct res_type *res_types;
static int nb_types; /* total number of types */
static int nb_id_types; /* number of types that have a numeric id */
static const char *file_base; /* base of resource file */
static const char *file_pos; /* current position in resource file */
static const char *file_end; /* end of resource file */
static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */
......@@ -121,8 +120,7 @@ static DWORD get_dword(void)
/* get a string from the current resource file */
static void get_string( struct string_id *str )
{
WCHAR *p = (WCHAR *)file_pos;
if (*p == 0xffff)
if (*(WCHAR *)file_pos == 0xffff)
{
get_word(); /* skip the 0xffff */
str->str = NULL;
......@@ -130,9 +128,9 @@ static void get_string( struct string_id *str )
}
else
{
str->str = xmalloc( (strlenW(p) + 1) * sizeof(WCHAR) );
str->id = 0;
p = str->str;
WCHAR *p = xmalloc( (strlenW((WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
str->str = p;
str->id = 0;
while ((*p++ = get_word()));
}
}
......@@ -197,9 +195,8 @@ void load_res32_file( const char *name )
}
file_name = name;
file_base = base;
file_pos = file_base;
file_end = file_base + st.st_size;
file_pos = base;
file_end = file_pos + st.st_size;
check_header();
while (file_pos < file_end) load_next_resource();
}
......
......@@ -62,7 +62,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
SEGTABLEENTRY *pSegment;
OFSTRUCT *pFileInfo;
BYTE *pstr;
WORD *pword;
ET_BUNDLE *bundle = 0;
ET_ENTRY *entry = 0;
......@@ -143,14 +142,12 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
/* Resource table */
pword = (WORD *)pSegment;
pModule->res_table = (int)pword - (int)pModule;
*pword++ = 0;
*pword++ = 0;
pstr = (char *)pSegment;
pModule->res_table = (int)pstr - (int)pModule;
pstr += output_res16_directory( pstr );
/* Imported names table */
pstr = (char *)pword;
pModule->import_table = (int)pstr - (int)pModule;
*pstr++ = 0;
*pstr++ = 0;
......@@ -243,7 +240,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
/* Dump the module content */
dump_bytes( outfile, (char *)pModule, (int)pstr - (int)pModule, "Module" );
dump_bytes( outfile, (char *)pModule, (int)pstr - (int)pModule, "Module", 0 );
return (int)pstr - (int)pModule;
}
......@@ -498,7 +495,7 @@ void BuildSpec16File( FILE *outfile )
{
ORDDEF **type, **typelist;
int i, nFuncs, nTypes;
int code_offset, data_offset, module_size;
int code_offset, data_offset, module_size, res_size;
unsigned char *data;
/* File header */
......@@ -699,16 +696,15 @@ void BuildSpec16File( FILE *outfile )
/* Output data segment */
dump_bytes( outfile, data, data_offset, "Data_Segment" );
dump_bytes( outfile, data, data_offset, "Data_Segment", 0 );
/* Build the module */
module_size = BuildModule16( outfile, code_offset, data_offset );
res_size = output_res16_data( outfile );
/* Output the DLL descriptor */
if (rsrc_name[0]) fprintf( outfile, "extern const char %s[];\n\n", rsrc_name );
fprintf( outfile, "\nstatic const BUILTIN16_DESCRIPTOR descriptor = \n{\n" );
fprintf( outfile, " \"%s\",\n", DLLName );
fprintf( outfile, " Module,\n" );
......@@ -716,9 +712,9 @@ void BuildSpec16File( FILE *outfile )
fprintf( outfile, " (BYTE *)&Code_Segment,\n" );
fprintf( outfile, " (BYTE *)Data_Segment,\n" );
fprintf( outfile, " \"%s\",\n", owner_name );
fprintf( outfile, " %s\n", rsrc_name[0] ? rsrc_name : "0" );
fprintf( outfile, " %s\n", res_size ? "resource_data" : "0" );
fprintf( outfile, "};\n" );
/* Output the DLL constructor */
fprintf( outfile, "#ifdef __GNUC__\n" );
......
......@@ -101,17 +101,18 @@ void warning( const char *msg, ... )
}
/* dump a byte stream into the assembly code */
void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label )
void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant )
{
int i;
fprintf( outfile, "\nstatic unsigned char %s[] = \n{", label );
fprintf( outfile, "\nstatic %sunsigned char %s[%d] = {",
constant ? "const " : "", label, len );
for (i = 0; i < len; i++)
{
if (!(i & 0x0f)) fprintf( outfile, "\n " );
fprintf( outfile, "%d", *data++ );
if (i < len - 1) fprintf( outfile, ", " );
if (!(i & 7)) fprintf( outfile, "\n " );
fprintf( outfile, "0x%02x", *data++ );
if (i < len - 1) fprintf( outfile, "," );
}
fprintf( outfile, "\n};\n" );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment