New loading scheme for Winelib apps, makes them behave like builtin

dlls and takes load order into account. Install them in dlldir.
Improved MODULE_GetBinaryType to recognize ELF binaries.
Added a wrapper script to setup the environment when running directly
from inside the source tree.
This commit is contained in:
Alexandre Julliard 2002-05-22 21:32:49 +00:00
parent df234a9f9f
commit 3536316a31
26 changed files with 993 additions and 823 deletions

View File

@ -4,4 +4,3 @@ autom4te.cache
config.cache config.cache
config.log config.log
config.status config.status
wine

View File

@ -68,6 +68,7 @@ LINTFLAGS = @LINTFLAGS@
ALLLINTFLAGS = $(LINTFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL) ALLLINTFLAGS = $(LINTFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL)
MKINSTALLDIRS= $(TOPSRCDIR)/tools/mkinstalldirs MKINSTALLDIRS= $(TOPSRCDIR)/tools/mkinstalldirs
WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check
WINEWRAPPER = $(TOPSRCDIR)/tools/winewrapper
WINEBUILD = $(TOOLSDIR)/tools/winebuild/winebuild WINEBUILD = $(TOOLSDIR)/tools/winebuild/winebuild
MAKEDEP = $(TOOLSDIR)/tools/makedep MAKEDEP = $(TOOLSDIR)/tools/makedep
WRC = $(TOOLSDIR)/tools/wrc/wrc WRC = $(TOOLSDIR)/tools/wrc/wrc
@ -79,11 +80,11 @@ LIBTSX11 = -L$(TOPOBJDIR)/tsx11 -lwine_tsx11
LIBUNICODE= -L$(TOPOBJDIR)/unicode -lwine_unicode LIBUNICODE= -L$(TOPOBJDIR)/unicode -lwine_unicode
LIBUUID = -L$(TOPOBJDIR)/ole -lwine_uuid LIBUUID = -L$(TOPOBJDIR)/ole -lwine_uuid
WINETEST = $(TOPOBJDIR)/programs/winetest/winetest WINETEST = $(TOPOBJDIR)/programs/winetest/winetest.exe$(DLLEXT)
RUNTEST = $(TOPSRCDIR)/programs/winetest/runtest RUNTEST = $(TOPSRCDIR)/programs/winetest/runtest
RUNTESTFLAGS = -q -P wine -M $(MODULE) -T $(TOPOBJDIR) RUNTESTFLAGS = -q -P wine -M $(MODULE) -T $(TOPOBJDIR)
TESTRESULTS = $(PLTESTS:.pl=.ok) $(CTESTS:.c=.ok) TESTRESULTS = $(PLTESTS:.pl=.ok) $(CTESTS:.c=.ok)
TESTPROGRAM = tests/$(MODULE:%.dll=%)_test TESTPROGRAM = tests/$(MODULE:%.dll=%)_test.exe
TESTLIST = tests/testlist.c TESTLIST = tests/testlist.c
TESTOBJS = $(TESTMAIN) $(TESTLIST:.c=.o) $(CTESTS:.c=.o) TESTOBJS = $(TESTMAIN) $(TESTLIST:.c=.o) $(CTESTS:.c=.o)
TESTMAIN = $(TOPOBJDIR)/programs/winetest/wtmain.o TESTMAIN = $(TOPOBJDIR)/programs/winetest/wtmain.o
@ -150,7 +151,7 @@ LINTS = $(C_SRCS:.c=.ln)
$(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 ) $(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 )
.c.ok: .c.ok:
$(RUNTEST) $(RUNTESTFLAGS) -p $(TESTPROGRAM) $< && touch $@ $(RUNTEST) $(RUNTESTFLAGS) -p $(TESTPROGRAM)$(DLLEXT) $< && touch $@
.pl.ok: .pl.ok:
$(RUNTEST) $(RUNTESTFLAGS) $< && touch $@ $(RUNTEST) $(RUNTESTFLAGS) $< && touch $@
@ -256,7 +257,7 @@ testclean:: $(SUBDIRS:%=%/__testclean__)
$(RM) $(TESTRESULTS) $(RM) $(TESTRESULTS)
clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__) clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__)
$(RM) $(CLEAN_FILES) $(GEN_C_SRCS) $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(TESTRESULTS) $(TESTLIST) $(TESTPROGRAM)$(EXEEXT) $(PROGRAMS) $(RM) $(CLEAN_FILES) $(GEN_C_SRCS) $(GEN_ASM_SRCS) $(RC_SRCS:.rc=.res) $(RC_SRCS16:.rc=.res) $(MC_SRCS:.mc=.mc.rc) $(TESTRESULTS) $(TESTLIST) $(TESTPROGRAM) $(PROGRAMS)
# Rules for installing # Rules for installing
@ -274,10 +275,10 @@ $(SUBDIRS:%=%/__test__): dummy
@cd `dirname $@` && $(MAKE) test @cd `dirname $@` && $(MAKE) test
$(PLTESTS:.c=.ok): $(WINETEST) $(PLTESTS:.c=.ok): $(WINETEST)
$(CTESTS:.c=.ok): $(TESTPROGRAM)$(EXEEXT) $(CTESTS:.c=.ok): $(TESTPROGRAM)$(DLLEXT)
$(WINETEST): $(WINETEST):
cd $(TOPOBJDIR)/programs/winetest && $(MAKE) winetest cd $(TOPOBJDIR)/programs/winetest && $(MAKE) winetest.exe$(DLLEXT)
$(TESTMAIN): $(TESTMAIN):
cd $(TOPOBJDIR)/programs/winetest && $(MAKE) wtmain.o cd $(TOPOBJDIR)/programs/winetest && $(MAKE) wtmain.o
@ -285,20 +286,17 @@ $(TESTMAIN):
$(TESTLIST): Makefile.in $(TESTLIST): Makefile.in
$(TOPSRCDIR)/programs/winetest/make_ctests $(CTESTS) >$(TESTLIST) || $(RM) $(TESTLIST) $(TOPSRCDIR)/programs/winetest/make_ctests $(CTESTS) >$(TESTLIST) || $(RM) $(TESTLIST)
$(TESTPROGRAM): $(TESTPROGRAM).exe.so $(TESTPROGRAM).so: $(TESTPROGRAM).spec.o $(TESTOBJS)
$(RM) $(TESTPROGRAM) && cd tests && $(LN_S) $(TOPOBJDIR)/../wine `basename $(TESTPROGRAM)` $(LDSHARED) $(LDDLLFLAGS) $(TESTPROGRAM).spec.o $(TESTOBJS) -o $@ $(LIBWINE) $(LIBS)
$(TESTPROGRAM).exe.so: $(TESTPROGRAM).exe.spec.o $(TESTOBJS) $(TESTPROGRAM).tmp.o: $(TESTOBJS)
$(LDSHARED) $(LDDLLFLAGS) $(TESTPROGRAM).exe.spec.o $(TESTOBJS) -o $@ $(LIBWINE) $(LIBS)
$(TESTPROGRAM).exe.tmp.o: $(TESTOBJS)
$(LDCOMBINE) $(TESTOBJS) -o $@ $(LDCOMBINE) $(TESTOBJS) -o $@
-$(STRIP) --strip-unneeded $@ -$(STRIP) --strip-unneeded $@
$(TESTPROGRAM).exe.spec.c: $(TESTPROGRAM).exe.tmp.o $(WINEBUILD) $(TESTPROGRAM).spec.c: $(TESTPROGRAM).tmp.o $(WINEBUILD)
$(LDPATH) $(WINEBUILD) $(DEFS) -sym $(TESTPROGRAM).exe.tmp.o -o $@ -exe $(TESTPROGRAM).exe -mcui -L$(DLLDIR) $(TESTIMPORTS:%=-l%) $(LDPATH) $(WINEBUILD) $(DEFS) -sym $(TESTPROGRAM).tmp.o -o $@ -exe $(TESTPROGRAM) -mcui -L$(DLLDIR) $(TESTIMPORTS:%=-l%)
$(TESTPROGRAM).exe: $(TESTOBJS) $(TESTPROGRAM): $(TESTOBJS)
$(CC) $(TESTOBJS) -o $@ $(TESTIMPORTS:%=-l%) $(LIBWINE) $(LIBS) $(CC) $(TESTOBJS) -o $@ $(TESTIMPORTS:%=-l%) $(LIBWINE) $(LIBS)
# Misc. rules # Misc. rules

View File

@ -20,50 +20,33 @@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
LIBEXT = @LIBEXT@ LIBEXT = @LIBEXT@
LDCONFIG = @LDCONFIG@ LDCONFIG = @LDCONFIG@
MODULE = wine MODULE = none
LDIMPORTS = ntdll.dll
# Stand-alone programs # Sub-directories containing stand-alone programs
PROGRAMS = \ PROGSUBDIRS = \
server/wineserver server
# Programs that link with libwine # Sub-directories containing programs that use some Wine dlls
LIBPROGRAMS = \ LIBPROGSUBDIRS = \
debugger \ miscemu \
programs programs
# Libraries (not dlls) to build # Sub-directories containing libraries (not dlls) to build
LIBRARIES = \ LIBSUBDIRS = \
library/libwine.$(LIBEXT) \ library \
ole/libwine_uuid.a \ ole \
tsx11/libwine_tsx11.$(LIBEXT) \ tsx11 \
unicode/libwine_unicode.$(LIBEXT) unicode
# Dlls that we need to link against (should go away)
LINKABLE_DLLS = user32.dll gdi32.dll kernel32.dll ntdll.dll
# Libraries symlinks to create at the top level
LIBSYMLINKS = \
$(LINKABLE_DLLS:%=lib%.$(LIBEXT)) \
libwine.$(LIBEXT) \
libwine_tsx11.$(LIBEXT) \
libwine_unicode.$(LIBEXT) \
libwine_uuid.a
# Sub-directories to run make depend/clean/install into # Sub-directories to run make depend/clean/install into
SUBDIRS = \ SUBDIRS = \
debugger \ $(LIBPROGSUBDIRS) \
$(LIBSUBDIRS) \
$(PROGSUBDIRS) \
dlls \ dlls \
documentation \ documentation \
include \ include \
library \ tools
miscemu \
ole \
programs \
server \
tools \
tsx11 \
unicode
# Sub-directories to run make test into # Sub-directories to run make test into
TESTSUBDIRS = \ TESTSUBDIRS = \
@ -73,7 +56,7 @@ TESTSUBDIRS = \
EMUOBJS = \ EMUOBJS = \
miscemu/miscemu.o miscemu/miscemu.o
all: Make.rules $(PROGRAMS) $(LIBPROGRAMS) $(LIBSYMLINKS) wine all: Make.rules $(PROGSUBDIRS) $(LIBPROGSUBDIRS) wine
@echo "Wine build complete." @echo "Wine build complete."
WINAPI_CHECK_EXTRA_FLAGS = --global WINAPI_CHECK_EXTRA_FLAGS = --global
@ -84,68 +67,30 @@ Make.rules: Make.rules.in configure
@echo $? is newer than 'Make.rules', please rerun ./configure! @echo $? is newer than 'Make.rules', please rerun ./configure!
@exit 1 @exit 1
wine: $(EMUOBJS) $(LDIMPORTS:%=lib%.$(LIBEXT)) library/libwine.$(LIBEXT) unicode/libwine_unicode.$(LIBEXT) wine: $(WINEWRAPPER)
$(CC) -o wine $(EMUOBJS) -L. $(LDIMPORTS:%=-l%) $(LIBWINE) $(LIBUNICODE) $(LIBS) $(LDFLAGS) $(RM) $@ && $(LN_S) $(WINEWRAPPER) $@
install_wine: dummy install:: all $(SUBDIRS:%=%/__install__)
$(MKINSTALLDIRS) $(bindir)
$(INSTALL_PROGRAM) wine $(bindir)/wine
install:: all install_wine $(SUBDIRS:%=%/__install__)
-$(LDCONFIG) -$(LDCONFIG)
uninstall:: $(SUBDIRS:%=%/__uninstall__) uninstall:: $(SUBDIRS:%=%/__uninstall__)
$(RM) $(bindir)/wine
$(EMUOBJS) $(PROGRAMS) $(LIBRARIES): dummy
@cd `dirname $@` && $(MAKE) `basename $@`
# Symlinks to libraries that we need to link against
libwine.$(LIBEXT): library/libwine.$(LIBEXT)
$(RM) $@ && $(LN_S) library/libwine.$(LIBEXT) $@
libwine_tsx11.$(LIBEXT): tsx11/libwine_tsx11.$(LIBEXT)
$(RM) $@ && $(LN_S) tsx11/libwine_tsx11.$(LIBEXT) $@
libwine_unicode.$(LIBEXT): unicode/libwine_unicode.$(LIBEXT)
$(RM) $@ && $(LN_S) unicode/libwine_unicode.$(LIBEXT) $@
libwine_uuid.a: ole/libwine_uuid.a
$(RM) $@ && $(LN_S) ole/libwine_uuid.a $@
libuser32.dll.$(LIBEXT): dlls/user32.dll$(DLLEXT)
$(RM) $@ && $(LN_S) dlls/user32.dll$(DLLEXT) $@
libgdi32.dll.$(LIBEXT): dlls/gdi32.dll$(DLLEXT)
$(RM) $@ && $(LN_S) dlls/gdi32.dll$(DLLEXT) $@
libkernel32.dll.$(LIBEXT): dlls/kernel32.dll$(DLLEXT)
$(RM) $@ && $(LN_S) dlls/kernel32.dll$(DLLEXT) $@
libntdll.dll.$(LIBEXT): dlls/ntdll.dll$(DLLEXT)
$(RM) $@ && $(LN_S) dlls/ntdll.dll$(DLLEXT) $@
$(LINKABLE_DLLS:%=dlls/%$(DLLEXT)): dlls
# Dependencies between directories # Dependencies between directories
$(PROGRAMS): tools $(LIBPROGSUBDIRS): tools dlls $(LIBSUBDIRS)
$(EMUOBJS): tools dlls $(PROGSUBDIRS): tools $(LIBSUBDIRS)
$(LIBPROGRAMS): tools dlls wine dlls: tools $(LIBSUBDIRS)
server tools: $(LIBRARIES) tools: $(LIBSUBDIRS)
dlls: tools $(LIBRARIES)
checklink:: checklink::
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c && $(RM) checklink $(CC) -o checklink $(TOPSRCDIR)/library/checklink.c && $(RM) checklink
checklink:: checklink::
@cd dlls && $(MAKE) checklink @cd dlls && $(MAKE) checklink
@cd debugger && $(MAKE) checklink @cd programs && $(MAKE) checklink
test_environment: dummy test_environment: dummy
@cd programs/winetest && $(MAKE) all @cd programs/winetest && $(MAKE) all

