mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Sync to Wine-20050211
svn path=/trunk/; revision=13573
This commit is contained in:
parent
eb51ddf583
commit
36e7b406b5
15 changed files with 7863 additions and 0 deletions
43
reactos/tools/winebuild/Makefile
Normal file
43
reactos/tools/winebuild/Makefile
Normal file
|
@ -0,0 +1,43 @@
|
|||
#
|
||||
# winebuild
|
||||
#
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
TARGET = winebuild$(EXE_POSTFIX)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
# relay.o spec16.o
|
||||
OBJECTS = \
|
||||
import.o \
|
||||
main.o \
|
||||
parser.o \
|
||||
res16.o \
|
||||
res32.o \
|
||||
spec32.o \
|
||||
utils.o \
|
||||
mkstemps.o
|
||||
|
||||
CLEAN_FILES = *.o $(TARGET)
|
||||
|
||||
HOST_CFLAGS = -D__USE_W32API -I$(PATH_TO_TOP)/include/wine
|
||||
|
||||
%.o: %.c
|
||||
$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(HOST_CC) $(OBJECTS) -o $(TARGET)
|
||||
|
||||
ifeq ($(HOST),mingw32-linux)
|
||||
clean:
|
||||
rm -f $(CLEAN_FILES)
|
||||
endif
|
||||
ifneq ($(HOST),mingw32-linux)
|
||||
clean:
|
||||
del $(CLEAN_FILES)
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
|
42
reactos/tools/winebuild/Makefile.in
Normal file
42
reactos/tools/winebuild/Makefile.in
Normal file
|
@ -0,0 +1,42 @@
|
|||
TOPSRCDIR = @top_srcdir@
|
||||
TOPOBJDIR = ../..
|
||||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
PROGRAMS = winebuild$(EXEEXT)
|
||||
MODULE = none
|
||||
|
||||
C_SRCS = \
|
||||
import.c \
|
||||
main.c \
|
||||
parser.c \
|
||||
relay.c \
|
||||
res16.c \
|
||||
res32.c \
|
||||
spec16.c \
|
||||
spec32.c \
|
||||
utils.c
|
||||
|
||||
all: $(PROGRAMS) winebuild.man
|
||||
|
||||
@MAKE_RULES@
|
||||
|
||||
winebuild$(EXEEXT): $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBPORT) $(LDFLAGS)
|
||||
|
||||
winebuild.man: winebuild.man.in
|
||||
sed -e 's,@PACKAGE_STRING\@,@PACKAGE_STRING@,g' $(SRCDIR)/winebuild.man.in >$@ || ($(RM) $@ && false)
|
||||
|
||||
install:: $(PROGRAMS) winebuild.man
|
||||
$(MKINSTALLDIRS) $(bindir) $(mandir)/man$(prog_manext)
|
||||
$(INSTALL_PROGRAM) winebuild$(EXEEXT) $(bindir)/winebuild$(EXEEXT)
|
||||
$(INSTALL_DATA) winebuild.man $(mandir)/man$(prog_manext)/winebuild.$(prog_manext)
|
||||
|
||||
uninstall::
|
||||
$(RM) $(bindir)/winebuild$(EXEEXT) $(mandir)/man$(prog_manext)/winebuild.$(prog_manext)
|
||||
|
||||
clean::
|
||||
$(RM) winebuild.man
|
||||
|
||||
### Dependencies:
|
213
reactos/tools/winebuild/build.h
Normal file
213
reactos/tools/winebuild/build.h
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1995, 1996, 1997 Alexandre Julliard
|
||||
* Copyright 1997 Eric Youngdale
|
||||
* Copyright 1999 Ulrich Weigand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_BUILD_H
|
||||
#define __WINE_BUILD_H
|
||||
|
||||
#ifndef __WINE_CONFIG_H
|
||||
# error You must include config.h to use this header
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TYPE_VARIABLE, /* variable */
|
||||
TYPE_PASCAL, /* pascal function (Win16) */
|
||||
TYPE_ABS, /* absolute value (Win16) */
|
||||
TYPE_STUB, /* unimplemented stub */
|
||||
TYPE_STDCALL, /* stdcall function (Win32) */
|
||||
TYPE_CDECL, /* cdecl function (Win32) */
|
||||
TYPE_VARARGS, /* varargs function (Win32) */
|
||||
TYPE_EXTERN, /* external symbol (Win32) */
|
||||
TYPE_NBTYPES
|
||||
} ORD_TYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPEC_WIN16,
|
||||
SPEC_WIN32
|
||||
} SPEC_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int n_values;
|
||||
int *values;
|
||||
} ORD_VARIABLE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char arg_types[21];
|
||||
} ORD_FUNCTION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int value;
|
||||
} ORD_ABS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ORD_TYPE type;
|
||||
int ordinal;
|
||||
int offset;
|
||||
int lineno;
|
||||
int flags;
|
||||
char *name; /* public name of this function */
|
||||
char *link_name; /* name of the C symbol to link to */
|
||||
char *export_name; /* name exported under for noname exports */
|
||||
union
|
||||
{
|
||||
ORD_VARIABLE var;
|
||||
ORD_FUNCTION func;
|
||||
ORD_ABS abs;
|
||||
} u;
|
||||
} ORDDEF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *file_name; /* file name of the dll */
|
||||
char *dll_name; /* internal name of the dll */
|
||||
char *owner_name; /* name of the 32-bit dll owning this one */
|
||||
char *init_func; /* initialization routine */
|
||||
SPEC_TYPE type; /* type of dll (Win16/Win32) */
|
||||
int base; /* ordinal base */
|
||||
int limit; /* ordinal limit */
|
||||
int stack_size; /* exe stack size */
|
||||
int heap_size; /* exe heap size */
|
||||
int nb_entry_points; /* number of used entry points */
|
||||
int alloc_entry_points; /* number of allocated entry points */
|
||||
int nb_names; /* number of entry points with names */
|
||||
int nb_resources; /* number of resources */
|
||||
int characteristics; /* characteristics for the PE header */
|
||||
int subsystem; /* subsystem id */
|
||||
int subsystem_major; /* subsystem version major number */
|
||||
int subsystem_minor; /* subsystem version minor number */
|
||||
ORDDEF *entry_points; /* dll entry points */
|
||||
ORDDEF **names; /* array of entry point names (points into entry_points) */
|
||||
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
|
||||
struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */
|
||||
} DLLSPEC;
|
||||
|
||||
/* entry point flags */
|
||||
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
|
||||
#define FLAG_NONAME 0x02 /* don't import function by name */
|
||||
#define FLAG_RET16 0x04 /* function returns a 16-bit value */
|
||||
#define FLAG_RET64 0x08 /* function returns a 64-bit value */
|
||||
#define FLAG_I386 0x10 /* function is i386 only */
|
||||
#define FLAG_REGISTER 0x20 /* use register calling convention */
|
||||
#define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */
|
||||
|
||||
#define FLAG_FORWARD 0x80 /* function is a forwarded name */
|
||||
|
||||
/* Offset of a structure field relative to the start of the struct */
|
||||
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
|
||||
|
||||
/* Offset of register relative to the start of the CONTEXT struct */
|
||||
#define CONTEXTOFFSET(reg) STRUCTOFFSET(CONTEXT86,reg)
|
||||
|
||||
/* Offset of register relative to the start of the STACK16FRAME struct */
|
||||
#define STACK16OFFSET(reg) STRUCTOFFSET(STACK16FRAME,reg)
|
||||
|
||||
/* Offset of register relative to the start of the STACK32FRAME struct */
|
||||
#define STACK32OFFSET(reg) STRUCTOFFSET(STACK32FRAME,reg)
|
||||
|
||||
/* Offset of the stack pointer relative to %fs:(0) */
|
||||
#define STACKOFFSET (STRUCTOFFSET(TEB,cur_stack))
|
||||
|
||||
|
||||
#define MAX_ORDINALS 65535
|
||||
|
||||
/* global functions */
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(X)
|
||||
#endif
|
||||
|
||||
extern void *xmalloc (size_t size);
|
||||
extern void *xrealloc (void *ptr, size_t size);
|
||||
extern char *xstrdup( const char *str );
|
||||
extern char *strupper(char *s);
|
||||
extern void fatal_error( const char *msg, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern void fatal_perror( const char *msg, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern void error( const char *msg, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern void warning( const char *msg, ... )
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
extern void output_standard_file_header( FILE *outfile );
|
||||
extern FILE *open_input_file( const char *srcdir, const char *name );
|
||||
extern void close_input_file( FILE *file );
|
||||
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
|
||||
const char *label, int constant );
|
||||
extern int remove_stdcall_decoration( char *name );
|
||||
extern DLLSPEC *alloc_dll_spec(void);
|
||||
extern void free_dll_spec( DLLSPEC *spec );
|
||||
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_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 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 void output_dll_init( FILE *outfile, const char *constructor, const char *destructor );
|
||||
|
||||
extern void BuildRelays16( FILE *outfile );
|
||||
extern void BuildRelays32( FILE *outfile );
|
||||
extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
|
||||
extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
|
||||
extern void BuildPedllFile( FILE *outfile, DLLSPEC *spec );
|
||||
|
||||
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
|
||||
extern int parse_def_file( FILE *file, DLLSPEC *spec );
|
||||
extern int parse_debug_channels( const char *srcdir, const char *filename );
|
||||
|
||||
/* global variables */
|
||||
|
||||
extern int current_line;
|
||||
extern int UsePIC;
|
||||
extern int debugging;
|
||||
extern int nb_debug_channels;
|
||||
extern int nb_lib_paths;
|
||||
extern int nb_errors;
|
||||
extern int display_warnings;
|
||||
extern int kill_at;
|
||||
|
||||
extern char *input_file_name;
|
||||
extern const char *output_file_name;
|
||||
extern char **debug_channels;
|
||||
extern char **lib_path;
|
||||
|
||||
extern char *ld_command;
|
||||
extern char *nm_command;
|
||||
|
||||
#endif /* __WINE_BUILD_H */
|
1105
reactos/tools/winebuild/import.c
Normal file
1105
reactos/tools/winebuild/import.c
Normal file
File diff suppressed because it is too large
Load diff
495
reactos/tools/winebuild/main.c
Normal file
495
reactos/tools/winebuild/main.c
Normal file
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
* Main function
|
||||
*
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1995, 1996, 1997 Alexandre Julliard
|
||||
* Copyright 1997 Eric Youngdale
|
||||
* Copyright 1999 Ulrich Weigand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
|
||||
#include "winglue.h"
|
||||
#include "build.h"
|
||||
|
||||
int UsePIC = 0;
|
||||
int nb_debug_channels = 0;
|
||||
int nb_lib_paths = 0;
|
||||
int nb_errors = 0;
|
||||
int display_warnings = 0;
|
||||
int kill_at = 0;
|
||||
|
||||
/* we only support relay debugging on i386 */
|
||||
#ifdef __i386__
|
||||
int debugging = 1;
|
||||
#else
|
||||
int debugging = 0;
|
||||
#endif
|
||||
|
||||
char **debug_channels = NULL;
|
||||
char **lib_path = NULL;
|
||||
|
||||
char *input_file_name = NULL;
|
||||
const char *output_file_name = NULL;
|
||||
|
||||
char *ld_command = "ld";
|
||||
char *nm_command = "nm";
|
||||
|
||||
static FILE *output_file;
|
||||
static const char *current_src_dir;
|
||||
static int nb_res_files;
|
||||
static char **res_files;
|
||||
static char *spec_file_name;
|
||||
|
||||
/* execution mode */
|
||||
enum exec_mode_values
|
||||
{
|
||||
MODE_NONE,
|
||||
MODE_DLL,
|
||||
MODE_EXE,
|
||||
MODE_DEF,
|
||||
MODE_DEBUG,
|
||||
MODE_RELAY16,
|
||||
MODE_RELAY32,
|
||||
MODE_PEDLL
|
||||
};
|
||||
|
||||
static enum exec_mode_values exec_mode = MODE_NONE;
|
||||
|
||||
/* set the dll file name from the input file name */
|
||||
static void set_dll_file_name( const char *name, DLLSPEC *spec )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (spec->file_name) return;
|
||||
|
||||
if ((p = strrchr( name, '\\' ))) name = p + 1;
|
||||
if ((p = strrchr( name, '/' ))) name = p + 1;
|
||||
spec->file_name = xmalloc( strlen(name) + 5 );
|
||||
strcpy( spec->file_name, name );
|
||||
if ((p = strrchr( spec->file_name, '.' )))
|
||||
{
|
||||
if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
|
||||
}
|
||||
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
|
||||
}
|
||||
|
||||
/* set the dll subsystem */
|
||||
static void set_subsystem( const char *subsystem, DLLSPEC *spec )
|
||||
{
|
||||
char *major, *minor, *str = xstrdup( subsystem );
|
||||
|
||||
if ((major = strchr( str, ':' ))) *major++ = 0;
|
||||
if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
|
||||
else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
|
||||
if (major)
|
||||
{
|
||||
if ((minor = strchr( major, '.' )))
|
||||
{
|
||||
*minor++ = 0;
|
||||
spec->subsystem_minor = atoi( minor );
|
||||
}
|
||||
spec->subsystem_major = atoi( major );
|
||||
}
|
||||
free( str );
|
||||
}
|
||||
|
||||
/* cleanup on program exit */
|
||||
static void cleanup(void)
|
||||
{
|
||||
if (output_file_name) unlink( output_file_name );
|
||||
}
|
||||
|
||||
/* clean things up when aborting on a signal */
|
||||
static void exit_on_signal( int sig )
|
||||
{
|
||||
exit(1); /* this will call atexit functions */
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* command-line option handling
|
||||
*/
|
||||
static const char usage_str[] =
|
||||
"Usage: winebuild [OPTIONS] [FILES]\n\n"
|
||||
"Options:\n"
|
||||
" -C --source-dir=DIR Look for source files in DIR\n"
|
||||
" -d --delay-lib=LIB Import the specified library in delayed mode\n"
|
||||
" -D SYM Ignored for C flags compatibility\n"
|
||||
" -e --entry=FUNC Set the DLL entry point function (default: DllMain)\n"
|
||||
" -f FLAGS Compiler flags (only -fPIC is supported)\n"
|
||||
" -F --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
|
||||
" -h --help Display this help message\n"
|
||||
" -H --heap=SIZE Set the heap size for a Win16 dll\n"
|
||||
" -i --ignore=SYM[,SYM] Ignore specified symbols when resolving imports\n"
|
||||
" -I DIR Ignored for C flags compatibility\n"
|
||||
" -k --kill-at Kill stdcall decorations in generated .def files\n"
|
||||
" -K FLAGS Compiler flags (only -KPIC is supported)\n"
|
||||
" --ld-cmd=LD Command to use for linking (default: ld)\n"
|
||||
" -l --library=LIB Import the specified library\n"
|
||||
" -L --library-path=DIR Look for imports libraries in DIR\n"
|
||||
" -M --main-module=MODULE Set the name of the main module for a Win16 dll\n"
|
||||
" --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n"
|
||||
" -N --dll-name=DLLNAME Set the DLL name (default: from input file name)\n"
|
||||
" -o --output=NAME Set the output file name (default: stdout)\n"
|
||||
" -r --res=RSRC.RES Load resources from RSRC.RES\n"
|
||||
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
|
||||
" --version Print the version and exit\n"
|
||||
" -w --warnings Turn on warnings\n"
|
||||
"\nMode options:\n"
|
||||
" --dll=FILE Build a .c file from a .spec or .def file\n"
|
||||
" --def=FILE.SPEC Build a .def file from a spec file\n"
|
||||
" --exe=NAME Build a .c file for the named executable\n"
|
||||
" --debug [FILES] Build a .c file with the debug channels declarations\n"
|
||||
" --relay16 Build the 16-bit relay assembly routines\n"
|
||||
" --relay32 Build the 32-bit relay assembly routines\n"
|
||||
" --pedll Build a .c file for PE dll\n\n"
|
||||
"The mode options are mutually exclusive; you must specify one and only one.\n\n";
|
||||
|
||||
enum long_options_values
|
||||
{
|
||||
LONG_OPT_DLL = 1,
|
||||
LONG_OPT_DEF,
|
||||
LONG_OPT_EXE,
|
||||
LONG_OPT_DEBUG,
|
||||
LONG_OPT_LDCMD,
|
||||
LONG_OPT_NMCMD,
|
||||
LONG_OPT_RELAY16,
|
||||
LONG_OPT_RELAY32,
|
||||
LONG_OPT_SUBSYSTEM,
|
||||
LONG_OPT_VERSION,
|
||||
LONG_OPT_PEDLL
|
||||
};
|
||||
|
||||
static const char short_options[] = "C:D:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w";
|
||||
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
{ "dll", 1, 0, LONG_OPT_DLL },
|
||||
{ "def", 1, 0, LONG_OPT_DEF },
|
||||
{ "exe", 1, 0, LONG_OPT_EXE },
|
||||
{ "debug", 0, 0, LONG_OPT_DEBUG },
|
||||
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD },
|
||||
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD },
|
||||
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
|
||||
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
|
||||
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
|
||||
{ "version", 0, 0, LONG_OPT_VERSION },
|
||||
{ "pedll", 1, 0, LONG_OPT_PEDLL },
|
||||
/* aliases for short options */
|
||||
{ "source-dir", 1, 0, 'C' },
|
||||
{ "delay-lib", 1, 0, 'd' },
|
||||
{ "entry", 1, 0, 'e' },
|
||||
{ "filename", 1, 0, 'F' },
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "heap", 1, 0, 'H' },
|
||||
{ "ignore", 1, 0, 'i' },
|
||||
{ "kill-at", 0, 0, 'k' },
|
||||
{ "library", 1, 0, 'l' },
|
||||
{ "library-path", 1, 0, 'L' },
|
||||
{ "main-module", 1, 0, 'M' },
|
||||
{ "dll-name", 1, 0, 'N' },
|
||||
{ "output", 1, 0, 'o' },
|
||||
{ "res", 1, 0, 'r' },
|
||||
{ "warnings", 0, 0, 'w' },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void usage( int exit_code )
|
||||
{
|
||||
fprintf( stderr, "%s", usage_str );
|
||||
exit( exit_code );
|
||||
}
|
||||
|
||||
static void set_exec_mode( enum exec_mode_values mode )
|
||||
{
|
||||
if (exec_mode != MODE_NONE) usage(1);
|
||||
exec_mode = mode;
|
||||
}
|
||||
|
||||
/* parse options from the argv array and remove all the recognized ones */
|
||||
static char **parse_options( int argc, char **argv, DLLSPEC *spec )
|
||||
{
|
||||
char *p;
|
||||
int optc;
|
||||
|
||||
while ((optc = getopt_long( argc, argv, short_options, long_options, NULL )) != -1)
|
||||
{
|
||||
switch(optc)
|
||||
{
|
||||
case 'C':
|
||||
current_src_dir = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
/* ignored */
|
||||
break;
|
||||
case 'F':
|
||||
spec->file_name = xstrdup( optarg );
|
||||
break;
|
||||
case 'H':
|
||||
if (!isdigit(optarg[0]))
|
||||
fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg );
|
||||
spec->heap_size = atoi(optarg);
|
||||
if (spec->heap_size > 65535)
|
||||
fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size );
|
||||
break;
|
||||
case 'I':
|
||||
/* ignored */
|
||||
break;
|
||||
case 'K':
|
||||
/* ignored, because cc generates correct code. */
|
||||
break;
|
||||
case 'L':
|
||||
lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) );
|
||||
lib_path[nb_lib_paths++] = xstrdup( optarg );
|
||||
break;
|
||||
case 'M':
|
||||
spec->owner_name = xstrdup( optarg );
|
||||
spec->type = SPEC_WIN16;
|
||||
break;
|
||||
case 'N':
|
||||
spec->dll_name = xstrdup( optarg );
|
||||
break;
|
||||
case 'd':
|
||||
add_import_dll( optarg, 1 );
|
||||
break;
|
||||
case 'e':
|
||||
spec->init_func = xstrdup( optarg );
|
||||
if ((p = strchr( spec->init_func, '@' ))) *p = 0; /* kill stdcall decoration */
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1;
|
||||
/* ignore all other flags */
|
||||
break;
|
||||
case 'h':
|
||||
usage(0);
|
||||
break;
|
||||
case 'i':
|
||||
{
|
||||
char *str = xstrdup( optarg );
|
||||
char *token = strtok( str, "," );
|
||||
while (token)
|
||||
{
|
||||
add_ignore_symbol( token );
|
||||
token = strtok( NULL, "," );
|
||||
}
|
||||
free( str );
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
kill_at = 1;
|
||||
break;
|
||||
case 'l':
|
||||
add_import_dll( optarg, 0 );
|
||||
break;
|
||||
case 'o':
|
||||
if (unlink( optarg ) == -1 && errno != ENOENT)
|
||||
fatal_error( "Unable to create output file '%s'\n", optarg );
|
||||
if (!(output_file = fopen( optarg, "w" )))
|
||||
fatal_error( "Unable to create output file '%s'\n", optarg );
|
||||
output_file_name = xstrdup(optarg);
|
||||
atexit( cleanup ); /* make sure we remove the output file on exit */
|
||||
break;
|
||||
case 'r':
|
||||
res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
|
||||
res_files[nb_res_files++] = xstrdup( optarg );
|
||||
break;
|
||||
case 'w':
|
||||
display_warnings = 1;
|
||||
break;
|
||||
case LONG_OPT_DLL:
|
||||
set_exec_mode( MODE_DLL );
|
||||
spec_file_name = xstrdup( optarg );
|
||||
set_dll_file_name( optarg, spec );
|
||||
break;
|
||||
case LONG_OPT_DEF:
|
||||
set_exec_mode( MODE_DEF );
|
||||
spec_file_name = xstrdup( optarg );
|
||||
set_dll_file_name( optarg, spec );
|
||||
break;
|
||||
case LONG_OPT_EXE:
|
||||
set_exec_mode( MODE_EXE );
|
||||
if ((p = strrchr( optarg, '/' ))) p++;
|
||||
else p = optarg;
|
||||
spec->file_name = xmalloc( strlen(p) + 5 );
|
||||
strcpy( spec->file_name, p );
|
||||
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
|
||||
if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
break;
|
||||
case LONG_OPT_DEBUG:
|
||||
set_exec_mode( MODE_DEBUG );
|
||||
break;
|
||||
case LONG_OPT_LDCMD:
|
||||
ld_command = xstrdup( optarg );
|
||||
break;
|
||||
case LONG_OPT_NMCMD:
|
||||
nm_command = xstrdup( optarg );
|
||||
break;
|
||||
case LONG_OPT_RELAY16:
|
||||
set_exec_mode( MODE_RELAY16 );
|
||||
break;
|
||||
case LONG_OPT_RELAY32:
|
||||
set_exec_mode( MODE_RELAY32 );
|
||||
break;
|
||||
case LONG_OPT_SUBSYSTEM:
|
||||
set_subsystem( optarg, spec );
|
||||
break;
|
||||
case LONG_OPT_VERSION:
|
||||
printf( "winebuild version " PACKAGE_VERSION "\n" );
|
||||
exit(0);
|
||||
case LONG_OPT_PEDLL:
|
||||
set_exec_mode( MODE_PEDLL );
|
||||
spec_file_name = xstrdup( optarg );
|
||||
set_dll_file_name( optarg, spec );
|
||||
break;
|
||||
case '?':
|
||||
usage(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return &argv[optind];
|
||||
}
|
||||
|
||||
|
||||
/* load all specified resource files */
|
||||
static void load_resources( char *argv[], DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
char **ptr, **last;
|
||||
|
||||
switch (spec->type)
|
||||
{
|
||||
case SPEC_WIN16:
|
||||
for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i], spec );
|
||||
break;
|
||||
|
||||
case SPEC_WIN32:
|
||||
for (i = 0; i < nb_res_files; i++)
|
||||
{
|
||||
if (!load_res32_file( res_files[i], spec ))
|
||||
fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] );
|
||||
}
|
||||
|
||||
/* load any resource file found in the remaining arguments */
|
||||
for (ptr = last = argv; *ptr; ptr++)
|
||||
{
|
||||
if (!load_res32_file( *ptr, spec ))
|
||||
*last++ = *ptr; /* not a resource file, keep it in the list */
|
||||
}
|
||||
*last = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_input_file( DLLSPEC *spec )
|
||||
{
|
||||
FILE *input_file = open_input_file( NULL, spec_file_name );
|
||||
char *extension = strrchr( spec_file_name, '.' );
|
||||
|
||||
if (extension && !strcmp( extension, ".def" ))
|
||||
return parse_def_file( input_file, spec );
|
||||
else
|
||||
return parse_spec_file( input_file, spec );
|
||||
close_input_file( input_file );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* main
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DLLSPEC *spec = alloc_dll_spec();
|
||||
|
||||
#ifdef SIGHUP
|
||||
signal( SIGHUP, exit_on_signal );
|
||||
#endif
|
||||
signal( SIGTERM, exit_on_signal );
|
||||
signal( SIGINT, exit_on_signal );
|
||||
|
||||
output_file = stdout;
|
||||
argv = parse_options( argc, argv, spec );
|
||||
|
||||
switch(exec_mode)
|
||||
{
|
||||
case MODE_DLL:
|
||||
spec->characteristics |= IMAGE_FILE_DLL;
|
||||
load_resources( argv, spec );
|
||||
if (!parse_input_file( spec )) break;
|
||||
switch (spec->type)
|
||||
{
|
||||
case SPEC_WIN16:
|
||||
fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
|
||||
break;
|
||||
case SPEC_WIN32:
|
||||
read_undef_symbols( argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
break;
|
||||
case MODE_EXE:
|
||||
if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
|
||||
load_resources( argv, spec );
|
||||
read_undef_symbols( argv );
|
||||
BuildSpec32File( output_file, spec );
|
||||
break;
|
||||
case MODE_DEF:
|
||||
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
|
||||
if (!parse_input_file( spec )) break;
|
||||
BuildDef32File( output_file, spec );
|
||||
break;
|
||||
case MODE_DEBUG:
|
||||
BuildDebugFile( output_file, current_src_dir, argv );
|
||||
break;
|
||||
case MODE_RELAY16:
|
||||
fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
|
||||
break;
|
||||
case MODE_RELAY32:
|
||||
fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
|
||||
break;
|
||||
case MODE_PEDLL:
|
||||
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
|
||||
if (!parse_input_file( spec )) break;
|
||||
BuildPedllFile( output_file, spec );
|
||||
break;
|
||||
default:
|
||||
usage(1);
|
||||
break;
|
||||
}
|
||||
if (nb_errors) exit(1);
|
||||
if (output_file_name)
|
||||
{
|
||||
fclose( output_file );
|
||||
output_file_name = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
138
reactos/tools/winebuild/mkstemps.c
Normal file
138
reactos/tools/winebuild/mkstemps.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* Copyright (C) 1991, 1992, 1996, 1998 Free Software Foundation, Inc.
|
||||
This file is derived from mkstemp.c from the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_PROCESS_H
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
/* We need to provide a type for gcc_uint64_t. */
|
||||
#ifdef __GNUC__
|
||||
__extension__ typedef unsigned long long gcc_uint64_t;
|
||||
#else
|
||||
typedef unsigned long gcc_uint64_t;
|
||||
#endif
|
||||
|
||||
#ifndef TMP_MAX
|
||||
#define TMP_MAX 16384
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@deftypefn Replacement int mkstemps (char *@var{template}, int @var{suffix_len})
|
||||
|
||||
Generate a unique temporary file name from @var{template}.
|
||||
@var{template} has the form:
|
||||
|
||||
@example
|
||||
@var{path}/ccXXXXXX@var{suffix}
|
||||
@end example
|
||||
|
||||
@var{suffix_len} tells us how long @var{suffix} is (it can be zero
|
||||
length). The last six characters of @var{template} before @var{suffix}
|
||||
must be @samp{XXXXXX}; they are replaced with a string that makes the
|
||||
filename unique. Returns a file descriptor open on the file for
|
||||
reading and writing.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
mkstemps (
|
||||
char *template,
|
||||
int suffix_len)
|
||||
{
|
||||
static const char letters[]
|
||||
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
static gcc_uint64_t value;
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
struct timeval tv;
|
||||
#endif
|
||||
char *XXXXXX;
|
||||
size_t len;
|
||||
int count;
|
||||
|
||||
len = strlen (template);
|
||||
|
||||
if ((int) len < 6 + suffix_len
|
||||
|| strncmp (&template[len - 6 - suffix_len], "XXXXXX", 6))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
XXXXXX = &template[len - 6 - suffix_len];
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
/* Get some more or less random data. */
|
||||
gettimeofday (&tv, NULL);
|
||||
value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
|
||||
#else
|
||||
value += getpid ();
|
||||
#endif
|
||||
|
||||
for (count = 0; count < TMP_MAX; ++count)
|
||||
{
|
||||
gcc_uint64_t v = value;
|
||||
int fd;
|
||||
|
||||
/* Fill in the random bits. */
|
||||
XXXXXX[0] = letters[v % 62];
|
||||
v /= 62;
|
||||
XXXXXX[1] = letters[v % 62];
|
||||
v /= 62;
|
||||
XXXXXX[2] = letters[v % 62];
|
||||
v /= 62;
|
||||
XXXXXX[3] = letters[v % 62];
|
||||
v /= 62;
|
||||
XXXXXX[4] = letters[v % 62];
|
||||
v /= 62;
|
||||
XXXXXX[5] = letters[v % 62];
|
||||
|
||||
#ifdef VMS
|
||||
fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600, "fop=tmd");
|
||||
#else
|
||||
fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
#endif
|
||||
if (fd >= 0)
|
||||
/* The file does not exist. */
|
||||
return fd;
|
||||
|
||||
/* This is a random value. It is only necessary that the next
|
||||
TMP_MAX values generated by adding 7777 to VALUE are different
|
||||
with (module 2^32). */
|
||||
value += 7777;
|
||||
}
|
||||
|
||||
/* We return the null string if we can't find a unique file name. */
|
||||
template[0] = '\0';
|
||||
return -1;
|
||||
}
|
1001
reactos/tools/winebuild/parser.c
Normal file
1001
reactos/tools/winebuild/parser.c
Normal file
File diff suppressed because it is too large
Load diff
1208
reactos/tools/winebuild/relay.c
Normal file
1208
reactos/tools/winebuild/relay.c
Normal file
File diff suppressed because it is too large
Load diff
360
reactos/tools/winebuild/res16.c
Normal file
360
reactos/tools/winebuild/res16.c
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Builtin dlls resource support
|
||||
*
|
||||
* Copyright 2000 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
{
|
||||
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 */
|
||||
};
|
||||
|
||||
/* top level of the resource tree */
|
||||
struct res_tree
|
||||
{
|
||||
struct res_type *types; /* types array */
|
||||
unsigned 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( DLLSPEC *spec )
|
||||
{
|
||||
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) );
|
||||
return &spec->resources[spec->nb_resources++];
|
||||
}
|
||||
|
||||
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
|
||||
{
|
||||
struct res_type *type;
|
||||
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
|
||||
type = &tree->types[tree->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 unsigned char 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 */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
unsigned char high = get_byte();
|
||||
unsigned char low = get_byte();
|
||||
#else
|
||||
unsigned char low = get_byte();
|
||||
unsigned char high = get_byte();
|
||||
#endif
|
||||
return low | (high << 8);
|
||||
}
|
||||
|
||||
/* get the next dword from the current resource file */
|
||||
static DWORD get_dword(void)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
WORD high = get_word();
|
||||
WORD low = get_word();
|
||||
#else
|
||||
WORD low = get_word();
|
||||
WORD high = get_word();
|
||||
#endif
|
||||
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( DLLSPEC *spec )
|
||||
{
|
||||
struct resource *res = add_resource( spec );
|
||||
|
||||
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, DLLSPEC *spec )
|
||||
{
|
||||
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", name );
|
||||
#ifdef HAVE_MMAP
|
||||
if ((base = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
|
||||
#endif /* HAVE_MMAP */
|
||||
{
|
||||
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( spec );
|
||||
}
|
||||
|
||||
/* 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 struct res_tree *build_resource_tree( DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
struct res_tree *tree;
|
||||
struct res_type *type = NULL;
|
||||
|
||||
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
|
||||
|
||||
tree = xmalloc( sizeof(*tree) );
|
||||
tree->types = NULL;
|
||||
tree->nb_types = 0;
|
||||
|
||||
for (i = 0; i < spec->nb_resources; i++)
|
||||
{
|
||||
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
|
||||
type = add_type( tree, &spec->resources[i] );
|
||||
type->nb_names++;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* free the resource tree */
|
||||
static void free_resource_tree( struct res_tree *tree )
|
||||
{
|
||||
free( tree->types );
|
||||
free( tree );
|
||||
}
|
||||
|
||||
inline static void put_byte( unsigned char **buffer, unsigned char val )
|
||||
{
|
||||
*(*buffer)++ = val;
|
||||
}
|
||||
|
||||
inline static void put_word( unsigned char **buffer, WORD val )
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
put_byte( buffer, HIBYTE(val) );
|
||||
put_byte( buffer, LOBYTE(val) );
|
||||
#else
|
||||
put_byte( buffer, LOBYTE(val) );
|
||||
put_byte( buffer, HIBYTE(val) );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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, DLLSPEC *spec )
|
||||
{
|
||||
const struct resource *res;
|
||||
unsigned char *buffer, *p;
|
||||
int i, total;
|
||||
|
||||
if (!spec->nb_resources) return 0;
|
||||
|
||||
for (i = total = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
|
||||
|
||||
buffer = p = xmalloc( total );
|
||||
for (i = 0, res = spec->resources; i < spec->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, DLLSPEC *spec )
|
||||
{
|
||||
int i, offset, res_offset = 0;
|
||||
unsigned int j;
|
||||
struct res_tree *tree;
|
||||
const struct res_type *type;
|
||||
const struct resource *res;
|
||||
unsigned char *start = buffer;
|
||||
|
||||
tree = build_resource_tree( spec );
|
||||
|
||||
offset = 4; /* alignment + terminator */
|
||||
offset += tree->nb_types * 8; /* typeinfo structures */
|
||||
offset += spec->nb_resources * 12; /* nameinfo structures */
|
||||
|
||||
put_word( &buffer, ALIGNMENT );
|
||||
|
||||
/* type and name structures */
|
||||
|
||||
for (i = 0, type = tree->types; i < tree->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 = tree->types; i < tree->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 */
|
||||
|
||||
free_resource_tree( tree );
|
||||
return buffer - start;
|
||||
}
|
489
reactos/tools/winebuild/res32.c
Normal file
489
reactos/tools/winebuild/res32.c
Normal file
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
* Builtin dlls resource support
|
||||
*
|
||||
* Copyright 2000 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "winglue.h"
|
||||
#include "build.h"
|
||||
|
||||
/* Unicode string or integer id */
|
||||
struct string_id
|
||||
{
|
||||
WCHAR *str; /* ptr to Unicode 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 lang;
|
||||
};
|
||||
|
||||
/* name level of the resource tree */
|
||||
struct res_name
|
||||
{
|
||||
const struct string_id *name; /* name */
|
||||
const struct resource *res; /* resource */
|
||||
int nb_languages; /* number of languages */
|
||||
unsigned int name_offset; /* offset of name in resource dir */
|
||||
};
|
||||
|
||||
/* type level of the resource tree */
|
||||
struct res_type
|
||||
{
|
||||
const struct string_id *type; /* type name */
|
||||
struct res_name *names; /* names array */
|
||||
unsigned int nb_names; /* total number of names */
|
||||
unsigned int nb_id_names; /* number of names that have a numeric id */
|
||||
unsigned int name_offset; /* offset of type name in resource dir */
|
||||
};
|
||||
|
||||
/* top level of the resource tree */
|
||||
struct res_tree
|
||||
{
|
||||
struct res_type *types; /* types array */
|
||||
unsigned 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 */
|
||||
|
||||
/* size of a resource directory with n entries */
|
||||
#define RESDIR_SIZE(n) ((4 + 2 * (n)) * sizeof(int))
|
||||
|
||||
|
||||
inline static struct resource *add_resource( DLLSPEC *spec )
|
||||
{
|
||||
spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) );
|
||||
return &spec->resources[spec->nb_resources++];
|
||||
}
|
||||
|
||||
static inline unsigned int strlenW( const WCHAR *str )
|
||||
{
|
||||
const WCHAR *s = str;
|
||||
while (*s) s++;
|
||||
return s - str;
|
||||
}
|
||||
|
||||
static inline int strcmpW( const WCHAR *str1, const WCHAR *str2 )
|
||||
{
|
||||
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
return *str1 - *str2;
|
||||
}
|
||||
|
||||
static struct res_name *add_name( struct res_type *type, const struct resource *res )
|
||||
{
|
||||
struct res_name *name;
|
||||
type->names = xrealloc( type->names, (type->nb_names + 1) * sizeof(*type->names) );
|
||||
name = &type->names[type->nb_names++];
|
||||
name->name = &res->name;
|
||||
name->res = res;
|
||||
name->nb_languages = 1;
|
||||
if (!name->name->str) type->nb_id_names++;
|
||||
return name;
|
||||
}
|
||||
|
||||
static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
|
||||
{
|
||||
struct res_type *type;
|
||||
tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
|
||||
type = &tree->types[tree->nb_types++];
|
||||
type->type = &res->type;
|
||||
type->names = NULL;
|
||||
type->nb_names = 0;
|
||||
type->nb_id_names = 0;
|
||||
return type;
|
||||
}
|
||||
|
||||
/* get the next word from the current resource file */
|
||||
static WORD get_word(void)
|
||||
{
|
||||
WORD ret = *(const WORD *)file_pos;
|
||||
file_pos += sizeof(WORD);
|
||||
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the next dword from the current resource file */
|
||||
static DWORD get_dword(void)
|
||||
{
|
||||
DWORD ret = *(const DWORD *)file_pos;
|
||||
file_pos += sizeof(DWORD);
|
||||
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get a string from the current resource file */
|
||||
static void get_string( struct string_id *str )
|
||||
{
|
||||
if (*(const WCHAR *)file_pos == 0xffff)
|
||||
{
|
||||
get_word(); /* skip the 0xffff */
|
||||
str->str = NULL;
|
||||
str->id = get_word();
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR *p = xmalloc( (strlenW((const WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
|
||||
str->str = p;
|
||||
str->id = 0;
|
||||
while ((*p++ = get_word()));
|
||||
}
|
||||
}
|
||||
|
||||
/* check the file header */
|
||||
/* all values must be zero except header size */
|
||||
static int check_header(void)
|
||||
{
|
||||
if (get_dword()) return 0; /* data size */
|
||||
if (get_dword() != 32) return 0; /* header size */
|
||||
if (get_word() != 0xffff || get_word()) return 0; /* type, must be id 0 */
|
||||
if (get_word() != 0xffff || get_word()) return 0; /* name, must be id 0 */
|
||||
if (get_dword()) return 0; /* data version */
|
||||
if (get_word()) return 0; /* mem options */
|
||||
if (get_word()) return 0; /* language */
|
||||
if (get_dword()) return 0; /* version */
|
||||
if (get_dword()) return 0; /* characteristics */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* load the next resource from the current file */
|
||||
static void load_next_resource( DLLSPEC *spec )
|
||||
{
|
||||
DWORD hdr_size;
|
||||
struct resource *res = add_resource( spec );
|
||||
|
||||
res->data_size = (get_dword() + 3) & ~3;
|
||||
hdr_size = get_dword();
|
||||
if (hdr_size & 3) fatal_error( "%s header size not aligned\n", file_name );
|
||||
|
||||
res->data = file_pos - 2*sizeof(DWORD) + hdr_size;
|
||||
get_string( &res->type );
|
||||
get_string( &res->name );
|
||||
if ((int)file_pos & 2) get_word(); /* align to dword boundary */
|
||||
get_dword(); /* skip data version */
|
||||
get_word(); /* skip mem options */
|
||||
res->lang = get_word();
|
||||
get_dword(); /* skip version */
|
||||
get_dword(); /* skip characteristics */
|
||||
|
||||
file_pos = (const char *)res->data + res->data_size;
|
||||
if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
|
||||
}
|
||||
|
||||
/* load a Win32 .res file */
|
||||
int load_res32_file( const char *name, DLLSPEC *spec )
|
||||
{
|
||||
int fd, ret;
|
||||
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", name );
|
||||
#ifdef HAVE_MMAP
|
||||
if ((base = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 )) == (void*)-1)
|
||||
#endif /* HAVE_MMAP */
|
||||
{
|
||||
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;
|
||||
if ((ret = check_header()))
|
||||
{
|
||||
while (file_pos < file_end) load_next_resource( spec );
|
||||
}
|
||||
close( fd );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* compare two unicode 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 strcmpW( str1->str, str2->str );
|
||||
}
|
||||
|
||||
/* compare two resources for sorting the resource directory */
|
||||
/* resources are stored first by type, then by name, then by language */
|
||||
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;
|
||||
if ((ret = cmp_string( &res1->name, &res2->name ))) return ret;
|
||||
return res1->lang - res2->lang;
|
||||
}
|
||||
|
||||
/* build the 3-level (type,name,language) resource tree */
|
||||
static struct res_tree *build_resource_tree( DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
struct res_tree *tree;
|
||||
struct res_type *type = NULL;
|
||||
struct res_name *name = NULL;
|
||||
|
||||
qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
|
||||
|
||||
tree = xmalloc( sizeof(*tree) );
|
||||
tree->types = NULL;
|
||||
tree->nb_types = 0;
|
||||
|
||||
for (i = 0; i < spec->nb_resources; i++)
|
||||
{
|
||||
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
|
||||
{
|
||||
type = add_type( tree, &spec->resources[i] );
|
||||
name = add_name( type, &spec->resources[i] );
|
||||
}
|
||||
else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */
|
||||
{
|
||||
name = add_name( type, &spec->resources[i] );
|
||||
}
|
||||
else name->nb_languages++;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* free the resource tree */
|
||||
static void free_resource_tree( struct res_tree *tree )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tree->nb_types; i++) free( tree->types[i].names );
|
||||
free( tree->types );
|
||||
free( tree );
|
||||
}
|
||||
|
||||
/* output a Unicode string */
|
||||
static void output_string( FILE *outfile, const WCHAR *name )
|
||||
{
|
||||
int i, len = strlenW(name);
|
||||
fprintf( outfile, "0x%04x", len );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, ", 0x%04x", name[i] );
|
||||
fprintf( outfile, " /* " );
|
||||
for (i = 0; i < len; i++) fprintf( outfile, "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
|
||||
fprintf( outfile, " */" );
|
||||
}
|
||||
|
||||
/* output the resource definitions */
|
||||
void output_resources( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
int i, j, k, nb_id_types;
|
||||
unsigned int n, offset, data_offset;
|
||||
struct res_tree *tree;
|
||||
struct res_type *type;
|
||||
struct res_name *name;
|
||||
const struct resource *res;
|
||||
|
||||
if (!spec->nb_resources) return;
|
||||
|
||||
tree = build_resource_tree( spec );
|
||||
|
||||
/* resource data */
|
||||
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
{
|
||||
const unsigned int *p = res->data;
|
||||
int size = res->data_size / 4;
|
||||
/* dump data as ints to ensure correct alignment */
|
||||
fprintf( outfile, "static const unsigned int res_%d[%d] = {\n ", i, size );
|
||||
for (j = 0; j < size - 1; j++, p++)
|
||||
{
|
||||
fprintf( outfile, "0x%08x,", *p );
|
||||
if ((j % 8) == 7) fprintf( outfile, "\n " );
|
||||
}
|
||||
fprintf( outfile, "0x%08x\n};\n\n", *p );
|
||||
}
|
||||
|
||||
/* directory structures */
|
||||
|
||||
fprintf( outfile, "struct res_dir {\n" );
|
||||
fprintf( outfile, " unsigned int Characteristics;\n" );
|
||||
fprintf( outfile, " unsigned int TimeDateStamp;\n" );
|
||||
fprintf( outfile, " unsigned short MajorVersion, MinorVersion;\n" );
|
||||
fprintf( outfile, " unsigned short NumerOfNamedEntries, NumberOfIdEntries;\n};\n\n" );
|
||||
fprintf( outfile, "struct res_dir_entry {\n" );
|
||||
fprintf( outfile, " unsigned int Name;\n" );
|
||||
fprintf( outfile, " unsigned int OffsetToData;\n};\n\n" );
|
||||
fprintf( outfile, "struct res_data_entry {\n" );
|
||||
fprintf( outfile, " const unsigned int *OffsetToData;\n" );
|
||||
fprintf( outfile, " unsigned int Size;\n" );
|
||||
fprintf( outfile, " unsigned int CodePage;\n" );
|
||||
fprintf( outfile, " unsigned int ResourceHandle;\n};\n\n" );
|
||||
|
||||
/* resource directory definition */
|
||||
|
||||
fprintf( outfile, "static struct res_struct{\n" );
|
||||
fprintf( outfile, " struct res_dir type_dir;\n" );
|
||||
fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", tree->nb_types );
|
||||
offset = RESDIR_SIZE( tree->nb_types );
|
||||
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
offset += RESDIR_SIZE( type->nb_names );
|
||||
fprintf( outfile, " struct res_dir name_%d_dir;\n", i );
|
||||
fprintf( outfile, " struct res_dir_entry name_%d_entries[%d];\n", i, type->nb_names );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
offset += RESDIR_SIZE( name->nb_languages );
|
||||
fprintf( outfile, " struct res_dir lang_%d_%d_dir;\n", i, n );
|
||||
fprintf( outfile, " struct res_dir_entry lang_%d_%d_entries[%d];\n",
|
||||
i, n, name->nb_languages );
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, " struct res_data_entry data_entries[%d];\n", spec->nb_resources );
|
||||
offset += spec->nb_resources * 4 * sizeof(int);
|
||||
|
||||
for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
if (type->type->str)
|
||||
{
|
||||
type->name_offset = offset | 0x80000000;
|
||||
offset += (strlenW(type->type->str)+1) * sizeof(unsigned short);
|
||||
fprintf( outfile, " unsigned short type_%d_name[%d];\n",
|
||||
i, strlenW(type->type->str)+1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
type->name_offset = type->type->id;
|
||||
nb_id_types++;
|
||||
}
|
||||
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
if (name->name->str)
|
||||
{
|
||||
name->name_offset = offset | 0x80000000;
|
||||
offset += (strlenW(name->name->str)+1) * sizeof(unsigned short);
|
||||
fprintf( outfile, " unsigned short name_%d_%d_name[%d];\n",
|
||||
i, n, strlenW(name->name->str)+1 );
|
||||
}
|
||||
else name->name_offset = name->name->id;
|
||||
}
|
||||
}
|
||||
|
||||
/* resource directory contents */
|
||||
|
||||
fprintf( outfile, "} resources = {\n" );
|
||||
fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
|
||||
|
||||
/* dump the type directory */
|
||||
offset = RESDIR_SIZE( tree->nb_types );
|
||||
fprintf( outfile, " {\n" );
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
fprintf( outfile, " { 0x%08x, 0x%08x },\n", type->name_offset, offset | 0x80000000 );
|
||||
offset += RESDIR_SIZE( type->nb_names );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
offset += RESDIR_SIZE( name->nb_languages );
|
||||
}
|
||||
fprintf( outfile, " },\n" );
|
||||
|
||||
data_offset = offset;
|
||||
offset = RESDIR_SIZE( tree->nb_types );
|
||||
|
||||
/* dump the names and languages directories */
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
fprintf( outfile, " { 0, 0, 0, 0, %d, %d }, /* name_%d_dir */\n {\n",
|
||||
type->nb_names - type->nb_id_names, type->nb_id_names, i );
|
||||
offset += RESDIR_SIZE( type->nb_names );
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
fprintf( outfile, " { 0x%08x, 0x%08x },\n", name->name_offset, offset | 0x80000000 );
|
||||
offset += RESDIR_SIZE( name->nb_languages );
|
||||
}
|
||||
fprintf( outfile, " },\n" );
|
||||
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
fprintf( outfile, " { 0, 0, 0, 0, 0, %d }, /* lang_%d_%d_dir */\n {\n",
|
||||
name->nb_languages, i, n );
|
||||
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
|
||||
{
|
||||
fprintf( outfile, " { 0x%04x, 0x%08x },\n",
|
||||
res->lang, data_offset + (res - spec->resources) * 4 * sizeof(int) );
|
||||
}
|
||||
fprintf( outfile, " },\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* dump the resource data entries */
|
||||
fprintf( outfile, " {\n" );
|
||||
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
|
||||
{
|
||||
fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 }, /* %08x */\n", i, i,
|
||||
data_offset + i * 4 * sizeof(int) );
|
||||
}
|
||||
|
||||
/* dump the name strings */
|
||||
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
|
||||
{
|
||||
if (type->type->str)
|
||||
{
|
||||
fprintf( outfile, " },\n { " );
|
||||
output_string( outfile, type->type->str );
|
||||
}
|
||||
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
|
||||
{
|
||||
if (name->name->str)
|
||||
{
|
||||
fprintf( outfile, " },\n { " );
|
||||
output_string( outfile, name->name->str );
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf( outfile, " }\n};\n\n" );
|
||||
free_resource_tree( tree );
|
||||
}
|
832
reactos/tools/winebuild/spec16.c
Normal file
832
reactos/tools/winebuild/spec16.c
Normal file
|
@ -0,0 +1,832 @@
|
|||
/*
|
||||
* 16-bit spec files
|
||||
*
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1995, 1996, 1997 Alexandre Julliard
|
||||
* Copyright 1997 Eric Youngdale
|
||||
* Copyright 1999 Ulrich Weigand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "wine/exception.h"
|
||||
#include "stackframe.h"
|
||||
#include "builtin16.h"
|
||||
#include "module.h"
|
||||
|
||||
#include "build.h"
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* get_cs
|
||||
*/
|
||||
#ifdef __i386__
|
||||
static inline unsigned short get_cs(void)
|
||||
{
|
||||
unsigned short res;
|
||||
#ifdef __GNUC__
|
||||
__asm__("movw %%cs,%w0" : "=r"(res));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm { mov res, cs }
|
||||
#else
|
||||
res = 0;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
#endif /* __i386__ */
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* output_file_header
|
||||
*
|
||||
* Output a file header with the common declarations we need.
|
||||
*/
|
||||
static void output_file_header( FILE *outfile )
|
||||
{
|
||||
output_standard_file_header( outfile );
|
||||
fprintf( outfile, "extern struct\n{\n" );
|
||||
fprintf( outfile, " void *base[8192];\n" );
|
||||
fprintf( outfile, " unsigned long limit[8192];\n" );
|
||||
fprintf( outfile, " unsigned char flags[8192];\n" );
|
||||
fprintf( outfile, "} wine_ldt_copy;\n\n" );
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, "#define __stdcall __attribute__((__stdcall__))\n\n" );
|
||||
#else
|
||||
fprintf( outfile, "#define __stdcall\n\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* 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;
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp) continue;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ( !selector )
|
||||
continue;
|
||||
|
||||
if ( bundle && bundle->last+1 == i )
|
||||
bundle->last++;
|
||||
else
|
||||
{
|
||||
pstr = (char *)(((long)pstr + 1) & ~1);
|
||||
if ( bundle )
|
||||
bundle->next = (char *)pstr - (char *)pModule;
|
||||
|
||||
bundle = (ET_BUNDLE *)pstr;
|
||||
bundle->first = i-1;
|
||||
bundle->last = i;
|
||||
bundle->next = 0;
|
||||
pstr += sizeof(ET_BUNDLE);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
*pstr++ = 0;
|
||||
|
||||
/* Dump the module content */
|
||||
|
||||
pstr = (char *)(((long)pstr + 3) & ~3);
|
||||
dump_bytes( outfile, (char *)pModule, (int)pstr - (int)pModule, "Module", 0 );
|
||||
return (int)pstr - (int)pModule;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __i386__
|
||||
/*******************************************************************
|
||||
* BuildCallFrom16Func
|
||||
*
|
||||
* Build a 16-bit-to-Wine callback glue function.
|
||||
*
|
||||
* The generated routines are intended to be used as argument conversion
|
||||
* routines to be called by the CallFrom16... core. Thus, the prototypes of
|
||||
* the generated routines are (see also CallFrom16):
|
||||
*
|
||||
* extern WORD WINAPI PREFIX_CallFrom16_C_word_xxx( FARPROC func, LPBYTE args );
|
||||
* extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args );
|
||||
* extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args,
|
||||
* CONTEXT86 *context );
|
||||
*
|
||||
* where 'C' is the calling convention ('p' for pascal or 'c' for cdecl),
|
||||
* and each 'x' is an argument ('w'=word, 's'=signed word, 'l'=long,
|
||||
* 'p'=linear pointer, 't'=linear pointer to null-terminated string,
|
||||
* 'T'=segmented pointer to null-terminated string).
|
||||
*
|
||||
* The generated routines fetch the arguments from the 16-bit stack (pointed
|
||||
* to by 'args'); the offsets of the single argument values are computed
|
||||
* according to the calling convention and the argument types. Then, the
|
||||
* 32-bit entry point is called with these arguments.
|
||||
*
|
||||
* For register functions, the arguments (if present) are converted just
|
||||
* the same as for normal functions, but in addition the CONTEXT86 pointer
|
||||
* filled with the current register values is passed to the 32-bit routine.
|
||||
*/
|
||||
static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char *prefix )
|
||||
{
|
||||
int i, pos, argsize = 0;
|
||||
int short_ret = 0;
|
||||
int reg_func = 0;
|
||||
int usecdecl = 0;
|
||||
int varargs = 0;
|
||||
const char *args = profile + 7;
|
||||
const char *ret_type;
|
||||
|
||||
/* Parse function type */
|
||||
|
||||
if (!strncmp( "c_", profile, 2 )) usecdecl = 1;
|
||||
else if (!strncmp( "v_", profile, 2 )) varargs = usecdecl = 1;
|
||||
else if (strncmp( "p_", profile, 2 ))
|
||||
{
|
||||
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
|
||||
else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
|
||||
else if (strncmp( "long_", profile + 2, 5 ))
|
||||
{
|
||||
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
|
||||
return;
|
||||
}
|
||||
|
||||
for ( i = 0; args[i]; i++ )
|
||||
switch ( args[i] )
|
||||
{
|
||||
case 'w': /* word */
|
||||
case 's': /* s_word */
|
||||
argsize += 2;
|
||||
break;
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
argsize += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
ret_type = reg_func? "void" : short_ret ? "unsigned short" : "unsigned int";
|
||||
|
||||
fprintf( outfile, "typedef %s (%s*proc_%s_t)( ",
|
||||
ret_type, usecdecl ? "" : "__stdcall ", profile );
|
||||
args = profile + 7;
|
||||
for ( i = 0; args[i]; i++ )
|
||||
{
|
||||
if ( i ) fprintf( outfile, ", " );
|
||||
switch (args[i])
|
||||
{
|
||||
case 'w': fprintf( outfile, "unsigned short" ); break;
|
||||
case 's': fprintf( outfile, "short" ); break;
|
||||
case 'l': case 'T': fprintf( outfile, "unsigned int" ); break;
|
||||
case 'p': case 't': fprintf( outfile, "void *" ); break;
|
||||
}
|
||||
}
|
||||
if (reg_func || varargs)
|
||||
fprintf( outfile, "%svoid *", i? ", " : "" );
|
||||
else if ( !i )
|
||||
fprintf( outfile, "void" );
|
||||
fprintf( outfile, " );\n" );
|
||||
|
||||
fprintf( outfile, "static %s __stdcall __wine_%s_CallFrom16_%s( proc_%s_t proc, unsigned char *args%s )\n",
|
||||
ret_type, make_c_identifier(prefix), profile, profile,
|
||||
reg_func? ", void *context" : "" );
|
||||
|
||||
fprintf( outfile, "{\n %sproc(\n", reg_func ? "" : "return " );
|
||||
args = profile + 7;
|
||||
pos = !usecdecl? argsize : 0;
|
||||
for ( i = 0; args[i]; i++ )
|
||||
{
|
||||
if ( i ) fprintf( outfile, ",\n" );
|
||||
fprintf( outfile, " " );
|
||||
switch (args[i])
|
||||
{
|
||||
case 'w': /* word */
|
||||
if ( !usecdecl ) pos -= 2;
|
||||
fprintf( outfile, "*(unsigned short *)(args+%d)", pos );
|
||||
if ( usecdecl ) pos += 2;
|
||||
break;
|
||||
|
||||
case 's': /* s_word */
|
||||
if ( !usecdecl ) pos -= 2;
|
||||
fprintf( outfile, "*(short *)(args+%d)", pos );
|
||||
if ( usecdecl ) pos += 2;
|
||||
break;
|
||||
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
if ( !usecdecl ) pos -= 4;
|
||||
fprintf( outfile, "*(unsigned int *)(args+%d)", pos );
|
||||
if ( usecdecl ) pos += 4;
|
||||
break;
|
||||
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
if ( !usecdecl ) pos -= 4;
|
||||
fprintf( outfile, "((char*)wine_ldt_copy.base[*(unsigned short*)(args+%d) >> 3] + *(unsigned short*)(args+%d))",
|
||||
pos + 2, pos );
|
||||
if ( usecdecl ) pos += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf( stderr, "Unknown arg type '%c'\n", args[i] );
|
||||
}
|
||||
}
|
||||
if ( reg_func )
|
||||
fprintf( outfile, "%s context", i? ",\n" : "" );
|
||||
else if (varargs)
|
||||
fprintf( outfile, "%s args + %d", i? ",\n" : "", argsize );
|
||||
fprintf( outfile, " );\n}\n\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* get_function_name
|
||||
*/
|
||||
static const char *get_function_name( const ORDDEF *odp )
|
||||
{
|
||||
static char buffer[80];
|
||||
|
||||
sprintf( buffer, "%s_%s_%s",
|
||||
(odp->type == TYPE_PASCAL) ? "p" :
|
||||
(odp->type == TYPE_VARARGS) ? "v" : "c",
|
||||
(odp->flags & FLAG_REGISTER) ? "regs" :
|
||||
(odp->flags & FLAG_RET16) ? "word" : "long",
|
||||
odp->u.func.arg_types );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Spec16TypeCompare
|
||||
*/
|
||||
static int Spec16TypeCompare( const void *e1, const void *e2 )
|
||||
{
|
||||
const ORDDEF *odp1 = *(const ORDDEF * const *)e1;
|
||||
const ORDDEF *odp2 = *(const ORDDEF * const *)e2;
|
||||
int retval;
|
||||
int type1 = odp1->type;
|
||||
int type2 = odp2->type;
|
||||
|
||||
if (type1 == TYPE_STUB) type1 = TYPE_CDECL;
|
||||
if (type2 == TYPE_STUB) type2 = TYPE_CDECL;
|
||||
|
||||
if ((retval = type1 - type2) != 0) return retval;
|
||||
|
||||
type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER);
|
||||
type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER);
|
||||
|
||||
if ((retval = type1 - type2) != 0) return retval;
|
||||
|
||||
return strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* output_stub_funcs
|
||||
*
|
||||
* Output the functions for stub entry points
|
||||
*/
|
||||
static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
|
||||
fprintf( outfile, "#endif\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func )\n{\n" );
|
||||
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, " } rec;\n\n" );
|
||||
fprintf( outfile, " extern void __stdcall RtlRaiseException( struct exc_record * );\n\n" );
|
||||
fprintf( outfile, " rec.code = 0x%08x;\n", EXCEPTION_WINE_STUB );
|
||||
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
|
||||
fprintf( outfile, " rec.rec = 0;\n" );
|
||||
fprintf( outfile, " rec.params = 2;\n" );
|
||||
fprintf( outfile, " rec.info[0] = \"%s\";\n", spec->file_name );
|
||||
fprintf( outfile, " rec.info[1] = func;\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}\n\n" );
|
||||
break;
|
||||
}
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || odp->type != TYPE_STUB) continue;
|
||||
odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 );
|
||||
strcpy( odp->link_name, "__wine_stub_" );
|
||||
strcat( odp->link_name, odp->name );
|
||||
for (p = odp->link_name; *p; p++) if (!isalnum(*p)) *p = '_';
|
||||
fprintf( outfile, "static void %s(void) { __wine_unimplemented(\"%s\"); }\n",
|
||||
odp->link_name, odp->name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* BuildSpec16File
|
||||
*
|
||||
* Build a Win16 assembly file from a spec file.
|
||||
*/
|
||||
void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
ORDDEF **type, **typelist;
|
||||
int i, nFuncs, nTypes;
|
||||
int code_offset, data_offset, module_size, res_size;
|
||||
unsigned char *data;
|
||||
char constructor[100], destructor[100];
|
||||
#ifdef __i386__
|
||||
unsigned short code_selector = get_cs();
|
||||
#endif
|
||||
|
||||
/* File header */
|
||||
|
||||
output_file_header( outfile );
|
||||
fprintf( outfile, "extern unsigned short __wine_call_from_16_word();\n" );
|
||||
fprintf( outfile, "extern unsigned int __wine_call_from_16_long();\n" );
|
||||
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;
|
||||
|
||||
if (!spec->dll_name) /* set default name from file name */
|
||||
{
|
||||
char *p;
|
||||
spec->dll_name = xstrdup( spec->file_name );
|
||||
if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
|
||||
}
|
||||
|
||||
output_stub_funcs( outfile, spec );
|
||||
|
||||
/* Build sorted list of all argument types, without duplicates */
|
||||
|
||||
typelist = (ORDDEF **)calloc( spec->limit+1, sizeof(ORDDEF *) );
|
||||
|
||||
for (i = nFuncs = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp) continue;
|
||||
switch (odp->type)
|
||||
{
|
||||
case TYPE_CDECL:
|
||||
case TYPE_PASCAL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_STUB:
|
||||
typelist[nFuncs++] = odp;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qsort( typelist, nFuncs, sizeof(ORDDEF *), Spec16TypeCompare );
|
||||
|
||||
i = nTypes = 0;
|
||||
while ( i < nFuncs )
|
||||
{
|
||||
typelist[nTypes++] = typelist[i++];
|
||||
while ( i < nFuncs && Spec16TypeCompare( typelist + i, typelist + nTypes-1 ) == 0 )
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Output CallFrom16 routines needed by this .spec file */
|
||||
#ifdef __i386__
|
||||
for ( i = 0; i < nTypes; i++ )
|
||||
{
|
||||
char profile[101];
|
||||
|
||||
strcpy( profile, get_function_name( typelist[i] ));
|
||||
BuildCallFrom16Func( outfile, profile, spec->file_name );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Output the DLL functions prototypes */
|
||||
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp) continue;
|
||||
switch(odp->type)
|
||||
{
|
||||
case TYPE_CDECL:
|
||||
case TYPE_PASCAL:
|
||||
case TYPE_VARARGS:
|
||||
fprintf( outfile, "extern void %s();\n", odp->link_name );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output code segment */
|
||||
|
||||
fprintf( outfile, "\n#include \"pshpack1.h\"\n" );
|
||||
fprintf( outfile, "\nstatic struct code_segment\n{\n" );
|
||||
fprintf( outfile, " struct {\n" );
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $relay */
|
||||
fprintf( outfile, " void *relay;\n" );
|
||||
fprintf( outfile, " unsigned char lcall;\n" ); /* lcall __FLATCS__:glue */
|
||||
fprintf( outfile, " void *glue;\n" );
|
||||
fprintf( outfile, " unsigned short flatcs;\n" );
|
||||
#endif
|
||||
fprintf( outfile, " unsigned short lret;\n" ); /* lret $args */
|
||||
fprintf( outfile, " unsigned short args;\n" );
|
||||
fprintf( outfile, " unsigned int arg_types[2];\n" );
|
||||
fprintf( outfile, " } call[%d];\n", nTypes );
|
||||
fprintf( outfile, " struct {\n" );
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, " unsigned short pushw_bp;\n" ); /* pushw %bp */
|
||||
fprintf( outfile, " unsigned char pushl;\n" ); /* pushl $target */
|
||||
#endif
|
||||
fprintf( outfile, " void (*target)();\n" );
|
||||
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;
|
||||
|
||||
for ( i = 0; i < nTypes; i++ )
|
||||
{
|
||||
char profile[101], *arg;
|
||||
unsigned int arg_types[2];
|
||||
int j, argsize = 0;
|
||||
|
||||
strcpy( profile, get_function_name( typelist[i] ));
|
||||
if ( typelist[i]->type == TYPE_PASCAL )
|
||||
for ( arg = typelist[i]->u.func.arg_types; *arg; arg++ )
|
||||
switch ( *arg )
|
||||
{
|
||||
case 'w': /* word */
|
||||
case 's': /* s_word */
|
||||
argsize += 2;
|
||||
break;
|
||||
case 'l': /* long or segmented pointer */
|
||||
case 'T': /* segmented pointer to null-terminated string */
|
||||
case 'p': /* linear pointer */
|
||||
case 't': /* linear pointer to null-terminated string */
|
||||
argsize += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* build the arg types bit fields */
|
||||
arg_types[0] = arg_types[1] = 0;
|
||||
for (j = 0; typelist[i]->u.func.arg_types[j]; j++)
|
||||
{
|
||||
int type = 0;
|
||||
switch(typelist[i]->u.func.arg_types[j])
|
||||
{
|
||||
case 'w': type = ARG_WORD; break;
|
||||
case 's': type = ARG_SWORD; break;
|
||||
case 'l': type = ARG_LONG; break;
|
||||
case 'p': type = ARG_PTR; break;
|
||||
case 't': type = ARG_STR; break;
|
||||
case 'T': type = ARG_SEGSTR; break;
|
||||
}
|
||||
arg_types[j / 10] |= type << (3 * (j % 10));
|
||||
}
|
||||
if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
|
||||
if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
|
||||
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
|
||||
make_c_identifier(spec->file_name), profile,
|
||||
(typelist[i]->flags & FLAG_REGISTER) ? "regs":
|
||||
(typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
|
||||
if (argsize)
|
||||
fprintf( outfile, " 0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n",
|
||||
code_selector, argsize, arg_types[0], arg_types[1] );
|
||||
else
|
||||
fprintf( outfile, " 0x%04x, 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
|
||||
code_selector, arg_types[0], arg_types[1] );
|
||||
#else
|
||||
if (argsize)
|
||||
fprintf( outfile, " { 0xca66, %d, { 0x%08x, 0x%08x } },\n",
|
||||
argsize, arg_types[0], arg_types[1] );
|
||||
else
|
||||
fprintf( outfile, " { 0xcb66, 0x9090, { 0x%08x, 0x%08x } },\n",
|
||||
arg_types[0], arg_types[1] );
|
||||
#endif
|
||||
code_offset += sizeof(CALLFROM16);
|
||||
}
|
||||
fprintf( outfile, " },\n {\n" );
|
||||
|
||||
for (i = 0; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
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:
|
||||
case TYPE_STUB:
|
||||
type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
|
||||
assert( type );
|
||||
|
||||
fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
|
||||
#ifdef __i386__
|
||||
fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
|
||||
#else
|
||||
fprintf( outfile, "{ %s, 0xe866, %d, /* %s */ },\n",
|
||||
#endif
|
||||
odp->link_name,
|
||||
(type-typelist)*sizeof(CALLFROM16) -
|
||||
(code_offset + sizeof(ENTRYPOINT16)),
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( outfile, " }\n};\n" );
|
||||
|
||||
/* Output data segment */
|
||||
|
||||
dump_bytes( outfile, data, data_offset, "Data_Segment", 0 );
|
||||
|
||||
/* Build the module */
|
||||
|
||||
module_size = BuildModule16( outfile, code_offset, data_offset, spec );
|
||||
res_size = output_res16_data( outfile, spec );
|
||||
|
||||
/* Output the DLL descriptor */
|
||||
|
||||
fprintf( outfile, "#include \"poppack.h\"\n\n" );
|
||||
|
||||
fprintf( outfile, "static const struct dll_descriptor\n{\n" );
|
||||
fprintf( outfile, " unsigned char *module_start;\n" );
|
||||
fprintf( outfile, " int module_size;\n" );
|
||||
fprintf( outfile, " struct code_segment *code_start;\n" );
|
||||
fprintf( outfile, " unsigned char *data_start;\n" );
|
||||
fprintf( outfile, " const char *owner;\n" );
|
||||
fprintf( outfile, " const unsigned char *rsrc;\n" );
|
||||
fprintf( outfile, "} descriptor =\n{\n" );
|
||||
fprintf( outfile, " Module,\n" );
|
||||
fprintf( outfile, " sizeof(Module),\n" );
|
||||
fprintf( outfile, " &code_segment,\n" );
|
||||
fprintf( outfile, " Data_Segment,\n" );
|
||||
fprintf( outfile, " \"%s\",\n", spec->owner_name );
|
||||
fprintf( outfile, " %s\n", res_size ? "resource_data" : "0" );
|
||||
fprintf( outfile, "};\n" );
|
||||
|
||||
/* Output the DLL constructor */
|
||||
|
||||
sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
|
||||
sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
|
||||
output_dll_init( outfile, constructor, destructor );
|
||||
|
||||
fprintf( outfile,
|
||||
"void %s(void)\n"
|
||||
"{\n"
|
||||
" extern void __wine_register_dll_16( const struct dll_descriptor *descr );\n"
|
||||
" __wine_register_dll_16( &descriptor );\n"
|
||||
"}\n", constructor );
|
||||
fprintf( outfile,
|
||||
"void %s(void)\n"
|
||||
"{\n"
|
||||
" extern void __wine_unregister_dll_16( const struct dll_descriptor *descr );\n"
|
||||
" __wine_unregister_dll_16( &descriptor );\n"
|
||||
"}\n", destructor );
|
||||
}
|
1057
reactos/tools/winebuild/spec32.c
Normal file
1057
reactos/tools/winebuild/spec32.c
Normal file
File diff suppressed because it is too large
Load diff
415
reactos/tools/winebuild/utils.c
Normal file
415
reactos/tools/winebuild/utils.c
Normal file
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* Small utility functions for winebuild
|
||||
*
|
||||
* Copyright 2000 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(WIN32)
|
||||
#undef strdup
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "build.h"
|
||||
|
||||
void *xmalloc (size_t size)
|
||||
{
|
||||
void *res;
|
||||
|
||||
res = malloc (size ? size : 1);
|
||||
if (res == NULL)
|
||||
{
|
||||
fprintf (stderr, "Virtual memory exhausted.\n");
|
||||
exit (1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void *xrealloc (void *ptr, size_t size)
|
||||
{
|
||||
void *res = realloc (ptr, size);
|
||||
if (res == NULL)
|
||||
{
|
||||
fprintf (stderr, "Virtual memory exhausted.\n");
|
||||
exit (1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
char *xstrdup( const char *str )
|
||||
{
|
||||
char *res = strdup( str );
|
||||
if (!res)
|
||||
{
|
||||
fprintf (stderr, "Virtual memory exhausted.\n");
|
||||
exit (1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
char *strupper(char *s)
|
||||
{
|
||||
char *p;
|
||||
for (p = s; *p; p++) *p = toupper(*p);
|
||||
return s;
|
||||
}
|
||||
|
||||
void fatal_error( const char *msg, ... )
|
||||
{
|
||||
va_list valist;
|
||||
va_start( valist, msg );
|
||||
if (input_file_name)
|
||||
{
|
||||
fprintf( stderr, "%s:", input_file_name );
|
||||
if (current_line)
|
||||
fprintf( stderr, "%d:", current_line );
|
||||
fputc( ' ', stderr );
|
||||
}
|
||||
else fprintf( stderr, "winebuild: " );
|
||||
vfprintf( stderr, msg, valist );
|
||||
va_end( valist );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void fatal_perror( const char *msg, ... )
|
||||
{
|
||||
va_list valist;
|
||||
va_start( valist, msg );
|
||||
if (input_file_name)
|
||||
{
|
||||
fprintf( stderr, "%s:", input_file_name );
|
||||
if (current_line)
|
||||
fprintf( stderr, "%d:", current_line );
|
||||
fputc( ' ', stderr );
|
||||
}
|
||||
vfprintf( stderr, msg, valist );
|
||||
perror( " " );
|
||||
va_end( valist );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void error( const char *msg, ... )
|
||||
{
|
||||
va_list valist;
|
||||
va_start( valist, msg );
|
||||
if (input_file_name)
|
||||
{
|
||||
fprintf( stderr, "%s:", input_file_name );
|
||||
if (current_line)
|
||||
fprintf( stderr, "%d:", current_line );
|
||||
fputc( ' ', stderr );
|
||||
}
|
||||
vfprintf( stderr, msg, valist );
|
||||
va_end( valist );
|
||||
nb_errors++;
|
||||
}
|
||||
|
||||
void warning( const char *msg, ... )
|
||||
{
|
||||
va_list valist;
|
||||
|
||||
if (!display_warnings) return;
|
||||
va_start( valist, msg );
|
||||
if (input_file_name)
|
||||
{
|
||||
fprintf( stderr, "%s:", input_file_name );
|
||||
if (current_line)
|
||||
fprintf( stderr, "%d:", current_line );
|
||||
fputc( ' ', stderr );
|
||||
}
|
||||
fprintf( stderr, "warning: " );
|
||||
vfprintf( stderr, msg, valist );
|
||||
va_end( valist );
|
||||
}
|
||||
|
||||
/* output a standard header for generated files */
|
||||
void output_standard_file_header( FILE *outfile )
|
||||
{
|
||||
if (input_file_name)
|
||||
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n",
|
||||
input_file_name );
|
||||
else
|
||||
fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
|
||||
fprintf( outfile,
|
||||
"/* This file can be copied, modified and distributed without restriction. */\n\n" );
|
||||
}
|
||||
|
||||
/* dump a byte stream into the assembly code */
|
||||
void dump_bytes( FILE *outfile, const unsigned char *data, int len,
|
||||
const char *label, int constant )
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf( outfile, "\nstatic %sunsigned char %s[%d] = {",
|
||||
constant ? "const " : "", label, len );
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (!(i & 7)) fprintf( outfile, "\n " );
|
||||
fprintf( outfile, "0x%02x", *data++ );
|
||||
if (i < len - 1) fprintf( outfile, "," );
|
||||
}
|
||||
fprintf( outfile, "\n};\n" );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* open_input_file
|
||||
*
|
||||
* Open a file in the given srcdir and set the input_file_name global variable.
|
||||
*/
|
||||
FILE *open_input_file( const char *srcdir, const char *name )
|
||||
{
|
||||
char *fullname;
|
||||
FILE *file = fopen( name, "r" );
|
||||
|
||||
if (!file && srcdir)
|
||||
{
|
||||
fullname = xmalloc( strlen(srcdir) + strlen(name) + 2 );
|
||||
strcpy( fullname, srcdir );
|
||||
strcat( fullname, "/" );
|
||||
strcat( fullname, name );
|
||||
file = fopen( fullname, "r" );
|
||||
}
|
||||
else fullname = xstrdup( name );
|
||||
|
||||
if (!file) fatal_error( "Cannot open file '%s'\n", fullname );
|
||||
input_file_name = fullname;
|
||||
current_line = 1;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* close_input_file
|
||||
*
|
||||
* Close the current input file (must have been opened with open_input_file).
|
||||
*/
|
||||
void close_input_file( FILE *file )
|
||||
{
|
||||
fclose( file );
|
||||
free( input_file_name );
|
||||
input_file_name = NULL;
|
||||
current_line = 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* remove_stdcall_decoration
|
||||
*
|
||||
* Remove a possible @xx suffix from a function name.
|
||||
* Return the numerical value of the suffix, or -1 if none.
|
||||
*/
|
||||
int remove_stdcall_decoration( char *name )
|
||||
{
|
||||
char *p, *end = strrchr( name, '@' );
|
||||
if (!end || !end[1] || end == name) return -1;
|
||||
/* make sure all the rest is digits */
|
||||
for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1;
|
||||
*end = 0;
|
||||
return atoi( end + 1 );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* alloc_dll_spec
|
||||
*
|
||||
* Create a new dll spec file descriptor
|
||||
*/
|
||||
DLLSPEC *alloc_dll_spec(void)
|
||||
{
|
||||
DLLSPEC *spec;
|
||||
|
||||
spec = xmalloc( sizeof(*spec) );
|
||||
spec->file_name = NULL;
|
||||
spec->dll_name = NULL;
|
||||
spec->owner_name = NULL;
|
||||
spec->init_func = NULL;
|
||||
spec->type = SPEC_WIN32;
|
||||
spec->base = MAX_ORDINALS;
|
||||
spec->limit = 0;
|
||||
spec->stack_size = 0;
|
||||
spec->heap_size = 0;
|
||||
spec->nb_entry_points = 0;
|
||||
spec->alloc_entry_points = 0;
|
||||
spec->nb_names = 0;
|
||||
spec->nb_resources = 0;
|
||||
spec->characteristics = 0;
|
||||
spec->subsystem = 0;
|
||||
spec->subsystem_major = 4;
|
||||
spec->subsystem_minor = 0;
|
||||
spec->entry_points = NULL;
|
||||
spec->names = NULL;
|
||||
spec->ordinals = NULL;
|
||||
spec->resources = NULL;
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* free_dll_spec
|
||||
*
|
||||
* Free dll spec file descriptor
|
||||
*/
|
||||
void free_dll_spec( DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
free( odp->name );
|
||||
free( odp->export_name );
|
||||
free( odp->link_name );
|
||||
}
|
||||
free( spec->file_name );
|
||||
free( spec->dll_name );
|
||||
free( spec->owner_name );
|
||||
free( spec->init_func );
|
||||
free( spec->entry_points );
|
||||
free( spec->names );
|
||||
free( spec->ordinals );
|
||||
free( spec->resources );
|
||||
free( spec );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* make_c_identifier
|
||||
*
|
||||
* Map a string to a valid C identifier.
|
||||
*/
|
||||
const char *make_c_identifier( const char *str )
|
||||
{
|
||||
static char buffer[256];
|
||||
char *p;
|
||||
|
||||
for (p = buffer; *str && p < buffer+sizeof(buffer)-1; p++, str++)
|
||||
{
|
||||
if (isalnum(*str)) *p = *str;
|
||||
else *p = '_';
|
||||
}
|
||||
*p = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Function: get_alignment
|
||||
*
|
||||
* Description:
|
||||
* According to the info page for gas, the .align directive behaves
|
||||
* differently on different systems. On some architectures, the
|
||||
* argument of a .align directive is the number of bytes to pad to, so
|
||||
* to align on an 8-byte boundary you'd say
|
||||
* .align 8
|
||||
* On other systems, the argument is "the number of low-order zero bits
|
||||
* that the location counter must have after advancement." So to
|
||||
* align on an 8-byte boundary you'd say
|
||||
* .align 3
|
||||
*
|
||||
* The reason gas is written this way is that it's trying to mimick
|
||||
* native assemblers for the various architectures it runs on. gas
|
||||
* provides other directives that work consistantly across
|
||||
* architectures, but of course we want to work on all arches with or
|
||||
* without gas. Hence this function.
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* alignBoundary -- the number of bytes to align to.
|
||||
* If we're on an architecture where
|
||||
* the assembler requires a 'number
|
||||
* of low-order zero bits' as a
|
||||
* .align argument, then this number
|
||||
* must be a power of 2.
|
||||
*
|
||||
*/
|
||||
int get_alignment(int alignBoundary)
|
||||
{
|
||||
#if defined(__powerpc__) || defined(__ALPHA__)
|
||||
|
||||
int n = 0;
|
||||
|
||||
switch(alignBoundary)
|
||||
{
|
||||
case 2:
|
||||
n = 1;
|
||||
break;
|
||||
case 4:
|
||||
n = 2;
|
||||
break;
|
||||
case 8:
|
||||
n = 3;
|
||||
break;
|
||||
case 16:
|
||||
n = 4;
|
||||
break;
|
||||
case 32:
|
||||
n = 5;
|
||||
break;
|
||||
case 64:
|
||||
n = 6;
|
||||
break;
|
||||
case 128:
|
||||
n = 7;
|
||||
break;
|
||||
case 256:
|
||||
n = 8;
|
||||
break;
|
||||
case 512:
|
||||
n = 9;
|
||||
break;
|
||||
case 1024:
|
||||
n = 10;
|
||||
break;
|
||||
case 2048:
|
||||
n = 11;
|
||||
break;
|
||||
case 4096:
|
||||
n = 12;
|
||||
break;
|
||||
case 8192:
|
||||
n = 13;
|
||||
break;
|
||||
case 16384:
|
||||
n = 14;
|
||||
break;
|
||||
case 32768:
|
||||
n = 15;
|
||||
break;
|
||||
case 65536:
|
||||
n = 16;
|
||||
break;
|
||||
default:
|
||||
fatal_error("Alignment to %d-byte boundary not supported on this architecture.\n",
|
||||
alignBoundary);
|
||||
}
|
||||
return n;
|
||||
|
||||
#elif defined(__i386__) || defined(__sparc__)
|
||||
|
||||
return alignBoundary;
|
||||
|
||||
#else
|
||||
#error "How does the '.align' assembler directive work on your architecture?"
|
||||
#endif
|
||||
}
|
434
reactos/tools/winebuild/winebuild.man.in
Normal file
434
reactos/tools/winebuild/winebuild.man.in
Normal file
|
@ -0,0 +1,434 @@
|
|||
.\" -*- nroff -*-
|
||||
.TH WINEBUILD 1 "March 2003" "@PACKAGE_STRING@" "Wine dll builder"
|
||||
.SH NAME
|
||||
winebuild \- Wine dll builder
|
||||
.SH SYNOPSIS
|
||||
.BI winebuild\ [options]\ [input\ files]
|
||||
.SH DESCRIPTION
|
||||
.B winebuild
|
||||
generates the C and assembly files that are necessary to build a Wine
|
||||
dll, which is basically a Win32 dll encapsulated inside a Unix
|
||||
library.
|
||||
.PP
|
||||
.B winebuild
|
||||
has different modes, depending on what kind of file it is asked to
|
||||
generate. The mode is specified by one of the mode options specified
|
||||
below. In addition to the mode option, various other command-line
|
||||
option can be specified, as described in the \fBOPTIONS\fR section.
|
||||
.SH "MODE OPTIONS"
|
||||
You have to specify exactly one of the following options, depending on
|
||||
what you want winebuild to generate.
|
||||
.TP
|
||||
.BI \--dll= filename
|
||||
Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for
|
||||
details), or from a standard Windows .def file. The resulting C file
|
||||
must be compiled and linked to the other object files to build a
|
||||
working Wine dll.
|
||||
.br
|
||||
In that mode, the
|
||||
.I input files
|
||||
should be the list of all object files that will be linked into the
|
||||
final dll, to allow
|
||||
.B winebuild
|
||||
to get the list of all undefined symbols that need to be imported from
|
||||
other dlls.
|
||||
.TP
|
||||
.BI \--exe= name
|
||||
Build a C file for the named executable. This is basically the same as
|
||||
the --dll mode except that it doesn't require a .spec file as input,
|
||||
since an executable doesn't export functions. The resulting C file
|
||||
must be compiled and linked to the other object files to build a
|
||||
working Wine executable, and all the other object files must be listed
|
||||
as
|
||||
.I input files.
|
||||
.TP
|
||||
.BI \--def= file.spec
|
||||
Build a .def file from a spec file. This is used when building dlls
|
||||
with a PE (Win32) compiler.
|
||||
.TP
|
||||
.B \--debug
|
||||
Build a C file containing the definitions for debugging channels. In
|
||||
that mode the
|
||||
.I input files
|
||||
should be a list of C files to search for debug channel
|
||||
definitions. The resulting C file must be compiled and linked with the
|
||||
dll.
|
||||
.TP
|
||||
.B \--relay16
|
||||
Generate the assembly code for the 16-bit relay routines. This is for
|
||||
Wine internal usage only, you should never need to use this option.
|
||||
.TP
|
||||
.B \--relay32
|
||||
Generate the assembly code for the 32-bit relay routines. This is for
|
||||
Wine internal usage only, you should never need to use this option.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \-C,\ --source-dir= directory
|
||||
Change to the specified directory before reading source files. Only
|
||||
meaningful in
|
||||
.BR \--debug\ mode.
|
||||
.TP
|
||||
.BI \-D\ symbol
|
||||
Ignored for compatibility with the C compiler.
|
||||
.TP
|
||||
.BI \-e,\ --entry= function
|
||||
Specify the module entry point function; if not specified, the default
|
||||
is
|
||||
.B DllMain
|
||||
for dlls, and
|
||||
.B WinMain
|
||||
for executables (if
|
||||
.B WinMain
|
||||
is not defined, the standard C
|
||||
.B main
|
||||
is used instead). This is only valid for Win32 modules.
|
||||
.TP
|
||||
.BI \-f\ flags
|
||||
Ignored for compatibility with the C compiler.
|
||||
.TP
|
||||
.BI \-F,\ --filename= filename
|
||||
Set the file name of the module. The default is to use the base name
|
||||
of the spec file (without any extension).
|
||||
.TP
|
||||
.B \-h, --help
|
||||
Display a usage message and exit.
|
||||
.TP
|
||||
.BI \-H,\ --heap= size
|
||||
Specify the size of the module local heap in bytes (only valid for
|
||||
Win16 modules); default is no local heap.
|
||||
.TP
|
||||
.BI \-i,\ --ignore= [-]symbol[,[-]symbol]
|
||||
Specify a list of symbols that should be ignored when resolving
|
||||
undefined symbols against the imported libraries. This forces these
|
||||
symbols to be resolved from the Unix C library (or from another Unix
|
||||
library linked with the application). If a symbol is prefixed by '-'
|
||||
it is removed from the list instead of being added; a stand-alone '-'
|
||||
clears the whole list.
|
||||
.TP
|
||||
.BI \-I\ directory
|
||||
Ignored for compatibility with the C compiler.
|
||||
.TP
|
||||
.B \-k, --kill-at
|
||||
Remove the stdcall decorations from the symbol names in the
|
||||
generated .def file. Only meaningful in \fB--def\fR mode.
|
||||
.TP
|
||||
.BI \-K\ flags
|
||||
Ignored for compatibility with the C compiler.
|
||||
.TP
|
||||
.BI \--ld-cmd= ld-command
|
||||
Specify the command to use to link the object files; the default is
|
||||
\fBld\fR.
|
||||
.TP
|
||||
.BI \--nm-cmd= nm-command
|
||||
Specify the command to use to get the list of undefined symbols; the
|
||||
default is \fBnm\fR.
|
||||
.TP
|
||||
.BI \-L,\ --library-path= directory
|
||||
Append the specified directory to the list of directories that are
|
||||
searched for import libraries.
|
||||
.TP
|
||||
.BI \-l,\ --library= name
|
||||
Import the specified library, looking for a corresponding
|
||||
\fIlibname.def\fR file in the directories specified with the \fB-L\fR
|
||||
option.
|
||||
.TP
|
||||
.BI \-d,\ --delay-lib= name
|
||||
Same as the \fB-l\fR option, but import the specified library in
|
||||
delayed mode (i.e. the library won't be loaded until a function
|
||||
imported from it is actually called).
|
||||
.TP
|
||||
.BI \-M,\ --main-module= module
|
||||
Specify that we are building a 16-bit dll, that will ultimately be
|
||||
linked together with the 32-bit dll specified in \fImodule\fR. Only
|
||||
meaningful in \fB--dll\fR mode.
|
||||
.TP
|
||||
.BI \-N,\ --dll-name= dllname
|
||||
Set the internal name of the module. It is only used in Win16
|
||||
modules. The default is to use the base name of the spec file (without
|
||||
any extension). This is used for KERNEL, since it lives in
|
||||
KRNL386.EXE. It shouldn't be needed otherwise.
|
||||
.TP
|
||||
.BI \-o,\ --output= file
|
||||
Set the name of the output file (default is standard output).
|
||||
.TP
|
||||
.BI \-r,\ --res= rsrc.res
|
||||
Load resources from the specified binary resource file. The
|
||||
\fIrsrc.res\fR can be produced from a source resource file with
|
||||
.BR wrc(1)
|
||||
(or with a Windows resource compiler).
|
||||
.br
|
||||
This option is only necessary for Win16 resource files, the Win32 ones
|
||||
can simply listed as
|
||||
.I input files
|
||||
and will automatically be handled correctly (though the
|
||||
.B \-r
|
||||
option will also work for Win32 files).
|
||||
.TP
|
||||
.BI --subsystem= subsystem[:major[.minor]]
|
||||
Set the subsystem of the executable, which can be one of the following:
|
||||
.br
|
||||
.B console
|
||||
for a command line executable,
|
||||
.br
|
||||
.B windows
|
||||
for a graphical executable,
|
||||
.br
|
||||
.B native
|
||||
for a native-mode dll.
|
||||
.br
|
||||
The entry point of a command line executable is a normal C \fBmain\fR
|
||||
function. A \fBwmain\fR function can be used instead if you need the
|
||||
argument array to use Unicode strings. A graphical executable has a
|
||||
\fBWinMain\fR entry point.
|
||||
.br
|
||||
Optionally a major and minor subsystem version can also be specified;
|
||||
the default subsystem version is 4.0.
|
||||
.TP
|
||||
.B \--version
|
||||
Display the program version and exit.
|
||||
.TP
|
||||
.B \-w, --warnings
|
||||
Turn on warnings.
|
||||
.SH "SPEC FILE SYNTAX"
|
||||
.SS "General syntax"
|
||||
A spec file should contain a list of ordinal declarations. The general
|
||||
syntax is the following:
|
||||
.PP
|
||||
.I ordinal functype
|
||||
.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB) \ [ handler ]
|
||||
.br
|
||||
.IB ordinal\ variable
|
||||
.RI [ flags ]\ exportname \ \fB(\fR\ [ data... ] \ \fB)
|
||||
.br
|
||||
.IB ordinal\ extern
|
||||
.RI [ flags ]\ exportname \ [ symbolname ]
|
||||
.br
|
||||
.IB ordinal\ stub
|
||||
.RI [ flags ]\ exportname
|
||||
.br
|
||||
.IB ordinal\ equate
|
||||
.RI [ flags ]\ exportname\ data
|
||||
.br
|
||||
.BI #\ comments
|
||||
.PP
|
||||
Declarations must fit on a single line, except if the end of line is
|
||||
escaped using a backslash character. The
|
||||
.B #
|
||||
character anywhere in a line causes the rest of the line to be ignored
|
||||
as a comment.
|
||||
.PP
|
||||
.I ordinal
|
||||
specifies the ordinal number corresponding to the entry point, or '@'
|
||||
for automatic ordinal allocation (Win32 only).
|
||||
.PP
|
||||
.I flags
|
||||
is a series of optional flags, preceded by a '-' character. The
|
||||
supported flags are:
|
||||
.RS
|
||||
.TP
|
||||
.B -norelay
|
||||
The entry point is not displayed in relay debugging traces (Win32
|
||||
only).
|
||||
.TP
|
||||
.B -noname
|
||||
The entry point will be imported by ordinal instead of by name.
|
||||
.TP
|
||||
.B -ret16
|
||||
The function returns a 16-bit value (Win16 only).
|
||||
.TP
|
||||
.B -ret64
|
||||
The function returns a 64-bit value (Win32 only).
|
||||
.TP
|
||||
.B -i386
|
||||
The entry point is only available on i386 platforms.
|
||||
.TP
|
||||
.B -register
|
||||
The function uses CPU register to pass arguments.
|
||||
.TP
|
||||
.B -private
|
||||
The function cannot be imported from other dlls, it can only be
|
||||
accessed through GetProcAddress.
|
||||
.SS "Function ordinals"
|
||||
Syntax:
|
||||
.br
|
||||
.I ordinal functype
|
||||
.RI [ flags ]\ exportname \ \fB(\fR\ [ args... ] \ \fB) \ [ handler ]
|
||||
.br
|
||||
|
||||
This declaration defines a function entry point. The prototype defined by
|
||||
.IR exportname \ \fB(\fR\ [ args... ] \ \fB)
|
||||
specifies the name available for dynamic linking and the format of the
|
||||
arguments. '@' can be used instead of
|
||||
.I exportname
|
||||
for ordinal-only exports.
|
||||
.PP
|
||||
.I functype
|
||||
should be one of:
|
||||
.RS
|
||||
.TP
|
||||
.B stdcall
|
||||
for a normal Win32 function
|
||||
.TP
|
||||
.B pascal
|
||||
for a normal Win16 function
|
||||
.TP
|
||||
.B cdecl
|
||||
for a Win16 or Win32 function using the C calling convention
|
||||
.TP
|
||||
.B varargs
|
||||
for a Win16 or Win32 function using the C calling convention with a
|
||||
variable number of arguments
|
||||
.RE
|
||||
.PP
|
||||
.I args
|
||||
should be one or several of:
|
||||
.RS
|
||||
.TP
|
||||
.B word
|
||||
(16-bit unsigned value)
|
||||
.TP
|
||||
.B s_word
|
||||
(16-bit signed word)
|
||||
.TP
|
||||
.B long
|
||||
(32-bit value)
|
||||
.TP
|
||||
.B double
|
||||
(64-bit value)
|
||||
.TP
|
||||
.B ptr
|
||||
(linear pointer)
|
||||
.TP
|
||||
.B str
|
||||
(linear pointer to a null-terminated ASCII string)
|
||||
.TP
|
||||
.B wstr
|
||||
(linear pointer to a null-terminated Unicode string)
|
||||
.TP
|
||||
.B segptr
|
||||
(segmented pointer)
|
||||
.TP
|
||||
.B segstr
|
||||
(segmented pointer to a null-terminated ASCII string).
|
||||
.HP
|
||||
.RB Only\ ptr ,\ str ,\ wstr ,\ long\ and\ double
|
||||
are valid for Win32 functions.
|
||||
.RE
|
||||
.PP
|
||||
.I handler
|
||||
is the name of the actual C function that will implement that entry
|
||||
point in 32-bit mode. The handler can also be specified as
|
||||
.IB dllname . function
|
||||
to define a forwarded function (one whose implementation is in another
|
||||
dll). If
|
||||
.I handler
|
||||
is not specified, it is assumed to be identical to
|
||||
.I exportname.
|
||||
.PP
|
||||
This first example defines an entry point for the 32-bit GetFocus()
|
||||
call:
|
||||
.IP
|
||||
@ stdcall GetFocus() GetFocus
|
||||
.PP
|
||||
This second example defines an entry point for the 16-bit
|
||||
CreateWindow() call (the ordinal 100 is just an example); it also
|
||||
shows how long lines can be split using a backslash:
|
||||
.IP
|
||||
100 pascal CreateWindow(ptr ptr long s_word s_word s_word \\
|
||||
s_word word word word ptr) WIN_CreateWindow
|
||||
.PP
|
||||
To declare a function using a variable number of arguments, specify
|
||||
the function as
|
||||
.B varargs
|
||||
and declare it in the C file with a '...' parameter for a Win32
|
||||
function, or with an extra VA_LIST16 argument for a Win16 function.
|
||||
See the wsprintf* functions in user.exe.spec and user32.spec for an
|
||||
example.
|
||||
.SS "Variable ordinals"
|
||||
Syntax:
|
||||
.br
|
||||
.IB ordinal\ variable
|
||||
.RI [ flags ]\ exportname \ \fB(\fR\ [ data... ] \ \fB)
|
||||
.PP
|
||||
This declaration defines data storage as 32-bit words at the ordinal
|
||||
specified.
|
||||
.I exportname
|
||||
will be the name available for dynamic
|
||||
linking.
|
||||
.I data
|
||||
can be a decimal number or a hex number preceeded by "0x". The
|
||||
following example defines the variable VariableA at ordinal 2 and
|
||||
containing 4 ints:
|
||||
.IP
|
||||
2 variable VariableA(-1 0xff 0 0)
|
||||
.PP
|
||||
This declaration only works in Win16 spec files. In Win32 you should
|
||||
use
|
||||
.B extern
|
||||
instead (see below).
|
||||
.SS "Extern ordinals"
|
||||
Syntax:
|
||||
.br
|
||||
.IB ordinal\ extern
|
||||
.RI [ flags ]\ exportname \ [ symbolname ]
|
||||
.PP
|
||||
This declaration defines an entry that simply maps to a C symbol
|
||||
(variable or function). It only works in Win32 spec files.
|
||||
.I exportname
|
||||
will point to the symbol
|
||||
.I symbolname
|
||||
that must be defined in the C code. Alternatively, it can be of the
|
||||
form
|
||||
.IB dllname . symbolname
|
||||
to define a forwarded symbol (one whose implementation is in another
|
||||
dll). If
|
||||
.I symbolname
|
||||
is not specified, it is assumed to be identical to
|
||||
.I exportname.
|
||||
.SS "Stub ordinals"
|
||||
Syntax:
|
||||
.br
|
||||
.IB ordinal\ stub
|
||||
.RI [ flags ]\ exportname
|
||||
.PP
|
||||
This declaration defines a stub function. It makes the name and
|
||||
ordinal available for dynamic linking, but will terminate execution
|
||||
with an error message if the function is ever called.
|
||||
.SS "Equate ordinals"
|
||||
Syntax:
|
||||
.br
|
||||
.IB ordinal\ equate
|
||||
.RI [ flags ]\ exportname\ data
|
||||
.PP
|
||||
This declaration defines an ordinal as an absolute value.
|
||||
.I exportname
|
||||
will be the name available for dynamic linking.
|
||||
.I data
|
||||
can be a decimal number or a hex number preceeded by "0x".
|
||||
.SH AUTHORS
|
||||
.B winebuild
|
||||
has been worked on by many people over the years. The main authors are
|
||||
Robert J. Amstadt, Alexandre Julliard, Martin von Loewis, Ulrich
|
||||
Weigand and Eric Youngdale. Many other Wine developers have
|
||||
contributed, please check the file Changelog in the Wine distribution
|
||||
for the complete details.
|
||||
.SH BUGS
|
||||
It is not yet possible to use a PE-format dll in an import
|
||||
specification; only Wine dlls can be imported.
|
||||
.PP
|
||||
If you find a bug, please submit a bug report at
|
||||
.UR http://bugs.winehq.org
|
||||
.B http://bugs.winehq.org.
|
||||
.UE
|
||||
.SH AVAILABILITY
|
||||
.B winebuild
|
||||
is part of the wine distribution, which is available through WineHQ,
|
||||
the
|
||||
.B wine
|
||||
development headquarters, at
|
||||
.UR http://www.winehq.org/
|
||||
.B http://www.winehq.org/.
|
||||
.UE
|
||||
.SH "SEE ALSO"
|
||||
.BR wine (1),
|
||||
.BR wrc (1).
|
31
reactos/tools/winebuild/winglue.h
Normal file
31
reactos/tools/winebuild/winglue.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _WINGLUE_H
|
||||
#define _WINGLUE_H
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
#define LOBYTE(w) ((BYTE)(w))
|
||||
#define HIBYTE(w) ((BYTE)(((WORD)(w)>>8)&0xFF))
|
||||
|
||||
#define DLL_PROCESS_ATTACH 1
|
||||
#define DLL_PROCESS_DETACH 0
|
||||
|
||||
#define IMAGE_FILE_DLL 8192
|
||||
#define IMAGE_SUBSYSTEM_NATIVE 1
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
#define IMAGE_FILE_MACHINE_I386 332
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
#ifndef min
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#endif /* _WINGLUE_H */
|
Loading…
Reference in a new issue