Added support for loading .res files for 16-bit resources.
This commit is contained in:
parent
cae289cbe4
commit
cbeb644a94
|
@ -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
|
*.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) \
|
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)
|
LINTS = $(C_SRCS:.c=.ln)
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ DLLS = \
|
||||||
|
|
||||||
# Implicit rules
|
# 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:
|
.c.o:
|
||||||
$(CC) -c $(ALLCFLAGS) -o $*.o $<
|
$(CC) -c $(ALLCFLAGS) -o $*.o $<
|
||||||
|
@ -171,9 +171,6 @@ DLLS = \
|
||||||
.mc.rc:
|
.mc.rc:
|
||||||
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WMC) -i -H /dev/null -o $@ $<
|
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:
|
.rc.res:
|
||||||
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(WRCFLAGS) $(DIVINCL) -o $@ -r $<
|
LD_LIBRARY_PATH="$(TOPOBJDIR):$$LD_LIBRARY_PATH" $(WRC) $(WRCFLAGS) $(DIVINCL) -o $@ -r $<
|
||||||
|
|
||||||
|
@ -253,8 +250,8 @@ winapi_check::
|
||||||
$(SUBDIRS:%=%/__depend__): $(MAKEDEP) dummy
|
$(SUBDIRS:%=%/__depend__): $(MAKEDEP) dummy
|
||||||
cd `dirname $@` && $(MAKE) depend
|
cd `dirname $@` && $(MAKE) depend
|
||||||
|
|
||||||
depend: $(MAKEDEP) $(C_SRCS) $(RC_SRCS) $(RC16_SRCS) $(EXTRA_SRCS) $(GEN_C_SRCS) $(SUBDIRS:%=%/__depend__)
|
depend: $(MAKEDEP) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS) $(GEN_C_SRCS) $(SUBDIRS:%=%/__depend__)
|
||||||
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(RC16_SRCS) $(EXTRA_SRCS) -C. $(GEN_C_SRCS)
|
$(MAKEDEP) $(DIVINCL) -C$(SRCDIR) $(C_SRCS) $(RC_SRCS) $(EXTRA_SRCS) -C. $(GEN_C_SRCS)
|
||||||
|
|
||||||
# Rules for cleaning
|
# Rules for cleaning
|
||||||
|
|
||||||
|
@ -265,7 +262,7 @@ $(EXTRASUBDIRS:%=%/__clean__): dummy
|
||||||
-cd `dirname $@` && $(RM) $(CLEAN_FILES)
|
-cd `dirname $@` && $(RM) $(CLEAN_FILES)
|
||||||
|
|
||||||
clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
|
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
|
# 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
|
$(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)
|
$(MC_SRCS:.mc=.rc): $(WMC)
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,10 @@ C_SRCS = \
|
||||||
thunk.c \
|
thunk.c \
|
||||||
user_main.c
|
user_main.c
|
||||||
|
|
||||||
RC16_SRCS = \
|
RC_SRCS = \
|
||||||
resources/display.rc16 \
|
resources/display.rc \
|
||||||
resources/mouse.rc16
|
resources/mouse.rc \
|
||||||
|
resources/user32.rc
|
||||||
RC_SRCS = resources/user32.rc
|
|
||||||
|
|
||||||
GLUE = thunk.c
|
GLUE = thunk.c
|
||||||
|
|
||||||
|
@ -46,4 +45,12 @@ EXTRASUBDIRS = \
|
||||||
$(EXTRA_OBJS): $(TOOLSUBDIRS) dummy
|
$(EXTRA_OBJS): $(TOOLSUBDIRS) dummy
|
||||||
@cd `dirname $@` && $(MAKE) `basename $@`
|
@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:
|
### Dependencies:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name display
|
name display
|
||||||
type win16
|
type win16
|
||||||
owner user32
|
owner user32
|
||||||
rsrc display
|
rsrc resources/display.res
|
||||||
|
|
||||||
1 stub BitBlt
|
1 stub BitBlt
|
||||||
2 stub ColorInfo
|
2 stub ColorInfo
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name mouse
|
name mouse
|
||||||
type win16
|
type win16
|
||||||
owner user32
|
owner user32
|
||||||
rsrc mouse
|
rsrc resources/mouse.res
|
||||||
|
|
||||||
1 pascal16 Inquire(ptr) MOUSE_Inquire
|
1 pascal16 Inquire(ptr) MOUSE_Inquire
|
||||||
2 pascal16 Enable(segptr) WIN16_MOUSE_Enable
|
2 pascal16 Enable(segptr) WIN16_MOUSE_Enable
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
display.s
|
display.res
|
||||||
mouse.s
|
mouse.res
|
||||||
user32.res
|
user32.res
|
||||||
|
|
|
@ -23,14 +23,6 @@
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(module);
|
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 */
|
/* Table of all built-in DLLs */
|
||||||
|
|
||||||
#define MAX_DLLS 50
|
#define MAX_DLLS 50
|
||||||
|
@ -47,13 +39,10 @@ static int nb_dlls;
|
||||||
static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
|
static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
|
||||||
{
|
{
|
||||||
NE_MODULE *pModule;
|
NE_MODULE *pModule;
|
||||||
int minsize, res_off;
|
int minsize;
|
||||||
SEGTABLEENTRY *pSegTable;
|
SEGTABLEENTRY *pSegTable;
|
||||||
HMODULE16 hModule;
|
HMODULE16 hModule;
|
||||||
const BUILTIN16_RESOURCE *rsrc = descr->rsrc;
|
|
||||||
|
|
||||||
if (!rsrc)
|
|
||||||
{
|
|
||||||
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
|
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
|
||||||
descr->module_size, 0,
|
descr->module_size, 0,
|
||||||
FALSE, FALSE, FALSE );
|
FALSE, FALSE, FALSE );
|
||||||
|
@ -61,40 +50,9 @@ static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
|
||||||
FarSetOwner16( hModule, hModule );
|
FarSetOwner16( hModule, hModule );
|
||||||
|
|
||||||
pModule = (NE_MODULE *)GlobalLock16( 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->self = 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 );
|
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),
|
LocalInit16( GlobalHandleToSel16(pSegTable->hSeg),
|
||||||
pSegTable->minsize, minsize );
|
pSegTable->minsize, minsize );
|
||||||
|
|
||||||
if (rsrc)
|
if (descr->rsrc) NE_InitResourceHandler(hModule);
|
||||||
NE_InitResourceHandler(hModule);
|
|
||||||
|
|
||||||
NE_RegisterModule( pModule );
|
NE_RegisterModule( pModule );
|
||||||
return hModule;
|
return hModule;
|
||||||
|
|
|
@ -13,6 +13,7 @@ C_SRCS = \
|
||||||
main.c \
|
main.c \
|
||||||
parser.c \
|
parser.c \
|
||||||
relay.c \
|
relay.c \
|
||||||
|
res16.c \
|
||||||
res32.c \
|
res32.c \
|
||||||
spec16.c \
|
spec16.c \
|
||||||
spec32.c \
|
spec32.c \
|
||||||
|
|
|
@ -139,12 +139,16 @@ extern char *strupper(char *s);
|
||||||
extern void fatal_error( const char *msg, ... );
|
extern void fatal_error( const char *msg, ... );
|
||||||
extern void fatal_perror( const char *msg, ... );
|
extern void fatal_perror( const char *msg, ... );
|
||||||
extern void warning( 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 add_import_dll( const char *name );
|
||||||
extern void resolve_imports( FILE *outfile );
|
extern void resolve_imports( FILE *outfile );
|
||||||
extern int output_imports( FILE *outfile );
|
extern int output_imports( FILE *outfile );
|
||||||
extern void load_res32_file( const char *name );
|
extern void load_res32_file( const char *name );
|
||||||
extern int output_resources( FILE *outfile );
|
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 BuildGlue( FILE *outfile, FILE *infile );
|
||||||
extern void BuildRelays( FILE *outfile );
|
extern void BuildRelays( FILE *outfile );
|
||||||
|
@ -169,7 +173,6 @@ extern unsigned short data_selector;
|
||||||
extern char DLLName[80];
|
extern char DLLName[80];
|
||||||
extern char DLLFileName[80];
|
extern char DLLFileName[80];
|
||||||
extern char DLLInitFunc[80];
|
extern char DLLInitFunc[80];
|
||||||
extern char rsrc_name[80];
|
|
||||||
extern char owner_name[80];
|
extern char owner_name[80];
|
||||||
extern const char *input_file_name;
|
extern const char *input_file_name;
|
||||||
extern const char *output_file_name;
|
extern const char *output_file_name;
|
||||||
|
|
|
@ -43,7 +43,6 @@ int debugging = 1;
|
||||||
char DLLName[80];
|
char DLLName[80];
|
||||||
char DLLFileName[80];
|
char DLLFileName[80];
|
||||||
char DLLInitFunc[80];
|
char DLLInitFunc[80];
|
||||||
char rsrc_name[80];
|
|
||||||
char owner_name[80];
|
char owner_name[80];
|
||||||
|
|
||||||
const char *input_file_name;
|
const char *input_file_name;
|
||||||
|
|
|
@ -482,11 +482,7 @@ SPEC_TYPE ParseTopLevel( FILE *file )
|
||||||
else if (strcmp(token, "rsrc") == 0)
|
else if (strcmp(token, "rsrc") == 0)
|
||||||
{
|
{
|
||||||
if (SpecType != SPEC_WIN16) load_res32_file( GetToken() );
|
if (SpecType != SPEC_WIN16) load_res32_file( GetToken() );
|
||||||
else
|
else load_res16_file( GetToken() );
|
||||||
{
|
|
||||||
strcpy( rsrc_name, GetToken() );
|
|
||||||
strcat( rsrc_name, "_ResourceDescriptor" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (strcmp(token, "owner") == 0)
|
else if (strcmp(token, "owner") == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* 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_types; /* total number of types */
|
||||||
static int nb_id_types; /* number of types that have a numeric id */
|
static int nb_id_types; /* number of types that have a numeric id */
|
||||||
|
|
||||||
static const char *file_base; /* base of resource file */
|
static const unsigned char *file_pos; /* current position in resource file */
|
||||||
static const char *file_pos; /* current position in resource file */
|
static const unsigned char *file_end; /* end of resource file */
|
||||||
static const char *file_end; /* end of resource file */
|
|
||||||
static const char *file_name; /* current resource file name */
|
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 */
|
/* get a string from the current resource file */
|
||||||
static void get_string( struct string_id *str )
|
static void get_string( struct string_id *str )
|
||||||
{
|
{
|
||||||
WCHAR *p = (WCHAR *)file_pos;
|
if (*(WCHAR *)file_pos == 0xffff)
|
||||||
if (*p == 0xffff)
|
|
||||||
{
|
{
|
||||||
get_word(); /* skip the 0xffff */
|
get_word(); /* skip the 0xffff */
|
||||||
str->str = NULL;
|
str->str = NULL;
|
||||||
|
@ -130,9 +128,9 @@ static void get_string( struct string_id *str )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str->str = xmalloc( (strlenW(p) + 1) * sizeof(WCHAR) );
|
WCHAR *p = xmalloc( (strlenW((WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
|
||||||
|
str->str = p;
|
||||||
str->id = 0;
|
str->id = 0;
|
||||||
p = str->str;
|
|
||||||
while ((*p++ = get_word()));
|
while ((*p++ = get_word()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,9 +195,8 @@ void load_res32_file( const char *name )
|
||||||
}
|
}
|
||||||
|
|
||||||
file_name = name;
|
file_name = name;
|
||||||
file_base = base;
|
file_pos = base;
|
||||||
file_pos = file_base;
|
file_end = file_pos + st.st_size;
|
||||||
file_end = file_base + st.st_size;
|
|
||||||
check_header();
|
check_header();
|
||||||
while (file_pos < file_end) load_next_resource();
|
while (file_pos < file_end) load_next_resource();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
|
||||||
SEGTABLEENTRY *pSegment;
|
SEGTABLEENTRY *pSegment;
|
||||||
OFSTRUCT *pFileInfo;
|
OFSTRUCT *pFileInfo;
|
||||||
BYTE *pstr;
|
BYTE *pstr;
|
||||||
WORD *pword;
|
|
||||||
ET_BUNDLE *bundle = 0;
|
ET_BUNDLE *bundle = 0;
|
||||||
ET_ENTRY *entry = 0;
|
ET_ENTRY *entry = 0;
|
||||||
|
|
||||||
|
@ -143,14 +142,12 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
|
||||||
|
|
||||||
/* Resource table */
|
/* Resource table */
|
||||||
|
|
||||||
pword = (WORD *)pSegment;
|
pstr = (char *)pSegment;
|
||||||
pModule->res_table = (int)pword - (int)pModule;
|
pModule->res_table = (int)pstr - (int)pModule;
|
||||||
*pword++ = 0;
|
pstr += output_res16_directory( pstr );
|
||||||
*pword++ = 0;
|
|
||||||
|
|
||||||
/* Imported names table */
|
/* Imported names table */
|
||||||
|
|
||||||
pstr = (char *)pword;
|
|
||||||
pModule->import_table = (int)pstr - (int)pModule;
|
pModule->import_table = (int)pstr - (int)pModule;
|
||||||
*pstr++ = 0;
|
*pstr++ = 0;
|
||||||
*pstr++ = 0;
|
*pstr++ = 0;
|
||||||
|
@ -243,7 +240,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
|
||||||
|
|
||||||
/* Dump the module content */
|
/* 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;
|
return (int)pstr - (int)pModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +495,7 @@ void BuildSpec16File( FILE *outfile )
|
||||||
{
|
{
|
||||||
ORDDEF **type, **typelist;
|
ORDDEF **type, **typelist;
|
||||||
int i, nFuncs, nTypes;
|
int i, nFuncs, nTypes;
|
||||||
int code_offset, data_offset, module_size;
|
int code_offset, data_offset, module_size, res_size;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
/* File header */
|
/* File header */
|
||||||
|
@ -699,16 +696,15 @@ void BuildSpec16File( FILE *outfile )
|
||||||
|
|
||||||
/* Output data segment */
|
/* Output data segment */
|
||||||
|
|
||||||
dump_bytes( outfile, data, data_offset, "Data_Segment" );
|
dump_bytes( outfile, data, data_offset, "Data_Segment", 0 );
|
||||||
|
|
||||||
/* Build the module */
|
/* Build the module */
|
||||||
|
|
||||||
module_size = BuildModule16( outfile, code_offset, data_offset );
|
module_size = BuildModule16( outfile, code_offset, data_offset );
|
||||||
|
res_size = output_res16_data( outfile );
|
||||||
|
|
||||||
/* Output the DLL descriptor */
|
/* 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, "\nstatic const BUILTIN16_DESCRIPTOR descriptor = \n{\n" );
|
||||||
fprintf( outfile, " \"%s\",\n", DLLName );
|
fprintf( outfile, " \"%s\",\n", DLLName );
|
||||||
fprintf( outfile, " Module,\n" );
|
fprintf( outfile, " Module,\n" );
|
||||||
|
@ -716,7 +712,7 @@ void BuildSpec16File( FILE *outfile )
|
||||||
fprintf( outfile, " (BYTE *)&Code_Segment,\n" );
|
fprintf( outfile, " (BYTE *)&Code_Segment,\n" );
|
||||||
fprintf( outfile, " (BYTE *)Data_Segment,\n" );
|
fprintf( outfile, " (BYTE *)Data_Segment,\n" );
|
||||||
fprintf( outfile, " \"%s\",\n", owner_name );
|
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" );
|
fprintf( outfile, "};\n" );
|
||||||
|
|
||||||
/* Output the DLL constructor */
|
/* Output the DLL constructor */
|
||||||
|
|
|
@ -101,16 +101,17 @@ void warning( const char *msg, ... )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump a byte stream into the assembly code */
|
/* 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;
|
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++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (!(i & 0x0f)) fprintf( outfile, "\n " );
|
if (!(i & 7)) fprintf( outfile, "\n " );
|
||||||
fprintf( outfile, "%d", *data++ );
|
fprintf( outfile, "0x%02x", *data++ );
|
||||||
if (i < len - 1) fprintf( outfile, "," );
|
if (i < len - 1) fprintf( outfile, "," );
|
||||||
}
|
}
|
||||||
fprintf( outfile, "\n};\n" );
|
fprintf( outfile, "\n};\n" );
|
||||||
|
|
Loading…
Reference in New Issue