View File

@ -35,14 +35,16 @@ $(MODULE).so: $(ALL_OBJS) Makefile.in
# Rules for .dll files # Rules for .dll files
$(MODULE): $(OBJS) $(MODULE).dbg.o $(SPEC_DEF) Makefile.in $(MODULE): $(OBJS) $(MODULE).dbg.o $(SPEC_DEF) Makefile.in
$(DLLWRAP) $(DLLWRAPFLAGS) --def $(SPEC_DEF) --implib $(MODULE:.dll=.a) -o $(MODULE) $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(IMPORTS:%=-l%) $(ALL_LIBS) $(DLLWRAP) $(DLLWRAPFLAGS) --def $(SPEC_DEF) --implib $(MODULE:.dll=.a) -o $@ $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(ALL_LIBS)
$(SPEC_DEF): $(WINEBUILD) $(SPEC_DEF): $(WINEBUILD)
# Rules for checking that no imports are missing # Rules for checking that no imports are missing
CHECKLINK_RPATH = dlls library tsx11 unicode
checklink:: $(MODULE)$(DLLEXT) checklink:: $(MODULE)$(DLLEXT)
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c $(MODULE)$(DLLEXT) && $(RM) checklink $(CC) -o checklink $(CHECKLINK_RPATH:%=-Wl,-rpath,$(TOPOBJDIR)/%) $(TOPSRCDIR)/library/checklink.c $(MODULE)$(DLLEXT) && $(RM) checklink
# Rules for testing # Rules for testing

View File

@ -288,8 +288,6 @@ BOOL X11DRV_CLIPBOARD_LaunchServer()
execl( BINDIR "/wineclipsrv", "wineclipsrv", execl( BINDIR "/wineclipsrv", "wineclipsrv",
selMask, dbgClassMask, clearSelection, NULL ); selMask, dbgClassMask, clearSelection, NULL );
execlp( "wineclipsrv", "wineclipsrv", selMask, dbgClassMask, clearSelection, NULL ); execlp( "wineclipsrv", "wineclipsrv", selMask, dbgClassMask, clearSelection, NULL );
execl( "./windows/x11drv/wineclipsrv", "wineclipsrv",
selMask, dbgClassMask, clearSelection, NULL );
/* Exec Failed! */ /* Exec Failed! */
perror("Could not start Wine clipboard server"); perror("Could not start Wine clipboard server");

View File

@ -65,7 +65,7 @@ $(BOOKNAME).ps: $(BOOK_SRCS)
db2ps $(BOOKNAME).sgml > /dev/null db2ps $(BOOKNAME).sgml > /dev/null
wine.man: wine.man.in wine.man: wine.man.in
sed -e 's,@bindir\@,$(bindir),g' -e 's,@libdir\@,$(libdir),g' $(SRCDIR)/wine.man.in >$@ || $(RM) $@ sed -e 's,@bindir\@,$(bindir),g' -e 's,@dlldir\@,$(dlldir),g' $(SRCDIR)/wine.man.in >$@ || $(RM) $@
install:: $(MAN_TARGETS) install:: $(MAN_TARGETS)
$(INSTALL) -d $(mandir)/man$(prog_manext) $(INSTALL) -d $(mandir)/man$(prog_manext)

View File

@ -107,6 +107,8 @@ WINE REGISTRY Version 2
"msacm" = "builtin, native" "msacm" = "builtin, native"
"msacm32" = "builtin, native" "msacm32" = "builtin, native"
"midimap.drv" = "builtin, native" "midimap.drv" = "builtin, native"
; you can specify applications too
"notepad.exe" = "native, builtin"
; default for all other dlls ; default for all other dlls
"*" = "native, builtin, so" "*" = "native, builtin, so"

View File

@ -254,31 +254,30 @@ processes, it is possible to run a number of truly independent
.B wine .B wine
processes. processes.
.TP .TP
.I WINEPRELOAD
If set, specifies the full name of a shared library that
.B wine
loads and runs as a Winelib application.
.TP
.I WINESERVER .I WINESERVER
Specifies the path and name of the Specifies the path and name of the
.B wineserver .B wineserver
binary. If not set, a file named "wineserver" is searched in the binary. If not set, Wine will try to load
path and in a few other likely locations. .B @bindir@/wineserver,
and if this doesn't exist will then look for a file named "wineserver"
in the path and in a few other likely locations.
.TP .TP
.I WINELOADER .I WINELOADER
Specifies the path and name of the Specifies the path and name of the
.B wine .B wine
binary to use to launch new Windows processes. If not set, a binary binary to use to launch new Windows processes. If not set, Wine will
named "wine" is searched in the path and in a few other likely try to load
locations. .B @bindir@/wine,
and if this doesn't exist will then look for a file named "wine" in
the path and in a few other likely locations.
.TP .TP
.I WINEDLLPATH .I WINEDLLPATH
Specifies the path(s) in which to search for builtin dll files. This Specifies the path(s) in which to search for builtin dlls and Winelib
is a list of directories separated by ":". Builtin dlls are also applications. This is a list of directories separated by ":". In
searched in the directories specified by the standard addition to any directory specified in
.I LD_LIBRARY_PATH .I WINEDLLPATH,
if they are not found in the directories listed in Wine will also look in
.I WINEDLLPATH. .B @dlldir@.
.TP .TP
.I DISPLAY .I DISPLAY
Specifies the X11 display to use. Specifies the X11 display to use.
@ -378,12 +377,12 @@ The
.B wine .B wine
debugger debugger
.TP .TP
.I @bindir@/wineclpsrv .I @bindir@/wineclipsrv
The The
.B wine .B wine
clipboard server clipboard server
.TP .TP
.I @libdir@ .I @dlldir@
Directory containing Directory containing
.B wine's .B wine's
shared libraries shared libraries

View File

@ -186,6 +186,19 @@ enum loadorder_type
LOADORDER_NTYPES LOADORDER_NTYPES
}; };
/* return values for MODULE_GetBinaryType */
enum binary_type
{
BINARY_UNKNOWN,
BINARY_PE_EXE,
BINARY_PE_DLL,
BINARY_WIN16,
BINARY_OS216,
BINARY_DOS,
BINARY_UNIX_EXE,
BINARY_UNIX_LIB
};
/* module.c */ /* module.c */
extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename ); extern WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename );
extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, BOOL snoop ); extern FARPROC MODULE_GetProcAddress( HMODULE hModule, LPCSTR function, BOOL snoop );
@ -197,6 +210,7 @@ extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD fl
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm ); extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
extern WINE_MODREF *MODULE_FindModule( LPCSTR path ); extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 ); extern HMODULE16 MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name ); extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address ); extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
extern void MODULE_WalkModref( DWORD id ); extern void MODULE_WalkModref( DWORD id );
@ -287,10 +301,5 @@ extern int BUILTIN32_dlclose( void *handle );
/* scheduler/process.c */ /* scheduler/process.c */
extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule ); extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule );
extern BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags,
STARTUPINFOA *startup, PROCESS_INFORMATION *info,
LPCSTR lpCurrentDirectory );
#endif /* __WINE_MODULE_H */ #endif /* __WINE_MODULE_H */

View File

@ -33,8 +33,7 @@ extern void *wine_dlsym( void *handle, const char *symbol, char *error, int erro
extern int wine_dlclose( void *handle, char *error, int errorsize ); extern int wine_dlclose( void *handle, char *error, int errorsize );
extern void wine_dll_set_callback( load_dll_callback_t load ); extern void wine_dll_set_callback( load_dll_callback_t load );
extern void *wine_dll_load( const char *filename, char *error, int errorsize ); extern void *wine_dll_load( const char *filename, char *error, int errorsize );
extern void *wine_dll_load_main_exe( const char *name, int search_path, extern void *wine_dll_load_main_exe( const char *name, char *error, int errorsize, int test_only );
char *error, int errorsize );
extern void wine_dll_unload( void *handle ); extern void wine_dll_unload( void *handle );
extern int __wine_main_argc; extern int __wine_main_argc;

View File

@ -118,7 +118,7 @@ inline static int file_exists( const char *name )
/* open a library for a given dll, searching in the dll path /* open a library for a given dll, searching in the dll path
* 'name' must be the Windows dll name (e.g. "kernel32.dll") */ * 'name' must be the Windows dll name (e.g. "kernel32.dll") */
static void *dlopen_dll( const char *name, char *error, int errorsize ) static void *dlopen_dll( const char *name, char *error, int errorsize, int test_only )
{ {
int i, namelen = strlen(name); int i, namelen = strlen(name);
char *buffer, *p; char *buffer, *p;
@ -139,17 +139,16 @@ static void *dlopen_dll( const char *name, char *error, int errorsize )
int len = strlen(dll_paths[i]); int len = strlen(dll_paths[i]);
p = buffer + dll_path_maxlen - len; p = buffer + dll_path_maxlen - len;
memcpy( p, dll_paths[i], len ); memcpy( p, dll_paths[i], len );
if ((ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break; if (test_only) /* just test for file existence */
if (file_exists( p )) /* exists but cannot be loaded, return the error */
{ {
free( buffer ); if ((ret = (void *)file_exists( p ))) break;
return NULL; }
else
{
if ((ret = wine_dlopen( p, RTLD_NOW, error, errorsize ))) break;
if (file_exists( p )) break; /* exists but cannot be loaded, return the error */
} }
} }
/* now try the default dlopen search path */
if (!ret)
ret = wine_dlopen( buffer + dll_path_maxlen + 1, RTLD_NOW, error, errorsize );
free( buffer ); free( buffer );
return ret; return ret;
} }
@ -374,7 +373,7 @@ void *wine_dll_load( const char *filename, char *error, int errorsize )
return (void *)1; return (void *)1;
} }
} }
return dlopen_dll( filename, error, errorsize ); return dlopen_dll( filename, error, errorsize, 0 );
} }
@ -393,46 +392,9 @@ void wine_dll_unload( void *handle )
/*********************************************************************** /***********************************************************************
* wine_dll_load_main_exe * wine_dll_load_main_exe
* *
* Try to load the .so for the main exe, optionally searching for it in PATH. * Try to load the .so for the main exe.
*/ */
void *wine_dll_load_main_exe( const char *name, int search_path, char *error, int errorsize ) void *wine_dll_load_main_exe( const char *name, char *error, int errorsize, int test_only )
{ {
void *ret = NULL; return dlopen_dll( name, error, errorsize, test_only );
const char *path = NULL;
if (search_path) path = getenv( "PATH" );
if (!path)
{
/* no path, try only the specified name */
ret = wine_dlopen( name, RTLD_NOW, error, errorsize );
}
else
{
char buffer[128], *tmp = buffer;
size_t namelen = strlen(name);
size_t pathlen = strlen(path);
if (namelen + pathlen + 2 > sizeof(buffer)) tmp = malloc( namelen + pathlen + 2 );
if (tmp)
{
char *basename = tmp + pathlen;
*basename = '/';
strcpy( basename + 1, name );
for (;;)
{
int len;
const char *p = strchr( path, ':' );
if (!p) p = path + strlen(path);
if ((len = p - path) > 0)
{
memcpy( basename - len, path, len );
if ((ret = wine_dlopen( basename - len, RTLD_NOW, error, errorsize ))) break;
}
if (!*p) break;
path = p + 1;
}
if (tmp != buffer) free( tmp );
}
}
return ret;
} }

