From 641ee76ace46cbe950b27bc249d2972f446b12e2 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 4 Aug 1997 16:34:36 +0000 Subject: [PATCH] Release 970804 Sun Aug 3 14:03:43 1997 Alexandre Julliard * [documentation/Makefile.in] Create links for files included from wine.texinfo. * [wine.man] Moved to documentation dir. * [if1632/builtin.c] Made SYSTEM.DLL always loaded by default. * [loader/signal.c] [if1632/signal.c] Split signal.c in generic/emulator-specific parts. * [misc/system.c] [if1632/thunk.c] Implemented system timer functions. Fixed InquireSystem parameters. * [msdos/ioports.c] Defined inb/outb functions to avoid including asm/io.h. Use the right instruction for word and dword direct access. * [multimedia/mmsystem.c] Fixed CallTo16 usage. Sat Aug 2 13:05:23 1997 Andreas Mohr <100.30936@germany.net> * [controls/edit.c] When text is inserted into a newly created editline, the caret is placed after the text. Should be placed before the text. Fixed. * [files/file.c] Removed O_TRUNC flag from OF_WRITE mode in _lopen32(). According to doc _lopen() never truncates files. * [if1632/user.spec] [misc/comm.c] Added stub for EnableCommNotification(). * [misc/ver.c] Fixed problem with VerQueryValue*() running over end of name table in rare cases. * [msdos/int21.c] Enhanced ioctlGetDeviceInfo() to correctly return the current drive. * [multimedia/joystick.c] [windows/message.c] Added joystick support !!! Needs Linux >= 2.1.45 or joystick-0.8.0.tar.gz. Fri Aug 1 18:02:09 1997 Morten Welinder * [if1632/user32.spec] Define DrawAnimatedRects32. * [graphics/painting.c] (DrawAnimatedRects32): Create stub. * [misc/registry.c] Cope with NULL class in RegQueryInfoKey32A. * [if1632/user32.spec] Add GetMenuItemInfo32[AW]. * [controls/menu.c] (InsertMenu32A): Upgrade flags to 8 hex-digits. (MENUEX_ParseResource): First shot at implementation. (LoadMenuIndirect32A): Handle extended menus. (GetMenuItemInfo32[AW]): First shot at implementation. * [include/windows.h] Define MFT_*, MFS_*, MIIM_* macros. Define MENUITEMINFO[AW] structures and pointers. * [Makefile.in] (etags): Add TAGS as target. * [if1632/comctl32.spec] Use Windows 95's ordinals. Add a few missing stubs. Thu Jul 31 14:01:13 1997 Marcus Meissner * [objects/color.c] Fix for 16 color mode of XFree. * [if1632/kernel32.spec][win32/ordinals.c] Moved/added some ordinal only exported functions from kernel32.dll (mostly thunking preparation stuff). Wed Jul 30 09:16:38 1997 John Harvey * [graphics/win16drv/init.c] [include/win16drv.h] Escape(SETABORTPROC) returns success to keep pbrush.exe happy. Escape(NEXTBAND) implemented to make HP PCL printer driver work in word. Stub for PATBLT added to start work on printing more than text. Mon Jul 28 13:14:28 1997 Victor Schneider * [libtest/expand.c] New Winelib test program. Wed Jul 23 09:37:13 1997 Adrian Harvey * [tools/build.c] [tools/build-spec.txt] [if1632/kernel.spec] [if1632/user.spec] Added ability to set filename wine considers the built-in DLLs to be in to something other than name.DLL with new "file" key in .spec files. Made kernel filename KRNL386.EXE (some programs use this name explicitly - ChemOffice install now starts up). Made user filename USER.EXE (just to be tidy). Sun Jul 20 23:51:02 1997 David A. Cuthbert * [controls/menu.c] [misc/tweak.c] [include/tweak.h] Fixed MENU_KeyLeft and MENU_KeyRight to handle multiple-column menus. Misc menu drawing issues for Win95 tweaks fixed. Misc warnings fixed. * [loader/module.c] Spaces are now permitted in file/path names on the command line. If multiple matches can be made, the preferred match is the path/file with fewer spaces. Tue Jul 29 02:21:15 1997 Bruce Milner * [misc/compobj.c] Added CLSIDFromString and StringFromCLSID. --- ANNOUNCE | 16 +- BUGS | 6 +- ChangeLog | 130 +++ Make.rules.in | 20 +- Makefile.in | 76 +- configure | 82 +- configure.in | 4 + controls/edit.c | 6 +- controls/menu.c | 325 +++++++- documentation/Makefile.in | 37 +- wine.man => documentation/wine.man | 0 documentation/wine.texinfo | 1207 ++++++++++++++++++++++++++-- files/directory.c | 6 +- files/file.c | 2 +- graphics/painting.c | 11 + graphics/win16drv/init.c | 75 +- if1632/Makefile.in | 1 + if1632/builtin.c | 2 +- if1632/comctl32.spec | 101 +-- if1632/compobj.spec | 4 +- if1632/gdi.spec | 1 + if1632/kernel.spec | 7 +- if1632/kernel32.spec | 33 +- if1632/signal.c | 124 +++ if1632/system.spec | 10 +- if1632/thunk.c | 28 +- if1632/user.spec | 3 +- if1632/user32.spec | 6 +- include/callback.h | 4 + include/compobj.h | 16 + include/miscemu.h | 13 +- include/module.h | 1 + include/tweak.h | 4 +- include/win16drv.h | 2 + include/windows.h | 68 ++ library/miscstubs.c | 4 - libtest/Makefile.in | 6 +- libtest/expand.c | 76 ++ loader/main.c | 15 +- loader/module.c | 250 +++--- loader/ne_image.c | 4 +- loader/resource.c | 2 +- loader/signal.c | 267 ++---- loader/task.c | 14 +- memory/ldt.c | 28 +- memory/local.c | 2 +- misc/comm.c | 44 +- misc/compobj.c | 110 +++ misc/registry.c | 7 +- misc/system.c | 168 +++- misc/tweak.c | 135 +++- misc/ver.c | 29 +- misc/winsock.c | 3 +- misc/wsprintf.c | 9 +- miscemu/instr.c | 5 +- msdos/int21.c | 16 +- msdos/ioports.c | 211 +++-- multimedia/joystick.c | 189 ++++- multimedia/mmsystem.c | 3 +- objects/color.c | 24 +- programs/progman/ChangeLog | 5 + programs/progman/grpfile.c | 126 ++- scheduler/process.c | 103 +-- scheduler/thread.c | 1 + tools/build-spec.txt | 9 +- tools/build.c | 17 +- win32/Makefile.in | 1 + win32/ordinals.c | 430 ++++++++++ windows/class.c | 13 +- windows/dialog.c | 7 + windows/message.c | 5 + windows/queue.c | 3 +- windows/win.c | 4 + 73 files changed, 3856 insertions(+), 920 deletions(-) rename wine.man => documentation/wine.man (100%) create mode 100644 if1632/signal.c create mode 100644 include/compobj.h create mode 100644 libtest/expand.c create mode 100644 win32/ordinals.c diff --git a/ANNOUNCE b/ANNOUNCE index bcff67442e3..73a0d1a0325 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,13 +1,13 @@ -This is release 970720 of Wine, the MS Windows emulator. This is still a +This is release 970804 of Wine, the MS Windows emulator. This is still a developer's only release. There are many bugs and many unimplemented API features. Most applications still do not work correctly. Patches should be submitted to "julliard@lrc.epfl.ch". Please don't forget to include a ChangeLog entry. -WHAT'S NEW with Wine-970720: (see ChangeLog for details) - - Preliminary Win95 look&feel implementation. - - Start of texinfo documentation. +WHAT'S NEW with Wine-970804: (see ChangeLog for details) + - Joystick support. + - More Win32 stuff. - Lots of bug fixes. See the README file in the distribution for installation instructions. @@ -16,10 +16,10 @@ Because of lags created by using mirror, this message may reach you before the release is available at the ftp sites. The sources will be available from the following locations: - ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970720.tar.gz - ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970720.tar.gz - ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970720.tar.gz - ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-970720.tar.gz + ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970804.tar.gz + ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970804.tar.gz + ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970804.tar.gz + ftp://ftp.progsoc.uts.edu.au/pub/Wine/development/Wine-970804.tar.gz It should also be available from any site that mirrors tsx-11 or sunsite. diff --git a/BUGS b/BUGS index 0d57d6899ed..74110a39a79 100644 --- a/BUGS +++ b/BUGS @@ -9,6 +9,10 @@ As of June 1997 - General: + * We need to do InsertMenuItem32[AW] and then code most of the other + inserting function in terms of this. Without this, we cannot support + all the new extended menus. Not hard, but slightly big. + * TrueType, .FON rasterizer. * No thread/process scheduling support in Win32 code. @@ -53,5 +57,3 @@ Miscellaneous: Where to look in source files: * grep for FIXME in the source files. - - diff --git a/ChangeLog b/ChangeLog index 74a428185f2..f1264adbd53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,133 @@ +---------------------------------------------------------------------- +Sun Aug 3 14:03:43 1997 Alexandre Julliard + + * [documentation/Makefile.in] + Create links for files included from wine.texinfo. + + * [wine.man] + Moved to documentation dir. + + * [if1632/builtin.c] + Made SYSTEM.DLL always loaded by default. + + * [loader/signal.c] [if1632/signal.c] + Split signal.c in generic/emulator-specific parts. + + * [misc/system.c] [if1632/thunk.c] + Implemented system timer functions. + Fixed InquireSystem parameters. + + * [msdos/ioports.c] + Defined inb/outb functions to avoid including asm/io.h. + Use the right instruction for word and dword direct access. + + * [multimedia/mmsystem.c] + Fixed CallTo16 usage. + +Sat Aug 2 13:05:23 1997 Andreas Mohr <100.30936@germany.net> + + * [controls/edit.c] + When text is inserted into a newly created editline, the caret + is placed after the text. Should be placed before the text. Fixed. + + * [files/file.c] + Removed O_TRUNC flag from OF_WRITE mode in _lopen32(). + According to doc _lopen() never truncates files. + + * [if1632/user.spec] [misc/comm.c] + Added stub for EnableCommNotification(). + + * [misc/ver.c] + Fixed problem with VerQueryValue*() running over end of name table + in rare cases. + + * [msdos/int21.c] + Enhanced ioctlGetDeviceInfo() to correctly return the current drive. + + * [multimedia/joystick.c] [windows/message.c] + Added joystick support !!! + Needs Linux >= 2.1.45 or joystick-0.8.0.tar.gz. + +Fri Aug 1 18:02:09 1997 Morten Welinder + + * [if1632/user32.spec] + Define DrawAnimatedRects32. + + * [graphics/painting.c] + (DrawAnimatedRects32): Create stub. + + * [misc/registry.c] + Cope with NULL class in RegQueryInfoKey32A. + + * [if1632/user32.spec] + Add GetMenuItemInfo32[AW]. + + * [controls/menu.c] + (InsertMenu32A): Upgrade flags to 8 hex-digits. + (MENUEX_ParseResource): First shot at implementation. + (LoadMenuIndirect32A): Handle extended menus. + (GetMenuItemInfo32[AW]): First shot at implementation. + + * [include/windows.h] + Define MFT_*, MFS_*, MIIM_* macros. Define MENUITEMINFO[AW] + structures and pointers. + + * [Makefile.in] + (etags): Add TAGS as target. + + * [if1632/comctl32.spec] + Use Windows 95's ordinals. Add a few missing stubs. + +Thu Jul 31 14:01:13 1997 Marcus Meissner + + * [objects/color.c] + Fix for 16 color mode of XFree. + + * [if1632/kernel32.spec][win32/ordinals.c] + Moved/added some ordinal only exported functions from kernel32.dll + (mostly thunking preparation stuff). + +Wed Jul 30 09:16:38 1997 John Harvey + + * [graphics/win16drv/init.c] [include/win16drv.h] + Escape(SETABORTPROC) returns success to keep pbrush.exe happy. + Escape(NEXTBAND) implemented to make HP PCL printer driver work in + word. Stub for PATBLT added to start work on printing more than + text. + +Mon Jul 28 13:14:28 1997 Victor Schneider + + * [libtest/expand.c] + New Winelib test program. + +Wed Jul 23 09:37:13 1997 Adrian Harvey + + * [tools/build.c] [tools/build-spec.txt] [if1632/kernel.spec] + [if1632/user.spec] + Added ability to set filename wine considers the built-in DLLs + to be in to something other than name.DLL with new "file" key + in .spec files. + Made kernel filename KRNL386.EXE (some programs use this name + explicitly - ChemOffice install now starts up). + Made user filename USER.EXE (just to be tidy). + +Sun Jul 20 23:51:02 1997 David A. Cuthbert + + * [controls/menu.c] [misc/tweak.c] [include/tweak.h] + Fixed MENU_KeyLeft and MENU_KeyRight to handle multiple-column + menus. Misc menu drawing issues for Win95 tweaks fixed. Misc + warnings fixed. + + * [loader/module.c] + Spaces are now permitted in file/path names on the command line. + If multiple matches can be made, the preferred match is the + path/file with fewer spaces. + +Tue Jul 29 02:21:15 1997 Bruce Milner + + * [misc/compobj.c] + Added CLSIDFromString and StringFromCLSID. + ---------------------------------------------------------------------- Sat Jul 19 13:03:01 1997 Alexandre Julliard diff --git a/Make.rules.in b/Make.rules.in index fd758a1b5dd..f6373079cc3 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -27,10 +27,14 @@ LDLIBS = @LDLIBS@ YACC = @YACC@ LEX = @LEX@ LEXLIB = @LEXLIB@ +RANLIB = @RANLIB@ +LN_S = @LN_S@ DIVINCL = -I$(TOPSRCDIR)/include -I$(TOPOBJDIR)/include -I$(SRCDIR) -I. ALLCFLAGS = $(CFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL) $(X_CFLAGS) LDCOMBINE = ld -r +AR = ar rc RM = rm -f +MKDIR = mkdir BUILD = $(TOPOBJDIR)/tools/build@PROGEXT@ MAKEDEP = $(TOPOBJDIR)/tools/makedep@PROGEXT@ WINERC = $(TOPOBJDIR)/rc/winerc@PROGEXT@ @@ -38,6 +42,20 @@ WINESTUB = $(TOPOBJDIR)/library/winestub.o SUBMAKE = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)' @SET_MAKE@ +# Installation infos + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@/man1 +manext = .1 +includedir = @includedir@/wine + OBJS = $(GEN_C_SRCS:.c=.o) $(C_SRCS:.c=.o) \ $(GEN_ASM_SRCS:.s=.o) $(ASM_SRCS:.S=.o) $(EXTRA_OBJS) @@ -96,7 +114,7 @@ depend:: $(MAKEDEP) $(C_SRCS) $(GEN_C_SRCS) $(MAKEDEP) $(DIVINCL) -C. $(GEN_C_SRCS) -C$(SRCDIR) $(C_SRCS) clean:: - $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc winerctmp.c $(GEN_C_SRCS) $(GEN_C_SRCS:.c=.h) $(GEN_ASM_SRCS) $(PROGRAMS) + $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc winerctmp.c core $(GEN_C_SRCS) $(GEN_C_SRCS:.c=.h) $(GEN_ASM_SRCS) $(PROGRAMS) dummy: diff --git a/Makefile.in b/Makefile.in index 61649fe925d..8028391251d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -3,47 +3,23 @@ # all (default): build wine # clean: remove all intermediate files # distclean: also remove all files created by configure +# install: install everything # depend: create the dependencies -# etags: Create a TAGS file for Emacs. +# etags: create a TAGS file for Emacs. # -# Author: Michael Patra -# - -# First some useful definitions - -SHELL = /bin/sh -CC = @CC@ -CFLAGS = @CFLAGS@ -OPTIONS = @OPTIONS@ -X_LIBS = @X_LIBS@ -TOPSRC = @top_srcdir@ -XPM_LIB = -lXpm -XLIB = @X_PRE_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@ -LDLIBS = @LDLIBS@ -AR = ar rc -RANLIB = @RANLIB@ -RM = rm -f -MKDIR = mkdir -SUBMAKE = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)' -@SET_MAKE@ - -# Installation infos - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -libdir = @libdir@ -mandir = @mandir@/man1 -manext = .1 -includedir = @includedir@/wine # Main target to build MAIN_TARGET = @MAIN_TARGET@ +# Directories + +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = . +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = none + COMMONSUBDIRS = \ rc \ controls \ @@ -76,6 +52,7 @@ PROGSUBDIRS = libtest programs DOCSUBDIRS = documentation +# All sub-directories ALLSUBDIRS = \ $(COMMONSUBDIRS) \ $(EMUSUBDIRS) \ @@ -83,6 +60,12 @@ ALLSUBDIRS = \ $(PROGSUBDIRS) \ $(DOCSUBDIRS) +# Sub-directories to run make depend into +DEPENDSUBDIRS = $(COMMONSUBDIRS) $(LIBSUBDIRS) $(EMUSUBDIRS) $(DOCSUBDIRS) + +# Sub-directories to run make install into +INSTALLSUBDIRS = $(DOCSUBDIRS) + COMMONOBJS = \ controls/controls.o \ files/files.o \ @@ -109,10 +92,11 @@ EMUOBJS = \ LIBOBJS = library/library.o - all: $(MAIN_TARGET) -install: install_$(MAIN_TARGET) +@MAKE_RULES@ + +install:: install_$(MAIN_TARGET) wine wine.sym: $(COMMONSUBDIRS) $(EMUSUBDIRS) dummy $(CC) -o wine $(COMMONOBJS) $(EMUOBJS) $(LDOPTIONS) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS) @@ -120,7 +104,6 @@ wine wine.sym: $(COMMONSUBDIRS) $(EMUSUBDIRS) dummy install_wine: dummy $(INSTALL_PROGRAM) wine $(bindir)/wine - $(INSTALL_DATA) $(TOPSRC)/wine.man $(mandir)/wine$(manext) libwine.a: $(COMMONSUBDIRS) $(LIBSUBDIRS) dummy $(RM) $@ @@ -146,17 +129,18 @@ $(ALLSUBDIRS): dummy install_programs: dummy @cd programs; $(SUBMAKE) install -depend: dummy - for i in $(COMMONSUBDIRS) $(LIBSUBDIRS) $(EMUSUBDIRS) $(DOCSUBDIRS); do \ - (cd $$i; $(MAKE) depend) || exit 1; \ - done +install:: + for i in $(INSTALLSUBDIRS); do (cd $$i && $(MAKE) install) || exit 1; done -etags: - etags `find . -name '*.[chS]' -print | grep -v dbgmain` +depend:: dummy + for i in $(DEPENDSUBDIRS); do (cd $$i && $(MAKE) depend) || exit 1; done -clean: +TAGS etags: + etags `find $(TOPSRCDIR) -name '*.[chS]' -print | grep -v dbgmain` + +clean:: for i in $(ALLSUBDIRS); do (cd $$i; $(MAKE) clean) || exit 1; done - for i in . include; do (cd $$i; $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc); done + for i in include; do (cd $$i; $(RM) *.o \#*\# *~ *.bak *.orig *.rej *.flc); done $(RM) wine wine.sym libwine.a libwine.so.1.0 TAGS distclean: clean @@ -169,4 +153,4 @@ configure: configure.in include/config.h.in: configure.in include/acconfig.h autoheader -l include -dummy: +### Dependencies: diff --git a/configure b/configure index bce2a755f66..d56268675ac 100755 --- a/configure +++ b/configure @@ -1872,8 +1872,29 @@ test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1877: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6 -echo "configure:1877: checking for i386_set_ldt in -li386" >&5 +echo "configure:1898: checking for i386_set_ldt in -li386" >&5 ac_lib_var=`echo i386'_'i386_set_ldt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1881,7 +1902,7 @@ else ac_save_LIBS="$LIBS" LIBS="-li386 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1913,12 +1934,14 @@ else fi +if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi + if test "x${GCC}" = "xyes" then CFLAGS="$CFLAGS -Wall" echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6 -echo "configure:1922: checking "for gcc strength-reduce bug"" >&5 +echo "configure:1945: checking "for gcc strength-reduce bug"" >&5 if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1926,7 +1949,7 @@ else ac_cv_c_gcc_strength_bug="yes" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_gcc_strength_bug="no" else @@ -1960,7 +1983,7 @@ fi echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6 -echo "configure:1964: checking "whether external symbols need an underscore prefix"" >&5 +echo "configure:1987: checking "whether external symbols need an underscore prefix"" >&5 if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1972,14 +1995,14 @@ _ac_test: .long 0 EOF cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2006: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_c_extern_prefix="yes" else @@ -2005,21 +2028,21 @@ fi if test "$MAIN_TARGET" = "libwine.so.1.0" then echo $ac_n "checking "whether we can build a dll"""... $ac_c" 1>&6 -echo "configure:2009: checking "whether we can build a dll"" >&5 +echo "configure:2032: checking "whether we can build a dll"" >&5 if eval "test \"`echo '$''{'ac_cv_c_dll'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else saved_cflags=$CFLAGS CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2046: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_c_dll="yes" else @@ -2046,12 +2069,12 @@ fi for ac_func in memmove tcgetattr usleep wait4 waitpid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2050: checking for $ac_func" >&5 +echo "configure:2073: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2099,12 +2122,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:2103: checking whether stat file-mode macros are broken" >&5 +echo "configure:2126: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2155,12 +2178,12 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:2159: checking for working const" >&5 +echo "configure:2182: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -2230,12 +2253,12 @@ EOF fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2234: checking for ANSI C header files" >&5 +echo "configure:2257: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2243,7 +2266,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2247: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2270: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2260,7 +2283,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2278,7 +2301,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2299,7 +2322,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2310,7 +2333,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2314: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : else @@ -2334,12 +2357,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2338: checking for size_t" >&5 +echo "configure:2361: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2549,6 +2572,7 @@ s%@LEXLIB@%$LEXLIB%g s%@RANLIB@%$RANLIB%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@LN_S@%$LN_S%g /@MAKE_RULES@/r $MAKE_RULES s%@MAKE_RULES@%%g diff --git a/configure.in b/configure.in index 530f1917e6f..9e97d28a102 100644 --- a/configure.in +++ b/configure.in @@ -38,9 +38,13 @@ AC_PROG_YACC AC_PROG_LEX AC_PROG_RANLIB AC_PROG_INSTALL +AC_PROG_LN_S dnl Check for -li386 for NetBSD and OpenBSD AC_CHECK_LIB(i386,i386_set_ldt,LDLIBS="$LDLIBS -li386") +dnl **** If ln -s doesn't work, use cp instead **** +if test "$ac_cv_prog_LN_S" = "ln -s"; then : ; else LN_S=cp ; fi + dnl **** Check for gcc strength-reduce bug **** if test "x${GCC}" = "xyes" diff --git a/controls/edit.c b/controls/edit.c index 469de645a17..0a8a3d487f0 100644 --- a/controls/edit.c +++ b/controls/edit.c @@ -3013,8 +3013,12 @@ static LRESULT EDIT_WM_Create(WND *wnd, LPCREATESTRUCT32A cs) * functions can be called, and in what order. */ EDIT_WM_SetFont(wnd, es, 0, FALSE); - if (cs->lpszName && *(cs->lpszName) != '\0') + if (cs->lpszName && *(cs->lpszName) != '\0') { EDIT_EM_ReplaceSel(wnd, es, FALSE, cs->lpszName); + /* if we insert text to the editline, the text scrolls out of the window, as the caret is placed after the insert pos normally; thus we reset es->selection... to 0 and update caret */ + es->selection_start = es->selection_end = 0; + EDIT_EM_ScrollCaret(wnd, es); + } return 0; } diff --git a/controls/menu.c b/controls/menu.c index d99b6cc392e..769084b31dc 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -167,7 +167,7 @@ static HMENU32 MENU_CopySysPopup(void) fprintf( stderr, "Unable to load default system menu\n" ); } - dprintf_menu( stddeb, "MENU_CopySysPopup: returning %ld.\n", hMenu ); + dprintf_menu( stddeb, "MENU_CopySysPopup: returning %d.\n", hMenu ); return hMenu; } @@ -279,6 +279,74 @@ void MENU_InitSysMenuPopup( HMENU32 hmenu, DWORD style, DWORD clsStyle ) } +/****************************************************************************** + * + * UINT32 MENU_GetStartOfNextColumn( + * HMENU32 hMenu ) + * + *****************************************************************************/ + +static UINT32 MENU_GetStartOfNextColumn( + HMENU32 hMenu ) +{ + POPUPMENU *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu); + UINT32 i = menu->FocusedItem + 1; + + if(!menu) + return NO_SELECTED_ITEM; + + if( i == NO_SELECTED_ITEM ) + return i; + + for( ; i < menu->nItems; ++i ) { + if( menu->items[i].item_flags & MF_MENUBARBREAK ) + return i; + } + + return NO_SELECTED_ITEM; +} + + +/****************************************************************************** + * + * UINT32 MENU_GetStartOfPrevColumn( + * HMENU32 hMenu ) + * + *****************************************************************************/ + +static UINT32 MENU_GetStartOfPrevColumn( + HMENU32 hMenu ) +{ + POPUPMENU const *menu = (POPUPMENU *)USER_HEAP_LIN_ADDR(hMenu); + UINT32 i; + + if( !menu ) + return NO_SELECTED_ITEM; + + if( menu->FocusedItem == 0 || menu->FocusedItem == NO_SELECTED_ITEM ) + return NO_SELECTED_ITEM; + + /* Find the start of the column */ + + for(i = menu->FocusedItem; i != 0 && + !(menu->items[i].item_flags & MF_MENUBARBREAK); + --i); /* empty */ + + if(i == 0) + return NO_SELECTED_ITEM; + + for(--i; i != 0; --i) { + if(menu->items[i].item_flags & MF_MENUBARBREAK) + break; + } + + dprintf_menu( stddeb, "MENU_GetStartOfPrevColumn: ret %d.\n", i ); + + return i; +} + + + /*********************************************************************** * MENU_FindItem * @@ -424,8 +492,8 @@ static void MENU_CalcItemSize( HDC32 hdc, MENUITEM *lpitem, HWND32 hwndOwner, DWORD dwSize; char *p; - dprintf_menu( stddeb, "MENU_CalcItemSize: HDC 0x%lx, item '%s', at " - "(%d, %d) %s\n", hdc, lpitem->text, orgX, orgY, + dprintf_menu( stddeb, "MENU_CalcItemSize: HDC %p, item '%s', at " + "(%d, %d) %s\n", (void *)hdc, lpitem->text, orgX, orgY, menuBar ? "(MenuBar)" : "" ); SetRect32( &lpitem->rect, orgX, orgY, orgX, orgY ); @@ -689,12 +757,17 @@ static void MENU_DrawMenuItem( HWND32 hwnd, HDC32 hdc, MENUITEM *lpitem, /* Draw the background */ if(TWEAK_Win95Look) { + rect.left += 2; + rect.right -= 2; + + /* if(menuBar) { --rect.left; ++rect.bottom; --rect.top; } InflateRect32( &rect, -1, -1 ); + */ } if (lpitem->item_flags & MF_HILITE) { @@ -720,16 +793,20 @@ static void MENU_DrawMenuItem( HWND32 hwnd, HDC32 hdc, MENUITEM *lpitem, if (!menuBar && (lpitem->item_flags & MF_MENUBARBREAK)) { - SelectObject32( hdc, sysColorObjects.hpenWindowFrame ); - MoveTo( hdc, rect.left, 0 ); - LineTo32( hdc, rect.left, height ); + if(TWEAK_Win95Look) + TWEAK_DrawMenuSeparatorVert95(hdc, rect.left - 1, 3, height - 3); + else { + SelectObject32( hdc, sysColorObjects.hpenWindowFrame ); + MoveTo( hdc, rect.left, 0 ); + LineTo32( hdc, rect.left, height ); + } } if (lpitem->item_flags & MF_SEPARATOR) { if(TWEAK_Win95Look) - TWEAK_DrawMenuSeparator95(hdc, rect.left + 1, - rect.top + SEPARATOR_HEIGHT / 2 + 1, - rect.right - 1); + TWEAK_DrawMenuSeparatorHoriz95(hdc, rect.left + 1, + rect.top + SEPARATOR_HEIGHT / 2 + 1, + rect.right - 1); else { SelectObject32( hdc, sysColorObjects.hpenWindowFrame ); MoveTo( hdc, rect.left, rect.top + SEPARATOR_HEIGHT/2 ); @@ -830,17 +907,19 @@ static void MENU_DrawMenuItem( HWND32 hwnd, HDC32 hdc, MENUITEM *lpitem, DT_LEFT | DT_VCENTER | DT_SINGLELINE ); } else { - ++rect.left; - ++rect.top; - ++rect.right; - ++rect.bottom; - SetTextColor32(hdc, RGB(0xff, 0xff, 0xff)); - DrawText32A( hdc, lpitem->text, i, &rect, - DT_LEFT | DT_VCENTER | DT_SINGLELINE ); - --rect.left; - --rect.top; - --rect.right; - --rect.bottom; + if (!(lpitem->item_flags & MF_HILITE)) { + ++rect.left; + ++rect.top; + ++rect.right; + ++rect.bottom; + SetTextColor32(hdc, RGB(0xff, 0xff, 0xff)); + DrawText32A( hdc, lpitem->text, i, &rect, + DT_LEFT | DT_VCENTER | DT_SINGLELINE ); + --rect.left; + --rect.top; + --rect.right; + --rect.bottom; + } SetTextColor32(hdc, RGB(0x80, 0x80, 0x80)); DrawText32A( hdc, lpitem->text, i, &rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE ); @@ -872,13 +951,16 @@ static void MENU_DrawPopupMenu( HWND32 hwnd, HDC32 hdc, HMENU32 hmenu ) RECT32 rect; GetClientRect32( hwnd, &rect ); - rect.bottom -= POPUP_YSHADE * SYSMETRICS_CYBORDER; - rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER; + +/* if(!TWEAK_Win95Look) { */ + rect.bottom -= POPUP_YSHADE * SYSMETRICS_CYBORDER; + rect.right -= POPUP_XSHADE * SYSMETRICS_CXBORDER; +/* } */ if((hPrevBrush = SelectObject32( hdc, sysColorObjects.hbrushMenu ))) { HPEN32 hPrevPen; - + Rectangle32( hdc, rect.left, rect.top, rect.right, rect.bottom ); hPrevPen = SelectObject32( hdc, GetStockObject32( NULL_PEN ) ); @@ -1380,6 +1462,68 @@ static LPCSTR MENU_ParseResource( LPCSTR res, HMENU32 hMenu, BOOL32 unicode ) } +/********************************************************************** + * MENUEX_ParseResource + * + * Parse an extended menu resource and add items to the menu. + * Return a pointer to the end of the resource. + */ +static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU32 hMenu) +{ + DWORD flags; + DWORD state; + DWORD id; + LPCWSTR str; + WORD resinfo; + + do + { + /* printf ("%p:", res); */ + + flags = GET_DWORD(res); + res += sizeof(DWORD); + state = GET_DWORD(res); + res += sizeof(DWORD); + id = GET_DWORD(res); + res += sizeof(DWORD); + resinfo = GET_WORD(res); /* FIXME: for 16-bit apps this is a byte. */ + res += sizeof(WORD); + /* Align the text on a word boundary. */ + res += (~((int)res - 1)) & 1; + str = (LPCWSTR)res; + res += (1 + lstrlen32W (str)) * sizeof(WCHAR); + /* Align the following fields on a dword boundary. */ + res += (~((int)res - 1)) & 3; + + /* FIXME: This is inefficient and cannot be optimised away by gcc. */ + { + LPSTR newstr = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); + dprintf_menu (stddeb, "Menu item: [%08lx,%08lx,%04lx,%04x,%s]\n", + flags, state, id, resinfo, newstr); + HeapFree( GetProcessHeap(), 0, newstr ); + } + + if (resinfo & 1) /* Pop-up? */ + { + DWORD helpid = GET_DWORD(res); /* FIXME: use this. */ + HMENU32 hSubMenu = CreatePopupMenu32(); + res += sizeof(DWORD); + if (!hSubMenu) return NULL; + if (!(res = MENUEX_ParseResource( res, hSubMenu))) + return NULL; + AppendMenu32W( hMenu, flags | MF_POPUP /* HACK! FIXME */, + (UINT32)hSubMenu, (LPCWSTR)str ); + } + else /* Not a popup */ + { + AppendMenu32W( hMenu, flags, id, + *(LPCWSTR)str ? (LPCWSTR)str : NULL ); + } + } while (!(resinfo & MF_END)); + return res; +} + + /*********************************************************************** * MENU_GetSubPopup * @@ -1861,10 +2005,20 @@ static void MENU_KeyLeft( MTRACKER* pmt ) { POPUPMENU *menu; HMENU32 hmenutmp, hmenuprev; + UINT32 prevcol; hmenuprev = hmenutmp = pmt->hTopMenu; menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenutmp ); + /* Try to move 1 column left (if possible) */ + if( (prevcol = MENU_GetStartOfPrevColumn( pmt->hCurrentMenu )) != + NO_SELECTED_ITEM ) { + + MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu, + prevcol, TRUE ); + return; + } + /* close topmost popup */ while (hmenutmp != pmt->hCurrentMenu) { @@ -1904,6 +2058,13 @@ static void MENU_KeyRight( MTRACKER* pmt ) { HMENU32 hmenutmp; POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( pmt->hTopMenu ); + UINT32 nextcol; + + dprintf_menu( stddeb, "MENU_KeyRight called, cur %x (%s), top %x (%s).\n", + pmt->hCurrentMenu, + ((POPUPMENU *)USER_HEAP_LIN_ADDR(pmt->hCurrentMenu))-> + items[0].text, + pmt->hTopMenu, menu->items[0].text ); if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu)) { @@ -1916,6 +2077,15 @@ static void MENU_KeyRight( MTRACKER* pmt ) if (hmenutmp != pmt->hCurrentMenu) return; } + /* Check to see if there's another column */ + if( (nextcol = MENU_GetStartOfNextColumn( pmt->hCurrentMenu )) != + NO_SELECTED_ITEM ) { + dprintf_menu( stddeb, "KeyRight: Going to %d.\n", nextcol ); + MENU_SelectItem( pmt->hOwnerWnd, pmt->hCurrentMenu, + nextcol, TRUE ); + return; + } + if (!(menu->wFlags & MF_POPUP)) /* menu bar tracking */ { if( pmt->hCurrentMenu != pmt->hTopMenu ) @@ -2687,10 +2857,10 @@ BOOL32 InsertMenu32A( HMENU32 hMenu, UINT32 pos, UINT32 flags, MENUITEM *item; if (IS_STRING_ITEM(flags) && str) - dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %04x, " + dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %08x, " "id %04x, str '%s'\n", hMenu, pos, flags, id, str ); - else dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %04x, " + else dprintf_menu( stddeb, "InsertMenu: hMenu %04x, pos %d, flags %08x, " "id %04x, str %08lx (not a string)\n", hMenu, pos, flags, id, (DWORD)str ); @@ -3341,24 +3511,36 @@ HMENU32 LoadMenuIndirect32A( LPCVOID template ) WORD version, offset; LPCSTR p = (LPCSTR)template; - dprintf_menu(stddeb,"LoadMenuIndirect16: %p\n", template ); + dprintf_menu(stddeb,"LoadMenuIndirect32A: %p\n", template ); version = GET_WORD(p); p += sizeof(WORD); - if (version) - { + switch (version) + { + case 0: + offset = GET_WORD(p); + p += sizeof(WORD) + offset; + if (!(hMenu = CreateMenu32())) return 0; + if (!MENU_ParseResource( p, hMenu, TRUE )) + { + DestroyMenu32( hMenu ); + return 0; + } + return hMenu; + case 1: + offset = GET_WORD(p); + p += sizeof(WORD) + offset; + if (!(hMenu = CreateMenu32())) return 0; + if (!MENUEX_ParseResource( p, hMenu)) + { + DestroyMenu32( hMenu ); + return 0; + } + return hMenu; + default: fprintf( stderr, "LoadMenuIndirect32A: version %d not supported.\n", version ); return 0; - } - offset = GET_WORD(p); - p += sizeof(WORD) + offset; - if (!(hMenu = CreateMenu32())) return 0; - if (!MENU_ParseResource( p, hMenu, TRUE )) - { - DestroyMenu32( hMenu ); - return 0; - } - return hMenu; + } } @@ -3382,6 +3564,73 @@ BOOL16 IsMenu16( HMENU16 hmenu ) return (menu->wMagic == MENU_MAGIC); } +/********************************************************************** + * GetMenuItemInfo32_common + */ + +static BOOL32 GetMenuItemInfo32_common ( HMENU32 hmenu, UINT32 item, + BOOL32 bypos, + LPMENUITEMINFO32A lpmii, + BOOL32 unicode) +{ + MENUITEM *menu = MENU_FindItem (&hmenu, &item, bypos); + if (!menu) return FALSE; + + if (lpmii->fMask && MIIM_TYPE) + { + lpmii->fType = menu->item_flags; + lpmii->dwTypeData = menu->text; + if (IS_STRING_ITEM (menu->item_flags)) + { + lpmii->cch = strlen (menu->text); + if (unicode) + ; /* UGH! FIXME */ + } + else + lpmii->cch = 0; + } + + if (lpmii->fMask && MIIM_STATE) + lpmii->fState = 0; /* FIXME -- not saved. */ + + if (lpmii->wID && MIIM_ID) + lpmii->fType = menu->item_id; + + if (lpmii->fMask && MIIM_SUBMENU) + lpmii->hSubMenu = menu->item_id; /* FIXME: ??? */ + + if (lpmii->fMask && MIIM_CHECKMARKS) + { + PCBITMAPS pCB = menu->pCB; + lpmii->hbmpChecked = pCB ? pCB->hCheckBit : 0; + lpmii->hbmpUnchecked = pCB ? pCB->hUnCheckBit : 0; + } + + if (lpmii->fMask && MIIM_DATA) + lpmii->dwItemData = 0; /* FIXME -- not saved. */ + + return TRUE; +} + +/********************************************************************** + * GetMenuItemInfo32A (USER32.263) + */ +BOOL32 GetMenuItemInfo32A( HMENU32 hmenu, UINT32 item, BOOL32 bypos, + LPMENUITEMINFO32A lpmii) +{ + return GetMenuItemInfo32_common (hmenu, item, bypos, lpmii, FALSE); +} + +/********************************************************************** + * GetMenuItemInfo32W (USER32.264) + */ +BOOL32 GetMenuItemInfo32W( HMENU32 hmenu, UINT32 item, BOOL32 bypos, + LPMENUITEMINFO32W lpmii) +{ + return GetMenuItemInfo32_common (hmenu, item, bypos, + (LPMENUITEMINFO32A)lpmii, TRUE); +} + /********************************************************************** * IsMenu32 (USER32.345) diff --git a/documentation/Makefile.in b/documentation/Makefile.in index 2e6c4a7dca1..fe1be2bff58 100644 --- a/documentation/Makefile.in +++ b/documentation/Makefile.in @@ -4,24 +4,43 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = none +INCLUDES = \ + AUTHORS \ + LICENSE \ + WARRANTY + SOURCES = \ wine.texinfo \ - $(TOPSRCDIR)/AUTHORS \ - $(TOPSRCDIR)/LICENSE \ - $(TOPSRCDIR)/WARRANTY + $(INCLUDES) -all: wine.info +INFOFILES = \ + wine.info \ + wine.info-1 \ + wine.info-2 + +DVIFILES = wine.dvi + +all: $(INFOFILES) $(DVIFILES) @MAKE_RULES@ -wine.info: $(SOURCES) - makeinfo -I$(TOPSRCDIR) $(SRCDIR)/wine.texinfo +$(INFOFILES): $(SOURCES) + makeinfo $(SRCDIR)/wine.texinfo -wine.dvi: $(SOURCES) +$(DVIFILES): $(SOURCES) texi2dvi $(SRCDIR)/wine.texinfo +$(INCLUDES): + $(RM) $(INCLUDES) + for i in $(INCLUDES); do $(LN_S) $(TOPSRCDIR)/$$i $$i || exit 1; done + +install:: $(INFOFILES) + for i in $(INFOFILES); do $(INSTALL_DATA) $$i $(infodir)/$$i; done + $(INSTALL_DATA) $(SRCDIR)/wine.man $(mandir)/wine$(manext) + clean:: - $(RM) wine.aux wine.cp wine.cps wine.dvi wine.fn wine.fns wine.info \ - wine.ky wine.log wine.pg wine.toc wine.tp wine.tps wine.vr + $(RM) $(INFOFILES) $(DVIFILES) $(INCLUDES) + $(RM) wine.aux wine.cp wine.cps wine.fn wine.fns wine.ky wine.log \ + wine.pg wine.toc wine.tp wine.tps wine.vr wine.vrs ### Dependencies: diff --git a/wine.man b/documentation/wine.man similarity index 100% rename from wine.man rename to documentation/wine.man diff --git a/documentation/wine.texinfo b/documentation/wine.texinfo index 1099cf3c086..a530871e105 100644 --- a/documentation/wine.texinfo +++ b/documentation/wine.texinfo @@ -24,7 +24,8 @@ This file documents Wine, the Windows Emulator. @c Copyright @copyright{} 1997 The Wine authors. @* -@xref{Authors}, for a list of the copyright holders. +@xref{Authors, The Wine Authors, The Wine Authors}, +for a list of the copyright holders. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and @@ -44,6 +45,8 @@ the section entitled ``License, Warranty, and Authors of Wine''. @sp 4 FIXME: UNIX and POSIX trademarks. @* +DOS @* +X11 @* MS-Windows, Windows-NT, Windows 95 are registered trademarks of Microsoft Corp. Postscript is a registered trademark of Adobe Systems Inc. All other product names mentioned herein are the trademarks of @@ -57,7 +60,7 @@ their respective owners. @sp 10 @center @titlefont{The Wine Reference Manual} -@center Edition 0.0.1, 6 July 1997 +@center Edition 0.0.2, 21 July 1997 @c The following two commands start the copyright page. @@ -65,7 +68,8 @@ their respective owners. @vskip 0pt plus 1filll Copyright @copyright{} 1997 The Wine authors. @* -@xref{Authors}, for a list of the copyright holders. +@xref{Authors, The Wine Authors, The Wine Authors}, +for a list of the copyright holders. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and @@ -91,19 +95,23 @@ their respective owners. @c Edit this macro manually in the above parts of the document @macro winemanualversion -0.0.1 +0.0.2 @end macro @c Edit this macro manually in the above parts of the document @macro winemanualdate -6 July 1997 +21 July 1997 @end macro @c Edit this macro manually into the TeX titlepage -@macro winemanualtitle {} +@macro winemanualtitle The Wine Reference Manual @end macro +@c +@macro winelib +Winelib +@end macro @c @c MICROSOFT @c @@ -118,6 +126,9 @@ MS-Windows @macro WIN32 WIN32 @end macro +@macro WIN16 +WIN16 +@end macro @c FIXME: automatical trademark reference @macro WINNT @@ -142,6 +153,15 @@ UNIX @macro posix POSIX @end macro + +@macro unicode +Unicode +@end macro + +@macro ascii +ASCII +@end macro + @c @c THIS MANUAL @c @@ -176,10 +196,49 @@ Present in @WIN95{} and @WINNT{}. Not yet implemented. @end macro +@c +@c MACROS FOR FUNCTIONS, TYPES, CONSTANTS, VARIABLES +@c +@c Constants in the WIN32 API +@macro defvr_cw32 {restofline} +@defvr Constant \restofline\ +@end macro +@macro defvrx_cw32 {restofline} +@defvrx Constant \restofline\ +@end macro +@c Functions in the WIN32 API +@macro deftypefn_w32 {restofline} +@deftypefn {WIN32 function} \restofline\ +@end macro +@macro deftypefnx_w32 {restofline} +@deftypefnx {WIN32 function} \restofline\ +@end macro +@c Types in the WIN32 API +@macro deftp_w32 {restofline} +@deftp {Data type} \restofline\ +@end macro +@macro deftpx_w32 {restofline} +@deftpx {Data type} \restofline\ +@end macro +@c Macros internal to Wine +@macro deffn_winemacro {restofline} +@deffn {Wine internal macro} \restofline\ +@end macro +@macro deffnx_winemacro {restofline} +@deffn {Wine internal macro} \restofline\ +@end macro + +@c Constants internal to Wine +@macro defvr_cwine {restofline} +@defvr {Wine internal constant} \restofline\ +@end macro +@macro defvrx_cwine {restofline} +@defvrx {Wine internal constant} \restofline\ +@end macro @c @@ -203,20 +262,20 @@ Wine is free software. Wine is still in development-only state. * Copying:: License, Warranty, and Authors of Wine. * Introduction:: A short overview. * Reference Manual:: The Wine reference manual. -* Installation:: Installing Wine. +* Installation:: Installing and configuring Wine. * The Wine Project:: How to contribute to Wine. * Concept Index:: Index of concepts and names. * Type Index:: Index of types and type qualifiers. * Function Index:: Index of functions and function-like macros. -* Variable Index:: Index of variables and variable-like - macros. +* Variable Index:: Index of variables, constants, and + variable-like macros. * File Index:: Index of programs and files. @end menu @node Copying, Introduction, Top, Top -@unnumbered License, Warranty, and Authors of Wine. +@unnumbered License, Warranty, and Authors of Wine @cindex copying conditions for Wine @cindex conditions for copying Wine @cindex Wine copying conditions @@ -274,11 +333,99 @@ Alexandre Julliard @* @node Introduction, Reference Manual, Copying, Top @chapter Introduction -FIXME: Somebody should say some solemn words. +@center Wine: +@center the WINdows Emulator, +@center or Wine Is Not an Emulator + +FIXME: make an easy-readable fluent text out of this. + +Welcome to @winemanualtitle{}. This is edition @winemanualversion{}, +last updated @winemanualdate{}. + +@strong{What is Wine?} + +Wine is a program that allows running MS-Windows programs under X11. + + +Wine incorporates two features, the program loader and @winelib{}: +@enumerate +@item +You can run @mswindows{} binaries (programs) in Wine. Wine contains a +program loader which loads and executes an @mswindows{} binary. It uses +the @winelib{} features of Wine to translate @WIN32{} and @WIN16{} calls +to their @unix{}/X11 equivalent. + +Both 16 bit and 32 bit binaries can be loaded. +@item +@winelib{}: Wine can also be used as a library which implements the +@mswindows{} API on top of a @unix{} or @unix{}-like operating system +with X11. @winelib{} (i.e. the Wine library) translates @WIN16{} or +@WIN32{} API calls to their @unix{}/X11 equivalent. + +You can write a user-level application program that calls the @WIN16{} +or @WIN32{} API functions and compile it on a @unix{} box. +@end enumerate + +@strong{Status} + +Wine is still at development stage. The file @file{ANNOUNCE} says, +``This is still a developer's only release. There are many bugs and +many unimplemented API features. Most applications still do not work +correctly.'' +@xref{Warranty}, for additional information. + +@strong{Requirements} + +Wine needs an 80x86 CPU to run on. Emulating the CPU is currently not +possible. + +Currently, you must have one of: +@itemize @bullet +@item +Linux version 0.99.13 or above +@item +NetBSD-current +@item +FreeBSD-current or FreeBSD 1.1 +@end itemize +You need X11, and you must have @file{libXpm} installed on your system. + +@strong{Availability} + +Wine is free software. The file @file{README} says, ``Basically, you can do +anything with it, except claim that you wrote it.'' +@xref{Copying}, for more information. + +@strong{Performance} + +Wine is expected to run @mswindows{} binaries about the same speed as +@mswindows{} would. However, be aware that the 16 bit versions of +@mswindows{} programs are generally slower than their 32 bit +counterparts. + +@strong{Further information} + +You should consult the files @file{README}, @file{ANNOUNCE}, +@file{RELEASE-NOTES}, @file{BUGS}, @file{LICENSE}, and @file{WARRANTY}, +in the root directory of the Wine distribution. + +The Wine FAQ, available from +@url{ftp://ftp.asgardpro.com/wine/dave/Wine.FAQ}, +@url{ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/Wine.FAQ}, +@url{ftp://rtfm.mit.edu/pub/usenet-by-group/comp.emulators.ms-windows.wine/WINE_(WINdows_Emulator)_Frequently_Asked_Questions}, +@url{ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/Wine.FAQ}, +@url{http://www.asgardpro.com/wine/index.html}, +gives answer to a lot of questions. + +The Wine USENET newsgroup is interesting for developers. It discusses technical +matters about Wine. The address is: @url{news:comp.emulators.ms-windows.wine}. + + @xref{The Wine Project}, if you consider contributing some work. + @node Reference Manual, Installation, Introduction, Top @menu @@ -305,11 +452,10 @@ FIXME: Somebody should say some solemn words. * Memory Management:: How your programs get memory from Wine. * I/O Facilities:: Input/Output in Wine. - .everything except communication and windows * Communication:: How processes can communicate. * Windows and Graphics:: GUI functions of @WIN32{}. * Errors and Exceptions:: How your program can report errors. - . messaging + (messaging) * Resources:: Functions for dealing with resources. * The Registry:: FIXME missing. * Dynamic Link Libraries:: Functions for dealing with DLL's. @@ -344,22 +490,22 @@ representations. * Type FILETIME:: The data structure used for specifying file times. * Compare File Times:: Compare two file times. -* Get File Times:: Get the time attributes of a file. @end menu @c @c *** struct FILETIME *** @c @node Type FILETIME, Compare File Times, , File Times +@subsubsection Type FILETIME @noindent File times in Wine are specified by the data type @code{FILETIME}, defined in @file{windows.h}. - -@deftp {Data type} FILETIME +@deftp_w32 FILETIME +@deftpx_w32 LPFILETIME This is the data type for specifying file times. The file times are stored with 64 bit precision. The actual data type is a structure with -two 32 bit values which are interpreted as the low and high parts of a +two 32-bit values which are interpreted as the low and high parts of a 64-bit value. This value gives a time measured in a granularity of 100 nanoseconds, so 1.5 seconds are specified by a value of 15,000,000. In Wine, this 64-bit value is signed, with the sign taken from the high @@ -367,11 +513,11 @@ part. The lower part is used as unsigned. The definition of @code{FILETIME} reads: @example -typedef struct _FILETIME +typedef struct @{ INT32 dwLowDateTime; INT32 dwHighDateTime; -@} FILETIME; +@} FILETIME, *LPFILETIME; @end example @cindex epoch in file time @@ -381,6 +527,8 @@ intervals elapsed since 1 January 1601, 00:00:00 UTC (Coordinated Universal Time, which is GMT, Greenwich Mean Time). This might be called the @dfn{epoch} for file times. With a signed 64-bit value, this representation covers absolute times of 29247 years around the epoch. +To convert this type to local time, use the function +@code{FileTimeToLocalFileTime}. @windiff{} In @mswindows{}, the elements of the structure are apparently of type @@ -391,14 +539,13 @@ unsigned I do not know. @c @c *** CompareFileTime *** @c -@node Compare File Times, Get File Times, Type FILETIME, File Times +@node Compare File Times, , Type FILETIME, File Times @noindent The Wine function @code{CompareFileTime} compares two file times, and returns whether the first time is less than, equal to, or greater than the second file time. It is defined in @file{windows.h}. - -@deftypefn {WIN32 function} LONG CompareFileTime (@w{CONST FILETIME* @var{time_1},} @w{CONST FILETIME* @var{time_2})} +@deftypefn_w32 LONG CompareFileTime (@w{CONST FILETIME* @var{time_1},} @w{CONST FILETIME* @var{time_2})} This function returns @code{1}, if @var{time_1} is greater than @var{time_2}, @code{-1} if it is less, and @code{0} if both times are equal. @@ -410,34 +557,6 @@ equal. @completionnone{} @end deftypefn -@c -@c ***GetFileTime *** -@c -@node Get File Times, , Compare File Times, File Times -@noindent -FIXME: move this function to the file IO section. @* -The Wine function @code{GetFileTime} returns the creation time and -the times of last the read and modification access to a file. It is -defined in @file{windows.h}. - -@deftypefn {WIN32 function} BOOL GetFileTime (@w{HANDLE @var{file},} @w{LPFILETIME @var{ctime},} @w{LPFILETIME @var{atime},} @w{LPFILETIME @var{mtime})} -This function obtains for the specified @var{file} the creation time -@var{ctime}, the time of the last access to the file @var{atime}, and -the time of the last modification (write) to the file, @var{mtime}. -The @var{file} handle must have been obtained by opening the file with -@code{GENERIC_READ} access. The file time arguments of this function are -pointers to @code{FILETIME} variables, which are filled with a value that -indicates an absolute time in UTC. To convert these values to local -times, use the function @code{FileTimeToLocalFileTime}. If you do not -need some of the times, you can pass a @code{NULL} pointer. -The function returns @code{TRUE} on success, @code{FALSE} on failure. - -@winconfall{} - -@windiffnone{} -@end deftypefn - - @node System Information, Memory Management, Date and Time, @WIN32{} Reference Manual @section System Information @@ -447,6 +566,247 @@ The function returns @code{TRUE} on success, @code{FALSE} on failure. @node I/O Facilities, Communication, Memory Management, @WIN32{} Reference Manual @section I/O Facilities +This section describes all input/output of a process, except for two +topics: communication with other processes, and communication with the +windowing system. + +@menu +* I/O on Files:: Accessing the contents of files. +* File System Interface:: Functions for manipulating files as a whole. +@end menu + +@node I/O on Files, File System Interface, , I/O Facilities +@subsection I/O on Files + +@node File System Interface, , I/O on Files, I/O Facilities +@subsection File System Interface + +These functions are concerned with operating on files themselves, rather +than on their contents. + +@menu +* Type BY_HANDLE_FILE_INFORMATION:: The data structure used to + specify file information. +* File attributes:: The file attributes flags in + a file information structure. +* Getting file information:: These functions let you obtain + information about a file. +@end menu + +@node Type BY_HANDLE_FILE_INFORMATION, File attributes, , File System Interface +@subsubsection The file information structure + +The file information structure of Wine is used to obtain information +about files. It is declared in the header @file{winedows.h}. +@deftp_w32 BY_HANDLE_FILE_INFORMATION +This is the data type for specifying information about files as objects +of the file system. It contains the following members: +@table @code +@item int dwFileAttributes + @cindex file attributes in file information + @cindex attributes of file in file information + @xref{File attributes}, for details. +@item FILETIME ftCreationTime + @cindex creation time in file information + @cindex time of file creation in file information + The time when the file was created. + @xref{Type FILETIME}, for details. +@item FILETIME ftLastAccessTime + @cindex access time in file information + @cindex time of file access in file information + The time when the file was last accessed. + @xref{Type FILETIME}, for details. +@item FILETIME ftLastWriteTime + @cindex write time in file information + @cindex time of last file write in file information + The time when the file was last written to. + @xref{Type FILETIME}, for details. +@item int dwVolumeSerialNumber + @cindex serial number of volume in file information + @cindex volume number (serial) in file information + The serial number of the volume containing the file. In Wine, + currently 0. +@item int nFileSizeHigh + @cindex file size in file information + @cindex size of file in file information + A 32 bit value which contains the high part of the 64 bit file size. +@item int nFileSizeLow + A 32 bit value which contains the low part of the 64 bit file size. +@item int nNumberOfLinks + @cindex hard links number in file information + @cindex links (number of hard) in file information + This is the number of hard links to the file. In a file system which + does not support hard links, this is 1. +@item int nFileIndexHigh + @cindex inode number in file information + @cindex file index in file information + @cindex index of file in file information + A 32 bit value which contains the high part of the 64 bit file + index. The file index is a unique number for a file on a volume. + This identifier cannot change while the file is opened by a process. + Together with the volume number, the file index is a unique + identifier for the file. This can be used by an application to check + whether two handles refer to the same file. Wine currently uses the + inode number for the file index. +@item int nFileIndexLow + A 32 bit value which contains the low part of the 64 bit file index. +@end table + +The definition of @code{BY_HANDLE_FILE_INFORMATION} reads: +@example +typedef struct +@{ + int dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + int dwVolumeSerialNumber; + int nFileSizeHigh; + int nFileSizeLow; + int nNumberOfLinks; + int nFileIndexHigh; + int nFileIndexLow; +@} BY_HANDLE_FILE_INFORMATION ; +@end example + +The @code{BY_HANDLE_FILE_INFORMATION} structure can be obtained by the +@code{GetFileInformationByHandle} function (@pxref{Getting file information}, for +details). + +@windiff{} +In @mswindows{}, the @code{int} elements of the structure are apparently +of type @code{DWORD}. +@end deftp + +@node File attributes, Getting file information, Type BY_HANDLE_FILE_INFORMATION, File System Interface +@subsubsection The file attributes in a file information structure + +The file attributes in a file information structure and in other structures +are a logical @emph{or} of one or more of the following constants: + +@defvr_cw32 FILE_ATTRIBUTE_READONLY +The file is a read-only file. (Wine value: 0x0001). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_HIDDEN +The file is a hidden file. Files in Wine do not have this attribute. (Wine value: +0x0002). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_SYSTEM +The file belongs to the operating system. Files in Wine do not have this +attribute. (Wine value: 0x0004). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_LABEL +This is not present in the @mswindows{} API. (Wine value: 0x0008). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_DIRECTORY +The file is a directory. (Wine value: 0x0010). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_ARCHIVE +The file is an archive file. All non-directory files are reported by Wine +to have this attribute. (Wine value: 0x0020). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_NORMAL +The file does not have any other attributes set. This value must be used +alone. In Wine, normal files are reported as archive files. (Wine value: +0x0080). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_TEMPORARY +The file is used as a temporary storage. Files in Wine do not have this +attribute. (Wine value: 0x0100). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_ATOMIC_WRITE +This is reserved for future use. Files in Wine do not have this +attribute. (Wine value: 0x0200). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_XACTION_WRITE +This is reserved for future use. Files in Wine do not have this +attribute. (Wine value: 0x0400). +@end defvr +@defvr_cw32 FILE_ATTRIBUTE_COMPRESSED +The file is compressed. Files in Wine do not have this attribute. (Wine +value: 0x0800). +@end defvr + +@node Getting file information, , File attributes, File System Interface +@subsubsection Getting file information + +The functions in this section describe how to get information about +files. + +@c +@c *** GetFileInformationByHandle +@c +@noindent +The Wine function @code{GetFileInformationByHandle} returns a file +information structure. It is defined in @file{windows.h}. + +@deftypefn_w32 BOOL GetFileInformationByHandle (@w{HFILE32 @var{file},} @w{BY_HANDLE_FILE_INFORMATION *@var{info})} +This function obtains for the specified @var{file} the file information, +and stores it in @var{info}. The file information contains the file +attributes, the file times, the volume serial number, the file size, the +number of links, and a unique file identifier. The function returns +@code{TRUE} on success, @code{FALSE} on failure. + +@winconfall{} + +@windiff{} +The Wine function can of course only give back information that is +accessible in the @unix{} file system. File times are produced in a +granularity of full seconds. Most file attributes are not present in the +@unix{} file system. @xref{File attributes}, for details. The volume +serial number is set to 0. +@end deftypefn + + +@c +@c *** GetFileTime *** +@c +@noindent +The Wine function @code{GetFileTime} returns the creation time and +the times of last the read and modification access to a file. It is +defined in @file{windows.h}. + +@deftypefn_w32 BOOL GetFileTime (@w{HANDLE @var{file},} @w{LPFILETIME @var{ctime},} @w{LPFILETIME @var{atime},} @w{LPFILETIME @var{mtime})} +This function obtains for the specified @var{file} the creation time +@var{ctime}, the time of the last access to the file @var{atime}, and +the time of the last modification (write) to the file, @var{mtime}. +The file time arguments of this function are pointers to @code{FILETIME} +variables, which are filled with a value that indicates an absolute time +in UTC. @xref{Type FILETIME}, for details. If you do not need some of +the times, you can pass a @code{NULL} pointer. +The function returns @code{TRUE} on +success, @code{FALSE} on failure. + +@winconfall{} + +@windiff{} +The file times are produced in a granularity of full seconds, due to the +underlying @unix{} file system. +@end deftypefn + +@c +@c *** GetFileAttributes *** +@c +@noindent +The Wine function @code{GetFileAttributes} returns the file attributes +for a file. It is defined in @file{windows.h}. + +@deftypefn_w32 DWORD GetFileAttributes (@w{LPCTSTR @var{name})} +This function looks up the file with name @var{name}, and returns the +attributes of the file. @xref{File attributes}, for details on the file +attributes. If the function is not successful, it returns a word with +all bits set (@samp{0xffffffff}). + +@winconfall{} + +@windiff{} +Most file attributes are not present in the +@unix{} file system. @xref{File attributes}, for details. +@end deftypefn + + + + @node Communication, Windows and Graphics, I/O Facilities, @WIN32{} Reference Manual @section Communication @@ -465,6 +825,11 @@ The function returns @code{TRUE} on success, @code{FALSE} on failure. @node Dynamic Link Libraries, , The Registry, @WIN32{} Reference Manual @section Dynamic Link Libraries (DLL's) +This section deals with API functions for handling DLL's (dynamic link +libraries). It does not describe DLL's themselves; nor does it give +information on how Wine handles DLL's. @xref{The build program}, for +information on how DLL's are integrated into Wine. + @@ -483,8 +848,318 @@ The function returns @code{TRUE} on success, @code{FALSE} on failure. @node Tools, , Programs, Reference Manual @chapter Tools +This chapter describes some of the tools that are used by Wine. These +are not user-level programs which the user of Wine will +run. @xref{Programs} for such programs. + +Tools are internal programs that are used to help compile or configure +Wine. + +@menu +* The build program:: A program used to build the DLL entry + points from specifications in @file{if1632/}. +@end menu + + +@node The build program, , , Tools +@section The @file{build} program + +@cindex modules of Wine +@cindex Wine modules +@cindex DLL's built-in in Wine +@cindex Wine DLL's built-in +@cindex built-in DLL's in Wine +Wine contains several modules that implement various DLL's which are +required to run @mswindows{} programs. + +The @file{build} program, located in the @file{tools/} directory, is +used to create the bindings for the DLL entry points of the API functions. +This program reads a @file{.spec}-file in the @file{if1632} directory +and creates the assembly code that translates the function arguments +correctly. + + +@menu +* The spec files:: The format of the @file{.spec}-files. +@end menu + +FIXME: where in Wine are the DLL's affixed? + +FIXME: write a description + +@xref{Implementing an API function}, for notes on using this program. + +@node The spec files, , , The build program +@subsection The @file{.spec}-files +@cindex DLL spec files +@cindex spec files of DLL's +@cindex entry points in DLL's + +This subsection describes the format of the @file{.spec}-files. + +A @file{.spec}-file contains the information about the functions, +variables, and constants that are contained in a DLL (dynamic link +library). + +To be able to interpret the contents of a @file{.spec}-file, you must +know about the concept of ordinals. +@menu +* The general format:: General format conventions. +* Ordinals:: Ordinals are indexes of entry + points into DLL's. +* Spec file header:: The header information. +* Variable entry points:: Entries for DLL variables. +* Function entry points:: Entries for DLL functions. +* Special entries:: Entries for stubs, dummy + functions, Wine symbols, and + constant values. +@end menu + +@node The general format, Ordinals, , The spec files +@subsubsection The general format +@cindex format of spec files +@cindex spec files format + +The @file{.spec}-file contains a header and a sequence of declarations. +Each declaration describes an ordinal. + +The header gives general information about the DLL and its properties. + +Ordinal declarations are optional. That means that there is a default +behaviour assigned to ordinals which are not mentioned in the +@file{.spec}-file. The default handler function of an ordinal will print +an error message when called. + +Comments are indicated by hash marks (@samp{#}); everything between a +hash mark and the end of the line is ignored. + +Empty lines are allowed. +@* FIXME: is that so? + +@node Ordinals, Spec file header, The general format, The spec files +@subsubsection Ordinals +@cindex ordinals in DLL's +@cindex DLL ordinals + +All references to DLL objects like functions or variables are indexed by +unique nonnegative numbers. These numbers are called +@dfn{ordinals}. Apparently, a program can refer to a DLL function or +variable by specifying its name or its ordinal. Although reference by +name is the common usage, some program parts (notably DLL's themselves) +sometimes refer to DLL entries by ordinal. Therefore, the ordinals +cannot be chosen arbitrarily. +@* FIXME: is that correct? + +@node Spec file header, Variable entry points, Ordinals, The spec files +@subsubsection The header of a @file{.spec}-file + +The @file{.spec}-file starts with two mandatory definitions. The first +line gives the name of the DLL which the @file{.spec}-file describes, +@example +name @var{NAME} +@end example +where @var{NAME} is the name of the DLL. The next line defines the type +of the DLL, +@example +type @var{TYPE} +@end example +with @var{TYPE} being either @samp{win16} or @samp{win32}. + +An optional statement of the form +@example +base @var{ORDINAL} +@end example +can be used to define the offset of the first ordinal. @var{ORDINAL} +must be an integer number. If no base is specified, the offset is zero. +@* FIXME: is this the offset of the first or an offset that is added to all +ordinals? +what is the offset? Is it added to the ordinals, or is it an address, or +xxx? + +An optional statement like +@example +heap @var{SIZE} +@end example +can be used to define the size of the module local heap. This is only +used for @WIN16{} DLL's. The local heap is the place where the segments +of 16 bit programs can locally allocate memory, without interfering with +one another. The default size of the local heap, if not specified, is 0. + +@* FIXME: to my impression, a local heap in DLL's would only be required +if DLL functions used it. As all DLL functions in Wine are truly 32 bit +functions that are mapped from 16 bit on being called and back to 16 bit +on returning, a local heap should never be necessary. +If I receive a confirmation of that here, I will state so. Otherwise I +am missing some information on local heaps. +But why is a heap defined in user.spec and gdi.spec? + +@node Variable entry points, Function entry points, Spec file header, The spec files +@subsubsection Variable entry points of @file{.spec}-files + +You can declare an ordinal that holds data. Data items may be of 8, 16, +or 32 bit in size. + +@example +@var{ORDINAL} @var{VARTYPE} @var{EXPORTNAME} (@var{DATA} @var{[DATA @dots{}]}) +@end example + +@var{ORDINAL} is the ordinal number corresponding to the +variable. @var{VARTYPE} must be @samp{byte}, @samp{word}, or +@samp{long}, for 8, 16, or 32 bits respectively. @var{EXPORTNAME} will +be the name available for dynamic linking. @var{DATA} can be a decimal +number or a hex number preceded by @samp{0x}. Each @var{DATA} item defines +a unit of storage. + +The following example defines the variable @samp{VariableA} at ordinal +2, containing 4 bytes: +@example +2 byte VariableA(-1 0xff 0 0) +@end example + + +@node Function entry points, Special entries, Variable entry points, The spec files +@subsubsection Function entry points of @file{.spec}-files + +@example +@var{ORDINAL} @var{FUNCTYPE} @var{EXPORTNAME} (@var{[ARGTYPE} @dots{} @var{]}) @var{HANDLERNAME} +@end example + +@var{ORDINAL} is the ordinal number corresponding to the +function. @var{FUNCTYPE} must be chosen from this table: +@table @samp +@item pascal16 +A @WIN16{} function that returns a 16 bit value. +@item pascal +A @WIN16{} function that returns a 32 bit value. +@item register +A function using CPU registers to pass arguments. +@item stdcall +A normal @WIN32{} function. +@item cdecl +A @WIN32{} function using the C calling conventions. (This is presently +only used for the built-in functions of the C runtime system). +@end table + +@var{EXPORTNAME} specifies the name (prototype) available for dynamic +linking. + +@var{ARGTYPE} must be chosen from this table: +@table @samp +@item byte + An 8 bit argument. Can be used in @WIN16{} functions only. +@item word + A 16 bit argument. Can be used in @WIN16{} functions only. +@item long + A 32 bit argument. Can be used in @WIN16{} or @WIN32{} functions. +@item ptr + A linear pointer, unsegmented. Can be used in @WIN16{} or @WIN32{} + functions. +@item str + A linear pointer, unsegmented, pointing to a null-terminated string. + Can be used in @WIN16{} or @WIN32{} functions. +@item s_byte + A signed 8 bit argument. Can be used in @WIN16{} functions only. +@item s_word + A signed 16 bit argument. Can be used in @WIN16{} functions only. +@item s_long + A signed 32 bit argument. Can be used in @WIN16{} or @WIN32{} + functions. +@item segptr + A segmented pointer. Can be used in @WIN16{} functions only. +@item segstr + A segmented pointer to a null-terminated string. Can be used in + @WIN16{} functions only. +@end table + +@var{HANDLERNAME} is the name of the actual Wine function that will +process the request in 32-bit mode. + + +@sp 2 +Here are some examples. The first example defines an entry point for the +@code{CreateWindow()} call (the ordinal 100 is just an example): +@example +100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word + word word word ptr) WIN_CreateWindow +@end example + +The second example defines an entry point for the @code{GetFocus()} call +(again, the ordinal 100 is an example): +@example +100 pascal GetFocus() WIN_GetFocus() +@end example + +To declare a function that uses a variable number of arguments, specify +the function as taking no arguments. In this special case, in @WIN32{} +the called function will be passed a pointer to the first arg; in +@WIN16{}, the args are available as @code{CURRENT_STACK16->args}. +@* FIXME: create a reference here +See the @code{wsprintf}* functions in @file{user.spec} and +@file{user32.spec} for an example. + + +@node Special entries, , Function entry points, The spec files +@subsubsection Special entries of @file{.spec}-files + +The @file{.spec}-files offer the possibility to use some special +entries. These entries are used for stubs (which allow linking for +non-existing functions), dummy functions that do not perform any +operations, Wine symbols that must be referenced directly, and constant +values. + + +@strong{Stub ordinals} + +This pseudo function type 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. + +@example +@var{ORDINAL} stub @var{EXPORTNAME} +@end example + +@var{ORDINAL} is the ordinal number corresponding to the +function. @var{EXPORTNAME} specifies the name (prototype) available for dynamic +linking. + +@strong{Return ordinals} + +This pseudo function type defines a function entry point whose handler +should do nothing but return a value. +@example +@var{ORDINAL} return @var{EXPORTNAME} @var{ARGLENGTH} @var{RETVALUE} +@end example + +@var{ORDINAL} is replaced by the ordinal number corresponding to the +function. @var{ARGLENGTH} is the number of bytes that need to be removed +from the stack before returning to the caller. @var{RETVALUE} is the +return value which will be passed back to the caller. + +@strong{Extern ordinals} + +@example +@var{ORDINAL} extern @var{EXPORTNAME} @var{SYMBOLNAME} +@end example +This type defines an entry that simply maps to a Wine symbol +(variable or function); @var{EXPORTNAME} will point to the symbol +@var{SYMBOLNAME} that must be defined in C code. This type only works with +@WIN32{}. + + +@strong{Equate ordinals} + +@example +@var{ORDINAL} equate @var{EXPORTNAME} @var{DATA} +@end example + +This type defines an ordinal as an absolute value. +@var{ORDINAL} is replaced by the ordinal number corresponding to the +entry. @var{EXPORTNAME} will be the name available for dynamic linking. +@var{DATA} can be a decimal number or a hex number preceeded by @samp{0x}. + + @node Installation, The Wine Project, Reference Manual, Top -@chapter Wine Installation +@chapter Wine installation and configuration FIXME: write installation guide @menu @@ -507,8 +1182,17 @@ If you are new to Wine and want to support this project, here are some suggestions. @menu -* Creating patches:: How to create patches for Wine. -* Adding Documentation:: Templates for the documentation. +* Implementing an API type:: How to implement a data type + of the API (a checklist). +* Implementing an API function:: How to implement one function + of the API (a checklist). +* API function and type naming:: How to name API functions in Wine. +* Creating patches:: How to create patches for Wine. +* Adding Documentation:: Templates for the documentation. +* File names:: How Wine treats @mswindows{} and + @unix{} file names. +* Wide character strings:: How Wine treats wide character + strings. @end menu @xref{Debugging}, for advice on how to debug Wine. @@ -516,13 +1200,366 @@ some suggestions. FIXME: what is most urgently needed -@node Creating patches, Adding Documentation, , The Wine Project +@node Implementing an API type, Implementing an API function, , The Wine Project +@section Implementing an API type + +Here is a checklist that should help you writing your first API type. It +will of course not tell you which elements to put into the type +(assuming it is a structure), but it should help you along the way of +integrating this type into Wine. +@xref{Implementing an API function}, for comparison. + +@enumerate +@item +Find out how the type should be named in Wine and in the DLL's. +@xref{API function and type naming}, for details. + +@item +Find out where the type should go. Please try to keep the header files +structure as similar to @mswindows{} as possible. + +@item +Prepare for the later patch (by saving the original files before you +work on them). @xref{Creating patches}, for details. + +@item +Put the type declaration into the header file. + +@item +Make sure the declaration is syntactically correct, i.e. it does not +keep Wine from compiling. + +@item +Make sure the declared type is layout-compatible with +@mswindows{}-compiled types. Especially keep an eye on the packing of +the structure. +@* FIXME: a reference to packed structures here. + +@item +Build Wine and test the type, if possible. If you cannot test the +type by implementing a proper API function, write a small test program +to test it on its own. Or rather stop here. + +@item +Write the documentation of the type in the @file{wine.texinfo} +file. @xref{Adding Documentation}, for details. +With types, be especially careful and document all the details. Also +document all constants or flags that are used in the type. + +@item +Create an entry in the @file{ChangeLog} file. + +@item +Collect some of these changes, and create a patch. @xref{Creating +patches}, for details. + +@item +Mail the patch to Alexandre Julliard, @email{julliard@@lrc.epfl.ch}. + +@item +Wait for the patch to appear in the official distribution. +@end enumerate + + +@node Implementing an API function, API function and type naming, Implementing an API type, The Wine Project +@section Implementing an API function + +Here is a checklist that should help you writing your first API +function. It will of course not tell you what to do in the function, +but it should help you along the way of integrating this function into +Wine. + +@enumerate +@item +Make sure all data types that appear in function arguments are properly +declared in Wine. Otherwise, start with the data types. + +@item +Find out how the function should be named in Wine and in the DLL's. +@xref{API function and type naming}, for details. + +@item +Find out where the function should go: +@enumerate +@item +Which header file for the prototype. +@item +Which C source file. +@item +Which DLL(s), and which ordinal the function will take there. Perhaps +the function name is already present in one of the @file{.spec}-files in +the @file{if1632} directory. +@end enumerate + +@item +Prepare for the later patch (by saving the original files before you +work on them). @xref{Creating patches}, for details. + +@item +Put the prototype into the header file, and the code into the C file. + +@item +Make sure the code compiles. + +@item +Create or change the information for the DLL entry points in the +@file{.spec}-file in the @file{if1632} directory. +@xref{The build program}, for details of the DLL spec files. + +@item +Build Wine and test the function, if possible. If you cannot test the +function in Wine, write a small test program to test it on its own. + +@item +Write the documentation of the function in the @file{wine.texinfo} +file. @xref{Adding Documentation}, for details. + +@item +Create an entry in the @file{ChangeLog} file. + +@item +Collect some of these changes, and create a patch. @xref{Creating +patches}, for details. + +@item +Mail the patch to Alexandre Julliard, @email{julliard@@lrc.epfl.ch}. + +@item +Wait for the patch to appear in the official distribution. +@end enumerate + + +@node API function and type naming, Creating patches, Implementing an API function, The Wine Project +@section API function and data type naming conventions +@cindex API function names +@cindex API type names +@cindex names of API functions and types +@cindex naming scheme for API functions and types +@cindex suffixes for API functions and types +@cindex endings of API function and type names + +This section describes Wine's naming scheme for API functions and data +types. + +The purpose of these naming conventions is to ensure that +@itemize @bullet +@item +both the @WIN16{} and @WIN32{} API are supported within the same source +code, +@item +both wide character functions (with @unicode{} strings) and 8 bit +character functions (with @ascii{} or extended @ascii{} encoding) are +supported, and +@item +the source code can be shared between the emulator and the library +version of Wine. +@end itemize + +A function or data type whose name in the @mswindows{} API is @var{xxx} +will in the Wine code have the following name(s): +@table @code +@item @var{xxx}16 +This is the version for the 16 bit API. You might call it the ``16 bit +version'' except that the function itself of course runs in true 32 bit +mode (being part of Wine). So, the correct meaning of the suffix is that +this function is part of the 16 bit API. +@item @var{xxx}32 +This is the version for the 32 bit API. Use this suffix only if the +function does not use character strings in its parameters or return +values. Otherwise use the next two. +@item @var{xxx}32A +This is the version for the 32 bit API which uses @ascii{} strings (or +rather, strings with 8 bit character encodings, i.e. the standard C +@code{char} type). This version always goes together with another +version, using the next suffix. +@item @var{xxx}32W +This is the version for the 32 bit API which uses @unicode{} strings, +i.e. strings with wide characters. It goes together with the @ascii{} +version. +@end table + +So, where the @mswindows{} API offers one name, Wine actually has two or +three different functions implemented (which will hopefully share a +large part of the code). + +Wine allows to use its API functions in two ways. The emulator part of +Wine provides DLL's for the @mswindows{} programs it can run. The +library part of Wine provides a @unix{} programmer with the facility to +use the Wine API's in a standard @unix{} program. + +@menu +* Access from the emulator:: How to access API functions and types + from applications that are run in the + Wine emulator. +* Access in the library:: How to access API functions and types + from applications that are linked with + the Wine library. +* Access from inside Wine:: How to access API functions and types + from inside the Wine code. +@end menu + +@node Access from the emulator, Access in the library, , API function and type naming +@subsection Accessing API functions and types from the emulator +@cindex access to DLL API functions and types +@cindex Wine emulator access to API functions and types +@cindex emulator access to Wine API functions and types + +The emulator part of Wine provides the hooks for dynamically linking the +API functions to the @mswindows{} executables (@file{.EXE}-files). The +Wine emulator contains all versions (16 or 32 bit, @ascii{} or +@unicode{}) of the API functions in one executable. The emulator +performs a mapping from the @mswindows{} name of the function, +by which the executable calls it, to one of the Wine internal names that +have been used in coding it. + +This mapping is done by the built-in DLL handling code of Wine. A +programmer of Wine has to declare the function in one of the virtual +DLL's that are provided by Wine. The declarations are done in the +@file{.spec}-files in the @file{if1632/} directory. @xref{The build +program}, for details. + +The @mswindows{} application simply calls the API function by its +standard @mswindows{} name. Wine will apply the correct mapping +according to Wine's selected appearance (as a 16 bit or 32 bit emulator, +which is a parameter on invocation of Wine). + + +@node Access in the library, Access from inside Wine, Access from the emulator, API function and type naming +@subsection Accessing API functions and types in the library +@cindex Wine library API function and type access +@cindex access to Wine library API functions and types + +If Wine is built as a library, and linked to a user-level main program, +the user will also use the standard @mswindows{} names for the API +functions. + +Some macros are defined in @file{include/wintypes.h} which perform the +necessary name mappings. + +These macros are (see the examples below): +@deffn_winemacro WINELIB_NAME (@var{xxx}) +This macro replaces @var{xxx} by one of @var{xxx}16 or +@var{xxx}32, depending on the definition of the symbols +@code{WINELIB16} and @code{WINELIB32}. @var{xxx} should +be the name of an API function that uses no string arguments. +Use this macro with a @code{#define} to establish the API name @var{xxx}. +@end deffn +@deffn_winemacro WINELIB_NAME_AW (@var{xxx}) +This macro replaces @var{xxx} by one of @var{xxx}16, @var{xxx}32A, or +@var{xxx}32W, depending on the definition of the symbols +@code{WINELIB16}, @code{WINELIB32}, and @code{UNICODE}. @var{xxx} should +be the name of an API function that uses string arguments. +Use this macro with a @code{#define} to establish the API name @var{xxx}. +@end deffn +@deffn_winemacro DECL_WINELIB_TYPE (@var{xxx}) +This macro declares @var{xxx} to be an equivalent to @var{xxx}16 or +@var{xxx}32, depending on the definition of the symbols +@code{WINELIB16} and @code{WINELIB32}. @var{xxx} should +be the name of an API data type that contains no string arguments. +@end deffn +@deffn_winemacro DECL_WINELIB_TYPE_AW (@var{xxx}) +This macro declares the type @var{xxx} to be an equivalent to +@var{xxx}16, @var{xxx}32A, or @var{xxx}32W, depending on the definition +of the symbols @code{WINELIB16}, @code{WINELIB32}, and +@code{UNICODE}. @var{xxx} should be the name of an API data type that +contains string arguments. +@end deffn + +If Wine is compiled as an emulator, these macros have no effect, for the +mapping is then done by the DLL code. This means that within Wine the +name @var{xxx} itself will not be defined. + +Note: If the definition of @var{xxx} is exactly the same in @WIN16{} and +@WIN32{}, you can simply use the same name as @mswindows{}. + +Here are some examples: +@example +/* A simple type without strings */ +typedef short INT16; +typedef int INT32; +DECL_WINELIB_TYPE(INT); + +/* A type with strings */ +typedef struct @{ /* Win32 ASCII data structure */ @} WNDCLASS32A; +typedef struct @{ /* Win32 Unicode data structure */ @} WNDCLASS32W; +typedef struct @{ /* Win16 data structure */ @} WNDCLASS16; +DECL_WINELIB_TYPE_AW(WNDCLASS); + +/* A function with strings */ +ATOM RegisterClass16( WNDCLASS16 * ); +ATOM RegisterClass32A( WNDCLASS32A * ); +ATOM RegisterClass32W( WNDCLASS32W * ); +#define RegisterClass WINELIB_NAME_AW(RegisterClass) +@end example + +The Winelib user can then say (in the application program): +@example + INT i; + WNDCLASS wc = @{ @dots{} @}; + RegisterClass( &wc ); +@end example +and this will use the correct declaration depending on the definitions +@code{WINELIB16}, @code{WINELIB32}, and @code{UNICODE}. + +Here are the primary defines that are used when Wine is compiled as a +library: +@defvr_cwine WINELIB16 +If this @code{#define} is set, the Wine library is to be compiled in its +16 bit form. That means, the 16 bit variants of all functions will be +used and the appearance of the application linked with the Wine library +will be that of a 16 bit application. Of course, both the application +and the Wine library function really run in 32 bit mode. The switch only +selects the function with the name ending in @code{@dots{}16}, which +will perhaps have a behaviour different from its 32 bit counterpart. +@end defvr +@defvr_cwine WINELIB32 +If this @code{#define} is set, the Wine library is to be compiled in its +32 bit form. That means, the 32 bit variants of all functions will be +used and the appearance of the application linked with the Wine library +will be that of a 32 bit application. +@end defvr +@defvr_cwine UNICODE +This @code{define} is used to select one of two possible 32 bit +variants. Functions and data types of the 32 bit API come in two +flavours: one handling @ascii{} strings (or rather strings with +characters encoded in 8 bit), the other @unicode{} strings. This define +selects the correct variant. As a user of the Wine library, you are +responsible to use the correct character type in your part of the +application which accesses the Wine API functions and data types. +@end defvr + +These switches are automatically set when Wine is compiled as a library. + + +@node Access from inside Wine, , Access in the library, API function and type naming +@subsection Accessing API functions from within Wine +@cindex explicit names of API functions and types + +Within Wine and during the compilation of Wine, you cannot rely on the +@mswindows{} names of the API functions and data types. If Wine is +compiled as a library, they will be defined; if Wine is compiled as an +emulator, they won't. + +You therefore have to access all functions and data types by their full +names, with the proper suffix explicitely appended. In Wine, the 16 bit +and 32 bit versions of the functions are distinct entities, which might +(theoretically) show a completely different behaviour. They may even +call each other (and they will quite frequently). + +Therefore Wine is a conglomerate that contains all two or +three flavours of each function at once, and exports to the +application whichever of these is appropriate. Remember that inside +Wine, there is no memory segmentation, so all functions are 32 bit. +The 16-to-32 bit mapping is done on exporting the DLL functions. + + +@node Creating patches, Adding Documentation, API function and type naming, The Wine Project @section Creating patches @xref{Applying patches}, for instructions on applying patches. FIXME: how to create patches -@node Adding Documentation, , Creating patches, The Wine Project +@node Adding Documentation, File names, Creating patches, The Wine Project @section Adding Documentation @ifinfo @@ -530,8 +1567,6 @@ Here are some templates which should help you collaborate on this documentation. Read the text below before examining them. @end ifinfo -FIXME they are not here in dvi - @menu * Type Template:: How to document data types in Wine's include files. @@ -552,6 +1587,9 @@ some documentation. Finally, read the info pages for @code{texinfo}. +The rest of this section provides some templates which can serve as a +start in writing documentation. + @subsection Template introduction @iftex On the following pages you will find some @code{texinfo} templates, which @@ -603,6 +1641,13 @@ adapt the comment like this: @@node Ints and Longs, NextNodeName, PreviousNodeName, ParentNodeName @end example +After the node name, put a sectioning command, such as @samp{@@chapter}, +@samp{@@section}, @samp{@@subsection}, or @samp{@@subsubsection}. +Without that command, cross references to the node will fail. +@example +@@subsubsection Type FILETIME +@end example + Start the description of the type(s) or function(s) with a single non-indented paragraph that gives a one-line description of the type(s) or function(s) and states the include files that are required. @@ -616,11 +1661,13 @@ as a common description. If more paragraphs are required for a proper description, indent all but the first of them. Then start the definition of the data type or function. Use the proper -macro and specify a category and the formal definition on the same -line. For proper categories, take a look at the specialized templates. +macro, which you will find defined in the beginning of the texinfo file. +If appropriate, add your own macros. Again, put everything that belongs to the header into a single line. +Use continuation lines for additional headers. @example -@@deftp @{Data type@} FILETIME +@@deftp_w32 FILETIME +@@deftpx_w32 LPFILETIME @end example In the definition, give a verbal explanation of the data type or @@ -647,11 +1694,11 @@ well prepared example will help the readers write their code. @example The definition of @@code@{FILETIME@} reads: @@example -typedef struct _FILETIME +typedef struct @@@{ INT32 dwLowDateTime; INT32 dwHighDateTime; -@@@} FILETIME; +@@@} FILETIME, *LPFILETIME; @@end example @end example @@ -728,7 +1775,7 @@ The Wine function @@code@{GetFileTime@} returns the creation time and the times of last the read and modification access to a file. It is defined in @@file@{windows.h@}. -@@deftypefn @{WIN32 function@} BOOL GetFileTime (@@w@{HANDLE @@var@{file@},@} @@w@{LPFILETIME @@var@{ctime@},@} @@w@{LPFILETIME @@var@{atime@},@} @@w@{LPFILETIME @@var@{mtime@})@} +@@deftypefn_w32 BOOL GetFileTime (@@w@{HANDLE @@var@{file@},@} @@w@{LPFILETIME @@var@{ctime@},@} @@w@{LPFILETIME @@var@{atime@},@} @@w@{LPFILETIME @@var@{mtime@})@} This function obtains for the specified @@var@{file@} the creation time @@var@{ctime@}, the time of the last access to the file @@var@{atime@}, and the time of the last modification (write) to the file, @@var@{mtime@}. @@ -747,8 +1794,40 @@ The function returns @@code@{TRUE@} on success, @@code@{FALSE@} on failure. @end example +@node File names, Wide character strings, Adding Documentation, The Wine Project +@section @mswindows{} and @unix{} file names in Wine +@cindex file names in Wine +@cindex Windows file names +@cindex DOS file names in Wine +@cindex UNIX file names in Wine +@cindex POSIX file names in Wine +FIXME: +@node Wide character strings, , File names, The Wine Project +@section Wide character strings in API functions +@cindex unicode strings in API functions +@cindex wide character strings in API functions +@cindex strings in API functions +@cindex ascii strings in API functions +@cindex 16 bit characters in API functions +@cindex wchar_t in API functions + +Presently, all wide character strings in API functions of Wine are +internally converted to 8 bit representation. Thus, the @WIN32{} API +with @unicode{} strings is not fully functional for the application +programmer at present. + +Even so, application programmers might consider developing their +applications in wide character format with Wine, as future versions +might bring a change. This might come when a @unix{} filesystem can +handle @unicode{} file names. + +Furthermore, the @unicode{} API is required to let Wine run @mswindows{} +applications which have been compiled for wide character strings. + +In Wine, wide characters are strictly 16 bit; the @code{wchar_t} type of +standard C can therefore not be used. @node Concept Index, , , Top @comment node-name, next, previous, up @@ -767,7 +1846,7 @@ The function returns @@code@{TRUE@} on success, @@code@{FALSE@} on failure. @node Variable Index, , , Top @comment node-name, next, previous, up -@unnumbered Variable Index +@unnumbered Variable, Constants, and Variable-like Macros Index @printindex vr @node File Index, , , Top diff --git a/files/directory.c b/files/directory.c index 1abc4b25b09..6bc5c4515b5 100644 --- a/files/directory.c +++ b/files/directory.c @@ -502,9 +502,9 @@ DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext, /* First check the supplied parameters */ - if (!(p = strrchr( name, '\\' ))) p = name; - if (!(p = strrchr( p, '/' ))) p = name; - if (strchr( p, '.' )) ext = NULL; /* Ignore the specified extension */ + p = strrchr( name, '.' ); + if (p && !strchr( p, '/' ) && !strchr( p, '\\' )) + ext = NULL; /* Ignore the specified extension */ if ((*name && (name[1] == ':')) || strchr( name, '/' ) || strchr( name, '\\' )) path = NULL; /* Ignore path if name already contains a path */ diff --git a/files/file.c b/files/file.c index 8b1c31eb8d9..742d518e1f9 100644 --- a/files/file.c +++ b/files/file.c @@ -951,7 +951,7 @@ HFILE32 _lopen32( LPCSTR path, INT32 mode ) switch(mode & 3) { case OF_WRITE: - unixMode = O_WRONLY | O_TRUNC; + unixMode = O_WRONLY; break; case OF_READWRITE: unixMode = O_RDWR; diff --git a/graphics/painting.c b/graphics/painting.c index bad5182a6f7..ed9646406e0 100644 --- a/graphics/painting.c +++ b/graphics/painting.c @@ -764,3 +764,14 @@ BOOL32 DrawFrameControl32( HDC32 hdc, LPRECT32 rc, UINT32 uType, UINT32 uState ) hdc,rc,uType,uState ); return TRUE; } + +/********************************************************************** + * DrawFrameControl32 (USER32.152) + */ +BOOL32 DrawAnimatedRects32( HWND32 hwnd, int idAni, + const LPRECT32 lprcFrom, const LPRECT32 lprcTo ) +{ + fprintf( stdnimp,"DrawAnimatedRects32(%x,%d,%p,%p), empty stub!\n", + hwnd, idAni, lprcFrom, lprcTo ); + return TRUE; +} diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c index ff4805986ab..9fc20860f89 100644 --- a/graphics/win16drv/init.c +++ b/graphics/win16drv/init.c @@ -73,7 +73,7 @@ static const DC_FUNCTIONS WIN16DRV_Funcs = NULL, /* pOffsetViewportOrgEx */ NULL, /* pOffsetWindowOrgEx */ NULL, /* pPaintRgn */ - NULL, /* pPatBlt */ + WIN16DRV_PatBlt, /* pPatBlt */ NULL, /* pPie */ NULL, /* pPolyPolygon */ NULL, /* pPolygon */ @@ -223,13 +223,13 @@ BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, int nPDEVICEsize; PDEVICE_HEADER *pPDH; WIN16DRV_PDEVICE *physDev; - + int numFonts; /* Realizing fonts */ int nSize; char printerEnabled[20]; PROFILE_GetWineIniString( "wine", "printer", "off", printerEnabled, sizeof(printerEnabled) ); - if (strcmp(printerEnabled,"on")) + if (lstrcmpi32A(printerEnabled,"on")) { printf("WIN16DRV_CreateDC disabled in wine.conf file\n"); return FALSE; @@ -323,6 +323,7 @@ BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, wepfc.nCount = 0; PRTDRV_EnumDFonts(physDev->segptrPDEVICE, NULL, pfnCallback, (void *)&wepfc); + numFonts = wepfc.nCount; } } } @@ -378,7 +379,12 @@ BOOL32 WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, return TRUE; } - +extern BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top, + INT32 width, INT32 height, DWORD rop ) +{ + printf("In WIN16DRV_PatBlt\n"); + return FALSE; +} /* * Escape (GDI.38) */ @@ -393,31 +399,56 @@ static INT32 WIN16DRV_Escape( DC *dc, INT32 nEscape, INT32 cbInput, if (dc != NULL && physDev->segptrPDEVICE != 0) { switch(nEscape) - { - case SETABORTPROC: - printf("Escape: SetAbortProc ignored\n"); + { + case SETABORTPROC: + printf("Escape: SetAbortProc ignored should be stored in dc somewhere\n"); + /* Make calling application believe this worked */ + nRet = 1; break; - case GETEXTENDEDTEXTMETRICS: - { - SEGPTR newInData = WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(EXTTEXTDATA))); - EXTTEXTDATA *textData = (EXTTEXTDATA *)(PTR_SEG_TO_LIN(newInData)); + case NEXTBAND: + { + SEGPTR newInData = WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(POINT16))); + nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape, + newInData, lpOutData); + GlobalFree16(newInData); + break; + } - textData->nSize = cbInput; - textData->lpindata = lpInData; - textData->lpFont = physDev->segptrFontInfo; - textData->lpXForm = win16drv_SegPtr_TextXForm; - textData->lpDrawMode = win16drv_SegPtr_DrawMode; + case GETEXTENDEDTEXTMETRICS: + { + SEGPTR newInData = WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(EXTTEXTDATA))); + EXTTEXTDATA *textData = (EXTTEXTDATA *)(PTR_SEG_TO_LIN(newInData)); + + textData->nSize = cbInput; + textData->lpindata = lpInData; + textData->lpFont = physDev->segptrFontInfo; + textData->lpXForm = win16drv_SegPtr_TextXForm; + textData->lpDrawMode = win16drv_SegPtr_DrawMode; + nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape, + newInData, lpOutData); + GlobalFree16(newInData); + + } + break; + case STARTDOC: nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape, - newInData, lpOutData); - GlobalFree16(newInData); - - } - break; - + lpInData, lpOutData); + if (nRet != -1) + { + SEGPTR newInData = WIN16_GlobalLock16(GlobalAlloc16(GHND, sizeof(HDC32))); +#define SETPRINTERDC SETABORTPROC + HDC32 *tmpHdc = (HDC32 *)(PTR_SEG_TO_LIN(newInData)); + *tmpHdc = dc->hSelf; + PRTDRV_Control(physDev->segptrPDEVICE, SETPRINTERDC, + newInData, (SEGPTR)NULL); + GlobalFree16(newInData); + } + break; default: nRet = PRTDRV_Control(physDev->segptrPDEVICE, nEscape, lpInData, lpOutData); + break; } } else diff --git a/if1632/Makefile.in b/if1632/Makefile.in index 140ca7548a4..20df6475aa3 100644 --- a/if1632/Makefile.in +++ b/if1632/Makefile.in @@ -58,6 +58,7 @@ C_SRCS = \ builtin.c \ dummy.c \ relay.c \ + signal.c \ thunk.c GEN_ASM_SRCS = \ diff --git a/if1632/builtin.c b/if1632/builtin.c index 16756875640..ebe48adb275 100644 --- a/if1632/builtin.c +++ b/if1632/builtin.c @@ -119,6 +119,7 @@ static BUILTIN_DLL BuiltinDLLs[] = { &KERNEL_Descriptor, DLL_FLAG_ALWAYS_USED }, { &USER_Descriptor, DLL_FLAG_ALWAYS_USED }, { &GDI_Descriptor, DLL_FLAG_ALWAYS_USED }, + { &SYSTEM_Descriptor, DLL_FLAG_ALWAYS_USED }, { &WIN87EM_Descriptor, DLL_FLAG_NOT_USED }, { &SHELL_Descriptor, 0 }, { &SOUND_Descriptor, 0 }, @@ -126,7 +127,6 @@ static BUILTIN_DLL BuiltinDLLs[] = { &WINSOCK_Descriptor, 0 }, { &STRESS_Descriptor, 0 }, { &MMSYSTEM_Descriptor, 0 }, - { &SYSTEM_Descriptor, 0 }, { &TOOLHELP_Descriptor, 0 }, { &MOUSE_Descriptor, 0 }, { &COMMDLG_Descriptor, DLL_FLAG_NOT_USED }, diff --git a/if1632/comctl32.spec b/if1632/comctl32.spec index 90b5e5d370b..be6c101ccdb 100644 --- a/if1632/comctl32.spec +++ b/if1632/comctl32.spec @@ -2,6 +2,10 @@ name comctl32 type win32 base 2 +# Functions exported by the Win95 comctl32.dll +# (these need to have these exact ordinals, because some win95 dlls +# import comctl32.dll by ordinal) + 00 stub MenuHelp 01 stub ShowHideMenuCtl 02 stub GetEffectiveClientRect @@ -9,53 +13,60 @@ base 2 04 stdcall CreateStatusWindowA(long ptr long long) CreateStatusWindow32A 05 stub CreateToolbar 06 stub CreateMappedBitmap -07 stub CreatePropertySheetPage -08 stub CreatePropertySheetPageA -09 stub CreatePropertySheetPageW -10 stub CreateStatusWindow +07 stub Cctl1632_ThunkData32 +08 stub CreatePropertySheetPage +09 stub CreatePropertySheetPageA +10 stub CreatePropertySheetPageW 11 stub MakeDragList 12 stub LBItemFromPt 13 stub DrawInsert 14 stub CreateUpDownControl 15 stdcall InitCommonControls() InitCommonControls -16 stub CreateStatusWindowW -17 stub CreateToolbarEx -18 stub DestroyPropertySheetPage -19 stub DrawStatusText -20 stub DrawStatusTextW -21 stub ImageList_Add -22 stub ImageList_AddIcon -23 stub ImageList_AddMasked -24 stub ImageList_BeginDrag -25 stub ImageList_Create -26 stub ImageList_Destroy -27 stub ImageList_DragEnter -28 stub ImageList_DragLeave -29 stub ImageList_DragMove -30 stub ImageList_DragShowNolock -31 stub ImageList_Draw -32 stub ImageList_DrawEx -33 stub ImageList_EndDrag -34 stub ImageList_GetBkColor -35 stub ImageList_GetDragImage -36 stub ImageList_GetIcon -37 stub ImageList_GetIconSize -38 stub ImageList_GetImageCount -39 stub ImageList_GetImageInfo -40 stub ImageList_GetImageRect -41 stub ImageList_LoadImage -42 stub ImageList_LoadImageA -43 stub ImageList_LoadImageW -44 stub ImageList_Merge -45 stub ImageList_Read -46 stub ImageList_Remove -47 stub ImageList_Replace -48 stub ImageList_ReplaceIcon -49 stub ImageList_SetBkColor -50 stub ImageList_SetDragCursorImage -51 stub ImageList_SetIconSize -52 stub ImageList_SetOverlayImage -53 stub ImageList_Write -54 stub PropertySheet -55 stub PropertySheetA -56 stub PropertySheetW +16 stub CreateStatusWindow +17 stub CreateStatusWindowW +18 stub CreateToolbarEx +19 stub DestroyPropertySheetPage +20 stub DllGetVersion +21 stub DrawStatusText +22 stub DrawStatusTextW +23 stub ImageList_Add +24 stub ImageList_AddIcon +25 stub ImageList_AddMasked +26 stub ImageList_BeginDrag +27 stub ImageList_Copy +28 stub ImageList_Create +29 stub ImageList_Destroy +30 stub ImageList_DragEnter +31 stub ImageList_DragLeave +32 stub ImageList_DragMove +33 stub ImageList_DragShowNolock +34 stub ImageList_Draw +35 stub ImageList_DrawEx +36 stub ImageList_EndDrag +37 stub ImageList_GetBkColor +38 stub ImageList_GetDragImage +39 stub ImageList_GetIcon +40 stub ImageList_GetIconSize +41 stub ImageList_GetImageCount +42 stub ImageList_GetImageInfo +43 stub ImageList_GetImageRect +44 stub ImageList_LoadImage +45 stub ImageList_LoadImageA +46 stub ImageList_LoadImageW +47 stub ImageList_Merge +48 stub ImageList_Read +49 stub ImageList_Remove +50 stub ImageList_Replace +51 stub ImageList_ReplaceIcon +52 stub ImageList_SetBkColor +53 stub ImageList_SetDragCursorImage +54 stub ImageList_SetFilter +55 stub ImageList_SetIconSize +56 stub ImageList_SetImageCount +57 stub ImageList_SetOverlayImage +58 stub ImageList_Write +59 stub InitCommonControlsEx +60 stub PropertySheet +61 stub PropertySheetA +62 stub PropertySheetW +63 stub _TrackMouseEvent diff --git a/if1632/compobj.spec b/if1632/compobj.spec index e325c24c683..3f81756072c 100644 --- a/if1632/compobj.spec +++ b/if1632/compobj.spec @@ -19,8 +19,8 @@ type win16 16 stub CORELEASEMARSHALDATA 17 stub COFREEUNUSEDLIBRARIES 18 stub ISEQUALGUID -19 stub STRINGFROMCLSID -20 stub CLSIDFROMSTRING +19 pascal STRINGFROMCLSID(ptr ptr) StringFromCLSID +20 pascal CLSIDFROMSTRING(str ptr) CLSIDFromString 21 stub ISVALIDPTRIN 22 stub ISVALIDPTROUT 23 stub ISVALIDINTERFACE diff --git a/if1632/gdi.spec b/if1632/gdi.spec index f1ef2bd4c19..e407b446d4a 100644 --- a/if1632/gdi.spec +++ b/if1632/gdi.spec @@ -1,6 +1,7 @@ name gdi type win16 heap 65488 # 65536 - 16 (instance data) - 32 (stock objects) +file gdi.exe 1 pascal SetBkColor(word long) SetBkColor16 2 pascal16 SetBkMode(word word) SetBkMode16 diff --git a/if1632/kernel.spec b/if1632/kernel.spec index 7153880e4a0..39a6b41c6dd 100644 --- a/if1632/kernel.spec +++ b/if1632/kernel.spec @@ -1,5 +1,6 @@ name kernel type win16 +file krnl386.exe 1 stub FatalExit 2 stub ExitKernel @@ -317,9 +318,9 @@ type win16 502 stub KERNEL_502 503 stub KERNEL_503 511 stub KERNEL_511 -513 pascal LoadLibraryEx32W(ptr long long) LoadLibraryEx32W16 -514 stub FreeLibrary32W -515 pascal GetProcAddress32W(long ptr) GetProcAddress32 +513 pascal LoadLibraryEx32W(ptr long long) LoadLibraryEx32W16 +514 pascal16 FreeLibrary32W(long) FreeLibrary32 +515 pascal GetProcAddress32W(long ptr) GetProcAddress32 516 stub GetVDMPointer32W 517 pascal CallProc32W() WIN16_CallProc32W 518 stub CallProcEx32W diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec index f824dc1a0ab..b858d621841 100644 --- a/if1632/kernel32.spec +++ b/if1632/kernel32.spec @@ -26,14 +26,18 @@ base 1 30 stub _KERNEL32_31 -34 stub LoadLibrary16 +33 stdcall _KERNEL32_34() _KERNEL32_34 +34 stdcall LoadLibrary16(ptr) LoadLibrary16 35 stub FreeLibrary16 -36 stub GetProcAddress16 +36 stdcall GetProcAddress16(long ptr) WIN32_GetProcAddress16 39 stub _KERNEL32_40 - -42 return _KERNEL32_43 20 0 -44 stub _KERNEL32_45 +40 stdcall _KERNEL32_41(long long long long long) _KERNEL32_41 +41 stub _KERNEL32_42 +42 stdcall _KERNEL32_43(long ptr long ptr ptr) _KERNEL32_43 +44 register _KERNEL32_45(long) _KERNEL32_45 +45 stdcall _KERNEL32_46(long long long long long) _KERNEL32_46 +46 stub _KERNEL32_47 49 stdcall AddAtomA(ptr) AddAtom32A @@ -42,7 +46,7 @@ base 1 # WOW calls 53 stub WOWCallback16 54 stub WOWCallback16Ex -55 stub WOWGetVDMPointer +55 stdcall WOWGetVDMPointer(long long long) WOWGetVDMPointer 56 stub WOWHandle32 57 stub WOWHandle16 58 stub WOWGlobalAlloc16 @@ -54,9 +58,9 @@ base 1 64 stub WOWGlobalLockSize16 65 stub WOWYield16 66 stub WOWDirectedYield16 -67 stub WOWGetVDMPointerFix -68 stub WOWGetVDMPointerUnfix -69 stub WOW32_1 +67 stdcall WOWGetVDMPointerFix(long long long) WOWGetVDMPointerFix +68 stdcall WOWGetVDMPointerUnfix(long) WOWGetVDMPointerUnfix +69 stdcall WOW32_1(long long) WOW32_1 71 stub RtlLargeIntegerAdd 72 stub RtlEnlargedIntegerMultiply @@ -73,11 +77,12 @@ base 1 83 stub RtlConvertLongToLargeInteger 84 stub RtlConvertUlongToLargeInteger -86 stub _KERNEL32_87 -87 stub _KERNEL32_88 - -90 stub _KERNEL32_90 -91 stub _KERNEL32_91 +86 stdcall _KERNEL32_87() _KERNEL32_87 +87 cdecl _KERNEL32_88(long long ptr) _KERNEL32_88 +88 stub _KERNEL32_89 +89 stub _KERNEL32_90 +90 register _KERNEL32_91() _KERNEL32_91 +91 stub _KERNEL32_92 92 stdcall GETPWIN16LOCK(ptr) GetPWinLock 96 stub ENTERSYSLEVEL 97 stub LEAVESYSLEVEL diff --git a/if1632/signal.c b/if1632/signal.c new file mode 100644 index 00000000000..58f0c0b74f2 --- /dev/null +++ b/if1632/signal.c @@ -0,0 +1,124 @@ +/* + * Emulator signal handling + * + * Copyright 1995 Alexandre Julliard + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__svr4__) || defined(_SCO_DS) || defined(__EMX__) +# if !defined(_SCO_DS) && !defined(__EMX__) +# include +# endif +# include +#else +# include +#endif + +#include "debugger.h" +#include "options.h" +#include "sigcontext.h" +#include "miscemu.h" + + +/* Signal handler declaration */ + +#ifdef linux +#define HANDLER_DEF(name) void name (int signal, SIGCONTEXT context_struct) +#define HANDLER_PROLOG SIGCONTEXT *context = &context_struct; { +#define HANDLER_EPILOG } +#elif defined(__svr4__) || defined(_SCO_DS) +#define HANDLER_DEF(name) void name (int signal, void *siginfo, SIGCONTEXT *context) +#define HANDLER_PROLOG /* nothing */ +#define HANDLER_EPILOG /* nothing */ +#else +#define HANDLER_DEF(name) void name (int signal, int code, SIGCONTEXT *context) +#define HANDLER_PROLOG /* nothing */ +#define HANDLER_EPILOG /* nothing */ +#endif + +extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags ); +extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context ); + + +/********************************************************************** + * SIGNAL_break + * + * Handle Ctrl-C and such + */ +static HANDLER_DEF(SIGNAL_break) +{ + HANDLER_PROLOG; + if (Options.debug) wine_debug( signal, context ); /* Enter our debugger */ + else exit(0); + HANDLER_EPILOG; +} + + +/********************************************************************** + * SIGNAL_trap + * + * SIGTRAP handler. + */ +static HANDLER_DEF(SIGNAL_trap) +{ + HANDLER_PROLOG; + wine_debug( signal, context ); /* Enter our debugger */ + HANDLER_EPILOG; +} + + +/********************************************************************** + * SIGNAL_fault + * + * Segfault handler. + */ +static HANDLER_DEF(SIGNAL_fault) +{ + HANDLER_PROLOG; + if (CS_sig(context) == WINE_CODE_SELECTOR) + { + fprintf( stderr, "Segmentation fault in Wine program (%04x:%08lx)." + " Please debug.\n", + (unsigned short) CS_sig(context), EIP_sig(context)); + } + else + { + if (INSTR_EmulateInstruction( context )) return; + fprintf( stderr, "Segmentation fault in Windows program %04x:%08lx.\n", + (unsigned short) CS_sig(context), EIP_sig(context) ); + } + wine_debug( signal, context ); + HANDLER_EPILOG; +} + + +/********************************************************************** + * SIGNAL_InitEmulator + * + * Initialize emulator signals. + */ +BOOL32 SIGNAL_InitEmulator(void) +{ + SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1); + SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1); + SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */ + SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break*/ +#ifdef SIGBUS + SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1); +#endif + return TRUE; +} diff --git a/if1632/system.spec b/if1632/system.spec index 13523967962..311643b816e 100644 --- a/if1632/system.spec +++ b/if1632/system.spec @@ -1,11 +1,11 @@ name system type win16 -1 pascal InquireSystem(word word word) InquireSystem -2 stub CreateSystemTimer -3 stub KillSystemTimer -4 stub EnableSystemTimers -5 stub DisableSystemTimers +1 pascal InquireSystem(word word) InquireSystem +2 pascal16 CreateSystemTimer(word segptr) THUNK_CreateSystemTimer +3 pascal16 KillSystemTimer(word) THUNK_KillSystemTimer +4 pascal16 EnableSystemTimers() EnableSystemTimers +5 pascal16 DisableSystemTimers() DisableSystemTimers 6 pascal GetSystemMSecCount() GetTickCount 7 return Get80x87SaveSize 0 94 8 stub Save80x87State diff --git a/if1632/thunk.c b/if1632/thunk.c index 5714096336d..39cf091691c 100644 --- a/if1632/thunk.c +++ b/if1632/thunk.c @@ -595,7 +595,33 @@ BOOL16 THUNK_UnhookWindowsHookEx16( HHOOK hhook ) } -/************************************************************* +/*********************************************************************** + * THUNK_CreateSystemTimer (SYSTEM.2) + */ +WORD THUNK_CreateSystemTimer( WORD rate, FARPROC16 callback ) +{ + THUNK *thunk = THUNK_Alloc( callback, (RELAY)CallTo16_word_ ); + if (!thunk) return 0; + return CreateSystemTimer( rate, (FARPROC16)thunk ); +} + + +/*********************************************************************** + * THUNK_KillSystemTimer (SYSTEM.3) + */ +WORD THUNK_KillSystemTimer( WORD timer ) +{ + extern WORD SYSTEM_KillSystemTimer( WORD timer ); /* misc/system.c */ + extern FARPROC16 SYSTEM_GetTimerProc( WORD timer ); /* misc/system.c */ + + THUNK *thunk = (THUNK *)SYSTEM_GetTimerProc( timer ); + WORD ret = SYSTEM_KillSystemTimer( timer ); + if (thunk) THUNK_Free( thunk ); + return ret; +} + + +/*********************************************************************** * THUNK_SetUnhandledExceptionFilter (KERNEL32.516) */ LPTOP_LEVEL_EXCEPTION_FILTER THUNK_SetUnhandledExceptionFilter( diff --git a/if1632/user.spec b/if1632/user.spec index aef0e5b4198..5f2dce14605 100644 --- a/if1632/user.spec +++ b/if1632/user.spec @@ -1,6 +1,7 @@ name user type win16 heap 65520 +file user.exe 1 pascal16 MessageBox(word str str word) MessageBox16 2 stub OldExitWindows @@ -247,7 +248,7 @@ heap 65520 CreateDialogIndirectParam16 243 pascal GetDialogBaseUnits() GetDialogBaseUnits 244 pascal16 EqualRect(ptr ptr) EqualRect16 -245 stub EnableCommNotification +245 pascal16 EnableCommNotification(s_word word s_word s_word) EnableCommNotification 246 pascal16 ExitWindowsExec(str str) ExitWindowsExec16 247 pascal16 GetCursor() GetCursor16 248 pascal16 GetOpenClipboardWindow() GetOpenClipboardWindow16 diff --git a/if1632/user32.spec b/if1632/user32.spec index 99bcd8ee492..2144d97876e 100644 --- a/if1632/user32.spec +++ b/if1632/user32.spec @@ -156,7 +156,7 @@ base 1 0149 stdcall DlgDirSelectExW(long ptr long long) DlgDirSelectEx32W 0150 stdcall DragDetect(long long long) DragDetect32 0151 stub DragObject -0152 stub DrawAnimatedRects +0152 stdcall DrawAnimatedRects(long long ptr ptr) DrawAnimatedRects32 0153 stub DrawCaption 0154 stdcall DrawEdge(long ptr long long) DrawEdge32 0155 stdcall DrawFocusRect(long ptr) DrawFocusRect32 @@ -267,8 +267,8 @@ base 1 0260 stub GetMenuIndex 0261 stdcall GetMenuItemCount(long) GetMenuItemCount32 0262 stdcall GetMenuItemID(long long) GetMenuItemID32 -0263 stub GetMenuItemInfoA -0264 stub GetMenuItemInfoW +0263 stdcall GetMenuItemInfoA(long long long ptr) GetMenuItemInfo32A +0264 stdcall GetMenuItemInfoW(long long long ptr) GetMenuItemInfo32W 0265 stub GetMenuItemRect 0266 stdcall GetMenuState(long long long) GetMenuState32 0267 stdcall GetMenuStringA(long long ptr long long) GetMenuString32A diff --git a/include/callback.h b/include/callback.h index d1cb792037d..c2d1020d9c9 100644 --- a/include/callback.h +++ b/include/callback.h @@ -48,6 +48,8 @@ extern LONG CallTo16_long_lwwllwlllllw( FARPROC16, LONG, WORD, WORD, LONG, #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \ CallTo16_long_lwwll( func, dwId, msg, hdrvr, lparam1, lparam2 ) +#define CallDriverCallback( func, hdev, msg, user, lparam1, lparam2 ) \ + CallTo16_word_wwlll( func, hdev, msg, user, lparam1, lparam2 ) #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \ CallTo16_word_wwlll( func, id, msg, dwUser, dw1, dw2 ) #define CallWindowsExitProc( func, nExitType ) \ @@ -78,6 +80,8 @@ extern LONG CallTo32_5( FARPROC32, DWORD, DWORD, DWORD, DWORD, DWORD ); #define CallDriverProc( func, dwId, msg, hdrvr, lparam1, lparam2 ) \ (*func)( dwId, msg, hdrvr, lparam1, lparam2 ) +#define CallDriverCallback( func, hdev, msg, user, lparam1, lparam2 ) \ + (*func)( hdev, msg, user, lparam1, lparam2 ) #define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \ (*func)( id, msg, dwUser, dw1, dw2 ) #define CallWindowsExitProc( func, nExitType ) \ diff --git a/include/compobj.h b/include/compobj.h new file mode 100644 index 00000000000..baa348f9ee4 --- /dev/null +++ b/include/compobj.h @@ -0,0 +1,16 @@ +#if !defined(COMPOBJ_H) +#define COMPOBJ_H + +struct tagCLSID { + DWORD Data1; + WORD Data2; + WORD Data3; + BYTE Data4[8]; +}; + +typedef struct tagCLSID CLSID; + +OLESTATUS StringFromCLSID(const CLSID *id, LPSTR); +OLESTATUS CLSIDFromString(const LPCSTR, CLSID *); + +#endif diff --git a/include/miscemu.h b/include/miscemu.h index dba7cffe132..4b5847b4b6a 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -10,7 +10,7 @@ #include #include "winnt.h" - /* miscemu/dosmem.c */ + /* msdos/dosmem.c */ extern HANDLE16 DOSMEM_BiosSeg; extern DWORD DOSMEM_CollateTable; @@ -24,9 +24,6 @@ extern LPVOID DOSMEM_MapRealToLinear(DWORD); /* real-mode to linear */ extern LPVOID DOSMEM_MapDosToLinear(UINT32); /* linear DOS to Wine */ extern UINT32 DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ -/* miscemu/interrupts.c */ -extern BOOL32 INT_Init(void); - /* msdos/interrupts.c */ extern FARPROC16 INT_GetHandler( BYTE intnum ); extern void INT_SetHandler( BYTE intnum, FARPROC16 handler ); @@ -39,6 +36,14 @@ extern void IO_outport( int port, int count, DWORD value ); /* msdos/int1a.c */ extern DWORD INT1A_GetTicksSinceMidnight(void); +/* loader/signal.c */ +extern BOOL32 SIGNAL_Init(void); +extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags ); +extern void SIGNAL_MaskAsyncEvents( BOOL32 flag ); + +/* if1632/signal.c */ +extern BOOL32 SIGNAL_InitEmulator(void); + #define INT_BARF(context,num) \ fprintf( stderr, "int%x: unknown/not implemented parameters:\n" \ "int%x: AX %04x, BX %04x, CX %04x, DX %04x, " \ diff --git a/include/module.h b/include/module.h index 872b498f4b8..563a2d8b2fd 100644 --- a/include/module.h +++ b/include/module.h @@ -126,6 +126,7 @@ extern FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal ); extern BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ); extern FARPROC16 MODULE_GetWndProcEntry16( const char *name ); +extern FARPROC16 WIN32_GetProcAddress16( HMODULE16 hmodule, LPSTR name ); /* builtin.c */ extern BOOL16 BUILTIN_Init(void); diff --git a/include/tweak.h b/include/tweak.h index d2dcbf683cb..02ac88a1bd9 100644 --- a/include/tweak.h +++ b/include/tweak.h @@ -15,7 +15,9 @@ int TWEAK_Init(); int TWEAK_CheckConfiguration(); INT32 TWEAK_PartyMessageBox(LPCSTR, LPCSTR, DWORD); void TWEAK_DrawReliefRect95(HDC32, RECT32 const *); -void TWEAK_DrawMenuSeparator95(HDC32, UINT32, UINT32, UINT32); +void TWEAK_DrawRevReliefRect95(HDC32, RECT32 const *); +void TWEAK_DrawMenuSeparatorHoriz95(HDC32, UINT32, UINT32, UINT32); +void TWEAK_DrawMenuSeparatorVert95(HDC32, UINT32, UINT32, UINT32); extern int TWEAK_Win95Look; extern int TWEAK_WineInitialized; extern HPEN32 TWEAK_PenFF95; diff --git a/include/win16drv.h b/include/win16drv.h index f7d144c8e0d..88acb12ccd5 100644 --- a/include/win16drv.h +++ b/include/win16drv.h @@ -188,6 +188,8 @@ extern BOOL32 WIN16DRV_ExtTextOut( DC *dc, INT32 x, INT32 y, UINT32 flags, const RECT32 *lprect, LPCSTR str, UINT32 count, const INT32 *lpDx ); extern HGDIOBJ32 WIN16DRV_SelectObject( DC *dc, HGDIOBJ32 handle ); +extern BOOL32 WIN16DRV_PatBlt( struct tagDC *dc, INT32 left, INT32 top, + INT32 width, INT32 height, DWORD rop ); diff --git a/include/windows.h b/include/windows.h index 28dd31de9dc..06814ac209c 100644 --- a/include/windows.h +++ b/include/windows.h @@ -2844,6 +2844,67 @@ typedef struct #define MF_HELP 0x4000 #define MF_MOUSESELECT 0x8000 +/* Flags for extended menu item types. */ +#define MFT_STRING MF_STRING +#define MFT_BITMAP MF_BITMAP +#define MFT_MENUBARBREAK MF_MENUBARBREAK +#define MFT_MENUBREAK MF_MENUBREAK +#define MFT_OWNERDRAW MF_OWNERDRAW +#define MFT_RADIOCHECK 0x00000200L +#define MFT_SEPARATOR MF_SEPARATOR +#define MFT_RIGHTORDER 0x00002000L +#define MFT_RIGHTJUSTIFY MF_RIGHTJUSTIFY + +/* Flags for extended menu item states. */ +#define MFS_GRAYED 0x00000003L +#define MFS_DISABLED MFS_GRAYED +#define MFS_CHECKED MF_CHECKED +#define MFS_HILITE MF_HILITE +#define MFS_ENABLED MF_ENABLED +#define MFS_UNCHECKED MF_UNCHECKED +#define MFS_UNHILITE MF_UNHILITE +#define MFS_DEFAULT MF_DEFAULT + +typedef struct { + UINT32 cbSize; + UINT32 fMask; + UINT32 fType; + UINT32 fState; + UINT32 wID; + HMENU32 hSubMenu; + HBITMAP32 hbmpChecked; + HBITMAP32 hbmpUnchecked; + DWORD dwItemData; + LPSTR dwTypeData; + UINT32 cch; +} MENUITEMINFO32A, *LPMENUITEMINFO32A; + +typedef struct { + UINT32 cbSize; + UINT32 fMask; + UINT32 fType; + UINT32 fState; + UINT32 wID; + HMENU32 hSubMenu; + HBITMAP32 hbmpChecked; + HBITMAP32 hbmpUnchecked; + DWORD dwItemData; + LPWSTR dwTypeData; + UINT32 cch; +} MENUITEMINFO32W, *LPMENUITEMINFO32W; + +DECL_WINELIB_TYPE_AW(MENUITEMINFO); +DECL_WINELIB_TYPE_AW(LPMENUITEMINFO); + +/* Field specifiers for MENUITEMINFO[AW] type. */ +#define MIIM_STATE 0x00000001 +#define MIIM_ID 0x00000002 +#define MIIM_SUBMENU 0x00000004 +#define MIIM_CHECKMARKS 0x00000008 +#define MIIM_TYPE 0x00000010 +#define MIIM_DATA 0x00000020 + + #ifndef NOWINOFFSETS #define GCW_HBRBACKGROUND (-10) #endif @@ -5070,13 +5131,17 @@ INT16 Catch(LPCATCHBUF); WORD ChangeSelector(WORD,WORD); INT16 CloseComm(INT16); HGLOBAL16 CreateCursorIconIndirect(HINSTANCE16,CURSORICONINFO*,LPCVOID,LPCVOID); +WORD CreateSystemTimer(WORD,FARPROC16); BOOL16 DCHook(HDC16,WORD,DWORD,LPARAM); VOID DirectedYield(HTASK16); HGLOBAL16 DirectResAlloc(HINSTANCE16,WORD,UINT16); +VOID DisableSystemTimers(void); BOOL16 DlgDirSelect(HWND16,LPSTR,INT16); BOOL16 DlgDirSelectComboBox(HWND16,LPSTR,INT16); DWORD DumpIcon(SEGPTR,WORD*,SEGPTR*,SEGPTR*); +BOOL16 EnableCommNotification(INT16,HWND16,INT16,INT16); BOOL16 EnableHardwareInput(BOOL16); +VOID EnableSystemTimers(void); INT16 ExcludeVisRect(HDC16,INT16,INT16,INT16,INT16); HANDLE16 FarGetOwner(HGLOBAL16); VOID FarSetOwner(HGLOBAL16,HANDLE16); @@ -5283,6 +5348,9 @@ DWORD GetFullPathName32W(LPCWSTR,DWORD,LPWSTR,LPWSTR*); #define GetFullPathName WINELIB_NAME_AW(GetFullPathName) VOID GetLocalTime(LPSYSTEMTIME); DWORD GetLogicalDrives(void); +BOOL32 GetMenuItemInfo32A(HMENU32,UINT32,BOOL32,MENUITEMINFO32A*); +BOOL32 GetMenuItemInfo32W(HMENU32,UINT32,BOOL32,MENUITEMINFO32W*); +#define GetMenuItemInfo WINELIB_NAME_AW(GetMenuItemInfo) UINT32 GetOEMCP(void); DWORD GetPriorityClass(HANDLE32); HANDLE32 GetProcessHeap(void); diff --git a/library/miscstubs.c b/library/miscstubs.c index 809e3da0150..045f25ac00e 100644 --- a/library/miscstubs.c +++ b/library/miscstubs.c @@ -12,10 +12,6 @@ #include "global.h" #include "debug.h" -void SIGNAL_MaskAsyncEvents( BOOL32 mask ) -{ - /* FIXME: signals don't work in the library */ -} /* for windows/winproc.c */ void CallFrom16_long_wwwll(void) {} diff --git a/libtest/Makefile.in b/libtest/Makefile.in index 32d39365771..e9f772a83e4 100644 --- a/libtest/Makefile.in +++ b/libtest/Makefile.in @@ -3,10 +3,11 @@ TOPOBJDIR = .. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = none -PROGRAMS = hello hello2 hello3 hello4 new rolex +PROGRAMS = expand hello hello2 hello3 hello4 new rolex ALL_LIBS = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS) C_SRCS = \ + expand.c \ hello.c \ hello2.c \ hello3.c \ @@ -21,6 +22,9 @@ all: check_winerc $(PROGRAMS) @MAKE_RULES@ +expand: expand.o + $(CC) -o expand expand.o $(LDOPTIONS) $(ALL_LIBS) + hello: hello.o $(CC) -o hello hello.o $(LDOPTIONS) $(ALL_LIBS) diff --git a/libtest/expand.c b/libtest/expand.c new file mode 100644 index 00000000000..656a3d610ef --- /dev/null +++ b/libtest/expand.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include + +int PASCAL WinMain(HINSTANCE hinstCurrent, + HINSTANCE hinstPrevious, + LPSTR lpCmdLine, + int nCmdShow) +{ + OFSTRUCT SourceOpenStruct1, SourceOpenStruct2; + char OriginalName[256], WriteBuf[256]; + char FAR *lpzDestFile, + FAR *lpzHolder = lpCmdLine, + FAR *arrgv[2] = {0}; + int wargs; + DWORD dwreturn; + HFILE hSourceFile, hDestFile; + + for (wargs = 1; wargs < 3; wargs++) + {arrgv[wargs] = lpzHolder; + for (; *lpzHolder != '\0'; lpzHolder++) + if (*lpzHolder == ' ') {*lpzHolder++ = '\0'; break;}; + }; + +MessageBox((HWND)NULL, (LPCSTR)arrgv[1], (LPCSTR)"arrgv[1]:", MB_OK); +MessageBox((HWND)NULL, (LPCSTR)arrgv[2], (LPCSTR)"arrgv[2]:", MB_OK); + + hSourceFile = LZOpenFile(arrgv[1], (LPOFSTRUCT) &SourceOpenStruct1, + OF_READ); + +wsprintf(WriteBuf, "Source File Handle: %d\nNo. of args: %d", + hSourceFile, wargs); +MessageBox((HWND)NULL, (LPCSTR)WriteBuf, (LPCSTR)NULL, MB_OK); + + if ((wargs == 3) && (arrgv[2] != NULL)) lpzDestFile = arrgv[2]; + else + { + lpzDestFile = OriginalName; + GetExpandedName(arrgv[1], lpzDestFile); + }; + + MessageBox((HWND)NULL, (LPCSTR)lpzDestFile, (LPCSTR)"Destination File", + MB_OK); + + hDestFile = LZOpenFile(lpzDestFile, (LPOFSTRUCT) &SourceOpenStruct2, + OF_CREATE | OF_WRITE); +wsprintf(WriteBuf, "Destination File Handle: %d\nNo. of args: %d", + hDestFile, wargs-1); +MessageBox((HWND)NULL, (LPCSTR)WriteBuf, (LPCSTR)NULL, MB_OK); + + dwreturn = LZCopy(hSourceFile, hDestFile); + + if (dwreturn == LZERROR_BADINHANDLE) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_BADINHANDLE\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_BADOUTHANDLE) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_BADOUTHANDLE\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_BADVALUE) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_BADVALUE\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_GLOBALLOC) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_GLOBALLOC\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_GLOBLOCK) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_GLOBLOCK\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_READ) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_READ\n", (LPCSTR)NULL, MB_OK); + if (dwreturn == LZERROR_WRITE) + MessageBox((HWND)NULL, (LPCSTR)"LZERROR_WRITE\n", (LPCSTR)NULL, MB_OK); + if ((long)dwreturn > 0L) + {wsprintf((LPSTR)WriteBuf, (LPCSTR)"Successful decompression from %s to %s\n", + arrgv[1], lpzDestFile); + MessageBox((HWND)NULL, (LPSTR)WriteBuf, (LPCSTR)NULL, MB_OK); + }; + LZClose(hSourceFile); LZClose(hDestFile); + return dwreturn; +} diff --git a/loader/main.c b/loader/main.c index 4fb3aa3d249..4ac8026e384 100644 --- a/loader/main.c +++ b/loader/main.c @@ -44,12 +44,7 @@ static char Copyright[] = "Copyright Robert J. Amstadt, 1993"; #include "debugger.h" #endif -/* Winelib run-time flag */ -#ifdef WINELIB -int __winelib = 1; -#else -int __winelib = 0; -#endif +int __winelib = 1; /* Winelib run-time flag */ HANDLE32 SystemHeap = 0; HANDLE32 SegptrHeap = 0; @@ -61,7 +56,6 @@ int MAIN_Init(void) { extern BOOL32 RELAY_Init(void); extern BOOL32 WIN16DRV_Init(void); - extern BOOL32 SIGNAL_Init(void); extern BOOL32 VIRTUAL_Init(void); extern BOOL32 WIDGETS_Init(void); @@ -80,6 +74,9 @@ int MAIN_Init(void) /* Initialize DOS memory */ if (!DOSMEM_Init()) return 0; + /* Initialize signal handling */ + if (!SIGNAL_Init()) return 0; + #ifdef WINELIB /* Create USER and GDI heap */ USER_HeapSel = GlobalAlloc16( GMEM_FIXED, 0x10000 ); @@ -94,7 +91,7 @@ int MAIN_Init(void) if (!BUILTIN_Init()) return 0; /* Initialize signal handling */ - if (!SIGNAL_Init()) return 0; + if (!SIGNAL_InitEmulator()) return 0; /* Create the Win16 printer driver */ if (!WIN16DRV_Init()) return 0; @@ -184,6 +181,8 @@ int main(int argc, char *argv[] ) int i,loaded; HINSTANCE16 handle; + __winelib = 0; /* First of all, clear the Winelib flag */ + /* * Save this so that the internal debugger can get a hold of it if * it needs to. diff --git a/loader/module.c b/loader/module.c index a3522c61db8..bd128303a5d 100644 --- a/loader/module.c +++ b/loader/module.c @@ -1162,8 +1162,9 @@ HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, BOOL32 first ) 0xFF00, hModule, FALSE, FALSE, FALSE) ); oldstack = IF1632_Saved16_ss_sp; - IF1632_Saved16_ss_sp = MAKELONG( 0xFF00 - sizeof(*stack16Top), - pModule->self_loading_sel ); + IF1632_Saved16_ss_sp = + PTR_SEG_OFF_TO_SEGPTR( pModule->self_loading_sel, + 0xff00 - sizeof(*stack16Top) ); stack16Top = CURRENT_STACK16; stack16Top->saved_ss_sp = 0; stack16Top->ebp = 0; @@ -1458,10 +1459,11 @@ HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow ) { LOADPARAMS params; HGLOBAL16 cmdShowHandle, cmdLineHandle; - HINSTANCE16 handle; + HINSTANCE16 handle = 2; WORD *cmdShowPtr; char *p, *cmdline, filename[256]; static int use_load_module = 1; + int spacelimit = 0, exhausted = 0; if (!lpCmdLine) return 2; /* File not found */ @@ -1473,115 +1475,148 @@ HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow ) return 8; /* Out of memory */ } - /* Store nCmdShow */ + /* Keep trying to load a file by trying different filenames; e.g., + for the cmdline "abcd efg hij", try "abcd" with args "efg hij", + then "abcd efg" with arg "hij", and finally "abcd efg hij" with + no args */ - cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle ); - cmdShowPtr[0] = 2; - cmdShowPtr[1] = nCmdShow; + while(!exhausted && handle == 2) { + int spacecount = 0; - /* Build the filename and command-line */ + /* Store nCmdShow */ - cmdline = (char *)GlobalLock16( cmdLineHandle ); - lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */); - for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++); - if (*p) lstrcpyn32A( cmdline + 1, p + 1, 127 ); - else cmdline[1] = '\0'; - cmdline[0] = strlen( cmdline + 1 ) + 1; - *p = '\0'; + cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle ); + cmdShowPtr[0] = 2; + cmdShowPtr[1] = nCmdShow; - /* Now load the executable file */ + /* Build the filename and command-line */ - if (use_load_module) - { + cmdline = (char *)GlobalLock16( cmdLineHandle ); + lstrcpyn32A(filename, lpCmdLine, + sizeof(filename) - 4 /* for extension */); + + /* Keep grabbing characters until end-of-string, tab, or until the + number of spaces is greater than the spacelimit */ + + for (p = filename; ; p++) { + if(*p == ' ') { + ++spacecount; + if(spacecount > spacelimit) { + ++spacelimit; + break; + } + } + + if(*p == '\0' || *p == '\t') { + exhausted = 1; + break; + } + } + + if (*p) + lstrcpyn32A( cmdline + 1, p + 1, 127 ); + else + cmdline[1] = '\0'; + + cmdline[0] = strlen( cmdline + 1 ) + 1; + *p = '\0'; + + /* Now load the executable file */ + + if (use_load_module) + { #ifdef WINELIB - /* WINELIB: Use LoadModule() only for the program itself */ - use_load_module = 0; - params.hEnvironment = (HGLOBAL16)GetDOSEnvironment(); + /* WINELIB: Use LoadModule() only for the program itself */ + use_load_module = 0; + params.hEnvironment = (HGLOBAL16)GetDOSEnvironment(); #else - params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() ); + params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() ); #endif /* WINELIB */ - params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle ); - params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle ); - params.reserved = 0; - handle = LoadModule16( filename, ¶ms ); - if (handle == 2) /* file not found */ - { - /* Check that the original file name did not have a suffix */ - p = strrchr(filename, '.'); - /* if there is a '.', check if either \ OR / follow */ - if (!p || strchr(p, '/') || strchr(p, '\\')) - { - p = filename + strlen(filename); - strcpy( p, ".exe" ); - handle = LoadModule16( filename, ¶ms ); - *p = '\0'; /* Remove extension */ - } + params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle ); + params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle ); + params.reserved = 0; + handle = LoadModule16( filename, ¶ms ); + if (handle == 2) /* file not found */ + { + /* Check that the original file name did not have a suffix */ + p = strrchr(filename, '.'); + /* if there is a '.', check if either \ OR / follow */ + if (!p || strchr(p, '/') || strchr(p, '\\')) + { + p = filename + strlen(filename); + strcpy( p, ".exe" ); + handle = LoadModule16( filename, ¶ms ); + *p = '\0'; /* Remove extension */ + } + } } - } - else handle = 2; + else + handle = 2; /* file not found */ - if (handle < 32) - { - /* Try to start it as a unix program */ - if (!fork()) + if (handle < 32) { - /* Child process */ - DOS_FULL_NAME full_name; - const char *unixfilename = NULL; - const char *argv[256], **argptr; - int iconic = (nCmdShow == SW_SHOWMINIMIZED || - nCmdShow == SW_SHOWMINNOACTIVE); + /* Try to start it as a unix program */ + if (!fork()) + { + /* Child process */ + DOS_FULL_NAME full_name; + const char *unixfilename = NULL; + const char *argv[256], **argptr; + int iconic = (nCmdShow == SW_SHOWMINIMIZED || + nCmdShow == SW_SHOWMINNOACTIVE); - /* get unixfilename */ - if (strchr(filename, '/') || - strchr(filename, ':') || - strchr(filename, '\\')) - { - if (DOSFS_GetFullName( filename, TRUE, &full_name )) - unixfilename = full_name.long_name; - } - else unixfilename = filename; + /* get unixfilename */ + if (strchr(filename, '/') || + strchr(filename, ':') || + strchr(filename, '\\')) + { + if (DOSFS_GetFullName( filename, TRUE, &full_name )) + unixfilename = full_name.long_name; + } + else unixfilename = filename; - if (unixfilename) - { - /* build argv */ - argptr = argv; - if (iconic) *argptr++ = "-iconic"; - *argptr++ = unixfilename; - p = cmdline; - while (1) - { - while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0'; - if (!*p) break; - *argptr++ = p; - while (*p && *p != ' ' && *p != '\t') p++; - } - *argptr++ = 0; + if (unixfilename) + { + /* build argv */ + argptr = argv; + if (iconic) *argptr++ = "-iconic"; + *argptr++ = unixfilename; + p = cmdline; + while (1) + { + while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0'; + if (!*p) break; + *argptr++ = p; + while (*p && *p != ' ' && *p != '\t') p++; + } + *argptr++ = 0; - /* Execute */ - execvp(argv[0], (char**)argv); - } + /* Execute */ + execvp(argv[0], (char**)argv); + } - /* Failed ! */ + /* Failed ! */ - if (__winelib) - { - /* build argv */ - argptr = argv; - *argptr++ = "wine"; - if (iconic) *argptr++ = "-iconic"; - *argptr++ = lpCmdLine; - *argptr++ = 0; + if (__winelib) + { + /* build argv */ + argptr = argv; + *argptr++ = "wine"; + if (iconic) *argptr++ = "-iconic"; + *argptr++ = lpCmdLine; + *argptr++ = 0; - /* Execute */ - execvp(argv[0] , (char**)argv); + /* Execute */ + execvp(argv[0] , (char**)argv); - /* Failed ! */ - fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine); - } - exit(1); + /* Failed ! */ + fprintf(stderr, "WinExec: can't exec 'wine %s'\n", + lpCmdLine); + } + exit(1); + } } - } + } /* while (!exhausted && handle < 32) */ GlobalFree16( cmdShowHandle ); GlobalFree16( cmdLineHandle ); @@ -1589,6 +1624,35 @@ HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow ) } +/*********************************************************************** + * WIN32_GetProcAddress16 (KERNEL32.36) + * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func) + */ +FARPROC16 WIN32_GetProcAddress16( HMODULE16 hModule, LPSTR name ) +{ + WORD ordinal; + FARPROC16 ret; + + if (!hModule) { + fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n"); + return (FARPROC16)0; + } + hModule = GetExePtr(hModule); + if (HIWORD(name)) { + ordinal = MODULE_GetOrdinal( hModule, name ); + dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n", + hModule, name ); + } else { + ordinal = LOWORD(name); + dprintf_module( stddeb, "GetProcAddress: %04x %04x\n", + hModule, ordinal ); + } + if (!ordinal) return (FARPROC16)0; + ret = MODULE_GetEntryPoint( hModule, ordinal ); + dprintf_module(stddeb,"WIN32_GetProcAddress16: returning %08x\n",(UINT32)ret); + return ret; +} + /*********************************************************************** * GetProcAddress16 (KERNEL.50) */ diff --git a/loader/ne_image.c b/loader/ne_image.c index ca2819b4a4a..353620664fe 100644 --- a/loader/ne_image.c +++ b/loader/ne_image.c @@ -77,8 +77,8 @@ BOOL32 NE_LoadSegment( HMODULE16 hModule, WORD segnum ) PTR_SEG_OFF_TO_LIN(pSegTable->selector,0); oldstack = IF1632_Saved16_ss_sp; oldselector = pSeg->selector; - IF1632_Saved16_ss_sp = MAKELONG( 0xFF00 - sizeof(*stack16Top), - pModule->self_loading_sel ); + IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel, + 0xff00 - sizeof(*stack16Top)); stack16Top = CURRENT_STACK16; stack16Top->saved_ss_sp = 0; stack16Top->ds = stack16Top->es = pModule->self_loading_sel; diff --git a/loader/resource.c b/loader/resource.c index a569850298b..6e4ac03a849 100644 --- a/loader/resource.c +++ b/loader/resource.c @@ -626,7 +626,7 @@ LoadString32A(HINSTANCE32 instance,UINT32 resource_id,LPSTR buffer,int buflen) if (buffer) buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 ); retval = LoadString32W(instance,resource_id,buffer2,buflen); - if (buffer) + if (buffer2) { lstrcpynWtoA( buffer, buffer2, buflen ); HeapFree( GetProcessHeap(), 0, buffer2 ); diff --git a/loader/signal.c b/loader/signal.c index 43aae82086a..1257e330517 100644 --- a/loader/signal.c +++ b/loader/signal.c @@ -1,4 +1,8 @@ -#ifndef WINELIB +/* + * Wine signal handling + * + */ + #include #include #include @@ -21,198 +25,110 @@ #include #endif -#include "debugger.h" -#include "options.h" -#include "sigcontext.h" -#include "win.h" +#include "miscemu.h" #include "winsock.h" -#if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__) -char * cstack[4096]; -#endif -#ifdef linux -extern void ___sig_restore(); -extern void ___masksig_restore(); +/* Linux sigaction function */ +#if defined(linux) && defined(__i386__) /* This is the sigaction structure from the Linux 2.1.20 kernel. */ - -struct kernel_sigaction { - __sighandler_t sa_handler; - unsigned long sa_mask; - unsigned long sa_flags; - void (*sa_restorer) __P ((void)); +struct kernel_sigaction +{ + void (*sa_handler)(); + unsigned long sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(); }; /* Similar to the sigaction function in libc, except it leaves alone the - restorer field */ - -static int -wine_sigaction(int sig,struct kernel_sigaction * new, - struct kernel_sigaction * old) + restorer field, which is used to specify the signal stack address */ +static __inline__ int wine_sigaction( int sig, struct kernel_sigaction *new, + struct kernel_sigaction *old ) { - __asm__("int $0x80":"=a" (sig) - :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old)); - if (sig>=0) - return 0; - errno = -sig; - return -1; + __asm__ __volatile__( "int $0x80" + : "=a" (sig) + : "0" (SYS_sigaction), + "b" (sig), + "c" (new), + "d" (old) ); + if (sig>=0) + return 0; + errno = -sig; + return -1; } -#endif /* linux */ +#endif /* linux && __i386__ */ -#ifdef linux -#define HANDLER_DEF(name) void name (int signal, SIGCONTEXT context_struct) -#define HANDLER_PROLOG SIGCONTEXT *context = &context_struct; (void)context; { -#define HANDLER_EPILOG } -#elif defined(__svr4__) || defined(_SCO_DS) -#define HANDLER_DEF(name) void name (int signal, void *siginfo, SIGCONTEXT *context) -#define HANDLER_PROLOG /* nothing */ -#define HANDLER_EPILOG /* nothing */ +/* Signal stack */ + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +# define SIGNAL_STACK_SIZE MINSIGSTKSZ +#elif defined (__svr4__) || defined(_SCO_DS) +# define SIGNAL_STACK_SIZE SIGSTKSZ #else -#define HANDLER_DEF(name) void name (int signal, int code, SIGCONTEXT *context) -#define HANDLER_PROLOG /* nothing */ -#define HANDLER_EPILOG /* nothing */ +# define SIGNAL_STACK_SIZE 4096 #endif -extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context ); +static char SIGNAL_Stack[SIGNAL_STACK_SIZE]; -/********************************************************************** - * wine_timer - * - * SIGALRM handler. - */ -static -HANDLER_DEF(wine_timer) -{ - HANDLER_PROLOG; - /* Should do real-time timers here */ - DOSMEM_Tick(); - HANDLER_EPILOG; -} - -/********************************************************************** - * SIGNAL_break - * - * Handle Ctrl-C and such - */ -static -HANDLER_DEF(SIGNAL_break) -{ - HANDLER_PROLOG; - if (Options.debug) wine_debug( signal, context ); /* Enter our debugger */ - exit(0); - HANDLER_EPILOG; -} /********************************************************************** * SIGNAL_child * * wait4 terminated child processes */ -static -HANDLER_DEF(SIGNAL_child) +static void SIGNAL_child(void) { - HANDLER_PROLOG; #ifdef HAVE_WAIT4 - wait4( 0, NULL, WNOHANG, NULL); + wait4( 0, NULL, WNOHANG, NULL); #elif defined (HAVE_WAITPID) - /* I am sort-of guessing that this is the same as the wait4 call. */ - waitpid (0, NULL, WNOHANG); + /* I am sort-of guessing that this is the same as the wait4 call. */ + waitpid (0, NULL, WNOHANG); #else - wait(NULL); + wait(NULL); #endif - HANDLER_EPILOG; -} - - -/********************************************************************** - * SIGNAL_trap - * - * SIGTRAP handler. - */ -static -HANDLER_DEF(SIGNAL_trap) -{ - HANDLER_PROLOG; - wine_debug( signal, context ); /* Enter our debugger */ - HANDLER_EPILOG; -} - - -/********************************************************************** - * SIGNAL_fault - * - * Segfault handler. - */ -static -HANDLER_DEF(SIGNAL_fault) -{ - HANDLER_PROLOG; - if (CS_sig(context) == WINE_CODE_SELECTOR) - { - fprintf( stderr, "Segmentation fault in Wine program (%04x:%08lx)." - " Please debug.\n", - (unsigned short) CS_sig(context), EIP_sig(context)); - } - else - { - if (INSTR_EmulateInstruction( context )) return; - fprintf( stderr, "Segmentation fault in Windows program %04x:%08lx.\n", - (unsigned short) CS_sig(context), EIP_sig(context) ); - } - wine_debug( signal, context ); - HANDLER_EPILOG; } /********************************************************************** * SIGNAL_SetHandler */ -static void SIGNAL_SetHandler( int sig, void (*func)(), int flags ) +void SIGNAL_SetHandler( int sig, void (*func)(), int flags ) { int ret; -#ifdef linux +#if defined(linux) && defined(__i386__) + struct kernel_sigaction sig_act; sig_act.sa_handler = func; sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0; /* Point to the top of the stack, minus 4 just in case, and make it aligned */ sig_act.sa_restorer = - (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3); + (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3); ret = wine_sigaction( sig, &sig_act, NULL ); -#endif /* linux */ -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#else /* linux && __i386__ */ + struct sigaction sig_act; sigset_t sig_mask; sigemptyset(&sig_mask); sig_act.sa_handler = func; + sig_act.sa_mask = sig_mask; + +# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) sig_act.sa_flags = SA_ONSTACK; - sig_act.sa_mask = sig_mask; - ret = sigaction( sig, &sig_act, NULL ); -#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */ - -#if defined (__svr4__) || defined(_SCO_DS) - struct sigaction sig_act; - sigset_t sig_mask; - sigemptyset(&sig_mask); - sig_act.sa_handler = func; +# elif defined (__svr4__) || defined(_SCO_DS) sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; - sig_act.sa_mask = sig_mask; - ret = sigaction( sig, &sig_act, NULL ); -#endif /* __svr4__ || _SCO_DS */ - -#if defined(__EMX__) - struct sigaction sig_act; - sigset_t sig_mask; - sigemptyset(&sig_mask); - sig_act.sa_handler = func; +# elif defined(__EMX__) sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */ - sig_act.sa_mask = sig_mask; +# else + sig_act.sa_flags = 0; +# endif ret = sigaction( sig, &sig_act, NULL ); -#endif /* __EMX__ */ + +#endif /* linux && __i386__ */ if (ret < 0) { @@ -230,80 +146,29 @@ extern void WINSOCK_sigio(int a); */ BOOL32 SIGNAL_Init(void) { -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__svr4__) || defined(_SCO_DS) struct sigaltstack ss; - - if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) { - fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n", - MINSIGSTKSZ); - return FALSE; - } - ss.ss_size = MINSIGSTKSZ; + ss.ss_sp = SIGNAL_Stack; + ss.ss_size = sizeof(SIGNAL_Stack); ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) { + if (sigaltstack(&ss, NULL) < 0) + { perror("sigstack"); return FALSE; } -#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */ - -#if defined (__svr4__) || defined(_SCO_DS) - struct sigaltstack ss; - - if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) { - fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n", - SIGSTKSZ); - return FALSE; - } - ss.ss_size = SIGSTKSZ; - ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) { - perror("sigstack"); - return FALSE; - } -#endif /* __svr4__ || _SCO_DS */ +#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __svr4__ || _SCO_DS */ - SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1); - SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1); SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1); - SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1); - SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1); - SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1); - SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */ - SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break */ -#ifdef SIGBUS - SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1); -#endif #ifdef CONFIG_IPC SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */ #endif -#ifndef __EMX__ /* FIXME */ +#ifdef SIGIO SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0); #endif return TRUE; } -/********************************************************************** - * SIGNAL_StartBIOSTimer - * - * Start the BIOS tick timer. - */ -void SIGNAL_StartBIOSTimer(void) -{ -#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */ - struct itimerval vt_timer; - static int timer_started = 0; - - if (timer_started) return; - timer_started = 1; - vt_timer.it_interval.tv_sec = 0; - vt_timer.it_interval.tv_usec = 54929; - vt_timer.it_value = vt_timer.it_interval; - - setitimer(ITIMER_REAL, &vt_timer, NULL); -#endif -} - /********************************************************************** * SIGNAL_MaskAsyncEvents */ @@ -311,7 +176,7 @@ void SIGNAL_MaskAsyncEvents( BOOL32 flag ) { sigset_t set; sigemptyset(&set); -#ifndef __EMX__ /* FIXME */ +#ifdef SIGIO sigaddset(&set, SIGIO); #endif sigaddset(&set, SIGUSR1); @@ -320,5 +185,3 @@ void SIGNAL_MaskAsyncEvents( BOOL32 flag ) #endif sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL); } - -#endif /* ifndef WINELIB */ diff --git a/loader/task.c b/loader/task.c index 93756c8c150..4094ee9381a 100644 --- a/loader/task.c +++ b/loader/task.c @@ -578,9 +578,9 @@ HTASK16 TASK_CreateTask( HMODULE16 hModule, HINSTANCE16 hInstance, /* Create the 16-bit stack frame */ - pTask->ss_sp = MAKELONG( ((pModule->sp != 0) ? pModule->sp : - pSegTable[pModule->ss-1].minsize + pModule->stack_size) & ~1, - hInstance ); + pTask->ss_sp = PTR_SEG_OFF_TO_SEGPTR( hInstance, + ((pModule->sp != 0) ? pModule->sp : + pSegTable[pModule->ss-1].minsize + pModule->stack_size) & ~1 ); stack16Top = (char *)PTR_SEG_TO_LIN( pTask->ss_sp ); frame16 = (STACK16FRAME *)stack16Top - 1; frame16->saved_ss_sp = 0; @@ -1159,8 +1159,8 @@ void SwitchStackTo( WORD seg, WORD ptr, WORD top ) /* Switch to the new stack */ - IF1632_Saved16_ss_sp = pTask->ss_sp = MAKELONG( ptr - sizeof(STACK16FRAME), - seg ); + IF1632_Saved16_ss_sp = pTask->ss_sp = PTR_SEG_OFF_TO_SEGPTR( seg, + ptr - sizeof(STACK16FRAME) ); newFrame = CURRENT_STACK16; /* Copy the stack frame and the local variables to the new stack */ @@ -1216,23 +1216,19 @@ void SwitchStackBack(void) /*********************************************************************** * GetTaskQueueDS (KERNEL.118) */ -#ifndef WINELIB void GetTaskQueueDS( CONTEXT *context ) { DS_reg(context) = GlobalHandleToSel( GetTaskQueue(0) ); } -#endif /* WINELIB */ /*********************************************************************** * GetTaskQueueES (KERNEL.119) */ -#ifndef WINELIB void GetTaskQueueES( CONTEXT *context ) { ES_reg(context) = GlobalHandleToSel( GetTaskQueue(0) ); } -#endif /* WINELIB */ /*********************************************************************** diff --git a/memory/ldt.c b/memory/ldt.c index fce33af8dd3..de1cad0a5df 100644 --- a/memory/ldt.c +++ b/memory/ldt.c @@ -13,8 +13,10 @@ #include "stddebug.h" #include "debug.h" +#ifdef __i386__ + #ifdef linux -#include +#include struct modify_ldt_s { @@ -28,8 +30,21 @@ struct modify_ldt_s unsigned int seg_not_present : 1; }; -static __inline__ _syscall3(int, modify_ldt, int, func, void *, ptr, - unsigned long, bytecount); +static __inline__ int modify_ldt( int func, struct modify_ldt_s *ptr, + unsigned long count ) +{ + int res; + __asm__ __volatile__("int $0x80" + : "=a" (res) + : "0" (SYS_modify_ldt), + "b" (func), + "c" (ptr), + "d" (count) ); + if (res >= 0) return res; + errno = -res; + return -1; +} + #endif /* linux */ #if defined(__svr4__) || defined(_SCO_DS) @@ -44,6 +59,8 @@ extern int i386_get_ldt(int, union descriptor *, int); extern int i386_set_ldt(int, union descriptor *, int); #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ +#endif /* __i386__ */ + ldt_copy_entry ldt_copy[LDT_SIZE]; unsigned char ldt_flags_copy[LDT_SIZE]; @@ -129,6 +146,8 @@ int LDT_SetEntry( int entry, const ldt_entry *content ) /* Entry 0 must not be modified; its base and limit are always 0 */ if (!entry) return 0; +#ifdef __i386__ + #ifdef linux if (!__winelib) { @@ -189,6 +208,7 @@ int LDT_SetEntry( int entry, const ldt_entry *content ) } } #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ + #if defined(__svr4__) || defined(_SCO_DS) if (!__winelib) { @@ -217,6 +237,8 @@ int LDT_SetEntry( int entry, const ldt_entry *content ) } #endif +#endif /* __i386__ */ + if (ret < 0) return ret; ldt_copy[entry].base = content->base; if (!content->limit_in_pages) ldt_copy[entry].limit = content->limit; diff --git a/memory/local.c b/memory/local.c index 3baea5d221d..e54c03a90e5 100644 --- a/memory/local.c +++ b/memory/local.c @@ -159,7 +159,7 @@ static void LOCAL_MakeBlockFree( char *baseptr, WORD block ) next = pNext->next; } - dprintf_local( stddeb, "Local_AddFreeBlock %04x, next %04x\n", block, next ); + dprintf_local( stddeb, "Local_MakeBlockFree %04x, next %04x\n", block, next ); /* Insert the free block in the free-list */ pArena->free_prev = pNext->free_prev; diff --git a/misc/comm.c b/misc/comm.c index 36d3f7e1628..d119200ee39 100644 --- a/misc/comm.c +++ b/misc/comm.c @@ -407,7 +407,7 @@ INT16 OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue) port = device[3] - '0'; if (port-- == 0) { - fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n"); + fprintf(stderr, "comm: BUG ! COM0 doesn't exist !\n"); commerror = IE_BADID; } @@ -738,18 +738,27 @@ INT16 GetCommError(INT16 fd,LPCOMSTAT lpStat) unsigned long cnt; int rc; - lpStat->status = 0; + if (lpStat) { + lpStat->status = 0; - rc = ioctl(fd, TIOCOUTQ, &cnt); - lpStat->cbOutQue = cnt; + rc = ioctl(fd, TIOCOUTQ, &cnt); + if (rc) fprintf(stderr, "Error !\n"); + lpStat->cbOutQue = cnt; - rc = ioctl(fd, TIOCINQ, &cnt); - lpStat->cbInQue = cnt; + rc = ioctl(fd, TIOCINQ, &cnt); + if (rc) fprintf(stderr, "Error !\n"); + lpStat->cbInQue = cnt; + + dprintf_comm(stddeb, + "GetCommError: fd %d, error %d, lpStat %d %d %d\n", + fd, commerror, + lpStat->status, lpStat->cbInQue, lpStat->cbOutQue); + } + else + dprintf_comm(stddeb, + "GetCommError: fd %d, error %d, lpStat NULL\n", + fd, commerror); - dprintf_comm(stddeb, - "GetCommError: fd %d, error %d, lpStat %d %d %d\n", - fd, commerror, - lpStat->status, lpStat->cbInQue, lpStat->cbOutQue); /* * [RER] I have no idea what the following is trying to accomplish. * [RER] It is certainly not what the reference manual suggests. @@ -1652,7 +1661,7 @@ INT16 WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite) * GetCommTimeouts (KERNEL32.160) */ BOOL32 GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) { - dprintf_comm(stddeb,"GetCommTimeouts(%x,%p), empty stub.\n", + fprintf(stderr,"GetCommTimeouts(%x,%p), empty stub.\n", fd,lptimeouts ); return TRUE; @@ -1662,8 +1671,19 @@ BOOL32 GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) { * SetCommTimeouts (KERNEL32.453) */ BOOL32 SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) { - dprintf_comm(stddeb,"SetCommTimeouts(%x,%p), empty stub.\n", + fprintf(stderr,"SetCommTimeouts(%x,%p), empty stub.\n", fd,lptimeouts ); return TRUE; } + +/*********************************************************************** + * EnableCommNotification (USER.246) + */ +BOOL16 EnableCommNotification( INT16 fd, HWND16 hwnd, INT16 cbWriteNotify, + INT16 cbOutQueue ) +{ + fprintf(stderr, "EnableCommNotification(%d, %x, %d, %d), empty stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue); + return TRUE; +} + diff --git a/misc/compobj.c b/misc/compobj.c index c7c76a2568c..45decf8c455 100644 --- a/misc/compobj.c +++ b/misc/compobj.c @@ -7,10 +7,14 @@ /* At the moment, these are only empty stubs. */ +#include +#include +#include #include "ole.h" #include "ole2.h" #include "stddebug.h" #include "debug.h" +#include "compobj.h" DWORD currentMalloc=0; @@ -66,3 +70,109 @@ OLESTATUS CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) dprintf_ole(stdnimp,"CoDisconnectObject:%p %lx\n",lpUnk,reserved); return OLE_OK; } + +/*********************************************************************** + * CLSIDFromString [COMPOBJ.20] + */ + +/* Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6] */ + +OLESTATUS +CLSIDFromString(const LPCSTR idstr, CLSID *id) +{ + BYTE *s = (BYTE *) idstr; + BYTE *p; + int i; + BYTE table[256]; + + dprintf_ole(stddeb,"ClsIDFromString() %s -> %p\n", idstr, id); + + /* quick lookup table */ + memset(table, 0, 256); + + for (i = 0; i < 10; i++) { + table['0' + i] = i; + } + for (i = 0; i < 6; i++) { + table['A' + i] = i+10; + table['a' + i] = i+10; + } + + /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ + + if (strlen(idstr) != 38) + return OLE_ERROR_OBJECT; + + p = (BYTE *) id; + + s++; /* skip leading brace */ + for (i = 0; i < 4; i++) { + p[3 - i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 4; + s++; /* skip - */ + + for (i = 0; i < 2; i++) { + p[1-i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 2; + s++; /* skip - */ + + for (i = 0; i < 2; i++) { + p[1-i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 2; + s++; /* skip - */ + + /* these are just sequential bytes */ + for (i = 0; i < 2; i++) { + *p++ = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + s++; /* skip - */ + + for (i = 0; i < 6; i++) { + *p++ = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + + return OLE_OK; +} + +/*********************************************************************** + * CLSIDFromString [COMPOBJ.19] + */ + +OLESTATUS +StringFromCLSID(const CLSID *id, LPSTR idstr) +{ + static const char *hex = "0123456789ABCDEF"; + char *s; + int i; + + sprintf(idstr, "{%08lx-%04x-%04x-%2x%2x-", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1]); + s = &idstr[25]; + + /* 6 hex bytes */ + for (i = 2; i < 8; i++) { + *s++ = hex[id->Data4[i]>>4]; + *s++ = hex[id->Data4[i] & 0xf]; + } + + *s++ = '}'; + *s++ = '\0'; + + for (i = strlen(idstr)-1; i >= 0; i--) { + idstr[i] = toupper(idstr[i]); + } + + dprintf_ole(stddeb,"StringFromClsID: %p->%s\n", id, idstr); + + return OLE_OK; +} + diff --git a/misc/registry.c b/misc/registry.c index 2719bd3dc3d..791e5db9bc6 100644 --- a/misc/registry.c +++ b/misc/registry.c @@ -26,8 +26,6 @@ #include "xmalloc.h" #include "winreg.h" -#define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y)) - /* FIXME: following defines should be configured global ... */ /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */ @@ -275,6 +273,7 @@ SHELL_StartupRegistry() { RegCreateKey16(HKEY_DYN_DATA,"\\PerfStats\\StatData",&xhkey); RegCloseKey(xhkey); + xhkey = 0; RegCreateKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey); #ifdef linux F=fopen("/proc/cpuinfo","r"); @@ -392,7 +391,7 @@ _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) { if (escapeeq && *s=='=') doescape = 1; if (*s=='\\') - fputc(*s,F); /* if \\ than put it twice. */ + fputc(*s,F); /* if \\ then put it twice. */ if (doescape) fprintf(F,"\\u%04x",*((unsigned short*)s)); else @@ -3000,7 +2999,7 @@ DWORD RegQueryInfoKey32A( lpcbSecurityDescriptor, ft ); - if (ret==ERROR_SUCCESS) + if (ret==ERROR_SUCCESS && lpszClass) lstrcpyWtoA(lpszClass,lpszClassW); if (lpcchClass) *lpcchClass/=2; diff --git a/misc/system.c b/misc/system.c index aaeeae55b1c..dee79bd0363 100644 --- a/misc/system.c +++ b/misc/system.c @@ -5,29 +5,187 @@ */ #include +#include +#include +#include +#include +#include +#include +#include + #include "windows.h" +#include "miscemu.h" + +typedef struct +{ + FARPROC16 callback; /* NULL if not in use */ + INT32 rate; + INT32 ticks; +} SYSTEM_TIMER; + +#define NB_SYS_TIMERS 8 +#define SYS_TIMER_RATE 54925 + +static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS]; +static int SYS_NbTimers = 0; +static BOOL32 SYS_TimersDisabled = FALSE; + +/*********************************************************************** + * SYSTEM_TimerTick + */ +static void SYSTEM_TimerTick(void) +{ + int i; + + for (i = 0; i < NB_SYS_TIMERS; i++) + { + if (!SYS_Timers[i].callback) continue; + if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0) + { + SYS_Timers[i].ticks += SYS_Timers[i].rate; + SYS_Timers[i].callback(); + } + } +} + + +/********************************************************************** + * SYSTEM_StartTicks + * + * Start the system tick timer. + */ +static void SYSTEM_StartTicks(void) +{ + static BOOL32 handler_installed = FALSE; + + if (!handler_installed) + { + handler_installed = TRUE; + SIGNAL_SetHandler( SIGALRM, SYSTEM_TimerTick, 1 ); + } +#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */ + { + struct itimerval vt_timer; + + vt_timer.it_interval.tv_sec = 0; + vt_timer.it_interval.tv_usec = 54929; + vt_timer.it_value = vt_timer.it_interval; + setitimer( ITIMER_REAL, &vt_timer, NULL ); + } +#endif +} + + +/********************************************************************** + * SYSTEM_StopTicks + * + * Stop the system tick timer. + */ +static void SYSTEM_StopTicks(void) +{ +#ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */ + struct itimerval vt_timer; + + vt_timer.it_interval.tv_sec = 0; + vt_timer.it_interval.tv_usec = 0; + vt_timer.it_value = vt_timer.it_interval; + setitimer( ITIMER_REAL, &vt_timer, NULL ); +#endif +} /*********************************************************************** * InquireSystem (SYSTEM.1) - */ -DWORD InquireSystem( WORD code, WORD drive, BOOL16 enable ) + * + * Note: the function always takes 2 WORD arguments, contrary to what + * "Undocumented Windows" says. + */ +DWORD InquireSystem( WORD code, WORD arg ) { WORD drivetype; switch(code) { case 0: /* Get timer resolution */ - return 54925; + return SYS_TIMER_RATE; case 1: /* Get drive type */ - drivetype = GetDriveType16( drive ); + drivetype = GetDriveType16( arg ); return MAKELONG( drivetype, drivetype ); case 2: /* Enable one-drive logic */ - fprintf( stderr, "InquireSystem(2): set single-drive %d not supported\n", enable ); + fprintf( stderr, "InquireSystem(2): set single-drive %d not supported\n", arg ); return 0; } fprintf( stderr, "InquireSystem: unknown code %d\n", code ); return 0; } + + +/*********************************************************************** + * CreateSystemTimer (SYSTEM.2) + */ +WORD CreateSystemTimer( WORD rate, FARPROC16 callback ) +{ + int i; + + for (i = 0; i < NB_SYS_TIMERS; i++) + if (!SYS_Timers[i].callback) /* Found one */ + { + SYS_Timers[i].rate = (UINT32)rate * 1000; + if (SYS_Timers[i].rate < SYS_TIMER_RATE) + SYS_Timers[i].rate = SYS_TIMER_RATE; + SYS_Timers[i].ticks = SYS_Timers[i].rate; + SYS_Timers[i].callback = callback; + if ((++SYS_NbTimers == 1) && !SYS_TimersDisabled) + SYSTEM_StartTicks(); + return i + 1; /* 0 means error */ + } + return 0; +} + + +/*********************************************************************** + * KillSystemTimer (SYSTEM.3) + * + * Note: do not confuse this function with USER.182 + */ +WORD SYSTEM_KillSystemTimer( WORD timer ) +{ + if (!timer || (timer > NB_SYS_TIMERS)) return timer; /* Error */ + SYS_Timers[timer-1].callback = NULL; + if ((!--SYS_NbTimers) && !SYS_TimersDisabled) SYSTEM_StopTicks(); + return 0; +} + + +/*********************************************************************** + * EnableSystemTimers (SYSTEM.4) + */ +void EnableSystemTimers(void) +{ + SYS_TimersDisabled = FALSE; + if (SYS_NbTimers) SYSTEM_StartTicks(); +} + + +/*********************************************************************** + * DisableSystemTimers (SYSTEM.5) + */ +void DisableSystemTimers(void) +{ + SYS_TimersDisabled = TRUE; + if (SYS_NbTimers) SYSTEM_StopTicks(); +} + + +/*********************************************************************** + * SYSTEM_GetTimerProc + * + * Return the timer proc of a system timer. Used by thunking code. + */ +FARPROC16 SYSTEM_GetTimerProc( WORD timer ) +{ + if (!timer || (timer > NB_SYS_TIMERS)) return NULL; + return SYS_Timers[timer-1].callback; +} diff --git a/misc/tweak.c b/misc/tweak.c index a9118d5c39c..e8f0095371a 100644 --- a/misc/tweak.c +++ b/misc/tweak.c @@ -410,16 +410,19 @@ void TWEAK_DrawReliefRect95( /****************************************************************************** * - * void TWEAK_DrawMenuSeparator95( + * void TWEAK_DrawRevReliefRect95( * HDC32 hdc, // Device context on which to draw - * UINT32 xc1, // Left x-coordinate - * UINT32 yc, // Y-coordinate of the LOWER line - * UINT32 xc2 ) // Right x-coordinate + * RECT32 const *rect ) // Rectangle to use * - * Draws the menu separator bar Win 95 style. + * Draws the double-bordered Win95-style relief rectangle. * * Bugs - * Same as those for DrawReliefRect95. + * There are some checks missing from this function. Perhaps the + * SelectObject32 calls should be examined? Hasn't failed on me (yet). + * + * Should I really be calling X functions directly from here? It is + * an optimization, but should I be optimizing alpha code? Probably + * not. * * Revision history * 08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu) @@ -427,7 +430,76 @@ void TWEAK_DrawReliefRect95( * *****************************************************************************/ -void TWEAK_DrawMenuSeparator95( +void TWEAK_DrawRevReliefRect95( + HDC32 hdc, + RECT32 const *rect ) +{ + DC *dc; + HPEN32 prevpen; + + if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) { + + /* Draw the top/left lines first */ + prevpen = SelectObject32(hdc, TWEAK_Pen8095); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top, + rect->right - 1, rect->top); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, rect->top, + rect->left, rect->bottom - 1); + + SelectObject32(hdc, TWEAK_Pen0095); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1, + rect->top + 1, rect->right - 2, rect->top + 1); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1, + rect->top + 1, rect->left + 1, rect->bottom - 2); + + + /* Now the bottom/right lines */ + SelectObject32(hdc, TWEAK_PenFF95); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left, + rect->bottom - 1, rect->right - 1, rect->bottom - 1); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 1, + rect->top, rect->right - 1, rect->bottom - 1); + + SelectObject32(hdc, TWEAK_PenE095); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->left + 1, + rect->bottom - 2, rect->right - 2, rect->bottom - 2); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, rect->right - 2, + rect->top + 1, rect->right - 2, rect->bottom - 2); + + SelectObject32(hdc, prevpen); + } + + return; +} + + + +/****************************************************************************** + * + * void TWEAK_DrawMenuSeparatorHoriz95( + * HDC32 hdc, // Device context on which to draw + * UINT32 xc1, // Left x-coordinate + * UINT32 yc, // Y-coordinate of the LOWER line + * UINT32 xc2 ) // Right x-coordinate + * + * Draws a horizontal menu separator bar Win 95 style. + * + * Bugs + * Same as those for DrawReliefRect95. + * + * Revision history + * 08-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu) + * Original implementation. + * 11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu) + * Changed name from DrawMenuSeparator95 + * + *****************************************************************************/ + +void TWEAK_DrawMenuSeparatorHoriz95( HDC32 hdc, UINT32 xc1, UINT32 yc, @@ -454,3 +526,52 @@ void TWEAK_DrawMenuSeparator95( return; } + + +/****************************************************************************** + * + * void TWEAK_DrawMenuSeparatorVert95( + * HDC32 hdc, // Device context on which to draw + * UINT32 xc, // X-coordinate of the RIGHT line + * UINT32 yc1, // top Y-coordinate + * UINT32 yc2 ) // bottom Y-coordinate + * + * Draws a vertical menu separator bar Win 95 style. + * + * Bugs + * Same as those for DrawReliefRect95. + * + * Revision history + * 11-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu) + * Original implementation. + * + *****************************************************************************/ + +void TWEAK_DrawMenuSeparatorVert95( + HDC32 hdc, + UINT32 xc, + UINT32 yc1, + UINT32 yc2 ) +{ + DC *dc; + HPEN32 prevpen; + + if((dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC))) { + + /* Draw the top line */ + prevpen = SelectObject32(hdc, TWEAK_Pen8095); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc, yc1, xc, + yc2); + + /* And the bottom line */ + SelectObject32(hdc, TWEAK_PenFF95); + DC_SetupGCForPen(dc); + XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, xc + 1, yc1, xc + 1, + yc2); + + SelectObject32(hdc, prevpen); + } + + return; +} diff --git a/misc/ver.c b/misc/ver.c index 51b9089f641..0a747bf75d6 100644 --- a/misc/ver.c +++ b/misc/ver.c @@ -983,15 +983,15 @@ struct db { /* in memory structure... */ char name[1]; /* padded to dword alignment */ /* .... - char data[datalen]; padded to dword alignemnt + char data[datalen]; padded to dword alignment BYTE subdirdata[]; until nextoff */ }; static BYTE* -_find_data(BYTE *block,LPCSTR str) { +_find_data(BYTE *block,LPCSTR str, WORD buff_remain) { char *nextslash; - int substrlen; + int substrlen, inc_size; struct db *db; while (*str && *str=='\\') @@ -1013,20 +1013,23 @@ _find_data(BYTE *block,LPCSTR str) { dprintf_ver(stddeb,"db=%p,db->nextoff=%d,db->datalen=%d,db->name=%s,db->data=%s\n", db,db->nextoff,db->datalen,db->name,(char*)((char*)db+4+((strlen(db->name)+4)&~3)) ); - if (!db->nextoff) + if ((!db->nextoff) || (!buff_remain)) /* no more entries ? */ return NULL; dprintf_ver(stddeb,"comparing with %s\n",db->name); if (!strncmp(db->name,str,substrlen)) { - if (nextslash) - return _find_data( - block+4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3) - ,nextslash - ); + if (nextslash) { + inc_size = 4+((strlen(db->name)+4)&~3)+((db->datalen+3)&~3); + + return _find_data( block+inc_size ,nextslash, + buff_remain - inc_size); + } else return block; } - block=block+((db->nextoff+3)&~3); + inc_size=((db->nextoff+3)&~3); + block=block+inc_size; + buff_remain=buff_remain-inc_size; } } @@ -1044,7 +1047,7 @@ VerQueryValue16(SEGPTR segblock,LPCSTR subblock,SEGPTR *buffer,UINT16 *buflen) ); s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock)+1); strcpy(s,"VS_VERSION_INFO\\");strcat(s,subblock); - b=_find_data(block,s); + b=_find_data(block, s, *(WORD *)block); if (b==NULL) { *buflen=0; return 0; @@ -1071,7 +1074,7 @@ VerQueryValue32A(LPVOID vblock,LPCSTR subblock,LPVOID *vbuffer,UINT32 *buflen) ); s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(subblock)+1); strcpy(s,"VS_VERSION_INFO\\");strcat(s,subblock); - b=_find_data(block,s); + b=_find_data(block, s, *(WORD *)block); if (b==NULL) { *buflen=0; return 0; @@ -1100,7 +1103,7 @@ VerQueryValue32W(LPVOID vblock,LPCWSTR subblock,LPVOID *vbuffer,UINT32 *buflen) sb = HEAP_strdupWtoA( GetProcessHeap(), 0, subblock ); s=(char*)xmalloc(strlen("VS_VERSION_INFO\\")+strlen(sb)+1); strcpy(s,"VS_VERSION_INFO\\");strcat(s,sb); - b=_find_data(block,s); + b=_find_data(block, s, *(WORD *)block); if (b==NULL) { *buflen=0; HeapFree( GetProcessHeap(), 0, sb ); diff --git a/misc/winsock.c b/misc/winsock.c index e4ecd51b503..159ed1c1c5e 100644 --- a/misc/winsock.c +++ b/misc/winsock.c @@ -42,6 +42,7 @@ #include "heap.h" #include "ldt.h" #include "winsock.h" +#include "miscemu.h" #include "stddebug.h" #include "debug.h" @@ -51,8 +52,6 @@ inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \ ntohs(((struct sockaddr_in *)a)->sin_port)) -extern void SIGNAL_MaskAsyncEvents( BOOL32 ); - #pragma pack(4) /* ----------------------------------- internal data */ diff --git a/misc/wsprintf.c b/misc/wsprintf.c index 4ca48280d9c..9cfbc57bbff 100644 --- a/misc/wsprintf.c +++ b/misc/wsprintf.c @@ -257,8 +257,15 @@ INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec, LPCVOID args ) else cur_arg = (DWORD)PTR_SEG_TO_LIN( *(SEGPTR *)args ); args = (SEGPTR *)args + 1; break; - case WPR_HEXA: case WPR_SIGNED: + if (!(format.flags & WPRINTF_LONG)) + { + cur_arg = (DWORD)(INT32)*(INT16 *)args; + args = (INT16 *)args + 1; + break; + } + /* fall through */ + case WPR_HEXA: case WPR_UNSIGNED: if (format.flags & WPRINTF_LONG) { diff --git a/miscemu/instr.c b/miscemu/instr.c index 0d50be60322..931cfe83cc7 100644 --- a/miscemu/instr.c +++ b/miscemu/instr.c @@ -28,10 +28,11 @@ static WORD INSTR_ReplaceSelector( SIGCONTEXT *context, WORD sel) { if (sel == 0x40) { - extern void SIGNAL_StartBIOSTimer(void); + static WORD sys_timer = 0; fprintf( stderr, "Direct access to segment 0x40 (cs:ip=%04x:%04lx).\n", CS_sig(context), EIP_sig(context) ); - SIGNAL_StartBIOSTimer(); + if (!sys_timer) + sys_timer = CreateSystemTimer( 55, (FARPROC16)DOSMEM_Tick ); return DOSMEM_BiosSeg; } return 0; /* Can't replace selector */ diff --git a/msdos/int21.c b/msdos/int21.c index d81368275bc..46b0004ed59 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -216,9 +216,11 @@ static void GetDrivePB( CONTEXT *context, int drive ) static void ioctlGetDeviceInfo( CONTEXT *context ) { + int curr_drive; dprintf_int (stddeb, "int21: ioctl (%d, GetDeviceInfo)\n", BX_reg(context)); - DX_reg(context) = 0x0942; + curr_drive = DRIVE_GetCurrentDrive(); + DX_reg(context) = 0x0140 + curr_drive + ((curr_drive > 1) ? 0x0800 : 0); /* no floppy */ /* bits 0-5 are current drive * bit 6 - file has NOT been written..FIXME: correct? * bit 8 - generate int24 if no diskspace on write/ read past end of file @@ -332,10 +334,11 @@ void OpenExistingFile( CONTEXT *context ) SET_CFLAG(context); } #if 0 - int handle; - int mode; - int lock; - + { + int handle; + int mode; + int lock; + switch (AX_reg(context) & 0x0070) { case 0x00: /* compatability mode */ @@ -385,7 +388,7 @@ void OpenExistingFile( CONTEXT *context ) if(result) { errno_to_doserr(); - AX_reg(context) = ExtendedError; + AX_reg(context) = DOS_ExtendedError; close(handle); SET_CFLAG(context); return; @@ -396,6 +399,7 @@ void OpenExistingFile( CONTEXT *context ) Error (0,0,0); AX_reg(context) = handle; RESET_CFLAG(context); + } #endif } diff --git a/msdos/ioports.c b/msdos/ioports.c index 4c9ebf942cd..166896311db 100644 --- a/msdos/ioports.c +++ b/msdos/ioports.c @@ -10,20 +10,15 @@ fix that, I guess. */ -#ifdef linux #include -#include -#include -#include -#include "options.h" -#endif - #include #include +#include #include +#include #include "windows.h" +#include "options.h" #include "stddebug.h" -/* #define DEBUG_INT */ #include "debug.h" static BYTE cmosaddress; @@ -40,9 +35,18 @@ static BYTE cmosimage[64] = 0x1b, 0x7b, 0x21, 0x00, 0x00, 0x00, 0x05, 0x5f }; -#ifdef linux -char do_direct_port_access = 0; -char port_permissions[0x10000]; +#if defined(linux) && defined(__i386__) +# define DIRECT_IO_ACCESS +#else +# undef DIRECT_IO_ACCESS +#endif /* linux && __i386__ */ + +#ifdef DIRECT_IO_ACCESS +static char do_direct_port_access = 0; +static char port_permissions[0x10000]; + +#define IO_READ 1 +#define IO_WRITE 2 #endif /********************************************************************** @@ -52,8 +56,8 @@ char port_permissions[0x10000]; /* set_IO_permissions(int val1, int val) * Helper function for IO_port_init */ -#ifdef linux -void set_IO_permissions(int val1, int val, char rw) +#ifdef DIRECT_IO_ACCESS +static void set_IO_permissions(int val1, int val, char rw) { int j; if (val1 != -1) { @@ -76,7 +80,7 @@ void set_IO_permissions(int val1, int val, char rw) * Helper function for IO_port_init */ -void do_IO_port_init_read_or_write(char* temp, char rw) +static void do_IO_port_init_read_or_write(char* temp, char rw) { int val, val1, i, len; if (!strcasecmp(temp, "all")) { @@ -126,32 +130,64 @@ void do_IO_port_init_read_or_write(char* temp, char rw) } } -#endif +static __inline__ BYTE inb( WORD port ) +{ + BYTE b; + __asm__ __volatile__( "inb %w1,%0" : "=a" (b) : "d" (port) ); + return b; +} + +static __inline__ WORD inw( WORD port ) +{ + WORD w; + __asm__ __volatile__( "inw %w1,%0" : "=a" (w) : "d" (port) ); + return w; +} + +static __inline__ DWORD inl( WORD port ) +{ + DWORD dw; + __asm__ __volatile__( "inl %w1,%0" : "=a" (dw) : "d" (port) ); + return dw; +} + +static __inline__ void outb( BYTE value, WORD port ) +{ + __asm__ __volatile__( "outb %b0,%w1" : : "a" (value), "d" (port) ); +} + +static __inline__ void outw( WORD value, WORD port ) +{ + __asm__ __volatile__( "outw %w0,%w1" : : "a" (value), "d" (port) ); +} + +static __inline__ void outl( DWORD value, WORD port ) +{ + __asm__ __volatile__( "outl %0,%w1" : : "a" (value), "d" (port) ); +} + +#endif /* DIRECT_IO_ACCESS */ void IO_port_init() { -#ifdef linux +#ifdef DIRECT_IO_ACCESS char temp[1024]; - memset(port_permissions, 0, sizeof(port_permissions)); - do_direct_port_access = 0; - /* Can we do that? */ if (!iopl(3)) { iopl(0); PROFILE_GetWineIniString( "ports", "read", "*", temp, sizeof(temp) ); - do_IO_port_init_read_or_write(temp, 1); + do_IO_port_init_read_or_write(temp, IO_READ); PROFILE_GetWineIniString( "ports", "write", "*", temp, sizeof(temp) ); - do_IO_port_init_read_or_write(temp, 2); + do_IO_port_init_read_or_write(temp, IO_WRITE); } - - -#endif +#endif /* DIRECT_IO_ACCESS */ } + /********************************************************************** * IO_inport */ @@ -160,43 +196,50 @@ DWORD IO_inport( int port, int count ) DWORD res = 0; BYTE b; -#ifdef linux - if (do_direct_port_access) iopl(3); +#ifdef DIRECT_IO_ACCESS + if (do_direct_port_access) + { + /* Make sure we have access to the whole range */ + int i; + for (i = 0; i < count; i++) + if (!(port_permissions[port+i] & IO_READ)) break; + if (i == count) + { + iopl(3); + switch(count) + { + case 1: res = inb( port ); break; + case 2: res = inw( port ); break; + case 4: res = inl( port ); break; + default: + fprintf( stderr, "IO_inport: invalid count %d\n", count); + } + iopl(0); + return res; + } + } #endif dprintf_int(stddeb, "IO: %d bytes from port 0x%02x ", count, port ); while (count-- > 0) { -#ifdef linux - if(port_permissions[port] & 1) { - b = inb(port); - } else -#endif - { - switch (port) - { - case 0x70: - b = cmosaddress; - break; - case 0x71: - b = cmosimage[cmosaddress & 0x3f]; - break; - default: - fprintf( stderr, - "Direct I/O read attempted " - "from port %x\n", port); - b = 0xff; - break; - } - } - - port++; - res = (res << 8) | b; + switch (port) + { + case 0x70: + b = cmosaddress; + break; + case 0x71: + b = cmosimage[cmosaddress & 0x3f]; + break; + default: + fprintf( stderr, "Direct I/O read attempted from port %x\n", port); + b = 0xff; + break; + } + port++; + res = (res << 8) | b; } -#ifdef linux - if (do_direct_port_access) iopl(0); -#endif dprintf_int(stddeb, "( 0x%lx )\n", res ); return res; } @@ -212,37 +255,47 @@ void IO_outport( int port, int count, DWORD value ) dprintf_int( stddeb, "IO: 0x%lx (%d bytes) to port 0x%02x\n", value, count, port ); -#ifdef linux - if (do_direct_port_access) iopl(3); +#ifdef DIRECT_IO_ACCESS + if (do_direct_port_access) + { + /* Make sure we have access to the whole range */ + int i; + for (i = 0; i < count; i++) + if (!(port_permissions[port+i] & IO_WRITE)) break; + if (i == count) + { + iopl(3); + switch(count) + { + case 1: outb( LOBYTE(value), port ); break; + case 2: outw( LOWORD(value), port ); break; + case 4: outl( value, port ); break; + default: + fprintf( stderr, "IO_outport: invalid count %d\n", count); + } + iopl(0); + return; + } + } #endif while (count-- > 0) { b = value & 0xff; value >>= 8; -#ifdef linux - if (port_permissions[port] & 2) { - outb(b, port); - } else -#endif - { - switch (port) - { - case 0x70: - cmosaddress = b & 0x7f; - break; - case 0x71: - cmosimage[cmosaddress & 0x3f] = b; - break; - default: - fprintf( stderr, "Direct I/O write attempted " - "to port %x\n", port ); - break; - } - } + switch (port) + { + case 0x70: + cmosaddress = b & 0x7f; + break; + case 0x71: + cmosimage[cmosaddress & 0x3f] = b; + break; + default: + fprintf( stderr, "Direct I/O write attempted " + "to port %x\n", port ); + break; + } port++; } -#ifdef linux - if (do_direct_port_access) iopl(0); -#endif } diff --git a/multimedia/joystick.c b/multimedia/joystick.c index 8bc7deb1e27..4e643e2cf72 100644 --- a/multimedia/joystick.c +++ b/multimedia/joystick.c @@ -1,7 +1,7 @@ /* - * MMSYTEM functions + * Joystick functions * - * Copyright 1993 Martin Ayotte + * Copyright 1997 Andreas Mohr */ #include @@ -18,13 +18,113 @@ #include "stddebug.h" #include "debug.h" +static int count_use[4] = {0, 0, 0, 0}; +static int dev_stat; +static int joy_nr_open = 0; +static BOOL16 JoyCaptured = FALSE; +static HWND16 CaptureWnd[2] = {0, 0}; +static int joy_dev[2] = {-1, -1}; +static JOYINFO JoyCapData[2]; +static unsigned int joy_threshold[2] = {0, 0}; + +struct js_status +{ + int buttons; + int x; + int y; +}; + + +/************************************************************************** + * JoyOpenDriver [internal] + */ +BOOL16 JoyOpenDriver(WORD wID) +{ + char dev_name[] = "/dev/jsx"; + + if (joy_dev[wID] >= 0) return TRUE; + dev_name[strlen(dev_name)-1]=(char) wID+0x30; + if ((joy_dev[wID] = open(dev_name, O_RDONLY)) >= 0) { + joy_nr_open++; + return TRUE; + } + else return FALSE; +} + +/************************************************************************** + * JoyCloseDriver [internal] + */ +void JoyCloseDriver(WORD wID) +{ + if (joy_dev[wID] >= 0) { + close(joy_dev[wID]); + joy_dev[wID] = -1; + joy_nr_open--; + } +} + +/************************************************************************** + * JoySendMessages [internal] + */ +void JoySendMessages(void) +{ + int joy; + struct js_status js; + + if (joy_nr_open) + for (joy=0; joy < 4; joy++) + if (joy_dev[joy] >= 0) { + if (count_use[joy] > 250) { + JoyCloseDriver(joy); + count_use[joy] = 0; + } + count_use[joy]++; + } + else return; + if (JoyCaptured == FALSE) return; + dprintf_mmsys(stddeb, "JoySendMessages()\n"); + for (joy=0; joy < 4; joy++) { + if (JoyOpenDriver(joy) == FALSE) continue; + dev_stat = read(joy_dev[joy], &js, sizeof(js)); + if (dev_stat == sizeof(js)) { + js.x = js.x*37; + js.y = js.y*37; + if ((JoyCapData[joy].wXpos != js.x) || (JoyCapData[joy].wYpos != js.y)) { + SendMessage32A(CaptureWnd[joy], MM_JOY1MOVE + joy, js.buttons, MAKELONG(js.x, js.y)); + JoyCapData[joy].wXpos = js.x; + JoyCapData[joy].wYpos = js.y; + } + if (JoyCapData[joy].wButtons != js.buttons) { + unsigned int ButtonChanged = (WORD)(JoyCapData[joy].wButtons ^ js.buttons)<<8; + if (JoyCapData[joy].wButtons < js.buttons) + SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONDOWN + joy, ButtonChanged, MAKELONG(js.x, js.y)); + else + if (JoyCapData[joy].wButtons > js.buttons) + SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONUP ++ joy, ButtonChanged, MAKELONG(js.x, js.y)); + JoyCapData[joy].wButtons = js.buttons; + } + } + } +} + /************************************************************************** * JoyGetNumDevs [MMSYSTEM.101] */ WORD JoyGetNumDevs(void) { - fprintf(stdnimp, "EMPTY STUB !!! JoyGetNumDevs();\n"); - return 0; +int joy; +WORD joy_cnt = 0; + + dprintf_mmsys(stddeb, "JoyGetNumDevs: "); + for (joy=0; joy<4; joy++) + if (JoyOpenDriver(joy) == TRUE) { + JoyCloseDriver(joy); + joy_cnt++; + } + dprintf_mmsys(stddeb, "returning %d\n", joy_cnt); + if (!joy_cnt) fprintf(stderr, "No joystick found - perhaps get joystick-0.8.0.tar.gz and load it as module or use Linux >= 2.1.45 to be able to use joysticks.\n"); + return joy_cnt; } /************************************************************************** @@ -32,8 +132,27 @@ WORD JoyGetNumDevs(void) */ WORD JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize) { - fprintf(stdnimp, "EMPTY STUB !!! JoyGetDevCaps(%04X, %p, %d);\n", - wID, lpCaps, wSize); + dprintf_mmsys(stderr, "JoyGetDevCaps(%04X, %p, %d);\n", + wID, lpCaps, wSize); + if (wSize != sizeof(*lpCaps)) return JOYERR_PARMS; /* FIXME: should we really return this error value ? */ + if (JoyOpenDriver(wID) == TRUE) { + lpCaps->wMid = MM_MICROSOFT; + lpCaps->wPid = MM_PC_JOYSTICK; + strcpy(lpCaps->szPname, "WineJoy\0"); /* joystick product name */ + lpCaps->wXmin = 0; /* FIXME */ + lpCaps->wXmax = 0xffff; + lpCaps->wYmin = 0; + lpCaps->wYmax = 0xffff; + lpCaps->wZmin = 0; + lpCaps->wZmax = 0xffff; + lpCaps->wNumButtons = 2; + lpCaps->wPeriodMin = 0; + lpCaps->wPeriodMax = 50; /* FIXME end */ + + JoyCloseDriver(wID); + return JOYERR_NOERROR; + } + else return MMSYSERR_NODRIVER; } @@ -42,8 +161,24 @@ WORD JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize) */ WORD JoyGetPos(WORD wID, LPJOYINFO lpInfo) { - fprintf(stdnimp, "EMPTY STUB !!! JoyGetPos(%04X, %p);\n", wID, lpInfo); - return MMSYSERR_NODRIVER; + struct js_status js; + + dprintf_mmsys(stderr, "JoyGetPos(%04X, %p):", wID, lpInfo); + if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER; + dev_stat = read(joy_dev[wID], &js, sizeof(js)); + if (dev_stat != sizeof(js)) { + JoyCloseDriver(wID); + return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */ + } + count_use[wID] = 0; + js.x = js.x*37; + js.y = js.y*37; + lpInfo->wXpos = js.x; /* FIXME: perhaps multiply it somehow ? */ + lpInfo->wYpos = js.y; + lpInfo->wZpos = 0; /* FIXME: Don't know what to do with this value as joystick driver doesn't provide a Z value */ + lpInfo->wButtons = js.buttons; + dprintf_mmsys(stderr, "x: %d, y: %d, buttons: %d\n", js.x, js.y, js.buttons); + return JOYERR_NOERROR; } /************************************************************************** @@ -51,8 +186,10 @@ WORD JoyGetPos(WORD wID, LPJOYINFO lpInfo) */ WORD JoyGetThreshold(WORD wID, LPWORD lpThreshold) { - fprintf(stdnimp, "EMPTY STUB !!! JoyGetThreshold(%04X, %p);\n", wID, lpThreshold); - return MMSYSERR_NODRIVER; + dprintf_mmsys(stderr, "JoyGetThreshold(%04X, %p);\n", wID, lpThreshold); + if (wID > 3) return JOYERR_PARMS; + *lpThreshold = joy_threshold[wID]; + return JOYERR_NOERROR; } /************************************************************************** @@ -60,8 +197,12 @@ WORD JoyGetThreshold(WORD wID, LPWORD lpThreshold) */ WORD JoyReleaseCapture(WORD wID) { - fprintf(stdnimp, "EMPTY STUB !!! JoyReleaseCapture(%04X);\n", wID); - return MMSYSERR_NODRIVER; + dprintf_mmsys(stderr, "JoyReleaseCapture(%04X);\n", wID); + JoyCaptured = FALSE; + JoyCloseDriver(wID); + joy_dev[wID] = -1; + CaptureWnd[wID] = 0; + return JOYERR_NOERROR; } /************************************************************************** @@ -69,9 +210,18 @@ WORD JoyReleaseCapture(WORD wID) */ WORD JoySetCapture(HWND16 hWnd, WORD wID, WORD wPeriod, BOOL16 bChanged) { - fprintf(stdnimp, "EMPTY STUB !!! JoySetCapture(%04X, %04X, %d, %d);\n", + + dprintf_mmsys(stderr, "JoySetCapture(%04X, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged); - return MMSYSERR_NODRIVER; + + if (!CaptureWnd[wID]) { + if (JoyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER; + JoyCaptured = TRUE; + CaptureWnd[wID] = hWnd; + return JOYERR_NOERROR; + } + else + return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ } /************************************************************************** @@ -79,8 +229,11 @@ WORD JoySetCapture(HWND16 hWnd, WORD wID, WORD wPeriod, BOOL16 bChanged) */ WORD JoySetThreshold(WORD wID, WORD wThreshold) { - fprintf(stdnimp, "EMPTY STUB !!! JoySetThreshold(%04X, %d);\n", wID, wThreshold); - return MMSYSERR_NODRIVER; + dprintf_mmsys(stderr, "JoySetThreshold(%04X, %d);\n", wID, wThreshold); + + if (wID > 3) return JOYERR_PARMS; + joy_threshold[wID] = wThreshold; + return JOYERR_NOERROR; } /************************************************************************** @@ -88,6 +241,6 @@ WORD JoySetThreshold(WORD wID, WORD wThreshold) */ WORD JoySetCalibration(WORD wID) { - fprintf(stdnimp, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID); - return MMSYSERR_NODRIVER; + fprintf(stderr, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID); + return JOYERR_NOCANDO; } diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c index 42eace9f91e..b4f6cf962ad 100644 --- a/multimedia/mmsystem.c +++ b/multimedia/mmsystem.c @@ -293,7 +293,8 @@ BOOL16 DriverCallback(DWORD dwCallBack, UINT16 uFlags, HANDLE16 hDev, return FALSE; case DCB_FUNCTION: dprintf_mmsys(stddeb, "DriverCallback() // CALLBACK_FUNCTION !\n"); - CallTo16_word_wwlll((FARPROC16)dwCallBack,hDev,wMsg,dwUser,dwParam1,dwParam2); + CallDriverCallback( (FARPROC16)dwCallBack, hDev, wMsg, + dwUser, dwParam1, dwParam2 ); break; } return TRUE; diff --git a/objects/color.c b/objects/color.c index 074359d90bb..7d5c0bdab88 100644 --- a/objects/color.c +++ b/objects/color.c @@ -194,7 +194,9 @@ static void COLOR_FillDefaultColors(void) int red, no_r, inc_r; int green, no_g, inc_g; int blue, no_b, inc_b; - + + if (cSpace.size <= NB_RESERVED_COLORS) + return; while (i*i*i < (cSpace.size - NB_RESERVED_COLORS)) i++; no_r = no_g = no_b = --i; if ((no_r * (no_g+1) * no_b) < (cSpace.size - NB_RESERVED_COLORS)) no_g++; @@ -623,13 +625,29 @@ BOOL32 COLOR_Init(void) case TrueColor: cSpace.flags |= COLOR_VIRTUAL; - case StaticColor: + case StaticColor: { + int *depths,nrofdepths; + /* FIXME: hack to detect XFree32 XF_VGA16 ... We just have + * depths 1 and 4 + */ + depths=XListDepths(display,DefaultScreen(display),&nrofdepths); + if ((nrofdepths==2) && ((depths[0]==4) || depths[1]==4)) { + cSpace.monoPlane = 1; + for( white = cSpace.size - 1; !(white & 1); white >>= 1 ) + cSpace.monoPlane++; + cSpace.flags = (white & mask) ? COLOR_WHITESET : 0; + cSpace.colorMap = DefaultColormapOfScreen( screen ); + XFree(depths); + break; + } + XFree(depths); cSpace.colorMap = DefaultColormapOfScreen( screen ); cSpace.flags |= COLOR_FIXED; COLOR_Computeshifts(visual->red_mask, &COLOR_Redshift, &COLOR_Redmax); COLOR_Computeshifts(visual->green_mask, &COLOR_Greenshift, &COLOR_Greenmax); COLOR_Computeshifts(visual->blue_mask, &COLOR_Blueshift, &COLOR_Bluemax); - break; + break; + } } dprintf_palette(stddeb," visual class %i (%i)\n", diff --git a/programs/progman/ChangeLog b/programs/progman/ChangeLog index 1a7c0726b1d..2d7bd4eba6d 100644 --- a/programs/progman/ChangeLog +++ b/programs/progman/ChangeLog @@ -1,3 +1,8 @@ +Mon Jul 28 18:28:14 1997 Peter Schlaile + + * [grpfile.c] + Added checksum calculation [UNTESTED!]. + Fri Jul 4 12:00:00 1997 Henrik Olsen * [Da.rc] (new) diff --git a/programs/progman/grpfile.c b/programs/progman/grpfile.c index 44f9f04f0bc..bb4a5e5feef 100644 --- a/programs/progman/grpfile.c +++ b/programs/progman/grpfile.c @@ -2,10 +2,12 @@ * Program Manager * * Copyright 1996 Ulrich Schmid + * 1997 Peter Schlaile */ #include "windows.h" #include "progman.h" +#include "mmsystem.h" #define MALLOCHUNK 1000 @@ -370,11 +372,11 @@ BOOL GRPFILE_WriteGroupFile(HLOCAL hGroup) } { - /* Warn about the incompatibility */ + /* Warn about the (possible) incompatibility */ CHAR msg[MAX_PATHNAME_LEN + 200]; wsprintf(msg, "Group files written by this DRAFT Program Manager " - "cannot be read by the Microsoft Program Manager!!\n" + "possibly cannot be read by the Microsoft Program Manager!!\n" "Are you sure to write %s?", szPath); if (IDOK != MessageBox(Globals.hMainWnd, msg, "WARNING", MB_OKCANCEL | MB_DEFBUTTON2)) return FALSE; @@ -425,6 +427,72 @@ static VOID GRPFILE_CalculateSizes(PROGRAM *program, *Icons += sizeXor; } +/***********************************************************************/ +UINT16 GRPFILE_checksum; +BOOL GRPFILE_checksum_half_word; +BYTE GRPFILE_checksum_last_byte; +/*********************************************************************** + * + * GRPFILE_InitChecksum + */ + +static void GRPFILE_InitChecksum() +{ + GRPFILE_checksum = 0; + GRPFILE_checksum_half_word = 0; +} + +/*********************************************************************** + * + * GRPFILE_GetChecksum + */ + +static UINT16 GRPFILE_GetChecksum() +{ + return GRPFILE_checksum; +} + +/*********************************************************************** + * + * GRPFILE_WriteWithChecksum + * + * Looks crazier than it is: + * + * chksum = 0; + * chksum = cksum - 1. word; + * chksum = cksum - 2. word; + * ... + * + * if (filelen is even) + * great I'm finished + * else + * ignore last byte + */ + +static UINT GRPFILE_WriteWithChecksum(HFILE file, LPCSTR str, UINT size) +{ + UINT i; + if (GRPFILE_checksum_half_word) { + GRPFILE_checksum -= GRPFILE_checksum_last_byte; + } + for (i=0; i < size; i++) { + if (GRPFILE_checksum_half_word) { + GRPFILE_checksum -= str[i] << 8; + } else { + GRPFILE_checksum -= str[i]; + } + GRPFILE_checksum_half_word ^= 1; + } + + if (GRPFILE_checksum_half_word) { + GRPFILE_checksum_last_byte = str[size-1]; + GRPFILE_checksum += GRPFILE_checksum_last_byte; + } + + return _lwrite(file, str, size); +} + + /*********************************************************************** * * GRPFILE_DoWriteGroupFile @@ -439,6 +507,10 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) BOOL need_extension; LPCSTR lpszTitle = LocalLock(group->hName); + UINT16 checksum; + + GRPFILE_InitChecksum(); + /* Calculate offsets */ NumProg = 0; Icons = 0; @@ -467,14 +539,10 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) /* Header */ buffer[0] = 'P'; buffer[1] = 'M'; -#if 0 - buffer[2] = 'C'; /* Original magic number */ + buffer[2] = 'C'; buffer[3] = 'C'; -#else - buffer[2] = 'X'; /* Modified magic number: no checksum */ - buffer[3] = 'X'; -#endif - PUT_SHORT(buffer, 4, 0); /* Checksum ignored */ + + PUT_SHORT(buffer, 4, 0); /* Checksum zero for now, written later */ PUT_SHORT(buffer, 6, Extension); /* Update group->nCmdShow */ if (IsIconic(group->hWnd)) nCmdShow = SW_SHOWMINIMIZED; @@ -494,7 +562,7 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 30, 0x0000); /* unknown */ PUT_SHORT(buffer, 32, NumProg); - if (HFILE_ERROR == _lwrite(file, buffer, 34)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 34)) return FALSE; /* Program table */ CurrProg = Progs; @@ -505,14 +573,16 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PROGRAM *program = LocalLock(hProgram); PUT_SHORT(buffer, 0, CurrProg); - if (HFILE_ERROR == _lwrite(file, buffer, 2)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 2)) + return FALSE; GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon); hProgram = program->hNext; } /* Title */ - if (HFILE_ERROR == _lwrite(file, lpszTitle, lstrlen(lpszTitle) + 1)) + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszTitle, + lstrlen(lpszTitle) + 1)) return FALSE; /* Program entries */ @@ -545,10 +615,10 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) ptr += lstrlen(CmdLine) + 1; PUT_SHORT(buffer, 22, ptr); - if (HFILE_ERROR == _lwrite(file, buffer, 24) || - HFILE_ERROR == _lwrite(file, Name, lstrlen(Name) + 1) || - HFILE_ERROR == _lwrite(file, CmdLine, lstrlen(CmdLine) + 1) || - HFILE_ERROR == _lwrite(file, IconFile, lstrlen(IconFile) + 1)) + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 24) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, Name, lstrlen(Name) + 1) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, CmdLine, lstrlen(CmdLine) + 1) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, IconFile, lstrlen(IconFile) + 1)) return FALSE; GRPFILE_CalculateSizes(program, &CurrProg, &CurrIcon); @@ -574,9 +644,9 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) buffer[10] = iconinfo->bPlanes; buffer[11] = iconinfo->bBitsPerPixel; - if (HFILE_ERROR == _lwrite(file, buffer, 12) || - HFILE_ERROR == _lwrite(file, AndBits, sizeAnd) || - HFILE_ERROR == _lwrite(file, XorBits, sizeXor)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 12) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, AndBits, sizeAnd) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, XorBits, sizeXor)) return FALSE; hProgram = program->hNext; } @@ -589,7 +659,8 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 4, 0x000a); buffer[6] = 'P', buffer[7] = 'M'; buffer[8] = 'C', buffer[9] = 'C'; - if (HFILE_ERROR == _lwrite(file, buffer, 10)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 10)) + return FALSE; seqnum = 0; hProgram = group->hPrograms; @@ -604,8 +675,8 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 0, 0x8101); PUT_SHORT(buffer, 2, seqnum); PUT_SHORT(buffer, 4, 7 + lstrlen(lpszWorkDir)); - if (HFILE_ERROR == _lwrite(file, buffer, 6) || - HFILE_ERROR == _lwrite(file, lpszWorkDir, lstrlen(lpszWorkDir) + 1)) + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6) || + HFILE_ERROR == GRPFILE_WriteWithChecksum(file, lpszWorkDir, lstrlen(lpszWorkDir) + 1)) return FALSE; } @@ -616,7 +687,7 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 2, seqnum); PUT_SHORT(buffer, 4, 8); PUT_SHORT(buffer, 6, program->nHotKey); - if (HFILE_ERROR == _lwrite(file, buffer, 8)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE; } /* Show command */ @@ -626,7 +697,7 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 2, seqnum); PUT_SHORT(buffer, 4, 8); PUT_SHORT(buffer, 6, program->nCmdShow); - if (HFILE_ERROR == _lwrite(file, buffer, 8)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 8)) return FALSE; } seqnum++; @@ -637,9 +708,14 @@ static BOOL GRPFILE_DoWriteGroupFile(HFILE file, GROUP *group) PUT_SHORT(buffer, 0, 0xffff); PUT_SHORT(buffer, 2, 0xffff); PUT_SHORT(buffer, 4, 0x0000); - if (HFILE_ERROR == _lwrite(file, buffer, 6)) return FALSE; + if (HFILE_ERROR == GRPFILE_WriteWithChecksum(file, buffer, 6)) return FALSE; } + checksum = GRPFILE_GetChecksum(); + _llseek(file, 4, SEEK_SET); + PUT_SHORT(buffer, 0, checksum); + _lwrite(file, buffer, 2); + return TRUE; } diff --git a/scheduler/process.c b/scheduler/process.c index 6e9db2929d9..05fa39dde7a 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -9,9 +9,11 @@ #include #include #include "process.h" +#include "module.h" #include "file.h" #include "heap.h" #include "task.h" +#include "ldt.h" #include "thread.h" #include "winerror.h" @@ -788,107 +790,6 @@ BOOL32 SetStdHandle( DWORD std_handle, HANDLE32 handle ) return FALSE; } -/*********************************************************************** - * _KERNEL32_18 (KERNEL32.18,Win95) - * 'Of course you cannot directly access Windows internal structures' - */ -extern THDB *pCurrentThread; -DWORD -_KERNEL32_18(DWORD processid,DWORD action) { - PDB32 *process; - TDB *pTask; - - action+=56; - fprintf(stderr,"_KERNEL32_18(%ld,%ld+0x38)\n",processid,action); - if (action>56) - return 0; - if (!processid) { - process=pCurrentProcess; - /* check if valid process */ - } else - process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */ - switch (action) { - case 0: /* return app compat flags */ - pTask = (TDB*)GlobalLock16(process->task); - if (!pTask) - return 0; - return pTask->compat_flags; - case 4: /* returns offset 0xb8 of process struct... dunno what it is */ - return 0; - case 8: /* return hinstance16 */ - pTask = (TDB*)GlobalLock16(process->task); - if (!pTask) - return 0; - return pTask->hInstance; - case 12:/* return expected windows version */ - pTask = (TDB*)GlobalLock16(process->task); - if (!pTask) - return 0; - return pTask->version; - case 16:/* return uncrypted pointer to current thread */ - return (DWORD)pCurrentThread; - case 20:/* return uncrypted pointer to process */ - return (DWORD)process; - case 24:/* return stdoutput handle from startupinfo */ - return (DWORD)(process->env_db->startup_info->hStdOutput); - case 28:/* return stdinput handle from startupinfo */ - return (DWORD)(process->env_db->startup_info->hStdInput); - case 32:/* get showwindow flag from startupinfo */ - return (DWORD)(process->env_db->startup_info->wShowWindow); - case 36:{/* return startup x and y sizes */ - LPSTARTUPINFO32A si = process->env_db->startup_info; - DWORD x,y; - - x=si->dwXSize;if (x==0x80000000) x=0x8000; - y=si->dwYSize;if (y==0x80000000) y=0x8000; - return (y<<16)+x; - } - case 40:{/* return startup x and y */ - LPSTARTUPINFO32A si = process->env_db->startup_info; - DWORD x,y; - - x=si->dwX;if (x==0x80000000) x=0x8000; - y=si->dwY;if (y==0x80000000) y=0x8000; - return (y<<16)+x; - } - case 44:/* return startup flags */ - return process->env_db->startup_info->dwFlags; - case 48:/* return uncrypted pointer to parent process (if any) */ - return (DWORD)process->parent; - case 52:/* return process flags */ - return process->flags; - case 56:/* unexplored */ - return 0; - default: - fprintf(stderr,"_KERNEL32_18:unknown offset (%ld)\n",action); - return 0; - } - /* shouldn't come here */ -} - -VOID /* FIXME */ -_KERNEL32_52(DWORD arg1,CONTEXT *regs) { - SEGPTR *str = SEGPTR_STRDUP("ThkBuf"); - - fprintf(stderr,"_KERNE32_52(arg1=%08lx,%08lx)\n",arg1,EDI_reg(regs)); - - EAX_reg(regs) = GetProcAddress16(EDI_reg(regs),SEGPTR_GET(str)); - fprintf(stderr," GetProcAddress16(\"ThkBuf\") returns %08lx\n", - EAX_reg(regs) - ); - SEGPTR_FREE(str); -} - -/*********************************************************************** - * GetPWinLock (KERNEL32) FIXME - */ -VOID -GetPWinLock(CRITICAL_SECTION **lock) { - static CRITICAL_SECTION plock; - fprintf(stderr,"GetPWinlock(%p)\n",lock); - *lock = &plock; -} - /*********************************************************************** * GetProcessVersion (KERNEL32) */ diff --git a/scheduler/thread.c b/scheduler/thread.c index ad4ff27f04a..22f78f65f0c 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -10,6 +10,7 @@ #include "winerror.h" #include "heap.h" #include "selectors.h" +#include "miscemu.h" #include "winnt.h" THDB *pCurrentThread = NULL; diff --git a/tools/build-spec.txt b/tools/build-spec.txt index 64917f2eeb9..8d731485d04 100644 --- a/tools/build-spec.txt +++ b/tools/build-spec.txt @@ -1,5 +1,6 @@ name NAME type win16|win32 +[file WINFILENAME] [base ORDINAL] [heap SIZE] @@ -25,8 +26,12 @@ General: declarations are optional, but the default handler will print an error message. "base" gives the offset of the first ordinal; default is 0. "heap" is the size of the module local heap (only valid for Win16 -modules); default is no local heap. Lines whose first character is a -'#' will be ignored as comments. +modules); default is no local heap. "file" gives the name of the +Windows file that is replaced by the builtin. .DLL is assumed if +none is given. (This is important for kernel, which lives in the +Windows file KRNL386.EXE). Lines whose first character is a '#' will +be ignored as comments. + Variable ordinals: ================== diff --git a/tools/build.c b/tools/build.c index 6d028952c3e..6ab1a55fa26 100644 --- a/tools/build.c +++ b/tools/build.c @@ -125,7 +125,8 @@ typedef struct static ORDDEF OrdinalDefinitions[MAX_ORDINALS]; static SPEC_TYPE SpecType = SPEC_INVALID; -char DLLName[80]; +static char DLLName[80]; +static char DLLFileName[80]; int Limit = 0; int Base = 0; int DLLHeapSize = 0; @@ -573,6 +574,12 @@ static int ParseTopLevel(void) { strcpy(DLLName, GetToken()); strupper(DLLName); + if (!DLLFileName[0]) sprintf( DLLFileName, "%s.DLL", DLLName ); + } + else if (strcmp(token, "file") == 0) + { + strcpy(DLLFileName, GetToken()); + strupper(DLLFileName); } else if (strcmp(token, "type") == 0) { @@ -743,8 +750,8 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pModule->fileinfo = (int)pFileInfo - (int)pModule; memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) - + strlen(DLLName) + 4; - sprintf( pFileInfo->szPathName, "%s.DLL", DLLName ); + + strlen(DLLFileName); + strcpy( pFileInfo->szPathName, DLLFileName ); pstr = (char *)pFileInfo + pFileInfo->cBytes + 1; /* Segment table */ @@ -928,8 +935,8 @@ static int BuildModule32( FILE *outfile ) pModule->fileinfo = (int)pFileInfo - (int)pModule; memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) - + strlen(DLLName) + 4; - sprintf( pFileInfo->szPathName, "%s.DLL", DLLName ); + + strlen(DLLFileName); + strcpy( pFileInfo->szPathName, DLLFileName ); pstr = (char *)pFileInfo + pFileInfo->cBytes + 1; /* Segment table */ diff --git a/win32/Makefile.in b/win32/Makefile.in index 0a7891a5a8f..834ad6247de 100644 --- a/win32/Makefile.in +++ b/win32/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ init.c \ k32obj.c \ newfns.c \ + ordinals.c \ process.c \ security.c \ string32.c \ diff --git a/win32/ordinals.c b/win32/ordinals.c new file mode 100644 index 00000000000..a617b0c34d1 --- /dev/null +++ b/win32/ordinals.c @@ -0,0 +1,430 @@ +/* + * Win32 ordinal only exported functions + * + * Copyright 1997 Marcus Meissner + */ + +#include +#include "thread.h" +#include "winerror.h" +#include "heap.h" +#include "selectors.h" +#include "miscemu.h" +#include "winnt.h" +#include "module.h" +#include "callback.h" +#include "debug.h" +#include "stddebug.h" + +extern THDB *pCurrentThread; +extern PDB32 *pCurrentProcess; + +/********************************************************************** + * _KERNEL32_88 + */ +DWORD +WOW32_1(DWORD x,DWORD y) { + fprintf(stderr,"WOW32_1(0x%08lx,0x%08lx), stub!\n",x,y); + return 0; +} + +/********************************************************************** + * WOWGetVDMPointer (KERNEL32.55) + * Get linear from segmented pointer. (MSDN lib) + */ +LPVOID +WOWGetVDMPointer(DWORD vp,DWORD nrofbytes,BOOL32 protected) { + /* FIXME: add size check too */ + fprintf(stdnimp,"WOWGetVDMPointer(%08lx,%ld,%d)\n",vp,nrofbytes,protected); + if (protected) + return PTR_SEG_TO_LIN(vp); + else + return DOSMEM_MapRealToLinear(vp); +} + +/********************************************************************** + * WOWGetVDMPointerFix (KERNEL32.55) + * Dito, but fix heapsegment (MSDN lib) + */ +LPVOID +WOWGetVDMPointerFix(DWORD vp,DWORD nrofbytes,BOOL32 protected) { + /* FIXME: fix heapsegment */ + fprintf(stdnimp,"WOWGetVDMPointerFix(%08lx,%ld,%d)\n",vp,nrofbytes,protected); + return WOWGetVDMPointer(vp,nrofbytes,protected); +} + +/********************************************************************** + * WOWGetVDMPointerUnFix (KERNEL32.56) + */ +void +WOWGetVDMPointerUnfix(DWORD vp) { + fprintf(stdnimp,"WOWGetVDMPointerUnfix(%08lx), STUB\n",vp); + /* FIXME: unfix heapsegment */ +} + + +/*********************************************************************** + * _KERNEL32_18 (KERNEL32.18) + * 'Of course you cannot directly access Windows internal structures' + */ + +DWORD +_KERNEL32_18(DWORD processid,DWORD action) { + PDB32 *process; + TDB *pTask; + + action+=56; + fprintf(stderr,"KERNEL32_18(%ld,%ld+0x38)\n",processid,action); + if (action>56) + return 0; + if (!processid) { + process=pCurrentProcess; + /* check if valid process */ + } else + process=(PDB32*)pCurrentProcess; /* decrypt too, if needed */ + switch (action) { + case 0: /* return app compat flags */ + pTask = (TDB*)GlobalLock16(process->task); + if (!pTask) + return 0; + return pTask->compat_flags; + case 4: /* returns offset 0xb8 of process struct... dunno what it is */ + return 0; + case 8: /* return hinstance16 */ + pTask = (TDB*)GlobalLock16(process->task); + if (!pTask) + return 0; + return pTask->hInstance; + case 12:/* return expected windows version */ + pTask = (TDB*)GlobalLock16(process->task); + if (!pTask) + return 0; + return pTask->version; + case 16:/* return uncrypted pointer to current thread */ + return (DWORD)pCurrentThread; + case 20:/* return uncrypted pointer to process */ + return (DWORD)process; + case 24:/* return stdoutput handle from startupinfo */ + return (DWORD)(process->env_db->startup_info->hStdOutput); + case 28:/* return stdinput handle from startupinfo */ + return (DWORD)(process->env_db->startup_info->hStdInput); + case 32:/* get showwindow flag from startupinfo */ + return (DWORD)(process->env_db->startup_info->wShowWindow); + case 36:{/* return startup x and y sizes */ + LPSTARTUPINFO32A si = process->env_db->startup_info; + DWORD x,y; + + x=si->dwXSize;if (x==0x80000000) x=0x8000; + y=si->dwYSize;if (y==0x80000000) y=0x8000; + return (y<<16)+x; + } + case 40:{/* return startup x and y */ + LPSTARTUPINFO32A si = process->env_db->startup_info; + DWORD x,y; + + x=si->dwX;if (x==0x80000000) x=0x8000; + y=si->dwY;if (y==0x80000000) y=0x8000; + return (y<<16)+x; + } + case 44:/* return startup flags */ + return process->env_db->startup_info->dwFlags; + case 48:/* return uncrypted pointer to parent process (if any) */ + return (DWORD)process->parent; + case 52:/* return process flags */ + return process->flags; + case 56:/* unexplored */ + return 0; + default: + fprintf(stderr,"_KERNEL32_18:unknown offset (%ld)\n",action); + return 0; + } + /* shouldn't come here */ +} + +/*********************************************************************** + * _KERNEL32_52 (KERNEL32.52) + * FIXME: what does it really do? + */ +VOID +_KERNEL32_52(DWORD arg1,CONTEXT *regs) { + fprintf(stderr,"_KERNE32_52(arg1=%08lx,%08lx)\n",arg1,EDI_reg(regs)); + + EAX_reg(regs) = (DWORD)WIN32_GetProcAddress16(EDI_reg(regs),"ThkBuf"); + + fprintf(stderr," GetProcAddress16(\"ThkBuf\") returns %08lx\n", + EAX_reg(regs) + ); +} + +/*********************************************************************** + * GetPWinLock (KERNEL32) FIXME + * get mutex? critical section for 16 bit mode? + */ +VOID +GetPWinLock(CRITICAL_SECTION **lock) { + static CRITICAL_SECTION plock; + fprintf(stderr,"GetPWinlock(%p)\n",lock); + *lock = &plock; +} + +/*********************************************************************** + * _KERNEL32_43 (KERNEL32.42) + * A thunkbuffer link routine + * The thunkbuf looks like: + * + * 00: DWORD length ? don't know exactly + * 04: SEGPTR ptr ? where does it point to? + * The pointer ptr is written into the first DWORD of 'thunk'. + * (probably correct implemented) + */ +BOOL32 +_KERNEL32_43(LPDWORD thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,LPCSTR dll32) { + HINSTANCE16 hmod; + LPDWORD addr; + SEGPTR segaddr; + + fprintf(stderr,"_KERNEL32_43(%p,%s,0x%08lx,%s,%s)\n",thunk,thkbuf,len,dll16,dll32); + + hmod = LoadLibrary16(dll16); + if (hmod<32) { + fprintf(stderr,"->failed to load 16bit DLL %s, error %d\n",dll16,hmod); + return NULL; + } + segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf); + if (!segaddr) { + fprintf(stderr,"->no %s exported from %s!\n",thkbuf,dll16); + return NULL; + } + addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr); + if (addr[0] != len) { + fprintf(stderr,"->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]); + return NULL; + } + if (!addr[1]) + return 0; + *(DWORD*)thunk = addr[1]; + return addr[1]; +} + +/*********************************************************************** + * _KERNEL32_45 (KERNEL32.44) + * FIXME: not sure what it does + */ +VOID +_KERNEL32_45(DWORD x,CONTEXT *context) { + fprintf(stderr,"_KERNEL32_45(0x%08lx,%%eax=0x%08lx,%%cx=0x%04lx,%%edx=0x%08lx)\n", + x,(DWORD)EAX_reg(context),(DWORD)CX_reg(context),(DWORD)EDX_reg(context) + ); +} + +/*********************************************************************** + * (KERNEL32.40) + * A thunk setup routine. + * Expects a pointer to a preinitialized thunkbuffer in the first argument + * looking like: + * 00..03: unknown (some pointer to the 16bit struct?) + * 04: EB1E jmp +0x20 + * + * 06..23: unknown (space for replacement code, check .90) + * + * 24:>E8xxxxxxxx call <32bitoffset xxxxxxxx> + * 29: 58 pop eax + * 2A: 2D2500xxxx and eax,0x2500xxxx + * 2F: BAxxxxxxxx mov edx,xxxxxxxx + * 34: 68yyyyyyyy push KERNEL32.90 + * 39: C3 ret + * + * 3A: EB1E jmp +0x20 + * 3E ... 59: unknown (space for replacement code?) + * 5A: E8xxxxxxxx call <32bitoffset xxxxxxxx> + * 5F: 5A pop edx + * 60: 81EA25xxxxxx sub edx, 0x25xxxxxx + * 66: 52 push edx + * 67: 68xxxxxxxx push xxxxxxxx + * 6C: 68yyyyyyyy push KERNEL32.89 + * 71: C3 ret + * 72: end? + * This function checks if the code is there, and replaces the yyyyyyyy entries + * by the functionpointers. + * The thunkbuf looks like: + * + * 00: DWORD length ? don't know exactly + * 04: SEGPTR ptr ? where does it point to? + * The segpointer ptr is written into the first DWORD of 'thunk'. + * (probably correct implemented) + */ + +LPVOID +_KERNEL32_41(LPBYTE thunk,LPCSTR thkbuf,DWORD len,LPCSTR dll16,LPCSTR dll32) { + HMODULE32 hkrnl32 = WIN32_GetModuleHandleA("KERNEL32"); + HMODULE16 hmod; + LPDWORD addr,addr2; + DWORD segaddr; + + fprintf(stderr,"KERNEL32_41(%p,%s,%ld,%s,%s)\n", + thunk,thkbuf,len,dll16,dll32 + ); + + /* FIXME: add checks for valid code ... */ + /* write pointers to kernel32.89 and kernel32.90 (+ordinal base of 1) */ + *(DWORD*)(thunk+0x35) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)91); + *(DWORD*)(thunk+0x6D) = (DWORD)GetProcAddress32(hkrnl32,(LPSTR)90); + + + hmod = LoadLibrary16(dll16); + if (hmod<32) { + fprintf(stderr,"->failed to load 16bit DLL %s, error %d\n",dll16,hmod); + return NULL; + } + segaddr = (DWORD)WIN32_GetProcAddress16(hmod,(LPSTR)thkbuf); + if (!segaddr) { + fprintf(stderr,"->no %s exported from %s!\n",thkbuf,dll16); + return NULL; + } + addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr); + if (addr[0] != len) { + fprintf(stderr,"->thkbuf length mismatch? %ld vs %ld\n",len,addr[0]); + return NULL; + } + addr2 = PTR_SEG_TO_LIN(addr[1]); + if (HIWORD(addr2)) + *(DWORD*)thunk = (DWORD)addr2; + return addr2; +} + +/*********************************************************************** + * (KERNEL32.33) + * Returns some internal value.... probably the default environment database? + */ +DWORD +_KERNEL32_34() { + fprintf(stderr,"KERNEL32_34(), STUB returning 0\n"); + return 0; +} + +/*********************************************************************** + * (KERNEL32.90) + * Thunk priming? function + * Rewrites the first part of the thunk to use the QT_Thunk interface. + * Replaces offset 4 ... 24 by: + * + * 33C9 xor ecx, ecx + * 8A4DFC mov cl , [ebp-04] + * 8B148Dxxxxxxxx mov edx, [4*ecx + (EAX+EDX)] + * B8yyyyyyyy mov eax, QT_Thunk + * FFE0 jmp eax + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * CC int 03 + * and jumps to the start of that code. + * (ok) + */ +VOID +_KERNEL32_91(CONTEXT *context) { + LPBYTE x; + + fprintf(stderr,"_KERNEL32_91(eax=0x%08lx,edx=0x%08lx)\n", + EAX_reg(context),EDX_reg(context) + ); + x = (LPBYTE)EAX_reg(context); + *x++ = 0x33;*x++=0xC9; /* xor ecx,ecx */ + *x++ = 0x8A;*x++=0x4D;*x++=0xFC; /* mov cl,[ebp-04] */ + *x++ = 0x8B;*x++=0x14;*x++=0x8D;*(DWORD*)x= EAX_reg(context)+EDX_reg(context); + x+=4; /* mov edx, [4*ecx + (EAX+EDX) */ + *x++ = 0xB8; *(DWORD*)x = (DWORD)GetProcAddress32(WIN32_GetModuleHandleA("KERNEL32"),"QT_Thunk"); + x+=4; /* mov eax , QT_Thunk */ + *x++ = 0xFF; *x++ = 0xE0; /* jmp eax */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + *x++ = 0xCC; /* int 03 */ + EIP_reg(context) = EAX_reg(context); +} + +/*********************************************************************** + * (KERNEL32.45) + * Another thunkbuf link routine. + * The start of the thunkbuf looks like this: + * 00: DWORD length + * 04: SEGPTR address for thunkbuffer pointer + */ +VOID +_KERNEL32_46(LPBYTE thunk,LPSTR thkbuf,DWORD len,LPSTR dll16,LPSTR dll32) { + LPDWORD addr; + HMODULE16 hmod; + SEGPTR segaddr; + + fprintf(stderr,"KERNEL32_46(%p,%s,%lx,%s,%s)\n", + thunk,thkbuf,len,dll16,dll32 + ); + hmod = LoadLibrary16(dll16); + if (hmod < 32) { + fprintf(stderr,"->couldn't load %s, error %d\n",dll16,hmod); + return; + } + segaddr = (SEGPTR)WIN32_GetProcAddress16(hmod,thkbuf); + if (!segaddr) { + fprintf(stderr,"-> haven't found %s in %s!\n",thkbuf,dll16); + return; + } + addr = (LPDWORD)PTR_SEG_TO_LIN(segaddr); + if (addr[0] != len) { + fprintf(stderr,"-> length of thkbuf differs from expected length! (%ld vs %ld)\n",addr[0],len); + return; + } + *(DWORD*)PTR_SEG_TO_LIN(addr[1]) = (DWORD)thunk; +} + +/********************************************************************** + * _KERNEL32_87 + * Check if thunking is initialized (ss selector set up etc.) + */ +BOOL32 _KERNEL32_87() { + fprintf(stderr,"KERNEL32_87 stub, returning TRUE\n"); + return TRUE; +} + +/********************************************************************** + * _KERNEL32_88 + * One of the real thunking functions + * Probably implemented totally wrong. + */ +BOOL32 _KERNEL32_88(DWORD nr,DWORD flags,LPVOID fun,DWORD *hmm) { + fprintf(stderr,"KERNEL32_88(%ld,0x%08lx,%p,%p) stub, returning TRUE\n", + nr,flags,fun,hmm + ); +#ifndef WINELIB + switch (nr) { + case 0: CallTo32_0(fun); + break; + case 4: CallTo32_1(fun,hmm[0]); + break; + case 8: CallTo32_2(fun,hmm[0],hmm[1]); + break; + default: + fprintf(stderr," unsupported nr of arguments, %ld\n",nr); + break; + + } +#endif + return TRUE; +} diff --git a/windows/class.c b/windows/class.c index c6fa82ecae1..4cc7eb686f0 100644 --- a/windows/class.c +++ b/windows/class.c @@ -320,10 +320,13 @@ ATOM RegisterClass16( const WNDCLASS16 *wc ) return 0; } - dprintf_class( stddeb, "RegisterClass16: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n", + dprintf_class( stddeb, "RegisterClass16: atom=%04x wndproc=%08lx hinst=%04x +bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n", atom, (DWORD)wc->lpfnWndProc, hInstance, wc->hbrBackground, wc->style, wc->cbClsExtra, - wc->cbWndExtra, classPtr ); + wc->cbWndExtra, classPtr, + HIWORD(wc->lpszClassName) ? + (char *)PTR_SEG_TO_LIN(wc->lpszClassName) : "" ); classPtr->hIcon = wc->hIcon; classPtr->hIconSm = 0; @@ -357,10 +360,12 @@ ATOM RegisterClass32A( const WNDCLASS32A* wc ) return 0; } - dprintf_class( stddeb, "RegisterClass32A: atom=%04x wndproc=%08lx hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p\n", + dprintf_class( stddeb, "RegisterClass32A: atom=%04x wndproc=%08lx +hinst=%04x bg=%04x style=%08x clsExt=%d winExt=%d class=%p name='%s'\n", atom, (DWORD)wc->lpfnWndProc, hInstance, wc->hbrBackground, wc->style, wc->cbClsExtra, - wc->cbWndExtra, classPtr ); + wc->cbWndExtra, classPtr, + HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" ); classPtr->hIcon = (HICON16)wc->hIcon; classPtr->hIconSm = 0; diff --git a/windows/dialog.c b/windows/dialog.c index 40243102c19..8b2f58048f4 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -899,6 +899,13 @@ static BOOL32 DIALOG_IsDialogMessage( HWND32 hwnd, HWND32 hwndDlg, *translate = *dispatch = FALSE; + if (message == WM_PAINT) + { + /* Apparently, we have to handle this one as well */ + *dispatch = TRUE; + return TRUE; + } + /* Only the key messages get special processing */ if ((message != WM_KEYDOWN) && (message != WM_SYSCHAR) && diff --git a/windows/message.c b/windows/message.c index a124fcdb48b..6bd4f4dd3c2 100644 --- a/windows/message.c +++ b/windows/message.c @@ -37,6 +37,8 @@ typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, extern MESSAGEQUEUE *pCursorQueue; /* queue.c */ extern MESSAGEQUEUE *pActiveQueue; +extern void JoySendMessages(void); + DWORD MSG_WineStartTicks; /* Ticks at Wine startup */ static UINT32 doubleClickSpeed = 452; @@ -412,6 +414,9 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter, MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue(); int i, kbd_msg, pos = sysMsgQueue->nextMessage; + /* FIXME: there has to be a better way to do this */ + JoySendMessages(); + /* If the queue is empty, attempt to fill it */ if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE, FALSE ); diff --git a/windows/queue.c b/windows/queue.c index 666f87b0698..4872a354f1e 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -6,6 +6,7 @@ #include #include +#include "miscemu.h" #include "module.h" #include "queue.h" #include "task.h" @@ -26,8 +27,6 @@ static MESSAGEQUEUE *sysMsgQueue = NULL; static MESSAGEQUEUE *pMouseQueue = NULL; /* Queue for last mouse message */ static MESSAGEQUEUE *pKbdQueue = NULL; /* Queue for last kbd message */ -extern void SIGNAL_MaskAsyncEvents(BOOL32); - MESSAGEQUEUE *pCursorQueue = NULL; MESSAGEQUEUE *pActiveQueue = NULL; diff --git a/windows/win.c b/windows/win.c index 371a47b7bf1..3200d5a2095 100644 --- a/windows/win.c +++ b/windows/win.c @@ -1172,6 +1172,10 @@ HWND16 FindWindowEx16( HWND16 parent, HWND16 child, { ATOM atom = 0; + dprintf_win(stddeb, "FindWindowEx16: %04x %04x '%s' '%s'\n", parent, + child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"", + title ? title : ""); + if (className) { /* If the atom doesn't exist, then no class */