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 */