View File

@ -518,10 +518,11 @@ WINE_MODREF *MODULE_FindModule(
* FIXME: is reading the module imports the only way of discerning * FIXME: is reading the module imports the only way of discerning
* old Windows binaries from OS/2 ones ? At least it seems so... * old Windows binaries from OS/2 ones ? At least it seems so...
*/ */
static DWORD MODULE_Decide_OS2_OldWin(HANDLE hfile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne) static enum binary_type MODULE_Decide_OS2_OldWin(HANDLE hfile, const IMAGE_DOS_HEADER *mz,
const IMAGE_OS2_HEADER *ne)
{ {
DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR); DWORD currpos = SetFilePointer( hfile, 0, NULL, SEEK_CUR);
DWORD type = SCS_OS216_BINARY; enum binary_type ret = BINARY_OS216;
LPWORD modtab = NULL; LPWORD modtab = NULL;
LPSTR nametab = NULL; LPSTR nametab = NULL;
DWORD len; DWORD len;
@ -548,7 +549,7 @@ static DWORD MODULE_Decide_OS2_OldWin(HANDLE hfile, IMAGE_DOS_HEADER *mz, IMAGE_
if (!(strncmp(&module[1], "KERNEL", module[0]))) if (!(strncmp(&module[1], "KERNEL", module[0])))
{ /* very old Windows file */ { /* very old Windows file */
MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n"); MESSAGE("This seems to be a very old (pre-3.0) Windows executable. Expect crashes, especially if this is a real-mode binary !\n");
type = SCS_WOW_BINARY; ret = BINARY_WIN16;
goto good; goto good;
} }
} }
@ -560,11 +561,120 @@ good:
HeapFree( GetProcessHeap(), 0, modtab); HeapFree( GetProcessHeap(), 0, modtab);
HeapFree( GetProcessHeap(), 0, nametab); HeapFree( GetProcessHeap(), 0, nametab);
SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */ SetFilePointer( hfile, currpos, NULL, SEEK_SET); /* restore filepos */
return type; return ret;
} }
/*********************************************************************** /***********************************************************************
* MODULE_GetBinaryType * MODULE_GetBinaryType
*/
enum binary_type MODULE_GetBinaryType( HANDLE hfile )
{
union
{
struct
{
unsigned char magic[4];
unsigned char ignored[12];
unsigned short type;
} elf;
IMAGE_DOS_HEADER mz;
} header;
char magic[4];
DWORD len;
/* Seek to the start of the file and read the header information. */
if (SetFilePointer( hfile, 0, NULL, SEEK_SET ) == -1)
return BINARY_UNKNOWN;
if (!ReadFile( hfile, &header, sizeof(header), &len, NULL ) || len != sizeof(header))
return BINARY_UNKNOWN;
if (!memcmp( header.elf.magic, "\177ELF", 4 ))
{
/* FIXME: we don't bother to check byte order, architecture, etc. */
switch(header.elf.type)
{
case 2: return BINARY_UNIX_EXE;
case 3: return BINARY_UNIX_LIB;
}
return BINARY_UNKNOWN;
}
/* Not ELF, try DOS */
if (header.mz.e_magic == IMAGE_DOS_SIGNATURE)
{
/* We do have a DOS image so we will now try to seek into
* the file by the amount indicated by the field
* "Offset to extended header" and read in the
* "magic" field information at that location.
* This will tell us if there is more header information
* to read or not.
*/
/* But before we do we will make sure that header
* structure encompasses the "Offset to extended header"
* field.
*/
if ((header.mz.e_cparhdr << 4) < sizeof(IMAGE_DOS_HEADER))
return BINARY_DOS;
if (header.mz.e_crlc && (header.mz.e_lfarlc < sizeof(IMAGE_DOS_HEADER)))
return BINARY_DOS;
if (header.mz.e_lfanew < sizeof(IMAGE_DOS_HEADER))
return BINARY_DOS;
if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) == -1)
return BINARY_DOS;
if (!ReadFile( hfile, magic, sizeof(magic), &len, NULL ) || len != sizeof(magic))
return BINARY_DOS;
/* Reading the magic field succeeded so
* we will try to determine what type it is.
*/
if (!memcmp( magic, "PE\0\0", 4 ))
{
IMAGE_NT_HEADERS nt;
if (SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1 &&
ReadFile( hfile, &nt, sizeof(nt), &len, NULL ) && len == sizeof(nt))
{
if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL) return BINARY_PE_DLL;
return BINARY_PE_EXE;
}
return BINARY_UNKNOWN;
}
if (!memcmp( magic, "NE", 2 ))
{
/* This is a Windows executable (NE) header. This can
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
* DOS program (running under a DOS extender). To decide
* which, we'll have to read the NE header.
*/
IMAGE_OS2_HEADER ne;
if ( SetFilePointer( hfile, header.mz.e_lfanew, NULL, SEEK_SET ) != -1
&& ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
&& len == sizeof(ne) )
{
switch ( ne.ne_exetyp )
{
case 2: return BINARY_WIN16;
case 5: return BINARY_DOS;
default: return MODULE_Decide_OS2_OldWin(hfile, &header.mz, &ne);
}
}
/* Couldn't read header, so abort. */
return BINARY_UNKNOWN;
}
/* Unknown extended header, but this file is nonetheless DOS-executable. */
return BINARY_DOS;
}
return BINARY_UNKNOWN;
}
/***********************************************************************
* GetBinaryTypeA [KERNEL32.@]
* GetBinaryType [KERNEL32.@]
* *
* The GetBinaryType function determines whether a file is executable * The GetBinaryType function determines whether a file is executable
* or not and if it is it returns what type of executable it is. * or not and if it is it returns what type of executable it is.
@ -593,133 +703,11 @@ good:
* Note that .COM and .PIF files are only recognized by their * Note that .COM and .PIF files are only recognized by their
* file name extension; but Windows does it the same way ... * file name extension; but Windows does it the same way ...
*/ */
static BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType )
{
IMAGE_DOS_HEADER mz_header;
char magic[4], *ptr;
DWORD len;
/* Seek to the start of the file and read the DOS header information.
*/
if ( SetFilePointer( hfile, 0, NULL, SEEK_SET ) != -1
&& ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL )
&& len == sizeof(mz_header) )
{
/* Now that we have the header check the e_magic field
* to see if this is a dos image.
*/
if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
{
BOOL lfanewValid = FALSE;
/* We do have a DOS image so we will now try to seek into
* the file by the amount indicated by the field
* "Offset to extended header" and read in the
* "magic" field information at that location.
* This will tell us if there is more header information
* to read or not.
*/
/* But before we do we will make sure that header
* structure encompasses the "Offset to extended header"
* field.
*/
if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
if ( ( mz_header.e_crlc == 0 ) ||
( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER)
&& SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ) != -1
&& ReadFile( hfile, magic, sizeof(magic), &len, NULL )
&& len == sizeof(magic) )
lfanewValid = TRUE;
if ( !lfanewValid )
{
/* If we cannot read this "extended header" we will
* assume that we have a simple DOS executable.
*/
*lpBinaryType = SCS_DOS_BINARY;
return TRUE;
}
else
{
/* Reading the magic field succeeded so
* we will try to determine what type it is.
*/
if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
{
/* This is an NT signature.
*/
*lpBinaryType = SCS_32BIT_BINARY;
return TRUE;
}
else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
{
/* The IMAGE_OS2_SIGNATURE indicates that the
* "extended header is a Windows executable (NE)
* header." This can mean either a 16-bit OS/2
* or a 16-bit Windows or even a DOS program
* (running under a DOS extender). To decide
* which, we'll have to read the NE header.
*/
IMAGE_OS2_HEADER ne;
if ( SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ) != -1
&& ReadFile( hfile, &ne, sizeof(ne), &len, NULL )
&& len == sizeof(ne) )
{
switch ( ne.ne_exetyp )
{
case 2: *lpBinaryType = SCS_WOW_BINARY; return TRUE;
case 5: *lpBinaryType = SCS_DOS_BINARY; return TRUE;
default: *lpBinaryType =
MODULE_Decide_OS2_OldWin(hfile, &mz_header, &ne);
return TRUE;
}
}
/* Couldn't read header, so abort. */
return FALSE;
}
else
{
/* Unknown extended header, but this file is nonetheless
DOS-executable.
*/
*lpBinaryType = SCS_DOS_BINARY;
return TRUE;
}
}
}
}
/* If we get here, we don't even have a correct MZ header.
* Try to check the file extension for known types ...
*/
ptr = strrchr( filename, '.' );
if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
{
if ( !FILE_strcasecmp( ptr, ".COM" ) )
{
*lpBinaryType = SCS_DOS_BINARY;
return TRUE;
}
if ( !FILE_strcasecmp( ptr, ".PIF" ) )
{
*lpBinaryType = SCS_PIF_BINARY;
return TRUE;
}
}
return FALSE;
}
/***********************************************************************
* GetBinaryTypeA [KERNEL32.@]
* GetBinaryType [KERNEL32.@]
*/
BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType ) BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
HANDLE hfile; HANDLE hfile;
char *ptr;
TRACE_(win32)("%s\n", lpApplicationName ); TRACE_(win32)("%s\n", lpApplicationName );
@ -737,12 +725,47 @@ BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
/* Check binary type /* Check binary type
*/ */
ret = MODULE_GetBinaryType( hfile, lpApplicationName, lpBinaryType ); switch(MODULE_GetBinaryType( hfile ))
{
case BINARY_UNKNOWN:
/* try to determine from file name */
ptr = strrchr( lpApplicationName, '.' );
if (!ptr) break;
if (!FILE_strcasecmp( ptr, ".COM" ))
{
*lpBinaryType = SCS_DOS_BINARY;
ret = TRUE;
}
else if (!FILE_strcasecmp( ptr, ".PIF" ))
{
*lpBinaryType = SCS_PIF_BINARY;
ret = TRUE;
}
break;
case BINARY_PE_EXE:
case BINARY_PE_DLL:
*lpBinaryType = SCS_32BIT_BINARY;
ret = TRUE;
break;
case BINARY_WIN16:
*lpBinaryType = SCS_WOW_BINARY;
ret = TRUE;
break;
case BINARY_OS216:
*lpBinaryType = SCS_OS216_BINARY;
ret = TRUE;
break;
case BINARY_DOS:
*lpBinaryType = SCS_DOS_BINARY;
ret = TRUE;
break;
case BINARY_UNIX_EXE:
case BINARY_UNIX_LIB:
ret = FALSE;
break;
}
/* Close the file.
*/
CloseHandle( hfile ); CloseHandle( hfile );
return ret; return ret;
} }
@ -967,238 +990,6 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
} }
/*************************************************************************
* get_file_name
*
* Helper for CreateProcess: retrieve the file name to load from the
* app name and command line. Store the file name in buffer, and
* return a possibly modified command line.
*/
static LPSTR get_file_name( LPCSTR appname, LPSTR cmdline, LPSTR buffer, int buflen )
{
char *name, *pos, *ret = NULL;
const char *p;
/* if we have an app name, everything is easy */
if (appname)
{
/* use the unmodified app name as file name */
lstrcpynA( buffer, appname, buflen );
if (!(ret = cmdline))
{
/* no command-line, create one */
if ((ret = HeapAlloc( GetProcessHeap(), 0, strlen(appname) + 3 )))
sprintf( ret, "\"%s\"", appname );
}
return ret;
}
if (!cmdline)
{
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
/* first check for a quoted file name */
if ((cmdline[0] == '"') && ((p = strchr( cmdline + 1, '"' ))))
{
int len = p - cmdline - 1;
/* extract the quoted portion as file name */
if (!(name = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return NULL;
memcpy( name, cmdline + 1, len );
name[len] = 0;
if (SearchPathA( NULL, name, ".exe", buflen, buffer, NULL ) ||
SearchPathA( NULL, name, NULL, buflen, buffer, NULL ))
ret = cmdline; /* no change necessary */
goto done;
}
/* now try the command-line word by word */
if (!(name = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 1 ))) return NULL;
pos = name;
p = cmdline;
while (*p)
{
do *pos++ = *p++; while (*p && *p != ' ');
*pos = 0;
TRACE("trying '%s'\n", name );
if (SearchPathA( NULL, name, ".exe", buflen, buffer, NULL ) ||
SearchPathA( NULL, name, NULL, buflen, buffer, NULL ))
{
ret = cmdline;
break;
}
}
if (!ret || !strchr( name, ' ' )) goto done; /* no change necessary */
/* now build a new command-line with quotes */
if (!(ret = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 3 ))) goto done;
sprintf( ret, "\"%s\"%s", name, p );
done:
HeapFree( GetProcessHeap(), 0, name );
return ret;
}
/**********************************************************************
* CreateProcessA (KERNEL32.@)
*/
BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags,
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInfo )
{
BOOL retv = FALSE;
HANDLE hFile;
DWORD type;
char name[MAX_PATH];
LPSTR tidy_cmdline;
/* Process the AppName and/or CmdLine to get module name and path */
TRACE("app %s cmdline %s\n", debugstr_a(lpApplicationName), debugstr_a(lpCommandLine) );
if (!(tidy_cmdline = get_file_name( lpApplicationName, lpCommandLine, name, sizeof(name) )))
return FALSE;
/* Warn if unsupported features are used */
if (dwCreationFlags & NORMAL_PRIORITY_CLASS)
FIXME("(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
if (dwCreationFlags & IDLE_PRIORITY_CLASS)
FIXME("(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
if (dwCreationFlags & HIGH_PRIORITY_CLASS)
FIXME("(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
if (dwCreationFlags & REALTIME_PRIORITY_CLASS)
FIXME("(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
if (dwCreationFlags & CREATE_NEW_PROCESS_GROUP)
FIXME("(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
if (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)
FIXME("(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)
FIXME("(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
if (dwCreationFlags & CREATE_SHARED_WOW_VDM)
FIXME("(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE)
FIXME("(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
if (dwCreationFlags & CREATE_NO_WINDOW)
FIXME("(%s,...): CREATE_NO_WINDOW ignored\n", name);
if (dwCreationFlags & PROFILE_USER)
FIXME("(%s,...): PROFILE_USER ignored\n", name);
if (dwCreationFlags & PROFILE_KERNEL)
FIXME("(%s,...): PROFILE_KERNEL ignored\n", name);
if (dwCreationFlags & PROFILE_SERVER)
FIXME("(%s,...): PROFILE_SERVER ignored\n", name);
if (lpStartupInfo->lpDesktop)
FIXME("(%s,...): lpStartupInfo->lpDesktop %s ignored\n",
name, debugstr_a(lpStartupInfo->lpDesktop));
if (lpStartupInfo->dwFlags & STARTF_RUNFULLSCREEN)
FIXME("(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
if (lpStartupInfo->dwFlags & STARTF_FORCEONFEEDBACK)
FIXME("(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
if (lpStartupInfo->dwFlags & STARTF_FORCEOFFFEEDBACK)
FIXME("(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
if (lpStartupInfo->dwFlags & STARTF_USEHOTKEY)
FIXME("(%s,...): STARTF_USEHOTKEY ignored\n", name);
/* Open file and determine executable type */
hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
if (hFile == INVALID_HANDLE_VALUE) goto done;
if ( !MODULE_GetBinaryType( hFile, name, &type ) )
{ /* unknown file, try as unix executable */
CloseHandle( hFile );
retv = PROCESS_Create( 0, name, tidy_cmdline, lpEnvironment,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpStartupInfo, lpProcessInfo, lpCurrentDirectory );
goto done;
}
/* Create process */
switch ( type )
{
case SCS_32BIT_BINARY:
case SCS_WOW_BINARY:
case SCS_DOS_BINARY:
retv = PROCESS_Create( hFile, name, tidy_cmdline, lpEnvironment,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpStartupInfo, lpProcessInfo, lpCurrentDirectory);
break;
case SCS_PIF_BINARY:
case SCS_POSIX_BINARY:
case SCS_OS216_BINARY:
FIXME("Unsupported executable type: %ld\n", type );
/* fall through */
default:
SetLastError( ERROR_BAD_FORMAT );
break;
}
CloseHandle( hFile );
done:
if (tidy_cmdline != lpCommandLine) HeapFree( GetProcessHeap(), 0, tidy_cmdline );
return retv;
}
/**********************************************************************
* CreateProcessW (KERNEL32.@)
* NOTES
* lpReserved is not converted
*/
BOOL WINAPI CreateProcessW( LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags,
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInfo )
{ BOOL ret;
STARTUPINFOA StartupInfoA;
LPSTR lpApplicationNameA = HEAP_strdupWtoA (GetProcessHeap(),0,lpApplicationName);
LPSTR lpCommandLineA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCommandLine);
LPSTR lpCurrentDirectoryA = HEAP_strdupWtoA (GetProcessHeap(),0,lpCurrentDirectory);
memcpy (&StartupInfoA, lpStartupInfo, sizeof(STARTUPINFOA));
StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpDesktop);
StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,lpStartupInfo->lpTitle);
TRACE_(win32)("(%s,%s,...)\n", debugstr_w(lpApplicationName), debugstr_w(lpCommandLine));
if (lpStartupInfo->lpReserved)
FIXME_(win32)("StartupInfo.lpReserved is used, please report (%s)\n", debugstr_w(lpStartupInfo->lpReserved));
ret = CreateProcessA( lpApplicationNameA, lpCommandLineA,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpEnvironment, lpCurrentDirectoryA,
&StartupInfoA, lpProcessInfo );
HeapFree( GetProcessHeap(), 0, lpCurrentDirectoryA );
HeapFree( GetProcessHeap(), 0, lpCommandLineA );
HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
return ret;
}
/*********************************************************************** /***********************************************************************
* GetModuleHandleA (KERNEL32.@) * GetModuleHandleA (KERNEL32.@)
* GetModuleHandle32 (KERNEL.488) * GetModuleHandle32 (KERNEL.488)
@ -1297,17 +1088,20 @@ HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
NULL, OPEN_EXISTING, 0, 0 ); NULL, OPEN_EXISTING, 0, 0 );
if (hFile != INVALID_HANDLE_VALUE) if (hFile != INVALID_HANDLE_VALUE)
{ {
DWORD type; HANDLE mapping;
MODULE_GetBinaryType( hFile, filename, &type ); switch (MODULE_GetBinaryType( hFile ))
if (type == SCS_32BIT_BINARY)
{ {
HANDLE mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, case BINARY_PE_EXE:
0, 0, NULL ); case BINARY_PE_DLL:
mapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if (mapping) if (mapping)
{ {
hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); hmod = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle( mapping ); CloseHandle( mapping );
} }
break;
default:
break;
} }
CloseHandle( hFile ); CloseHandle( hFile );
} }

View File

@ -1,2 +1,3 @@
Makefile Makefile
wine
wine.spec.c wine.spec.c

View File

@ -3,19 +3,32 @@ TOPSRCDIR = @top_srcdir@
TOPOBJDIR = .. TOPOBJDIR = ..
SRCDIR = @srcdir@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = miscemu MODULE = wine
IMPORTS = ntdll IMPORTS = ntdll
LDIMPORTS = ntdll.dll
SPEC_SRCS = wine.spec SPEC_SRCS = wine.spec
C_SRCS = \ C_SRCS = \
main.c main.c
all: $(MODULE).o all: $(MODULE)
@MAKE_RULES@ @MAKE_RULES@
$(MODULE).o: $(SPEC_SRCS:.spec=.spec.o) $(OBJS) Makefile.in $(TOPSRCDIR)/Make.rules.in ALL_OBJS = $(SPEC_SRCS:.spec=.spec.o) $(OBJS)
$(LDCOMBINE) $(SPEC_SRCS:.spec=.spec.o) $(OBJS) -o $@
$(MODULE): $(ALL_OBJS)
$(CC) -o $@ $(ALL_OBJS) -L$(DLLDIR) $(LDIMPORTS:%=-l%) $(LIBWINE) $(LIBUNICODE) $(LIBS) $(LDFLAGS)
install:: $(MODULE)
$(MKINSTALLDIRS) $(bindir)
$(INSTALL_PROGRAM) wine $(bindir)/wine
uninstall::
$(RM) $(bindir)/wine
clean::
$(RM) $(MODULE)
### Dependencies: ### Dependencies:

View File

@ -1,2 +1,3 @@
Makefile Makefile
Makeprog.rules Makeprog.rules
wineapploader

View File

@ -4,8 +4,33 @@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = none MODULE = none
INSTALLSUBDIRS = \ SUBDIRS = \
$(TOPOBJDIR)/debugger \
avitools \
clock \
cmdlgtst \
control \ control \
expand \
notepad \
osversioncheck \
progman \
regapi \
regedit \
regsvr32 \
regtest \
uninstaller \
view \
wcmd \
wineconsole \
winemine \
winepath \
winetest \
winhelp \
winver
# Programs to install in bin directory
# We don't install everything to avoid polluting /usr/bin too much
INSTALLPROGS = \
expand \ expand \
notepad \ notepad \
progman \ progman \
@ -14,44 +39,71 @@ INSTALLSUBDIRS = \
uninstaller \ uninstaller \
wcmd \ wcmd \
wineconsole \ wineconsole \
winedbg \
winemine \ winemine \
winepath \ winepath \
winhelp \ winhelp
winver
# Programs that are not generally useful and don't get installed # Symlinks to apps that we want to run from inside the source tree
# Use 'make everything' to build them SYMLINKS = \
OTHERSUBDIRS = \ wineconsole.exe \
avitools \ winedbg.exe \
clock \ winetest.exe
cmdlgtst \
osversioncheck \
regapi \
regtest \
view \
winetest
SUBDIRS = $(INSTALLSUBDIRS) $(OTHERSUBDIRS)
all: $(INSTALLSUBDIRS)
@MAKE_RULES@ @MAKE_RULES@
everything: $(SUBDIRS) all: wineapploader $(SUBDIRS) $(SYMLINKS:%=%$(DLLEXT))
install-everything: $(SUBDIRS:%=%/__install__) wineapploader: wineapploader.in
sed -e 's,@bindir\@,$(bindir),g' $(SRCDIR)/wineapploader.in >$@ || $(RM) $@
uninstall-everything: $(SUBDIRS:%=%/__uninstall__) # Rules for installation
install:: $(INSTALLSUBDIRS:%=%/__install__) .PHONY: install-apploader install-progs install-progs.so $(INSTALLPROGS:%=%/__installprog__)
uninstall:: $(INSTALLSUBDIRS:%=%/__uninstall__) install-apploader: wineapploader dummy
$(MKINSTALLDIRS) $(bindir)
$(INSTALL_SCRIPT) wineapploader $(bindir)/wineapploader
$(INSTALLPROGS:%=%/__installprog__): install-apploader
$(RM) $(bindir)/`dirname $@` && $(LN) $(bindir)/wineapploader $(bindir)/`dirname $@`
install-progs.so: $(INSTALLPROGS:%=%/__installprog__)
$(RM) $(bindir)/wineapploader
install-progs: # nothing to do here
install:: $(SUBDIRS:%=%/__install__) install-progs$(DLLEXT)
uninstall:: $(SUBDIRS:%=%/__uninstall__)
$(RM) $(bindir)/wineapploader $(INSTALLPROGS:%=$(bindir)/%)
-rmdir $(dlldir)
clean::
$(RM) wineapploader $(SYMLINKS)
# Rules for testing
$(SUBDIRS:%=%/__checklink__): dummy $(SUBDIRS:%=%/__checklink__): dummy
@cd `dirname $@` && $(MAKE) checklink @cd `dirname $@` && $(MAKE) checklink
check test:: $(SUBDIRS:%=%/__test__)
checklink:: $(SUBDIRS:%=%/__checklink__) checklink:: $(SUBDIRS:%=%/__checklink__)
check test:: $(SUBDIRS:%=%/__test__)
# Rules for symlinks
wineconsole.exe$(DLLEXT): wineconsole/wineconsole.exe$(DLLEXT)
$(RM) $@ && $(LN_S) wineconsole/wineconsole.exe$(DLLEXT) $@
winedbg.exe$(DLLEXT): $(TOPOBJDIR)/debugger/winedbg.exe$(DLLEXT)
$(RM) $@ && $(LN_S) $(TOPOBJDIR)/debugger/winedbg.exe$(DLLEXT) $@
winetest.exe$(DLLEXT): winetest/winetest.exe$(DLLEXT)
$(RM) $@ && $(LN_S) winetest/winetest.exe$(DLLEXT) $@
wineconsole/wineconsole.exe$(DLLEXT): wineconsole
$(TOPOBJDIR)/debugger/winedbg.exe$(DLLEXT): $(TOPOBJDIR)/debugger
winetest/winetest.exe$(DLLEXT): winetest
### Dependencies: ### Dependencies:

View File

@ -32,8 +32,8 @@ $(MODULE).spec.c: $(RC_SRCS:.rc=.res) $(SYMBOLFILE) $(WINEBUILD)
$(MODULE).so: $(MODULE).spec.o $(ALL_OBJS) Makefile.in $(MODULE).so: $(MODULE).spec.o $(ALL_OBJS) Makefile.in
$(LDSHARED) $(LDDLLFLAGS) $(MODULE).spec.o $(ALL_OBJS) -o $@ $(ALL_LIBS) $(LDSHARED) $(LDDLLFLAGS) $(MODULE).spec.o $(ALL_OBJS) -o $@ $(ALL_LIBS)
$(BASEMODULE): $(MODULE).so $(BASEMODULE): $(WINEWRAPPER)
$(RM) $(BASEMODULE) && $(LN_S) $(TOPOBJDIR)/wine $(BASEMODULE) $(RM) $@ && $(LN_S) $(WINEWRAPPER) $@
# Rules for .exe main module # Rules for .exe main module
@ -42,8 +42,10 @@ $(MODULE): $(ALL_OBJS) $(RCOBJS) Makefile.in
# Rules for checking that no imports are missing # Rules for checking that no imports are missing
CHECKLINK_RPATH = library tsx11 unicode
checklink:: $(MODULE).so checklink:: $(MODULE).so
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c $(MODULE).so && $(RM) checklink $(CC) -o checklink $(CHECKLINK_RPATH:%=-Wl,-rpath,$(TOPOBJDIR)/%) $(TOPSRCDIR)/library/checklink.c $(MODULE).so && $(RM) checklink
# Rules for testing # Rules for testing
@ -51,21 +53,25 @@ $(TESTRESULTS): $(MODULE)$(DLLEXT)
# Rules for installation # Rules for installation
.PHONY: install_prog install_prog.so .PHONY: install_prog install_prog.so uninstall_prog uninstall_prog.so
install_prog.so:: $(MODULE).so install_prog.so: $(MODULE).so
$(MKINSTALLDIRS) $(bindir) $(MKINSTALLDIRS) $(dlldir)
$(INSTALL_PROGRAM) $(MODULE).so $(bindir)/$(MODULE).so $(INSTALL_PROGRAM) $(MODULE).so $(dlldir)/$(MODULE).so
cd $(bindir) && $(RM) $(BASEMODULE) && $(LN_S) wine $(BASEMODULE)
install_prog.exe:: $(MODULE) install_prog: $(MODULE)
$(MKINSTALLDIRS) $(bindir) $(MKINSTALLDIRS) $(bindir)
$(INSTALL_PROGRAM) $(MODULE) $(bindir)/$(MODULE) $(INSTALL_PROGRAM) $(MODULE) $(bindir)/$(MODULE)
uninstall_prog.so: dummy
$(RM) $(dlldir)/$(MODULE).so
uninstall_prog: dummy
$(RM) $(bindir)/$(MODULE)
install:: install_prog$(DLLEXT) install:: install_prog$(DLLEXT)
uninstall:: uninstall:: uninstall_prog$(DLLEXT)
$(RM) $(bindir)/$(BASEMODULE) $(bindir)/$(MODULE) $(bindir)/$(MODULE).so
clean:: clean::
$(RM) $(BASEMODULE) $(MODULE) $(RM) $(BASEMODULE) $(MODULE)

View File

@ -15,25 +15,25 @@ C_SRCS = \
@MAKE_RULES@ @MAKE_RULES@
all: $(PROGRAMS:%=%$(DLLEXT)) $(PROGRAMS:%.exe=%$(EXEEXT)) all: $(PROGRAMS:%=%$(DLLEXT)) $(PROGRAMS:.exe=$(EXEEXT))
aviinfo.exe.spec.c: aviinfo.o $(WINEBUILD) aviinfo.exe.spec.c: aviinfo.o $(WINEBUILD)
$(LDPATH) $(WINEBUILD) $(DEFS) -sym aviinfo.o -o aviinfo.exe.spec.c -exe aviinfo.exe -mgui -L$(DLLDIR) -lkernel32 $(LDPATH) $(WINEBUILD) $(DEFS) -sym aviinfo.o -o $@ -exe aviinfo.exe -mgui -L$(DLLDIR) -lkernel32
aviplay.exe.spec.c: aviplay.o $(WINEBUILD) aviplay.exe.spec.c: aviplay.o $(WINEBUILD)
$(LDPATH) $(WINEBUILD) $(DEFS) -sym aviplay.o -o aviplay.exe.spec.c -exe aviplay.exe -mgui -L$(DLLDIR) -lddraw -lkernel32 $(LDPATH) $(WINEBUILD) $(DEFS) -sym aviplay.o -o $@ -exe aviplay.exe -mgui -L$(DLLDIR) -lddraw -lkernel32
icinfo.exe.spec.c: icinfo.o $(WINEBUILD) icinfo.exe.spec.c: icinfo.o $(WINEBUILD)
$(LDPATH) $(WINEBUILD) $(DEFS) -sym icinfo.o -o icinfo.exe.spec.c -exe icinfo.exe -mgui -L$(DLLDIR) -lmsvfw32 -lkernel32 $(LDPATH) $(WINEBUILD) $(DEFS) -sym icinfo.o -o $@ -exe icinfo.exe -mgui -L$(DLLDIR) -lmsvfw32 -lkernel32
aviinfo.exe.so: aviinfo.o aviinfo.exe.spec.o aviinfo.exe.so: aviinfo.o aviinfo.exe.spec.o
$(LDSHARED) $(LDDLLFLAGS) -o aviinfo.exe.so aviinfo.o aviinfo.exe.spec.o $(ALL_LIBS) $(LDSHARED) $(LDDLLFLAGS) -o $@ aviinfo.o aviinfo.exe.spec.o $(ALL_LIBS)
aviplay.exe.so: aviplay.o aviplay.exe.spec.o aviplay.exe.so: aviplay.o aviplay.exe.spec.o
$(LDSHARED) $(LDDLLFLAGS) -o aviplay.exe.so aviplay.o aviplay.exe.spec.o $(ALL_LIBS) $(LDSHARED) $(LDDLLFLAGS) -o $@ aviplay.o aviplay.exe.spec.o $(ALL_LIBS)
icinfo.exe.so: icinfo.o icinfo.exe.spec.o icinfo.exe.so: icinfo.o icinfo.exe.spec.o
$(LDSHARED) $(LDDLLFLAGS) -o icinfo.exe.so icinfo.o icinfo.exe.spec.o $(ALL_LIBS) $(LDSHARED) $(LDDLLFLAGS) -o $@ icinfo.o icinfo.exe.spec.o $(ALL_LIBS)
aviinfo.exe: aviinfo.o aviinfo.exe: aviinfo.o
$(CC) -o $@ aviinfo.o -lkernel32 $(ALL_LIBS) $(CC) -o $@ aviinfo.o -lkernel32 $(ALL_LIBS)
@ -44,38 +44,45 @@ aviplay.exe: aviplay.o
icinfo.exe: icinfo.o icinfo.exe: icinfo.o
$(CC) -o $@ icinfo.o -lmsvfw32 -lkernel32 $(ALL_LIBS) $(CC) -o $@ icinfo.o -lmsvfw32 -lkernel32 $(ALL_LIBS)
aviinfo: aviinfo.exe.so $(PROGRAMS:.exe=): $(WINEWRAPPER)
$(RM) aviinfo && $(LN_S) $(TOPOBJDIR)/wine aviinfo $(RM) $@ && $(LN_S) $(WINEWRAPPER) $@
aviplay: aviplay.exe.so # Rules for installation
$(RM) aviplay && $(LN_S) $(TOPOBJDIR)/wine aviplay
icinfo: icinfo.exe.so .PHONY: install_prog install_prog.so uninstall_prog uninstall_prog.so
$(RM) icinfo && $(LN_S) $(TOPOBJDIR)/wine icinfo
.PHONY: install_prog install_prog.so install_prog.so: $(PROGRAMS:%=%.so)
$(MKINSTALLDIRS) $(dlldir)
$(INSTALL_PROGRAM) aviinfo.exe.so $(dlldir)/aviinfo.exe.so
$(INSTALL_PROGRAM) aviplay.exe.so $(dlldir)/aviplay.exe.so
$(INSTALL_PROGRAM) icinfo.exe.so $(dlldir)/icinfo.exe.so
install_prog.so:: $(PROGRAMS:%=%.so) install_prog: $(PROGRAMS)
$(MKINSTALLDIRS) $(bindir)
$(INSTALL_PROGRAM) aviinfo.exe.so $(bindir)/aviinfo.exe.so
$(INSTALL_PROGRAM) aviplay.exe.so $(bindir)/aviplay.exe.so
$(INSTALL_PROGRAM) icinfo.exe.so $(bindir)/icinfo.exe.so
cd $(bindir) && $(LN_S) wine aviinfo && $(LN_S) wine aviplay && $(LN_S) wine icinfo
install_prog:: $(PROGRAMS)
$(MKINSTALLDIRS) $(bindir) $(MKINSTALLDIRS) $(bindir)
$(INSTALL_PROGRAM) aviinfo.exe $(bindir)/aviinfo.exe $(INSTALL_PROGRAM) aviinfo.exe $(bindir)/aviinfo.exe
$(INSTALL_PROGRAM) aviplay.exe $(bindir)/aviplay.exe $(INSTALL_PROGRAM) aviplay.exe $(bindir)/aviplay.exe
$(INSTALL_PROGRAM) icinfo.exe $(bindir)/icinfo.exe $(INSTALL_PROGRAM) icinfo.exe $(bindir)/icinfo.exe
uninstall_prog.so:
$(RM) $(PROGRAMS:%=$(dlldir)/%.so)
uninstall_prog:
$(RM) $(PROGRAMS:%=$(bindir)/%)
install:: install_prog$(DLLEXT) install:: install_prog$(DLLEXT)
uninstall:: uninstall:: uninstall_prog$(DLLEXT)
$(RM) $(PROGRAMS:%=$(bindir)/%$(DLLEXT)) $(PROGRAMS:%.exe=$(bindir)/%)
clean::
$(RM) $(PROGRAMS:.exe=)
# Rules for checking that no imports are missing
CHECKLINK_RPATH = library tsx11 unicode
checklink:: $(PROGRAMS:%=%.so) checklink:: $(PROGRAMS:%=%.so)
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c aviinfo.exe.so && $(RM) checklink $(CC) -o checklink $(CHECKLINK_RPATH:%=-Wl,-rpath,$(TOPOBJDIR)/%) $(TOPSRCDIR)/library/checklink.c aviinfo.exe.so && $(RM) checklink
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c aviplay.exe.so && $(RM) checklink $(CC) -o checklink $(CHECKLINK_RPATH:%=-Wl,-rpath,$(TOPOBJDIR)/%) $(TOPSRCDIR)/library/checklink.c aviplay.exe.so && $(RM) checklink
$(CC) -o checklink $(TOPSRCDIR)/library/checklink.c icinfo.exe.so && $(RM) checklink $(CC) -o checklink $(CHECKLINK_RPATH:%=-Wl,-rpath,$(TOPOBJDIR)/%) $(TOPSRCDIR)/library/checklink.c icinfo.exe.so && $(RM) checklink
### Dependencies: ### Dependencies:

52
programs/wineapploader.in Executable file
View File

@ -0,0 +1,52 @@
#!/bin/sh
#
# Wrapper script to start a Winelib application once it is installed
#
# Copyright (C) 2002 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
#
# determine the app Winelib library name
appname=`basename "$0" .exe`.exe
# first try explicit WINELOADER
if [ -x "$WINELOADER" ]; then exec "$WINELOADER" "$appname" "$@"; fi
# then default bin directory
if [ -x "@bindir@/wine" ]; then exec "@bindir@/wine" "$appname" "$@"; fi
# now try the directory containing $0
appdir=""
case "$0" in
*/*)
# $0 contains a path, use it
appdir=`dirname "$0"`
;;
*)
# no directory in $0, search in PATH
saved_ifs=$IFS
IFS=:
for d in $PATH
do
IFS=$saved_ifs
if [ -x "$d/$0" ]; then appdir="$d"; break; fi
done
;;
esac
if [ -x "$appdir/wine" ]; then exec "$appdir/wine" "$appname" "$@"; fi
# finally look in PATH
exec wine "$appname" "$@"

View File

@ -28,13 +28,6 @@ all: wtmain.o
wine.c: wine.xs wine.c: wine.xs
perl $(XSUBPPDIR)/xsubpp -typemap $(XSUBPPDIR)/typemap $(SRCDIR)/wine.xs >wine.c || $(RM) wine.c perl $(XSUBPPDIR)/xsubpp -typemap $(XSUBPPDIR)/typemap $(SRCDIR)/wine.xs >wine.c || $(RM) wine.c
install::
$(MKINSTALLDIRS) $(libdir)
$(INSTALL_DATA) wine.pm $(libdir)/wine.pm
uninstall::
$(RM) $(libdir)/wine.pm
clean:: clean::
$(RM) wine.c $(RM) wine.c

View File

@ -119,11 +119,12 @@ if (defined($topobjdir))
{ {
chop($topobjdir = `cd $topobjdir && pwd`); chop($topobjdir = `cd $topobjdir && pwd`);
$ENV{LD_LIBRARY_PATH} = $topobjdir . ":" . $ENV{LD_LIBRARY_PATH}; $ENV{LD_LIBRARY_PATH} = $topobjdir . ":" . $ENV{LD_LIBRARY_PATH};
$ENV{WINEDLLPATH} = $topobjdir . "/dlls"; $ENV{WINEDLLPATH} = $topobjdir . "/dlls:" . $topobjdir . "/programs";
$ENV{WINESERVER} = $topobjdir . "/server/wineserver"; $ENV{WINESERVER} = $topobjdir . "/server/wineserver";
$ENV{WINELOADER} = $topobjdir . "/wine"; $ENV{WINELOADER} = $topobjdir . "/wine";
$ENV{WINETEST_PLATFORM} = $platform || "wine"; $ENV{WINETEST_PLATFORM} = $platform || "wine";
$program ||= $topobjdir . "/programs/winetest/winetest"; $program ||= "winetest.exe";
exec $ENV{WINELOADER}, $program, $infile, @ARGV;
} }
else else
{ {
@ -131,7 +132,7 @@ else
} }
# and now exec the program # and now exec the program
$program ||= "winetest"; $program ||= "winetest.exe";
exec $program, $infile, @ARGV; exec $program, $infile, @ARGV;
print STDERR "Could not exec $program\n"; print STDERR "Could not exec $program\n";
exit 1; exit 1;

View File

@ -488,24 +488,12 @@ static void start_server( const char *oldcwd )
{ {
strcpy( p, "/wineserver" ); strcpy( p, "/wineserver" );
execl( path, "wineserver", NULL ); execl( path, "wineserver", NULL );
strcpy( p, "/server/wineserver" );
execl( path, "wineserver", NULL );
} }
free(path); free(path);
} }
/* now try the path */ /* finally try the path */
execlp( "wineserver", "wineserver", NULL ); execlp( "wineserver", "wineserver", NULL );
/* and finally the current dir */
if (!(path = malloc( strlen(oldcwd) + 20 )))
fatal_error( "out of memory\n" );
p = strcpy( path, oldcwd ) + strlen( oldcwd );
strcpy( p, "/wineserver" );
execl( path, "wineserver", NULL );
strcpy( p, "/server/wineserver" );
execl( path, "wineserver", NULL );
free(path);
fatal_error( "could not exec wineserver\n" ); fatal_error( "could not exec wineserver\n" );
} }
started = 1; started = 1;

View File

@ -36,6 +36,7 @@
#include "drive.h" #include "drive.h"
#include "module.h" #include "module.h"
#include "file.h" #include "file.h"
#include "heap.h"
#include "thread.h" #include "thread.h"
#include "winerror.h" #include "winerror.h"
#include "wincon.h" #include "wincon.h"
@ -236,6 +237,118 @@ void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule )
proc( uCode, GetCurrentProcessId(), dwFlags, hModule ); proc( uCode, GetCurrentProcessId(), dwFlags, hModule );
} }
/***********************************************************************
* get_basename
*/
inline static const char *get_basename( const char *name )
{
char *p;
if ((p = strrchr( name, '/' ))) name = p + 1;
if ((p = strrchr( name, '\\' ))) name = p + 1;
return name;
}
/***********************************************************************
* open_exe_file
*
* Open an exe file, taking load order into account.
* Returns the file handle or 0 for a builtin exe.
*/
static HANDLE open_exe_file( const char *name )
{
enum loadorder_type loadorder[LOADORDER_NTYPES];
HANDLE handle;
int i;
SetLastError( ERROR_FILE_NOT_FOUND );
MODULE_GetLoadOrder( loadorder, name, TRUE );
for(i = 0; i < LOADORDER_NTYPES; i++)
{
if (loadorder[i] == LOADORDER_INVALID) break;
switch(loadorder[i])
{
case LOADORDER_DLL:
TRACE( "Trying native exe %s\n", debugstr_a(name) );
if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE)
return handle;
if (GetLastError() != ERROR_FILE_NOT_FOUND) return INVALID_HANDLE_VALUE;
break;
case LOADORDER_BI:
TRACE( "Trying built-in exe %s\n", debugstr_a(name) );
if (wine_dll_load_main_exe( get_basename(name), NULL, 0, 1 )) return 0;
break;
default:
break;
}
}
return INVALID_HANDLE_VALUE;
}
/***********************************************************************
* find_exe_file
*
* Open an exe file, and return the full name and file handle.
* Returns FALSE if file could not be found.
* If file exists but cannot be opened, returns TRUE and set handle to INVALID_HANDLE_VALUE.
* If file is a builtin exe, returns TRUE and sets handle to 0.
*/
static BOOL find_exe_file( const char *name, char *buffer, int buflen, HANDLE *handle )
{
enum loadorder_type loadorder[LOADORDER_NTYPES];
int i;
TRACE("looking for %s\n", debugstr_a(name) );
if (SearchPathA( NULL, name, ".exe", buflen, buffer, NULL ))
{
*handle = open_exe_file( buffer );
return TRUE;
}
/* no such file in path, try builtin with .exe extension */
lstrcpynA( buffer, get_basename(name), buflen );
if (!strchr( buffer, '.' ))
{
char *p = buffer + strlen(buffer);
lstrcpynA( p, ".exe", buflen - (p - buffer) );
}
MODULE_GetLoadOrder( loadorder, buffer, TRUE );
for (i = 0; i < LOADORDER_NTYPES; i++)
{
if (loadorder[i] == LOADORDER_BI)
{
TRACE( "Trying built-in exe %s\n", debugstr_a(buffer) );
if (wine_dll_load_main_exe( buffer, NULL, 0, 1 ))
{
*handle = 0;
return TRUE;
}
break;
}
if (loadorder[i] == LOADORDER_INVALID) break;
}
/* no builtin found, try native without extension in case it is a Unix app */
if (SearchPathA( NULL, name, NULL, buflen, buffer, NULL ))
{
TRACE( "Trying native/Unix binary %s\n", debugstr_a(buffer) );
if ((*handle = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE)
return TRUE;
}
return FALSE;
}
/*********************************************************************** /***********************************************************************
* process_init * process_init
* *
@ -266,16 +379,13 @@ static BOOL process_init( char *argv[] )
{ {
req->ldt_copy = &wine_ldt_copy; req->ldt_copy = &wine_ldt_copy;
req->ppid = getppid(); req->ppid = getppid();
wine_server_set_reply( req, main_exe_name, sizeof(main_exe_name)-1 );
if ((ret = !wine_server_call_err( req ))) if ((ret = !wine_server_call_err( req )))
{ {
size_t len = wine_server_reply_size( reply ); main_exe_file = reply->exe_file;
main_exe_name[len] = 0; main_create_flags = reply->create_flags;
main_exe_file = reply->exe_file; info_size = reply->info_size;
main_create_flags = reply->create_flags; info = reply->info;
info_size = reply->info_size; server_startticks = reply->server_start;
info = reply->info;
server_startticks = reply->server_start;
current_startupinfo.hStdInput = reply->hstdin; current_startupinfo.hStdInput = reply->hstdin;
current_startupinfo.hStdOutput = reply->hstdout; current_startupinfo.hStdOutput = reply->hstdout;
current_startupinfo.hStdError = reply->hstderr; current_startupinfo.hStdError = reply->hstderr;
@ -418,58 +528,6 @@ static void start_process(void)
} }
/***********************************************************************
* open_winelib_app
*
* Try to open the Winelib app .so file based on argv[0] or WINEPRELOAD.
*/
void *open_winelib_app( char *argv[] )
{
void *ret = NULL;
char *tmp;
const char *name;
char errStr[100];
if ((name = getenv( "WINEPRELOAD" )))
{
if (!(ret = wine_dll_load_main_exe( name, 0, errStr, sizeof(errStr) )))
{
MESSAGE( "%s: could not load '%s' as specified in the WINEPRELOAD environment variable: %s\n",
argv[0], name, errStr );
ExitProcess(1);
}
}
else
{
const char *argv0 = main_exe_name;
if (!*argv0)
{
/* if argv[0] is "wine", don't try to load anything */
argv0 = argv[0];
if (!(name = strrchr( argv0, '/' ))) name = argv0;
else name++;
if (!strcmp( name, "wine" )) return NULL;
}
/* now try argv[0] with ".so" appended */
if ((tmp = HeapAlloc( GetProcessHeap(), 0, strlen(argv0) + 8 )))
{
strcpy( tmp, argv0 );
strcat( tmp, ".exe.so" );
/* search in PATH only if there was no '/' in argv[0] */
ret = wine_dll_load_main_exe( tmp, (name == argv0), errStr, sizeof(errStr) );
if (!ret && !argv[1] && !main_exe_name[0])
{
/* if no argv[1], this will be better than displaying usage */
MESSAGE( "%s: could not load library '%s' as Winelib application: %s\n",
argv[0], tmp, errStr );
ExitProcess(1);
}
HeapFree( GetProcessHeap(), 0, tmp );
}
}
return ret;
}
/*********************************************************************** /***********************************************************************
* PROCESS_InitWine * PROCESS_InitWine
* *
@ -477,54 +535,86 @@ void *open_winelib_app( char *argv[] )
*/ */
void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file ) void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file )
{ {
char error[100];
DWORD stack_size = 0; DWORD stack_size = 0;
/* Initialize everything */ /* Initialize everything */
if (!process_init( argv )) exit(1); if (!process_init( argv )) exit(1);
if (open_winelib_app( argv )) goto found; /* try to open argv[0] as a winelib app */
argv++; /* remove argv[0] (wine itself) */ argv++; /* remove argv[0] (wine itself) */
TRACE( "starting process name=%s file=%x argv[0]=%s\n",
debugstr_a(main_exe_name), main_exe_file, debugstr_a(argv[0]) );
if (!main_exe_name[0]) if (!main_exe_name[0])
{ {
if (!argv[0]) OPTIONS_Usage(); if (!argv[0]) OPTIONS_Usage();
/* open the exe file */ if (!find_exe_file( argv[0], main_exe_name, sizeof(main_exe_name), &main_exe_file ))
if (!SearchPathA( NULL, argv[0], ".exe", sizeof(main_exe_name), main_exe_name, NULL) &&
!SearchPathA( NULL, argv[0], NULL, sizeof(main_exe_name), main_exe_name, NULL))
{ {
MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] ); MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] );
goto error; ExitProcess(1);
} }
} if (main_exe_file == INVALID_HANDLE_VALUE)
if (!main_exe_file)
{
if ((main_exe_file = CreateFileA( main_exe_name, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
{ {
MESSAGE( "%s: cannot open '%s'\n", argv0, main_exe_name ); MESSAGE( "%s: cannot open '%s'\n", argv0, main_exe_name );
goto error; ExitProcess(1);
} }
} }
/* first try Win32 format; this will fail if the file is not a PE binary */ if (!main_exe_file) /* no file handle -> Winelib app */
if ((current_process.module = PE_LoadImage( main_exe_file, main_exe_name, 0 )))
{ {
if (PE_HEADER(current_process.module)->FileHeader.Characteristics & IMAGE_FILE_DLL) TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) );
ExitProcess( ERROR_BAD_EXE_FORMAT ); if (wine_dll_load_main_exe( get_basename(main_exe_name), error, sizeof(error), 0 ))
goto found; goto found;
MESSAGE( "%s: cannot open builtin library for '%s': %s\n", argv0, main_exe_name, error );
ExitProcess(1);
} }
/* it must be 16-bit or DOS format */ switch( MODULE_GetBinaryType( main_exe_file ))
NtCurrentTeb()->tibflags &= ~TEBF_WIN32; {
current_process.flags |= PDB32_WIN16_PROC; case BINARY_UNKNOWN:
strcpy( win16_exe_name, main_exe_name ); MESSAGE( "%s: cannot determine executable type for '%s'\n", argv0, main_exe_name );
main_exe_name[0] = 0; ExitProcess(1);
*win16_exe_file = main_exe_file; case BINARY_PE_EXE:
main_exe_file = 0; TRACE( "starting Win32 binary %s\n", debugstr_a(main_exe_name) );
_EnterWin16Lock(); if ((current_process.module = PE_LoadImage( main_exe_file, main_exe_name, 0 ))) goto found;
MESSAGE( "%s: could not load '%s' as Win32 binary\n", argv0, main_exe_name );
ExitProcess(1);
case BINARY_PE_DLL:
MESSAGE( "%s: '%s' is a DLL, not an executable\n", argv0, main_exe_name );
ExitProcess(1);
case BINARY_WIN16:
case BINARY_DOS:
TRACE( "starting Win16/DOS binary %s\n", debugstr_a(main_exe_name) );
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
current_process.flags |= PDB32_WIN16_PROC;
strcpy( win16_exe_name, main_exe_name );
main_exe_name[0] = 0;
*win16_exe_file = main_exe_file;
main_exe_file = 0;
_EnterWin16Lock();
goto found;
case BINARY_OS216:
MESSAGE( "%s: '%s' is an OS/2 binary, not supported\n", argv0, main_exe_name );
ExitProcess(1);
case BINARY_UNIX_EXE:
MESSAGE( "%s: '%s' is a Unix binary, not supported\n", argv0, main_exe_name );
ExitProcess(1);
case BINARY_UNIX_LIB:
{
DOS_FULL_NAME full_name;
const char *name = main_exe_name;
TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) );
if (DOSFS_GetFullName( name, TRUE, &full_name )) name = full_name.long_name;
CloseHandle( main_exe_file );
main_exe_file = 0;
if (wine_dlopen( name, RTLD_NOW, error, sizeof(error) )) goto found;
MESSAGE( "%s: could not load '%s': %s\n", argv0, main_exe_name, error );
ExitProcess(1);
}
}
found: found:
/* build command line */ /* build command line */
@ -680,7 +770,6 @@ static char **build_envp( const char *env, const char *extra_env )
{ {
if (memcmp( p, "PATH=", 5 ) && if (memcmp( p, "PATH=", 5 ) &&
memcmp( p, "HOME=", 5 ) && memcmp( p, "HOME=", 5 ) &&
memcmp( p, "WINEPRELOAD=", 12 ) &&
memcmp( p, "WINEPREFIX=", 11 )) *envptr++ = (char *)p; memcmp( p, "WINEPREFIX=", 11 )) *envptr++ = (char *)p;
} }
*envptr = 0; *envptr = 0;
@ -734,10 +823,6 @@ static void exec_wine_binary( char **argv, char **envp )
} }
} }
free( argv[0] ); free( argv[0] );
/* finally try the current directory */
argv[0] = "./wine";
execve( argv[0], argv, envp );
} }
@ -796,43 +881,21 @@ static int fork_and_exec( const char *filename, char *cmdline,
/*********************************************************************** /***********************************************************************
* PROCESS_Create * create_process
* *
* Create a new process. If hFile is a valid handle we have an exe * Create a new process. If hFile is a valid handle we have an exe
* file, and we exec a new copy of wine to load it; otherwise we * file, otherwise it is a Winelib app.
* simply exec the specified filename as a Unix process.
*/ */
BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env, static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup, BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
LPPROCESS_INFORMATION info, LPCSTR lpCurrentDirectory ) LPPROCESS_INFORMATION info, LPCSTR unixdir )
{ {
BOOL ret; BOOL ret;
const char *unixfilename = NULL;
const char *unixdir = NULL;
DOS_FULL_NAME full_dir, full_name;
HANDLE load_done_evt = 0; HANDLE load_done_evt = 0;
HANDLE process_info; HANDLE process_info;
startup_info_t startup_info; startup_info_t startup_info;
info->hThread = info->hProcess = 0;
info->dwProcessId = info->dwThreadId = 0;
if (lpCurrentDirectory)
{
if (DOSFS_GetFullName( lpCurrentDirectory, TRUE, &full_dir ))
unixdir = full_dir.long_name;
}
else
{
char buf[MAX_PATH];
if (GetCurrentDirectoryA(sizeof(buf),buf))
{
if (DOSFS_GetFullName( buf, TRUE, &full_dir ))
unixdir = full_dir.long_name;
}
}
/* fill the startup info structure */ /* fill the startup info structure */
startup_info.size = sizeof(startup_info); startup_info.size = sizeof(startup_info);
@ -874,20 +937,11 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
req->hstderr = GetStdHandle( STD_ERROR_HANDLE ); req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
} }
if (!hFile) /* unix process */ if (GetLongPathNameA( filename, buf, MAX_PATH ))
{ nameptr = buf;
unixfilename = filename; else
if (DOSFS_GetFullName( filename, TRUE, &full_name )) nameptr = filename;
unixfilename = full_name.long_name;
nameptr = unixfilename;
}
else /* new wine process */
{
if (GetLongPathNameA( filename, buf, MAX_PATH ))
nameptr = buf;
else
nameptr = filename;
}
startup_info.filename_len = strlen(nameptr); startup_info.filename_len = strlen(nameptr);
wine_server_add_data( req, &startup_info, sizeof(startup_info) ); wine_server_add_data( req, &startup_info, sizeof(startup_info) );
wine_server_add_data( req, nameptr, startup_info.filename_len ); wine_server_add_data( req, nameptr, startup_info.filename_len );
@ -903,7 +957,7 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
/* fork and execute */ /* fork and execute */
if (fork_and_exec( unixfilename, cmd_line, env, unixdir ) == -1) if (fork_and_exec( NULL, cmd_line, env, unixdir ) == -1)
{ {
CloseHandle( process_info ); CloseHandle( process_info );
return FALSE; return FALSE;
@ -956,6 +1010,260 @@ BOOL PROCESS_Create( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
} }
/*************************************************************************
* get_file_name
*
* Helper for CreateProcess: retrieve the file name to load from the
* app name and command line. Store the file name in buffer, and
* return a possibly modified command line.
* Also returns a handle to the opened file if it's a Windows binary.
*/
static LPSTR get_file_name( LPCSTR appname, LPSTR cmdline, LPSTR buffer,
int buflen, HANDLE *handle )
{
char *name, *pos, *ret = NULL;
const char *p;
/* if we have an app name, everything is easy */
if (appname)
{
/* use the unmodified app name as file name */
lstrcpynA( buffer, appname, buflen );
*handle = open_exe_file( buffer );
if (!(ret = cmdline))
{
/* no command-line, create one */
if ((ret = HeapAlloc( GetProcessHeap(), 0, strlen(appname) + 3 )))
sprintf( ret, "\"%s\"", appname );
}
return ret;
}
if (!cmdline)
{
SetLastError( ERROR_INVALID_PARAMETER );
return NULL;
}
/* first check for a quoted file name */
if ((cmdline[0] == '"') && ((p = strchr( cmdline + 1, '"' ))))
{
int len = p - cmdline - 1;
/* extract the quoted portion as file name */
if (!(name = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return NULL;
memcpy( name, cmdline + 1, len );
name[len] = 0;
if (find_exe_file( name, buffer, buflen, handle ))
ret = cmdline; /* no change necessary */
goto done;
}
/* now try the command-line word by word */
if (!(name = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 1 ))) return NULL;
pos = name;
p = cmdline;
while (*p)
{
do *pos++ = *p++; while (*p && *p != ' ');
*pos = 0;
if (find_exe_file( name, buffer, buflen, handle ))
{
ret = cmdline;
break;
}
}
if (!ret || !strchr( name, ' ' )) goto done; /* no change necessary */
/* now build a new command-line with quotes */
if (!(ret = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 3 ))) goto done;
sprintf( ret, "\"%s\"%s", name, p );
done:
HeapFree( GetProcessHeap(), 0, name );
return ret;
}
/**********************************************************************
* CreateProcessA (KERNEL32.@)
*/
BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUTES process_attr,
LPSECURITY_ATTRIBUTES thread_attr, BOOL inherit,
DWORD flags, LPVOID env, LPCSTR cur_dir,
LPSTARTUPINFOA startup_info, LPPROCESS_INFORMATION info )
{
BOOL retv = FALSE;
HANDLE hFile = 0;
const char *unixdir = NULL;
DOS_FULL_NAME full_dir;
char name[MAX_PATH];
LPSTR tidy_cmdline;
/* Process the AppName and/or CmdLine to get module name and path */
TRACE("app %s cmdline %s\n", debugstr_a(app_name), debugstr_a(cmd_line) );
if (!(tidy_cmdline = get_file_name( app_name, cmd_line, name, sizeof(name), &hFile )))
return FALSE;
if (hFile == INVALID_HANDLE_VALUE) goto done;
/* Warn if unsupported features are used */
if (flags & NORMAL_PRIORITY_CLASS)
FIXME("(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name);
if (flags & IDLE_PRIORITY_CLASS)
FIXME("(%s,...): IDLE_PRIORITY_CLASS ignored\n", name);
if (flags & HIGH_PRIORITY_CLASS)
FIXME("(%s,...): HIGH_PRIORITY_CLASS ignored\n", name);
if (flags & REALTIME_PRIORITY_CLASS)
FIXME("(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name);
if (flags & CREATE_NEW_PROCESS_GROUP)
FIXME("(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name);
if (flags & CREATE_UNICODE_ENVIRONMENT)
FIXME("(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name);
if (flags & CREATE_SEPARATE_WOW_VDM)
FIXME("(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name);
if (flags & CREATE_SHARED_WOW_VDM)
FIXME("(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name);
if (flags & CREATE_DEFAULT_ERROR_MODE)
FIXME("(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name);
if (flags & CREATE_NO_WINDOW)
FIXME("(%s,...): CREATE_NO_WINDOW ignored\n", name);
if (flags & PROFILE_USER)
FIXME("(%s,...): PROFILE_USER ignored\n", name);
if (flags & PROFILE_KERNEL)
FIXME("(%s,...): PROFILE_KERNEL ignored\n", name);
if (flags & PROFILE_SERVER)
FIXME("(%s,...): PROFILE_SERVER ignored\n", name);
if (startup_info->lpDesktop)
FIXME("(%s,...): startup_info->lpDesktop %s ignored\n",
name, debugstr_a(startup_info->lpDesktop));
if (startup_info->dwFlags & STARTF_RUNFULLSCREEN)
FIXME("(%s,...): STARTF_RUNFULLSCREEN ignored\n", name);
if (startup_info->dwFlags & STARTF_FORCEONFEEDBACK)
FIXME("(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name);
if (startup_info->dwFlags & STARTF_FORCEOFFFEEDBACK)
FIXME("(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name);
if (startup_info->dwFlags & STARTF_USEHOTKEY)
FIXME("(%s,...): STARTF_USEHOTKEY ignored\n", name);
if (cur_dir)
{
if (DOSFS_GetFullName( cur_dir, TRUE, &full_dir ))
unixdir = full_dir.long_name;
}
else
{
char buf[MAX_PATH];
if (GetCurrentDirectoryA(sizeof(buf),buf))
{
if (DOSFS_GetFullName( buf, TRUE, &full_dir )) unixdir = full_dir.long_name;
}
}
info->hThread = info->hProcess = 0;
info->dwProcessId = info->dwThreadId = 0;
/* Determine executable type */
if (!hFile) /* builtin exe */
{
TRACE( "starting %s as Winelib app\n", debugstr_a(name) );
retv = create_process( 0, name, tidy_cmdline, env, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir );
goto done;
}
switch( MODULE_GetBinaryType( hFile ))
{
case BINARY_PE_EXE:
case BINARY_WIN16:
case BINARY_DOS:
TRACE( "starting %s as Windows binary\n", debugstr_a(name) );
retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir );
break;
case BINARY_OS216:
FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) );
SetLastError( ERROR_BAD_EXE_FORMAT );
break;
case BINARY_PE_DLL:
TRACE( "not starting %s since it is a dll\n", debugstr_a(name) );
SetLastError( ERROR_BAD_EXE_FORMAT );
break;
case BINARY_UNIX_LIB:
TRACE( "%s is a Unix library, starting as Winelib app\n", debugstr_a(name) );
retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
inherit, flags, startup_info, info, unixdir );
break;
case BINARY_UNIX_EXE:
case BINARY_UNKNOWN:
{
/* unknown file, try as unix executable */
DOS_FULL_NAME full_name;
const char *unixfilename = name;
TRACE( "starting %s as Unix binary\n", debugstr_a(name) );
if (DOSFS_GetFullName( name, TRUE, &full_name )) unixfilename = full_name.long_name;
retv = (fork_and_exec( unixfilename, tidy_cmdline, env, unixdir ) != -1);
}
break;
}
CloseHandle( hFile );
done:
if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline );
return retv;
}
/**********************************************************************
* CreateProcessW (KERNEL32.@)
* NOTES
* lpReserved is not converted
*/
BOOL WINAPI CreateProcessW( LPCWSTR app_name, LPWSTR cmd_line, LPSECURITY_ATTRIBUTES process_attr,
LPSECURITY_ATTRIBUTES thread_attr, BOOL inherit, DWORD flags,
LPVOID env, LPCWSTR cur_dir, LPSTARTUPINFOW startup_info,
LPPROCESS_INFORMATION info )
{
BOOL ret;
STARTUPINFOA StartupInfoA;
LPSTR app_nameA = HEAP_strdupWtoA (GetProcessHeap(),0,app_name);
LPSTR cmd_lineA = HEAP_strdupWtoA (GetProcessHeap(),0,cmd_line);
LPSTR cur_dirA = HEAP_strdupWtoA (GetProcessHeap(),0,cur_dir);
memcpy (&StartupInfoA, startup_info, sizeof(STARTUPINFOA));
StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,startup_info->lpDesktop);
StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,startup_info->lpTitle);
TRACE_(win32)("(%s,%s,...)\n", debugstr_w(app_name), debugstr_w(cmd_line));
if (startup_info->lpReserved)
FIXME_(win32)("StartupInfo.lpReserved is used, please report (%s)\n",
debugstr_w(startup_info->lpReserved));
ret = CreateProcessA( app_nameA, cmd_lineA, process_attr, thread_attr,
inherit, flags, env, cur_dirA, &StartupInfoA, info );
HeapFree( GetProcessHeap(), 0, cur_dirA );
HeapFree( GetProcessHeap(), 0, cmd_lineA );
HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop );
HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle );
return ret;
}
/*********************************************************************** /***********************************************************************
* ExitProcess (KERNEL32.@) * ExitProcess (KERNEL32.@)
*/ */

92
tools/winewrapper Executable file
View File

@ -0,0 +1,92 @@
#!/bin/sh
#
# Wrapper script to run Wine and Winelib apps from inside the source tree
#
# Copyright (C) 2002 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
#
# first determine the directory that contains the app itself
appdir=""
case "$0" in
*/*)
# $0 contains a path, use it
appdir=`dirname "$0"`
;;
*)
# no directory in $0, search in PATH
saved_ifs=$IFS
IFS=:
for d in $PATH
do
IFS=$saved_ifs
if [ -x "$d/$0" ]
then
appdir="$d"
break
fi
done
;;
esac
# now find the top-level directory of the source tree
if [ -x "$appdir/server/wineserver" ]
then topdir="$appdir"
elif [ -x "$appdir/../server/wineserver" ]
then topdir="$appdir/.."
elif [ -x "$appdir/../../server/wineserver" ]
then topdir="$appdir/../.."
elif [ -x "$appdir/../../../server/wineserver" ]
then topdir="$appdir/../../.."
else
echo "$0: could not locate Wine source tree"
exit 1
fi
# setup the environment
topdir=`cd "$topdir" && pwd`
if [ -n "$LD_LIBRARY_PATH" ]
then
LD_LIBRARY_PATH="$topdir/dlls:$topdir/library:$topdir/unicode:$topdir/tsx11:$LD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$topdir/dlls:$topdir/library:$topdir/unicode:$topdir/tsx11"
fi
WINEDLLPATH="$topdir/dlls:$topdir/programs"
WINESERVER="$topdir/server/wineserver"
WINELOADER="$topdir/miscemu/wine"
export LD_LIBRARY_PATH WINEDLLPATH WINESERVER WINELOADER
# and run the application
case "$0" in
wine|*/wine)
exec "$WINELOADER" "$@"
;;
*/*)
[ -f "$0.exe.so" ] && exec "$WINELOADER" "$0.exe.so" "$@"
echo "$0: cannot find corresponding application"
exit 1
;;
*)
[ -f "$appdir/$0.exe.so" ] && exec "$WINELOADER" "$appdir/$0.exe.so" "$@"
echo "$0: cannot find corresponding application"
exit 1
;;
esac

View File

@ -82,7 +82,7 @@ static BOOL start_console_renderer(void)
STARTUPINFOA si; STARTUPINFOA si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
HANDLE hEvent = 0; HANDLE hEvent = 0;
LPSTR p, path = NULL; LPSTR p;
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
attr.Length = sizeof(attr); attr.Length = sizeof(attr);
@ -109,55 +109,6 @@ static BOOL start_console_renderer(void)
ERR("Couldn't launch Wine console from WINECONSOLE env var... trying default access\n"); ERR("Couldn't launch Wine console from WINECONSOLE env var... trying default access\n");
} }
/* then the regular installation dir */
ret = snprintf(buffer, sizeof(buffer), "%s --use-event=%d", BINDIR "/wineconsole", hEvent);
if ((ret > -1) && (ret < sizeof(buffer)) &&
CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
goto succeed;
/* then try the dir where we were started from */
if ((path = HeapAlloc(GetProcessHeap(), 0, strlen(full_argv0) + sizeof(buffer))))
{
int n;
if ((p = strrchr(strcpy( path, full_argv0 ), '/')))
{
p++;
sprintf(p, "wineconsole --use-event=%d", hEvent);
if (CreateProcessA(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
goto succeed;
sprintf(p, "programs/wineconsole/wineconsole --use-event=%d", hEvent);
if (CreateProcessA(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
goto succeed;
}
n = readlink(full_argv0, buffer, sizeof(buffer));
if (n != -1 && n < sizeof(buffer))
{
buffer[n] = 0;
if (buffer[0] == '/') /* absolute path ? */
strcpy(path, buffer);
else if ((p = strrchr(strcpy( path, full_argv0 ), '/')))
{
strcpy(p + 1, buffer);
}
else *path = 0;
if ((p = strrchr(path, '/')))
{
p++;
sprintf(p, "wineconsole --use-event=%d", hEvent);
if (CreateProcessA(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
goto succeed;
sprintf(p, "programs/wineconsole/wineconsole --use-event=%d", hEvent);
if (CreateProcessA(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
goto succeed;
}
} else perror("readlink");
HeapFree(GetProcessHeap(), 0, path); path = NULL;
}
/* then try the regular PATH */ /* then try the regular PATH */
sprintf(buffer, "wineconsole --use-event=%d\n", hEvent); sprintf(buffer, "wineconsole --use-event=%d\n", hEvent);
if (CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi)) if (CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
@ -166,7 +117,6 @@ static BOOL start_console_renderer(void)
goto the_end; goto the_end;
succeed: succeed:
if (path) HeapFree(GetProcessHeap(), 0, path);
if (WaitForSingleObject(hEvent, INFINITE) != WAIT_OBJECT_0) goto the_end; if (WaitForSingleObject(hEvent, INFINITE) != WAIT_OBJECT_0) goto the_end;
CloseHandle(hEvent); CloseHandle(hEvent);
@ -176,7 +126,6 @@ static BOOL start_console_renderer(void)
the_end: the_end:
ERR("Can't allocate console\n"); ERR("Can't allocate console\n");
if (path) HeapFree(GetProcessHeap(), 0, path);
CloseHandle(hEvent); CloseHandle(hEvent);
return FALSE; return FALSE;
} }

View File

@ -87,7 +87,7 @@
# #
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug] [HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug]
# command line to start a debugger when an exception occurs # command line to start a debugger when an exception occurs
"Debugger"="debugger/winedbg %ld %ld" "Debugger"="winedbg %ld %ld"
# to 0 if a message box has to be presented before running the debugger # to 0 if a message box has to be presented before running the debugger
"Auto"="1" "Auto"="1"